Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/md2_loader/src/lib/graphics/importer/md2Model.cc @ 4211

Last change on this file since 4211 was 4211, checked in by patrick, 19 years ago

orxonox/branches/md2_model: implemented some functions setAnimation and animate, which are both used for the md2 animation subsystem

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