Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/branches/md2_loader: some minor changes in the graphics engine fps function

File size: 8.3 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
22#include "list.h"
23
24
25using namespace std;
26
27/********************************************************************************
28 *   MD2MODEL                                                                   *
29 ********************************************************************************/
30
31/**
32   \brief standard constructor
33   
34        creates a new model
35*/
36MD2Model::MD2Model () 
37{
38   this->setClassName ("MD2Model");
39}
40
41
42/**
43   \brief standard deconstructor
44
45*/
46MD2Model::~MD2Model () 
47{
48  // delete what has to be deleted here
49}
50
51
52/********************************************************************************
53 *   MD2LOADER                                                                  *
54 ********************************************************************************/
55
56/**
57   \brief standard deconstructor
58        creates a new model loader
59*/
60MD2Loader::MD2Loader()
61{
62   this->setClassName ("MD2Loader");
63   /* initialize all data to initial state */
64   memset(&this->header, 0, sizeof(tMd2Header));
65   this->pSkins = NULL;
66   this->pTexCoords = NULL;
67   this->pTriangles = NULL;
68   this->pFrames = NULL;
69}
70
71/**
72   \brief standard deconstructor
73*/
74MD2Loader::~MD2Loader()
75{}
76 
77
78/**
79        \brief this is called by the client to open the .Md2 file, read it, then clean up
80        \param model to load in
81        \param file name to load
82        \param texture name to load
83*/
84bool MD2Loader::importMD2(t3DModel *pModel, char *fileName, char *textureName)
85{
86        this->pFile = fopen(fileName, "rb");
87        if( unlikely(!pFile)) 
88        {
89                PRINTF(1)("Couldn't open the MD2 File for loading. Exiting.\n");
90                return false;
91        }
92        fread(&this->header, 1, sizeof(tMd2Header), pFile);
93        /* check for the header version: make sure its a md2 file :) */
94        if( likely(this->header.version != 8))
95        {
96                PRINTF(1)("Couldn't load file %s: invalid file format: stop loading\n", fileName);
97                return false;
98        }
99       
100        this->readMD2Data();
101        this->convertDataStructures(pModel);
102
103        if( likely((int)textureName))
104        {
105                tMaterialInfo* textureInfo = new tMaterialInfo;
106                strcpy(textureInfo->strFile, textureName);
107                /* since there is only one texture for a .Md2 file, the ID is always 0 */
108                textureInfo->texureId = 0;
109                textureInfo->uTile = 1;
110                /* we only have 1 material for a model */
111                pModel->numOfMaterials = 1;
112                pModel->materialList->add(textureInfo);
113        }
114       
115        this->cleanUp();
116        return true;
117}
118
119/**
120        \brief This function reads in all of the model's data, except the animation frames
121*/
122void MD2Loader::readMD2Data()
123{
124        unsigned char buffer[MD2_MAX_FRAMESIZE];
125        this->pSkins     = new tMd2Skin[this->header.numSkins];
126        this->pTexCoords = new tMd2TexCoord[this->header.numTexCoords];
127        this->pTriangles = new tMd2Face[this->header.numTriangles];
128        this->pFrames    = new tMd2Frame[this->header.numFrames];
129
130        /* we read the skins */
131        fseek(this->pFile, this->header.offsetSkins, SEEK_SET);
132        fread(this->pSkins, sizeof(tMd2Skin), this->header.numSkins, this->pFile);
133        /* read all vertex data */
134        fseek(this->pFile, this->header.offsetTexCoords, SEEK_SET);
135        fread(this->pTexCoords, sizeof(tMd2TexCoord), this->header.numTexCoords, this->pFile);
136        /* read face data for each triangle (normals) */
137        fseek(this->pFile, this->header.offsetTriangles, SEEK_SET);
138        fread(this->pTriangles, sizeof(tMd2Face), this->header.numTriangles, this->pFile);
139        /* reading all frame data */
140        fseek(this->pFile, this->header.offsetFrames, SEEK_SET);
141        for(int i = 0; i < this->header.numFrames; i++)
142        {
143                tMd2AliasFrame *pFrame = (tMd2AliasFrame *) buffer;
144                this->pFrames[i].pVertices = new tMd2Triangle [this->header.numVertices];
145
146                /* read the frame animation data */
147                fread(pFrame, 1, this->header.frameSize, this->pFile);
148                strcpy(this->pFrames[i].strName, pFrame->name);
149                tMd2Triangle *pVertices = this->pFrames[i].pVertices;
150                /*
151                   scale translations, store vertices: since id used a non-opengl xyz notation, we have to swap y and z
152                   and negate z axis
153                */
154                for(int j = 0; j < this->header.numVertices; j++)
155                {
156                        pVertices[j].vertex[0] = pFrame->aliasVertices[j].vertex[0] * pFrame->scale[0] + pFrame->translate[0];
157                        pVertices[j].vertex[2] = -1 * (pFrame->aliasVertices[j].vertex[1] * pFrame->scale[1] + pFrame->translate[1]);
158                        pVertices[j].vertex[1] = pFrame->aliasVertices[j].vertex[2] * pFrame->scale[2] + pFrame->translate[2];
159                }
160        }
161}
162
163/**
164        \brief this function fills in the animation list for each animation by name and frame
165        \param model
166*/
167void MD2Loader::parseAnimations(t3DModel *pModel)
168{
169        tAnimationInfo* animationInfo = new tAnimationInfo;
170        string strLastName = "";
171
172        /* the animation parse process looks a little bit weired: this is because there are no
173           fix bounds for the animation lengths, so the frames are destingushed using their names
174           which is normaly composed of <animationname><number>
175        */
176
177        for(int i = 0; i < pModel->numOfObjects; i++)
178        {
179                string strName  = this->pFrames[i].strName;
180                int frameNum = 0;
181               
182                for(unsigned int j = 0; j < strName.length(); j++)
183                {
184                        if( isdigit(strName[j]) && j >= strName.length() - 2)
185                        {
186                                frameNum = atoi(&strName[j]);
187                                strName.erase(j, strName.length() - j);
188                                break;
189                        }
190                }
191
192                /* animations are sorted through their names: this is how its been done: */
193                if(strName != strLastName || i == pModel->numOfObjects - 1)
194                {
195                        if(strLastName != "")
196                        {
197                                strcpy(animationInfo->strName, strLastName.c_str());
198                                animationInfo->endFrame = i;
199                                pModel->animationList->add(animationInfo);
200                                memset(&animationInfo, 0, sizeof(tAnimationInfo));
201                                pModel->numOfAnimations++;
202                        }
203                        animationInfo->startFrame = frameNum - 1 + i;
204                }
205                strLastName = strName;
206        }
207}
208
209/**
210        \brief this function converts the .md2 structures to our own model and object structures: decompress
211        \param model
212*/
213void MD2Loader::convertDataStructures(t3DModel *pModel)
214{
215        int j = 0, i = 0;
216       
217        memset(pModel, 0, sizeof(t3DModel));
218        pModel->numOfObjects = this->header.numFrames;
219
220        this->parseAnimations(pModel);
221
222        for (i = 0; i < pModel->numOfObjects; i++)
223        {
224                t3DObject* currentFrame = new t3DObject;
225
226                currentFrame->numOfVerts = this->header.numVertices;
227                currentFrame->numTexVertex = this->header.numTexCoords;
228                currentFrame->numOfFaces = this->header.numTriangles;
229
230                currentFrame->pVerts = new CVector3[currentFrame->numOfVerts];
231
232                for (j = 0; j < currentFrame->numOfVerts; j++)
233                {
234                        currentFrame->pVerts[j].x = this->pFrames[i].pVertices[j].vertex[0];
235                        currentFrame->pVerts[j].y = this->pFrames[i].pVertices[j].vertex[1];
236                        currentFrame->pVerts[j].z = this->pFrames[i].pVertices[j].vertex[2];
237                }
238
239                delete this->pFrames[i].pVertices;
240
241                if( likely(i > 0))
242                {
243                        pModel->objectList->add(currentFrame);
244                        continue;
245                }
246                       
247                currentFrame->pTexVerts = new CVector2[currentFrame->numTexVertex];
248                currentFrame->pFaces = new tFace[currentFrame->numOfFaces];
249
250                for(j = 0; j < currentFrame->numTexVertex; j++)
251                {
252                        currentFrame->pTexVerts[j].x = this->pTexCoords[j].u / float(this->header.skinWidth);
253                        currentFrame->pTexVerts[j].y = 1 - this->pTexCoords[j].v / float(this->header.skinHeight);
254                }
255
256                for(j = 0; j < currentFrame->numOfFaces; j++)
257                {
258                        currentFrame->pFaces[j].vertIndex[0] = this->pTriangles[j].vertexIndices[0];
259                        currentFrame->pFaces[j].vertIndex[1] = this->pTriangles[j].vertexIndices[1];
260                        currentFrame->pFaces[j].vertIndex[2] = this->pTriangles[j].vertexIndices[2];
261
262                        currentFrame->pFaces[j].coordIndex[0] = this->pTriangles[j].textureIndices[0];
263                        currentFrame->pFaces[j].coordIndex[1] = this->pTriangles[j].textureIndices[1];
264                        currentFrame->pFaces[j].coordIndex[2] = this->pTriangles[j].textureIndices[2];
265                }
266                pModel->objectList->add(currentFrame);
267        }
268}
269
270
271/**
272        \brief this function conputes the normals of the model
273        \param model
274*/
275void MD2Loader::computeNormals(t3DModel *pModel)
276{}
277
278
279/**
280        \brief This function cleans up our allocated memory and closes the file
281*/
282void MD2Loader::cleanUp()
283{
284        fclose(this->pFile);                   
285       
286        if( this->pSkins) delete [] this->pSkins;               
287        if( this->pTexCoords) delete this->pTexCoords;
288        if( this->pTriangles) delete this->pTriangles;
289        if( this->pFrames) delete this->pFrames;
290}
Note: See TracBrowser for help on using the repository browser.