00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifdef _WIN32
00019 #define WIN32_LEAN_AND_MEAN
00020 #include <windows.h>
00021 #endif
00022
00023 #include <GL/gl.h>
00024 #include <GL/glu.h>
00025 #include <iostream>
00026 #include <cmath>
00027
00028 using std::cout;
00029 using std::cerr;
00030 using std::endl;
00031
00032 #include "Md3Model.h"
00033 #include "TextureManager.h"
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 Md3Model::Md3QuaternionTag::Md3QuaternionTag (const Md3Tag_t &tag)
00050 : name (tag.name)
00051 {
00052
00053 origin._x = tag.origin[0];
00054 origin._y = tag.origin[1];
00055 origin._z = tag.origin[2];
00056
00057
00058 Matrix4x4f m;
00059 m._m11 = tag.axis[0][0]; m._m12 = tag.axis[0][1]; m._m13 = tag.axis[0][2];
00060 m._m21 = tag.axis[1][0]; m._m22 = tag.axis[1][1]; m._m23 = tag.axis[1][2];
00061 m._m31 = tag.axis[2][0]; m._m32 = tag.axis[2][1]; m._m33 = tag.axis[2][2];
00062
00063
00064 orient.fromMatrix (m);
00065 orient.normalize ();
00066 }
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 NormalLookupTable::NormalLookupTable ()
00082 {
00083 for (int i = 0; i < 256; ++i)
00084 {
00085 for (int j = 0; j < 256; ++j)
00086 {
00087 float lng = i * 2.0f * kPi / 255.0f;
00088 float lat = j * 2.0f * kPi / 255.0f;
00089
00090 _normal[i][j][0] = std::cos (lat) * std::sin (lng);
00091 _normal[i][j][1] = std::sin (lat) * std::sin (lng);
00092 _normal[i][j][2] = std::cos (lng);
00093 }
00094 }
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 const NormalLookupTable Md3Mesh::_kAnorms;
00106
00107
00108 const int Md3Mesh::_kMd3Ident = 'I' + ('D'<<8) + ('P'<<16) + ('3'<<24);
00109
00110
00111 vec3_t Md3Mesh::_kVertexArray[kMd3MaxTriangles * 3];
00112 vec3_t Md3Mesh::_kNormalArray[kMd3MaxTriangles * 3];
00113
00114
00115
00116
00117
00118
00119
00120
00121 Md3Mesh::Md3Mesh (std::ifstream &ifs)
00122 throw (Md3Exception)
00123 : _tex (NULL)
00124 {
00125
00126 if (!ifs.is_open ())
00127 throw Md3Exception ("Stream not opened");
00128
00129
00130 long pos = ifs.tellg ();
00131
00132
00133 ifs.read (reinterpret_cast<char *>(&_header),
00134 sizeof (Md3MeshHeader_t));
00135
00136
00137 if (_header.ident != _kMd3Ident)
00138 throw Md3Exception ("Bad mesh ident");
00139
00140
00141 _shaders.reserve (_header.num_shaders);
00142 _triangles.reserve (_header.num_triangles);
00143 _texCoords.reserve (_header.num_verts);
00144 _vertices.reserve (_header.num_verts * _header.num_frames);
00145 _indices.reserve (_header.num_triangles * 3);
00146
00147
00148 Md3Shader_t shader;
00149 ifs.seekg (pos + _header.offset_shaders, std::ios::beg);
00150 for (int i = 0; i < _header.num_shaders; ++i)
00151 {
00152 ifs.read (reinterpret_cast<char *>(&shader), sizeof (Md3Shader_t));
00153 _shaders.push_back (Md3ShaderPtr (new Md3Shader_t (shader)));
00154 }
00155
00156
00157 Md3Triangle_t tri;
00158 ifs.seekg (pos + _header.offset_triangles, std::ios::beg);
00159 for (int i = 0; i < _header.num_triangles; ++i)
00160 {
00161 ifs.read (reinterpret_cast<char *>(&tri), sizeof (Md3Triangle_t));
00162 _triangles.push_back (Md3TrianglePtr (new Md3Triangle_t (tri)));
00163 }
00164
00165
00166 Md3TexCoord_t st;
00167 ifs.seekg (pos + _header.offset_st, std::ios::beg);
00168 for (int i = 0; i < _header.num_verts; ++i)
00169 {
00170 ifs.read (reinterpret_cast<char *>(&st), sizeof (Md3TexCoord_t));
00171 _texCoords.push_back (st);
00172 }
00173
00174
00175
00176 Md3Vertex_t vert;
00177 ifs.seekg (pos + _header.offset_xyznormal, std::ios::beg);
00178 for (int i = 0; i < _header.num_verts * _header.num_frames; ++i)
00179 {
00180 ifs.read (reinterpret_cast<char *>(&vert), sizeof (Md3Vertex_t));
00181 _vertices.push_back (Md3VertexPtr (new Md3Vertex_t (vert)));
00182 }
00183
00184
00185 ifs.seekg (pos + _header.offset_end, std::ios::beg);
00186
00187
00188 for (int i = 0; i < _header.num_triangles; ++i)
00189 {
00190
00191
00192 for (int j = 2; j >= 0; --j)
00193 _indices.push_back (_triangles[i]->index[j]);
00194 }
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204 Md3Mesh::~Md3Mesh ()
00205 {
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215 void
00216 Md3Mesh::loadShader (int index)
00217 {
00218 if (index < 0 || index >= _header.num_shaders)
00219 return;
00220
00221 const string filename (_shaders[index]->name);
00222 if (!filename.empty ())
00223 {
00224
00225 Texture2DManager *texMgr = Texture2DManager::getInstance ();
00226
00227
00228 setTexture (texMgr->load (filename));
00229 }
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239 void
00240 Md3Mesh::bindTexture () const
00241 {
00242 if (!_tex)
00243 {
00244
00245 glBindTexture (GL_TEXTURE_2D, 0);
00246 return;
00247 }
00248
00249 _tex->bind ();
00250
00251
00252
00253
00254
00255
00256
00257 if (_tex->stdCoordSystem ())
00258 {
00259 glMatrixMode (GL_TEXTURE);
00260 glLoadIdentity ();
00261 glScalef (1.0f, -1.0f, 1.0f);
00262 glTranslatef (0.0f, -1.0f, 0.0f);
00263 glMatrixMode (GL_MODELVIEW);
00264 }
00265 }
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 void
00278 Md3Mesh::setupVertexArrays (int frameA, int frameB, float interp, float scale)
00279 {
00280 int frameOffsetA = frameA * _header.num_verts;
00281 int frameOffsetB = frameB * _header.num_verts;
00282
00283 float s = scale * kMd3XYZScale;
00284
00285 for (int i = 0; i < _header.num_verts; ++i)
00286 {
00287 const Md3Vertex_t *pVertA = _vertices[frameOffsetA + i].get ();
00288 const Md3Vertex_t *pVertB = _vertices[frameOffsetB + i].get ();
00289
00290
00291 const int &uA = pVertA->normal[0];
00292 const int &vA = pVertA->normal[1];
00293
00294 const int &uB = pVertB->normal[0];
00295 const int &vB = pVertB->normal[1];
00296
00297 const float *normA = _kAnorms[uA][vA];
00298 const float *normB = _kAnorms[uB][vB];
00299
00300 _kNormalArray[i][0] = normA[0] + interp * (normB[0] - normA[0]);
00301 _kNormalArray[i][1] = normA[1] + interp * (normB[1] - normA[1]);
00302 _kNormalArray[i][2] = normA[2] + interp * (normB[2] - normA[2]);
00303
00304
00305 const short *vertA = pVertA->v;
00306 const short *vertB = pVertB->v;
00307
00308 _kVertexArray[i][0] = (vertA[0] + interp * (vertB[0] - vertA[0])) * s;
00309 _kVertexArray[i][1] = (vertA[1] + interp * (vertB[1] - vertA[1])) * s;
00310 _kVertexArray[i][2] = (vertA[2] + interp * (vertB[2] - vertA[2])) * s;
00311 }
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 void
00323 Md3Mesh::renderFrameImmediate (int frame, float scale) const
00324 {
00325 int frameOffset = frame * _header.num_verts;
00326
00327
00328 float scale_and_uncompress = scale * kMd3XYZScale;
00329
00330 glPushAttrib (GL_POLYGON_BIT);
00331 glFrontFace (GL_CW);
00332
00333
00334 bindTexture ();
00335
00336 glBegin (GL_TRIANGLES);
00337
00338 for (int i = 0; i < _header.num_triangles; ++i)
00339 {
00340
00341 for (int j = 0; j < 3; ++j)
00342 {
00343 const int &vertIndex = _triangles[i]->index[j];
00344 const Md3Vertex_t *pVert = _vertices[frameOffset + vertIndex].get ();
00345 const Md3TexCoord_t *pTexCoords = &_texCoords[vertIndex];
00346
00347
00348 glTexCoord2f (pTexCoords->s, pTexCoords->t);
00349
00350
00351 const unsigned char &un = pVert->normal[0];
00352 const unsigned char &vn = pVert->normal[1];
00353
00354 glNormal3fv (_kAnorms[un][vn]);
00355
00356
00357 vec3_t v;
00358
00359 v[0] = pVert->v[0] * scale_and_uncompress;
00360 v[1] = pVert->v[1] * scale_and_uncompress;
00361 v[2] = pVert->v[2] * scale_and_uncompress;
00362
00363 glVertex3fv (v);
00364 }
00365 }
00366 glEnd ();
00367
00368
00369 glPopAttrib ();
00370 }
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 void
00381 Md3Mesh::renderWithVertexArrays () const
00382 {
00383 glEnableClientState (GL_VERTEX_ARRAY);
00384 glEnableClientState (GL_NORMAL_ARRAY);
00385 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
00386
00387
00388 glVertexPointer (3, GL_FLOAT, 0, _kVertexArray);
00389 glNormalPointer (GL_FLOAT, 0, _kNormalArray);
00390 glTexCoordPointer (2, GL_FLOAT, 0, &_texCoords.front ());
00391
00392
00393 bindTexture ();
00394
00395
00396 glDrawElements (GL_TRIANGLES, _header.num_triangles * 3,
00397 GL_UNSIGNED_INT, &_indices.front ());
00398
00399 glDisableClientState (GL_VERTEX_ARRAY);
00400 glDisableClientState (GL_NORMAL_ARRAY);
00401 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
00402 }
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 const int Md3Model::_kMd3Ident = 'I' + ('D'<<8) + ('P'<<16) + ('3'<<24);
00413
00414
00415 const int Md3Model::_kMd3Version = 15;
00416
00417
00418
00419
00420
00421
00422
00423
00424 Md3Model::Md3Model (const string &filename)
00425 throw (Md3Exception)
00426 : _currFrame (0), _nextFrame (0), _interp (0.0f),
00427 _scale (1.0f), _name (filename)
00428 {
00429
00430 std::ifstream ifs (filename.c_str(), std::ios::in | std::ios::binary);
00431
00432 if (ifs.fail ())
00433 throw Md3Exception ("Couldn't open file", filename);
00434
00435
00436 ifs.read (reinterpret_cast<char *>(&_header),
00437 sizeof (Md3Header_t));
00438
00439
00440 if (_header.ident != _kMd3Ident)
00441 throw Md3Exception ("Bad file ident", filename);
00442
00443 if (_header.version != _kMd3Version)
00444 throw Md3Exception ("Bad file version", filename);
00445
00446
00447 _meshes.reserve (_header.num_meshes);
00448 _qtags.reserve (_header.num_tags * _header.num_frames);
00449 _links.reserve (_header.num_tags);
00450
00451
00452 Md3Frame_t frame;
00453 ifs.seekg (_header.offset_frames, std::ios::beg);
00454 for (int i = 0; i < _header.num_frames; ++i)
00455 {
00456 ifs.read (reinterpret_cast<char *>(&frame), sizeof (Md3Frame_t));
00457 _frames.push_back (Md3FramePtr (new Md3Frame_t (frame)));
00458 }
00459
00460
00461 Md3Tag_t tag;
00462 ifs.seekg (_header.offset_tag, std::ios::beg);
00463 for (int i = 0; i < _header.num_tags * _header.num_frames; ++i)
00464 {
00465 ifs.read (reinterpret_cast<char *>(&tag), sizeof (Md3Tag_t));
00466 _qtags.push_back (Md3TagPtr (new Md3QuaternionTag (tag)));
00467 }
00468
00469
00470 ifs.seekg (_header.offset_meshes, std::ios::beg);
00471 for (int i = 0; i < _header.num_meshes; ++i)
00472 _meshes.push_back (Md3MeshPtr (new Md3Mesh (ifs)));
00473
00474
00475 ifs.close();
00476
00477
00478 for (int i = 0; i < _header.num_tags; ++i)
00479 _links.push_back (NULL);
00480 }
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 Md3Model::~Md3Model ()
00491 {
00492 }
00493
00494
00495
00496
00497
00498
00499
00500
00501 void
00502 Md3Model::loadShaders () const
00503 {
00504 for (int i = 0; i < _header.num_meshes; ++i)
00505 _meshes[i]->loadShader (0);
00506 }
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 void
00517 Md3Model::draw () const
00518 {
00519 Matrix4x4f m;
00520
00521
00522 renderFrameItpWithVertexArrays (_currFrame, _nextFrame, _interp);
00523
00524
00525 for (int i = 0; i < _header.num_tags; ++i)
00526 {
00527 if (!_links[i])
00528 continue;
00529
00530 const Quaternionf &qA = _qtags[_currFrame * _header.num_tags + i]->orient;
00531 const Quaternionf &qB = _qtags[_nextFrame * _header.num_tags + i]->orient;
00532
00533 m.fromQuaternion (Slerp (qA, qB, _interp));
00534
00535 const Vector3f &currPos = _qtags[_currFrame * _header.num_tags + i]->origin;
00536 const Vector3f &nextPos = _qtags[_nextFrame * _header.num_tags + i]->origin;
00537
00538 m.setTranslation ((currPos + _interp * (nextPos - currPos)) * _scale);
00539
00540 glPushMatrix ();
00541 glMultMatrixf (m);
00542 _links[i]->draw ();
00543 glPopMatrix ();
00544 }
00545 }
00546
00547
00548
00549
00550
00551
00552
00553
00554 void
00555 Md3Model::renderFrameImmediate (int frame) const
00556 {
00557
00558 if ((frame < 0) || (frame >= _header.num_frames))
00559 return;
00560
00561 for (int i = 0; i < _header.num_meshes; ++i)
00562 _meshes[i]->renderFrameImmediate (frame, _scale);
00563 }
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573 void
00574 Md3Model::renderFrameItpWithVertexArrays (int frameA, int frameB,
00575 float interp) const
00576 {
00577 int maxFrame = _header.num_frames - 1;
00578
00579
00580 if ((frameA < 0) || (frameB < 0))
00581 return;
00582
00583 if ((frameA > maxFrame) || (frameB > maxFrame))
00584 return;
00585
00586 for (int i = 0; i < _header.num_meshes; ++i)
00587 {
00588 _meshes[i]->setupVertexArrays (frameA, frameB, interp, _scale);
00589 _meshes[i]->renderWithVertexArrays ();
00590 }
00591 }
00592
00593
00594
00595
00596
00597
00598
00599
00600 bool
00601 Md3Model::link (const string &name, const Md3Model *model)
00602 {
00603 for (int i = 0; i < _header.num_tags; ++i)
00604 {
00605 if (name == _qtags[i]->name)
00606 {
00607 _links[i] = model;
00608 return true;
00609 }
00610 }
00611
00612 return false;
00613 }
00614
00615
00616
00617
00618
00619
00620
00621
00622 bool
00623 Md3Model::unlink (const string &name)
00624 {
00625 for (int i = 0; i < _header.num_tags; ++i)
00626 {
00627 if (name == _qtags[i]->name)
00628 {
00629 _links[i] = NULL;
00630 return true;
00631 }
00632 }
00633
00634 return false;
00635 }
00636
00637
00638
00639
00640
00641
00642
00643 void
00644 Md3Model::setTexture (const string &mesh, const Texture2D *tex)
00645 {
00646 for (int i = 0; i < _header.num_meshes; ++i)
00647 {
00648 if (_meshes[i]->name () == mesh)
00649 _meshes[i]->setTexture (tex);
00650 }
00651 }
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661 void
00662 Md3Model::setupAnimation (int currFrame, int nextFrame, float interp)
00663 {
00664 _currFrame = currFrame;
00665 _nextFrame = nextFrame;
00666 _interp = interp;
00667
00668
00669 if (_currFrame >= _header.num_frames)
00670 _currFrame = _header.num_frames - 1;
00671
00672 if (_nextFrame >= _header.num_frames)
00673 _nextFrame = _header.num_frames - 1;
00674 }