/////////////////////////////////////////////////////////////////////////////////////// // Get Window coordinates, discard Z... void m3dProjectXY(M3DVector2f vPointOut, const M3DMatrix44f mModelView, const M3DMatrix44f mProjection, const int iViewPort[4], const M3DVector3f vPointIn) { M3DVector4f vBack, vForth; memcpy(vBack, vPointIn, sizeof(float)*3); vBack[3] = 1.0f; m3dTransformVector4(vForth, vBack, mModelView); m3dTransformVector4(vBack, vForth, mProjection); if(!m3dCloseEnough(vBack[3], 0.0f, 0.000001f)) { float div = 1.0f / vBack[3]; vBack[0] *= div; vBack[1] *= div; //vBack[2] *= div; } vPointOut[0] = float(iViewPort[0])+(1.0f+float(vBack[0]))*float(iViewPort[2])/2.0f; vPointOut[1] = float(iViewPort[1])+(1.0f+float(vBack[1]))*float(iViewPort[3])/2.0f; // This was put in for Grand Tour... I think it's right. // .... please report any bugs if(iViewPort[0] != 0) // Cast to float is expensive... avoid if posssible vPointOut[0] -= float(iViewPort[0]); if(iViewPort[1] != 0) vPointOut[1] -= float(iViewPort[1]); }
/////////////////////////////////////////////////////////////////////////////////////// // Get window coordinates, we also want Z.... void m3dProjectXYZ(M3DVector3f vPointOut, const M3DMatrix44f mModelView, const M3DMatrix44f mProjection, const int iViewPort[4], const M3DVector3f vPointIn) { M3DVector4f vBack, vForth; memcpy(vBack, vPointIn, sizeof(float)*3); vBack[3] = 1.0f; m3dTransformVector4(vForth, vBack, mModelView); m3dTransformVector4(vBack, vForth, mProjection); if(!m3dCloseEnough(vBack[3], 0.0f, 0.000001f)) { float div = 1.0f / vBack[3]; vBack[0] *= div; vBack[1] *= div; vBack[2] *= div; } vPointOut[0] = float(iViewPort[0])+(1.0f+float(vBack[0]))*float(iViewPort[2])/2.0f; vPointOut[1] = float(iViewPort[1])+(1.0f+float(vBack[1]))*float(iViewPort[3])/2.0f; if(iViewPort[0] != 0) // Cast to float is expensive... avoid if posssible vPointOut[0] -= float(iViewPort[0]); if(iViewPort[1] != 0) vPointOut[1] -= float(iViewPort[1]); vPointOut[2] = vBack[2]; }
/////////////////////////////////////////////////////////////////////////////////////// // Get window coordinates, we also want Z.... void m3dProjectXYZ(const M3DMatrix44f mModelView, const M3DMatrix44f mProjection, const int iViewPort[4], const M3DVector3f vPointIn, M3DVector3f vPointOut) { M3DVector4f vBack, vForth; memcpy(vBack, vPointIn, sizeof(float)*3); vBack[3] = 1.0f; m3dTransformVector4(vForth, vBack, mModelView); m3dTransformVector4(vBack, vForth, mProjection); if(!m3dCloseEnough(vBack[3], 0.0f, 0.000001f)) { float div = 1.0f / vBack[3]; vBack[0] *= div; vBack[1] *= div; vBack[2] *= div; } vPointOut[0] = vBack[0] * 0.5f + 0.5f; vPointOut[1] = vBack[1] * 0.5f + 0.5f; vPointOut[2] = vBack[2] * 0.5f + 0.5f; /* Map x,y to viewport */ vPointOut[0] = (vPointOut[0] * iViewPort[2]) + iViewPort[0]; vPointOut[1] = (vPointOut[1] * iViewPort[3]) + iViewPort[1]; }
///////////////////////////////////////////////////////////////// // Add a triangle to the mesh. This searches the current list for identical // (well, almost identical - these are floats you know...) verts. If one is found, it // is added to the index array. If not, it is added to both the index array and the vertex // array grows by one as well. void CVBOMesh::AddTriangle(M3DVector3f verts[3], M3DVector3f vNorms[3], M3DVector2f vTexCoords[3]) { const float e = 0.000001; // How small a difference to equate // First thing we do is make sure the normals are unit length! // It's almost always a good idea to work with pre-normalized normals m3dNormalizeVector(vNorms[0]); m3dNormalizeVector(vNorms[1]); m3dNormalizeVector(vNorms[2]); // Search for match - triangle consists of three verts for(GLuint iVertex = 0; iVertex < 3; iVertex++) { GLuint iMatch = 0; for(iMatch = 0; iMatch < nNumVerts; iMatch++) { // If the vertex positions are the same if(m3dCloseEnough(pVerts[iMatch][0], verts[iVertex][0], e) && m3dCloseEnough(pVerts[iMatch][1], verts[iVertex][1], e) && m3dCloseEnough(pVerts[iMatch][2], verts[iVertex][2], e) && // AND the Normal is the same... m3dCloseEnough(pNorms[iMatch][0], vNorms[iVertex][0], e) && m3dCloseEnough(pNorms[iMatch][1], vNorms[iVertex][1], e) && m3dCloseEnough(pNorms[iMatch][2], vNorms[iVertex][2], e) && // And Texture is the same... m3dCloseEnough(pTexCoords[iMatch][0], vTexCoords[iVertex][0], e) && m3dCloseEnough(pTexCoords[iMatch][1], vTexCoords[iVertex][1], e)) { // Then add the index only pIndexes[nNumIndexes] = iMatch; nNumIndexes++; break; } } // No match for this vertex, add to end of list if(iMatch == nNumVerts) { memcpy(pVerts[nNumVerts], verts[iVertex], sizeof(M3DVector3f)); memcpy(pNorms[nNumVerts], vNorms[iVertex], sizeof(M3DVector3f)); memcpy(pTexCoords[nNumVerts], &vTexCoords[iVertex], sizeof(M3DVector2f)); pIndexes[nNumIndexes] = nNumVerts; nNumIndexes++; nNumVerts++; } } }
// Draw a cylinder. Much like gluCylinder void gltMakeCylinder(GLTriangleBatch& cylinderBatch, GLfloat baseRadius, GLfloat topRadius, GLfloat fLength, GLint numSlices, GLint numStacks) { float fRadiusStep = (topRadius - baseRadius) / float(numStacks); GLfloat fStepSizeSlice = (3.1415926536f * 2.0f) / float(numSlices); M3DVector3f vVertex[4]; M3DVector3f vNormal[4]; M3DVector2f vTexture[4]; cylinderBatch.BeginMesh(numSlices * numStacks * 6); GLfloat ds = 1.0f / float(numSlices); GLfloat dt = 1.0f / float(numStacks); GLfloat s; GLfloat t; for (int i = 0; i < numStacks; i++) { if(i == 0) t = 0.0f; else t = float(i) * dt; float tNext; if(i == (numStacks - 1)) tNext = 1.0f; else tNext = float(i+1) * dt; float fCurrentRadius = baseRadius + (fRadiusStep * float(i)); float fNextRadius = baseRadius + (fRadiusStep * float(i+1)); float theyta; float theytaNext; float fCurrentZ = float(i) * (fLength / float(numStacks)); float fNextZ = float(i+1) * (fLength / float(numStacks)); float zNormal = 0.0f; if(!m3dCloseEnough(baseRadius - topRadius, 0.0f, 0.00001f)) { // Rise over run... zNormal = (baseRadius - topRadius); } for (int j = 0; j < numSlices; j++) { if(j == 0) s = 0.0f; else s = float(j) * ds; float sNext; if(j == (numSlices -1)) sNext = 1.0f; else sNext = float(j+1) * ds; theyta = fStepSizeSlice * float(j); if(j == (numSlices - 1)) theytaNext = 0.0f; else theytaNext = fStepSizeSlice * (float(j+1)); // Inner First vVertex[1][0] = cos(theyta) * fCurrentRadius; // X vVertex[1][1] = sin(theyta) * fCurrentRadius; // Y vVertex[1][2] = fCurrentZ; // Z vNormal[1][0] = vVertex[1][0]; // Surface Normal, same for everybody vNormal[1][1] = vVertex[1][1]; vNormal[1][2] = zNormal; m3dNormalizeVector3(vNormal[1]); vTexture[1][0] = s; // Texture Coordinates, I have no idea... vTexture[1][1] = t; // Outer First vVertex[0][0] = cos(theyta) * fNextRadius; // X vVertex[0][1] = sin(theyta) * fNextRadius; // Y vVertex[0][2] = fNextZ; // Z if(!m3dCloseEnough(fNextRadius, 0.0f, 0.00001f)) { vNormal[0][0] = vVertex[0][0]; // Surface Normal, same for everybody vNormal[0][1] = vVertex[0][1]; // For cones, tip is tricky vNormal[0][2] = zNormal; m3dNormalizeVector3(vNormal[0]); } else memcpy(vNormal[0], vNormal[1], sizeof(M3DVector3f)); vTexture[0][0] = s; // Texture Coordinates, I have no idea... vTexture[0][1] = tNext; // Inner second vVertex[3][0] = cos(theytaNext) * fCurrentRadius; // X vVertex[3][1] = sin(theytaNext) * fCurrentRadius; // Y vVertex[3][2] = fCurrentZ; // Z vNormal[3][0] = vVertex[3][0]; // Surface Normal, same for everybody vNormal[3][1] = vVertex[3][1]; vNormal[3][2] = zNormal; m3dNormalizeVector3(vNormal[3]); vTexture[3][0] = sNext; // Texture Coordinates, I have no idea... vTexture[3][1] = t; // Outer second vVertex[2][0] = cos(theytaNext) * fNextRadius; // X vVertex[2][1] = sin(theytaNext) * fNextRadius; // Y vVertex[2][2] = fNextZ; // Z if(!m3dCloseEnough(fNextRadius, 0.0f, 0.00001f)) { vNormal[2][0] = vVertex[2][0]; // Surface Normal, same for everybody vNormal[2][1] = vVertex[2][1]; vNormal[2][2] = zNormal; m3dNormalizeVector3(vNormal[2]); } else memcpy(vNormal[2], vNormal[3], sizeof(M3DVector3f)); vTexture[2][0] = sNext; // Texture Coordinates, I have no idea... vTexture[2][1] = tNext; cylinderBatch.AddTriangle(vVertex, vNormal, vTexture); // Rearrange for next triangle memcpy(vVertex[0], vVertex[1], sizeof(M3DVector3f)); memcpy(vNormal[0], vNormal[1], sizeof(M3DVector3f)); memcpy(vTexture[0], vTexture[1], sizeof(M3DVector2f)); memcpy(vVertex[1], vVertex[3], sizeof(M3DVector3f)); memcpy(vNormal[1], vNormal[3], sizeof(M3DVector3f)); memcpy(vTexture[1], vTexture[3], sizeof(M3DVector2f)); cylinderBatch.AddTriangle(vVertex, vNormal, vTexture); } } cylinderBatch.End(); }