Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/lib/graphics/importer/md2Model.cc @ 4279

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

orxonox/trunk: changed header struct name, fixed windows compile problem (definition of point animation)

File size: 9.2 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#include "material.h"
19
20#include "resource_manager.h"
21
22#include <fstream>
23
24
25
26using namespace std;
27
28
29sVec3D MD2Model::anorms[NUM_VERTEX_NORMALS] = {
30 #include "anorms.h"
31};
32
33float MD2Model::anormsDots[SHADEDOT_QUANT][256] = {
34  #include "anormtab.h"
35};
36
37static float *shadeDots = MD2Model::anormsDots[0];
38
39float md2Angle = 0.0f;
40
41
42sAnim MD2Model::animationList[21] =
43  {
44 // begin, end, fps
45    {   0,  39,  9 },   // STAND
46    {  40,  45, 10 },   // RUN
47    {  46,  53, 10 },   // ATTACK
48    {  54,  57,  7 },   // PAIN_A
49    {  58,  61,  7 },   // PAIN_B
50    {  62,  65,  7 },   // PAIN_C
51    {  66,  71,  7 },   // JUMP
52    {  72,  83,  7 },   // FLIP
53    {  84,  94,  7 },   // SALUTE
54    {  95, 111, 10 },   // FALLBACK
55    { 112, 122,  7 },   // WAVE
56    { 123, 134,  6 },   // POINTT
57    { 135, 153, 10 },   // CROUCH_STAND
58    { 154, 159,  7 },   // CROUCH_WALK
59    { 160, 168, 10 },   // CROUCH_ATTACK
60    { 196, 172,  7 },   // CROUCH_PAIN
61    { 173, 177,  5 },   // CROUCH_DEATH
62    { 178, 183,  7 },   // DEATH_FALLBACK
63    { 184, 189,  7 },   // DEATH_FALLFORWARD
64    { 190, 197,  7 },   // DEATH_FALLBACKSLOW
65    { 198, 198,  5 },   // BOOM
66  };
67
68
69
70/********************************************************************************
71 *   MD2Model2                                                                  *
72 ********************************************************************************/
73
74MD2Model::MD2Model()
75{
76  this->pVertices = NULL;
77  this->pGLCommands = NULL;
78  this->pLightNormals = NULL; 
79
80  this->numFrames = 0;
81  this->numVertices = 0;
82  this->numGLCommands = 0;
83 
84  this->scaleFactor = 1.0f;
85
86  this->setAnim(BOOM);
87}
88
89
90MD2Model::~MD2Model()
91{
92  delete [] this->pVertices;
93  delete [] this->pGLCommands;
94  delete [] this->pLightNormals;
95}
96
97
98
99bool MD2Model::loadModel(const char* fileName)
100{
101  FILE *pFile;                            //file stream
102  char* buffer;                           //buffer for frame data
103  sFrame* frame;                          //temp frame
104  sVec3D *pVertex;
105  int* pNormals;
106
107  pFile = fopen(fileName, "rb");
108  if( unlikely(!pFile)) 
109    {
110      PRINTF(1)("Couldn't open the MD2 File for loading. Exiting.\n");
111      return false;
112    }
113  this->header = new MD2Header;
114  fread(this->header, 1, sizeof(MD2Header), pFile);
115  /* check for the header version: make sure its a md2 file :) */
116  if( unlikely(this->header->version != MD2_VERSION) && unlikely(this->header->ident != MD2_IDENT))
117    {
118      PRINTF(1)("Couldn't load file %s: invalid file format: stop loading\n", fileName);
119      return false;
120    }
121
122  this->fileName = new char[strlen(fileName)+1];
123  strcpy(this->fileName, fileName);
124  /* got the data: map it to locals */
125  this->numFrames = this->header->numFrames;
126  this->numVertices = this->header->numVertices;
127  this->numTriangles = this->header->numTriangles;
128  this->numGLCommands = this->header->numGlCommands;
129  /* allocate memory for the data storage */
130  this->pVertices = new sVec3D[this->numVertices * this->numFrames];
131  this->pGLCommands = new int[this->numGLCommands];
132  this->pLightNormals = new int[this->numVertices * this->numFrames];
133  buffer = new char[this->numFrames * this->header->frameSize];
134
135  /* read frame data from the file to a temp buffer */
136  fseek(pFile, this->header->offsetFrames, SEEK_SET);
137  fread(buffer, this->header->frameSize, this->numFrames, pFile);
138  /* read opengl commands */
139  fseek(pFile, this->header->offsetGlCommands, SEEK_SET);
140  fread(this->pGLCommands, sizeof(int), this->numGLCommands, pFile);
141
142  for(int i = 0; i < this->numFrames; ++i)
143    {
144      frame = (sFrame*)(buffer + this->header->frameSize * i); 
145      pVertex = this->pVertices + this->numVertices  * i;
146      pNormals = this->pLightNormals + this->numVertices * i;
147
148      for(int j = 0; j < this->numVertices; ++j)
149        {
150          /* SPEEDUP: *(pVerts + i + 0) = (*(frame->pVertices + i + 0)...  */
151          pVertex[j][0] = (frame->pVertices[j].v[0] * frame->scale[0]) + frame->translate[0];
152          pVertex[j][1] = (frame->pVertices[j].v[2] * frame->scale[2]) + frame->translate[2];
153          pVertex[j][2] = -1.0 * (frame->pVertices[j].v[1] * frame->scale[1] + frame->translate[1]);
154         
155          pNormals[j] = frame->pVertices[j].lightNormalIndex;
156        }
157    }
158
159  delete [] buffer;
160  fclose(pFile);
161}
162
163
164bool MD2Model::loadSkin(const char* fileName)
165{
166  this->skinFileName = new char[strlen(fileName)+1];
167  strcpy(this->skinFileName, fileName);
168  this->material = new Material("md2ModelTest");
169  this->material->setDiffuseMap(fileName);
170  this->material->setIllum(3);
171  this->material->setAmbient(1.0, 1.0, 1.0);
172}
173
174
175/**
176   \brief initializes an array of vert with the current frame scaled vertices
177
178   we won't use the pVertices array directly, since its much easier and we need
179   saving of data anyway
180*/
181void MD2Model::interpolate(sVec3D* verticesList)
182{
183  sVec3D* currVec;
184  sVec3D* nextVec;
185
186  currVec = &this->pVertices[this->numVertices * this->animationState.currentFrame];
187  nextVec = &this->pVertices[this->numVertices * this->animationState.nextFrame];
188
189  for(int i = 0; i < this->numFrames; ++i)
190    {
191      verticesList[i][0] = (currVec[i][0] + this->animationState.interpolationState * (nextVec[i][0] - currVec[i][0])) * this->scaleFactor;
192      verticesList[i][1] = (currVec[i][1] + this->animationState.interpolationState * (nextVec[i][1] - currVec[i][1])) * this->scaleFactor;
193      verticesList[i][2] = (currVec[i][2] + this->animationState.interpolationState * (nextVec[i][2] - currVec[i][2])) * this->scaleFactor;
194    }
195}
196
197
198void MD2Model::setAnim(int type)
199{
200  if( (type < 0) || (type > MAX_ANIMATIONS) )
201    type = 0;
202
203  this->animationState.startFrame = animationList[type].firstFrame;
204  this->animationState.endFrame = animationList[type].lastFrame;
205  this->animationState.nextFrame = animationList[type].firstFrame + 1;
206  this->animationState.fps = animationList[type].fps;
207  this->animationState.type = type;
208 
209  this->animationState.interpolationState = 0.0;
210  this->animationState.localTime = 0.0;
211  this->animationState.lastTime = 0.0;
212  this->animationState.currentFrame = animationList[type].firstFrame;
213}
214
215
216void MD2Model::animate()
217{
218  if( this->animationState.localTime - this->animationState.lastTime > (1.0f / this->animationState.fps))
219    {
220      this->animationState.currentFrame = this->animationState.nextFrame;
221      this->animationState.nextFrame++;
222     
223      if( this->animationState.nextFrame > this->animationState.endFrame)
224        this->animationState.nextFrame = this->animationState.startFrame;
225      this->animationState.lastTime = this->animationState.localTime;
226    }
227
228  if( this->animationState.currentFrame > (this->numFrames - 1) )
229    this->animationState.currentFrame = 0;
230  if( this->animationState.nextFrame > (this->numFrames - 1) )
231    this->animationState.nextFrame = 0;
232
233  this->animationState.interpolationState = this->animationState.fps * 
234    (this->animationState.localTime - this->animationState.lastTime);
235}
236
237
238/* hhmmm... id used a very different way to do lightning... */
239void MD2Model::processLighting()
240{
241  shadeDots = anormsDots[((int)(md2Angle*(SHADEDOT_QUANT / 360.0)))&(SHADEDOT_QUANT - 1)];
242}
243
244
245void MD2Model::tick(float time)
246{
247  this->animationState.localTime += time;
248}
249
250
251void MD2Model::draw()
252{
253  if( likely(this->animationState.localTime > 0.0))
254    this->animate();
255
256  glPushMatrix();
257
258  this->renderFrame();
259
260  glPopMatrix();
261} 
262
263
264void MD2Model::renderFrame()
265{
266  static sVec3D verticesList[MD2_MAX_VERTICES]; /* performance: created only once in a lifetime */
267  int* pCommands = this->pGLCommands;
268
269  /* some face culling stuff */
270  glPushAttrib(GL_POLYGON_BIT);
271  glFrontFace(GL_CW);
272  glEnable(GL_CULL_FACE);
273  glCullFace(GL_BACK);
274     
275  this->processLighting();
276  this->interpolate(verticesList);
277  this->material->select();
278
279  /* draw the triangles */
280  while( int i = *(pCommands++)) /* strange looking while loop for maximum performance */
281    {
282      if( i < 0)
283        {
284          glBegin(GL_TRIANGLE_FAN);
285          i = -i;
286        }
287      else
288        {
289          glBegin(GL_TRIANGLE_STRIP);
290        }
291
292      for(; i > 0; i--, pCommands += 3) /* down counting for loop, next 3 gl commands */
293        {
294          glNormal3fv(anorms[this->pLightNormals[pCommands[2]]]);
295          glTexCoord2f( ((float *)pCommands)[0], 1.0-((float *)pCommands)[1] );
296          glVertex3fv(verticesList[pCommands[2]]);
297        }
298      glEnd();
299    }
300  glDisable(GL_CULL_FACE);
301  glPopAttrib();
302}
303
304
305void MD2Model::debug()
306{
307  PRINT(0)("==========================| MD2Model::debug() |===\n");
308  PRINT(0)("=  Model FileName:\t%s\n", this->fileName);
309  PRINT(0)("=  Skin FileName:\t%s\n", this->skinFileName);
310  PRINT(0)("=  Size in Memory:\t%i Bytes\n", this->header->frameSize * this->header->numFrames + 64); // 64bytes is the header size
311  PRINT(0)("=  Number of Vertices:\t%i\n", this->header->numVertices);
312  PRINT(0)("=  Number of Frames: \t%i\n", this->header->numFrames);
313  PRINT(0)("=  Height, Width\t\t%i, %i\n", this->header->skinHeight, this->header->skinWidth);
314  PRINT(0)("===================================================\n\n");
315}
Note: See TracBrowser for help on using the repository browser.