Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/md2_loader: altered some vector functions and wiped out most of the compiler errors. still remaining one link error.

File size: 11.5 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"
18
[4079]19#include <fstream>
[4082]20#include <string>
[4142]21#include <vector>
[4079]22
[4080]23
[4065]24using namespace std;
25
[4077]26/********************************************************************************
27 *   MD2MODEL                                                                   *
28 ********************************************************************************/
[4065]29
30/**
31   \brief standard constructor
[4076]32   
[4140]33   creates a new model
[4065]34*/
35MD2Model::MD2Model () 
36{
[4140]37  this->setClassName ("MD2Model");
[4065]38}
39
40
41/**
42   \brief standard deconstructor
43
44*/
45MD2Model::~MD2Model () 
46{
47  // delete what has to be deleted here
48}
[4076]49
[4138]50/**
[4140]51   \brief draw function
[4138]52 
[4140]53   these function will take NO argument in the final version, just for testing
[4138]54*/
55void MD2Model::draw(t3DModel *pModel)
56{
[4146]57  if( pModel->objectList.size() <= 0) return;
[4076]58
[4146]59  t3DObject *pObject = &pModel->objectList[0];
[4140]60  glBegin(GL_TRIANGLES);
61  for(int j = 0; j < pObject->numOfFaces; j++)
62    {
63      for(int whichVertex = 0; whichVertex < 3; whichVertex++)
64        {
[4147]65          printf("now drawing vertex %i of face nr: %i\n", whichVertex, j);
[4140]66          int index = pObject->pFaces[j].vertIndex[whichVertex];
67          int index2 = pObject->pFaces[j].coordIndex[whichVertex];
[4147]68          printf("using index: %i, %i\n", index, index2);
[4140]69          /* we invert the normals since the md2 file format uses different style */
[4147]70          glNormal3f(-pObject->pNormals[index].x, -pObject->pNormals[index].y, -pObject->pNormals[index].z);
71
72          if( pObject->pTexVerts) 
[4140]73            {
74              glTexCoord2f(pObject->pTexVerts[ index2 ].x, pObject->pTexVerts[ index2 ].y);
75            }
76          glVertex3f(pObject->pVerts[ index ].x, pObject->pVerts[ index ].y, pObject->pVerts[ index ].z);
77        }
78    }
79  glEnd();
[4138]80}
81
[4077]82/********************************************************************************
83 *   MD2LOADER                                                                  *
84 ********************************************************************************/
85
[4076]86/**
87   \brief standard deconstructor
[4140]88   creates a new model loader
[4076]89*/
90MD2Loader::MD2Loader()
[4077]91{
[4140]92  this->setClassName ("MD2Loader");
93  /* initialize all data to initial state */
94  memset(&this->header, 0, sizeof(tMd2Header));
95  this->pSkins = NULL;
96  this->pTexCoords = NULL;
97  this->pTriangles = NULL;
98  this->pFrames = NULL;
[4077]99}
[4076]100
101/**
102   \brief standard deconstructor
103*/
104MD2Loader::~MD2Loader()
105{}
106 
107
108/**
[4140]109   \brief this is called by the client to open the .Md2 file, read it, then clean up
110   \param model to load in
111   \param file name to load
112   \param texture name to load
[4076]113*/
[4079]114bool MD2Loader::importMD2(t3DModel *pModel, char *fileName, char *textureName)
115{
[4140]116  this->pFile = fopen(fileName, "rb");
117  if( unlikely(!pFile)) 
118    {
119      PRINTF(1)("Couldn't open the MD2 File for loading. Exiting.\n");
120      return false;
121    }
122  fread(&this->header, 1, sizeof(tMd2Header), pFile);
123  /* check for the header version: make sure its a md2 file :) */
124  if( likely(this->header.version != 8))
125    {
126      PRINTF(1)("Couldn't load file %s: invalid file format: stop loading\n", fileName);
127      return false;
128    }
[4079]129       
[4140]130  this->readMD2Data();
131  this->convertDataStructures(pModel);
[4079]132
[4140]133  if( likely((int)textureName))
134    {
[4146]135      tMaterialInfo textureInfo;
136      strcpy(textureInfo.strFile, textureName);
[4140]137      /* since there is only one texture for a .Md2 file, the ID is always 0 */
[4146]138      textureInfo.texureId = 0;
139      textureInfo.uTile = 1;
[4140]140      /* we only have 1 material for a model */
141      pModel->numOfMaterials = 1;
[4146]142      pModel->materialList.push_back(textureInfo);
[4140]143    }
[4079]144       
[4140]145  this->cleanUp();
146  return true;
[4079]147}
148
[4076]149/**
[4140]150   \brief This function reads in all of the model's data, except the animation frames
[4076]151*/
152void MD2Loader::readMD2Data()
[4080]153{
[4140]154  unsigned char buffer[MD2_MAX_FRAMESIZE];
155  this->pSkins     = new tMd2Skin[this->header.numSkins];
156  this->pTexCoords = new tMd2TexCoord[this->header.numTexCoords];
157  this->pTriangles = new tMd2Face[this->header.numTriangles];
158  this->pFrames    = new tMd2Frame[this->header.numFrames];
[4076]159
[4140]160  /* we read the skins */
161  fseek(this->pFile, this->header.offsetSkins, SEEK_SET);
162  fread(this->pSkins, sizeof(tMd2Skin), this->header.numSkins, this->pFile);
163  /* read all vertex data */
164  fseek(this->pFile, this->header.offsetTexCoords, SEEK_SET);
165  fread(this->pTexCoords, sizeof(tMd2TexCoord), this->header.numTexCoords, this->pFile);
166  /* read face data for each triangle (normals) */
167  fseek(this->pFile, this->header.offsetTriangles, SEEK_SET);
168  fread(this->pTriangles, sizeof(tMd2Face), this->header.numTriangles, this->pFile);
169  /* reading all frame data */
170  fseek(this->pFile, this->header.offsetFrames, SEEK_SET);
[4147]171  for( int i = 0; i < this->header.numFrames; i++)
[4140]172    {
173      tMd2AliasFrame *pFrame = (tMd2AliasFrame *) buffer;
174      this->pFrames[i].pVertices = new tMd2Triangle [this->header.numVertices];
175
176      /* read the frame animation data */
177      fread(pFrame, 1, this->header.frameSize, this->pFile);
178      strcpy(this->pFrames[i].strName, pFrame->name);
179      tMd2Triangle *pVertices = this->pFrames[i].pVertices;
180      /*
181         scale translations, store vertices: since id used a non-opengl xyz notation, we have to swap y and z
182         and negate z axis
183      */
[4147]184      for( int j = 0; j < this->header.numVertices; j++)
[4080]185        {
[4140]186          pVertices[j].vertex[0] = pFrame->aliasVertices[j].vertex[0] * pFrame->scale[0] + pFrame->translate[0];
187          pVertices[j].vertex[2] = -1 * (pFrame->aliasVertices[j].vertex[1] * pFrame->scale[1] + pFrame->translate[1]);
188          pVertices[j].vertex[1] = pFrame->aliasVertices[j].vertex[2] * pFrame->scale[2] + pFrame->translate[2];
[4080]189        }
[4140]190    }
[4080]191}
192
[4076]193/**
[4140]194   \brief this function fills in the animation list for each animation by name and frame
195   \param model
[4076]196*/
197void MD2Loader::parseAnimations(t3DModel *pModel)
[4082]198{
[4146]199  tAnimationInfo animationInfo;
[4140]200  string strLastName = "";
[4076]201
[4141]202  /* the animation parse process looks a little bit wired: this is because there are no
[4140]203     fix bounds for the animation lengths, so the frames are destingushed using their names
204     which is normaly composed of <animationname><number>
205  */
[4082]206
[4140]207  for(int i = 0; i < pModel->numOfObjects; i++)
208    {
209      string strName  = this->pFrames[i].strName;
210      int frameNum = 0;
[4141]211       
212      /* erease the frame number from the frame-name */
[4140]213      for(unsigned int j = 0; j < strName.length(); j++)
[4082]214        {
[4140]215          if( isdigit(strName[j]) && j >= strName.length() - 2)
216            {
217              frameNum = atoi(&strName[j]);
218              strName.erase(j, strName.length() - j);
219              break;
220            }
221        }
[4082]222
[4141]223      printf("current: %s, last: %s\n", strName.c_str(), strLastName.c_str());
224
[4140]225      /* animations are sorted through their names: this is how its been done: */
[4141]226      if( strName != strLastName || i == pModel->numOfObjects - 1)
[4140]227        {
[4141]228          if( strLastName != "")
[4140]229            {
[4146]230              strcpy(animationInfo.strName, strLastName.c_str());
231              animationInfo.endFrame = i;
232              pModel->animationList.push_back(animationInfo);
[4140]233              memset(&animationInfo, 0, sizeof(tAnimationInfo));
234              pModel->numOfAnimations++;
235            }
[4146]236          animationInfo.startFrame = frameNum - 1 + i;
[4082]237        }
[4140]238      strLastName = strName;
239    }
[4082]240}
241
[4076]242/**
[4140]243   \brief this function converts the .md2 structures to our own model and object structures: decompress
244   \param model
[4076]245*/
246void MD2Loader::convertDataStructures(t3DModel *pModel)
[4087]247{
[4140]248  int j = 0, i = 0;
[4087]249       
[4140]250  memset(pModel, 0, sizeof(t3DModel));
251  pModel->numOfObjects = this->header.numFrames;
[4076]252
[4140]253  this->parseAnimations(pModel);
[4076]254
[4140]255  for (i = 0; i < pModel->numOfObjects; i++)
256    {
[4146]257      t3DObject currentFrame;
[4087]258
[4146]259      currentFrame.numOfVerts = this->header.numVertices;
260      currentFrame.numTexVertex = this->header.numTexCoords;
261      currentFrame.numOfFaces = this->header.numTriangles;
[4087]262
[4146]263      currentFrame.pVerts = new CVector3[currentFrame.numOfVerts];
[4087]264
[4146]265      for (j = 0; j < currentFrame.numOfVerts; j++)
[4140]266        {
[4146]267          currentFrame.pVerts[j].x = this->pFrames[i].pVertices[j].vertex[0];
268          currentFrame.pVerts[j].y = this->pFrames[i].pVertices[j].vertex[1];
269          currentFrame.pVerts[j].z = this->pFrames[i].pVertices[j].vertex[2];
[4140]270        }
[4087]271
[4140]272      delete this->pFrames[i].pVertices;
[4087]273
[4140]274      if( likely(i > 0))
275        {
[4146]276          pModel->objectList.push_back(currentFrame);
[4140]277          continue;
278        }
[4087]279                       
[4146]280      currentFrame.pTexVerts = new CVector2[currentFrame.numTexVertex];
281      currentFrame.pFaces = new tFace[currentFrame.numOfFaces];
[4087]282
[4146]283      for(j = 0; j < currentFrame.numTexVertex; j++)
[4140]284        {
[4146]285          currentFrame.pTexVerts[j].x = this->pTexCoords[j].u / float(this->header.skinWidth);
286          currentFrame.pTexVerts[j].y = 1 - this->pTexCoords[j].v / float(this->header.skinHeight);
[4140]287        }
[4087]288
[4146]289      for(j = 0; j < currentFrame.numOfFaces; j++)
[4140]290        {
[4146]291          currentFrame.pFaces[j].vertIndex[0] = this->pTriangles[j].vertexIndices[0];
292          currentFrame.pFaces[j].vertIndex[1] = this->pTriangles[j].vertexIndices[1];
293          currentFrame.pFaces[j].vertIndex[2] = this->pTriangles[j].vertexIndices[2];
[4087]294
[4146]295          currentFrame.pFaces[j].coordIndex[0] = this->pTriangles[j].textureIndices[0];
296          currentFrame.pFaces[j].coordIndex[1] = this->pTriangles[j].textureIndices[1];
297          currentFrame.pFaces[j].coordIndex[2] = this->pTriangles[j].textureIndices[2];
[4087]298        }
[4146]299      pModel->objectList.push_back(currentFrame);
[4140]300    }
[4087]301}
302
303
[4076]304/**
[4140]305   \brief this function conputes the normals of the model
306   \param model
[4076]307*/
308void MD2Loader::computeNormals(t3DModel *pModel)
[4148]309{
310        CVector3 vVector1, vVector2, vNormal, vPoly[3];
[4076]311
[4148]312        if( unlikely(pModel->numOfObjects <= 0))
313                return;
314        /* now computing face normals: this means just averaging the vertex normals of a face */
315        /* so for every object: */
316        for(int index = 0; index < pModel->numOfObjects; index++)
317        {
318                t3DObject *pObject = &(pModel->objectList[index]);
[4126]319
[4148]320                /* allocate all the memory we need to calculate the normals */
321                CVector3 *pNormals = new CVector3 [pObject->numOfFaces];
322                CVector3 *pTempNormals = new CVector3 [pObject->numOfFaces];
323                pObject->pNormals = new CVector3 [pObject->numOfVerts];
324
325                for(int i=0; i < pObject->numOfFaces; i++)
326                {
327                    /* cache the points to make coding easier :) */
328                        vPoly[0] = pObject->pVerts[pObject->pFaces[i].vertIndex[0]];
329                        vPoly[1] = pObject->pVerts[pObject->pFaces[i].vertIndex[1]];
330                        vPoly[2] = pObject->pVerts[pObject->pFaces[i].vertIndex[2]];
331
332                        vVector1 = VectorDiff(vPoly[0], vPoly[2]);             
333                        vVector2 = VectorDiff(vPoly[2], vPoly[1]);             
334                       
335                        vNormal  = CrossProduct(vVector1, vVector2);           
336                        pTempNormals[i] = vNormal;                                     
337                        vNormal  = NormalizeVector(vNormal);                           
338
339                        pNormals[i] = vNormal;
340                }
341
342                /* now calculating vertex normals */
343                CVector3 vSum = {0.0, 0.0, 0.0};
344                CVector3 vZero = vSum;
345                int shared=0;
346
347                for (i = 0; i < pObject->numOfVerts; i++)                       
348                {
349                        for (int j = 0; j < pObject->numOfFaces; j++)   
350                        {                                                                                               
351                                        if (pObject->pFaces[j].vertIndex[0] == i || 
352                                        pObject->pFaces[j].vertIndex[1] == i || 
353                                        pObject->pFaces[j].vertIndex[2] == i)
354                                {
355                                        vSum = AddVector(vSum, pTempNormals[j]);
356                                        shared++;                                                                                               }
357                        }     
358                        pObject->pNormals[i] = DivideVectorByScaler(vSum, float(-shared));
359                        pObject->pNormals[i] = NormalizeVector(pObject->pNormals[i]);   
360
361                        vSum = vZero;                                                                   
362                        shared = 0;                                                                             
363                }
364                delete [] pTempNormals;
365                delete [] pNormals;
366        }
367}
368
369
[4076]370/**
[4140]371   \brief This function cleans up our allocated memory and closes the file
[4076]372*/
373void MD2Loader::cleanUp()
[4087]374{
[4140]375  fclose(this->pFile);                 
[4087]376       
[4140]377  if( this->pSkins) delete [] this->pSkins;             
378  if( this->pTexCoords) delete this->pTexCoords;
379  if( this->pTriangles) delete this->pTriangles;
380  if( this->pFrames) delete this->pFrames;
[4087]381}
Note: See TracBrowser for help on using the repository browser.