Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/heathaze/src/lib/graphics/importer/md3/md3_model.cc

Last change on this file was 9110, checked in by bensch, 18 years ago

orxonox/trunk: merged the Presentation back

File size: 22.4 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#include "md3_animation.h"
24
25#include "md3_animation_cfg.h"
26
27#include "material.h"
28#include "quaternion.h"
29
30#include "loading/resource_manager.h"
31
32#include "debug.h"
33
34namespace md3
35{
36
37  /**
38   * md3 model
39   */
40  MD3Model::MD3Model(std::string filename, float scaling)
41  {
42    this->autoAssemblePlayerModel(filename, scaling);
43
44    this->bDrawBones = false;
45    this->bDrawNormals = false;
46
47    this->time = 0.0f;
48
49    // set the animation
50    this->interpolate(this->md3Data, this->config->getAnimation("Dead 1"), MD3_ANIM_NEXT, true);
51  }
52
53
54
55  MD3Model::~MD3Model()
56  {
57//     delete this->tmpBoneFrame;
58//     delete [] this->tmpMesh;
59
60    ///TODO deleting mesh
61    ///TODO deleting matrices
62  }
63
64
65  /**
66   * auto assemples a player model
67   * @param filename is the name to the directory of the modelzzzzzz
68   */
69  void MD3Model::autoAssemblePlayerModel(std::string filename, float scaling)
70  {
71    // loading the config file
72    std::string cfgName(filename + "/animation.cfg");
73    this->config = (MD3AnimationCfg*)ResourceManager::getInstance()->load(cfgName, MD3_CONFIG, RP_GAME);
74
75    //first load the torso or the upper part
76    std::string nameUpper(filename + "/upper.md3");
77    if( (this->md3Data = (MD3Data*)ResourceManager::getInstance()->load(nameUpper, MD3, RP_GAME, nameUpper, scaling)) == NULL)
78    {
79      std::string nameTorso(filename + "/torso.md3");
80      this->md3Data = (MD3Data*)ResourceManager::getInstance()->load(nameTorso, MD3, RP_GAME, nameTorso, scaling);
81    }
82
83    if( this->md3Data == NULL)
84    {
85      PRINTF(1)("Problems loading the MD3Model. Abording\n");
86      return;
87    }
88
89    // load lower
90    std::string nameLower(filename + "/lower.md3");
91    MD3Data* lower = (MD3Data*)ResourceManager::getInstance()->load(nameLower, MD3, RP_GAME, nameLower, scaling);
92    if( lower != NULL)
93    {
94      int tag = this->md3Data->getTagIndexByName("tag_lower");
95      PRINTF(0)("Loaded the %s model on index %i\n", nameLower.c_str(), tag);
96      if( tag >= 0)
97       this->md3Data->addLinkedModel(tag, lower);
98      else
99        PRINTF(0)("Could not add %s\n", nameLower.c_str());
100
101    }
102
103
104    // load head
105    std::string nameHead(filename + "/head.md3");
106    MD3Data* head = (MD3Data*)ResourceManager::getInstance()->load(nameHead, MD3, RP_GAME, nameLower, scaling);
107    if( head != NULL)
108    {
109      int tag = this->md3Data->getTagIndexByName("tag_head");
110      PRINTF(0)("Loaded the %s model on index %i\n", nameHead.c_str(), tag);
111      if( tag >= 0)
112        this->md3Data->addLinkedModel(tag, head);
113      else
114        PRINTF(0)("Could not add %s\n", nameHead.c_str());
115    }
116
117  }
118
119
120
121  /**
122   * tick float
123   * @param time: time elapsed
124   */
125  void MD3Model::tick(float time)
126  {
127    if(this->md3Data == NULL)
128      return;
129
130    this->visit(this->md3Data, time);
131
132    this->tick(time, this->md3Data);
133  }
134
135
136  /**
137   * tick each data
138   */
139  void MD3Model::tick(float time, MD3Data* data)
140  {
141    // draw the bones if needed#
142    if( this->bDrawBones)
143    {
144      // get bone frame, interpolate if necessary
145      if( data->animationState.interpolationFraction != 0.0 &&
146          data->animationState.currentFrame != data->animationState.nextFrame)
147      {
148        //interpolate bone frame
149        data->tmpBoneFrame = this->interpolateBoneFrame(data, data->boneFrames[data->animationState.currentFrame],
150                                                        data->boneFrames[data->animationState.nextFrame],
151                                                        data->animationState.interpolationFraction);
152      }
153      else
154      {
155        data->tmpBoneFrame = data->boneFrames[data->animationState.currentFrame];
156      }
157    }
158
159
160    //draw all meshes of current frame of this model
161    for( int i = 0;  i < data->header->meshNum; i++)
162    {
163      MD3Mesh* mesh = data->meshes[i];
164
165      //interpolate mesh frame between the 2 current mesh frames
166      if( data->header->boneFrameNum > 1)
167        this->interpolateMeshFrame( data,
168                                    mesh->meshFrames[data->animationState.currentFrame],
169                                    mesh->meshFrames[data->animationState.nextFrame],
170                                    data->animationState.interpolationFraction, mesh, i);
171      else
172        this->interpolateMeshFrame( data,
173                                    mesh->meshFrames[data->animationState.currentFrame],
174                                    mesh->meshFrames[data->animationState.currentFrame],
175                                    0.0f, mesh, i);
176
177      // draw vertex normals if needed
178      if( this->bDrawNormals)
179      {
180        // get vertex normals, interpolate if necessary
181        if( data->animationState.interpolationFraction != 0.0 &&
182            data->animationState.currentFrame != data->animationState.nextFrame)
183        {
184          //interpolate vertex normals
185          this->interpolateVertexNormals(data,
186                                         mesh->normals[data->animationState.currentFrame],
187                                         mesh->normals[data->animationState.nextFrame],
188                                         data->animationState.interpolationFraction, mesh, i);
189        }
190      }
191    }
192
193
194    // draw all models linked to this model
195    std::map<int, MD3Data*>::iterator it = data->sortedMap.begin();
196    int i = 0;
197    while( it != data->sortedMap.end())
198    {
199      MD3Data* child = it->second;
200
201      //build transformation array m from matrix, interpolate if necessary
202
203      MD3Tag* currFrameTag = data->boneFrames[data->animationState.currentFrame]->tags[child->parentTagIndex];
204
205      if( data->animationState.interpolationFraction != 0.0 &&
206          data->animationState.currentFrame != data->animationState.nextFrame)
207      {
208        //we need to interpolate
209        MD3Tag* nextFrameTag = data->boneFrames[data->animationState.nextFrame]->tags[child->parentTagIndex];
210        this->interpolateTransformation(child, currFrameTag, nextFrameTag, data->animationState.interpolationFraction, i);
211      }
212      else
213      {
214        //no interpolation needed, stay with last transformation
215        //OpenGL matrix is in column-major order
216        data->tmpMatrix[i][0] = currFrameTag->matrix[0][0];
217        data->tmpMatrix[i][1] = currFrameTag->matrix[1][0];
218        data->tmpMatrix[i][2] = currFrameTag->matrix[2][0];
219        data->tmpMatrix[i][3] = 0.0f;
220        data->tmpMatrix[i][4] = currFrameTag->matrix[0][1];
221        data->tmpMatrix[i][5] = currFrameTag->matrix[1][1];
222        data->tmpMatrix[i][6] = currFrameTag->matrix[2][1];
223        data->tmpMatrix[i][7] = 0.0f;
224        data->tmpMatrix[i][8] = currFrameTag->matrix[0][2];
225        data->tmpMatrix[i][9] = currFrameTag->matrix[1][2];
226        data->tmpMatrix[i][10]= currFrameTag->matrix[2][2];
227        data->tmpMatrix[i][11]= 0.0f;
228        data->tmpMatrix[i][12] = currFrameTag->position.x;
229        data->tmpMatrix[i][13] = currFrameTag->position.y;
230        data->tmpMatrix[i][14] = currFrameTag->position.z;
231        data->tmpMatrix[i][15] = 1.0f;
232      }
233
234      // switch to child coord system
235
236      // and tick child
237      this->tick(time, child);
238
239      i++;
240      it++;
241    }
242  }
243
244
245  /**
246   * this draws the md3 model
247   */
248  void MD3Model::draw() const
249  {
250    //draw current bone frame
251    this->draw(this->md3Data);
252  }
253
254
255  /**
256   * draw the md3model
257   * @param data: the data to be drawn
258   */
259  void MD3Model::draw(MD3Data* data) const
260  {
261
262    // draw the bones if needed
263    if( this->bDrawBones)
264    {
265      // get bone frame, interpolate if necessary
266      if( data->animationState.interpolationFraction != 0.0 &&
267          data->animationState.currentFrame != data->animationState.nextFrame) {
268        //interpolate bone frame
269        this->drawBoneFrame(data->tmpBoneFrame);
270      }
271      else {
272        //stick with current bone frame
273        this->drawBoneFrame(data->boneFrames[data->animationState.currentFrame]);
274      }
275    }
276
277
278    //draw all meshes of current frame of this model
279    for( int i = 0;  i < data->header->meshNum; i++)
280    {
281      MD3Mesh* mesh = data->meshes[i];
282      sVec3D* frame = data->tmpMesh[i];
283
284      if( mesh->header->textureNum > 0 && &mesh->material[0] != NULL)
285        mesh->material[0].select();
286
287      this->drawMesh(mesh, frame);
288
289      // draw vertex normals if needed
290      if( this->bDrawNormals)
291      {
292        // get vertex normals, interpolate if necessary
293        if( data->animationState.interpolationFraction != 0.0 &&
294            data->animationState.currentFrame != data->animationState.nextFrame)
295        {
296          //interpolate vertex normals
297          this->drawVertexNormals(frame, data->tmpNormal[i]);
298        }
299        else {
300          //stick with current vertex normals
301          this->drawVertexNormals(frame, mesh->normals[data->animationState.currentFrame]);
302        }
303      }
304    }
305
306
307    // draw all models linked to this model
308    int i = 0;
309    std::map<int, MD3Data*>::iterator it = data->sortedMap.begin();
310    while( it != data->sortedMap.end())
311    {
312      MD3Data* child = it->second;
313
314      //switch to child coord system
315      glPushMatrix();
316      glMultMatrixf(data->tmpMatrix[i]);
317
318      // and draw child
319      this->draw(child);
320
321      glPopMatrix();
322
323      i++;
324      it++;
325    }
326
327  }
328
329
330  /**
331   * draws the mesh
332   */
333  void MD3Model::drawMesh(MD3Mesh* mesh, sVec3D* frame) const
334  {
335    Vector tmpVec1, tmpVec2;
336
337    glColor3f(1.0f, 1.0f, 1.0f);
338    glBegin( GL_TRIANGLES);
339
340    // upload all triangles in the frame to OpenGL
341    for( int t = 0; t < mesh->header->triangleNum; t++)
342    {
343      // calc normal vector
344      tmpVec1.x = frame[mesh->triangles[t].vertexOffset[1]][0] - frame[mesh->triangles[t].vertexOffset[0]][0];
345      tmpVec1.y = frame[mesh->triangles[t].vertexOffset[1]][1] - frame[mesh->triangles[t].vertexOffset[0]][1];
346      tmpVec1.z = frame[mesh->triangles[t].vertexOffset[1]][2] - frame[mesh->triangles[t].vertexOffset[0]][2];
347
348      tmpVec2.x = frame[mesh->triangles[t].vertexOffset[2]][0] - frame[mesh->triangles[t].vertexOffset[0]][0];
349      tmpVec2.y = frame[mesh->triangles[t].vertexOffset[2]][1] - frame[mesh->triangles[t].vertexOffset[0]][1];
350      tmpVec2.z = frame[mesh->triangles[t].vertexOffset[2]][2] - frame[mesh->triangles[t].vertexOffset[0]][2];
351
352      Vector normal = tmpVec1.cross(tmpVec2);
353      normal.normalize();
354
355//       PRINTF(0)("normal: %f, %f, %f\n", normal.x, normal.y, normal.z);
356
357      glNormal3f(normal.x, normal.y, normal.z);
358      glTexCoord2fv( mesh->texVecs[mesh->triangles[t].vertexOffset[0]].textureCoord);
359      glVertex3f( frame[mesh->triangles[t].vertexOffset[0]][0],
360                  frame[mesh->triangles[t].vertexOffset[0]][2],
361                  frame[mesh->triangles[t].vertexOffset[0]][1]);
362
363      glNormal3f(normal.x, normal.y, normal.z);
364      glTexCoord2fv( mesh->texVecs[mesh->triangles[t].vertexOffset[1]].textureCoord);
365      glVertex3f( frame[mesh->triangles[t].vertexOffset[1]][0],
366                  frame[mesh->triangles[t].vertexOffset[1]][2],
367                  frame[mesh->triangles[t].vertexOffset[1]][1]);
368
369      glNormal3f(normal.x, normal.y, normal.z);
370      glTexCoord2fv( mesh->texVecs[mesh->triangles[t].vertexOffset[2]].textureCoord);
371      glVertex3f( frame[mesh->triangles[t].vertexOffset[2]][0],
372                  frame[mesh->triangles[t].vertexOffset[2]][2],
373                  frame[mesh->triangles[t].vertexOffset[2]][1]);
374    }
375    glEnd();
376  }
377
378
379  /**
380   *  drawo vertex normals
381   */
382  void MD3Model::drawVertexNormals(sVec3D* frame, MD3Normal* normals) const
383  {}
384
385
386  /**
387   * draw bone frame
388   */
389  void MD3Model::drawBoneFrame(MD3BoneFrame* frame) const
390  {
391    float x1 = frame->mins.x;
392    float y1 = frame->mins.y;
393    float z1 = frame->mins.z;
394    float x2 = frame->maxs.x;
395    float y2 = frame->maxs.y;
396    float z2 = frame->maxs.z;
397
398    glPushAttrib(GL_TEXTURE_2D);
399    glPushAttrib(GL_LIGHTING);
400
401    glColor3f(1.0f,0.0f,0.0f);
402    glPointSize(6.0f);
403
404    glBegin(GL_POINTS);
405    glVertex3f(frame->position.x, frame->position.y, frame->position.z);
406    glEnd();
407    glPointSize(1.0f);
408
409    glColor3f(0.0f,1.0f,0.0f);
410    glBegin(GL_LINE_LOOP);
411    glVertex3f(x1,y1,z1);
412    glVertex3f(x1,y1,z2);
413    glVertex3f(x1,y2,z2);
414    glVertex3f(x1,y2,z1);
415    glEnd();
416
417    glBegin(GL_LINE_LOOP);
418    glVertex3f(x2,y2,z2);
419    glVertex3f(x2,y1,z2);
420    glVertex3f(x2,y1,z1);
421    glVertex3f(x2,y2,z1);
422    glEnd();
423
424    glBegin(GL_LINES);
425    glVertex3f(x1,y1,z1);
426    glVertex3f(x2,y1,z1);
427
428    glVertex3f(x1,y1,z2);
429    glVertex3f(x2,y1,z2);
430
431    glVertex3f(x1,y2,z2);
432    glVertex3f(x2,y2,z2);
433
434    glVertex3f(x1,y2,z1);
435    glVertex3f(x2,y2,z1);
436    glEnd();
437
438     glPopAttrib();
439     glPopAttrib();
440  }
441
442
443  /**
444   *  interpolate bone frame
445   * @param currBoneFrame Start bone frame.
446   * @param nextBoneFrame End bone frame.
447   * @param frac Interpolation fraction, in [0,1].
448   */
449  MD3BoneFrame* MD3Model::interpolateBoneFrame(MD3Data* data, MD3BoneFrame* currBoneFrame, MD3BoneFrame* nextBoneFrame, float frac)
450  {
451    data->tmpBoneFrame->mins.x      = (1.0f - frac) * currBoneFrame->mins.x       + frac * nextBoneFrame->mins.x;
452    data->tmpBoneFrame->maxs.x      = (1.0f - frac) * currBoneFrame->maxs.x       + frac * nextBoneFrame->maxs.x;
453    data->tmpBoneFrame->position.= (1.0f - frac) * currBoneFrame->position.x   + frac * nextBoneFrame->position.x;
454    data->tmpBoneFrame->mins.y      = (1.0f - frac) * currBoneFrame->mins.y       + frac * nextBoneFrame->mins.y;
455    data->tmpBoneFrame->maxs.y      = (1.0f - frac) * currBoneFrame->maxs.y       + frac * nextBoneFrame->maxs.y;
456    data->tmpBoneFrame->position.= (1.0f - frac) * currBoneFrame->position.y   + frac * nextBoneFrame->position.y;
457    data->tmpBoneFrame->mins.z      = (1.0f - frac) * currBoneFrame->mins.z       + frac * nextBoneFrame->mins.z;
458    data->tmpBoneFrame->maxs.z      = (1.0f - frac) * currBoneFrame->maxs.z       + frac * nextBoneFrame->maxs.z;
459    data->tmpBoneFrame->position.= (1.0f - frac) * currBoneFrame->position.z   + frac * nextBoneFrame->position.z;
460
461    return data->tmpBoneFrame;
462  }
463
464
465
466  /**
467   * interpolate mesh frame
468   */
469  sVec3D* MD3Model::interpolateMeshFrame(MD3Data* data, sVec3D* currMeshFrame, sVec3D* nextMeshFrame, float frac, MD3Mesh* mesh, int i)
470  {
471    int vertexNum = mesh->header->vertexNum;
472
473    if( /*frac == 0.0f*/ true)
474    {
475      // just copy the vertices
476      for( int t = 0; t < vertexNum; t++)
477      {
478        data->tmpMesh[i][t][0]  = currMeshFrame[t][0];
479        data->tmpMesh[i][t][1]  = currMeshFrame[t][1];
480        data->tmpMesh[i][t][2]  = currMeshFrame[t][2];
481      }
482    }
483    else
484    {
485      // calc interpolated vertices
486      for( int t = 0; t < vertexNum; t++)
487      {
488        data->tmpMesh[i][t][0]  = (1.0f - frac)   * currMeshFrame[t][0]  + frac * nextMeshFrame[t][0];
489        data->tmpMesh[i][t][1]  = (1.0f - frac)   * currMeshFrame[t][1]  + frac * nextMeshFrame[t][1];
490        data->tmpMesh[i][t][2]  = (1.0f - frac)   * currMeshFrame[t][2]  + frac * nextMeshFrame[t][2];
491      }
492    }
493
494    return data->tmpMesh[i];
495  }
496
497
498  /**
499   * interpolate vertex normal
500   */
501  MD3Normal* MD3Model::interpolateVertexNormals(MD3Data* data, MD3Normal* currNormals, MD3Normal* nextNormals, float frac, MD3Mesh* mesh, int i)
502  {
503    for( int j = 0; j < mesh->header->vertexNum; j++)
504    {
505      data->tmpNormal[i][j].vertexNormal[0] = (int)((1.0f - frac) * currNormals[j].vertexNormal[0] + frac * nextNormals[j].vertexNormal[0]);
506      data->tmpNormal[i][j].vertexNormal[1] = (int)((1.0f - frac) * currNormals[j].vertexNormal[1] + frac * nextNormals[j].vertexNormal[1]);
507    }
508
509    return data->tmpNormal[i];
510  }
511
512
513  /**
514   * interpolate transformation
515   */
516  float* MD3Model::interpolateTransformation(MD3Data* data, MD3Tag* currFrameTag, MD3Tag* nextFrameTag, float frac, int i)
517  {
518    // interpolate position
519    Vector interpolatedPosition = currFrameTag->position * (1.0f - frac) + nextFrameTag->position * frac;
520
521
522    // interpolate rotation matrix
523    float  currRot[4][4];
524    float  nextRot[4][4];
525    float  interpolatedMatrix[4][4];
526
527    /// TODO CHANGED BY BENSCH TO MATCH NEW QUATERNION FUNCTIONALITY
528    Quaternion currQuat; currQuat.from3x3(currFrameTag->matrix); currQuat.matrix(currRot);
529    Quaternion nextQuat; nextQuat.from3x3(nextFrameTag->matrix); nextQuat.matrix(nextRot);
530
531    Quaternion interpolatedQuat = Quaternion::quatSlerp(currQuat, nextQuat, frac); interpolatedQuat.matrix(interpolatedMatrix);
532
533    // quaternion code is column based, so use transposed matrix when spitting out to gl
534    data->tmpMatrix[i][0] = interpolatedMatrix[0][0];
535    data->tmpMatrix[i][4] = interpolatedMatrix[1][0];
536    data->tmpMatrix[i][8] = interpolatedMatrix[2][0];
537    data->tmpMatrix[i][12] = interpolatedPosition.x;
538    data->tmpMatrix[i][1] = interpolatedMatrix[0][1];
539    data->tmpMatrix[i][5] = interpolatedMatrix[1][1];
540    data->tmpMatrix[i][9] = interpolatedMatrix[2][1];
541    data->tmpMatrix[i][13] = interpolatedPosition.y;
542    data->tmpMatrix[i][2] = interpolatedMatrix[0][2];
543    data->tmpMatrix[i][6] = interpolatedMatrix[1][2];
544    data->tmpMatrix[i][10]= interpolatedMatrix[2][2];
545    data->tmpMatrix[i][14] = interpolatedPosition.z;
546    data->tmpMatrix[i][3] = 0.0f;
547    data->tmpMatrix[i][7] = 0.0f;
548    data->tmpMatrix[i][11]= 0.0f;
549    data->tmpMatrix[i][15] = 1.0f;
550
551    return data->tmpMatrix[i];
552
553  }
554
555
556
557  /**
558   * visit the model
559   */
560  void MD3Model::visit(MD3Data* data, float time)
561  {
562    if ( (data->filename.find("lower") == std::string::npos &&
563          (data->animation->type == LEGS || data->animation->type == BOTH)) // this is the LEGS model and the animation is applicable
564          ||
565          (data->filename.find("upper") == std::string::npos &&
566          (data->animation->type == TORSO || data->animation->type == BOTH)) // this is the TORSO model and the animation is applicable
567          ||
568          data->animation->type == ALL // the animation is allways applicable
569       )
570      this->doOp(data, time);
571
572    // visit children
573//     std::map<int, MD3Data*>::iterator it = data->sortedMap.begin();
574//     while( it != data->sortedMap.end())
575//     {
576//       this->visit(it->second);
577//       it++;
578//     }
579  }
580
581
582  /**
583   * Create a new visitor to apply an animation operation (NEXT, REWIND, ...)
584   * to a MD3 model. The operation is executed in the context of the specified
585   * animation.
586   *
587   * @param anim The animation that provides the context for the operation.
588   * @param op The operation to apply.
589   * @param interpolate Should interpolation be done?
590   */
591  void MD3Model::interpolate(MD3Data* data, MD3Animation* anim, int op, bool bInterpolate)
592  {
593     data->animation = anim;
594     if( op == MD3_ANIM_NEXT || op == MD3_ANIM_PREVIOUS || op == MD3_ANIM_REWIND)
595      data->op = op;
596
597     data->bInterpolate = bInterpolate;
598  }
599
600
601  /**
602   * calc next frame number
603   */
604  int MD3Model::next(MD3Data* data, int nr)
605  {
606    if( nr < (data->upperBound - 1))
607      return nr + 1;
608    else
609    { //rewind needed
610      if( data->animation->numFrames < 0)
611        return data->animation->first;
612      else {
613        nr = (data->animation->numLoopFrames != 0)?(data->animation->numFrames - data->animation->numLoopFrames):0;
614        return data->animation->first + nr;
615      }
616    }
617  }
618
619
620  /**
621   * calc prev frame number
622   */
623  int MD3Model::prev(MD3Data* data, int nr)
624  {
625    if( nr == data->animation->first)
626      return data->upperBound - 1;
627    else
628      return nr - 1;
629  }
630
631
632  /**
633   * apply the specified operation to the animation state data members of the model
634   * taking the specified animation into account
635   *
636   * @param data: the data of the model
637   */
638  void MD3Model::doOp(MD3Data* data, float time)
639  {
640    // animation to be applied could have illegal data with respect to this model,
641    // ignore anim in this case
642
643    if( data->animation->first >= data->animation->numFrames || data->animation->first < 0)
644    {
645      PRINTF(0)("MD3: this animation type seems to be invalid, no animation calculated\n");
646      return;
647    }
648
649
650    //calc upper bound for animation frames in this model
651    if( data->animation->numFrames < 0)
652      data->upperBound = data->header->boneFrameNum; //use all available frames
653    else
654    {
655      if( data->header->boneFrameNum < (data->animation->first + data->animation->numFrames))
656        data->upperBound = data->header->boneFrameNum;
657      else
658        data->upperBound = (data->animation->first + data->animation->numFrames);
659    }
660
661
662    switch( data->op) {
663
664      case MD3_ANIM_NEXT:
665        if( data->bInterpolate)
666        {
667          // keyframe interpolation animation
668          data->animationState.interpolationFraction += time * data->animation->fps;
669
670          if( data->animationState.interpolationFraction >= 1.0f)
671          {
672            data->animationState.currentFrame = data->animationState.nextFrame;
673            data->animationState.nextFrame = next(data, data->animationState.nextFrame);
674            data->animationState.interpolationFraction = 0.0f;
675          }
676        }
677        else
678        {
679          // only keyframe animation
680          this->time += time * data->animation->fps;
681          if( this->time > 1.0f)
682          {
683            data->animationState.currentFrame = data->animationState.nextFrame;
684            data->animationState.nextFrame = next(data, data->animationState.nextFrame);
685            this->time = 0.0f;
686          }
687        }
688        break;
689
690      case MD3_ANIM_PREVIOUS:
691        if( data->bInterpolate)
692        {
693          data->animationState.interpolationFraction -= time / data->animation->fps;
694          if( data->animationState.interpolationFraction < 0.0f)
695          {
696            data->animationState.nextFrame = data->animationState.currentFrame;
697            data->animationState.currentFrame = prev(data, data->animationState.currentFrame);
698            data->animationState.interpolationFraction = 0.8f;
699          }
700        }
701        else
702        {
703          data->animationState.nextFrame = data->animationState.currentFrame;
704          data->animationState.currentFrame = prev(data, data->animationState.currentFrame);
705        }
706        break;
707
708      case MD3_ANIM_REWIND:
709        data->animationState.currentFrame = data->animation->first;
710        data->animationState.nextFrame = next(data, data->animationState.currentFrame);
711        data->animationState.interpolationFraction = 0.0f;
712        break;
713    }
714
715  }
716
717
718}
Note: See TracBrowser for help on using the repository browser.