Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/bsp_model/src/lib/graphics/importer/md3/md3_model.cc @ 8597

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

bsp: md3 child models work started

File size: 17.8 KB
Line 
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_model.h"
18
19#include "md3_data.h"
20#include "md3_mesh.h"
21#include "md3_tag.h"
22#include "md3_bone_frame.h"
23
24#include "md3_animation_cfg.h"
25
26#include "material.h"
27#include "quaternion.h"
28
29#include "loading/resource_manager.h"
30
31#include "debug.h"
32
33namespace md3
34{
35
36  /**
37   * md3 model
38   */
39  MD3Model::MD3Model(std::string filename, float scaling)
40  {
41    this->autoAssemblePlayerModel(filename, scaling);
42
43
44    // create the temporary data to work with (interpolation data)
45    this->tmpBoneFrame = new MD3BoneFrame();
46
47    this->tmpMesh = new sVec3D*[this->md3Data->header->meshNum];
48    for( int i = 0; i < this->md3Data->header->meshNum; i++)
49      this->tmpMesh[i] = new sVec3D[this->md3Data->meshes[i]->header->vertexNum];
50
51    this->tmpNormal = new MD3Normal*[this->md3Data->header->meshNum];
52    for( int i = 0; i < this->md3Data->header->meshNum; i++)
53      this->tmpNormal[i] = new MD3Normal[this->md3Data->meshes[i]->header->vertexNum];
54
55    this->tmpMatrix = new float*[this->md3Data->header->tagNum];
56    for( int i = 0; i < this->md3Data->header->tagNum; i++)
57      this->tmpMatrix[i] = new float[16];
58
59    this->bDrawBones = false;
60    this->bDrawNormals = false;
61  }
62
63
64
65  MD3Model::~MD3Model()
66  {
67    delete this->tmpBoneFrame;
68//     delete [] this->tmpMesh;
69
70    ///TODO deleting mesh
71    ///TODO deleting matrices
72  }
73
74
75  /**
76   * auto assemples a player model
77   * @param filename is the name to the directory of the modelzzzzzz
78   */
79  void MD3Model::autoAssemblePlayerModel(std::string filename, float scaling)
80  {
81    // loading the config file
82    std::string cfgName(filename + "/animation.cfg");
83    this->config = (MD3AnimationCfg*)ResourceManager::getInstance()->load(cfgName, MD3_CONFIG, RP_GAME);
84
85    //first load the torso or the upper part
86    std::string nameUpper(filename + "/upper.md3");
87    if( (this->md3Data = (MD3Data*)ResourceManager::getInstance()->load(nameUpper, MD3, RP_GAME, nameUpper, scaling)) == NULL)
88    {
89      std::string nameTorso(filename + "/torso.md3");
90      this->md3Data = (MD3Data*)ResourceManager::getInstance()->load(nameTorso, MD3, RP_GAME, nameTorso, scaling);
91    }
92
93    if( this->md3Data == NULL)
94    {
95      PRINTF(1)("Problems loading the MD3Model. Abording\n");
96      return;
97    }
98
99    // load lower
100    std::string nameLower(filename + "/lower.md3");
101    MD3Data* lower = (MD3Data*)ResourceManager::getInstance()->load(nameLower, MD3, RP_GAME, nameLower, scaling);
102    if( lower != NULL)
103    {
104      int tag = this->md3Data->getTagIndexByName("tag_lower");
105      PRINTF(0)("Loaded the %s model on index %i\n", nameLower.c_str(), tag);
106      if( tag >= 0)
107       this->md3Data->addLinkedModel(tag, lower);
108      else
109        PRINTF(0)("Could not add %s\n", nameLower.c_str());
110    }
111
112
113    // load head
114    std::string nameHead(filename + "/head.md3");
115    MD3Data* head = (MD3Data*)ResourceManager::getInstance()->load(nameHead, MD3, RP_GAME, nameLower, scaling);
116    if( head != NULL)
117    {
118      int tag = this->md3Data->getTagIndexByName("tag_head");
119      PRINTF(0)("Loaded the %s model on index %i\n", nameHead.c_str(), tag);
120      if( tag >= 0)
121        this->md3Data->addLinkedModel(tag, head);
122      else
123        PRINTF(0)("Could not add %s\n", nameHead.c_str());
124    }
125
126  }
127
128
129
130  /**
131   * tick float
132   * @param time: time elapsed
133   */
134  void MD3Model::tick(float time)
135  {
136
137    this->tick(time, this->md3Data);
138  }
139
140
141  /**
142   * tick each data
143   */
144  void MD3Model::tick(float time, MD3Data* data)
145  {
146    // draw the bones if needed
147    if( this->bDrawBones)
148    {
149      // get bone frame, interpolate if necessary
150      if( data->animationState.interpolationFraction != 0.0 &&
151          data->animationState.currentFrame != data->animationState.nextFrame)
152      {
153        //interpolate bone frame
154        this->tmpBoneFrame = this->interpolateBoneFrame(data->boneFrames[data->animationState.currentFrame],
155                                                        data->boneFrames[data->animationState.nextFrame],
156                                                        data->animationState.interpolationFraction);
157      }
158      else
159      {
160        this->tmpBoneFrame = data->boneFrames[data->animationState.currentFrame];
161      }
162    }
163
164    //draw all meshes of current frame of this model
165    for( int i = 0;  i < data->header->meshNum; i++)
166    {
167      MD3Mesh* mesh = data->meshes[i];
168
169      // get mesh frame, do interpolation if necessary
170      sVec3D* frame;
171      if( data->animationState.interpolationFraction != 0.0 &&
172          data->animationState.currentFrame != data->animationState.nextFrame)
173      {
174        //interpolate mesh frame between the 2 current mesh frames
175        frame = this->interpolateMeshFrame( data->meshes[data->animationState.currentFrame]->meshFrames,
176                                            data->meshes[data->animationState.nextFrame]->meshFrames,
177                                            data->animationState.interpolationFraction, mesh, i);
178      }
179      else
180      {
181        //no interpolation needed, just draw current frame
182        frame = &mesh->meshFrames[data->animationState.currentFrame];
183      }
184      this->tmpMesh[i] = frame;
185
186      // draw vertex normals if needed
187      if( this->bDrawNormals)
188      {
189        // get vertex normals, interpolate if necessary
190        if( data->animationState.interpolationFraction != 0.0 &&
191            data->animationState.currentFrame != data->animationState.nextFrame)
192        {
193          //interpolate vertex normals
194          this->interpolateVertexNormals(&mesh->normals[data->animationState.currentFrame],
195                                         &mesh->normals[data->animationState.nextFrame],
196                                         data->animationState.interpolationFraction, mesh, i);
197        }
198      }
199    }
200
201
202    // draw all models linked to this model
203    std::map<int, MD3Data*>::iterator it = data->sortedMap.begin();
204    int i = 0;
205    while( it != data->sortedMap.end())
206    {
207      MD3Data* child = it->second;
208
209      //build transformation array m from matrix, interpolate if necessary
210
211      MD3Tag* currFrameTag = data->boneFrames[data->animationState.currentFrame]->tags[child->parentTagIndex];
212
213      if( data->animationState.interpolationFraction != 0.0 &&
214          data->animationState.currentFrame != data->animationState.nextFrame) {
215        //we need to interpolate
216        MD3Tag* nextFrameTag = data->boneFrames[data->animationState.nextFrame]->tags[child->parentTagIndex];
217        this->tmpMatrix[i] = this->interpolateTransformation(currFrameTag, nextFrameTag, data->animationState.interpolationFraction, i);
218      }
219      else
220      {
221        //no interpolation needed, stay with last transformation
222        //OpenGL matrix is in column-major order
223        this->tmpMatrix[i][0] = currFrameTag->matrix[0][0];
224        this->tmpMatrix[i][1] = currFrameTag->matrix[1][0];
225        this->tmpMatrix[i][2] = currFrameTag->matrix[2][0];
226        this->tmpMatrix[i][3] = 0.0f;
227        this->tmpMatrix[i][4] = currFrameTag->matrix[0][1];
228        this->tmpMatrix[i][5] = currFrameTag->matrix[1][1];
229        this->tmpMatrix[i][6] = currFrameTag->matrix[2][1];
230        this->tmpMatrix[i][7] = 0.0f;
231        this->tmpMatrix[i][8] = currFrameTag->matrix[0][2];
232        this->tmpMatrix[i][9] = currFrameTag->matrix[1][2];
233        this->tmpMatrix[i][10]= currFrameTag->matrix[2][2];
234        this->tmpMatrix[i][11]= 0.0f;
235        this->tmpMatrix[i][12] = currFrameTag->position.x;
236        this->tmpMatrix[i][13] = currFrameTag->position.y;
237        this->tmpMatrix[i][14] = currFrameTag->position.z;
238        this->tmpMatrix[i][15] = 1.0f;
239      }
240
241      // switch to child coord system
242
243      // and tick child
244      this->tick(time, child);
245
246      i++;
247      it++;
248    }
249  }
250
251
252  /**
253   * this draws the md3 model
254   */
255  void MD3Model::draw() const
256  {
257    //draw current bone frame
258    this->draw(this->md3Data);
259  }
260
261
262  /**
263   * draw the md3model
264   * @param data: the data to be drawn
265   */
266  void MD3Model::draw(MD3Data* data) const
267  {
268
269    // draw the bones if needed
270    if( this->bDrawBones)
271    {
272      // get bone frame, interpolate if necessary
273      if( data->animationState.interpolationFraction != 0.0 &&
274          data->animationState.currentFrame != data->animationState.nextFrame) {
275        //interpolate bone frame
276        this->drawBoneFrame(this->tmpBoneFrame);
277      }
278      else {
279        //stick with current bone frame
280        this->drawBoneFrame(data->boneFrames[data->animationState.currentFrame]);
281      }
282    }
283
284
285    //draw all meshes of current frame of this model
286    for( int i = 0;  i < data->header->meshNum; i++)
287    {
288      MD3Mesh* mesh = data->meshes[i];
289
290//       gl.glBlendFunc(mesh.GLSrcBlendFunc, mesh.GLDstBlendFunc);
291//       gl.glDepthMask(mesh.GLDepthMask);
292
293      if( mesh->header->textureNum > 0 && &mesh->material[0] != NULL)
294        mesh->material[0].select();
295
296      // get mesh frame, do interpolation if necessary
297      sVec3D* frame = this->tmpMesh[i];
298
299      this->drawMesh(mesh, frame);
300
301
302      // draw vertex normals if needed
303      if( this->bDrawNormals) {
304        // get vertex normals, interpolate if necessary
305        if( data->animationState.interpolationFraction != 0.0 &&
306            data->animationState.currentFrame != data->animationState.nextFrame) {
307          //interpolate vertex normals
308          this->drawVertexNormals(frame, this->tmpNormal[i]);
309            }
310            else {
311          //stick with current vertex normals
312              this->drawVertexNormals(frame, &mesh->normals[data->animationState.currentFrame]);
313            }
314      }
315    }
316
317
318    // draw all models linked to this model
319    int i = 0;
320    std::map<int, MD3Data*>::iterator it = data->sortedMap.begin();
321    while( it != data->sortedMap.end())
322    {
323      MD3Data* child = it->second;
324
325      //switch to child coord system
326      glPushMatrix();
327      glMultMatrixf(this->tmpMatrix[i]);
328
329      // and draw child
330      this->draw(child);
331
332      glPopMatrix();
333      i++;
334      it++;
335    }
336  }
337
338
339  /**
340   * draws the mesh
341   */
342  void MD3Model::drawMesh(MD3Mesh* mesh, sVec3D* frame) const
343  {
344    glColor3f(1.0f, 1.0f, 1.0f);
345
346    glBegin( GL_TRIANGLES);
347    glScalef( 0.7f , 0.7f, 0.7f );
348
349    Vector tmpVec1, tmpVec2;
350
351    // upload all triangles in the frame to OpenGL
352    for( int t = 0; t < mesh->header->triangleNum; t++)
353    {
354      // calc normal vector
355      tmpVec1.x = frame[mesh->triangles[t].vertexOffset[1]][0] - frame[mesh->triangles[t].vertexOffset[0]][0];
356      tmpVec1.y = frame[mesh->triangles[t].vertexOffset[1]][1] - frame[mesh->triangles[t].vertexOffset[0]][1];
357      tmpVec1.z = frame[mesh->triangles[t].vertexOffset[1]][2] - frame[mesh->triangles[t].vertexOffset[0]][2];
358
359      tmpVec2.x = frame[mesh->triangles[t].vertexOffset[2]][0] - frame[mesh->triangles[t].vertexOffset[0]][0];
360      tmpVec2.y = frame[mesh->triangles[t].vertexOffset[2]][1] - frame[mesh->triangles[t].vertexOffset[0]][1];
361      tmpVec2.z = frame[mesh->triangles[t].vertexOffset[2]][2] - frame[mesh->triangles[t].vertexOffset[0]][2];
362
363      Vector normal = tmpVec1.cross(tmpVec2);
364      normal.normalize();
365
366//       PRINTF(0)("normal: %f, %f, %f\n", normal.x, normal.y, normal.z);
367
368      glNormal3f(normal.x, normal.y, normal.z);
369      glTexCoord2fv( mesh->texVecs[mesh->triangles[t].vertexOffset[0]].textureCoord);
370      glVertex3f( frame[mesh->triangles[t].vertexOffset[0]][0],
371                  frame[mesh->triangles[t].vertexOffset[0]][2],
372                  frame[mesh->triangles[t].vertexOffset[0]][1]);
373
374      glNormal3f(normal.x, normal.y, normal.z);
375      glTexCoord2fv( mesh->texVecs[mesh->triangles[t].vertexOffset[1]].textureCoord);
376      glVertex3f( frame[mesh->triangles[t].vertexOffset[1]][0],
377                  frame[mesh->triangles[t].vertexOffset[1]][2],
378                  frame[mesh->triangles[t].vertexOffset[1]][1]);
379
380      glNormal3f(normal.x, normal.y, normal.z);
381      glTexCoord2fv( mesh->texVecs[mesh->triangles[t].vertexOffset[2]].textureCoord);
382      glVertex3f( frame[mesh->triangles[t].vertexOffset[2]][0],
383                  frame[mesh->triangles[t].vertexOffset[2]][2],
384                  frame[mesh->triangles[t].vertexOffset[2]][1]);
385    }
386    glEnd();
387
388  }
389
390
391  /**
392   *  drawo vertex normals
393   */
394  void MD3Model::drawVertexNormals(sVec3D* frame, MD3Normal* normals) const
395  {}
396
397
398  /**
399   * draw bone frame
400   */
401  void MD3Model::drawBoneFrame(MD3BoneFrame* frame) const
402  {
403    float x1 = frame->mins.x;
404    float y1 = frame->mins.y;
405    float z1 = frame->mins.z;
406    float x2 = frame->maxs.x;
407    float y2 = frame->maxs.y;
408    float z2 = frame->maxs.z;
409
410    glPushAttrib(GL_TEXTURE_2D);
411    glPushAttrib(GL_LIGHTING);
412
413    glColor3f(1.0f,0.0f,0.0f);
414    glPointSize(6.0f);
415
416    glBegin(GL_POINTS);
417    glVertex3f(frame->position.x, frame->position.y, frame->position.z);
418    glEnd();
419    glPointSize(1.0f);
420
421    glColor3f(0.0f,1.0f,0.0f);
422    glBegin(GL_LINE_LOOP);
423    glVertex3f(x1,y1,z1);
424    glVertex3f(x1,y1,z2);
425    glVertex3f(x1,y2,z2);
426    glVertex3f(x1,y2,z1);
427    glEnd();
428
429    glBegin(GL_LINE_LOOP);
430    glVertex3f(x2,y2,z2);
431    glVertex3f(x2,y1,z2);
432    glVertex3f(x2,y1,z1);
433    glVertex3f(x2,y2,z1);
434    glEnd();
435
436    glBegin(GL_LINES);
437    glVertex3f(x1,y1,z1);
438    glVertex3f(x2,y1,z1);
439
440    glVertex3f(x1,y1,z2);
441    glVertex3f(x2,y1,z2);
442
443    glVertex3f(x1,y2,z2);
444    glVertex3f(x2,y2,z2);
445
446    glVertex3f(x1,y2,z1);
447    glVertex3f(x2,y2,z1);
448    glEnd();
449
450     glPopAttrib();
451     glPopAttrib();
452  }
453
454
455  /**
456   *  interpolate bone frame
457   * @param currBoneFrame Start bone frame.
458   * @param nextBoneFrame End bone frame.
459   * @param frac Interpolation fraction, in [0,1].
460   */
461  MD3BoneFrame* MD3Model::interpolateBoneFrame(MD3BoneFrame* currBoneFrame, MD3BoneFrame* nextBoneFrame, float frac)
462  {
463    this->tmpBoneFrame->mins.x      = (1.0f - frac) * currBoneFrame->mins.x       + frac * nextBoneFrame->mins.x;
464    this->tmpBoneFrame->maxs.x      = (1.0f - frac) * currBoneFrame->maxs.x       + frac * nextBoneFrame->maxs.x;
465    this->tmpBoneFrame->position.= (1.0f - frac) * currBoneFrame->position.x   + frac * nextBoneFrame->position.x;
466    this->tmpBoneFrame->mins.y      = (1.0f - frac) * currBoneFrame->mins.y       + frac * nextBoneFrame->mins.y;
467    this->tmpBoneFrame->maxs.y      = (1.0f - frac) * currBoneFrame->maxs.y       + frac * nextBoneFrame->maxs.y;
468    this->tmpBoneFrame->position.= (1.0f - frac) * currBoneFrame->position.y   + frac * nextBoneFrame->position.y;
469    this->tmpBoneFrame->mins.z      = (1.0f - frac) * currBoneFrame->mins.z       + frac * nextBoneFrame->mins.z;
470    this->tmpBoneFrame->maxs.z      = (1.0f - frac) * currBoneFrame->maxs.z       + frac * nextBoneFrame->maxs.z;
471    this->tmpBoneFrame->position.= (1.0f - frac) * currBoneFrame->position.z   + frac * nextBoneFrame->position.z;
472
473    return this->tmpBoneFrame;
474  }
475
476
477
478  /**
479   * interpolate mesh frame
480   */
481  sVec3D* MD3Model::interpolateMeshFrame(sVec3D* currMeshFrame, sVec3D* nextMeshFrame, float frac, MD3Mesh* mesh, int i)
482  {
483    int vertexNum = mesh->header->vertexNum;
484
485    // calc interpolated vertices
486    for( int t = 0; t < vertexNum * 3.0f; t++)
487    {
488
489//       PRINTF(0)("tmp mesh: %f, %f, %f\n", this->tmpMesh[i][t][0], this->tmpMesh[i][t][1], this->tmpMesh[i][t][2]);
490
491      this->tmpMesh[i][t][0]  = (1.0f - frac)   * currMeshFrame[t][0]  + frac * nextMeshFrame[t][0];
492      this->tmpMesh[i][t][1]  = (1.0f - frac)   * currMeshFrame[t][1]  + frac * nextMeshFrame[t][1];
493      this->tmpMesh[i][t][2]  = (1.0f - frac)   * currMeshFrame[t][2]  + frac * nextMeshFrame[t][2];
494    }
495
496    return this->tmpMesh[i];
497  }
498
499
500  /**
501   * interpolate vertex normal
502   */
503  MD3Normal* MD3Model::interpolateVertexNormals(MD3Normal* currNormals, MD3Normal* nextNormals, float frac, MD3Mesh* mesh, int i)
504  {
505    for( int j = 0; j < mesh->header->vertexNum; j++)
506    {
507      this->tmpNormal[i][j].vertexNormal[0] = (int)((1.0f - frac) * currNormals[j].vertexNormal[0] + frac * nextNormals[j].vertexNormal[0]);
508      this->tmpNormal[i][j].vertexNormal[1] = (int)((1.0f - frac) * currNormals[j].vertexNormal[1] + frac * nextNormals[j].vertexNormal[1]);
509    }
510
511    return this->tmpNormal[i];
512  }
513
514
515  /**
516   * interpolate transformation
517   */
518  float* MD3Model::interpolateTransformation(MD3Tag* currFrameTag, MD3Tag* nextFrameTag, float frac, int i)
519  {
520    // interpolate position
521    Vector interpolatedPosition = currFrameTag->position * (1.0f - frac) + nextFrameTag->position * frac;
522
523
524    // interpolate rotation matrix
525    float  currRot[4][4];
526    float  nextRot[4][4];
527    float  interpolatedMatrix[4][4];
528
529    Quaternion currQuat(currFrameTag->matrix); currQuat.matrix(currRot);
530    Quaternion nextQuat(nextFrameTag->matrix); nextQuat.matrix(nextRot);
531
532    Quaternion interpolatedQuat = Quaternion::quatSlerp(currQuat, nextQuat, frac); interpolatedQuat.matrix(interpolatedMatrix);
533
534    // quaternion code is column based, so use transposed matrix when spitting out to gl
535    this->tmpMatrix[i][0] = interpolatedMatrix[0][0];
536    this->tmpMatrix[i][4] = interpolatedMatrix[1][0];
537    this->tmpMatrix[i][8] = interpolatedMatrix[2][0];
538    this->tmpMatrix[i][12] = interpolatedPosition.x;
539    this->tmpMatrix[i][1] = interpolatedMatrix[0][1];
540    this->tmpMatrix[i][5] = interpolatedMatrix[1][1];
541    this->tmpMatrix[i][9] = interpolatedMatrix[2][1];
542    this->tmpMatrix[i][13] = interpolatedPosition.y;
543    this->tmpMatrix[i][2] = interpolatedMatrix[0][2];
544    this->tmpMatrix[i][6] = interpolatedMatrix[1][2];
545    this->tmpMatrix[i][10]= interpolatedMatrix[2][2];
546    this->tmpMatrix[i][14] = interpolatedPosition.z;
547    this->tmpMatrix[i][3] = 0.0f;
548    this->tmpMatrix[i][7] = 0.0f;
549    this->tmpMatrix[i][11]= 0.0f;
550    this->tmpMatrix[i][15] = 1.0f;
551
552    return this->tmpMatrix[i];
553
554  }
555
556
557}
Note: See TracBrowser for help on using the repository browser.