Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/lib/graphics/importer/md2Model.cc @ 4261

Last change on this file since 4261 was 4246, checked in by bensch, 20 years ago

orxonox/trunk: md2_sloppy data-dir-fix

File size: 22.5 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 "md2Model.h"
18#include "material.h"
19
20#include "resource_manager.h"
21
22#include <fstream>
23#include <string>
24#include <vector>
25
26
27using namespace std;
28
29
30sVec3D MD2Model2::anorms[NUM_VERTEX_NORMALS] = {
31 #include "anorms.h"
32};
33
34float MD2Model2::anormsDots[SHADEDOT_QUANT][256] = {
35  #include "anormtab.h"
36};
37
38static float *shadeDots = MD2Model2::anormsDots[0];
39
40float md2Angle = 0.0f;
41
42
43sAnim MD2Model2::animationList[21] =
44  {
45 // begin, end, fps
46    {   0,  39,  9 },   // STAND
47    {  40,  45, 10 },   // RUN
48    {  46,  53, 10 },   // ATTACK
49    {  54,  57,  7 },   // PAIN_A
50    {  58,  61,  7 },   // PAIN_B
51    {  62,  65,  7 },   // PAIN_C
52    {  66,  71,  7 },   // JUMP
53    {  72,  83,  7 },   // FLIP
54    {  84,  94,  7 },   // SALUTE
55    {  95, 111, 10 },   // FALLBACK
56    { 112, 122,  7 },   // WAVE
57    { 123, 134,  6 },   // POINT
58    { 135, 153, 10 },   // CROUCH_STAND
59    { 154, 159,  7 },   // CROUCH_WALK
60    { 160, 168, 10 },   // CROUCH_ATTACK
61    { 196, 172,  7 },   // CROUCH_PAIN
62    { 173, 177,  5 },   // CROUCH_DEATH
63    { 178, 183,  7 },   // DEATH_FALLBACK
64    { 184, 189,  7 },   // DEATH_FALLFORWARD
65    { 190, 197,  7 },   // DEATH_FALLBACKSLOW
66    { 198, 198,  5 },   // BOOM
67  };
68
69
70/********************************************************************************
71 *   MD2MODEL                                                                   *
72 ********************************************************************************/
73
74/**
75   \brief standard constructor
76   
77   creates a new model
78*/
79MD2Model::MD2Model () 
80{
81  this->setClassName ("MD2Model");
82
83  MD2Loader* md2loader = new MD2Loader();
84  this->model = new t3DModel;
85  md2loader->importMD2(this->model, ResourceManager::getFullName("models/tris.md2"));
86  delete md2loader;
87}
88
89
90/**
91   \brief standard deconstructor
92
93*/
94MD2Model::~MD2Model () 
95{
96  // delete what has to be deleted here
97}
98
99
100void MD2Model::animate()
101{
102  if( unlikely(this->model->objectList.size() <= 0)) return;
103  /* get current animation from the list */
104  tAnimationInfo *pAnim = &(this->model->animationList[this->model->currentAnim]);
105
106  int nextFrame = (this->model->currentFrame + 1) % pAnim->endFrame;
107  if( unlikely(nextFrame == 0)) 
108    nextFrame =  pAnim->startFrame;
109
110  t3DObject *pFrame = &this->model->objectList[this->model->currentFrame];
111  t3DObject *pNextFrame = &this->model->objectList[nextFrame];
112
113  /* we have stored the texture and face information only in the first frame */
114  t3DObject *pFirstFrame = &this->model->objectList[0];
115
116  /* get the current time as a value in the domain [0..1] :)) */
117  float t = this->getCurrentTime(this->model, nextFrame);
118
119  glBegin(GL_TRIANGLES);
120  for(int j = 0; j < pFrame->numOfFaces; j++)
121    {
122      for(int whichVertex = 0; whichVertex < 3; whichVertex++)
123        {
124          int vertIndex = pFirstFrame->pFaces[j].vertIndex[whichVertex];
125          int texIndex  = pFirstFrame->pFaces[j].coordIndex[whichVertex];
126                                               
127          if( likely(pFirstFrame->pTexVerts != NULL)) 
128            {
129              glTexCoord2f(pFirstFrame->pTexVerts[texIndex].x, 
130                           pFirstFrame->pTexVerts[texIndex].y);
131            }
132                       
133          /* here comes the interpolation part */
134          CVector3 vPoint1 = pFrame->pVerts[vertIndex];
135          CVector3 vPoint2 = pNextFrame->pVerts[vertIndex];
136          glVertex3f(vPoint1.x + t * (vPoint2.x - vPoint1.x), 
137                     vPoint1.y + t * (vPoint2.y - vPoint1.y),
138                     vPoint1.z + t * (vPoint2.z - vPoint1.z));
139        }
140    }
141  glEnd();
142}
143
144
145float MD2Model::getCurrentTime(t3DModel *pModel, int nextFrame)
146{
147  /* stretch the time with animation speed (and make seconds out of it) */
148  //float t = this->dtS / kAnimationSpeed;
149       
150  if ( unlikely(this->localTime*1000.0 >=  1000.0/kAnimationSpeed) )
151    {
152      pModel->currentFrame = nextFrame;
153      this->localTime = 0.0f;
154    }
155  return (this->localTime / kAnimationSpeed);
156}
157
158
159void MD2Model::tick(float dtS)
160{
161  this->localTime += dtS;
162}
163
164/**
165   \brief draw function
166 
167   these function will take NO argument in the final version, just for testing
168*/
169void MD2Model::draw()
170{
171  if( this->model->objectList.size() <= 0) return;
172
173  t3DObject *pObject = &this->model->objectList[0];
174  glBegin(GL_TRIANGLES);
175  for(int j = 0; j < pObject->numOfFaces; j++)
176    {
177      for(int whichVertex = 0; whichVertex < 3; whichVertex++)
178        {
179          int index = pObject->pFaces[j].vertIndex[whichVertex];
180          int index2 = pObject->pFaces[j].coordIndex[whichVertex];
181          /* we invert the normals since the md2 file format uses different style */
182          /* FIX FIX FIX: ther are actualy no reasons to compute the normals every frame: change this later*/
183          glNormal3f(-pObject->pNormals[index].x, -pObject->pNormals[index].y, -pObject->pNormals[index].z);
184
185          if( likely(pObject->pTexVerts != NULL)) 
186            {
187              glTexCoord2f(pObject->pTexVerts[index2].x, pObject->pTexVerts[index2].y);
188            }
189          glVertex3f(pObject->pVerts[index].x, pObject->pVerts[index].y, pObject->pVerts[index].z);
190        }
191    }
192  glEnd();
193}
194
195/********************************************************************************
196 *   MD2LOADER                                                                  *
197 ********************************************************************************/
198
199/**
200   \brief standard deconstructor
201   creates a new model loader
202*/
203MD2Loader::MD2Loader()
204{
205  this->setClassName ("MD2Loader");
206  /* initialize all data to initial state */
207  memset(&this->header, 0, sizeof(tMd2Header));
208  this->pSkins = NULL;
209  this->pTexCoords = NULL;
210  this->pTriangles = NULL;
211  this->pFrames = NULL;
212}
213
214/**
215   \brief standard deconstructor
216*/
217MD2Loader::~MD2Loader()
218{}
219 
220
221/**
222   \brief this is called by the client to open the .Md2 file, read it, then clean up
223   \param model to load in
224   \param file name to load
225   \param texture name to load
226*/
227bool MD2Loader::importMD2(t3DModel *pModel, char *fileName, char *textureName)
228{
229  this->pFile = fopen(fileName, "rb");
230  if( unlikely(!pFile)) 
231    {
232      PRINTF(1)("Couldn't open the MD2 File for loading. Exiting.\n");
233      return false;
234    }
235  fread(&this->header, 1, sizeof(tMd2Header), pFile);
236  /* check for the header version: make sure its a md2 file :) */
237  if( likely(this->header.version != 8))
238    {
239      PRINTF(1)("Couldn't load file %s: invalid file format: stop loading\n", fileName);
240      return false;
241    }
242       
243  this->readMD2Data();
244  this->convertDataStructures(pModel);
245  this->computeNormals(pModel);
246
247  if( likely((int)textureName))
248    {
249      tMaterialInfo textureInfo;
250      strcpy(textureInfo.strFile, textureName);
251      /* since there is only one texture for a .Md2 file, the ID is always 0 */
252      textureInfo.texureId = 0;
253      textureInfo.uTile = 1;
254      /* we only have 1 material for a model */
255      pModel->numOfMaterials = 1;
256      pModel->materialList.push_back(textureInfo);
257    }
258       
259  this->cleanUp();
260  return true;
261}
262
263
264/**
265   \brief This function reads in all of the model's data, except the animation frames
266*/
267void MD2Loader::readMD2Data()
268{
269  unsigned char buffer[MD2_MAX_FRAMESIZE];
270  this->pSkins     = new tMd2Skin[this->header.numSkins];
271  this->pTexCoords = new tMd2TexCoord[this->header.numTexCoords];
272  this->pTriangles = new tMd2Face[this->header.numTriangles];
273  this->pFrames    = new tMd2Frame[this->header.numFrames];
274
275  /* we read the skins */
276  fseek(this->pFile, this->header.offsetSkins, SEEK_SET);
277  fread(this->pSkins, sizeof(tMd2Skin), this->header.numSkins, this->pFile);
278  /* read all vertex data */
279  fseek(this->pFile, this->header.offsetTexCoords, SEEK_SET);
280  fread(this->pTexCoords, sizeof(tMd2TexCoord), this->header.numTexCoords, this->pFile);
281  /* read face data for each triangle (normals) */
282  fseek(this->pFile, this->header.offsetTriangles, SEEK_SET);
283  fread(this->pTriangles, sizeof(tMd2Face), this->header.numTriangles, this->pFile);
284  /* reading all frame data */
285  fseek(this->pFile, this->header.offsetFrames, SEEK_SET);
286  for( int i = 0; i < this->header.numFrames; i++)
287    {
288      tMd2AliasFrame *pFrame = (tMd2AliasFrame *) buffer;
289      this->pFrames[i].pVertices = new tMd2Triangle [this->header.numVertices];
290
291      /* read the frame animation data */
292      fread(pFrame, 1, this->header.frameSize, this->pFile);
293      strcpy(this->pFrames[i].strName, pFrame->name);
294      tMd2Triangle *pVertices = this->pFrames[i].pVertices;
295      /*
296         scale translations, store vertices: since id used a non-opengl xyz notation, we have to swap y and z
297         and negate z axis
298      */
299      for( int j = 0; j < this->header.numVertices; j++)
300        {
301          pVertices[j].vertex[0] = pFrame->aliasVertices[j].vertex[0] * pFrame->scale[0] + pFrame->translate[0];
302          pVertices[j].vertex[2] = -1 * (pFrame->aliasVertices[j].vertex[1] * pFrame->scale[1] + pFrame->translate[1]);
303          pVertices[j].vertex[1] = pFrame->aliasVertices[j].vertex[2] * pFrame->scale[2] + pFrame->translate[2];
304
305          printf("vertices %i --- %f, %f, %f\n",j, pVertices[j].vertex[0], pVertices[j].vertex[1], pVertices[j].vertex[2]);
306        }
307    }
308}
309
310
311/**
312   \brief this function fills in the animation list for each animation by name and frame
313   \param model
314*/
315void MD2Loader::parseAnimations(t3DModel *pModel)
316{
317  tAnimationInfo animationInfo;
318  string strLastName = "";
319
320  /* the animation parse process looks a little bit wired: this is because there are no
321     fix bounds for the animation lengths, so the frames are destingushed using their names
322     which is normaly composed of <animationname><number>
323  */
324
325  for(int i = 0; i < pModel->numOfObjects; i++)
326    {
327      string strName  = this->pFrames[i].strName;
328      int frameNum = 0;
329       
330      /* erease the frame number from the frame-name */
331      for(unsigned int j = 0; j < strName.length(); j++)
332        {
333          if( isdigit(strName[j]) && j >= strName.length() - 2)
334            {
335              frameNum = atoi(&strName[j]);
336              strName.erase(j, strName.length() - j);
337              break;
338            }
339        }
340
341      printf("current: %s, last: %s\n", strName.c_str(), strLastName.c_str());
342
343      /* animations are sorted through their names: this is how its been done: */
344      if( strName != strLastName || i == pModel->numOfObjects - 1)
345        {
346          if( strLastName != "")
347            {
348              strcpy(animationInfo.strName, strLastName.c_str());
349              animationInfo.endFrame = i;
350              pModel->animationList.push_back(animationInfo);
351              memset(&animationInfo, 0, sizeof(tAnimationInfo));
352              pModel->numOfAnimations++;
353            }
354          animationInfo.startFrame = frameNum - 1 + i;
355        }
356      strLastName = strName;
357    }
358}
359
360
361/**
362   \brief this function converts the .md2 structures to our own model and object structures: decompress
363   \param model
364*/
365void MD2Loader::convertDataStructures(t3DModel *pModel)
366{
367  int j = 0, i = 0;
368       
369  memset(pModel, 0, sizeof(t3DModel));
370  pModel->numOfObjects = this->header.numFrames;
371
372  this->parseAnimations(pModel);
373
374  for (i = 0; i < pModel->numOfObjects; i++)
375    {
376      t3DObject currentFrame;
377
378      currentFrame.numOfVerts = this->header.numVertices;
379      currentFrame.numTexVertex = this->header.numTexCoords;
380      currentFrame.numOfFaces = this->header.numTriangles;
381
382      currentFrame.pVerts = new CVector3[currentFrame.numOfVerts];
383
384      for (j = 0; j < currentFrame.numOfVerts; j++)
385        {
386          currentFrame.pVerts[j].x = this->pFrames[i].pVertices[j].vertex[0];
387          currentFrame.pVerts[j].y = this->pFrames[i].pVertices[j].vertex[1];
388          currentFrame.pVerts[j].z = this->pFrames[i].pVertices[j].vertex[2];
389        }
390
391      delete this->pFrames[i].pVertices;
392
393      if( likely(i > 0))
394        {
395          pModel->objectList.push_back(currentFrame);
396          continue;
397        }
398                       
399      currentFrame.pTexVerts = new CVector2[currentFrame.numTexVertex];
400      currentFrame.pFaces = new tFace[currentFrame.numOfFaces];
401
402      for(j = 0; j < currentFrame.numTexVertex; j++)
403        {
404          currentFrame.pTexVerts[j].x = this->pTexCoords[j].u / float(this->header.skinWidth);
405          currentFrame.pTexVerts[j].y = 1 - this->pTexCoords[j].v / float(this->header.skinHeight);
406        }
407
408      for(j = 0; j < currentFrame.numOfFaces; j++)
409        {
410          currentFrame.pFaces[j].vertIndex[0] = this->pTriangles[j].vertexIndices[0];
411          currentFrame.pFaces[j].vertIndex[1] = this->pTriangles[j].vertexIndices[1];
412          currentFrame.pFaces[j].vertIndex[2] = this->pTriangles[j].vertexIndices[2];
413
414          currentFrame.pFaces[j].coordIndex[0] = this->pTriangles[j].textureIndices[0];
415          currentFrame.pFaces[j].coordIndex[1] = this->pTriangles[j].textureIndices[1];
416          currentFrame.pFaces[j].coordIndex[2] = this->pTriangles[j].textureIndices[2];
417        }
418      pModel->objectList.push_back(currentFrame);
419    }
420}
421
422
423/**
424   \brief this function conputes the normals of the model
425   \param model
426*/
427void MD2Loader::computeNormals(t3DModel *pModel)
428{
429  CVector3 vVector1, vVector2, vNormal, vPoly[3];
430
431  if( unlikely(pModel->numOfObjects <= 0))
432    return;
433  /* now computing face normals: this means just averaging the vertex normals of a face */
434  /* so for every object: */
435  for(int index = 0; index < pModel->numOfObjects; index++)
436    {
437      t3DObject *pObject = &(pModel->objectList[index]);
438
439      /* allocate all the memory we need to calculate the normals */
440      CVector3 *pNormals = new CVector3 [pObject->numOfFaces];
441      CVector3 *pTempNormals = new CVector3 [pObject->numOfFaces];
442      pObject->pNormals = new CVector3 [pObject->numOfVerts];
443
444      for(int i=0; i < pObject->numOfFaces; i++)
445        {
446          /* cache the points to make coding easier :) */
447          vPoly[0] = pObject->pVerts[pObject->pFaces[i].vertIndex[0]];
448          vPoly[1] = pObject->pVerts[pObject->pFaces[i].vertIndex[1]];
449          vPoly[2] = pObject->pVerts[pObject->pFaces[i].vertIndex[2]];
450
451          vVector1 = MathHelp::VectorDiff(vPoly[0], vPoly[2]);         
452          vVector2 = MathHelp::VectorDiff(vPoly[2], vPoly[1]);         
453                       
454          vNormal  = MathHelp::CrossProduct(vVector1, vVector2);               
455          pTempNormals[i] = vNormal;                                   
456          vNormal  = MathHelp::NormalizeVector(vNormal);                               
457
458          pNormals[i] = vNormal;
459        }
460
461      /* now calculating vertex normals */
462      CVector3 vSum = {0.0, 0.0, 0.0};
463      CVector3 vZero = vSum;
464      int shared=0;
465
466      for (int i = 0; i < pObject->numOfVerts; i++)                     
467        {
468          for (int j = 0; j < pObject->numOfFaces; j++) 
469            {                                                                                           
470              if (pObject->pFaces[j].vertIndex[0] == i || 
471                  pObject->pFaces[j].vertIndex[1] == i || 
472                  pObject->pFaces[j].vertIndex[2] == i)
473                {
474                  vSum = MathHelp::AddVector(vSum, pTempNormals[j]);
475                  shared++;                                                                                             }
476            }     
477          pObject->pNormals[i] = MathHelp::DivideVectorByScaler(vSum, float(-shared));
478          pObject->pNormals[i] = MathHelp::NormalizeVector(pObject->pNormals[i]);       
479
480          vSum = vZero;                                                                 
481          shared = 0;                                                                           
482        }
483      delete [] pTempNormals;
484      delete [] pNormals;
485    }
486}
487
488
489/**
490   \brief This function cleans up our allocated memory and closes the file
491*/
492void MD2Loader::cleanUp()
493{
494  fclose(this->pFile);                 
495       
496  if( this->pSkins) delete [] this->pSkins;             
497  if( this->pTexCoords) delete this->pTexCoords;
498  if( this->pTriangles) delete this->pTriangles;
499  if( this->pFrames) delete this->pFrames;
500}
501
502
503/********************************************************************************
504 *   MD2LOADER2                                                                 *
505 ********************************************************************************/
506
507MD2Model2::MD2Model2()
508{
509  this->pVertices = NULL;
510  this->pGLCommands = NULL;
511  this->pLightNormals = NULL; 
512
513  this->numFrames = 0;
514  this->numVertices = 0;
515  this->numGLCommands = 0;
516 
517  this->textureID = 0;
518  this->scaleFactor = 1.0f;
519
520  this->setAnim(BOOM);
521}
522
523
524MD2Model2::~MD2Model2()
525{
526  delete [] this->pVertices;
527  delete [] this->pGLCommands;
528  delete [] this->pLightNormals;
529}
530
531
532
533bool MD2Model2::loadModel(const char* fileName)
534{
535  FILE *pFile;                            //file stream
536  char* buffer;                           //buffer for frame data
537  sFrame* frame;                          //temp frame
538  sVec3D *pVertex;
539  int* pNormals;
540
541  pFile = fopen(fileName, "rb");
542  if( unlikely(!pFile)) 
543    {
544      PRINTF(1)("Couldn't open the MD2 File for loading. Exiting.\n");
545      return false;
546    }
547  this->header = new tMd2Header;
548  fread(this->header, 1, sizeof(tMd2Header), pFile);
549  /* check for the header version: make sure its a md2 file :) */
550  if( unlikely(this->header->version != MD2_VERSION) && unlikely(this->header->ident != MD2_IDENT))
551    {
552      PRINTF(1)("Couldn't load file %s: invalid file format: stop loading\n", fileName);
553      return false;
554    }
555
556  this->fileName = new char[strlen(fileName)+1];
557  strcpy(this->fileName, fileName);
558  /* got the data: map it to locals */
559  this->numFrames = this->header->numFrames;
560  this->numVertices = this->header->numVertices;
561  this->numTriangles = this->header->numTriangles;
562  this->numGLCommands = this->header->numGlCommands;
563  /* allocate memory for the data storage */
564  this->pVertices = new sVec3D[this->numVertices * this->numFrames];
565  this->pGLCommands = new int[this->numGLCommands];
566  this->pLightNormals = new int[this->numVertices * this->numFrames];
567  buffer = new char[this->numFrames * this->header->frameSize];
568
569  /* read frame data from the file to a temp buffer */
570  fseek(pFile, this->header->offsetFrames, SEEK_SET);
571  fread(buffer, this->header->frameSize, this->numFrames, pFile);
572  /* read opengl commands */
573  fseek(pFile, this->header->offsetGlCommands, SEEK_SET);
574  fread(this->pGLCommands, sizeof(int), this->numGLCommands, pFile);
575
576  for(int i = 0; i < this->numFrames; ++i)
577    {
578      frame = (sFrame*)(buffer + this->header->frameSize * i); 
579      pVertex = this->pVertices + this->numVertices  * i;
580      pNormals = this->pLightNormals + this->numVertices * i;
581
582      for(int j = 0; j < this->numVertices; ++j)
583        {
584          /* SPEEDUP: *(pVerts + i + 0) = (*(frame->pVertices + i + 0)...  */
585          pVertex[j][0] = (frame->pVertices[j].v[0] * frame->scale[0]) + frame->translate[0];
586          pVertex[j][1] = (frame->pVertices[j].v[2] * frame->scale[2]) + frame->translate[2];
587          pVertex[j][2] = -1.0 * (frame->pVertices[j].v[1] * frame->scale[1] + frame->translate[1]);
588         
589          pNormals[j] = frame->pVertices[j].lightNormalIndex;
590        }
591    }
592
593  delete [] buffer;
594  fclose(pFile);
595}
596
597
598bool MD2Model2::loadSkin(const char* fileName)
599{
600  this->material = new Material("md2ModelTest");
601  this->material->setDiffuseMap(fileName);
602  this->material->setIllum(3);
603  this->material->setAmbient(1.0, 1.0, 1.0);
604}
605
606
607/**
608   \brief initializes an array of vert with the current frame scaled vertices
609
610   we won't use the pVertices array directly, since its much easier and we need
611   saving of data anyway
612*/
613void MD2Model2::interpolate(sVec3D* verticesList)
614{
615  sVec3D* currVec;
616  sVec3D* nextVec;
617
618  currVec = &this->pVertices[this->numVertices * this->animationState.currentFrame];
619  nextVec = &this->pVertices[this->numVertices * this->animationState.nextFrame];
620
621  for(int i = 0; i < this->numFrames; ++i)
622    {
623      verticesList[i][0] = (currVec[i][0] + this->animationState.interpolationState * (nextVec[i][0] - currVec[i][0])) * this->scaleFactor;
624      verticesList[i][1] = (currVec[i][1] + this->animationState.interpolationState * (nextVec[i][1] - currVec[i][1])) * this->scaleFactor;
625      verticesList[i][2] = (currVec[i][2] + this->animationState.interpolationState * (nextVec[i][2] - currVec[i][2])) * this->scaleFactor;
626    }
627}
628
629
630void MD2Model2::setAnim(int type)
631{
632  if( (type < 0) || (type > MAX_ANIMATIONS) )
633    type = 0;
634
635  this->animationState.startFrame = animationList[type].firstFrame;
636  this->animationState.endFrame = animationList[type].lastFrame;
637  this->animationState.nextFrame = animationList[type].firstFrame + 1;
638  this->animationState.fps = animationList[type].fps;
639  this->animationState.type = type;
640 
641  this->animationState.interpolationState = 0.0;
642  this->animationState.localTime = 0.0;
643  this->animationState.lastTime = 0.0;
644  this->animationState.currentFrame = animationList[type].firstFrame;
645}
646
647
648void MD2Model2::animate()
649{
650  if( this->animationState.localTime - this->animationState.lastTime > (1.0f / this->animationState.fps))
651    {
652      this->animationState.currentFrame = this->animationState.nextFrame;
653      this->animationState.nextFrame++;
654     
655      if( this->animationState.nextFrame > this->animationState.endFrame)
656        this->animationState.nextFrame = this->animationState.startFrame;
657      this->animationState.lastTime = this->animationState.localTime;
658    }
659
660  if( this->animationState.currentFrame > (this->numFrames - 1) )
661    this->animationState.currentFrame = 0;
662  if( this->animationState.nextFrame > (this->numFrames - 1) )
663    this->animationState.nextFrame = 0;
664
665  this->animationState.interpolationState = this->animationState.fps * 
666    (this->animationState.localTime - this->animationState.lastTime);
667}
668
669
670/* hhmmm... id used a very different way to do lightning... */
671void MD2Model2::processLighting()
672{
673  shadeDots = anormsDots[((int)(md2Angle*(SHADEDOT_QUANT / 360.0)))&(SHADEDOT_QUANT - 1)];
674}
675
676
677void MD2Model2::tick(float time)
678{
679  this->animationState.localTime += time;
680}
681
682
683void MD2Model2::draw()
684{
685  if( likely(this->animationState.localTime > 0.0))
686    this->animate();
687
688  glPushMatrix();
689
690  this->renderFrame();
691
692  glPopMatrix();
693}
694
695
696void MD2Model2::renderFrame()
697{
698  static sVec3D verticesList[MD2_MAX_VERTICES]; /* performance: created only once in a lifetime */
699  int* pCommands = this->pGLCommands;
700
701  /* some face culling stuff */
702  glPushAttrib(GL_POLYGON_BIT);
703  glFrontFace(GL_CW);
704  glEnable(GL_CULL_FACE);
705  glCullFace(GL_BACK);
706     
707  this->processLighting();
708  this->interpolate(verticesList);
709  this->material->select();
710
711  /* draw the triangles */
712  while( int i = *(pCommands++)) /* strange looking while loop for maximum performance */
713    {
714      if( i < 0)
715        {
716          glBegin(GL_TRIANGLE_FAN);
717          i = -i;
718        }
719      else
720        {
721          glBegin(GL_TRIANGLE_STRIP);
722        }
723
724      for(; i > 0; i--, pCommands += 3) /* down counting for loop, next 3 gl commands */
725        {
726          glNormal3fv(anorms[this->pLightNormals[pCommands[2]]]);
727          glTexCoord2f( ((float *)pCommands)[0], 1.0-((float *)pCommands)[1] );
728          glVertex3fv(verticesList[pCommands[2]]);
729        }
730      glEnd();
731    }
732  glDisable(GL_CULL_FACE);
733  glPopAttrib();
734}
735
736
737void MD2Model2::debug()
738{
739  PRINT(0)("==========================| MD2Model2::debug() |===\n");
740  PRINT(0)("=  Model FileName:\t%s\n", this->fileName);
741  PRINT(0)("=  Size in Memory:\t%i Bytes\n", this->header->frameSize * this->header->numFrames + 64); // 64bytes is the header size
742  PRINT(0)("=  Number of Vertices:\t%i\n", this->header->numVertices);
743  PRINT(0)("=  Number of Frames: \t%i\n", this->header->numFrames);
744  PRINT(0)("=  Height, Width\t\t%i, %i\n", this->header->skinHeight, this->header->skinWidth);
745  PRINT(0)("===================================================\n\n");
746}
Note: See TracBrowser for help on using the repository browser.