//------------------------------------------------------------- //- CalcNorms //- Calculate the vertex and face normals //------------------------------------------------------------- void CalcNorms() { //Calculate face normals first for(int x = 0; x < 10; x++) { CVector3 vTmp = CalcFaceNormal(CVector3(verts[Tris[x][2]]), CVector3(verts[Tris[x][1]]), CVector3(verts[Tris[x][0]])); memcpy(facenormals[x], vTmp.Get(), 12); } //Calculate the vertex normals for(x = 0; x < 10; x++) { int iShared[10]; //Indices of shared faces int iNumShared = 0; //Number of faces that share vertex //first find out which faces share the vertex for(int y = 0; y < 10; y++) { for(int z = 0; z < 3; z++) { if(Tris[y][z] == x) { iShared[iNumShared] = y; iNumShared ++; } } } //Calculate a normal by averaging the face normals of the shared faces CVector3 finalNorm; for(y = 0; y < iNumShared; y++) { finalNorm += facenormals[iShared[y]]; } finalNorm /= (float)iNumShared; memcpy(&vertnormals[x], finalNorm.Get(), 12); } }
//------------------------------------------------------------- //- RenderT //- Transform and render the meshes //------------------------------------------------------------- void CMs3d::RenderT() { glEnable(GL_TEXTURE_2D); //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); for(int x = 0; x < m_usNumMeshes; x++) { //Set up materials if(m_pMeshes[x].m_cMaterial >= 0) { SMs3dMaterial * pCurMat = &m_pMaterials[m_pMeshes[x].m_cMaterial]; //Set the alpha for transparency pCurMat->m_fDiffuse[3] = pCurMat->m_fTransparency; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, pCurMat->m_fAmbient); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pCurMat->m_fDiffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, pCurMat->m_fSpecular); glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, pCurMat->m_fEmissive); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, pCurMat->m_fShininess); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //Texture map pCurMat->m_Texture.Bind(); } else glDisable(GL_BLEND); //Draw mesh //Transformed vertices and normals CVector3 vecNormal; CVector3 vecVertex; glBegin(GL_TRIANGLES); //Loop through triangles for(int y = 0; y < m_pMeshes[x].m_usNumTris; y++) { //Set triangle pointer to triangle #1 SMs3dTriangle * pTri = &m_pTriangles[m_pMeshes[x].m_uspIndices[y]]; //Loop through each vertex for(int z = 0; z < 3; z++) { //Get the vertex SMs3dVertex * pVert = &m_pVertices[pTri->m_usVertIndices[z]]; //If it has no bone, render as is if(pVert->m_cBone == -1) { //Send all 3 components without modification glTexCoord2f(pTri->m_fTexCoords[0][z], pTri->m_fTexCoords[1][z]); glVertex3fv(pVert->m_vVert.Get()); glNormal3fv(pTri->m_vNormals[z].Get()); } //Otherwise, transform the vertices and normals before displaying them else { //Send the texture coordinates glTexCoord2f(pTri->m_fTexCoords[0][z], pTri->m_fTexCoords[1][z]); SMs3dJoint * pJoint = &m_pJoints[pVert->m_cBone]; //Transform the normals vecNormal = pTri->m_vNormals[z]; //Only rotate it, no translation vecNormal.Transform3(pJoint->m_matFinal); //Send the normal to OpenGL glNormal3fv(vecNormal.Get()); //Transform the vertex vecVertex = pVert->m_vVert; //translate as well as rotate vecVertex.Transform4(pJoint->m_matFinal); //Send vertex to openGL glVertex3fv(vecVertex.Get()); } } } glEnd(); } }
//------------------------------------------------------------- //- Main //- Main game loop //------------------------------------------------------------- void Main() { static float rot = 0; static bool bFaceNormals = true; static bool bWireframe = false; static bool bDrawNormals = true; glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glColor3f(1, 1, 1); APP->Print(.75f, .9f, "FPS: %4.2f", APP->GetFPS()); APP->Print(-.9f, .9f, "Face Normals are %s", bFaceNormals ? "enabled" : "disabled"); APP->Print(-.9f, .8f, "Vertex Normals are %s", bFaceNormals ? "disabled" : "enabled"); APP->Print(-.9f, .7f, "Wireframe is %s", bWireframe ? "enabled" : "disabled"); APP->Print(-.9f, .5f, "Press N to toggle normal types"); APP->Print(-.9f, .4f, "Press W to toggle wireframe"); APP->Print(-.9f, .3f, "Press D to toggle the normal display"); glLoadIdentity(); glTranslatef(0.0f, 0.0f, -10.0f); //Draw light glColor3f(1.0f, 1.0f, 0.0f); glPointSize(8); glBegin(GL_POINTS); glVertex3f(0.0f, 3.5f, 0.0f); glEnd(); glEnable(GL_LIGHTING); glRotatef(rot, 1.0f, 1.0f, 1.0f); //GetInput if(KeyPressOnce('N')) bFaceNormals = !bFaceNormals; if(KeyPressOnce('W')) bWireframe = !bWireframe; if(KeyPressOnce('D')) bDrawNormals = !bDrawNormals; //Draw the mesh //Draw with one normal per face if(bFaceNormals) { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glBegin(GL_TRIANGLES); for(int x = 0; x < 10; x++) { glNormal3fv( facenormals[x] ); glVertex3fv( verts[Tris[x][0]] ); glVertex3fv( verts[Tris[x][1]] ); glVertex3fv( verts[Tris[x][2]] ); } glEnd(); if(bDrawNormals) { //Draw the normals glDisable(GL_LIGHTING); glBegin(GL_LINES); for(x = 0; x < 10; x++) { CVector3 vCenter = (CVector3(verts[Tris[x][0]]) + CVector3(verts[Tris[x][1]]) + CVector3(verts[Tris[x][2]])) / 3; CVector3 vEnd = vCenter + CVector3(facenormals[x]); glColor3f(0.0f, 0.0f, 1.0f); glVertex3fv(vCenter.Get()); glColor3f(0.0f, 1.0f, 0.0f); glVertex3fv(vEnd.Get()); } glEnd(); } } //Use vertex normals else { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glBegin(GL_TRIANGLES); for(int x = 0; x < 10; x++) { glNormal3fv( vertnormals[Tris[x][0]] ); glVertex3fv( verts[Tris[x][0]] ); glNormal3fv( vertnormals[Tris[x][1]] ); glVertex3fv( verts[Tris[x][1]] ); glNormal3fv( vertnormals[Tris[x][2]] ); glVertex3fv( verts[Tris[x][2]] ); } glEnd(); if(bDrawNormals) { //Draw the normals glDisable(GL_LIGHTING); glBegin(GL_LINES); for(x = 0; x < 10; x++) { glColor3f(0.0f, 0.0f, 1.0f); glVertex3fv(verts[x]); CVector3 vEnd = CVector3(verts[x]) + CVector3(vertnormals[x]); glColor3f(0.0f, 1.0f, 0.0f); glVertex3fv(vEnd.Get()); } glEnd(); } } if(bWireframe) { glDisable(GL_LIGHTING); glColor3f(1.0f, 0.0f, 1.0f); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glBegin(GL_TRIANGLES); for(int x = 0; x < 10; x++) { glVertex3fv( verts[Tris[x][0]]); glVertex3fv( verts[Tris[x][1]]); glVertex3fv( verts[Tris[x][2]]); } glEnd(); } rot+=0.2f; }