Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/bsp_model/src/lib/graphics/importer/md3/md3_data.cc @ 8660

Last change on this file since 8660 was 8660, checked in by patrick, 18 years ago

bsp: found the interpolation bug, tracing

File size: 15.1 KB
RevLine 
[8344]1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Patrick Boenzli
13*/
14
15#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_IMPORTER
16
17#include "md3_data.h"
18
[8357]19#include "md3_bone_frame.h"
[8371]20#include "md3_tag.h"
[8372]21#include "md3_mesh.h"
[8344]22
[8418]23#include "material.h"
[8357]24
[8490]25#include "debug.h"
[8418]26
[8351]27namespace md3
28{
[8344]29
30/********************************************************************************
31 *   MD3Data                                                                    *
32 ********************************************************************************/
33
34/**
35  \brief simple constructor
36*/
37MD3Data::MD3Data(const std::string& modelFileName, const std::string& skinFileName, float scale)
38{
[8654]39  this->filename = modelFileName;
[8344]40
[8549]41  this->parentTagIndex = -1;
42  this->parent = NULL;
[8344]43
[8551]44  this->animationState.currentFrame = 0;
45  this->animationState.nextFrame = 1;
46  this->animationState.interpolationFraction = 0.0f;
47
[8654]48  this->animation = NULL;
[8660]49  this->bInterpolate = false;
50  this->upperBound = 0;
[8654]51
[8344]52  this->loadModel(modelFileName);
[8354]53//   this->loadSkin(skinFileName);
[8634]54  this->init();
[8344]55}
56
57
58/**
59  \brief simple destructor
60
61  this will clean out all the necessary data for a specific md2model
62*/
63MD3Data::~MD3Data()
64{
65  delete this->header;
66}
67
68
[8549]69/**
[8634]70 * init data
71 */
72void MD3Data::init()
73{
74  // create the temporary data to work with (interpolation data)
75  this->tmpBoneFrame = new MD3BoneFrame();
76
77  this->tmpMesh = new sVec3D*[this->header->meshNum];
78  for( int i = 0; i < this->header->meshNum; i++)
79    this->tmpMesh[i] = new sVec3D[this->meshes[i]->header->vertexNum];
80
81  this->tmpNormal = new MD3Normal*[this->header->meshNum];
82  for( int i = 0; i < this->header->meshNum; i++)
83    this->tmpNormal[i] = new MD3Normal[this->meshes[i]->header->vertexNum];
84
85  this->tmpMatrix = new float*[this->header->tagNum];
86  for( int i = 0; i < this->header->tagNum; i++)
87    this->tmpMatrix[i] = new float[16];
88
89}
90
91
92/**
[8597]93 * link a model at the specified tag position to this model. if the position is already
[8549]94 * occupied, the old submodel will be replaced
95 *
96 *  @param tagIndex: tag to link the submodel to
97 *  @param child: the submodel that should be linked to this model
98 */
99void MD3Data::addLinkedModel(int tagIndex, MD3Data* child)
100{
101  this->sortedMap[tagIndex] = child;
102  child->parentTagIndex = tagIndex;
103}
[8344]104
[8549]105
[8597]106
[8344]107/**
[8597]108 * Return the index of the tag with the given name for this model.
109 *
110 * This will return -1 if their is no such tag.
111 */
112 int MD3Data::getTagIndexByName(std::string tagName)
113{
114   int res = -1;
115
116   if( this->header->boneFrameNum > 0) {
117     MD3Tag** tags = this->boneFrames[0]->tags;
118     for( int i = 0; i < this->header->tagNum; i++)
119       if( tags[i]->name.find(tagName) == std::string::npos)
120         return i;
121   }
122
123   return res;
124 }
125
126
127
128/**
[8344]129  \brief this will load the whole model data (vertices, opengl command list, ...)
130* @param fileName: the name of the model file
131  \return true if success
132*/
133bool MD3Data::loadModel(const std::string& fileName)
134{
135  FILE *pFile;                            //file stream
[8353]136//  char* buffer;                           //buffer for frame data
[8354]137  int fileOffset = 0;                     // file data offset
[8346]138
139
[8344]140  //! @todo this chek should include deleting a loaded model (eventually)
141  if (fileName.empty())
142    return false;
143
[8354]144  PRINTF(0)("opening file: %s\n", fileName.c_str());
[8344]145  pFile = fopen(fileName.c_str(), "rb");
146  if( unlikely(!pFile))
147    {
[8347]148      PRINTF(1)("Couldn't open the MD3 File for loading. Exiting.\n");
[8344]149      return false;
150    }
[8357]151  fileOffset += this->readHeader(pFile, fileOffset);
[8344]152  /* check for the header version: make sure its a md2 file :) */
[8354]153  if( unlikely(this->header->version != MD3_VERSION) && unlikely(this->header->ident != MD3_IDENT))
[8344]154    {
155      PRINTF(1)("Couldn't load file %s: invalid file format: stop loading\n", fileName.c_str());
156      return false;
157    }
158
[8353]159
[8354]160    // check if the filesize is correct
161    if( this->header->fileSize > this->header->tagStart &&
162        this->header->fileSize >= this->header->meshStart)
163    {
164      bool bBoneFrames, bTags, bMeshes;
165      bBoneFrames = ( this->header->boneFrameNum == 0);
166      bTags = ( this->header->tagNum == 0);
167      bMeshes = ( this->header->meshNum == 0);
168
169      // read different parts of the model in correct order
170      while( !(bBoneFrames && bTags && bMeshes))
171      {
[8426]172        printf("while, fileOffset = %i\n", fileOffset);
[8354]173        if( fileOffset == this->header->boneFrameStart && !bBoneFrames)
[8355]174        {
175          fileOffset += this->readBoneFrames(pFile, fileOffset);
176          bBoneFrames = true;
177        }
[8354]178        else if( fileOffset == this->header->tagStart && !bTags)
[8355]179        {
180          fileOffset += this->readTags(pFile, fileOffset);
181          bTags = true;
182        }
[8354]183        else if( fileOffset == this->header->meshStart && !bMeshes)
[8355]184        {
185          fileOffset += this->readMeshes(pFile, fileOffset);
186          bMeshes = true;
187        }
[8354]188      }
189
190    }
191
[8344]192  fclose(pFile);
[8347]193
194  return true;
[8344]195}
196
197
198/**
199  \brief loads the skin/material stuff
200* @param fileName: name of the skin file
201  \return true if success
202*/
203bool MD3Data::loadSkin(const std::string& fileName)
204{
[8357]205//   if( fileName.empty())
206//     {
207//       this->skinFileName = "";
208//       return false;
209//     }
210//
211//   this->skinFileName = fileName;
212//
213//   this->material.setName("md2ModelMaterial");
214//   this->material.setDiffuseMap(fileName);
215//   this->material.setIllum(3);
216//   this->material.setAmbient(1.0, 1.0, 1.0);
[8344]217
[8347]218  return true;
[8344]219}
[8346]220
221
222/**
223 * read heaader
224 */
[8355]225int MD3Data::readHeader(FILE* pFile, int fileOffset)
226{
[8426]227  PRINTF(0)("Reading Header\n");
228
[8357]229  this->header = new MD3Header;
230  fread(this->header, 1, sizeof(MD3Header), pFile);
231
232    //header debug:
233  PRINTF(0)("MD3 Header debug section======================================\n");
234  printf("ident: %i\n", this->header->ident);
235  printf("version: %i\n", this->header->version);
236  printf("filename: %s\n", this->header->filename);
237  printf("boneFrameNum: %i\n", this->header->boneFrameNum);
238  printf("tag number: %i\n", this->header->tagNum);
239  printf("mesh number: %i\n", this->header->meshNum);
240  printf("max tex num: %i\n", this->header->maxTexNum);
241  printf("bone frame start: %i\n", this->header->boneFrameStart);
242  printf("tag start: %i\n", this->header->tagStart);
243  printf("mesh start: %i\n", this->header->meshStart);
244  printf("fileSize: %i\n", this->header->fileSize);
245
246  return sizeof(MD3Header);
[8355]247}
[8346]248
249
250/**
251 * read bone frames
252 */
[8355]253int MD3Data::readBoneFrames(FILE* pFile, int fileOffset)
254{
[8426]255  PRINTF(0)("Reading Bone Frames\n");
256
[8357]257  this->boneFrames = new MD3BoneFrame*[this->header->boneFrameNum];
258
259  for( int i = 0; i < this->header->boneFrameNum; i++)
[8358]260  {
[8357]261    this->boneFrames[i] = new MD3BoneFrame(i);
262
[8358]263    MD3BoneFrameData* md = new MD3BoneFrameData;
264    fread(md, 1, sizeof(MD3BoneFrameData), pFile);
[8372]265    this->boneFrames[i]->data = md;
[8358]266  }
267
268  return this->header->boneFrameNum * sizeof(MD3BoneFrameData);
[8355]269}
[8346]270
271
272/**
273 * read the tags
274 */
[8355]275int MD3Data::readTags(FILE* pFile, int fileOffset)
276{
[8426]277  PRINTF(0)("Reading Tags\n");
[8359]278
279  for( int i = 0; i < this->header->boneFrameNum; i++)
280  {
[8371]281    this->boneFrames[i]->tags = new MD3Tag*[this->header->tagNum];
282
[8359]283    for( int j = 0; j < this->header->tagNum; j++)
284    {
[8371]285      this->boneFrames[i]->tags[j] = new MD3Tag();
286      MD3TagData* md = new MD3TagData;
287      fread(md, 1, sizeof(MD3TagData), pFile);
[8372]288      this->boneFrames[i]->tags[j]->data = md;
[8579]289
290      this->boneFrames[i]->tags[j]->name = std::string(this->boneFrames[i]->tags[j]->data->name);
291      this->boneFrames[i]->tags[j]->position = Vector( this->boneFrames[i]->tags[j]->data->position[0],
292                                                       this->boneFrames[i]->tags[j]->data->position[1],
293                                                       this->boneFrames[i]->tags[j]->data->position[2]);
294      for( int k = 0; k < 3; k++)
295        for( int l = 0; l < 3; l++)
296          this->boneFrames[i]->tags[j]->matrix[k][l] = this->boneFrames[i]->tags[j]->data->matrix[k][l];
297
298      //PRINTF(0)("Tag name: %s\n", this->boneFrames[i]->tags[j]->name.c_str());
[8359]299    }
300  }
301
[8371]302  return this->header->boneFrameNum * this->header->tagNum * sizeof(MD3TagData);
[8355]303}
[8346]304
305
306/**
307 * read meshes
308 */
[8355]309int MD3Data::readMeshes(FILE* pFile, int fileOffset)
310{
[8426]311  PRINTF(0)("Reading Mesh Data\n");
[8375]312
[8432]313  fileOffset = 0;
[8426]314
[8372]315  this->meshes = new MD3Mesh*[this->header->meshNum];
316
317  for( int i = 0; i < this->header->meshNum; i++)
318  {
319    this->meshes[i] = new MD3Mesh();
320
[8432]321    int localFileOffset = 0;
[8375]322    bool   bTriangles, bTexVecs, bVertices, bTextures;            //!< the parts that have been read so far
[8374]323
324    //start reading mesh data
[8375]325    MD3MeshHeader* md = new MD3MeshHeader;
326    fread(md, 1, sizeof(MD3MeshHeader), pFile);
327    this->meshes[i]->header = md;
328    localFileOffset += sizeof(MD3MeshHeader);
[8374]329
[8426]330    PRINTF(0)("MD3 Mesh Header debug section\n");
331    printf("ident: %i\n", md->id);
332    printf("filename: %s\n", md->name);
333    printf("meshFrameNum: %i\n", md->meshFrameNum);
334    printf("textureNum: %i\n", md->textureNum);
335    printf("vertexNum: %i \n", md->vertexNum);
336    printf("triangleNum: %i\n", md->triangleNum);
337    printf("triangleStart: %i\n", md->triangleStart);
338    printf("textureStart: %i\n", md->textureStart);
339    printf("texVecStart: %i\n", md->texVecStart);
340    printf("vertexStart: %i\n", md->vertexStart);
341    printf("fileSize: %i\n", md->meshSize);
342
[8432]343    if( unlikely(this->meshes[i]->header->id != MD3_IDENT))
344    {
345      PRINTF(1)("Wrong MD3 mesh file tag, file %s could be corrupt\n", this->filename.c_str());
346      return false;
347    }
348
[8375]349    // check which parts to be loaded
350    bTriangles = ( this->meshes[i]->header->triangleNum == 0);
351    bTexVecs = ( this->meshes[i]->header->vertexNum == 0);
352    bVertices = ( this->meshes[i]->header->meshFrameNum == 0);
353    bTextures = ( this->meshes[i]->header->textureNum == 0);
354
355    // now read the data block whise
356    while( !(bTriangles && bTexVecs && bVertices && bTextures))
357    {
[8426]358      PRINTF(0)("while2: localOffset = %i\n", localFileOffset);
[8375]359      if( localFileOffset == this->meshes[i]->header->triangleStart  && !bTriangles)
360      {
[8382]361        localFileOffset += this->readMeshTriangles(pFile, localFileOffset, i);
[8375]362        bTriangles = true;
363      }
364      else if( localFileOffset == this->meshes[i]->header->textureStart && !bTextures)
365      {
[8428]366        localFileOffset += this->readMeshTextures(pFile, localFileOffset, i);
[8375]367        bTextures = true;
368      }
369      else if( localFileOffset == this->meshes[i]->header->texVecStart && !bTexVecs)
370      {
[8382]371        localFileOffset += this->readMeshTexVecs(pFile, localFileOffset, i);
[8375]372        bTexVecs = true;
373      }
[8428]374      else if( localFileOffset == this->meshes[i]->header->vertexStart && !bVertices)
[8375]375      {
[8382]376        localFileOffset += this->readMeshVertices(pFile, localFileOffset, i);
[8375]377        bVertices = true;
378      }
379    }
[8432]380    fileOffset += localFileOffset;
381    PRINTF(0)("finished reading mesh %i, got %i of %i byes\n", i, localFileOffset, md->meshSize);
[8372]382  }
[8432]383  return fileOffset;
[8355]384}
[8351]385
[8382]386
387
[8418]388/**
389 * reading in the mesh triangles
390 */
[8382]391int MD3Data::readMeshTriangles(FILE* pFile, int fileOffset, int mesh)
392{
[8426]393  PRINTF(0)("Reading Mesh Triangles\n");
[8416]394  // create the memomry to save the triangles
[8418]395  this->meshes[mesh]->triangles = new MD3Triangle[this->meshes[mesh]->header->triangleNum];
[8433]396  fread(this->meshes[mesh]->triangles, 1, sizeof(MD3Triangle) * this->meshes[mesh]->header->triangleNum, pFile);
[8416]397
[8573]398//   for( int i = 0; i < this->meshes[mesh]->header->triangleNum; i++) {
399//     PRINTF(0)("Triangle read: %i, %i, %i\n", this->meshes[mesh]->triangles[i].vertexOffset[0], this->meshes[mesh]->triangles[i].vertexOffset[1]
400//         , this->meshes[mesh]->triangles[i].vertexOffset[2]);
401//   }
402
[8416]403  return this->meshes[mesh]->header->triangleNum * sizeof(MD3Triangle);
[8353]404}
405
[8418]406
407/**
408 * reading in the mesh textures
409 */
[8382]410int MD3Data::readMeshTextures(FILE* pFile, int fileOffset, int mesh)
[8416]411{
[8426]412  PRINTF(0)("Reading Mesh Textures\n");
413
[8418]414  // create the textures
415  this->meshes[mesh]->material = new Material[this->meshes[mesh]->header->textureNum];
416
417  MD3Texture* tex = new MD3Texture[this->meshes[mesh]->header->textureNum];
[8433]418  fread(tex, 1, sizeof(MD3Texture) * this->meshes[mesh]->header->textureNum, pFile);
[8418]419
420  for( int i = 0; i < this->meshes[mesh]->header->textureNum; i++) {
421    PRINTF(0)(" texture file: %s\n", tex[i].fileName);
[8579]422#warning texture stuff hard coded. make this again
[8578]423    std::string path("/home/boenzlip/tmp/q3/Downloads/MOH/q3mdl-alien3/");
424    std::string path1(tex[i].fileName);
425    std::string fullPath( path + path1);
[8590]426    this->meshes[mesh]->material[i].setDiffuseMap(/*tex[i].fileName*/ /*fullPath.c_str()*/ "maps/creatures/gork/gorkup.tga");
[8418]427    this->meshes[mesh]->material[i].setAmbient(1, 1, 1);
428  }
429
430  return this->meshes[mesh]->header->textureNum * sizeof(MD3Texture);
[8416]431}
[8382]432
[8418]433
434/**
435 * reading in the mesh tex vecs
436 */
[8382]437int MD3Data::readMeshTexVecs(FILE* pFile, int fileOffset, int mesh)
[8416]438{
[8426]439  PRINTF(0)("Reading Mesh TexVecs\n");
[8428]440
[8420]441  this->meshes[mesh]->texVecs = new MD3TexVecs[this->meshes[mesh]->header->vertexNum];
[8433]442  fread(this->meshes[mesh]->texVecs, 1, sizeof(MD3TexVecs) * this->meshes[mesh]->header->vertexNum, pFile);
[8420]443
[8573]444//   for( int i = 0; i < this->meshes[mesh]->header->vertexNum; i++)  {
445//     PRINTF(0)("TexVec read: %f, %f\n", this->meshes[mesh]->texVecs[i].textureCoord[0], this->meshes[mesh]->texVecs[i].textureCoord[0]);
446//   }
447
[8420]448  return this->meshes[mesh]->header->vertexNum * sizeof(MD3TexVecs);
[8416]449}
[8382]450
[8418]451
452/**
453 * reading in the mesh vertices
454 */
[8382]455int MD3Data::readMeshVertices(FILE* pFile, int fileOffset, int mesh)
[8416]456{
[8426]457  PRINTF(0)("Reading Mesh Vertices\n");
458
[8423]459  // reserver memory for the vertex informations
[8658]460  this->meshes[mesh]->meshFrames = new sVec3D*[this->meshes[mesh]->header->meshFrameNum]; // * this->meshes[mesh]->header->vertexNum
461  this->meshes[mesh]->normals = new MD3Normal*[this->meshes[mesh]->header->meshFrameNum];
[8423]462
[8658]463  for( int i = 0; i < this->meshes[mesh]->header->meshFrameNum; i++)
[8436]464  {
[8658]465    this->meshes[mesh]->meshFrames[i] = new sVec3D[this->meshes[mesh]->header->vertexNum];
466    this->meshes[mesh]->normals[i] = new MD3Normal[this->meshes[mesh]->header->vertexNum];
[8423]467
[8658]468    for( int j = 0; j < this->meshes[mesh]->header->vertexNum; j++)
469    {
470      // read out the compressed data
471      MD3VertexCompressed* vc = new MD3VertexCompressed;
472      fread(vc, 1, sizeof(MD3VertexCompressed), pFile);
[8423]473
[8658]474      this->meshes[mesh]->meshFrames[i][j][0] = (float)vc->vector[0] / 64.0f;
475      this->meshes[mesh]->meshFrames[i][j][1] = (float)vc->vector[1] / 64.0f;
476      this->meshes[mesh]->meshFrames[i][j][2] = (float)vc->vector[2] / 64.0f;
[8439]477
[8658]478      this->meshes[mesh]->normals[i][j].vertexNormal[0] = (int)vc->vertexNormal[0];
479      this->meshes[mesh]->normals[i][j].vertexNormal[1] = (int)vc->vertexNormal[1];
480
[8573]481//     PRINTF(0)("nr: %i, meshframes: %f, %f, %f, normal: %f, %f\n", i, this->meshes[mesh]->meshFrames[i][0], this->meshes[mesh]->meshFrames[i][1],
482//     this->meshes[mesh]->meshFrames[i][2], this->meshes[mesh]->normals[i].vertexNormal[0], this->meshes[mesh]->normals[i].vertexNormal[1]);
483
[8658]484      delete vc;
485    }
[8423]486  }
487
488  return this->meshes[mesh]->header->meshFrameNum * this->meshes[mesh]->header->vertexNum * sizeof(MD3VertexCompressed);
[8416]489}
[8382]490
[8573]491
492
[8382]493}
494
495
496
497
498
499
500
Note: See TracBrowser for help on using the repository browser.