www.pudn.com > Gimcrack-v0.0051-Source.zip > ms3d.cpp
/* GcModel.cpp Loads and renders a Milkshape3D model. Author: Brett Porter Email: brettporter@yahoo.com Website: http://rsn.gamedev.net Copyright (C)2001, Brett Porter. All Rights Reserved. This file may be used only as long as this copyright notice remains intact. */ //#include#include #include "ms3d.h" using namespace std; /////////////////////////////////////////////////////////////////////////////////////// GcMS3D::GcMS3D() { m_numMeshes = 0; m_meshes = NULL; m_numMaterials = 0; m_materials = NULL; m_numTriangles = 0; m_triangles = NULL; m_numVertices = 0; m_vertices = NULL; // { NEW } m_numJoints = 0; m_joints = NULL; } /////////////////////////////////////////////////////////////////////////////////////// GcMS3D::~GcMS3D() { Destroy(); } /////////////////////////////////////////////////////////////////////////////////////// bool GcMS3D::Load(char *filename) { ifstream inputFile( filename, ios::in | ios::binary ); if( inputFile.fail() ) { //cerr << "Couldn't open the model file." << endl; return false; } char pathTemp[PATH_MAX+1]; int pathLength; for ( pathLength = strlen( filename ); --pathLength; ) { if ( filename[pathLength] == '/' || filename[pathLength] == '\\' ) { break; } } strncpy(pathTemp, filename, pathLength); int i; if ( pathLength > 0 ) { pathTemp[pathLength++] = '/'; } inputFile.seekg(0, ios::end); long fileSize = inputFile.tellg(); inputFile.seekg(0, ios::beg); byte * pBuffer = new byte[fileSize]; inputFile.read((char *)pBuffer, fileSize); inputFile.close(); const byte *pPtr = pBuffer; MS3DHeader *pHeader = ( MS3DHeader* )pPtr; pPtr += sizeof( MS3DHeader ); if(strncmp( pHeader->m_ID, "MS3D000000", 10 ) != 0) { //cerr << "Not an MS3D file." << endl; return false; } if( pHeader->m_version < 3 ) { //cerr << "I know nothing about MS3D v1.2" << endl; return false; } int nVertices = *(word*)pPtr; m_numVertices = nVertices; m_vertices = new Vertex[nVertices]; pPtr += sizeof(word); for(i = 0; i < nVertices; i++) { MS3DVertex * pVertex = (MS3DVertex*)pPtr; m_vertices[i].m_boneID = pVertex->m_boneID; memcpy( m_vertices[i].m_location, pVertex->m_vertex, sizeof(float)*3); //m_vertices[i].m_location.x = pVertex->m_vertex[0]; //m_vertices[i].m_location.y = pVertex->m_vertex[1]; //m_vertices[i].m_location.z = pVertex->m_vertex[2]; pPtr += sizeof(MS3DVertex); } int nTriangles = *(word*)pPtr; m_numTriangles = nTriangles; m_triangles = new Triangle[nTriangles]; pPtr += sizeof(word); for ( i = 0; i < nTriangles; i++ ) { MS3DTriangle *pTriangle = ( MS3DTriangle* )pPtr; int vertexIndices[3] = { pTriangle->m_vertexIndices[0], pTriangle->m_vertexIndices[1], pTriangle->m_vertexIndices[2] }; float t[3] = { 1.0f-pTriangle->m_t[0], 1.0f-pTriangle->m_t[1], 1.0f-pTriangle->m_t[2] }; memcpy( m_triangles[i].m_vertexNormals, pTriangle->m_vertexNormals, sizeof(float)*3*3 ); memcpy( m_triangles[i].m_s, pTriangle->m_s, sizeof(float)*3 ); memcpy( m_triangles[i].m_t, t, sizeof(float)*3 ); memcpy( m_triangles[i].m_vertexIndices, vertexIndices, sizeof(int)*3 ); pPtr += sizeof( MS3DTriangle ); } int nGroups = *(word*)pPtr; m_numMeshes = nGroups; m_meshes = new Mesh[nGroups]; pPtr += sizeof(word); for ( i = 0; i < nGroups; i++ ) { pPtr += sizeof(byte); // flags pPtr += 32; // name word nTriangles = *(word*)pPtr; pPtr += sizeof(word); int *pTriangleIndices = new int[nTriangles]; for ( int j = 0; j < nTriangles; j++ ) { pTriangleIndices[j] = *(word*)pPtr; pPtr += sizeof(word); } char materialIndex = *(char*)pPtr; pPtr += sizeof(char); m_meshes[i].m_materialIndex = materialIndex; m_meshes[i].m_numTriangles = nTriangles; m_meshes[i].m_triangleIndices = pTriangleIndices; } int nMaterials = *(word*)pPtr; m_numMaterials = nMaterials; m_materials = new Material[nMaterials]; pPtr += sizeof(word); for(i = 0; i < nMaterials; i++) { MS3DMaterial *pMaterial = ( MS3DMaterial* )pPtr; memcpy( m_materials[i].m_ambient, pMaterial->m_ambient, sizeof(float)*4 ); memcpy( m_materials[i].m_diffuse, pMaterial->m_diffuse, sizeof(float)*4 ); memcpy( m_materials[i].m_specular, pMaterial->m_specular, sizeof(float)*4 ); memcpy( m_materials[i].m_emissive, pMaterial->m_emissive, sizeof(float)*4 ); m_materials[i].m_shininess = pMaterial->m_shininess; if(strncmp(pMaterial->m_texture, ".\\", 2) == 0) { // MS3D 1.5.x relative path strcpy(pathTemp + pathLength, pMaterial->m_texture + 2); //m_materials[i].m_textureFilename = new char[strlen( pathTemp )+1]; //strcpy(m_materials[i].m_textureFilename, pa strcpy( m_materials[i].m_textureFilename, pathTemp ); m_materials[i].texture.Create(pathTemp); } else { // MS3D 1.4.x or earlier - absolute path //m_materials[i].m_textureFilename = new char[strlen( pMaterial->m_texture )+1]; strcpy( m_materials[i].m_textureFilename, pMaterial->m_texture ); m_materials[i].texture.Create(pathTemp); } pPtr += sizeof(MS3DMaterial); } // Load Skeletal Animation Stuff float animFPS = *(float*)pPtr; pPtr += sizeof(float); // skip currentTime pPtr += sizeof(float); int totalFrames = *(int*)pPtr; pPtr += sizeof(int); m_totalTime = totalFrames*1000.0/animFPS; delete[] pBuffer; GcVector3 extreme(0, 0, 0); for( i = 0; i < m_numMeshes; i++ ) { for( int j = 0; j < m_meshes[i].m_numTriangles; j++ ) { int triangleIndex = m_meshes[i].m_triangleIndices[j]; const Triangle * pTri = &m_triangles[triangleIndex]; for ( int k = 0; k < 3; k++ ) { int index = pTri->m_vertexIndices[k]; if( m_vertices[index].m_location[0] > extreme.x ) extreme.x = m_vertices[index].m_location[0]; if( m_vertices[index].m_location[1] > extreme.y ) extreme.y = m_vertices[index].m_location[1]; if( m_vertices[index].m_location[2] > extreme.z ) extreme.z = m_vertices[index].m_location[2]; } } } g_Debug->Log("Extreme x: %f - y: %f - z: %f\n", extreme.x, extreme.y, extreme.z ); SetExtents(extreme); return true; } /////////////////////////////////////////////////////////////////////////////////////// bool GcMS3D::RenderKeyFrame(int frame) { glPushMatrix(); static int loop = 0; loop++; if(loop > 360) { loop = 0; } glMultMatrixf(m_worldMatrix); glScalef(GetWorldScaling().x, GetWorldScaling().y, GetWorldScaling().z ); /* if(settings.ShowDebug()) { glBegin(GL_LINES); glColor3f(0.5, 0.0, 0.0); glVertex3f(-2000, 0.0, 0.0); glVertex3f( 2000, 0.0, 0.0); glColor3f(0.5, 0.0, 0.0); glVertex3f( 0, -2000, 0.0); glVertex3f( 0, 2000, 0.0); glColor3f(0.5, 0.0, 0.0); glVertex3f( 0, 0, -2000); glVertex3f( 0, 0, 2000); glEnd(); }*/ glColor3f(1.0, 1.0, 1.0); // Draw by group for(int i = 0; i < m_numMeshes; i++) { int materialIndex = m_meshes[i].m_materialIndex; if(materialIndex >= 0) { glMaterialfv( GL_FRONT, GL_AMBIENT, m_materials[materialIndex].m_ambient ); glMaterialfv( GL_FRONT, GL_DIFFUSE, m_materials[materialIndex].m_diffuse ); glMaterialfv( GL_FRONT, GL_SPECULAR, m_materials[materialIndex].m_specular ); glMaterialfv( GL_FRONT, GL_EMISSION, m_materials[materialIndex].m_emissive ); glMaterialf( GL_FRONT, GL_SHININESS, m_materials[materialIndex].m_shininess ); if(m_materials[materialIndex].texture.IsLoaded()) { glEnable(GL_TEXTURE_2D); m_materials[materialIndex].texture.Bind(); } } glBegin( GL_TRIANGLES ); { for ( int j = 0; j < m_meshes[i].m_numTriangles; j++ ) { int triangleIndex = m_meshes[i].m_triangleIndices[j]; const Triangle * pTri = &m_triangles[triangleIndex]; for ( int k = 0; k < 3; k++ ) { int index = pTri->m_vertexIndices[k]; // same as before glTexCoord2f( pTri->m_s[k], pTri->m_t[k] ); glNormal3fv( pTri->m_vertexNormals[k] ); glVertex3fv( m_vertices[index].m_location ); } } } glEnd(); } glPopMatrix(); //glDisable(GL_TEXTURE_2D); return true; } /////////////////////////////////////////////////////////////////////////////////////// void GcMS3D::Destroy() { int i; for ( i = 0; i < m_numMeshes; i++ ) delete[] m_meshes[i].m_triangleIndices; //for ( i = 0; i < m_numMaterials; i++ ) //delete[] m_materials[i].m_pTextureFilename; m_numMeshes = 0; if ( m_meshes != NULL ) { delete[] m_meshes; m_meshes = NULL; } m_numMaterials = 0; if ( m_materials != NULL ) { delete[] m_materials; m_materials = NULL; } m_numTriangles = 0; if ( m_triangles != NULL ) { delete[] m_triangles; m_triangles = NULL; } m_numVertices = 0; if ( m_vertices != NULL ) { delete[] m_vertices; m_vertices = NULL; } // { NEW } for ( i = 0; i < m_numJoints; i++ ) { delete[] m_joints[i].m_rotationKeyframes; delete[] m_joints[i].m_translationKeyframes; } m_numJoints = 0; if ( m_joints != NULL ) { delete[] m_joints; m_joints = NULL; } // { end NEW } } ///////////////////////////////////////////////////////////////////////////////////////