Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/md2_model: implemented interpolate and some animation structures

File size: 20.3 KB
RevLine 
[4065]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
[4079]15#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_IMPORTER
[4065]16
17#include "md2Model.h"
[4172]18#include "material.h"
[4065]19
[4079]20#include <fstream>
[4082]21#include <string>
[4142]22#include <vector>
[4079]23
[4080]24
[4065]25using namespace std;
26
[4187]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
[4188]36static float *shadeDots = MD2Model2::anormsDots[0];
[4187]37
[4188]38float md2Angle = 0.0f;
[4187]39
[4188]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
[4077]67/********************************************************************************
68 *   MD2MODEL                                                                   *
69 ********************************************************************************/
[4065]70
71/**
72   \brief standard constructor
[4076]73   
[4140]74   creates a new model
[4065]75*/
76MD2Model::MD2Model () 
77{
[4140]78  this->setClassName ("MD2Model");
[4168]79
80  MD2Loader* md2loader = new MD2Loader();
81  this->model = new t3DModel;
82  md2loader->importMD2(this->model, "../data/models/tris.md2");
[4169]83  delete md2loader;
[4065]84}
85
86
87/**
88   \brief standard deconstructor
89
90*/
91MD2Model::~MD2Model () 
92{
93  // delete what has to be deleted here
94}
[4076]95
[4161]96
[4168]97void MD2Model::animate()
[4161]98{
[4168]99  if( unlikely(this->model->objectList.size() <= 0)) return;
[4162]100  /* get current animation from the list */
[4168]101  tAnimationInfo *pAnim = &(this->model->animationList[this->model->currentAnim]);
[4161]102
[4168]103  int nextFrame = (this->model->currentFrame + 1) % pAnim->endFrame;
[4162]104  if( unlikely(nextFrame == 0)) 
105    nextFrame =  pAnim->startFrame;
[4161]106
[4168]107  t3DObject *pFrame = &this->model->objectList[this->model->currentFrame];
108  t3DObject *pNextFrame = &this->model->objectList[nextFrame];
[4161]109
[4162]110  /* we have stored the texture and face information only in the first frame */
[4168]111  t3DObject *pFirstFrame = &this->model->objectList[0];
[4161]112
[4162]113  /* get the current time as a value in the domain [0..1] :)) */
[4168]114  float t = this->getCurrentTime(this->model, nextFrame);
[4161]115
[4162]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];
[4161]123                                               
[4162]124          if( likely(pFirstFrame->pTexVerts != NULL)) 
125            {
[4168]126              glTexCoord2f(pFirstFrame->pTexVerts[texIndex].x, 
127                           pFirstFrame->pTexVerts[texIndex].y);
[4162]128            }
[4161]129                       
[4162]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();
[4161]139}
140
141
[4162]142float MD2Model::getCurrentTime(t3DModel *pModel, int nextFrame)
[4161]143{
[4162]144  /* stretch the time with animation speed (and make seconds out of it) */
[4163]145  //float t = this->dtS / kAnimationSpeed;
[4161]146       
[4163]147  if ( unlikely(this->localTime*1000.0 >=  1000.0/kAnimationSpeed) )
148    {
[4162]149      pModel->currentFrame = nextFrame;
[4163]150      this->localTime = 0.0f;
151    }
[4168]152  return (this->localTime / kAnimationSpeed);
[4161]153}
154
[4162]155
156void MD2Model::tick(float dtS)
157{
[4163]158  this->localTime += dtS;
[4162]159}
160
[4138]161/**
[4140]162   \brief draw function
[4138]163 
[4140]164   these function will take NO argument in the final version, just for testing
[4138]165*/
[4168]166void MD2Model::draw()
[4138]167{
[4168]168  if( this->model->objectList.size() <= 0) return;
[4076]169
[4168]170  t3DObject *pObject = &this->model->objectList[0];
[4140]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 */
[4150]179          /* FIX FIX FIX: ther are actualy no reasons to compute the normals every frame: change this later*/
[4147]180          glNormal3f(-pObject->pNormals[index].x, -pObject->pNormals[index].y, -pObject->pNormals[index].z);
181
[4158]182          if( likely(pObject->pTexVerts != NULL)) 
[4140]183            {
[4158]184              glTexCoord2f(pObject->pTexVerts[index2].x, pObject->pTexVerts[index2].y);
[4140]185            }
[4158]186          glVertex3f(pObject->pVerts[index].x, pObject->pVerts[index].y, pObject->pVerts[index].z);
[4140]187        }
188    }
189  glEnd();
[4138]190}
191
[4077]192/********************************************************************************
193 *   MD2LOADER                                                                  *
194 ********************************************************************************/
195
[4076]196/**
197   \brief standard deconstructor
[4140]198   creates a new model loader
[4076]199*/
200MD2Loader::MD2Loader()
[4077]201{
[4140]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;
[4077]209}
[4076]210
211/**
212   \brief standard deconstructor
213*/
214MD2Loader::~MD2Loader()
215{}
216 
217
218/**
[4140]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
[4076]223*/
[4079]224bool MD2Loader::importMD2(t3DModel *pModel, char *fileName, char *textureName)
225{
[4140]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    }
[4079]239       
[4140]240  this->readMD2Data();
241  this->convertDataStructures(pModel);
[4150]242  this->computeNormals(pModel);
[4079]243
[4140]244  if( likely((int)textureName))
245    {
[4146]246      tMaterialInfo textureInfo;
247      strcpy(textureInfo.strFile, textureName);
[4140]248      /* since there is only one texture for a .Md2 file, the ID is always 0 */
[4146]249      textureInfo.texureId = 0;
250      textureInfo.uTile = 1;
[4140]251      /* we only have 1 material for a model */
252      pModel->numOfMaterials = 1;
[4146]253      pModel->materialList.push_back(textureInfo);
[4140]254    }
[4079]255       
[4140]256  this->cleanUp();
257  return true;
[4079]258}
259
[4157]260
[4076]261/**
[4140]262   \brief This function reads in all of the model's data, except the animation frames
[4076]263*/
264void MD2Loader::readMD2Data()
[4080]265{
[4140]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];
[4076]271
[4140]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);
[4147]283  for( int i = 0; i < this->header.numFrames; i++)
[4140]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      */
[4147]296      for( int j = 0; j < this->header.numVertices; j++)
[4080]297        {
[4140]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];
[4080]301        }
[4140]302    }
[4080]303}
304
[4157]305
[4076]306/**
[4140]307   \brief this function fills in the animation list for each animation by name and frame
308   \param model
[4076]309*/
310void MD2Loader::parseAnimations(t3DModel *pModel)
[4082]311{
[4146]312  tAnimationInfo animationInfo;
[4140]313  string strLastName = "";
[4076]314
[4141]315  /* the animation parse process looks a little bit wired: this is because there are no
[4140]316     fix bounds for the animation lengths, so the frames are destingushed using their names
317     which is normaly composed of <animationname><number>
318  */
[4082]319
[4140]320  for(int i = 0; i < pModel->numOfObjects; i++)
321    {
322      string strName  = this->pFrames[i].strName;
323      int frameNum = 0;
[4141]324       
325      /* erease the frame number from the frame-name */
[4140]326      for(unsigned int j = 0; j < strName.length(); j++)
[4082]327        {
[4140]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        }
[4082]335
[4141]336      printf("current: %s, last: %s\n", strName.c_str(), strLastName.c_str());
337
[4140]338      /* animations are sorted through their names: this is how its been done: */
[4141]339      if( strName != strLastName || i == pModel->numOfObjects - 1)
[4140]340        {
[4141]341          if( strLastName != "")
[4140]342            {
[4146]343              strcpy(animationInfo.strName, strLastName.c_str());
344              animationInfo.endFrame = i;
345              pModel->animationList.push_back(animationInfo);
[4140]346              memset(&animationInfo, 0, sizeof(tAnimationInfo));
347              pModel->numOfAnimations++;
348            }
[4146]349          animationInfo.startFrame = frameNum - 1 + i;
[4082]350        }
[4140]351      strLastName = strName;
352    }
[4082]353}
354
[4157]355
[4076]356/**
[4140]357   \brief this function converts the .md2 structures to our own model and object structures: decompress
358   \param model
[4076]359*/
360void MD2Loader::convertDataStructures(t3DModel *pModel)
[4087]361{
[4140]362  int j = 0, i = 0;
[4087]363       
[4140]364  memset(pModel, 0, sizeof(t3DModel));
365  pModel->numOfObjects = this->header.numFrames;
[4076]366
[4140]367  this->parseAnimations(pModel);
[4076]368
[4140]369  for (i = 0; i < pModel->numOfObjects; i++)
370    {
[4146]371      t3DObject currentFrame;
[4087]372
[4146]373      currentFrame.numOfVerts = this->header.numVertices;
374      currentFrame.numTexVertex = this->header.numTexCoords;
375      currentFrame.numOfFaces = this->header.numTriangles;
[4087]376
[4146]377      currentFrame.pVerts = new CVector3[currentFrame.numOfVerts];
[4087]378
[4146]379      for (j = 0; j < currentFrame.numOfVerts; j++)
[4140]380        {
[4146]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];
[4140]384        }
[4087]385
[4140]386      delete this->pFrames[i].pVertices;
[4087]387
[4140]388      if( likely(i > 0))
389        {
[4146]390          pModel->objectList.push_back(currentFrame);
[4140]391          continue;
392        }
[4087]393                       
[4146]394      currentFrame.pTexVerts = new CVector2[currentFrame.numTexVertex];
395      currentFrame.pFaces = new tFace[currentFrame.numOfFaces];
[4087]396
[4146]397      for(j = 0; j < currentFrame.numTexVertex; j++)
[4140]398        {
[4146]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);
[4140]401        }
[4087]402
[4146]403      for(j = 0; j < currentFrame.numOfFaces; j++)
[4140]404        {
[4146]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];
[4087]408
[4146]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];
[4087]412        }
[4146]413      pModel->objectList.push_back(currentFrame);
[4140]414    }
[4087]415}
416
417
[4076]418/**
[4140]419   \brief this function conputes the normals of the model
420   \param model
[4076]421*/
422void MD2Loader::computeNormals(t3DModel *pModel)
[4148]423{
[4149]424  CVector3 vVector1, vVector2, vNormal, vPoly[3];
[4076]425
[4149]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]);
[4126]433
[4149]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];
[4148]438
[4149]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]];
[4148]445
[4149]446          vVector1 = MathHelp::VectorDiff(vPoly[0], vPoly[2]);         
447          vVector2 = MathHelp::VectorDiff(vPoly[2], vPoly[1]);         
[4148]448                       
[4149]449          vNormal  = MathHelp::CrossProduct(vVector1, vVector2);               
450          pTempNormals[i] = vNormal;                                   
451          vNormal  = MathHelp::NormalizeVector(vNormal);                               
[4148]452
[4149]453          pNormals[i] = vNormal;
454        }
[4148]455
[4149]456      /* now calculating vertex normals */
457      CVector3 vSum = {0.0, 0.0, 0.0};
458      CVector3 vZero = vSum;
459      int shared=0;
[4148]460
[4149]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)
[4148]468                {
[4149]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]);       
[4148]474
[4149]475          vSum = vZero;                                                                 
476          shared = 0;                                                                           
[4148]477        }
[4149]478      delete [] pTempNormals;
479      delete [] pNormals;
480    }
[4148]481}
482
483
[4076]484/**
[4140]485   \brief This function cleans up our allocated memory and closes the file
[4076]486*/
487void MD2Loader::cleanUp()
[4087]488{
[4140]489  fclose(this->pFile);                 
[4087]490       
[4140]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;
[4087]495}
[4172]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{
[4188]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
[4172]627  for(int i = 0; i < this->numFrames; ++i)
628    {
629      verticesList[i][0] = this->pVertices[i + (this->numFrames * this->animationState.currentFrame)][0] * this->scaleFactor;
630      verticesList[i][1] = this->pVertices[i + (this->numFrames * this->animationState.currentFrame)][1] * this->scaleFactor;
631      verticesList[i][2] = this->pVertices[i + (this->numFrames * this->animationState.currentFrame)][2] * this->scaleFactor;
632    }
633}
634
635
636/* hhmmm... id used a very different way to do lightning...*/
637void MD2Model2::processLighting()
638{
[4188]639  shadeDots = anormsDots[ ((int)(md2Angle*(SHADEDOT_QUANT / 360.0)))&(SHADEDOT_QUANT - 1)];
[4172]640}
641
642
643void MD2Model2::renderFrame()
644{
645  static sVec3D verticesList[MD2_MAX_VERTICES]; /* performance: created only once in a lifetime */
646  int* pCommands = this->pGLCommands;
647
648  /* some face culling stuff */
649  glPushAttrib(GL_POLYGON_BIT);
650  glFrontFace(GL_CW);
651  glEnable(GL_CULL_FACE);
652  glCullFace(GL_BACK);
653     
[4188]654  this->processLighting();
[4172]655  this->interpolate(verticesList);
656  this->material->select();
657
658  /* draw the triangles */
659  /* \todo: take int i out of while loop */
660  while( int i = *(pCommands++)) /* strange looking while loop for maximum performance */
661    {
662      if( i < 0)
663        {
664          glBegin(GL_TRIANGLE_FAN);
665          i = -i;
666        }
667      else
668        {
669          glBegin(GL_TRIANGLE_STRIP);
670        }
671
672      for(; i > 0; --i, pCommands += 3) /* down counting for loop, next 3 gl commands */
673        {
674          /* for quake2 lighting */
[4188]675          float l = shadeDots[this->pLightNormals[pCommands[2]]];
[4172]676          //glColor3f(l * lcolor[0], l * lcolor[1], l * lcolor[2]);
677
678          glTexCoord2f( ((float *)pCommands)[0], ((float *)pCommands)[1] );
[4188]679          glNormal3fv(anorms[this->pLightNormals[2]]);
[4172]680          glVertex3fv(verticesList[pCommands[2]]);
681        }
682      glEnd();
683    }
684  glDisable(GL_CULL_FACE);
685  glPopAttrib();
686}
687
Note: See TracBrowser for help on using the repository browser.