Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
May 24, 2005, 11:08:33 AM (19 years ago)
Author:
patrick
Message:

orxonox/trunk: cleaned out the md2 model class, there is now only one model again

File:
1 edited

Legend:

Unmodified
Added
Removed
  • orxonox/trunk/src/lib/graphics/importer/md2Model.cc

    r4246 r4276  
    2828
    2929
    30 sVec3D MD2Model2::anorms[NUM_VERTEX_NORMALS] = {
     30sVec3D MD2Model::anorms[NUM_VERTEX_NORMALS] = {
    3131 #include "anorms.h"
    3232};
    3333
    34 float MD2Model2::anormsDots[SHADEDOT_QUANT][256] = {
     34float MD2Model::anormsDots[SHADEDOT_QUANT][256] = {
    3535  #include "anormtab.h"
    3636};
    3737
    38 static float *shadeDots = MD2Model2::anormsDots[0];
     38static float *shadeDots = MD2Model::anormsDots[0];
    3939
    4040float md2Angle = 0.0f;
    4141
    4242
    43 sAnim MD2Model2::animationList[21] =
     43sAnim MD2Model::animationList[21] =
    4444  {
    4545 // begin, end, fps
     
    6868
    6969
     70
    7071/********************************************************************************
    71  *   MD2MODEL                                                                   *
     72 *   MD2Model2                                                                  *
    7273 ********************************************************************************/
    7374
    74 /**
    75    \brief standard constructor
    76    
    77    creates a new model
    78 */
    79 MD2Model::MD2Model ()
    80 {
    81   this->setClassName ("MD2Model");
    82 
    83   MD2Loader* md2loader = new MD2Loader();
    84   this->model = new t3DModel;
    85   md2loader->importMD2(this->model, ResourceManager::getFullName("models/tris.md2"));
    86   delete md2loader;
    87 }
    88 
    89 
    90 /**
    91    \brief standard deconstructor
    92 
    93 */
    94 MD2Model::~MD2Model ()
    95 {
    96   // delete what has to be deleted here
    97 }
    98 
    99 
    100 void MD2Model::animate()
    101 {
    102   if( unlikely(this->model->objectList.size() <= 0)) return;
    103   /* get current animation from the list */
    104   tAnimationInfo *pAnim = &(this->model->animationList[this->model->currentAnim]);
    105 
    106   int nextFrame = (this->model->currentFrame + 1) % pAnim->endFrame;
    107   if( unlikely(nextFrame == 0))
    108     nextFrame =  pAnim->startFrame;
    109 
    110   t3DObject *pFrame = &this->model->objectList[this->model->currentFrame];
    111   t3DObject *pNextFrame = &this->model->objectList[nextFrame];
    112 
    113   /* we have stored the texture and face information only in the first frame */
    114   t3DObject *pFirstFrame = &this->model->objectList[0];
    115 
    116   /* get the current time as a value in the domain [0..1] :)) */
    117   float t = this->getCurrentTime(this->model, nextFrame);
    118 
    119   glBegin(GL_TRIANGLES);
    120   for(int j = 0; j < pFrame->numOfFaces; j++)
    121     {
    122       for(int whichVertex = 0; whichVertex < 3; whichVertex++)
    123         {
    124           int vertIndex = pFirstFrame->pFaces[j].vertIndex[whichVertex];
    125           int texIndex  = pFirstFrame->pFaces[j].coordIndex[whichVertex];
    126                                                
    127           if( likely(pFirstFrame->pTexVerts != NULL))
    128             {
    129               glTexCoord2f(pFirstFrame->pTexVerts[texIndex].x,
    130                            pFirstFrame->pTexVerts[texIndex].y);
    131             }
    132                        
    133           /* here comes the interpolation part */
    134           CVector3 vPoint1 = pFrame->pVerts[vertIndex];
    135           CVector3 vPoint2 = pNextFrame->pVerts[vertIndex];
    136           glVertex3f(vPoint1.x + t * (vPoint2.x - vPoint1.x),
    137                      vPoint1.y + t * (vPoint2.y - vPoint1.y),
    138                      vPoint1.z + t * (vPoint2.z - vPoint1.z));
    139         }
    140     }
    141   glEnd();
    142 }
    143 
    144 
    145 float MD2Model::getCurrentTime(t3DModel *pModel, int nextFrame)
    146 {
    147   /* stretch the time with animation speed (and make seconds out of it) */
    148   //float t = this->dtS / kAnimationSpeed;
    149        
    150   if ( unlikely(this->localTime*1000.0 >=  1000.0/kAnimationSpeed) )
    151     {
    152       pModel->currentFrame = nextFrame;
    153       this->localTime = 0.0f;
    154     }
    155   return (this->localTime / kAnimationSpeed);
    156 }
    157 
    158 
    159 void MD2Model::tick(float dtS)
    160 {
    161   this->localTime += dtS;
    162 }
    163 
    164 /**
    165    \brief draw function
    166  
    167    these function will take NO argument in the final version, just for testing
    168 */
    169 void MD2Model::draw()
    170 {
    171   if( this->model->objectList.size() <= 0) return;
    172 
    173   t3DObject *pObject = &this->model->objectList[0];
    174   glBegin(GL_TRIANGLES);
    175   for(int j = 0; j < pObject->numOfFaces; j++)
    176     {
    177       for(int whichVertex = 0; whichVertex < 3; whichVertex++)
    178         {
    179           int index = pObject->pFaces[j].vertIndex[whichVertex];
    180           int index2 = pObject->pFaces[j].coordIndex[whichVertex];
    181           /* we invert the normals since the md2 file format uses different style */
    182           /* FIX FIX FIX: ther are actualy no reasons to compute the normals every frame: change this later*/
    183           glNormal3f(-pObject->pNormals[index].x, -pObject->pNormals[index].y, -pObject->pNormals[index].z);
    184 
    185           if( likely(pObject->pTexVerts != NULL))
    186             {
    187               glTexCoord2f(pObject->pTexVerts[index2].x, pObject->pTexVerts[index2].y);
    188             }
    189           glVertex3f(pObject->pVerts[index].x, pObject->pVerts[index].y, pObject->pVerts[index].z);
    190         }
    191     }
    192   glEnd();
    193 }
    194 
    195 /********************************************************************************
    196  *   MD2LOADER                                                                  *
    197  ********************************************************************************/
    198 
    199 /**
    200    \brief standard deconstructor
    201    creates a new model loader
    202 */
    203 MD2Loader::MD2Loader()
    204 {
    205   this->setClassName ("MD2Loader");
    206   /* initialize all data to initial state */
    207   memset(&this->header, 0, sizeof(tMd2Header));
    208   this->pSkins = NULL;
    209   this->pTexCoords = NULL;
    210   this->pTriangles = NULL;
    211   this->pFrames = NULL;
    212 }
    213 
    214 /**
    215    \brief standard deconstructor
    216 */
    217 MD2Loader::~MD2Loader()
    218 {}
    219  
    220 
    221 /**
    222    \brief this is called by the client to open the .Md2 file, read it, then clean up
    223    \param model to load in
    224    \param file name to load
    225    \param texture name to load
    226 */
    227 bool MD2Loader::importMD2(t3DModel *pModel, char *fileName, char *textureName)
    228 {
    229   this->pFile = fopen(fileName, "rb");
    230   if( unlikely(!pFile))
    231     {
    232       PRINTF(1)("Couldn't open the MD2 File for loading. Exiting.\n");
    233       return false;
    234     }
    235   fread(&this->header, 1, sizeof(tMd2Header), pFile);
    236   /* check for the header version: make sure its a md2 file :) */
    237   if( likely(this->header.version != 8))
    238     {
    239       PRINTF(1)("Couldn't load file %s: invalid file format: stop loading\n", fileName);
    240       return false;
    241     }
    242        
    243   this->readMD2Data();
    244   this->convertDataStructures(pModel);
    245   this->computeNormals(pModel);
    246 
    247   if( likely((int)textureName))
    248     {
    249       tMaterialInfo textureInfo;
    250       strcpy(textureInfo.strFile, textureName);
    251       /* since there is only one texture for a .Md2 file, the ID is always 0 */
    252       textureInfo.texureId = 0;
    253       textureInfo.uTile = 1;
    254       /* we only have 1 material for a model */
    255       pModel->numOfMaterials = 1;
    256       pModel->materialList.push_back(textureInfo);
    257     }
    258        
    259   this->cleanUp();
    260   return true;
    261 }
    262 
    263 
    264 /**
    265    \brief This function reads in all of the model's data, except the animation frames
    266 */
    267 void MD2Loader::readMD2Data()
    268 {
    269   unsigned char buffer[MD2_MAX_FRAMESIZE];
    270   this->pSkins     = new tMd2Skin[this->header.numSkins];
    271   this->pTexCoords = new tMd2TexCoord[this->header.numTexCoords];
    272   this->pTriangles = new tMd2Face[this->header.numTriangles];
    273   this->pFrames    = new tMd2Frame[this->header.numFrames];
    274 
    275   /* we read the skins */
    276   fseek(this->pFile, this->header.offsetSkins, SEEK_SET);
    277   fread(this->pSkins, sizeof(tMd2Skin), this->header.numSkins, this->pFile);
    278   /* read all vertex data */
    279   fseek(this->pFile, this->header.offsetTexCoords, SEEK_SET);
    280   fread(this->pTexCoords, sizeof(tMd2TexCoord), this->header.numTexCoords, this->pFile);
    281   /* read face data for each triangle (normals) */
    282   fseek(this->pFile, this->header.offsetTriangles, SEEK_SET);
    283   fread(this->pTriangles, sizeof(tMd2Face), this->header.numTriangles, this->pFile);
    284   /* reading all frame data */
    285   fseek(this->pFile, this->header.offsetFrames, SEEK_SET);
    286   for( int i = 0; i < this->header.numFrames; i++)
    287     {
    288       tMd2AliasFrame *pFrame = (tMd2AliasFrame *) buffer;
    289       this->pFrames[i].pVertices = new tMd2Triangle [this->header.numVertices];
    290 
    291       /* read the frame animation data */
    292       fread(pFrame, 1, this->header.frameSize, this->pFile);
    293       strcpy(this->pFrames[i].strName, pFrame->name);
    294       tMd2Triangle *pVertices = this->pFrames[i].pVertices;
    295       /*
    296          scale translations, store vertices: since id used a non-opengl xyz notation, we have to swap y and z
    297          and negate z axis
    298       */
    299       for( int j = 0; j < this->header.numVertices; j++)
    300         {
    301           pVertices[j].vertex[0] = pFrame->aliasVertices[j].vertex[0] * pFrame->scale[0] + pFrame->translate[0];
    302           pVertices[j].vertex[2] = -1 * (pFrame->aliasVertices[j].vertex[1] * pFrame->scale[1] + pFrame->translate[1]);
    303           pVertices[j].vertex[1] = pFrame->aliasVertices[j].vertex[2] * pFrame->scale[2] + pFrame->translate[2];
    304 
    305           printf("vertices %i --- %f, %f, %f\n",j, pVertices[j].vertex[0], pVertices[j].vertex[1], pVertices[j].vertex[2]);
    306         }
    307     }
    308 }
    309 
    310 
    311 /**
    312    \brief this function fills in the animation list for each animation by name and frame
    313    \param model
    314 */
    315 void MD2Loader::parseAnimations(t3DModel *pModel)
    316 {
    317   tAnimationInfo animationInfo;
    318   string strLastName = "";
    319 
    320   /* the animation parse process looks a little bit wired: this is because there are no
    321      fix bounds for the animation lengths, so the frames are destingushed using their names
    322      which is normaly composed of <animationname><number>
    323   */
    324 
    325   for(int i = 0; i < pModel->numOfObjects; i++)
    326     {
    327       string strName  = this->pFrames[i].strName;
    328       int frameNum = 0;
    329        
    330       /* erease the frame number from the frame-name */
    331       for(unsigned int j = 0; j < strName.length(); j++)
    332         {
    333           if( isdigit(strName[j]) && j >= strName.length() - 2)
    334             {
    335               frameNum = atoi(&strName[j]);
    336               strName.erase(j, strName.length() - j);
    337               break;
    338             }
    339         }
    340 
    341       printf("current: %s, last: %s\n", strName.c_str(), strLastName.c_str());
    342 
    343       /* animations are sorted through their names: this is how its been done: */
    344       if( strName != strLastName || i == pModel->numOfObjects - 1)
    345         {
    346           if( strLastName != "")
    347             {
    348               strcpy(animationInfo.strName, strLastName.c_str());
    349               animationInfo.endFrame = i;
    350               pModel->animationList.push_back(animationInfo);
    351               memset(&animationInfo, 0, sizeof(tAnimationInfo));
    352               pModel->numOfAnimations++;
    353             }
    354           animationInfo.startFrame = frameNum - 1 + i;
    355         }
    356       strLastName = strName;
    357     }
    358 }
    359 
    360 
    361 /**
    362    \brief this function converts the .md2 structures to our own model and object structures: decompress
    363    \param model
    364 */
    365 void MD2Loader::convertDataStructures(t3DModel *pModel)
    366 {
    367   int j = 0, i = 0;
    368        
    369   memset(pModel, 0, sizeof(t3DModel));
    370   pModel->numOfObjects = this->header.numFrames;
    371 
    372   this->parseAnimations(pModel);
    373 
    374   for (i = 0; i < pModel->numOfObjects; i++)
    375     {
    376       t3DObject currentFrame;
    377 
    378       currentFrame.numOfVerts = this->header.numVertices;
    379       currentFrame.numTexVertex = this->header.numTexCoords;
    380       currentFrame.numOfFaces = this->header.numTriangles;
    381 
    382       currentFrame.pVerts = new CVector3[currentFrame.numOfVerts];
    383 
    384       for (j = 0; j < currentFrame.numOfVerts; j++)
    385         {
    386           currentFrame.pVerts[j].x = this->pFrames[i].pVertices[j].vertex[0];
    387           currentFrame.pVerts[j].y = this->pFrames[i].pVertices[j].vertex[1];
    388           currentFrame.pVerts[j].z = this->pFrames[i].pVertices[j].vertex[2];
    389         }
    390 
    391       delete this->pFrames[i].pVertices;
    392 
    393       if( likely(i > 0))
    394         {
    395           pModel->objectList.push_back(currentFrame);
    396           continue;
    397         }
    398                        
    399       currentFrame.pTexVerts = new CVector2[currentFrame.numTexVertex];
    400       currentFrame.pFaces = new tFace[currentFrame.numOfFaces];
    401 
    402       for(j = 0; j < currentFrame.numTexVertex; j++)
    403         {
    404           currentFrame.pTexVerts[j].x = this->pTexCoords[j].u / float(this->header.skinWidth);
    405           currentFrame.pTexVerts[j].y = 1 - this->pTexCoords[j].v / float(this->header.skinHeight);
    406         }
    407 
    408       for(j = 0; j < currentFrame.numOfFaces; j++)
    409         {
    410           currentFrame.pFaces[j].vertIndex[0] = this->pTriangles[j].vertexIndices[0];
    411           currentFrame.pFaces[j].vertIndex[1] = this->pTriangles[j].vertexIndices[1];
    412           currentFrame.pFaces[j].vertIndex[2] = this->pTriangles[j].vertexIndices[2];
    413 
    414           currentFrame.pFaces[j].coordIndex[0] = this->pTriangles[j].textureIndices[0];
    415           currentFrame.pFaces[j].coordIndex[1] = this->pTriangles[j].textureIndices[1];
    416           currentFrame.pFaces[j].coordIndex[2] = this->pTriangles[j].textureIndices[2];
    417         }
    418       pModel->objectList.push_back(currentFrame);
    419     }
    420 }
    421 
    422 
    423 /**
    424    \brief this function conputes the normals of the model
    425    \param model
    426 */
    427 void MD2Loader::computeNormals(t3DModel *pModel)
    428 {
    429   CVector3 vVector1, vVector2, vNormal, vPoly[3];
    430 
    431   if( unlikely(pModel->numOfObjects <= 0))
    432     return;
    433   /* now computing face normals: this means just averaging the vertex normals of a face */
    434   /* so for every object: */
    435   for(int index = 0; index < pModel->numOfObjects; index++)
    436     {
    437       t3DObject *pObject = &(pModel->objectList[index]);
    438 
    439       /* allocate all the memory we need to calculate the normals */
    440       CVector3 *pNormals = new CVector3 [pObject->numOfFaces];
    441       CVector3 *pTempNormals = new CVector3 [pObject->numOfFaces];
    442       pObject->pNormals = new CVector3 [pObject->numOfVerts];
    443 
    444       for(int i=0; i < pObject->numOfFaces; i++)
    445         {
    446           /* cache the points to make coding easier :) */
    447           vPoly[0] = pObject->pVerts[pObject->pFaces[i].vertIndex[0]];
    448           vPoly[1] = pObject->pVerts[pObject->pFaces[i].vertIndex[1]];
    449           vPoly[2] = pObject->pVerts[pObject->pFaces[i].vertIndex[2]];
    450 
    451           vVector1 = MathHelp::VectorDiff(vPoly[0], vPoly[2]);         
    452           vVector2 = MathHelp::VectorDiff(vPoly[2], vPoly[1]);         
    453                        
    454           vNormal  = MathHelp::CrossProduct(vVector1, vVector2);               
    455           pTempNormals[i] = vNormal;                                   
    456           vNormal  = MathHelp::NormalizeVector(vNormal);                               
    457 
    458           pNormals[i] = vNormal;
    459         }
    460 
    461       /* now calculating vertex normals */
    462       CVector3 vSum = {0.0, 0.0, 0.0};
    463       CVector3 vZero = vSum;
    464       int shared=0;
    465 
    466       for (int i = 0; i < pObject->numOfVerts; i++)                     
    467         {
    468           for (int j = 0; j < pObject->numOfFaces; j++)
    469             {                                                                                           
    470               if (pObject->pFaces[j].vertIndex[0] == i ||
    471                   pObject->pFaces[j].vertIndex[1] == i ||
    472                   pObject->pFaces[j].vertIndex[2] == i)
    473                 {
    474                   vSum = MathHelp::AddVector(vSum, pTempNormals[j]);
    475                   shared++;                                                                                             }
    476             }     
    477           pObject->pNormals[i] = MathHelp::DivideVectorByScaler(vSum, float(-shared));
    478           pObject->pNormals[i] = MathHelp::NormalizeVector(pObject->pNormals[i]);       
    479 
    480           vSum = vZero;                                                                 
    481           shared = 0;                                                                           
    482         }
    483       delete [] pTempNormals;
    484       delete [] pNormals;
    485     }
    486 }
    487 
    488 
    489 /**
    490    \brief This function cleans up our allocated memory and closes the file
    491 */
    492 void MD2Loader::cleanUp()
    493 {
    494   fclose(this->pFile);                 
    495        
    496   if( this->pSkins) delete [] this->pSkins;             
    497   if( this->pTexCoords) delete this->pTexCoords;
    498   if( this->pTriangles) delete this->pTriangles;
    499   if( this->pFrames) delete this->pFrames;
    500 }
    501 
    502 
    503 /********************************************************************************
    504  *   MD2LOADER2                                                                 *
    505  ********************************************************************************/
    506 
    507 MD2Model2::MD2Model2()
     75MD2Model::MD2Model()
    50876{
    50977  this->pVertices = NULL;
     
    52290
    52391
    524 MD2Model2::~MD2Model2()
     92MD2Model::~MD2Model()
    52593{
    52694  delete [] this->pVertices;
     
    53199
    532100
    533 bool MD2Model2::loadModel(const char* fileName)
     101bool MD2Model::loadModel(const char* fileName)
    534102{
    535103  FILE *pFile;                            //file stream
     
    596164
    597165
    598 bool MD2Model2::loadSkin(const char* fileName)
    599 {
     166bool MD2Model::loadSkin(const char* fileName)
     167{
     168  this->skinFileName = new char[strlen(fileName)+1];
     169  strcpy(this->skinFileName, fileName);
    600170  this->material = new Material("md2ModelTest");
    601171  this->material->setDiffuseMap(fileName);
     
    611181   saving of data anyway
    612182*/
    613 void MD2Model2::interpolate(sVec3D* verticesList)
     183void MD2Model::interpolate(sVec3D* verticesList)
    614184{
    615185  sVec3D* currVec;
     
    628198
    629199
    630 void MD2Model2::setAnim(int type)
     200void MD2Model::setAnim(int type)
    631201{
    632202  if( (type < 0) || (type > MAX_ANIMATIONS) )
     
    646216
    647217
    648 void MD2Model2::animate()
     218void MD2Model::animate()
    649219{
    650220  if( this->animationState.localTime - this->animationState.lastTime > (1.0f / this->animationState.fps))
     
    669239
    670240/* hhmmm... id used a very different way to do lightning... */
    671 void MD2Model2::processLighting()
     241void MD2Model::processLighting()
    672242{
    673243  shadeDots = anormsDots[((int)(md2Angle*(SHADEDOT_QUANT / 360.0)))&(SHADEDOT_QUANT - 1)];
     
    675245
    676246
    677 void MD2Model2::tick(float time)
     247void MD2Model::tick(float time)
    678248{
    679249  this->animationState.localTime += time;
     
    681251
    682252
    683 void MD2Model2::draw()
     253void MD2Model::draw()
    684254{
    685255  if( likely(this->animationState.localTime > 0.0))
     
    691261
    692262  glPopMatrix();
    693 }
    694 
    695 
    696 void MD2Model2::renderFrame()
     263} 
     264
     265
     266void MD2Model::renderFrame()
    697267{
    698268  static sVec3D verticesList[MD2_MAX_VERTICES]; /* performance: created only once in a lifetime */
     
    735305
    736306
    737 void MD2Model2::debug()
    738 {
    739   PRINT(0)("==========================| MD2Model2::debug() |===\n");
     307void MD2Model::debug()
     308{
     309  PRINT(0)("==========================| MD2Model::debug() |===\n");
    740310  PRINT(0)("=  Model FileName:\t%s\n", this->fileName);
     311  PRINT(0)("=  Skin FileName:\t%s\n", this->skinFileName);
    741312  PRINT(0)("=  Size in Memory:\t%i Bytes\n", this->header->frameSize * this->header->numFrames + 64); // 64bytes is the header size
    742313  PRINT(0)("=  Number of Vertices:\t%i\n", this->header->numVertices);
Note: See TracChangeset for help on using the changeset viewer.