1. 程式人生 > >Directx11教程(55) 建立球形和錐形物體

Directx11教程(55) 建立球形和錐形物體

函數 alt indices lis oid file eight 模式 ack

原文:Directx11教程(55) 建立球形和錐形物體

本教程中,我們新建2個model class,SphereModelClass以及CylinderModelClass,分別用來表示球形和錐形物體。

程序執行後的界面如下:

技術分享圖片

線框模式界面如下:

技術分享圖片

從線框模式可以看出,球形是由三個因素決定:半徑、經度線、緯度線

       在SphereModelClass.cpp中,我們看到,初始化頂點緩沖和索引緩沖的函數為:InitializeBuffers(ID3D11Device* device,  float radius, int numSlices, int numStacks

),它多了三個參數,分別表示半徑、經度切片的數量、緯度切面的數量。具體構建球形頂點的操作在函數buildStacks(vertices, indices)中,主要就是把經緯度切片的數目轉化成球坐標系中的角度,求出球坐標系中頂點,再轉化到笛卡爾坐標系中。

代碼如下:

void SphereModelClass::buildStacks(VertexList& vertices, IndexList& indices)
    {
    float phiStep = PI/m_NumStacks;

    int numRings = m_NumStacks-1;

    // 對於每個緯度環,計算頂點.
    for(int i = 1; i <= numRings; ++i)
        {
        float phi = i*phiStep;

        // 環上的頂點
        float thetaStep = 2.0f*PI/m_NumSlices;
        for(int j = 0; j <= m_NumSlices; ++j)
            {
            float theta = j*thetaStep;

            VertexType v;

            // 球坐標到笛卡爾坐標的轉化
            v.position.x = m_Radius*sinf(phi)*cosf(theta);
            v.position.y = m_Radius*cosf(phi);
            v.position .z = m_Radius*sinf(phi)*sinf(theta);

            D3DXVec3Normalize(&v.normal, &v.position);

            //球的紋理坐標
            v.texture.x = theta / (2.0f*PI);
            v.texture.y = phi / PI;

            v.Kd    = D3DXVECTOR4(0.2, 0.2, 0.1,1.0);
            v.Ks = D3DXVECTOR4(0.2, 0.2, 0.2,1.0);
            vertices.push_back( v );
            }
        }

    // 球的極點: 會出現紋理坐標扭曲
     VertexType t1;
     t1.position = D3DXVECTOR3(0.0f, -m_Radius, 0.0f);
     t1.normal = D3DXVECTOR3(0.0f, -1.0f, 0.0f);
     t1.texture = D3DXVECTOR2(0.0f, 1.0f);
     t1.Kd = D3DXVECTOR4(0.2, 0.2, 0.1,1.0);
     t1.Ks = D3DXVECTOR4(0.2, 0.2, 0.2,1.0);
    
     vertices.push_back( t1 );

     t1.position = D3DXVECTOR3(0.0f, m_Radius, 0.0f);
     t1.normal = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
     t1.texture = D3DXVECTOR2(0.0f, 0.0f);

    vertices.push_back(t1 );

    int northPoleIndex = (int)vertices.size()-1;
    int southPoleIndex = (int)vertices.size()-2;

    int numRingVertices = m_NumSlices+1;

    // 計算索引(不考慮極點)
    for(int i = 0; i < m_NumStacks-2; ++i)
        {
        for(int j = 0; j < m_NumSlices; ++j)
            {
            indices.push_back(i*numRingVertices + j);
            indices.push_back(i*numRingVertices + j+1);
            indices.push_back((i+1)*numRingVertices + j);

            indices.push_back((i+1)*numRingVertices + j);
            indices.push_back(i*numRingVertices + j+1);
            indices.push_back((i+1)*numRingVertices + j+1);
            }
        }

//北極點索引
    for(int i = 0; i < m_NumSlices; ++i)
        {
        indices.push_back(northPoleIndex);
        indices.push_back(i+1);
        indices.push_back(i);
        }

//南極點索引
    int baseIndex = (numRings-1)*numRingVertices;
    for(int i = 0; i < m_NumSlices; ++i)
        {
        indices.push_back(southPoleIndex);
        indices.push_back(baseIndex+i);
        indices.push_back(baseIndex+i+1);
        }
    }

      在CylinderModelClass.cpp中,我們看到InitializeBuffers(ID3D11Device* device,  float topRadius, float bottomRadius,     float height, int numSlices, int numStacks),它多出了5個參數,分別表示錐體的頂部圓半徑、底部圓半徑,高度、經度切片的數量、緯度切片的數量。

具體計算頂點緩沖和索引緩沖由個函數組成,這三個函數的具體代碼請參考源文件:

buildStacks(vertices, indices);
buildTopCap(vertices, indices);
buildBottomCap(vertices, indices);

    

完整的代碼請參考:

工程文件myTutorialD3D11_50

代碼下載:

http://files.cnblogs.com/mikewolf2002/d3d1150-58.zip

http://files.cnblogs.com/mikewolf2002/pictures.zip

Directx11教程(55) 建立球形和錐形物體