Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/md2_loader: debug information output added

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