Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/md2_loader: fixed the segfault bug: the glcommand list had some offset problems :)

File size: 24.9 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->pGLCommands2 = new int[this->numGLCommands];
565  this->pLightNormals = new int[this->numVertices * this->numFrames];
566  buffer = new char[this->numFrames * this->header->frameSize];
567
568  /* read frame data from the file to a temp buffer */
569  fseek(pFile, this->header->offsetFrames, SEEK_SET);
570  fread(buffer, this->header->frameSize, this->numFrames, pFile);
571  /* read opengl commands */
572  fseek(pFile, this->header->offsetGlCommands, SEEK_SET);
573  fread(this->pGLCommands, sizeof(int), this->numGLCommands, pFile);
574  //fread(this->pGLCommands2, sizeof(glCommandVertex), this->numGLCommands, pFile);
575
576  for(int i = 0; i < this->numFrames; ++i)
577    {
578      /*
579      faster but evt. buggy
580      frame = (sFrame*)(buffer + this->header->frameSize * i);
581      pVertex = this->pVertices + this->numVertices  * i;
582      pNormals = this->pLightNormals + this->numVertices * i;
583      */
584      frame = (sFrame *)&buffer[this->header->frameSize * i];
585      pVertex = &this->pVertices[this->numVertices * i];
586      pNormals = &this->pLightNormals[this->numVertices * i];
587
588      for(int j = 0; j < this->numVertices; ++j)
589        {
590          /* SPEEDUP: *(pVerts + i + 0) = (*(frame->pVertices + i + 0)...  */
591          pVertex[j][0] = (frame->pVertices[j].v[0] * frame->scale[0]) + frame->translate[0];
592          pVertex[j][1] = (frame->pVertices[j].v[1] * frame->scale[1]) + frame->translate[1];
593          pVertex[j][2] = (frame->pVertices[j].v[2] * frame->scale[2]) + frame->translate[2];
594         
595          //printf("pVertex %f, %f, %f\n", pVertex[j][0], pVertex[j][1], pVertex[j][2]);
596
597          pNormals[j] = frame->pVertices[j].lightNormalIndex;
598        }
599    }
600
601  delete [] buffer;
602  fclose(pFile);
603}
604
605
606bool MD2Model2::loadSkin(const char* fileName)
607{
608  this->material = new Material("md2ModelTest");
609  this->material->setDiffuseMap(fileName);
610  this->material->setIllum(3);
611  this->material->setAmbient(1.0, 1.0, 1.0);
612}
613
614
615/**
616   \brief initializes an array of vert with the current frame scaled vertices
617
618   we won't use the pVertices array directly, since its much easier and we need
619   saving of data anyway
620*/
621void MD2Model2::interpolate(sVec3D* verticesList)
622{
623  sVec3D* currVec;
624  sVec3D* nextVec;
625
626  currVec = &this->pVertices[this->numVertices * this->animationState.currentFrame];
627  nextVec = &this->pVertices[this->numVertices * this->animationState.nextFrame];
628
629  //printf("currVec: %f, %f, %f\n", currVec[0][0], currVec[0][1], currVec[0][2]);
630  //printf("nextVec: %f, %f, %f\n", nextVec[0][0], nextVec[1][1], nextVec[2][2]);
631 
632  //printf("numFrames: %i\n", this->numFrames);
633  //printf("currentFrame: %i\n", this->animationState.currentFrame);
634 
635    //for(int i = 0; i < this->numFrames; ++i)
636    for(int i = 0; i < this->numVertices; ++i)
637      { 
638        /*
639        verticesList[i][0] = this->pVertices[i + (this->numFrames * this->animationState.currentFrame)][0] * this->scaleFactor;
640        verticesList[i][1] = this->pVertices[i + (this->numFrames * this->animationState.currentFrame)][1] * this->scaleFactor;
641        verticesList[i][2] = this->pVertices[i + (this->numFrames * this->animationState.currentFrame)][2] * this->scaleFactor;
642        */
643
644
645        verticesList[i][0] = (currVec[i][0] + this->animationState.interpolationState * (nextVec[i][0] - currVec[i][0])) * this->scaleFactor;
646        verticesList[i][1] = (currVec[i][1] + this->animationState.interpolationState * (nextVec[i][1] - currVec[i][1])) * this->scaleFactor;
647        verticesList[i][2] = (currVec[i][2] + this->animationState.interpolationState * (nextVec[i][2] - currVec[i][2])) * this->scaleFactor;
648
649
650        //printf("  pVertices %f, %f, %f\n", pVertices[i][0], pVertices[i][1], pVertices[i][2]);
651        //printf("  list:     %f, %f, %f \n", verticesList[i][0], verticesList[i][1], verticesList[i][2]);     
652      }
653}
654
655
656void MD2Model2::setAnim(int type)
657{
658  if( (type < 0) || (type > MAX_ANIMATIONS) )
659    type = 0;
660
661  this->animationState.startFrame = animationList[type].firstFrame;
662  this->animationState.endFrame = animationList[type].lastFrame;
663  this->animationState.nextFrame = animationList[type].firstFrame + 1;
664  this->animationState.fps = animationList[type].fps;
665  this->animationState.type = type;
666 
667  this->animationState.interpolationState = 0.0;
668  this->animationState.localTime = 0.0;
669  this->animationState.lastTime = 0.0;
670  this->animationState.currentFrame = animationList[type].firstFrame;
671}
672
673
674void MD2Model2::animate()
675{
676  if( this->animationState.localTime - this->animationState.lastTime > (1.0f / this->animationState.fps))
677    {
678      this->animationState.currentFrame = this->animationState.nextFrame;
679      this->animationState.nextFrame++;
680     
681      if( this->animationState.nextFrame > this->animationState.endFrame)
682        this->animationState.nextFrame = this->animationState.startFrame;
683      this->animationState.lastTime = this->animationState.localTime;
684    }
685
686  if( this->animationState.currentFrame > (this->numFrames - 1) )
687    this->animationState.currentFrame = 0;
688  if( this->animationState.nextFrame > (this->numFrames - 1) )
689    this->animationState.nextFrame = 0;
690
691  this->animationState.interpolationState = this->animationState.fps * 
692    (this->animationState.localTime - this->animationState.lastTime);
693}
694
695
696/* hhmmm... id used a very different way to do lightning... */
697void MD2Model2::processLighting()
698{
699  shadeDots = anormsDots[((int)(md2Angle*(SHADEDOT_QUANT / 360.0)))&(SHADEDOT_QUANT - 1)];
700}
701
702
703void MD2Model2::tick(float time)
704{
705  this->animationState.localTime += time;
706}
707
708
709void MD2Model2::draw()
710{
711  if( likely(this->animationState.localTime > 0.0))
712    this->animate();
713
714  glPushMatrix();
715  /* rotate because id software uses another orientation then the openGL default */
716  /* \todo: rotate the axis already when loading... easy :) */
717  glRotatef(-90.0, 1.0, 0.0, 0.0);
718  glRotatef(-90.0, 0.0, 0.0, 1.0);
719
720  this->renderFrame();
721
722  glPopMatrix();
723}
724
725
726void MD2Model2::draw2()
727{
728  glBegin(GL_TRIANGLES);
729  for(int j = 0; j < this->numTriangles; j++)
730    {
731      for(int whichVertex = 0; whichVertex < 3; whichVertex++)
732        {
733          /*
734          int index = pObject->pFaces[j].vertIndex[whichVertex];
735          int index2 = pObject->pFaces[j].coordIndex[whichVertex];
736          glNormal3f(-pObject->pNormals[index].x, -pObject->pNormals[index].y, -pObject->pNormals[index].z);
737         
738          if( likely(pObject->pTexVerts != NULL))
739            {
740              glTexCoord2f(pObject->pTexVerts[index2].x, pObject->pTexVerts[index2].y);
741            }
742          glVertex3f(pObject->pVerts[index].x, pObject->pVerts[index].y, pObject->pVerts[index].z);
743          */
744        }
745    }
746  glEnd();
747}
748
749
750void MD2Model2::renderFrame()
751{
752  static sVec3D verticesList[MD2_MAX_VERTICES]; /* performance: created only once in a lifetime */
753  int* pCommands = this->pGLCommands;
754
755  /* some face culling stuff */
756  glPushAttrib(GL_POLYGON_BIT);
757  glFrontFace(GL_CW);
758  glEnable(GL_CULL_FACE);
759  glCullFace(GL_BACK);
760     
761  this->processLighting();
762  this->interpolate(verticesList);
763  this->material->select();
764
765  /* draw the triangles */
766  /* \todo: take int i out of while loop */
767  while( int i = *(pCommands++)) /* strange looking while loop for maximum performance */
768    {
769      if( i < 0)
770        {
771          glBegin(GL_TRIANGLE_FAN);
772          i = -i;
773        }
774      else
775        {
776          glBegin(GL_TRIANGLE_STRIP);
777        }
778
779      for(; i > 0; i--, pCommands += 3) /* down counting for loop, next 3 gl commands */
780        {
781          /* for quake2 lighting */
782          //float l = shadeDots[this->pLightNormals[pCommands[2]]];
783          //glColor3f(l * lcolor[0], l * lcolor[1], l * lcolor[2]);
784
785          glNormal3fv(anorms[this->pLightNormals[pCommands[2]]]);
786          glTexCoord2f( ((float *)pCommands)[0], ((float *)pCommands)[1] );
787          glVertex3fv(verticesList[pCommands[2]]);
788
789          //printf("draw vert: %f, %f, %f\n", verticesLit[pCommands[2]][0], verticesList[pCommands[2]][1], verticesList[pCommands[2]][2] );
790        }
791      glEnd();
792    }
793  glDisable(GL_CULL_FACE);
794  glPopAttrib();
795}
796
797
798void MD2Model2::debug()
799{
800  PRINT(0)("==========================| MD2Model2::debug() |===\n");
801  PRINT(0)("=  Model FileName:\t%s\n", this->fileName);
802  PRINT(0)("=  Size in Memory:\t%i Bytes\n", this->header->frameSize * this->header->numFrames + 64); // 64bytes is the header size
803  PRINT(0)("=  Number of Vertices:\t%i\n", this->header->numVertices);
804  PRINT(0)("=  Number of Frames: \t%i\n", this->header->numFrames);
805  PRINT(0)("=  Height, Width\t\t%i, %i\n", this->header->skinHeight, this->header->skinWidth);
806  PRINT(0)("===================================================\n\n");
807}
Note: See TracBrowser for help on using the repository browser.