迈克老狼2012 发表于 2012-10-25 01:16:26

Directx11教程(55) 建立球形和锥形物体

Directx11教程(55) 建立球形和锥形物体

“本教程中,我们新建2个model class,SphereModelClass以及CylinderModelClass,分别用来表示球形和锥形物体。
程序执行后的界面如下:
http://images.cnblogs.com/cnblogs_com/mikewolf2002/201208/201208090658289435.png
线框模式界面如下:
http://images.cnblogs.com/cnblogs_com/mikewolf2002/201208/201208090658369756.png
从线框模式可以看出,球形是由三个因素决定:半径、经度线、纬度线。
       在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
页: [1]
查看完整版本: Directx11教程(55) 建立球形和锥形物体