/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Patrick Boenzli */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_IMPORTER #include "md3_data.h" #include "md3_bone_frame.h" #include "md3_tag.h" #include "md3_mesh.h" #include "material.h" namespace md3 { /******************************************************************************** * MD3Data * ********************************************************************************/ /** \brief simple constructor */ MD3Data::MD3Data(const std::string& modelFileName, const std::string& skinFileName, float scale) { this->loadModel(modelFileName); // this->loadSkin(skinFileName); } /** \brief simple destructor this will clean out all the necessary data for a specific md2model */ MD3Data::~MD3Data() { delete this->header; } /** \brief this will load the whole model data (vertices, opengl command list, ...) * @param fileName: the name of the model file \return true if success */ bool MD3Data::loadModel(const std::string& fileName) { FILE *pFile; //file stream // char* buffer; //buffer for frame data int fileOffset = 0; // file data offset //! @todo this chek should include deleting a loaded model (eventually) if (fileName.empty()) return false; PRINTF(0)("opening file: %s\n", fileName.c_str()); pFile = fopen(fileName.c_str(), "rb"); if( unlikely(!pFile)) { PRINTF(1)("Couldn't open the MD3 File for loading. Exiting.\n"); return false; } fileOffset += this->readHeader(pFile, fileOffset); /* check for the header version: make sure its a md2 file :) */ if( unlikely(this->header->version != MD3_VERSION) && unlikely(this->header->ident != MD3_IDENT)) { PRINTF(1)("Couldn't load file %s: invalid file format: stop loading\n", fileName.c_str()); return false; } // check if the filesize is correct if( this->header->fileSize > this->header->tagStart && this->header->fileSize >= this->header->meshStart) { bool bBoneFrames, bTags, bMeshes; bBoneFrames = ( this->header->boneFrameNum == 0); bTags = ( this->header->tagNum == 0); bMeshes = ( this->header->meshNum == 0); // read different parts of the model in correct order while( !(bBoneFrames && bTags && bMeshes)) { printf("while\n"); if( fileOffset == this->header->boneFrameStart && !bBoneFrames) { fileOffset += this->readBoneFrames(pFile, fileOffset); bBoneFrames = true; } else if( fileOffset == this->header->tagStart && !bTags) { fileOffset += this->readTags(pFile, fileOffset); bTags = true; } else if( fileOffset == this->header->meshStart && !bMeshes) { fileOffset += this->readMeshes(pFile, fileOffset); bMeshes = true; } } } fclose(pFile); return true; } /** \brief loads the skin/material stuff * @param fileName: name of the skin file \return true if success */ bool MD3Data::loadSkin(const std::string& fileName) { // if( fileName.empty()) // { // this->skinFileName = ""; // return false; // } // // this->skinFileName = fileName; // // this->material.setName("md2ModelMaterial"); // this->material.setDiffuseMap(fileName); // this->material.setIllum(3); // this->material.setAmbient(1.0, 1.0, 1.0); return true; } /** * read heaader */ int MD3Data::readHeader(FILE* pFile, int fileOffset) { this->header = new MD3Header; fread(this->header, 1, sizeof(MD3Header), pFile); //header debug: PRINTF(0)("MD3 Header debug section======================================\n"); printf("ident: %i\n", this->header->ident); printf("version: %i\n", this->header->version); printf("filename: %s\n", this->header->filename); printf("boneFrameNum: %i\n", this->header->boneFrameNum); printf("tag number: %i\n", this->header->tagNum); printf("mesh number: %i\n", this->header->meshNum); printf("max tex num: %i\n", this->header->maxTexNum); printf("bone frame start: %i\n", this->header->boneFrameStart); printf("tag start: %i\n", this->header->tagStart); printf("mesh start: %i\n", this->header->meshStart); printf("fileSize: %i\n", this->header->fileSize); return sizeof(MD3Header); } /** * read bone frames */ int MD3Data::readBoneFrames(FILE* pFile, int fileOffset) { this->boneFrames = new MD3BoneFrame*[this->header->boneFrameNum]; for( int i = 0; i < this->header->boneFrameNum; i++) { this->boneFrames[i] = new MD3BoneFrame(i); MD3BoneFrameData* md = new MD3BoneFrameData; fread(md, 1, sizeof(MD3BoneFrameData), pFile); this->boneFrames[i]->data = md; } return this->header->boneFrameNum * sizeof(MD3BoneFrameData); } /** * read the tags */ int MD3Data::readTags(FILE* pFile, int fileOffset) { // this->boneFrames = new MD3BoneFrame*[this->header->boneFrameNum]; for( int i = 0; i < this->header->boneFrameNum; i++) { this->boneFrames[i]->tags = new MD3Tag*[this->header->tagNum]; for( int j = 0; j < this->header->tagNum; j++) { this->boneFrames[i]->tags[j] = new MD3Tag(); MD3TagData* md = new MD3TagData; fread(md, 1, sizeof(MD3TagData), pFile); this->boneFrames[i]->tags[j]->data = md; } } return this->header->boneFrameNum * this->header->tagNum * sizeof(MD3TagData); } /** * read meshes */ int MD3Data::readMeshes(FILE* pFile, int fileOffset) { int localFileOffset = fileOffset; //!< local file offset this->meshes = new MD3Mesh*[this->header->meshNum]; for( int i = 0; i < this->header->meshNum; i++) { this->meshes[i] = new MD3Mesh(); bool bTriangles, bTexVecs, bVertices, bTextures; //!< the parts that have been read so far //start reading mesh data MD3MeshHeader* md = new MD3MeshHeader; fread(md, 1, sizeof(MD3MeshHeader), pFile); this->meshes[i]->header = md; localFileOffset += sizeof(MD3MeshHeader); if( unlikely(this->meshes[i]->header->id != MD3_IDENT)) { PRINTF(1)("Wrong MD3 mesh file tag, file %s could be corrupt\n", this->filename.c_str()); return false; } // check which parts to be loaded bTriangles = ( this->meshes[i]->header->triangleNum == 0); bTexVecs = ( this->meshes[i]->header->vertexNum == 0); bVertices = ( this->meshes[i]->header->meshFrameNum == 0); bTextures = ( this->meshes[i]->header->textureNum == 0); // now read the data block whise while( !(bTriangles && bTexVecs && bVertices && bTextures)) { if( localFileOffset == this->meshes[i]->header->triangleStart && !bTriangles) { localFileOffset += this->readMeshTriangles(pFile, localFileOffset, i); bTriangles = true; } else if( localFileOffset == this->meshes[i]->header->textureStart && !bTextures) { fileOffset += this->readMeshTextures(pFile, localFileOffset, i); bTextures = true; } else if( localFileOffset == this->meshes[i]->header->texVecStart && !bTexVecs) { localFileOffset += this->readMeshTexVecs(pFile, localFileOffset, i); bTexVecs = true; } else if( fileOffset == this->meshes[i]->header->vertexStart && !bVertices) { localFileOffset += this->readMeshVertices(pFile, localFileOffset, i); bVertices = true; } } } return localFileOffset - fileOffset; } /** * reading in the mesh triangles */ int MD3Data::readMeshTriangles(FILE* pFile, int fileOffset, int mesh) { // create the memomry to save the triangles this->meshes[mesh]->triangles = new MD3Triangle[this->meshes[mesh]->header->triangleNum]; fread(this->meshes[mesh]->triangles, 1, sizeof(MD3Triangle), pFile); return this->meshes[mesh]->header->triangleNum * sizeof(MD3Triangle); } /** * reading in the mesh textures */ int MD3Data::readMeshTextures(FILE* pFile, int fileOffset, int mesh) { // create the textures this->meshes[mesh]->material = new Material[this->meshes[mesh]->header->textureNum]; MD3Texture* tex = new MD3Texture[this->meshes[mesh]->header->textureNum]; fread(this->meshes[mesh]->material, 1, sizeof(MD3Texture), pFile); for( int i = 0; i < this->meshes[mesh]->header->textureNum; i++) { PRINTF(0)(" texture file: %s\n", tex[i].fileName); this->meshes[mesh]->material[i].setDiffuseMap(tex[i].fileName); this->meshes[mesh]->material[i].setAmbient(1, 1, 1); } return this->meshes[mesh]->header->textureNum * sizeof(MD3Texture); } /** * reading in the mesh tex vecs */ int MD3Data::readMeshTexVecs(FILE* pFile, int fileOffset, int mesh) { return 0; } /** * reading in the mesh vertices */ int MD3Data::readMeshVertices(FILE* pFile, int fileOffset, int mesh) { return 0; } }