OPENGL-ES 球体顶点坐标计算

//创建球体模型的顶点坐标 
bool OGLESFiveSpheres::CreateGeometry() 

    unsigned int i; 
 
    /* 
        g_ui32RimNo 多少个同心圆 
        g_uiRimSize 每个同心圆上的点数 
    */ 
    /* 
        Creates the sphere vertices and texture coordinates 
    */ 
    m_ui32VertexNo = (g_ui32RimNo - 2) * g_uiRimSize + 2
    m_pVertex = new SVertex[m_ui32VertexNo]; 
 
    if(!m_pVertex) 
    { 
        PVRShellSet(prefExitMessage, "Error: Out of memory."); 
        return false
    } 
 
    // Bottom vertex 
    m_pVertex[0].fPos.x = 0
    m_pVertex[0].fPos.y = -0.5f * g_ui32SphereScale; 
    m_pVertex[0].fPos.z = 0
    m_pVertex[0].fU = 0.5f; 
    m_pVertex[0].fV = 0.5f; 
 
    // 7 rims of 16 vertices each 
    float fYAngleInc = PVRT_PI / (float) (g_ui32RimNo - 1); 
    float fYAngle = fYAngleInc; 
    int i32Index = 1
 
    for(i = 0; i < (g_ui32RimNo - 2); ++i) 
    { 
        float fPosY = (float) cos(fYAngle) * -0.5f; 
        fYAngle += fYAngleInc; 
 
        for(int j = 0; j < g_uiRimSize; ++j) 
        { 
            float fAngle = (float)j * 2.0f * PVRT_PI / (float)g_uiRimSize; 
            float fSize = (float) cos(asin(fPosY*2)) * 0.50f; 
            m_pVertex[GetVertexIndex(i+1,j)].fPos.x = (float)PVRTFCOS(fAngle) * (fSize*g_ui32SphereScale); 
            m_pVertex[GetVertexIndex(i+1,j)].fPos.y = fPosY * g_ui32SphereScale; 
            m_pVertex[GetVertexIndex(i+1,j)].fPos.z = (float)PVRTFSIN(fAngle) * (fSize*g_ui32SphereScale); 
            m_pVertex[GetVertexIndex(i+1,j)].fU = m_pVertex[GetVertexIndex(i+1,j)].fPos.x + 0.5f; 
            m_pVertex[GetVertexIndex(i+1,j)].fV = m_pVertex[GetVertexIndex(i+1,j)].fPos.z + 0.5f; 
            ++i32Index; 
        } 
    } 
 
    // Top vertex 
    m_pVertex[i32Index].fPos.x = 0
    m_pVertex[i32Index].fPos.y = 0.5f * g_ui32SphereScale; 
    m_pVertex[i32Index].fPos.z = 0
    m_pVertex[i32Index].fU = 0.5f; 
    m_pVertex[i32Index].fV = 0.5f; 
 
    /* 
        Creates the sphere normals. 
    */ 
    for(i = 0; i < (g_ui32RimNo - 2) * g_uiRimSize + 2; ++i) 
    { 
        PVRTVec3 vNormal; 
        vNormal.x = m_pVertex[i].fPos.x; 
        vNormal.y = m_pVertex[i].fPos.y; 
        vNormal.z = m_pVertex[i].fPos.z; 
 
        vNormal.normalize(); 
 
        m_pVertex[i].fNormal.x = vNormal.x; 
        m_pVertex[i].fNormal.y = vNormal.y; 
        m_pVertex[i].fNormal.z = vNormal.z; 
    } 
 
    return true

 

说明:假如球体有180个同心圆(g_ui32RimNo = 180)当然包含最上面一个点和最下面一个点,南极北极。

那么每个同心圆之间的角度差都是1°。即角度增量为:

float fYAngleInc = PVRT_PI / (float) (g_ui32RimNo - 1); //B角

同一个同心圆上面所有点的Y坐标都是一致的。

float fPosY = (float) cos(fYAngle) * -0.5f; 

角度Q的计算:

 float fAngle = (float)j * 2.0f * PVRT_PI / (float)g_uiRimSize; //图中有点错误,Q画成了与X负轴夹角,应该是正轴夹角。

同心圆半径R1的计算:

float fSize = (float) cos(asin(fPosY*2)) * 0.50f; 

fPosY*2 =   (float) cos(fYAngle) * -0.5f * 2 =  (float) cos(fYAngle)  = sin(π/2 - fYAngle)

其实R1也可以这样计算: (float) sin(fYAngle) * 0.50f; 

X坐标计算:

R1 * cosQ

Z坐标计算:

R1 * sinQ

你可能感兴趣的:(OPENGL-ES 球体顶点坐标计算)