Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/physics/src/lib/graphics/importer/md2Model.cc @ 4283

Last change on this file since 4283 was 4283, checked in by bensch, 19 years ago

orxonox/branches/physics: merged the trunk back to branches/physics
merged with command
svn merge -r 4223:HEAD ../../trunk/ .
conflicts additively included

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