Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/md2_loader: fixed a problem in the loading process

File size: 24.0 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  {
[4224]43 // begin, end, fps
[4188]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
[4077]68/********************************************************************************
69 *   MD2MODEL                                                                   *
70 ********************************************************************************/
[4065]71
72/**
73   \brief standard constructor
[4076]74   
[4140]75   creates a new model
[4065]76*/
77MD2Model::MD2Model () 
78{
[4140]79  this->setClassName ("MD2Model");
[4168]80
81  MD2Loader* md2loader = new MD2Loader();
82  this->model = new t3DModel;
83  md2loader->importMD2(this->model, "../data/models/tris.md2");
[4169]84  delete md2loader;
[4065]85}
86
87
88/**
89   \brief standard deconstructor
90
91*/
92MD2Model::~MD2Model () 
93{
94  // delete what has to be deleted here
95}
[4076]96
[4161]97
[4168]98void MD2Model::animate()
[4161]99{
[4168]100  if( unlikely(this->model->objectList.size() <= 0)) return;
[4162]101  /* get current animation from the list */
[4168]102  tAnimationInfo *pAnim = &(this->model->animationList[this->model->currentAnim]);
[4161]103
[4168]104  int nextFrame = (this->model->currentFrame + 1) % pAnim->endFrame;
[4162]105  if( unlikely(nextFrame == 0)) 
106    nextFrame =  pAnim->startFrame;
[4161]107
[4168]108  t3DObject *pFrame = &this->model->objectList[this->model->currentFrame];
109  t3DObject *pNextFrame = &this->model->objectList[nextFrame];
[4161]110
[4162]111  /* we have stored the texture and face information only in the first frame */
[4168]112  t3DObject *pFirstFrame = &this->model->objectList[0];
[4161]113
[4162]114  /* get the current time as a value in the domain [0..1] :)) */
[4168]115  float t = this->getCurrentTime(this->model, nextFrame);
[4161]116
[4162]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];
[4161]124                                               
[4162]125          if( likely(pFirstFrame->pTexVerts != NULL)) 
126            {
[4168]127              glTexCoord2f(pFirstFrame->pTexVerts[texIndex].x, 
128                           pFirstFrame->pTexVerts[texIndex].y);
[4162]129            }
[4161]130                       
[4162]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();
[4161]140}
141
142
[4162]143float MD2Model::getCurrentTime(t3DModel *pModel, int nextFrame)
[4161]144{
[4162]145  /* stretch the time with animation speed (and make seconds out of it) */
[4163]146  //float t = this->dtS / kAnimationSpeed;
[4161]147       
[4163]148  if ( unlikely(this->localTime*1000.0 >=  1000.0/kAnimationSpeed) )
149    {
[4162]150      pModel->currentFrame = nextFrame;
[4163]151      this->localTime = 0.0f;
152    }
[4168]153  return (this->localTime / kAnimationSpeed);
[4161]154}
155
[4162]156
157void MD2Model::tick(float dtS)
158{
[4163]159  this->localTime += dtS;
[4162]160}
161
[4138]162/**
[4140]163   \brief draw function
[4138]164 
[4140]165   these function will take NO argument in the final version, just for testing
[4138]166*/
[4168]167void MD2Model::draw()
[4138]168{
[4168]169  if( this->model->objectList.size() <= 0) return;
[4076]170
[4168]171  t3DObject *pObject = &this->model->objectList[0];
[4140]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 */
[4150]180          /* FIX FIX FIX: ther are actualy no reasons to compute the normals every frame: change this later*/
[4147]181          glNormal3f(-pObject->pNormals[index].x, -pObject->pNormals[index].y, -pObject->pNormals[index].z);
182
[4158]183          if( likely(pObject->pTexVerts != NULL)) 
[4140]184            {
[4158]185              glTexCoord2f(pObject->pTexVerts[index2].x, pObject->pTexVerts[index2].y);
[4140]186            }
[4158]187          glVertex3f(pObject->pVerts[index].x, pObject->pVerts[index].y, pObject->pVerts[index].z);
[4140]188        }
189    }
190  glEnd();
[4138]191}
192
[4077]193/********************************************************************************
194 *   MD2LOADER                                                                  *
195 ********************************************************************************/
196
[4076]197/**
198   \brief standard deconstructor
[4140]199   creates a new model loader
[4076]200*/
201MD2Loader::MD2Loader()
[4077]202{
[4140]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;
[4077]210}
[4076]211
212/**
213   \brief standard deconstructor
214*/
215MD2Loader::~MD2Loader()
216{}
217 
218
219/**
[4140]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
[4076]224*/
[4079]225bool MD2Loader::importMD2(t3DModel *pModel, char *fileName, char *textureName)
226{
[4140]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    }
[4079]240       
[4140]241  this->readMD2Data();
242  this->convertDataStructures(pModel);
[4150]243  this->computeNormals(pModel);
[4079]244
[4140]245  if( likely((int)textureName))
246    {
[4146]247      tMaterialInfo textureInfo;
248      strcpy(textureInfo.strFile, textureName);
[4140]249      /* since there is only one texture for a .Md2 file, the ID is always 0 */
[4146]250      textureInfo.texureId = 0;
251      textureInfo.uTile = 1;
[4140]252      /* we only have 1 material for a model */
253      pModel->numOfMaterials = 1;
[4146]254      pModel->materialList.push_back(textureInfo);
[4140]255    }
[4079]256       
[4140]257  this->cleanUp();
258  return true;
[4079]259}
260
[4157]261
[4076]262/**
[4140]263   \brief This function reads in all of the model's data, except the animation frames
[4076]264*/
265void MD2Loader::readMD2Data()
[4080]266{
[4140]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];
[4076]272
[4140]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);
[4147]284  for( int i = 0; i < this->header.numFrames; i++)
[4140]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      */
[4147]297      for( int j = 0; j < this->header.numVertices; j++)
[4080]298        {
[4140]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];
[4225]302
303          printf("vertices %i --- %f, %f, %f\n",j, pVertices[j].vertex[0], pVertices[j].vertex[1], pVertices[j].vertex[2]);
[4080]304        }
[4140]305    }
[4080]306}
307
[4157]308
[4076]309/**
[4140]310   \brief this function fills in the animation list for each animation by name and frame
311   \param model
[4076]312*/
313void MD2Loader::parseAnimations(t3DModel *pModel)
[4082]314{
[4146]315  tAnimationInfo animationInfo;
[4140]316  string strLastName = "";
[4076]317
[4141]318  /* the animation parse process looks a little bit wired: this is because there are no
[4140]319     fix bounds for the animation lengths, so the frames are destingushed using their names
320     which is normaly composed of <animationname><number>
321  */
[4082]322
[4140]323  for(int i = 0; i < pModel->numOfObjects; i++)
324    {
325      string strName  = this->pFrames[i].strName;
326      int frameNum = 0;
[4141]327       
328      /* erease the frame number from the frame-name */
[4140]329      for(unsigned int j = 0; j < strName.length(); j++)
[4082]330        {
[4140]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        }
[4082]338
[4141]339      printf("current: %s, last: %s\n", strName.c_str(), strLastName.c_str());
340
[4140]341      /* animations are sorted through their names: this is how its been done: */
[4141]342      if( strName != strLastName || i == pModel->numOfObjects - 1)
[4140]343        {
[4141]344          if( strLastName != "")
[4140]345            {
[4146]346              strcpy(animationInfo.strName, strLastName.c_str());
347              animationInfo.endFrame = i;
348              pModel->animationList.push_back(animationInfo);
[4140]349              memset(&animationInfo, 0, sizeof(tAnimationInfo));
350              pModel->numOfAnimations++;
351            }
[4146]352          animationInfo.startFrame = frameNum - 1 + i;
[4082]353        }
[4140]354      strLastName = strName;
355    }
[4082]356}
357
[4157]358
[4076]359/**
[4140]360   \brief this function converts the .md2 structures to our own model and object structures: decompress
361   \param model
[4076]362*/
363void MD2Loader::convertDataStructures(t3DModel *pModel)
[4087]364{
[4140]365  int j = 0, i = 0;
[4087]366       
[4140]367  memset(pModel, 0, sizeof(t3DModel));
368  pModel->numOfObjects = this->header.numFrames;
[4076]369
[4140]370  this->parseAnimations(pModel);
[4076]371
[4140]372  for (i = 0; i < pModel->numOfObjects; i++)
373    {
[4146]374      t3DObject currentFrame;
[4087]375
[4146]376      currentFrame.numOfVerts = this->header.numVertices;
377      currentFrame.numTexVertex = this->header.numTexCoords;
378      currentFrame.numOfFaces = this->header.numTriangles;
[4087]379
[4146]380      currentFrame.pVerts = new CVector3[currentFrame.numOfVerts];
[4087]381
[4146]382      for (j = 0; j < currentFrame.numOfVerts; j++)
[4140]383        {
[4146]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];
[4140]387        }
[4087]388
[4140]389      delete this->pFrames[i].pVertices;
[4087]390
[4140]391      if( likely(i > 0))
392        {
[4146]393          pModel->objectList.push_back(currentFrame);
[4140]394          continue;
395        }
[4087]396                       
[4146]397      currentFrame.pTexVerts = new CVector2[currentFrame.numTexVertex];
398      currentFrame.pFaces = new tFace[currentFrame.numOfFaces];
[4087]399
[4146]400      for(j = 0; j < currentFrame.numTexVertex; j++)
[4140]401        {
[4146]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);
[4140]404        }
[4087]405
[4146]406      for(j = 0; j < currentFrame.numOfFaces; j++)
[4140]407        {
[4146]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];
[4087]411
[4146]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];
[4087]415        }
[4146]416      pModel->objectList.push_back(currentFrame);
[4140]417    }
[4087]418}
419
420
[4076]421/**
[4140]422   \brief this function conputes the normals of the model
423   \param model
[4076]424*/
425void MD2Loader::computeNormals(t3DModel *pModel)
[4148]426{
[4149]427  CVector3 vVector1, vVector2, vNormal, vPoly[3];
[4076]428
[4149]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]);
[4126]436
[4149]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];
[4148]441
[4149]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]];
[4148]448
[4149]449          vVector1 = MathHelp::VectorDiff(vPoly[0], vPoly[2]);         
450          vVector2 = MathHelp::VectorDiff(vPoly[2], vPoly[1]);         
[4148]451                       
[4149]452          vNormal  = MathHelp::CrossProduct(vVector1, vVector2);               
453          pTempNormals[i] = vNormal;                                   
454          vNormal  = MathHelp::NormalizeVector(vNormal);                               
[4148]455
[4149]456          pNormals[i] = vNormal;
457        }
[4148]458
[4149]459      /* now calculating vertex normals */
460      CVector3 vSum = {0.0, 0.0, 0.0};
461      CVector3 vZero = vSum;
462      int shared=0;
[4148]463
[4149]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)
[4148]471                {
[4149]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]);       
[4148]477
[4149]478          vSum = vZero;                                                                 
479          shared = 0;                                                                           
[4148]480        }
[4149]481      delete [] pTempNormals;
482      delete [] pNormals;
483    }
[4148]484}
485
486
[4076]487/**
[4140]488   \brief This function cleans up our allocated memory and closes the file
[4076]489*/
490void MD2Loader::cleanUp()
[4087]491{
[4140]492  fclose(this->pFile);                 
[4087]493       
[4140]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;
[4087]498}
[4172]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;
[4224]516  this->scaleFactor = 0.001f;
[4172]517
[4214]518  this->setAnim(STAND);
[4172]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  tMd2Header header;
535  char* buffer;                           //buffer for frame data
536  sFrame* frame;                          //temp frame
537  sVec3D *pVertex;
538  int* pNormals;
539
540  pFile = fopen(fileName, "rb");
541  if( unlikely(!pFile)) 
542    {
543      PRINTF(1)("Couldn't open the MD2 File for loading. Exiting.\n");
544      return false;
545    }
546  fread(&header, 1, sizeof(tMd2Header), pFile);
547  /* check for the header version: make sure its a md2 file :) */
548  if( unlikely(header.version != MD2_VERSION) && unlikely(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  /* got the data: map it to locals */
555  this->numFrames = header.numFrames;
556  this->numVertices = header.numVertices;
[4224]557  this->numTriangles = header.numTriangles;
[4172]558  this->numGLCommands = header.numGlCommands;
559  /* allocate memory for the data storage */
560  this->pVertices = new sVec3D[this->numVertices * this->numFrames];
561  this->pGLCommands = new int[this->numGLCommands];
562  this->pLightNormals = new int[this->numVertices * this->numFrames];
563  buffer = new char[this->numFrames * header.frameSize];
564
565  /* read frame data from the file to a temp buffer */
566  fseek(pFile, header.offsetFrames, SEEK_SET);
567  fread(buffer, header.frameSize, this->numFrames, pFile);
568  /* read opengl commands */
569  fseek(pFile, header.offsetGlCommands, SEEK_SET);
570  fread(this->pGLCommands, sizeof(int), this->numGLCommands, pFile);
571
572  for(int i = 0; i < this->numFrames; ++i)
573    {
[4212]574      /*
575        faster but evt. buggy
[4172]576      frame = (sFrame*)(buffer + header.frameSize * i);
577      pVertex = this->pVertices + this->numVertices  * i;
578      pNormals = this->pLightNormals + this->numVertices * i;
[4212]579      */
580      frame = (sFrame *)&buffer[header.frameSize * i];
581      pVertex = &this->pVertices[this->numVertices * i];
582      pNormals = &this->pLightNormals[this->numVertices * i];
[4172]583
584      for(int j = 0; j < this->numVertices; ++j)
585        {
586          /* SPEEDUP: *(pVerts + i + 0) = (*(frame->pVertices + i + 0)...  */
[4225]587          pVertex[j][0] = (frame->pVertices[j].v[0] * frame->scale[0]) + frame->translate[0];
588          pVertex[j][1] = (frame->pVertices[j].v[1] * frame->scale[1]) + frame->translate[1];
589          pVertex[j][2] = (frame->pVertices[j].v[2] * frame->scale[2]) + frame->translate[2];
590         
591          printf("pVertex %f, %f, %f\n", pVertex[j][0], pVertex[j][1], pVertex[j][2]);
[4172]592
[4225]593          pNormals[j] = frame->pVertices[j].lightNormalIndex;
[4172]594        }
595    }
596
597  delete [] buffer;
598  fclose(pFile);
599}
600
601
602bool MD2Model2::loadSkin(const char* fileName)
603{
604  this->material = new Material("md2ModelTest");
605  this->material->setDiffuseMap(fileName);
606  this->material->setIllum(3);
607  this->material->setAmbient(1.0, 1.0, 1.0);
608}
609
610
611/**
612   \brief initializes an array of vert with the current frame scaled vertices
613
614   we won't use the pVertices array directly, since its much easier and we need
615   saving of data anyway
616*/
617void MD2Model2::interpolate(sVec3D* verticesList)
618{
[4188]619  sVec3D* currVec;
620  sVec3D* nextVec;
621
622  currVec = &this->pVertices[this->numVertices * this->animationState.currentFrame];
[4212]623  nextVec = &this->pVertices[this->numVertices * this->animationState.nextFrame];
[4188]624
[4224]625    printf("currVec: %f, %f, %f\n", currVec[0][0], currVec[0][1], currVec[0][2]);
626    printf("nextVec: %f, %f, %f\n", nextVec[0][0], nextVec[1][1], nextVec[2][2]);
[4212]627 
[4224]628    printf("numFrames: %i\n", this->numFrames);
629    printf("currentFrame: %i\n", this->animationState.currentFrame);
[4189]630
[4224]631    //for(int i = 0; i < this->numFrames; ++i)
632    for(int i = 0; i < this->numVertices; ++i)
633      { 
634        /*
635        verticesList[i][0] = this->pVertices[i + (this->numFrames * this->animationState.currentFrame)][0] * this->scaleFactor;
636        verticesList[i][1] = this->pVertices[i + (this->numFrames * this->animationState.currentFrame)][1] * this->scaleFactor;
637        verticesList[i][2] = this->pVertices[i + (this->numFrames * this->animationState.currentFrame)][2] * this->scaleFactor;
638        */
639
640
641        verticesList[i][0] = (currVec[i][0] + this->animationState.interpolationState * (nextVec[i][0] - currVec[i][0])) * this->scaleFactor;
642        verticesList[i][1] = (currVec[i][1] + this->animationState.interpolationState * (nextVec[i][1] - currVec[i][1])) * this->scaleFactor;
643        verticesList[i][2] = (currVec[i][2] + this->animationState.interpolationState * (nextVec[i][2] - currVec[i][2])) * this->scaleFactor;
644
645
646        //printf("  pVertices %f, %f, %f\n", pVertices[i][0], pVertices[i][1], pVertices[i][2]);
647        //printf("  list:     %f, %f, %f \n", verticesList[i][0], verticesList[i][1], verticesList[i][2]);     
648      }
[4172]649}
650
651
[4211]652void MD2Model2::setAnim(int type)
653{
654  if( (type < 0) || (type > MAX_ANIMATIONS) )
655    type = 0;
[4224]656
657this->animationState.startFrame = animationList[type].firstFrame;
658this->animationState.endFrame = animationList[type].lastFrame;
659this->animationState.nextFrame = animationList[type].firstFrame + 1;
660this->animationState.fps = animationList[type].fps;
661this->animationState.type = type;
662
663this->animationState.interpolationState = 0.0;
664this->animationState.localTime = 0.0;
665this->animationState.lastTime = 0.0;
666this->animationState.currentFrame = animationList[type].firstFrame;
[4211]667}
668
669
[4213]670void MD2Model2::animate()
[4211]671{
672  if( this->animationState.localTime - this->animationState.lastTime > (1.0f / this->animationState.fps))
673    {
674      this->animationState.currentFrame = this->animationState.nextFrame;
675      this->animationState.nextFrame++;
676     
677      if( this->animationState.nextFrame > this->animationState.endFrame)
678        this->animationState.nextFrame = this->animationState.startFrame;
679      this->animationState.lastTime = this->animationState.localTime;
680    }
681
682  if( this->animationState.currentFrame > (this->numFrames - 1) )
683    this->animationState.currentFrame = 0;
684  if( this->animationState.nextFrame > (this->numFrames - 1) )
685    this->animationState.nextFrame = 0;
686
687  this->animationState.interpolationState = this->animationState.fps * 
688    (this->animationState.localTime - this->animationState.lastTime);
689}
690
691
[4224]692/* hhmmm... id used a very different way to do lightning... */
[4172]693void MD2Model2::processLighting()
694{
[4189]695  shadeDots = anormsDots[((int)(md2Angle*(SHADEDOT_QUANT / 360.0)))&(SHADEDOT_QUANT - 1)];
[4172]696}
697
[4224]698
[4214]699void MD2Model2::tick(float time)
700{
701  this->animationState.localTime += time;
702}
[4172]703
[4214]704
705void MD2Model2::draw()
706{
707  if( likely(this->animationState.localTime > 0.0))
708    this->animate();
709
710  glPushMatrix();
711  /* rotate because id software uses another orientation then the openGL default */
712  /* \todo: rotate the axis already when loading... easy :) */
713  glRotatef(-90.0, 1.0, 0.0, 0.0);
714  glRotatef(-90.0, 0.0, 0.0, 1.0);
715
716  this->renderFrame();
717
718  glPopMatrix();
719}
720
721
[4224]722void MD2Model2::draw2()
723{
724  glBegin(GL_TRIANGLES);
725  for(int j = 0; j < this->numTriangles; j++)
726    {
727      for(int whichVertex = 0; whichVertex < 3; whichVertex++)
728        {
729          /*
730          int index = pObject->pFaces[j].vertIndex[whichVertex];
731          int index2 = pObject->pFaces[j].coordIndex[whichVertex];
732          glNormal3f(-pObject->pNormals[index].x, -pObject->pNormals[index].y, -pObject->pNormals[index].z);
733         
734          if( likely(pObject->pTexVerts != NULL))
735            {
736              glTexCoord2f(pObject->pTexVerts[index2].x, pObject->pTexVerts[index2].y);
737            }
738          glVertex3f(pObject->pVerts[index].x, pObject->pVerts[index].y, pObject->pVerts[index].z);
739          */
740        }
741    }
742  glEnd();
743}
744
745
[4172]746void MD2Model2::renderFrame()
747{
748  static sVec3D verticesList[MD2_MAX_VERTICES]; /* performance: created only once in a lifetime */
749  int* pCommands = this->pGLCommands;
750
751  /* some face culling stuff */
[4214]752  glPushAttrib(GL_POLYGON_BIT);
753  glFrontFace(GL_CW);
754  glEnable(GL_CULL_FACE);
755  glCullFace(GL_BACK);
[4172]756     
[4188]757  this->processLighting();
[4212]758  this->interpolate(verticesList);
[4172]759  this->material->select();
760
761  /* draw the triangles */
762  /* \todo: take int i out of while loop */
[4224]763  while( false /*int i = *(pCommands++)*/) /* strange looking while loop for maximum performance */
[4172]764    {
[4224]765      int i;
[4172]766      if( i < 0)
767        {
768          glBegin(GL_TRIANGLE_FAN);
769          i = -i;
770        }
771      else
772        {
773          glBegin(GL_TRIANGLE_STRIP);
774        }
775
[4215]776      for(; i > 0; i--, pCommands += 3) /* down counting for loop, next 3 gl commands */
[4172]777        {
778          /* for quake2 lighting */
[4214]779          //float l = shadeDots[this->pLightNormals[pCommands[2]]];
[4172]780          //glColor3f(l * lcolor[0], l * lcolor[1], l * lcolor[2]);
781
[4215]782          glNormal3fv(anorms[this->pLightNormals[pCommands[2]]]);
[4172]783          glTexCoord2f( ((float *)pCommands)[0], ((float *)pCommands)[1] );
784          glVertex3fv(verticesList[pCommands[2]]);
[4224]785
[4225]786          printf("draw vert: %f, %f, %f\n", verticesList[pCommands[2]][0], verticesList[pCommands[2]][1], verticesList[pCommands[2]][2] );
[4172]787        }
788      glEnd();
789    }
[4214]790  glDisable(GL_CULL_FACE);
791  glPopAttrib();
[4172]792}
793
Note: See TracBrowser for help on using the repository browser.