Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/md2_loader: some debug information outpur, code beautifullizer

File size: 9.7 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Patrick Boenzli
13*/
14
15#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_IMPORTER
16
17#include "md2Model.h"
18
19#include <fstream>
20#include <string>
21#include <vector>
22
23
24using namespace std;
25
26/********************************************************************************
27 *   MD2MODEL                                                                   *
28 ********************************************************************************/
29
30/**
31   \brief standard constructor
32   
33   creates a new model
34*/
35MD2Model::MD2Model () 
36{
37  this->setClassName ("MD2Model");
38}
39
40
41/**
42   \brief standard deconstructor
43
44*/
45MD2Model::~MD2Model () 
46{
47  // delete what has to be deleted here
48}
49
50/**
51   \brief draw function
52 
53   these function will take NO argument in the final version, just for testing
54*/
55void MD2Model::draw(t3DModel *pModel)
56{
57  if( pModel->objectList.size() <= 0) return;
58
59  t3DObject *pObject = &pModel->objectList[0];
60  glBegin(GL_TRIANGLES);
61  for(int j = 0; j < pObject->numOfFaces; j++)
62    {
63      for(int whichVertex = 0; whichVertex < 3; whichVertex++)
64        {
65          printf("now drawing vertex %i of face nr: %i\n", whichVertex, j);
66          int index = pObject->pFaces[j].vertIndex[whichVertex];
67          int index2 = pObject->pFaces[j].coordIndex[whichVertex];
68          printf("using index: %i, %i\n", index, index2);
69          /* we invert the normals since the md2 file format uses different style */
70          glNormal3f(-pObject->pNormals[index].x, -pObject->pNormals[index].y, -pObject->pNormals[index].z);
71
72          if( pObject->pTexVerts) 
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();
80}
81
82/********************************************************************************
83 *   MD2LOADER                                                                  *
84 ********************************************************************************/
85
86/**
87   \brief standard deconstructor
88   creates a new model loader
89*/
90MD2Loader::MD2Loader()
91{
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;
99}
100
101/**
102   \brief standard deconstructor
103*/
104MD2Loader::~MD2Loader()
105{}
106 
107
108/**
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
113*/
114bool MD2Loader::importMD2(t3DModel *pModel, char *fileName, char *textureName)
115{
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    }
129       
130  this->readMD2Data();
131  this->convertDataStructures(pModel);
132
133  if( likely((int)textureName))
134    {
135      tMaterialInfo textureInfo;
136      strcpy(textureInfo.strFile, textureName);
137      /* since there is only one texture for a .Md2 file, the ID is always 0 */
138      textureInfo.texureId = 0;
139      textureInfo.uTile = 1;
140      /* we only have 1 material for a model */
141      pModel->numOfMaterials = 1;
142      pModel->materialList.push_back(textureInfo);
143    }
144       
145  this->cleanUp();
146  return true;
147}
148
149/**
150   \brief This function reads in all of the model's data, except the animation frames
151*/
152void MD2Loader::readMD2Data()
153{
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];
159
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);
171  for( int i = 0; i < this->header.numFrames; i++)
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      */
184      for( int j = 0; j < this->header.numVertices; j++)
185        {
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];
189        }
190    }
191}
192
193/**
194   \brief this function fills in the animation list for each animation by name and frame
195   \param model
196*/
197void MD2Loader::parseAnimations(t3DModel *pModel)
198{
199  tAnimationInfo animationInfo;
200  string strLastName = "";
201
202  /* the animation parse process looks a little bit wired: this is because there are no
203     fix bounds for the animation lengths, so the frames are destingushed using their names
204     which is normaly composed of <animationname><number>
205  */
206
207  for(int i = 0; i < pModel->numOfObjects; i++)
208    {
209      string strName  = this->pFrames[i].strName;
210      int frameNum = 0;
211       
212      /* erease the frame number from the frame-name */
213      for(unsigned int j = 0; j < strName.length(); j++)
214        {
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        }
222
223      printf("current: %s, last: %s\n", strName.c_str(), strLastName.c_str());
224
225      /* animations are sorted through their names: this is how its been done: */
226      if( strName != strLastName || i == pModel->numOfObjects - 1)
227        {
228          if( strLastName != "")
229            {
230              strcpy(animationInfo.strName, strLastName.c_str());
231              animationInfo.endFrame = i;
232              pModel->animationList.push_back(animationInfo);
233              memset(&animationInfo, 0, sizeof(tAnimationInfo));
234              pModel->numOfAnimations++;
235            }
236          animationInfo.startFrame = frameNum - 1 + i;
237        }
238      strLastName = strName;
239    }
240}
241
242/**
243   \brief this function converts the .md2 structures to our own model and object structures: decompress
244   \param model
245*/
246void MD2Loader::convertDataStructures(t3DModel *pModel)
247{
248  int j = 0, i = 0;
249       
250  memset(pModel, 0, sizeof(t3DModel));
251  pModel->numOfObjects = this->header.numFrames;
252
253  this->parseAnimations(pModel);
254
255  for (i = 0; i < pModel->numOfObjects; i++)
256    {
257      t3DObject currentFrame;
258
259      currentFrame.numOfVerts = this->header.numVertices;
260      currentFrame.numTexVertex = this->header.numTexCoords;
261      currentFrame.numOfFaces = this->header.numTriangles;
262
263      currentFrame.pVerts = new CVector3[currentFrame.numOfVerts];
264
265      for (j = 0; j < currentFrame.numOfVerts; j++)
266        {
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];
270        }
271
272      delete this->pFrames[i].pVertices;
273
274      if( likely(i > 0))
275        {
276          pModel->objectList.push_back(currentFrame);
277          continue;
278        }
279                       
280      currentFrame.pTexVerts = new CVector2[currentFrame.numTexVertex];
281      currentFrame.pFaces = new tFace[currentFrame.numOfFaces];
282
283      for(j = 0; j < currentFrame.numTexVertex; j++)
284        {
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);
287        }
288
289      for(j = 0; j < currentFrame.numOfFaces; j++)
290        {
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];
294
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];
298        }
299      pModel->objectList.push_back(currentFrame);
300    }
301}
302
303
304/**
305   \brief this function conputes the normals of the model
306   \param model
307*/
308void MD2Loader::computeNormals(t3DModel *pModel)
309{}
310
311
312/**
313   \brief This function cleans up our allocated memory and closes the file
314*/
315void MD2Loader::cleanUp()
316{
317  fclose(this->pFile);                 
318       
319  if( this->pSkins) delete [] this->pSkins;             
320  if( this->pTexCoords) delete this->pTexCoords;
321  if( this->pTriangles) delete this->pTriangles;
322  if( this->pFrames) delete this->pFrames;
323}
Note: See TracBrowser for help on using the repository browser.