www.pudn.com > Gimcrack-v0.0051-Source.zip > gmd.cpp
#include#include #include "gmdformat.h" #include "gmd.h" #include "../math/vector.h" #include "../math/math.h" using namespace std; /////////////////////////////////////////////////////////////////////////////////////////// GcGMD::GcGMD(): triangles(NULL), vertices(NULL), texCoords(NULL), texture(NULL), interpol(0.0f), activeSkin(0) { } /////////////////////////////////////////////////////////////////////////////////////////// GcGMD::~GcGMD() { // Destroy the model Destroy(); } /////////////////////////////////////////////////////////////////////////////////////////// bool GcGMD::Load(char *fileName, char *skinName) { // Load the model Load(fileName); // Allocate memory for the skin texture = new GcTexture[1]; // Create the texture texture[0].Create(skinName); // Set the active skin activeSkin = 0; header.numSkins = 1; return true; } /////////////////////////////////////////////////////////////////////////////////////////// bool GcGMD::Load(char *fileName) { // Open the file for reading ifstream file(fileName, ios::in | ios::binary); // Check for success if(!file) { return false; } // Read the head from the file file.read((char*)&header, sizeof(GMDHeader)); // Allocate memory from the vertices vertices = new GcPoint3[header.numVertices * header.numFrames]; // Read the vertices from the file file.read((char*)vertices, sizeof(GcPoint3) * header.numVertices * header.numFrames); // Allocate memory for the texture coordinates texCoords = new GcPoint2[header.numTexCoords]; // Read the texture coordinates from the file file.read((char*)texCoords, sizeof(GcPoint2) * header.numTexCoords); // Allocate memory for the triangles triangles = new GMDTri[header.numTris]; // Find the correct reading position file.seekg(header.offsetTris, ios::beg); // Read the triangles from the file file.read((char*)triangles, sizeof(GMDTri) * header.numTris); // No skin was loaded header.numSkins = 0; /* Find the extreme points for the bounding box */ GcVector3 extreme(0, 0, 0); GcPoint3 currPoint; for(int i = 0; i < header.numTris; i++) { // Get the first points from this fram and the next currPoint.x = vertices[triangles[i].triInd[0]].x; currPoint.y = vertices[triangles[i].triInd[0]].y; currPoint.z = vertices[triangles[i].triInd[0]].z; if(currPoint.x > extreme.x) { extreme.x = currPoint.x; } if(currPoint.y > extreme.y) { extreme.y = currPoint.y; } if(currPoint.z > extreme.z) { extreme.z = currPoint.z; } } g_Debug->Log("Extreme x: %f - y: %f - z: %f\n", extreme.x, extreme.y, extreme.z ); SetExtents(extreme); return true; } /////////////////////////////////////////////////////////////////////////////////////////// bool GcGMD::LoadSkin(char *skinName, uint index) { // Check to see that the skin is valid and that a texture space for it exist if((texture == NULL) || (index > header.numSkins - 1)) { g_Debug->Log("Failed to load skin %d\n", index); return false; } // Create the skin texture[index].Create(skinName); return true; } /////////////////////////////////////////////////////////////////////////////////////////// void GcGMD::SetNumberOfSkins(uint num) { // Delete previus textures if needed if(texture != NULL) { delete [] texture; } // Create new textures texture = new GcTexture[num]; // Save the number of skins header.numSkins = num; } /////////////////////////////////////////////////////////////////////////////////////////// bool GcGMD::Animate(int startFrame, int endFrame, float percent) { GcPoint3 *currList; // Holds the current frame's vertices GcPoint3 *nextList; // Holds the next frame's vertices GcPoint3 currPoint; GcPoint3 nextPoint; GcPoint3 vertex[3]; // The vertex's to be rendered GcVector3 normal; // The vertex normal if(startFrame > currentFrame) { currentFrame = startFrame; } if((startFrame < 0) || (endFrame < 0)) { return false; } if((startFrame >= header.numFrames) || (endFrame >= header.numFrames)) { return false; } if(interpol >= 1.0f) { // Re-set the interpolation interpol = 0.0f; // Another fram has gone by currentFrame++; // Time to start the animation over? if(currentFrame >= endFrame) { currentFrame = startFrame; } // Set the next frame nextFrame = currentFrame + 1; // Time to start the animation over? if(nextFrame >= endFrame) { nextFrame = startFrame; } } // Set the pointers to point to this frame's vertices, and the next currList = &vertices[header.numVertices * currentFrame]; nextList = &vertices[header.numVertices * nextFrame]; // Bind the texture for the model if(header.numSkins > 0) { texture[activeSkin].Bind(); } glPushMatrix(); glMultMatrixf(m_worldMatrix); glBegin(GL_TRIANGLES); for(int i = 0; i < header.numTris; i++) { // Get the first points from this fram and the next currPoint.x = currList[triangles[i].triInd[0]].x; currPoint.y = currList[triangles[i].triInd[0]].y; currPoint.z = currList[triangles[i].triInd[0]].z; nextPoint.x = nextList[triangles[i].triInd[0]].x; nextPoint.y = nextList[triangles[i].triInd[0]].y; nextPoint.z = nextList[triangles[i].triInd[0]].z; // Claculate the first interpolated vertex vertex[0] = (nextPoint - currPoint) * interpol + currPoint; // Get the first points from this fram and the next currPoint.x = currList[triangles[i].triInd[1]].x; currPoint.y = currList[triangles[i].triInd[1]].y; currPoint.z = currList[triangles[i].triInd[1]].z; nextPoint.x = nextList[triangles[i].triInd[1]].x; nextPoint.y = nextList[triangles[i].triInd[1]].y; nextPoint.z = nextList[triangles[i].triInd[1]].z; // Claculate the second interpolated vertex vertex[1] = (nextPoint - currPoint) * interpol + currPoint; // Get the first points from this fram and the next currPoint.x = currList[triangles[i].triInd[2]].x; currPoint.y = currList[triangles[i].triInd[2]].y; currPoint.z = currList[triangles[i].triInd[2]].z; nextPoint.x = nextList[triangles[i].triInd[2]].x; nextPoint.y = nextList[triangles[i].triInd[2]].y; nextPoint.z = nextList[triangles[i].triInd[2]].z; // Claculate the first interpolated vertex vertex[2] = (nextPoint - currPoint) * interpol + currPoint; // Calculate the normal normal = GcMath::ClaculateNormal(vertex[0], vertex[1], vertex[3]); // Give the normal to OpenGL glNormal3f(normal.x, normal.y, normal.z); // Render the triangle glTexCoord2f(texCoords[triangles[i].texCrdInd[0]].x, texCoords[triangles[i].texCrdInd[0]].y); glVertex3fv(vertex[0].array); glTexCoord2f(texCoords[triangles[i].texCrdInd[2]].x, texCoords[triangles[i].texCrdInd[2]].y); glVertex3fv(vertex[2].array); glTexCoord2f(texCoords[triangles[i].texCrdInd[1]].x, texCoords[triangles[i].texCrdInd[1]].y); glVertex3fv(vertex[1].array); } glEnd(); glPopMatrix(); interpol += percent; return true; } /////////////////////////////////////////////////////////////////////////////////////////// bool GcGMD::RenderKeyFrame(int frame) { GcPoint3 *currList; // Holds the current frame's vertices GcPoint3 vertex[3]; // The vertices to be rendered GcVector3 normal; // The triangle normal // Check for a valid frame if(frame < 0 || frame > header.numFrames) { return false; } // Set the pointers to point to this frame's vertices currList = &vertices[header.numVertices * frame]; // Bind the texture for the model if(header.numSkins > 0) { texture[activeSkin].Bind(); } glPushMatrix(); glMultMatrixf(m_worldMatrix); glBegin(GL_TRIANGLES); for(int i = 0; i < header.numTris; i++) { // Get the first point from this frame vertex[0].x = currList[triangles[i].triInd[0]].x; vertex[0].y = currList[triangles[i].triInd[0]].y; vertex[0].z = currList[triangles[i].triInd[0]].z; // Get the second point from this frame vertex[1].x = currList[triangles[i].triInd[1]].x; vertex[1].y = currList[triangles[i].triInd[1]].y; vertex[1].z = currList[triangles[i].triInd[1]].z; // Get the third point from this frame vertex[2].x = currList[triangles[i].triInd[2]].x; vertex[2].y = currList[triangles[i].triInd[2]].y; vertex[2].z = currList[triangles[i].triInd[2]].z; // Calculate the normal normal = GcMath::ClaculateNormal(vertex[0], vertex[1], vertex[3]); // Give the normal to OpenGL glNormal3f(normal.x, normal.y, normal.z); // Render the triangle glTexCoord2f(texCoords[triangles[i].texCrdInd[0]].x, texCoords[triangles[i].texCrdInd[0]].y); glVertex3fv(vertex[0].array); glTexCoord2f(texCoords[triangles[i].texCrdInd[2]].x, texCoords[triangles[i].texCrdInd[2]].y); glVertex3fv(vertex[2].array); glTexCoord2f(texCoords[triangles[i].texCrdInd[1]].x, texCoords[triangles[i].texCrdInd[1]].y); glVertex3fv(vertex[1].array); } glEnd(); glPopMatrix(); return true; } /////////////////////////////////////////////////////////////////////////////////////////// void GcGMD::Destroy() { // Clean up the memory if(triangles != NULL) { delete [] triangles; triangles = NULL; } if(vertices != NULL) { delete [] vertices; vertices = NULL; } if(texCoords != NULL) { delete [] texCoords; texCoords = NULL; } if(texture != NULL) { delete [] texture; texture = NULL; } } ///////////////////////////////////////////////////////////////////////////////////////////