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