OSG3DSLoader.cpp

Go to the documentation of this file.
00001 // copyright (c) 2001 Lev Povalahev
00002
00003 #include <cstdio>
00004 #include <cstdlib>
00005 #include <cstring>
00006 #include <cmath>
00007
00008 #include "OSG3DSLoader.h"
00009
00010 //using namespace std;
00011
00012 //-------------------------------------------------------
00013 // generic stuff
00014 //-------------------------------------------------------
00015
00016 #define SEEK_START           1900
00017 #define SEEK_CURSOR          1901
00018 
00019 // common chunks
00020 // colors
00021 #define COLOR_F             0x0010
00022 #define COLOR_24            0x0011
00023 #define LIN_COLOR_24        0x0012
00024 #define LIN_COLOR_F         0x0013
00025 
00026 // percentage
00027 #define INT_PERCENTAGE      0x0030
00028 #define FLOAT_PERCENTAGE    0x0031
00029 
00030 // ambient light
00031 #define AMBIENT_LIGHT       0x2100
00032 
00033 #define MAIN3DS             0x4D4D
00034 #define EDIT3DS             0x3D3D  // this is the start of the editor config
00035 
00036 // keyframer chunk ids
00037 #define KFDATA              0xB000  // the keyframer section
00038 #define KFHDR               0xB00A
00039 #define OBJECT_NODE_TAG     0xB002
00040 #define NODE_HDR            0xB010
00041 #define PIVOT               0xB013
00042 #define POS_TRACK_TAG       0xB020
00043 #define ROT_TRACK_TAG       0xB021
00044 #define SCL_TRACK_TAG       0xB022
00045 
00046 // material entries
00047 #define MAT_ENTRY           0xAFFF
00048 #define MAT_NAME            0xA000
00049 #define MAT_AMBIENT         0xA010
00050 #define MAT_DIFFUSE         0xA020
00051 #define MAT_SPECULAR        0xA030
00052 #define MAT_SHININESS       0xA040
00053 #define MAT_SHIN2PCT        0xA041
00054 #define MAT_TRANSPARENCY    0xA050
00055 #define MAT_SHADING         0xA100
00056 #define MAT_TWO_SIDE        0xA081
00057 #define MAT_ADDITIVE        0xA083
00058 #define MAT_WIRE            0xA085
00059 #define MAT_FACEMAP         0xA088
00060 #define MAT_WIRESIZE        0xA087
00061 #define MAT_DECAL           0xA082
00062 #define MAT_TEXMAP          0xA200
00063 #define MAT_MAPNAME         0xA300
00064 #define MAT_MAP_TILING      0xA351
00065 #define MAT_MAP_USCALE      0xA354
00066 #define MAT_MAP_VSCALE      0xA356
00067 #define MAT_MAP_UOFFSET     0xA358
00068 #define MAT_MAP_VOFFSET     0xA35A
00069 #define MAT_MAP_ANG         0xA35C
00070 #define MAT_TEX2MAP         0xA33A
00071 #define MAT_OPACMAP         0xA210
00072 #define MAT_BUMPMAP         0xA230
00073 #define MAT_SPECMAP         0xA204
00074 #define MAT_SHINMAP         0xA33C
00075 #define MAT_REFLMAP         0xA220
00076 #define MAT_ACUBIC          0xA310
00077 
00078 #define EDIT_OBJECT         0x4000
00079 #define OBJ_TRIMESH         0x4100
00080 #define OBJ_LIGHT           0x4600
00081 #define OBJ_CAMERA          0x4700
00082 
00083 #define CAM_RANGES            0x4720
00084 
00085 #define LIT_OFF             0x4620
00086 #define LIT_SPOT            0x4610
00087 #define LIT_INRANGE         0x4659
00088 #define LIT_OUTRANGE        0x465A
00089 
00090 #define TRI_VERTEXLIST      0x4110
00091 #define TRI_VERTEXOPTIONS   0x4111
00092 #define TRI_FACELIST        0x4120
00093 #define TRI_MAT_GROUP       0x4130
00094 #define TRI_SMOOTH_GROUP    0x4150
00095 #define TRI_FACEMAPPING     0x4140
00096 #define TRI_MATRIX          0x4160
00097 #define TRI_TEXTURE_INFO    0x4170
00098 
00099 #define SPOTLIGHT           0x4610
00100 
00101 //----------------------------------
00102
00103 #define MAX_SHARED_TRIS     100
00104 
00105 // the error reporting routine
00106
00107 // globals
00108
00109 LColor3 black = {0, 0, 0};
00110
00111 LVector3 zero3 = {0, 0, 0};
00112
00113 LVector4 zero4 = {0, 0, 0, 0};
00114
00115 LMap emptyMap = {0, "", 1, 1, 0, 0, 0, 0};
00116
00117 LVector3 _4to3(const LVector4 &vec)
00118 {
00119     LVector3 t;
00120     t.x = vec.x;
00121     t.y = vec.y;
00122     t.z = vec.z;
00123     return t;
00124 }
00125
00126 LVector3 AddVectors(const LVector3 &a, const LVector3 &b)
00127 {
00128     LVector3 t;
00129     t.x = a.x+b.x;
00130     t.y = a.y+b.y;
00131     t.z = a.z+b.z;
00132     return t;
00133 }
00134
00135 LVector3 SubtractVectors(const LVector3 &a, const LVector3 &b)
00136 {
00137     LVector3 t;
00138     t.x = a.x-b.x;
00139     t.y = a.y-b.y;
00140     t.z = a.z-b.z;
00141     return t;
00142 }
00143
00144 float VectorLength(const LVector3 &vec)
00145 {
00146     return float(sqrt(vec.x*vec.x + vec.y*vec.y+vec.z*vec.z));
00147 }
00148
00149 LVector3 NormalizeVector(const LVector3 &vec)
00150 {
00151     float a = VectorLength(vec);
00152     if (a == 0)
00153         return vec;
00154     float b = 1/a;
00155     LVector3 v;
00156     v.x = vec.x*b;
00157     v.y = vec.y*b;
00158     v.z = vec.z*b;
00159     return v;
00160 }
00161
00162 LVector3 CrossProduct(const LVector3 &a, const LVector3 &b)
00163 {
00164     LVector3 v;
00165     v.x = a.y*b.z - a.z*b.y;
00166     v.y = a.z*b.x - a.x*b.z;
00167     v.z = a.x*b.y - a.y*b.x;
00168     return v;
00169 }
00170
00171 void LoadIdentityMatrix(LMatrix4 &m)
00172 {
00173     m._11 = 1.0f;
00174     m._12 = 0.0f;
00175     m._13 = 0.0f;
00176     m._14 = 0.0f;
00177
00178     m._21 = 0.0f;
00179     m._22 = 1.0f;
00180     m._23 = 0.0f;
00181     m._24 = 0.0f;
00182
00183     m._31 = 0.0f;
00184     m._32 = 0.0f;
00185     m._33 = 1.0f;
00186     m._34 = 0.0f;
00187
00188     m._41 = 0.0f;
00189     m._42 = 0.0f;
00190     m._43 = 1.0f;
00191     m._44 = 0.0f;
00192 }
00193
00194 LVector4 VectorByMatrix(const LMatrix4 &m, const LVector4 &vec)
00195 {
00196     LVector4 res;
00197     res.x = m._11*vec.x + m._12*vec.y + m._13*vec.z + m._14*vec.w;
00198     res.y = m._21*vec.x + m._22*vec.y + m._23*vec.z + m._24*vec.w;
00199     res.z = m._31*vec.x + m._32*vec.y + m._33*vec.z + m._34*vec.w;
00200     res.w = m._41*vec.x + m._42*vec.y + m._43*vec.z + m._44*vec.w;
00201     if (res.w != 0)
00202     {
00203         float b =  1/res.w;
00204         res.x *= b;
00205         res.y *= b;
00206         res.z *= b;
00207         res.w = 1;
00208     }
00209     else
00210         res.w = 1;
00211
00212     return res;
00213 }
00214
00215 //-------------------------------------------------------
00216 // LObject implementation
00217 //-------------------------------------------------------
00218
00219 LObject::LObject()
00220 {
00221     m_name = "";//.clear();
00222 }
00223
00224 LObject::~LObject()
00225 {
00226     // nothing here
00227 }
00228
00229 void LObject::SetName(const std::string& value)
00230 {
00231     m_name = value;
00232 }
00233
00234 const std::string& LObject::GetName()
00235 {
00236     return m_name;
00237 }
00238
00239 bool LObject::IsObject(const std::string &name)
00240 {
00241     return (m_name == name);
00242 }
00243
00244
00245 //-------------------------------------------------------
00246 // LMaterial implementation
00247 //-------------------------------------------------------
00248
00249 LMaterial::LMaterial()
00250 : LObject()
00251 {
00252     m_id = 0;
00253     m_texMap1 = emptyMap;
00254     m_texMap2 = emptyMap;
00255     m_opacMap = emptyMap;
00256     m_bumpMap = emptyMap;
00257     m_reflMap = emptyMap;
00258     m_specMap = emptyMap;
00259     m_ambient = black;
00260     m_diffuse = black;
00261     m_specular = black;
00262     m_shading = sGouraud;
00263     m_shininess = 0;
00264     m_transparency = 0;
00265 }
00266
00267 LMaterial::~LMaterial()
00268 {
00269
00270 }
00271
00272 uint LMaterial::GetID()
00273 {
00274     return m_id;
00275 }
00276
00277 LMap& LMaterial::GetTextureMap1()
00278 {
00279     return m_texMap1;
00280 }
00281
00282 LMap& LMaterial::GetTextureMap2()
00283 {
00284     return m_texMap2;
00285 }
00286
00287 LMap& LMaterial::GetOpacityMap()
00288 {
00289     return m_opacMap;
00290 }
00291
00292 LMap& LMaterial::GetSpecularMap()
00293 {
00294     return m_specMap;
00295 }
00296
00297 LMap& LMaterial::GetBumpMap()
00298 {
00299     return m_bumpMap;
00300 }
00301
00302 LMap& LMaterial::GetReflectionMap()
00303 {
00304     return m_reflMap;
00305 }
00306
00307 LColor3 LMaterial::GetAmbientColor()
00308 {
00309     return m_ambient;
00310 }
00311
00312 LColor3 LMaterial::GetDiffuseColor()
00313 {
00314     return m_diffuse;
00315 }
00316
00317 LColor3 LMaterial::GetSpecularColor()
00318 {
00319     return m_specular;
00320 }
00321
00322 float LMaterial::GetShininess()
00323 {
00324     return m_shininess;
00325 }
00326
00327 float LMaterial::GetTransparency()
00328 {
00329     return m_transparency;
00330 }
00331
00332 LShading LMaterial::GetShadingType()
00333 {
00334     return m_shading;
00335 }
00336
00337 void LMaterial::SetID(uint value)
00338 {
00339     m_id = value;
00340 }
00341
00342 void LMaterial::SetAmbientColor(const LColor3 &color)
00343 {
00344     m_ambient = color;
00345 }
00346
00347 void LMaterial::SetDiffuseColor(const LColor3 &color)
00348 {
00349     m_diffuse = color;
00350 }
00351
00352 void LMaterial::SetSpecularColor(const LColor3 &color)
00353 {
00354     m_specular = color;
00355 }
00356
00357 void LMaterial::SetShininess(float value)
00358 {
00359     m_shininess = value;
00360     if (m_shininess < 0)
00361         m_shininess = 0;
00362     if (m_shininess > 1)
00363         m_shininess = 1;
00364 }
00365
00366 void LMaterial::SetTransparency(float value)
00367 {
00368     m_transparency = value;
00369     if (m_transparency < 0)
00370         m_transparency = 0;
00371     if (m_transparency > 1)
00372         m_transparency = 1;
00373 }
00374
00375 void LMaterial::SetShadingType(LShading shading)
00376 {
00377     m_shading = shading;
00378 }
00379
00380 //-------------------------------------------------------
00381 // LMesh implementation
00382 //-------------------------------------------------------
00383
00384 LMesh::LMesh()
00385 :   LObject()
00386 {
00387     Clear();
00388 }
00389
00390 LMesh::~LMesh()
00391 {
00392     Clear();
00393 }
00394
00395 void LMesh::Clear()
00396 {
00397     m_vertices.clear();
00398     m_normals.clear();
00399     m_uv.clear();
00400     m_tangents.clear();
00401     m_binormals.clear();
00402     m_triangles.clear();
00403     m_tris.clear();
00404     m_materials.clear();
00405     LoadIdentityMatrix(m_matrix);
00406 }
00407
00408 uint LMesh::GetVertexCount()
00409 {
00410     return m_vertices.size();
00411 }
00412
00413 void LMesh::SetVertexArraySize(uint value)
00414 {
00415     m_vertices.resize(value);
00416     m_normals.resize(value);
00417     m_uv.resize(value);
00418     m_tangents.resize(value);
00419     m_binormals.resize(value);
00420 }
00421
00422 uint LMesh::GetTriangleCount()
00423 {
00424     return m_triangles.size();
00425 }
00426
00427 void LMesh::SetTriangleArraySize(uint value)
00428 {
00429     m_triangles.resize(value);
00430     m_tris.resize(value);
00431 }
00432
00433 const LVector4& LMesh::GetVertex(uint index)
00434 {
00435     return m_vertices[index];
00436 }
00437
00438 const LVector3& LMesh::GetNormal(uint index)
00439 {
00440     return m_normals[index];
00441 }
00442
00443 const LVector2& LMesh::GetUV(uint index)
00444 {
00445     return m_uv[index];
00446 }
00447
00448 const LVector3& LMesh::GetTangent(uint index)
00449 {
00450     return m_tangents[index];
00451 }
00452
00453 const LVector3& LMesh::GetBinormal(uint index)
00454 {
00455     return m_binormals[index];
00456 }
00457
00458 void LMesh::SetVertex(const LVector4 &vec, uint index)
00459 {
00460     if (index >= m_vertices.size())
00461         return;
00462     m_vertices[index] = vec;
00463 }
00464
00465 void LMesh::SetNormal(const LVector3 &vec, uint index)
00466 {
00467     if (index >= m_vertices.size())
00468         return;
00469     m_normals[index] = vec;
00470 }
00471
00472 void LMesh::SetUV(const LVector2 &vec, uint index)
00473 {
00474     if (index >= m_vertices.size())
00475         return;
00476     m_uv[index] = vec;
00477 }
00478
00479 void LMesh::SetTangent(const LVector3 &vec, uint index)
00480 {
00481     if (index >= m_vertices.size())
00482         return;
00483     m_tangents[index] = vec;
00484 }
00485
00486 void LMesh::SetBinormal(const LVector3 &vec, uint index)
00487 {
00488     if (index >= m_vertices.size())
00489         return;
00490     m_binormals[index] = vec;
00491 }
00492
00493 const LTriangle& LMesh::GetTriangle(uint index)
00494 {
00495     return m_triangles[index];
00496 }
00497
00498 LTriangle2 LMesh::GetTriangle2(uint index)
00499 {
00500     LTriangle2 f;
00501     LTriangle t = GetTriangle(index);
00502     f.vertices[0] = GetVertex(t.a);
00503     f.vertices[1] = GetVertex(t.b);
00504     f.vertices[2] = GetVertex(t.c);
00505
00506     f.vertexNormals[0] = GetNormal(t.a);
00507     f.vertexNormals[1] = GetNormal(t.b);
00508     f.vertexNormals[2] = GetNormal(t.c);
00509
00510     f.textureCoords[0] = GetUV(t.a);
00511     f.textureCoords[1] = GetUV(t.b);
00512     f.textureCoords[2] = GetUV(t.c);
00513
00514     LVector3 a, b;
00515
00516     a = SubtractVectors(_4to3(f.vertices[1]), _4to3(f.vertices[0]));
00517     b = SubtractVectors(_4to3(f.vertices[1]), _4to3(f.vertices[2]));
00518
00519     f.faceNormal = CrossProduct(b, a);
00520
00521     f.faceNormal = NormalizeVector(f.faceNormal);
00522
00523     f.materialId = m_tris[index].materialId;
00524
00525     return f;
00526 }
00527
00528 LMatrix4 LMesh::GetMatrix()
00529 {
00530     return m_matrix;
00531 }
00532
00533 void LMesh::SetMatrix(LMatrix4 m)
00534 {
00535     m_matrix = m;
00536 }
00537
00538 void LMesh::TransformVertices()
00539 {
00540     for (uint i=0; i<m_vertices.size(); i++)
00541         m_vertices[i] = VectorByMatrix(m_matrix, m_vertices[i]);
00542 }
00543
00544 void LMesh::CalcNormals(bool useSmoothingGroups)
00545 {
00546     uint i;
00547     // first calculate the face normals
00548     for (i=0; i<m_triangles.size(); i++)
00549     {
00550         LVector3 a, b;
00551         a = SubtractVectors(_4to3(m_vertices[m_tris[i].b]), _4to3(m_vertices[m_tris[i].a]));
00552         b = SubtractVectors(_4to3(m_vertices[m_tris[i].b]), _4to3(m_vertices[m_tris[i].c]));
00553         m_tris[i].normal = NormalizeVector(CrossProduct(b, a));
00554     }
00555
00556     std::vector< std::vector<int> > array;
00557     array.resize(m_vertices.size());
00558     for (i=0; i<m_triangles.size(); i++)
00559     {
00560         uint k = m_tris[i].a;
00561         array[k].push_back(i);
00562
00563         k = m_tris[i].b;
00564         array[k].push_back(i);
00565
00566         k = m_tris[i].c;
00567         array[k].push_back(i);
00568     }
00569
00570     LVector3 temp;
00571
00572     if (!useSmoothingGroups)
00573     {
00574         // now calculate the normals without using smoothing groups
00575         for (i=0; i<m_vertices.size(); i++)
00576         {
00577             temp = zero3;
00578             int t = array[i].size();
00579
00580             for (int k=0; k<t; k++)
00581             {
00582                 temp.x += m_tris[array[i][k]].normal.x;
00583                 temp.y += m_tris[array[i][k]].normal.y;
00584                 temp.z += m_tris[array[i][k]].normal.z;
00585             }
00586             m_normals[i] = NormalizeVector(temp);
00587         }
00588     }
00589     else
00590     {
00591         // now calculate the normals _USING_ smoothing groups
00592         // I'm assuming a triangle can only belong to one smoothing group at a time!
00593         std::vector<ulong> smGroups;
00594         std::vector< std::vector <uint> > smList;
00595
00596         uint loop_size = m_vertices.size();
00597
00598         for (i=0; i<loop_size; i++)
00599         {
00600             int t = array[i].size();
00601
00602             if (t == 0)
00603                 continue;
00604
00605             smGroups.clear();
00606             smList.clear();
00607             smGroups.push_back(m_tris[array[i][0]].smoothingGroups);
00608             smList.resize(smGroups.size());
00609             smList[smGroups.size()-1].push_back(array[i][0]);
00610
00611             // first build a list of smoothing groups for the vertex
00612             for (int k=0; k<t; k++)
00613             {
00614                 bool found = false;
00615                 for (uint j=0; j<smGroups.size(); j++)
00616                 {
00617                     if (m_tris[array[i][k]].smoothingGroups == smGroups[j])
00618                     {
00619                         smList[j].push_back(array[i][k]);
00620                         found = true;
00621                     }
00622                 }
00623                 if (!found)
00624                 {
00625                     smGroups.push_back(m_tris[array[i][k]].smoothingGroups);
00626                     smList.resize(smGroups.size());
00627                     smList[smGroups.size()-1].push_back(array[i][k]);
00628                 }
00629             }
00630             // now we have the list of faces for the vertex sorted by smoothing groups
00631
00632
00633             // now duplicate the vertices so that there's only one smoothing group "per vertex"
00634             if (smGroups.size() > 1)
00635                 for (uint j=1; j< smGroups.size(); j++)
00636                 {
00637                     m_vertices.push_back(m_vertices[i]);
00638                     m_normals.push_back(m_normals[i]);
00639                     m_uv.push_back(m_uv[i]);
00640                     m_tangents.push_back(m_tangents[i]);
00641                     m_binormals.push_back(m_binormals[i]);
00642
00643                     uint t = m_vertices.size()-1;
00644                     for (uint h=0; h<smList[j].size(); h++)
00645                     {
00646                         if (m_tris[smList[j][h]].a == i)
00647                             m_tris[smList[j][h]].a = t;
00648                         if (m_tris[smList[j][h]].b == i)
00649                             m_tris[smList[j][h]].b = t;
00650                         if (m_tris[smList[j][h]].c == i)
00651                             m_tris[smList[j][h]].c = t;
00652                     }
00653                 }
00654         }
00655
00656         // now rebuild a face list for each vertex, since the old one is invalidated
00657         for (i=0; i<array.size(); i++)
00658             array[i].clear();
00659         array.clear();
00660         array.resize(m_vertices.size());
00661         for (i=0; i<m_triangles.size(); i++)
00662         {
00663             uint k = m_tris[i].a;
00664             array[k].push_back(i);
00665
00666             k = m_tris[i].b;
00667             array[k].push_back(i);
00668
00669             k = m_tris[i].c;
00670             array[k].push_back(i);
00671         }
00672
00673         // now compute the normals
00674         for (i=0; i<m_vertices.size(); i++)
00675         {
00676             temp = zero3;
00677             int t = array[i].size();
00678
00679             for (int k=0; k<t; k++)
00680             {
00681                 temp.x += m_tris[array[i][k]].normal.x;
00682                 temp.y += m_tris[array[i][k]].normal.y;
00683                 temp.z += m_tris[array[i][k]].normal.z;
00684             }
00685             m_normals[i] = NormalizeVector(temp);
00686         }
00687
00688     }
00689
00690     // copy m_tris to m_triangles
00691     for (i=0; i<m_triangles.size(); i++)
00692     {
00693         m_triangles[i].a = m_tris[i].a;
00694         m_triangles[i].b = m_tris[i].b;
00695         m_triangles[i].c = m_tris[i].c;
00696     }
00697 }
00698
00699 void LMesh::CalcTextureSpace()
00700 {
00701     // a understandable description of how to do that can be found here:
00702     // http://members.rogers.com/deseric/tangentspace.htm
00703     // first calculate the tangent for each triangle
00704     LVector3 x_vec,
00705              y_vec,
00706              z_vec;
00707     LVector3 v1, v2;
00708     for (uint i=0; i<m_triangles.size(); i++)
00709     {
00710         v1.x = m_vertices[m_tris[i].b].x - m_vertices[m_tris[i].a].x;
00711         v1.y = m_uv[m_tris[i].b].x - m_uv[m_tris[i].a].x;
00712         v1.z = m_uv[m_tris[i].b].y - m_uv[m_tris[i].a].y;
00713
00714         v2.x = m_vertices[m_tris[i].c].x - m_vertices[m_tris[i].a].x;
00715         v2.y = m_uv[m_tris[i].c].x - m_uv[m_tris[i].a].x;
00716         v2.z = m_uv[m_tris[i].c].y - m_uv[m_tris[i].a].y;
00717
00718         x_vec = CrossProduct(v1, v2);
00719
00720         v1.x = m_vertices[m_tris[i].b].y - m_vertices[m_tris[i].a].y;
00721         v1.y = m_uv[m_tris[i].b].x - m_uv[m_tris[i].a].x;
00722         v1.z = m_uv[m_tris[i].b].y - m_uv[m_tris[i].a].y;
00723
00724         v2.x = m_vertices[m_tris[i].c].y - m_vertices[m_tris[i].a].y;
00725         v2.y = m_uv[m_tris[i].c].x - m_uv[m_tris[i].a].x;
00726         v2.z = m_uv[m_tris[i].c].y - m_uv[m_tris[i].a].y;
00727
00728         y_vec = CrossProduct(v1, v2);
00729
00730         v1.x = m_vertices[m_tris[i].b].z - m_vertices[m_tris[i].a].z;
00731         v1.y = m_uv[m_tris[i].b].x - m_uv[m_tris[i].a].x;
00732         v1.z = m_uv[m_tris[i].b].y - m_uv[m_tris[i].a].y;
00733
00734         v2.x = m_vertices[m_tris[i].c].z - m_vertices[m_tris[i].a].z;
00735         v2.y = m_uv[m_tris[i].c].x - m_uv[m_tris[i].a].x;
00736         v2.z = m_uv[m_tris[i].c].y - m_uv[m_tris[i].a].y;
00737
00738         z_vec = CrossProduct(v1, v2);
00739
00740         m_tris[i].tangent.x = -(x_vec.y/x_vec.x);
00741         m_tris[i].tangent.y = -(y_vec.y/y_vec.x);
00742         m_tris[i].tangent.z = -(z_vec.y/z_vec.x);
00743
00744         m_tris[i].binormal.x = -(x_vec.z/x_vec.x);
00745         m_tris[i].binormal.y = -(y_vec.z/y_vec.x);
00746         m_tris[i].binormal.z = -(z_vec.z/z_vec.x);
00747
00748     }
00749
00750     // now for each vertex build a list of face that share this vertex
00751     std::vector< std::vector<int> > array;
00752     array.resize(m_vertices.size());
00753     for (size_t i=0; i<m_triangles.size(); i++)
00754     {
00755         uint k = m_tris[i].a;
00756         array[k].push_back(i);
00757
00758         k = m_tris[i].b;
00759         array[k].push_back(i);
00760
00761         k = m_tris[i].c;
00762         array[k].push_back(i);
00763     }
00764
00765     // now average the tangents and compute the binormals as (tangent X normal)
00766     for (size_t i=0; i<m_vertices.size(); i++)
00767     {
00768         v1 = zero3;
00769         v2 = zero3;
00770         int t = array[i].size();
00771
00772         for (int k=0; k<t; k++)
00773         {
00774             v1.x += m_tris[array[i][k]].tangent.x;
00775             v1.y += m_tris[array[i][k]].tangent.y;
00776             v1.z += m_tris[array[i][k]].tangent.z;
00777
00778             v2.x += m_tris[array[i][k]].binormal.x;
00779             v2.y += m_tris[array[i][k]].binormal.y;
00780             v2.z += m_tris[array[i][k]].binormal.z;
00781         }
00782         m_tangents[i] = NormalizeVector(v1);
00783         //m_binormals[i] = NormalizeVector(v2);
00784
00785         m_binormals[i] = NormalizeVector(CrossProduct(m_tangents[i], m_normals[i]));
00786     }
00787 }
00788
00789 void LMesh::Optimize(LOptimizationLevel value)
00790 {
00791     switch (value)
00792     {
00793     case oNone:
00794         TransformVertices();
00795         break;
00796     case oSimple:
00797         //TransformVertices();
00798         CalcNormals(false);
00799         break;
00800     case oFull:
00801         //TransformVertices();
00802         CalcNormals(true);
00803         CalcTextureSpace();
00804         break;
00805     }
00806 }
00807
00808 void LMesh::SetTri(const LTri &tri, uint index)
00809 {
00810     if (index >= m_triangles.size())
00811         return;
00812     m_tris[index] = tri;
00813 }
00814
00815 LTri& LMesh::GetTri(uint index)
00816 {
00817     return m_tris[index];
00818 }
00819
00820 uint LMesh::GetMaterial(uint index)
00821 {
00822     return m_materials[index];
00823 }
00824
00825 uint LMesh::AddMaterial(uint id)
00826 {
00827     m_materials.push_back(id);
00828     return m_materials.size()-1;
00829 }
00830
00831 uint LMesh::GetMaterialCount()
00832 {
00833     return m_materials.size();
00834 }
00835
00836 //-------------------------------------------------------
00837 // LCamera implementation
00838 //-------------------------------------------------------
00839
00840 LCamera::LCamera()
00841 :   LObject()
00842 {
00843     Clear();
00844 }
00845
00846 LCamera::~LCamera()
00847 {
00848
00849 }
00850
00851 void LCamera::Clear()
00852 {
00853     m_pos.x = m_pos.y = m_pos.z = 0.0f;
00854     m_target.x = m_target.y = m_target.z = 0.0f;
00855     m_fov = 80;
00856     m_bank = 0;;
00857     m_near = 10;
00858     m_far = 10000;
00859 }
00860
00861 void LCamera::SetPosition(LVector3 vec)
00862 {
00863     m_pos = vec;
00864 }
00865
00866 LVector3 LCamera::GetPosition()
00867 {
00868     return m_pos;
00869 }
00870
00871 void LCamera::SetTarget(LVector3 target)
00872 {
00873     m_target = target;
00874 }
00875
00876 LVector3 LCamera::GetTarget()
00877 {
00878     return m_target;
00879 }
00880
00881 void LCamera::SetFOV(float value)
00882 {
00883     m_fov = value;
00884 }
00885
00886 float LCamera::GetFOV()
00887 {
00888     return m_fov;
00889 }
00890
00891 void LCamera::SetBank(float value)
00892 {
00893     m_bank = value;
00894 }
00895
00896 float LCamera::GetBank()
00897 {
00898     return m_bank;
00899 }
00900
00901 void LCamera::SetNearplane(float value)
00902 {
00903     m_near = value;
00904 }
00905
00906 float LCamera::GetNearplane()
00907 {
00908     return m_near;
00909 }
00910
00911 void LCamera::SetFarplane(float value)
00912 {
00913     m_far = value;
00914 }
00915
00916 float LCamera::GetFarplane()
00917 {
00918     return m_far;
00919 }
00920
00921 //-------------------------------------------------------
00922 // LLight implementation
00923 //-------------------------------------------------------
00924
00925 LLight::LLight()
00926 :   LObject()
00927 {
00928     Clear();
00929 }
00930
00931 LLight::~LLight()
00932 {
00933
00934 }
00935
00936 void LLight::Clear()
00937 {
00938     m_pos.x = m_pos.y = m_pos.z = 0.0f;
00939     m_color.r = m_color.g = m_color.b = 0.0f;
00940     m_spotlight = false;
00941     m_attenuationend = 100;
00942     m_attenuationstart = 1000;
00943 }
00944
00945 void LLight::SetPosition(LVector3 vec)
00946 {
00947     m_pos = vec;
00948 }
00949
00950 LVector3 LLight::GetPosition()
00951 {
00952     return m_pos;
00953 }
00954
00955 void LLight::SetColor(LColor3 color)
00956 {
00957     m_color = color;
00958 }
00959
00960 LColor3 LLight::GetColor()
00961 {
00962     return m_color;
00963 }
00964
00965 void LLight::SetSpotlight(bool value)
00966 {
00967     m_spotlight = value;
00968 }
00969
00970 bool LLight::GetSpotlight()
00971 {
00972     return m_spotlight;
00973 }
00974
00975 void LLight::SetTarget(LVector3 target)
00976 {
00977     m_target = target;
00978 }
00979
00980 LVector3 LLight::GetTarget()
00981 {
00982     return m_target;
00983 }
00984
00985 void LLight::SetHotspot(float value)
00986 {
00987     m_hotspot = value;
00988 }
00989
00990 float LLight::GetHotspot()
00991 {
00992     return m_hotspot;
00993 }
00994
00995 void LLight::SetFalloff(float value)
00996 {
00997     m_falloff = value;
00998 }
00999
01000 float LLight::GetFalloff()
01001 {
01002     return m_falloff;
01003 }
01004
01005 void LLight::SetAttenuationstart(float value)
01006 {
01007     m_attenuationend = value;
01008 }
01009
01010 float LLight::GetAttenuationstart()
01011 {
01012     return m_attenuationend;
01013 }
01014
01015 void LLight::SetAttenuationend(float value)
01016 {
01017     m_attenuationstart = value;
01018 }
01019
01020 float LLight::GetAttenuationend()
01021 {
01022     return m_attenuationstart;
01023 }
01024
01025 //-------------------------------------------------------
01026 // LImporter implementation
01027 //-------------------------------------------------------
01028
01029 LImporter::LImporter()
01030 {
01031     Clear();
01032 }
01033
01034 LImporter::~LImporter()
01035 {
01036     Clear();
01037 }
01038
01039 uint LImporter::GetMeshCount()
01040 {
01041     return m_meshes.size();
01042 }
01043
01044 uint LImporter::GetLightCount()
01045 {
01046     return m_lights.size();
01047 }
01048
01049 uint LImporter::GetMaterialCount()
01050 {
01051     return m_materials.size();
01052 }
01053
01054 uint LImporter::GetCameraCount()
01055 {
01056     return m_cameras.size();
01057 }
01058
01059 LMesh& LImporter::GetMesh(uint index)
01060 {
01061     return m_meshes[index];
01062 }
01063
01064 LLight& LImporter::GetLight(uint index)
01065 {
01066     return m_lights[index];
01067 }
01068
01069 LMaterial& LImporter::GetMaterial(uint index)
01070 {
01071     return m_materials[index];
01072 }
01073
01074 LCamera& LImporter::GetCamera(uint index)
01075 {
01076     return m_cameras[index];
01077 }
01078
01079 LMaterial* LImporter::FindMaterial(const std::string& name)
01080 {
01081     for (uint i=0; i<m_materials.size(); i++)
01082         if (m_materials[i].IsObject(name))
01083             return &m_materials[i];
01084     return 0;
01085 }
01086
01087 LMesh* LImporter::FindMesh(const std::string& name)
01088 {
01089     for (uint i=0; i<m_meshes.size(); i++)
01090         if (m_meshes[i].IsObject(name))
01091             return &m_meshes[i];
01092     return 0;
01093 }
01094
01095 LLight* LImporter::FindLight(const std::string& name)
01096 {
01097     for (uint i=0; i<m_lights.size(); i++)
01098         if (m_lights[i].IsObject(name))
01099             return &m_lights[i];
01100     return 0;
01101 }
01102
01103 void LImporter::Clear()
01104 {
01105     m_meshes.clear();
01106     m_lights.clear();
01107     m_materials.clear();
01108     m_optLevel = oFull;
01109 }
01110
01111 void LImporter::SetOptimizationLevel(LOptimizationLevel value)
01112 {
01113     m_optLevel = value;
01114 }
01115
01116 LOptimizationLevel LImporter::GetOptimizationLevel()
01117 {
01118     return m_optLevel;
01119 }
01120
01121 //-------------------------------------------------------
01122 // L3DS implementation
01123 //-------------------------------------------------------
01124
01125 L3DS::L3DS()
01126 : LImporter()
01127 {
01128     m_buffer = 0;
01129     m_bufferSize = 0;
01130     m_pos = 0;
01131     m_eof = false;
01132 }
01133
01134 L3DS::L3DS(const char *filename)
01135 : LImporter()
01136 {
01137     m_buffer = 0;
01138     m_bufferSize = 0;
01139     m_pos = 0;
01140     m_eof = false;
01141     Load(filename);
01142 }
01143
01144 L3DS::~L3DS()
01145 {
01146     if (m_bufferSize > 0)
01147         free(m_buffer);
01148 }
01149
01150 bool L3DS::Load(std::istream &is)
01151 {
01152     // get length of file:
01153     is.seekg(0, std::ios::end);
01154     m_bufferSize = is.tellg();
01155     is.seekg(0, std::ios::beg);
01156
01157     m_buffer = static_cast<unsigned char*>(calloc(m_bufferSize, 1));
01158     if (m_buffer == 0)
01159     {
01160         fprintf(stderr, "L3DS::LoadFile - not enough memory (malloc failed)");
01161         return false;
01162     }
01163     is.read(reinterpret_cast<char *>(m_buffer), m_bufferSize);
01164     if(is.gcount() != std::streamsize(m_bufferSize))
01165     {
01166         free(m_buffer);
01167         m_bufferSize = 0;
01168         fprintf(stderr, "L3DS::LoadFile - error reading from stream");
01169         return false;
01170     }
01171
01172     Clear();
01173     bool res = Read3DS();
01174     free(m_buffer);
01175     m_buffer = 0;
01176     m_bufferSize = 0;
01177     return res;
01178 }
01179
01180 bool L3DS::Load(const char *filename)
01181 {
01182     FILE *f;
01183     f = fopen(filename, "rb");
01184     if (f == 0)
01185     {
01186         fprintf(stderr, "L3DS::LoadFile - cannot open file");
01187         return false;
01188     }
01189     fseek(f, 0, SEEK_END);
01190     m_bufferSize = ftell(f);
01191     fseek(f, 0, SEEK_SET);
01192     m_buffer = static_cast<unsigned char *>(calloc(m_bufferSize, 1));
01193     if (m_buffer == 0)
01194     {
01195         fprintf(stderr, "L3DS::LoadFile - not enough memory (malloc failed)");
01196         return false;
01197     }
01198     if (fread(m_buffer, m_bufferSize, 1, f) != 1)
01199     {
01200         fclose(f);
01201         free(m_buffer);
01202         m_bufferSize = 0;
01203         fprintf(stderr, "L3DS::LoadFile - error reading from file");
01204         return false;
01205     }
01206     fclose(f);
01207
01208     Clear();
01209     bool res = Read3DS();
01210     free(m_buffer);
01211     m_buffer = 0;
01212     m_bufferSize = 0;
01213     return res;
01214 }
01215
01216 short L3DS::ReadShort()
01217 {
01218     if ((m_buffer!=0) && (m_bufferSize != 0) && ((m_pos+2)<m_bufferSize))
01219     {
01220         short *w = reinterpret_cast<short *>(m_buffer+m_pos);
01221         short s = *w;//(short)*(m_buffer+m_pos);
01222         m_pos += 2;
01223         return s;
01224     }
01225     m_eof = true;
01226     return 0;
01227 }
01228
01229 int L3DS::ReadInt()
01230 {
01231     if ((m_buffer!=0) && (m_bufferSize != 0) && ((m_pos+4)<m_bufferSize))
01232     {
01233         int *w = reinterpret_cast<int *>(m_buffer+m_pos);
01234         int s = *w;//(int)*(m_buffer+m_pos);
01235         m_pos += 4;
01236         return s;
01237     }
01238     m_eof = true;
01239     return 0;
01240 }
01241
01242 char L3DS::ReadChar()
01243 {
01244     if ((m_buffer!=0) && (m_bufferSize != 0) && ((m_pos+1)<m_bufferSize))
01245     {
01246         char s = char(*(m_buffer+m_pos));
01247         m_pos += 1;
01248         return s;
01249     }
01250     m_eof = true;
01251     return 0;
01252 }
01253
01254 float L3DS::ReadFloat()
01255 {
01256     if ((m_buffer!=0) && (m_bufferSize != 0) && ((m_pos+4)<m_bufferSize))
01257     {
01258         float *w = reinterpret_cast<float *>(m_buffer+m_pos);
01259         float s = *w;//(float)*(m_buffer+m_pos);
01260         m_pos += 4;
01261         return s;
01262     }
01263     m_eof = true;
01264     return 0.0;
01265 }
01266
01267 byte L3DS::ReadByte()
01268 {
01269     if ((m_buffer!=0) && (m_bufferSize != 0) && ((m_pos+1)<m_bufferSize))
01270     {
01271         byte s = byte(*(m_buffer+m_pos));
01272         m_pos += 1;
01273         return s;
01274     }
01275     m_eof = true;
01276     return 0;
01277 }
01278
01279 int L3DS::ReadASCIIZ(char *buf, int max_count)
01280 {
01281     int count;
01282     if ((m_buffer==0) || (m_bufferSize == 0) || (m_pos>=m_bufferSize))
01283     {
01284         count = 0;
01285         m_eof = true;
01286         return count;
01287     }
01288     count = 0;
01289     char c = ReadChar();
01290     while ((c!=0) && (count<max_count-1))
01291     {
01292         buf[count] = c;
01293         count ++;
01294         c = ReadChar();
01295     }
01296     buf[count] = 0;
01297     return count;
01298 }
01299
01300 void L3DS::Seek(int offset, int origin)
01301 {
01302     if (origin == SEEK_START)
01303         m_pos = offset;
01304     if (origin == SEEK_CURSOR)
01305         m_pos += offset;
01306     if (static_cast<signed>(m_pos) < 0)
01307         m_pos = 0;
01308     if (m_pos >= m_bufferSize)
01309         m_pos = m_bufferSize-1;
01310     m_eof = false;
01311 }
01312
01313 uint L3DS::Pos()
01314 {
01315     return m_pos;
01316 }
01317
01318 LChunk L3DS::ReadChunk()
01319 {
01320     LChunk chunk;
01321     chunk.id = ReadShort();
01322     int a = ReadInt();
01323     chunk.start = Pos();
01324     chunk.end = chunk.start+a-6;
01325     return chunk;
01326 }
01327
01328 bool L3DS::FindChunk(LChunk &target, const LChunk &parent)
01329 {
01330     if (Pos() >= parent.end)
01331         return false;
01332     LChunk chunk;
01333     chunk = ReadChunk();
01334     while (( chunk.id != target.id) && (chunk.end <= parent.end))
01335     {
01336         SkipChunk(chunk);
01337         if (chunk.end >= parent.end)
01338             break;
01339         unsigned short id = chunk.id;
01340         uint end = chunk.end;
01341         chunk = ReadChunk();
01342         // try to detect a endless loop amz
01343         if(id == chunk.id && end == chunk.end)
01344             break;
01345     }
01346     if (chunk.id == target.id)
01347     {
01348         target.start = chunk.start;
01349         target.end = chunk.end;
01350         return true;
01351     }
01352     return false;
01353 }
01354
01355 void L3DS::SkipChunk(const LChunk &chunk)
01356 {
01357     Seek(chunk.end, SEEK_START);
01358 }
01359
01360 void L3DS::GotoChunk(const LChunk &chunk)
01361 {
01362     Seek(chunk.start, SEEK_START);
01363 }
01364
01365 LColor3 L3DS::ReadColor(const LChunk &chunk)
01366 {
01367     LColor3 col = black;
01368     GotoChunk(chunk);
01369     switch (chunk.id)
01370     {
01371     case COLOR_F:
01372         col.r = ReadFloat();
01373         col.g = ReadFloat();
01374         col.b = ReadFloat();
01375         break;
01376     case COLOR_24:
01377         col.r = ReadByte()/255.0f;
01378         col.g = ReadByte()/255.0f;
01379         col.b = ReadByte()/255.0f;
01380         break;
01381     case LIN_COLOR_F:
01382         col.r = ReadFloat();
01383         col.g = ReadFloat();
01384         col.b = ReadFloat();
01385         break;
01386     case LIN_COLOR_24:
01387         col.r = ReadByte()/255.0f;
01388         col.g = ReadByte()/255.0f;
01389         col.b = ReadByte()/255.0f;
01390         break;
01391     default:
01392         fprintf(stderr, "L3DS::ReadColor - error this is not a color chunk");
01393     }
01394     return col;
01395 }
01396
01397 float L3DS::ReadPercentage(const LChunk &chunk)
01398 {
01399     GotoChunk(chunk);
01400     switch (chunk.id)
01401     {
01402     case INT_PERCENTAGE:
01403         return (ReadShort()/100.0f);
01404     case FLOAT_PERCENTAGE:
01405         return ReadFloat();
01406     }
01407     fprintf(stderr, "L3DS::ReadPercentage - error, the chunk is not a percentage chunk");
01408     return 0;
01409 }
01410
01411 bool L3DS::Read3DS()
01412 {
01413     LChunk mainchunk;
01414     LChunk edit;
01415     edit.id = EDIT3DS;
01416     mainchunk = ReadChunk();
01417     if (mainchunk.id != MAIN3DS)
01418     {
01419         fprintf(stderr, "L3DS::Read3DS - wrong file format");
01420         return false;
01421     }
01422     if (!FindChunk(edit, mainchunk))
01423         return false;
01424     LChunk obj;
01425     LChunk ml;
01426
01427     GotoChunk(edit);
01428     obj.id = MAT_ENTRY;
01429     while (FindChunk(obj, edit))
01430     {
01431         ReadMaterial(obj);
01432         SkipChunk(obj);
01433     }
01434     GotoChunk(edit);
01435
01436     obj.id = EDIT_OBJECT;
01437     {
01438         while (FindChunk(obj, edit))
01439         {
01440             ReadASCIIZ(m_objName, 99);
01441             ml = ReadChunk();
01442             if (ml.id == OBJ_TRIMESH)
01443                 ReadMesh(ml);
01444             else
01445             if (ml.id == OBJ_LIGHT)
01446                 ReadLight(ml);
01447             else
01448             if (ml.id == OBJ_CAMERA)
01449                 ReadCamera(ml);
01450             SkipChunk(obj);
01451         }
01452     }
01453
01454     // read the keyframer data here to find out correct object orientation
01455
01456     LChunk keyframer;
01457     keyframer.id = KFDATA;
01458
01459     LChunk objtrack;
01460     objtrack.id = OBJECT_NODE_TAG;
01461
01462     GotoChunk(mainchunk);
01463     if (FindChunk(keyframer, mainchunk))
01464     {   // keyframer chunk is present
01465         GotoChunk(keyframer);
01466         while (FindChunk(objtrack, keyframer))
01467         {
01468             ReadKeyframeData(objtrack);
01469             SkipChunk(objtrack);
01470         }
01471     }
01472
01473     for (uint i=0; i<m_meshes.size(); i++)
01474         m_meshes[i].Optimize(m_optLevel);
01475     m_pos = 0;
01476     strcpy(m_objName, "");
01477     return true;
01478 }
01479
01480 void L3DS::ReadLight(const LChunk &parent)
01481 {
01482     float t;
01483     LVector3 v;
01484     LLight light;
01485     light.SetName(m_objName);
01486     v.x = ReadFloat();
01487     v.y = ReadFloat();
01488     v.z = ReadFloat();
01489     light.SetPosition(v);
01490     LChunk chunk = ReadChunk();
01491     while (chunk.end <= parent.end)
01492     {
01493         switch (chunk.id)
01494         {
01495         case COLOR_24:
01496         case COLOR_F:
01497         case LIN_COLOR_F:
01498         case LIN_COLOR_24:
01499             light.SetColor(ReadColor(chunk));
01500             break;
01501         case SPOTLIGHT:
01502             v.x = ReadFloat();
01503             v.y = ReadFloat();
01504             v.z = ReadFloat();
01505             light.SetTarget(v);
01506             t = ReadFloat();
01507             light.SetHotspot(t);
01508             t = ReadFloat();
01509             light.SetFalloff(t);
01510             break;
01511         case LIT_INRANGE:
01512             light.SetAttenuationstart(ReadFloat());
01513             break;
01514         case LIT_OUTRANGE:
01515             light.SetAttenuationend(ReadFloat());
01516             break;
01517         default:
01518             break;
01519         }
01520         SkipChunk(chunk);
01521         if (chunk.end >= parent.end)
01522             break;
01523         chunk = ReadChunk();
01524
01525     }
01526     m_lights.push_back(light);
01527 }
01528
01529 void L3DS::ReadCamera(const LChunk &parent)
01530 {
01531     LVector3 v,t;
01532     LCamera camera;
01533     camera.SetName(m_objName);
01534     v.x = ReadFloat();
01535     v.y = ReadFloat();
01536     v.z = ReadFloat();
01537     t.x = ReadFloat();
01538     t.y = ReadFloat();
01539     t.z = ReadFloat();
01540     camera.SetPosition(v);
01541     camera.SetTarget(t);
01542     camera.SetBank(ReadFloat());
01543     camera.SetFOV(2400.0f/ReadFloat());
01544     LChunk chunk = ReadChunk();
01545     while (chunk.end <= parent.end)
01546     {
01547         switch (chunk.id)
01548         {
01549         case CAM_RANGES:
01550             camera.SetNearplane(ReadFloat());
01551             camera.SetFarplane(ReadFloat());
01552             break;
01553         default:
01554             break;
01555         }
01556         SkipChunk(chunk);
01557         if (chunk.end >= parent.end)
01558             break;
01559         chunk = ReadChunk();
01560
01561     }
01562     m_cameras.push_back(camera);
01563 }
01564
01565 void L3DS::ReadMesh(const LChunk &parent)
01566 {
01567     unsigned short count, i;
01568     LVector4 p;
01569     LMatrix4 m;
01570     LVector2 t;
01571     p.w = 1.0f;
01572     LMesh mesh;
01573     mesh.SetName(m_objName);
01574     GotoChunk(parent);
01575     LChunk chunk = ReadChunk();
01576     while (chunk.end <= parent.end)
01577     {
01578         switch (chunk.id)
01579         {
01580         case TRI_VERTEXLIST:
01581             count = ReadShort();
01582             mesh.SetVertexArraySize(count);
01583             for (i=0; i < count; i++)
01584             {
01585                 p.x = ReadFloat();
01586                 p.y = ReadFloat();
01587                 p.z = ReadFloat();
01588                 mesh.SetVertex(p, i);
01589             }
01590             break;
01591         case TRI_FACEMAPPING:
01592             count = ReadShort();
01593             if (mesh.GetVertexCount() == 0)
01594                 mesh.SetVertexArraySize(count);
01595             for (i=0; i < count; i++)
01596             {
01597                 t.x = ReadFloat();
01598                 t.y = ReadFloat();
01599                 mesh.SetUV(t, i);
01600             }
01601             break;
01602         case TRI_FACELIST:
01603             ReadFaceList(chunk, mesh);
01604             break;
01605         case TRI_MATRIX:
01606             m._11 = ReadFloat();
01607             m._12 = ReadFloat();
01608             m._13 = ReadFloat();
01609
01610             m._21 = ReadFloat();
01611             m._22 = ReadFloat();
01612             m._23 = ReadFloat();
01613
01614             m._31 = ReadFloat();
01615             m._32 = ReadFloat();
01616             m._33 = ReadFloat();
01617
01618             m._41 = ReadFloat();
01619             m._42 = ReadFloat();
01620             m._43 = ReadFloat();
01621
01622             m._14 = 0.0f;
01623             m._24 = 0.0f;
01624             m._34 = 0.0f;
01625             m._44 = 1.0f;
01626
01627             mesh.SetMatrix(m);
01628             break;
01629         default:
01630             break;
01631         }
01632         SkipChunk(chunk);
01633         if (chunk.end >= parent.end)
01634             break;
01635         chunk = ReadChunk();
01636     }
01637     m_meshes.push_back(mesh);
01638 }
01639
01640 void L3DS::ReadFaceList(const LChunk &chunk, LMesh &mesh)
01641 {
01642     // variables
01643     unsigned short count, t;
01644     uint i;
01645     LTri tri;
01646     LChunk ch;
01647     char str[20];
01648     //uint mat;
01649
01650     // consistency checks
01651     if (chunk.id != TRI_FACELIST)
01652     {
01653         fprintf(stderr, "L3DS::ReadFaceList - internal error: wrong chunk passed as parameter");
01654         return;
01655     }
01656     GotoChunk(chunk);
01657     tri.smoothingGroups = 1;
01658     // read the number of faces
01659     count = ReadShort();
01660     mesh.SetTriangleArraySize(count);
01661     for (i=0; i<count; i++)
01662     {
01663         tri.a = ReadShort();
01664         tri.b = ReadShort();
01665         tri.c = ReadShort();
01666         ReadShort();
01667         mesh.SetTri(tri, i);
01668     }
01669     // now read the optional chunks
01670     ch = ReadChunk();
01671     int mat_id;
01672     while (ch.end <= chunk.end)
01673     {
01674         switch (ch.id)
01675         {
01676         case TRI_MAT_GROUP:
01677             ReadASCIIZ(str, 20);
01678             mat_id = FindMaterial(str)->GetID();
01679             mesh.AddMaterial(mat_id);
01680             count = ReadShort();
01681             for (i=0; i<count; i++)
01682             {
01683                 t = ReadShort();
01684                 mesh.GetTri(t).materialId = mat_id;
01685             }
01686             break;
01687         case TRI_SMOOTH_GROUP:
01688             for (i=0; i<mesh.GetTriangleCount(); i++)
01689                 mesh.GetTri(i).smoothingGroups = ulong(ReadInt());
01690             break;
01691         }
01692         SkipChunk(ch);
01693         ch = ReadChunk();
01694     }
01695 }
01696
01697 void L3DS::ReadMaterial(const LChunk &parent)
01698 {
01699     // variables
01700     LChunk chunk;
01701     LChunk child;
01702     char str[30];
01703     LMaterial mat;
01704     short sh;
01705
01706     GotoChunk(parent);
01707
01708     chunk = ReadChunk();
01709     while (chunk.end <= parent.end)
01710     {
01711         switch (chunk.id)
01712         {
01713         case MAT_NAME:
01714             ReadASCIIZ(str, 30);
01715             mat.SetName(str);
01716             break;
01717         case MAT_AMBIENT:
01718             child = ReadChunk();
01719             mat.SetAmbientColor(ReadColor(child));
01720             break;
01721         case MAT_DIFFUSE:
01722             child = ReadChunk();
01723             mat.SetDiffuseColor(ReadColor(child));
01724             break;
01725         case MAT_SPECULAR:
01726             child = ReadChunk();
01727             mat.SetSpecularColor(ReadColor(child));
01728             break;
01729         case MAT_SHININESS:
01730             child = ReadChunk();
01731             mat.SetShininess(ReadPercentage(child));
01732             break;
01733         case MAT_TRANSPARENCY:
01734             child = ReadChunk();
01735             mat.SetTransparency(ReadPercentage(child));
01736             break;
01737         case MAT_SHADING:
01738             sh = ReadShort();
01739             switch (sh)
01740             {
01741             case 0:
01742                 mat.SetShadingType(sWireframe);
01743                 break;
01744             case 1:
01745                 mat.SetShadingType(sFlat);
01746                 break;
01747             case 2:
01748                 mat.SetShadingType(sGouraud);
01749                 break;
01750             case 3:
01751                 mat.SetShadingType(sPhong);
01752                 break;
01753             case 4:
01754                 mat.SetShadingType(sMetal);
01755                 break;
01756             }
01757             break;
01758         case MAT_WIRE:
01759             mat.SetShadingType(sWireframe);
01760             break;
01761         case MAT_TEXMAP:
01762             ReadMap(chunk, mat.GetTextureMap1());
01763             break;
01764         case MAT_TEX2MAP:
01765             ReadMap(chunk, mat.GetTextureMap2());
01766             break;
01767         case MAT_OPACMAP:
01768             ReadMap(chunk, mat.GetOpacityMap());
01769             break;
01770         case MAT_BUMPMAP:
01771             ReadMap(chunk, mat.GetBumpMap());
01772             break;
01773         case MAT_SPECMAP:
01774             ReadMap(chunk, mat.GetSpecularMap());
01775             break;
01776         case MAT_REFLMAP:
01777             // AMZ not really a bugfix but it seems to work!
01778 #if 1
01779             ReadMap(chunk, mat.GetReflectionMap());
01780 #else
01781             child = ReadChunk();
01782             mat.GetReflectionMap().strength = ReadPercentage(child);
01783             SkipChunk(child);
01784             child = ReadChunk();
01785             if (child.id != MAT_MAPNAME)
01786             {
01787                 fprintf(stderr, "L3DS::ReadMaterial - error, expected chunk not found");
01788                 return;
01789             }
01790             ReadASCIIZ(str, 30);
01791             if (strcmp(str, "") == 0)
01792                 strcpy(mat.GetReflectionMap().mapName, "auto");
01793 #endif
01794             break;
01795         }
01796
01797         SkipChunk(chunk);
01798         chunk = ReadChunk();
01799     }
01800     m_materials.push_back(mat);
01801     m_materials[m_materials.size()-1].SetID(m_materials.size()-1);
01802 }
01803
01804 void L3DS::ReadMap(const LChunk &chunk, LMap& map)
01805 {
01806     LChunk child;
01807     char str[20];
01808     GotoChunk(chunk);
01809     child = ReadChunk();
01810     while (child.end <= chunk.end)
01811     {
01812         switch (child.id)
01813         {
01814         case INT_PERCENTAGE:
01815             map.strength = ReadPercentage(child);
01816             break;
01817         case MAT_MAPNAME:
01818             ReadASCIIZ(str, 20);
01819             strcpy(map.mapName, str);
01820             break;
01821         case MAT_MAP_TILING:
01822             map.tiling = ReadShort();
01823             break;
01824         case MAT_MAP_USCALE:
01825             map.uScale = ReadFloat();
01826             break;
01827         case MAT_MAP_VSCALE:
01828             map.vScale = ReadFloat();
01829             break;
01830         case MAT_MAP_UOFFSET:
01831             map.uOffset = ReadFloat();
01832             break;
01833         case MAT_MAP_VOFFSET:
01834             map.vOffset = ReadFloat();
01835             break;
01836         case MAT_MAP_ANG:
01837             map.angle = ReadFloat();
01838             break;
01839         }
01840         SkipChunk(child);
01841         child = ReadChunk();
01842     }
01843 }
01844
01845 void L3DS::ReadKeyframeData(const LChunk &parent)
01846 {
01847     uint frames = 0;
01848
01849     LChunk node_hdr;
01850     node_hdr.id = NODE_HDR;
01851
01852     char str[20];
01853     LMesh *mesh;
01854
01855     GotoChunk(parent);
01856     if (!FindChunk(node_hdr, parent))
01857         return;
01858     GotoChunk(node_hdr);
01859     ReadASCIIZ(str, 19);
01860     mesh = FindMesh(str);
01861     if (mesh == 0)
01862         return;
01863     GotoChunk(parent);
01864
01865     // read the pivot
01866     //LVector3 pivot = zero3;
01867
01868     LChunk pivotchunk;
01869     pivotchunk.id = PIVOT;
01870     if (FindChunk(pivotchunk, parent))
01871     {
01872         GotoChunk(pivotchunk);
01873         /*pivot.x =*/ ReadFloat();
01874         /*pivot.y =*/ ReadFloat();
01875         /*pivot.z =*/ ReadFloat();
01876     }
01877     GotoChunk(parent);
01878
01879     // read frame 0 from the position track
01880     //LVector3 pos = zero3;
01881
01882     frames = 0;
01883
01884     LChunk poschunk;
01885     poschunk.id = POS_TRACK_TAG;
01886     if (FindChunk(poschunk, parent))
01887     {
01888         GotoChunk(poschunk);
01889         // read the trackheader structure
01890         ReadShort();
01891         ReadInt();
01892         ReadInt();
01893         frames = ReadInt();
01894         if (frames > 0)
01895         {
01896             ReadKeyheader();
01897             /*pos.x =*/ ReadFloat();
01898             /*pos.y =*/ ReadFloat();
01899             /*pos.z =*/ ReadFloat();
01900         }
01901     }
01902     GotoChunk(parent);
01903
01904     // now read the rotation track
01905     //LVector4 rot = zero4;
01906
01907     LChunk rotchunk;
01908     rotchunk.id = ROT_TRACK_TAG;
01909
01910     frames = 0;
01911     if (FindChunk(rotchunk, parent))
01912     {
01913         GotoChunk(rotchunk);
01914         // read the trackheader structure
01915         ReadShort();
01916         ReadInt();
01917         ReadInt();
01918         frames = ReadInt();
01919         if (frames > 0)
01920         {
01921             ReadKeyheader();
01922             /*rot.x =*/ ReadFloat();
01923             /*rot.y =*/ ReadFloat();
01924             /*rot.z =*/ ReadFloat();
01925             /*rot.w =*/ ReadFloat();
01926         }
01927     }
01928     GotoChunk(parent);
01929
01930     // now read the scaling chunk
01931     //LVector3 scale;
01932     //scale.x = 1;
01933     //scale.y = 1;
01934     //scale.z = 1;
01935
01936     LChunk scalechunk;
01937     scalechunk.id = SCL_TRACK_TAG;
01938
01939     frames = 0;
01940
01941     if (FindChunk(scalechunk, parent))
01942     {
01943         GotoChunk(scalechunk);
01944         // read the trackheader structure
01945         ReadShort();
01946         ReadInt();
01947         ReadInt();
01948         frames = ReadInt();
01949         if (frames > 0)
01950         {
01951             ReadKeyheader();
01952             /*scale.x =*/ ReadFloat();
01953             /*scale.y =*/ ReadFloat();
01954             /*scale.z =*/ ReadFloat();
01955         }
01956     }
01957     GotoChunk(parent);
01958 }
01959
01960 long L3DS::ReadKeyheader()
01961 {
01962     long frame;
01963     frame = ReadInt();
01964     short opts = ReadShort();
01965     if (opts & 32768) // 32768 is 1000000000000000 binary
01966     {  // tension is present
01967         ReadFloat();
01968     }
01969     if (opts & 16384) // 16384 is 0100000000000000 binary
01970     {  // continuity is present
01971         ReadFloat();
01972     }
01973     if (opts & 8192)
01974     {  // bias info present
01975         ReadFloat();
01976     }
01977     if (opts & 4096)
01978     {  // "ease to" present
01979         ReadFloat();
01980     }
01981     if (opts & 2048)
01982     {  // "ease from" present
01983         ReadFloat();
01984     }
01985     return frame;
01986 }