Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

bsp: new quaterinon constructor created for 3x3 matrices, bone rotation interpolation via quaternions implemented

File size: 10.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
29namespace md3
30{
31
32  /**
33   * md3 model
34   */
35  MD3Model::MD3Model(std::string filename, float scaling)
36  {
37    this->md3Data = new MD3Data(filename, filename, scaling);
38
39    MD3AnimationCfg cfg("/home/boenzlip/tmp/q3/Downloads/MOH/q3mdl-alien3/models/players/alien3/animation.cfg");
40
41    this->tmpBoneFrame = new MD3BoneFrame();
42    this->tmpMesh = new sVec3D[2048];          //!< the temporary mesh, hopefully newer bigger than 2048 vertices
43    this->tmpNormal = new MD3Normal[2048];     //!< the temporary normals
44  }
45
46
47
48  MD3Model::~MD3Model()
49  {
50    delete this->tmpBoneFrame;
51    delete [] this->tmpMesh;
52  }
53
54
55
56  /**
57   * this draws the md3 model
58   */
59  void MD3Model::draw()
60  {
61    //draw current bone frame
62    this->draw(this->md3Data);
63  }
64
65
66  /**
67   * draw the md3model
68   * @param data: the data to be drawn
69   */
70  void MD3Model::draw(MD3Data* data)
71  {
72
73    // draw the bones if needed
74    if( this->bDrawBones)
75    {
76      // get bone frame, interpolate if necessary
77      if( data->animationState.interpolationFraction != 0.0 &&
78          data->animationState.currentFrame != data->animationState.nextFrame) {
79        //interpolate bone frame
80        this->drawBoneFrame(this->interpolateBoneFrame(data->boneFrames[data->animationState.currentFrame],
81                            data->boneFrames[data->animationState.nextFrame],
82                            data->animationState.interpolationFraction));
83      }
84      else {
85        //stick with current bone frame
86        this->drawBoneFrame(data->boneFrames[data->animationState.currentFrame]);
87      }
88    }
89
90
91    //draw all meshes of current frame of this model
92    for( int i = 0;  i < data->meshNum; i++)
93    {
94      MD3Mesh* mesh = data->meshes[i];
95
96//       gl.glBlendFunc(mesh.GLSrcBlendFunc, mesh.GLDstBlendFunc);
97//       gl.glDepthMask(mesh.GLDepthMask);
98
99      if( mesh->header->textureNum > 0 && &mesh->material[0] != NULL)
100        mesh->material[0].select();
101
102      // get mesh frame, do interpolation if necessary
103      sVec3D* frame;
104      if( data->animationState.interpolationFraction != 0.0 &&
105          data->animationState.currentFrame != data->animationState.nextFrame) {
106        //interpolate mesh frame between the 2 current mesh frames
107//         frame = this->interpolateMeshFrame(mesh, data->animationState.currentFrame, data->animationState.nextFrame,
108//                                            data->animationState.interpolationFraction);
109        frame = this->interpolateMeshFrame( data->meshes[data->animationState.currentFrame]->meshFrames,
110                                            data->meshes[data->animationState.nextFrame]->meshFrames,
111                                            data->animationState.interpolationFraction, mesh);
112      }
113      else {
114        //no interpolation needed, just draw current frame
115        frame = &mesh->meshFrames[data->animationState.currentFrame];
116      }
117
118      this->drawMesh(mesh, frame);
119
120
121      // draw vertex normals if needed
122      if( this->bDrawNormals) {
123        // get vertex normals, interpolate if necessary
124        if( data->animationState.interpolationFraction != 0.0 &&
125            data->animationState.currentFrame != data->animationState.nextFrame) {
126          //interpolate vertex normals
127          this->drawVertexNormals(frame, this->interpolateVertexNormals(&mesh->normals[data->animationState.currentFrame],
128                                  &mesh->normals[data->animationState.nextFrame], data->animationState.interpolationFraction, mesh));
129        }
130        else {
131          //stick with current vertex normals
132          this->drawVertexNormals(frame, &mesh->normals[data->animationState.currentFrame]);
133        }
134      }
135    }
136
137
138    // draw all models linked to this model
139    std::map<int, MD3Data*>::iterator it = data->sortedMap.begin();
140    while( it != data->sortedMap.end())
141    {
142      MD3Data* child = it->second;
143
144      //build transformation array m from matrix, interpolate if necessary
145      float* m = new float[16];
146
147      MD3Tag* currFrameTag = data->boneFrames[data->animationState.currentFrame]->tags[child->parentTagIndex];
148
149      if( data->animationState.interpolationFraction != 0.0 &&
150          data->animationState.currentFrame != data->animationState.nextFrame) {
151        //we need to interpolate
152        MD3Tag* nextFrameTag = data->boneFrames[data->animationState.nextFrame]->tags[child->parentTagIndex];
153        m = this->interpolateTransformation(currFrameTag, nextFrameTag, data->animationState.interpolationFraction);
154      }
155      else {
156        //no interpolation needed, stay with last transformation
157        //OpenGL matrix is in column-major order
158        m[0] = currFrameTag->matrix[0][0];
159        m[1] = currFrameTag->matrix[1][0];
160        m[2] = currFrameTag->matrix[2][0];
161        m[3] = 0.0f;
162        m[4] = currFrameTag->matrix[0][1];
163        m[5] = currFrameTag->matrix[1][1];
164        m[6] = currFrameTag->matrix[2][1];
165        m[7] = 0.0f;
166        m[8] = currFrameTag->matrix[0][2];
167        m[9] = currFrameTag->matrix[1][2];
168        m[10]= currFrameTag->matrix[2][2];
169        m[11]= 0.0f;
170        m[12] = currFrameTag->position.x;
171        m[13] = currFrameTag->position.y;
172        m[14] = currFrameTag->position.z;
173        m[15] = 1.0f;
174      }
175
176      //switch to child coord system
177      glPushMatrix();
178      glMultMatrixf(m);
179
180      // and draw child
181      this->draw(child);
182
183      glPopMatrix();
184    }
185  }
186
187
188  /**
189   * draws the mesh
190   */
191  void MD3Model::drawMesh(MD3Mesh* mesh, sVec3D* frame)
192  {}
193
194
195  /**
196   *  drawo vertex normals
197   */
198  void MD3Model::drawVertexNormals(sVec3D* frame, MD3Normal* normals)
199  {}
200
201
202  /**
203   * draw bone frame
204   */
205  void MD3Model::drawBoneFrame(MD3BoneFrame* frame)
206  {}
207
208
209  /**
210   *  interpolate bone frame
211   * @param currBoneFrame Start bone frame.
212   * @param nextBoneFrame End bone frame.
213   * @param frac Interpolation fraction, in [0,1].
214   */
215  MD3BoneFrame* MD3Model::interpolateBoneFrame(MD3BoneFrame* currBoneFrame, MD3BoneFrame* nextBoneFrame, float frac)
216  {
217    this->tmpBoneFrame->mins.x      = (1.0f - frac) * currBoneFrame->mins.x       + frac * nextBoneFrame->mins.x;
218    this->tmpBoneFrame->maxs.x      = (1.0f - frac) * currBoneFrame->maxs.x       + frac * nextBoneFrame->maxs.x;
219    this->tmpBoneFrame->position.= (1.0f - frac) * currBoneFrame->position.x   + frac * nextBoneFrame->position.x;
220    this->tmpBoneFrame->mins.y      = (1.0f - frac) * currBoneFrame->mins.y       + frac * nextBoneFrame->mins.y;
221    this->tmpBoneFrame->maxs.y      = (1.0f - frac) * currBoneFrame->maxs.y       + frac * nextBoneFrame->maxs.y;
222    this->tmpBoneFrame->position.= (1.0f - frac) * currBoneFrame->position.y   + frac * nextBoneFrame->position.y;
223    this->tmpBoneFrame->mins.z      = (1.0f - frac) * currBoneFrame->mins.z       + frac * nextBoneFrame->mins.z;
224    this->tmpBoneFrame->maxs.z      = (1.0f - frac) * currBoneFrame->maxs.z       + frac * nextBoneFrame->maxs.z;
225    this->tmpBoneFrame->position.= (1.0f - frac) * currBoneFrame->position.z   + frac * nextBoneFrame->position.z;
226
227    return this->tmpBoneFrame;
228  }
229
230
231  /**
232   * interpolate mesh frame
233   */
234  sVec3D* MD3Model::interpolateMeshFrame(sVec3D* currMeshFrame, sVec3D* nextMeshFrame, float frac, MD3Mesh* mesh)
235  {
236    int vertexNum = mesh->header->vertexNum;
237
238    // calc interpolated vertices
239    for( int t = 0; t < vertexNum * 3.0f; t++)
240    {
241      this->tmpMesh[t][0]  = (1.0f - frac)   * currMeshFrame[t][0]  + frac * nextMeshFrame[t][0];
242      this->tmpMesh[t][1]  = (1.0f - frac)   * currMeshFrame[t][1]  + frac * nextMeshFrame[t][1];
243      this->tmpMesh[t][2]  = (1.0f - frac)   * currMeshFrame[t][2]  + frac * nextMeshFrame[t][2];
244    }
245
246    return this->tmpMesh;
247  }
248
249
250  /**
251   * interpolate vertex normal
252   */
253  MD3Normal* MD3Model::interpolateVertexNormals(MD3Normal* currNormals, MD3Normal* nextNormals, float frac, MD3Mesh* mesh)
254  {
255    for( int i = 0; i < mesh->header->vertexNum; i++)
256    {
257      this->tmpNormal[i].vertexNormal[0] = (int)((1.0f - frac) * currNormals[i].vertexNormal[0] + frac * nextNormals[i].vertexNormal[0]);
258      this->tmpNormal[i].vertexNormal[1] = (int)((1.0f - frac) * currNormals[i].vertexNormal[1] + frac * nextNormals[i].vertexNormal[1]);
259    }
260
261    return this->tmpNormal;
262  }
263
264
265  /**
266   * interpolate transformation
267   */
268  float* MD3Model::interpolateTransformation(MD3Tag* currFrameTag, MD3Tag* nextFrameTag, float frac)
269  {
270    // interpolate position
271    Vector interpolatedPosition = currFrameTag->position * (1.0f - frac) + nextFrameTag->position * frac;
272
273
274    // interpolate rotation matrix
275    float  currRot[4][4];
276    float  nextRot[4][4];
277    float  interpolatedMatrix[4][4];
278
279    Quaternion currQuat(currFrameTag->matrix); currQuat.matrix(currRot);
280    Quaternion nextQuat(nextFrameTag->matrix); nextQuat.matrix(nextRot);
281
282    Quaternion interpolatedQuat = Quaternion::quatSlerp(currQuat, nextQuat, frac); interpolatedQuat.matrix(interpolatedMatrix);
283
284    // quaternion code is column based, so use transposed matrix when spitting out to gl
285    this->tmpMatrix[0] = interpolatedMatrix[0][0];
286    this->tmpMatrix[4] = interpolatedMatrix[1][0];
287    this->tmpMatrix[8] = interpolatedMatrix[2][0];
288    this->tmpMatrix[12] = interpolatedPosition.x;
289    this->tmpMatrix[1] = interpolatedMatrix[0][1];
290    this->tmpMatrix[5] = interpolatedMatrix[1][1];
291    this->tmpMatrix[9] = interpolatedMatrix[2][1];
292    this->tmpMatrix[13] = interpolatedPosition.y;
293    this->tmpMatrix[2] = interpolatedMatrix[0][2];
294    this->tmpMatrix[6] = interpolatedMatrix[1][2];
295    this->tmpMatrix[10]= interpolatedMatrix[2][2];
296    this->tmpMatrix[14] = interpolatedPosition.z;
297    this->tmpMatrix[3] = 0.0f;
298    this->tmpMatrix[7] = 0.0f;
299    this->tmpMatrix[11]= 0.0f;
300    this->tmpMatrix[15] = 1.0f;
301
302    return this->tmpMatrix;
303
304  }
305
306
307}
Note: See TracBrowser for help on using the repository browser.