Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

bsp: md3 integrated to the resource manager

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