Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/bsp_model/src/lib/graphics/importer/md3/md3_model.cc @ 8562

Last change on this file since 8562 was 8562, checked in by patrick, 18 years ago

bsp: md3 mesh drawing functions introduced

File size: 13.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 "md3_model.h"
18
19#include "md3_data.h"
20#include "md3_mesh.h"
21#include "md3_tag.h"
22#include "md3_bone_frame.h"
23
24#include "md3_animation_cfg.h"
25
26#include "material.h"
27#include "quaternion.h"
28
29#include "debug.h"
30
31namespace md3
32{
33
34  /**
35   * md3 model
36   */
37  MD3Model::MD3Model(std::string filename, float scaling)
38  {
39    this->md3Data = new MD3Data(filename, filename, scaling);
40
41    MD3AnimationCfg cfg("/home/boenzlip/tmp/q3/Downloads/MOH/q3mdl-alien3/models/players/alien3/animation.cfg");
42
43    this->tmpBoneFrame = new MD3BoneFrame();
44    this->tmpMesh = new sVec3D[2048];          //!< the temporary mesh, hopefully newer bigger than 2048 vertices
45    this->tmpNormal = new MD3Normal[2048];     //!< the temporary normals
46  }
47
48
49
50  MD3Model::~MD3Model()
51  {
52    delete this->tmpBoneFrame;
53    delete [] this->tmpMesh;
54  }
55
56
57
58  /**
59   * this draws the md3 model
60   */
61  void MD3Model::draw()
62  {
63    //draw current bone frame
64    this->draw(this->md3Data);
65
66    PRINTF(0)("draw\n");
67  }
68
69
70  /**
71   * draw the md3model
72   * @param data: the data to be drawn
73   */
74  void MD3Model::draw(MD3Data* data)
75  {
76
77    // draw the bones if needed
78    if( this->bDrawBones)
79    {
80      // get bone frame, interpolate if necessary
81      if( data->animationState.interpolationFraction != 0.0 &&
82          data->animationState.currentFrame != data->animationState.nextFrame) {
83        //interpolate bone frame
84        this->drawBoneFrame(this->interpolateBoneFrame(data->boneFrames[data->animationState.currentFrame],
85                            data->boneFrames[data->animationState.nextFrame],
86                            data->animationState.interpolationFraction));
87      }
88      else {
89        //stick with current bone frame
90        this->drawBoneFrame(data->boneFrames[data->animationState.currentFrame]);
91      }
92    }
93
94
95    //draw all meshes of current frame of this model
96    for( int i = 0;  i < data->meshNum; i++)
97    {
98      MD3Mesh* mesh = data->meshes[i];
99
100//       gl.glBlendFunc(mesh.GLSrcBlendFunc, mesh.GLDstBlendFunc);
101//       gl.glDepthMask(mesh.GLDepthMask);
102
103      if( mesh->header->textureNum > 0 && &mesh->material[0] != NULL)
104        mesh->material[0].select();
105
106      // get mesh frame, do interpolation if necessary
107      sVec3D* frame;
108      if( data->animationState.interpolationFraction != 0.0 &&
109          data->animationState.currentFrame != data->animationState.nextFrame) {
110        //interpolate mesh frame between the 2 current mesh frames
111//         frame = this->interpolateMeshFrame(mesh, data->animationState.currentFrame, data->animationState.nextFrame,
112//                                            data->animationState.interpolationFraction);
113        frame = this->interpolateMeshFrame( data->meshes[data->animationState.currentFrame]->meshFrames,
114                                            data->meshes[data->animationState.nextFrame]->meshFrames,
115                                            data->animationState.interpolationFraction, mesh);
116      }
117      else {
118        //no interpolation needed, just draw current frame
119        frame = &mesh->meshFrames[data->animationState.currentFrame];
120      }
121
122      this->drawMesh(mesh, frame);
123
124
125      // draw vertex normals if needed
126      if( this->bDrawNormals) {
127        // get vertex normals, interpolate if necessary
128        if( data->animationState.interpolationFraction != 0.0 &&
129            data->animationState.currentFrame != data->animationState.nextFrame) {
130          //interpolate vertex normals
131          this->drawVertexNormals(frame, this->interpolateVertexNormals(&mesh->normals[data->animationState.currentFrame],
132                                  &mesh->normals[data->animationState.nextFrame], data->animationState.interpolationFraction, mesh));
133        }
134        else {
135          //stick with current vertex normals
136          this->drawVertexNormals(frame, &mesh->normals[data->animationState.currentFrame]);
137        }
138      }
139    }
140
141
142    // draw all models linked to this model
143    std::map<int, MD3Data*>::iterator it = data->sortedMap.begin();
144    while( it != data->sortedMap.end())
145    {
146      MD3Data* child = it->second;
147
148      //build transformation array m from matrix, interpolate if necessary
149      float* m = new float[16];
150
151      MD3Tag* currFrameTag = data->boneFrames[data->animationState.currentFrame]->tags[child->parentTagIndex];
152
153      if( data->animationState.interpolationFraction != 0.0 &&
154          data->animationState.currentFrame != data->animationState.nextFrame) {
155        //we need to interpolate
156        MD3Tag* nextFrameTag = data->boneFrames[data->animationState.nextFrame]->tags[child->parentTagIndex];
157        m = this->interpolateTransformation(currFrameTag, nextFrameTag, data->animationState.interpolationFraction);
158      }
159      else {
160        //no interpolation needed, stay with last transformation
161        //OpenGL matrix is in column-major order
162        m[0] = currFrameTag->matrix[0][0];
163        m[1] = currFrameTag->matrix[1][0];
164        m[2] = currFrameTag->matrix[2][0];
165        m[3] = 0.0f;
166        m[4] = currFrameTag->matrix[0][1];
167        m[5] = currFrameTag->matrix[1][1];
168        m[6] = currFrameTag->matrix[2][1];
169        m[7] = 0.0f;
170        m[8] = currFrameTag->matrix[0][2];
171        m[9] = currFrameTag->matrix[1][2];
172        m[10]= currFrameTag->matrix[2][2];
173        m[11]= 0.0f;
174        m[12] = currFrameTag->position.x;
175        m[13] = currFrameTag->position.y;
176        m[14] = currFrameTag->position.z;
177        m[15] = 1.0f;
178      }
179
180      //switch to child coord system
181      glPushMatrix();
182      glMultMatrixf(m);
183
184      // and draw child
185      this->draw(child);
186
187      glPopMatrix();
188    }
189  }
190
191
192  /**
193   * draws the mesh
194   */
195  void MD3Model::drawMesh(MD3Mesh* mesh, sVec3D* frame)
196  {
197    glColor3f(1.0f, 1.0f, 1.0f);
198    glBegin( GL_TRIANGLES );
199
200    // upload all triangles in the frame to OpenGL
201    for( int t = 0; t < mesh->header->triangleNum; t++) {
202      // calc normal vector
203      this->tmpVec1.x = frame[mesh->triangles[t].vertexOffset[1]][0] - frame[mesh->triangles[t].vertexOffset[0]][0];
204      this->tmpVec2.x = frame[mesh->triangles[t].vertexOffset[2]][0] - frame[mesh->triangles[t].vertexOffset[0]][0];
205
206      this->tmpVec1.y = frame[mesh->triangles[t].vertexOffset[1]][1] - frame[mesh->triangles[t].vertexOffset[0]][1];
207      this->tmpVec2.y = frame[mesh->triangles[t].vertexOffset[2]][1] - frame[mesh->triangles[t].vertexOffset[0]][1];
208
209      this->tmpVec1.z = frame[mesh->triangles[t].vertexOffset[1]][2] - frame[mesh->triangles[t].vertexOffset[0]][2];
210      this->tmpVec2.z = frame[mesh->triangles[t].vertexOffset[2]][2] - frame[mesh->triangles[t].vertexOffset[0]][2];
211
212      Vector normal = this->tmpVec1.cross(tmpVec2);
213      normal.normalize();
214
215      glNormal3f(normal.x, normal.y, normal.z);
216      //no normalization necessary, GL_NORMALIZE is enabled!
217
218      glTexCoord2fv( mesh->texVecs[mesh->triangles[t].vertexOffset[0]].textureCoord);
219      glVertex3f( frame[mesh->triangles[t].vertexOffset[0]][0],
220                  frame[mesh->triangles[t].vertexOffset[0]][1],
221                  frame[mesh->triangles[t].vertexOffset[0]][2]);
222      glTexCoord2fv( mesh->texVecs[mesh->triangles[t].vertexOffset[1]].textureCoord);
223      glVertex3f( frame[mesh->triangles[t].vertexOffset[1]][0],
224                  frame[mesh->triangles[t].vertexOffset[1]][1],
225                  frame[mesh->triangles[t].vertexOffset[1]][2]);
226      glTexCoord2fv( mesh->texVecs[mesh->triangles[t].vertexOffset[2]].textureCoord);
227      glVertex3f( frame[mesh->triangles[t].vertexOffset[2]][0],
228                  frame[mesh->triangles[t].vertexOffset[2]][1],
229                  frame[mesh->triangles[t].vertexOffset[2]][2]);
230    }
231
232    glEnd();
233  }
234
235
236  /**
237   *  drawo vertex normals
238   */
239  void MD3Model::drawVertexNormals(sVec3D* frame, MD3Normal* normals)
240  {}
241
242
243  /**
244   * draw bone frame
245   */
246  void MD3Model::drawBoneFrame(MD3BoneFrame* frame)
247  {
248    float x1 = frame->mins.x;
249    float y1 = frame->mins.y;
250    float z1 = frame->mins.z;
251    float x2 = frame->maxs.x;
252    float y2 = frame->maxs.y;
253    float z2 = frame->maxs.z;
254
255    glPushAttrib(GL_TEXTURE_2D);
256    glPushAttrib(GL_LIGHTING);
257
258    glColor3f(1.0f,0.0f,0.0f);
259    glPointSize(6.0f);
260
261    glBegin(GL_POINTS);
262    glVertex3f(frame->position.x, frame->position.y, frame->position.z);
263    glEnd();
264    glPointSize(1.0f);
265
266    glColor3f(0.0f,1.0f,0.0f);
267    glBegin(GL_LINE_LOOP);
268    glVertex3f(x1,y1,z1);
269    glVertex3f(x1,y1,z2);
270    glVertex3f(x1,y2,z2);
271    glVertex3f(x1,y2,z1);
272    glEnd();
273
274    glBegin(GL_LINE_LOOP);
275    glVertex3f(x2,y2,z2);
276    glVertex3f(x2,y1,z2);
277    glVertex3f(x2,y1,z1);
278    glVertex3f(x2,y2,z1);
279    glEnd();
280
281    glBegin(GL_LINES);
282    glVertex3f(x1,y1,z1);
283    glVertex3f(x2,y1,z1);
284
285    glVertex3f(x1,y1,z2);
286    glVertex3f(x2,y1,z2);
287
288    glVertex3f(x1,y2,z2);
289    glVertex3f(x2,y2,z2);
290
291    glVertex3f(x1,y2,z1);
292    glVertex3f(x2,y2,z1);
293    glEnd();
294
295    glPopAttrib();
296    glPopAttrib();
297  }
298
299
300  /**
301   *  interpolate bone frame
302   * @param currBoneFrame Start bone frame.
303   * @param nextBoneFrame End bone frame.
304   * @param frac Interpolation fraction, in [0,1].
305   */
306  MD3BoneFrame* MD3Model::interpolateBoneFrame(MD3BoneFrame* currBoneFrame, MD3BoneFrame* nextBoneFrame, float frac)
307  {
308    this->tmpBoneFrame->mins.x      = (1.0f - frac) * currBoneFrame->mins.x       + frac * nextBoneFrame->mins.x;
309    this->tmpBoneFrame->maxs.x      = (1.0f - frac) * currBoneFrame->maxs.x       + frac * nextBoneFrame->maxs.x;
310    this->tmpBoneFrame->position.= (1.0f - frac) * currBoneFrame->position.x   + frac * nextBoneFrame->position.x;
311    this->tmpBoneFrame->mins.y      = (1.0f - frac) * currBoneFrame->mins.y       + frac * nextBoneFrame->mins.y;
312    this->tmpBoneFrame->maxs.y      = (1.0f - frac) * currBoneFrame->maxs.y       + frac * nextBoneFrame->maxs.y;
313    this->tmpBoneFrame->position.= (1.0f - frac) * currBoneFrame->position.y   + frac * nextBoneFrame->position.y;
314    this->tmpBoneFrame->mins.z      = (1.0f - frac) * currBoneFrame->mins.z       + frac * nextBoneFrame->mins.z;
315    this->tmpBoneFrame->maxs.z      = (1.0f - frac) * currBoneFrame->maxs.z       + frac * nextBoneFrame->maxs.z;
316    this->tmpBoneFrame->position.= (1.0f - frac) * currBoneFrame->position.z   + frac * nextBoneFrame->position.z;
317
318    return this->tmpBoneFrame;
319  }
320
321
322  /**
323   * interpolate mesh frame
324   */
325  sVec3D* MD3Model::interpolateMeshFrame(sVec3D* currMeshFrame, sVec3D* nextMeshFrame, float frac, MD3Mesh* mesh)
326  {
327    int vertexNum = mesh->header->vertexNum;
328
329    // calc interpolated vertices
330    for( int t = 0; t < vertexNum * 3.0f; t++)
331    {
332      this->tmpMesh[t][0]  = (1.0f - frac)   * currMeshFrame[t][0]  + frac * nextMeshFrame[t][0];
333      this->tmpMesh[t][1]  = (1.0f - frac)   * currMeshFrame[t][1]  + frac * nextMeshFrame[t][1];
334      this->tmpMesh[t][2]  = (1.0f - frac)   * currMeshFrame[t][2]  + frac * nextMeshFrame[t][2];
335    }
336
337    return this->tmpMesh;
338  }
339
340
341  /**
342   * interpolate vertex normal
343   */
344  MD3Normal* MD3Model::interpolateVertexNormals(MD3Normal* currNormals, MD3Normal* nextNormals, float frac, MD3Mesh* mesh)
345  {
346    for( int i = 0; i < mesh->header->vertexNum; i++)
347    {
348      this->tmpNormal[i].vertexNormal[0] = (int)((1.0f - frac) * currNormals[i].vertexNormal[0] + frac * nextNormals[i].vertexNormal[0]);
349      this->tmpNormal[i].vertexNormal[1] = (int)((1.0f - frac) * currNormals[i].vertexNormal[1] + frac * nextNormals[i].vertexNormal[1]);
350    }
351
352    return this->tmpNormal;
353  }
354
355
356  /**
357   * interpolate transformation
358   */
359  float* MD3Model::interpolateTransformation(MD3Tag* currFrameTag, MD3Tag* nextFrameTag, float frac)
360  {
361    // interpolate position
362    Vector interpolatedPosition = currFrameTag->position * (1.0f - frac) + nextFrameTag->position * frac;
363
364
365    // interpolate rotation matrix
366    float  currRot[4][4];
367    float  nextRot[4][4];
368    float  interpolatedMatrix[4][4];
369
370    Quaternion currQuat(currFrameTag->matrix); currQuat.matrix(currRot);
371    Quaternion nextQuat(nextFrameTag->matrix); nextQuat.matrix(nextRot);
372
373    Quaternion interpolatedQuat = Quaternion::quatSlerp(currQuat, nextQuat, frac); interpolatedQuat.matrix(interpolatedMatrix);
374
375    // quaternion code is column based, so use transposed matrix when spitting out to gl
376    this->tmpMatrix[0] = interpolatedMatrix[0][0];
377    this->tmpMatrix[4] = interpolatedMatrix[1][0];
378    this->tmpMatrix[8] = interpolatedMatrix[2][0];
379    this->tmpMatrix[12] = interpolatedPosition.x;
380    this->tmpMatrix[1] = interpolatedMatrix[0][1];
381    this->tmpMatrix[5] = interpolatedMatrix[1][1];
382    this->tmpMatrix[9] = interpolatedMatrix[2][1];
383    this->tmpMatrix[13] = interpolatedPosition.y;
384    this->tmpMatrix[2] = interpolatedMatrix[0][2];
385    this->tmpMatrix[6] = interpolatedMatrix[1][2];
386    this->tmpMatrix[10]= interpolatedMatrix[2][2];
387    this->tmpMatrix[14] = interpolatedPosition.z;
388    this->tmpMatrix[3] = 0.0f;
389    this->tmpMatrix[7] = 0.0f;
390    this->tmpMatrix[11]= 0.0f;
391    this->tmpMatrix[15] = 1.0f;
392
393    return this->tmpMatrix;
394
395  }
396
397
398}
Note: See TracBrowser for help on using the repository browser.