fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / FileIO / 3DS / OSG3DSLoader.cpp
blobccd23d99a08c2471a1bd971b8f654f6e4838c4c2
1 // copyright (c) 2001 Lev Povalahev
3 #include <cstdio>
4 #include <cstdlib>
5 #include <cstring>
6 #include <cmath>
8 #include "OSG3DSLoader.h"
10 //using namespace std;
12 //-------------------------------------------------------
13 // generic stuff
14 //-------------------------------------------------------
16 #define SEEK_START 1900
17 #define SEEK_CURSOR 1901
19 // common chunks
20 // colors
21 #define COLOR_F 0x0010
22 #define COLOR_24 0x0011
23 #define LIN_COLOR_24 0x0012
24 #define LIN_COLOR_F 0x0013
26 // percentage
27 #define INT_PERCENTAGE 0x0030
28 #define FLOAT_PERCENTAGE 0x0031
30 // ambient light
31 #define AMBIENT_LIGHT 0x2100
33 #define MAIN3DS 0x4D4D
34 #define EDIT3DS 0x3D3D // this is the start of the editor config
36 // keyframer chunk ids
37 #define KFDATA 0xB000 // the keyframer section
38 #define KFHDR 0xB00A
39 #define OBJECT_NODE_TAG 0xB002
40 #define NODE_HDR 0xB010
41 #define PIVOT 0xB013
42 #define POS_TRACK_TAG 0xB020
43 #define ROT_TRACK_TAG 0xB021
44 #define SCL_TRACK_TAG 0xB022
46 // material entries
47 #define MAT_ENTRY 0xAFFF
48 #define MAT_NAME 0xA000
49 #define MAT_AMBIENT 0xA010
50 #define MAT_DIFFUSE 0xA020
51 #define MAT_SPECULAR 0xA030
52 #define MAT_SHININESS 0xA040
53 #define MAT_SHIN2PCT 0xA041
54 #define MAT_TRANSPARENCY 0xA050
55 #define MAT_SHADING 0xA100
56 #define MAT_TWO_SIDE 0xA081
57 #define MAT_ADDITIVE 0xA083
58 #define MAT_WIRE 0xA085
59 #define MAT_FACEMAP 0xA088
60 #define MAT_WIRESIZE 0xA087
61 #define MAT_DECAL 0xA082
62 #define MAT_TEXMAP 0xA200
63 #define MAT_MAPNAME 0xA300
64 #define MAT_MAP_TILING 0xA351
65 #define MAT_MAP_USCALE 0xA354
66 #define MAT_MAP_VSCALE 0xA356
67 #define MAT_MAP_UOFFSET 0xA358
68 #define MAT_MAP_VOFFSET 0xA35A
69 #define MAT_MAP_ANG 0xA35C
70 #define MAT_TEX2MAP 0xA33A
71 #define MAT_OPACMAP 0xA210
72 #define MAT_BUMPMAP 0xA230
73 #define MAT_SPECMAP 0xA204
74 #define MAT_SHINMAP 0xA33C
75 #define MAT_REFLMAP 0xA220
76 #define MAT_ACUBIC 0xA310
78 #define EDIT_OBJECT 0x4000
79 #define OBJ_TRIMESH 0x4100
80 #define OBJ_LIGHT 0x4600
81 #define OBJ_CAMERA 0x4700
83 #define CAM_RANGES 0x4720
85 #define LIT_OFF 0x4620
86 #define LIT_SPOT 0x4610
87 #define LIT_INRANGE 0x4659
88 #define LIT_OUTRANGE 0x465A
90 #define TRI_VERTEXLIST 0x4110
91 #define TRI_VERTEXOPTIONS 0x4111
92 #define TRI_FACELIST 0x4120
93 #define TRI_MAT_GROUP 0x4130
94 #define TRI_SMOOTH_GROUP 0x4150
95 #define TRI_FACEMAPPING 0x4140
96 #define TRI_MATRIX 0x4160
97 #define TRI_TEXTURE_INFO 0x4170
99 #define SPOTLIGHT 0x4610
101 //----------------------------------
103 #define MAX_SHARED_TRIS 100
105 // the error reporting routine
107 // globals
109 LColor3 black = {0, 0, 0};
111 LVector3 zero3 = {0, 0, 0};
113 LVector4 zero4 = {0, 0, 0, 0};
115 LMap emptyMap = {0, "", 1, 1, 0, 0, 0, 0};
117 LVector3 _4to3(const LVector4 &vec)
119 LVector3 t;
120 t.x = vec.x;
121 t.y = vec.y;
122 t.z = vec.z;
123 return t;
126 LVector3 AddVectors(const LVector3 &a, const LVector3 &b)
128 LVector3 t;
129 t.x = a.x+b.x;
130 t.y = a.y+b.y;
131 t.z = a.z+b.z;
132 return t;
135 LVector3 SubtractVectors(const LVector3 &a, const LVector3 &b)
137 LVector3 t;
138 t.x = a.x-b.x;
139 t.y = a.y-b.y;
140 t.z = a.z-b.z;
141 return t;
144 float VectorLength(const LVector3 &vec)
146 return float(sqrt(vec.x*vec.x + vec.y*vec.y+vec.z*vec.z));
149 LVector3 NormalizeVector(const LVector3 &vec)
151 float a = VectorLength(vec);
152 if (a == 0)
153 return vec;
154 float b = 1/a;
155 LVector3 v;
156 v.x = vec.x*b;
157 v.y = vec.y*b;
158 v.z = vec.z*b;
159 return v;
162 LVector3 CrossProduct(const LVector3 &a, const LVector3 &b)
164 LVector3 v;
165 v.x = a.y*b.z - a.z*b.y;
166 v.y = a.z*b.x - a.x*b.z;
167 v.z = a.x*b.y - a.y*b.x;
168 return v;
171 void LoadIdentityMatrix(LMatrix4 &m)
173 m._11 = 1.0f;
174 m._12 = 0.0f;
175 m._13 = 0.0f;
176 m._14 = 0.0f;
178 m._21 = 0.0f;
179 m._22 = 1.0f;
180 m._23 = 0.0f;
181 m._24 = 0.0f;
183 m._31 = 0.0f;
184 m._32 = 0.0f;
185 m._33 = 1.0f;
186 m._34 = 0.0f;
188 m._41 = 0.0f;
189 m._42 = 0.0f;
190 m._43 = 1.0f;
191 m._44 = 0.0f;
194 LVector4 VectorByMatrix(const LMatrix4 &m, const LVector4 &vec)
196 LVector4 res;
197 res.x = m._11*vec.x + m._12*vec.y + m._13*vec.z + m._14*vec.w;
198 res.y = m._21*vec.x + m._22*vec.y + m._23*vec.z + m._24*vec.w;
199 res.z = m._31*vec.x + m._32*vec.y + m._33*vec.z + m._34*vec.w;
200 res.w = m._41*vec.x + m._42*vec.y + m._43*vec.z + m._44*vec.w;
201 if (res.w != 0)
203 float b = 1/res.w;
204 res.x *= b;
205 res.y *= b;
206 res.z *= b;
207 res.w = 1;
209 else
210 res.w = 1;
212 return res;
215 //-------------------------------------------------------
216 // LObject implementation
217 //-------------------------------------------------------
219 LObject::LObject() :
220 m_name("")
224 LObject::~LObject()
226 // nothing here
229 void LObject::SetName(const std::string& value)
231 m_name = value;
234 const std::string& LObject::GetName()
236 return m_name;
239 bool LObject::IsObject(const std::string &name)
241 return (m_name == name);
245 //-------------------------------------------------------
246 // LMaterial implementation
247 //-------------------------------------------------------
249 LMaterial::LMaterial() :
250 LObject ( ),
251 m_id (0 ),
252 m_texMap1 (emptyMap),
253 m_texMap2 (emptyMap),
254 m_opacMap (emptyMap),
255 m_reflMap (emptyMap),
256 m_bumpMap (emptyMap),
257 m_specMap (emptyMap),
258 m_ambient (black ),
259 m_diffuse (black ),
260 m_specular (black ),
261 m_shininess (0 ),
262 m_transparency(0 ),
263 m_shading (sGouraud)
267 LMaterial::~LMaterial()
272 uint LMaterial::GetID()
274 return m_id;
277 LMap& LMaterial::GetTextureMap1()
279 return m_texMap1;
282 LMap& LMaterial::GetTextureMap2()
284 return m_texMap2;
287 LMap& LMaterial::GetOpacityMap()
289 return m_opacMap;
292 LMap& LMaterial::GetSpecularMap()
294 return m_specMap;
297 LMap& LMaterial::GetBumpMap()
299 return m_bumpMap;
302 LMap& LMaterial::GetReflectionMap()
304 return m_reflMap;
307 LColor3 LMaterial::GetAmbientColor()
309 return m_ambient;
312 LColor3 LMaterial::GetDiffuseColor()
314 return m_diffuse;
317 LColor3 LMaterial::GetSpecularColor()
319 return m_specular;
322 float LMaterial::GetShininess()
324 return m_shininess;
327 float LMaterial::GetTransparency()
329 return m_transparency;
332 LShading LMaterial::GetShadingType()
334 return m_shading;
337 void LMaterial::SetID(uint value)
339 m_id = value;
342 void LMaterial::SetAmbientColor(const LColor3 &color)
344 m_ambient = color;
347 void LMaterial::SetDiffuseColor(const LColor3 &color)
349 m_diffuse = color;
352 void LMaterial::SetSpecularColor(const LColor3 &color)
354 m_specular = color;
357 void LMaterial::SetShininess(float value)
359 m_shininess = value;
360 if (m_shininess < 0)
361 m_shininess = 0;
362 if (m_shininess > 1)
363 m_shininess = 1;
366 void LMaterial::SetTransparency(float value)
368 m_transparency = value;
369 if (m_transparency < 0)
370 m_transparency = 0;
371 if (m_transparency > 1)
372 m_transparency = 1;
375 void LMaterial::SetShadingType(LShading shading)
377 m_shading = shading;
380 //-------------------------------------------------------
381 // LMesh implementation
382 //-------------------------------------------------------
384 LMesh::LMesh() :
385 LObject(),
386 m_vertices(),
387 m_normals(),
388 m_binormals(),
389 m_tangents(),
390 m_uv(),
392 m_triangles(),
394 m_tris(),
396 m_matrix(),
398 // the material ID array
399 m_materials()
402 Clear();
405 LMesh::~LMesh()
407 Clear();
410 void LMesh::Clear()
412 m_vertices.clear();
413 m_normals.clear();
414 m_uv.clear();
415 m_tangents.clear();
416 m_binormals.clear();
417 m_triangles.clear();
418 m_tris.clear();
419 m_materials.clear();
420 LoadIdentityMatrix(m_matrix);
423 uint LMesh::GetVertexCount()
425 return uint(m_vertices.size());
428 void LMesh::SetVertexArraySize(uint value)
430 m_vertices.resize(value);
431 m_normals.resize(value);
432 m_uv.resize(value);
433 m_tangents.resize(value);
434 m_binormals.resize(value);
437 uint LMesh::GetTriangleCount()
439 return uint(m_triangles.size());
442 void LMesh::SetTriangleArraySize(uint value)
444 m_triangles.resize(value);
445 m_tris.resize(value);
448 const LVector4& LMesh::GetVertex(uint index)
450 return m_vertices[index];
453 const LVector3& LMesh::GetNormal(uint index)
455 return m_normals[index];
458 const LVector2& LMesh::GetUV(uint index)
460 return m_uv[index];
463 const LVector3& LMesh::GetTangent(uint index)
465 return m_tangents[index];
468 const LVector3& LMesh::GetBinormal(uint index)
470 return m_binormals[index];
473 void LMesh::SetVertex(const LVector4 &vec, uint index)
475 if (index >= m_vertices.size())
476 return;
477 m_vertices[index] = vec;
480 void LMesh::SetNormal(const LVector3 &vec, uint index)
482 if (index >= m_vertices.size())
483 return;
484 m_normals[index] = vec;
487 void LMesh::SetUV(const LVector2 &vec, uint index)
489 if (index >= m_vertices.size())
490 return;
491 m_uv[index] = vec;
494 void LMesh::SetTangent(const LVector3 &vec, uint index)
496 if (index >= m_vertices.size())
497 return;
498 m_tangents[index] = vec;
501 void LMesh::SetBinormal(const LVector3 &vec, uint index)
503 if (index >= m_vertices.size())
504 return;
505 m_binormals[index] = vec;
508 const LTriangle& LMesh::GetTriangle(uint index)
510 return m_triangles[index];
513 LTriangle2 LMesh::GetTriangle2(uint index)
515 LTriangle2 f;
516 LTriangle t = GetTriangle(index);
517 f.vertices[0] = GetVertex(t.a);
518 f.vertices[1] = GetVertex(t.b);
519 f.vertices[2] = GetVertex(t.c);
521 f.vertexNormals[0] = GetNormal(t.a);
522 f.vertexNormals[1] = GetNormal(t.b);
523 f.vertexNormals[2] = GetNormal(t.c);
525 f.textureCoords[0] = GetUV(t.a);
526 f.textureCoords[1] = GetUV(t.b);
527 f.textureCoords[2] = GetUV(t.c);
529 LVector3 a, b;
531 a = SubtractVectors(_4to3(f.vertices[1]), _4to3(f.vertices[0]));
532 b = SubtractVectors(_4to3(f.vertices[1]), _4to3(f.vertices[2]));
534 f.faceNormal = CrossProduct(b, a);
536 f.faceNormal = NormalizeVector(f.faceNormal);
538 f.materialId = m_tris[index].materialId;
540 return f;
543 LMatrix4 LMesh::GetMatrix()
545 return m_matrix;
548 void LMesh::SetMatrix(LMatrix4 m)
550 m_matrix = m;
553 void LMesh::TransformVertices()
555 for (uint i=0; i<m_vertices.size(); i++)
556 m_vertices[i] = VectorByMatrix(m_matrix, m_vertices[i]);
559 void LMesh::CalcNormals(bool useSmoothingGroups)
561 uint i;
562 // first calculate the face normals
563 for (i=0; i<m_triangles.size(); i++)
565 LVector3 a, b;
566 a = SubtractVectors(_4to3(m_vertices[m_tris[i].b]), _4to3(m_vertices[m_tris[i].a]));
567 b = SubtractVectors(_4to3(m_vertices[m_tris[i].b]), _4to3(m_vertices[m_tris[i].c]));
568 m_tris[i].normal = NormalizeVector(CrossProduct(b, a));
571 std::vector< std::vector<int> > array;
572 array.resize(m_vertices.size());
573 for (i=0; i<m_triangles.size(); i++)
575 uint k = m_tris[i].a;
576 array[k].push_back(i);
578 k = m_tris[i].b;
579 array[k].push_back(i);
581 k = m_tris[i].c;
582 array[k].push_back(i);
585 LVector3 temp;
587 if (!useSmoothingGroups)
589 // now calculate the normals without using smoothing groups
590 for (i=0; i<m_vertices.size(); i++)
592 temp = zero3;
593 int t = int(array[i].size());
595 for (int k=0; k<t; k++)
597 temp.x += m_tris[array[i][k]].normal.x;
598 temp.y += m_tris[array[i][k]].normal.y;
599 temp.z += m_tris[array[i][k]].normal.z;
601 m_normals[i] = NormalizeVector(temp);
604 else
606 // now calculate the normals _USING_ smoothing groups
607 // I'm assuming a triangle can only belong to one smoothing group at a time!
608 std::vector<ulong> smGroups;
609 std::vector< std::vector <uint> > smList;
611 uint loop_size = uint(m_vertices.size());
613 for (i=0; i<loop_size; i++)
615 int t = uint(array[i].size());
617 if (t == 0)
618 continue;
620 smGroups.clear();
621 smList.clear();
622 smGroups.push_back(m_tris[array[i][0]].smoothingGroups);
623 smList.resize(smGroups.size());
624 smList[smGroups.size()-1].push_back(array[i][0]);
626 // first build a list of smoothing groups for the vertex
627 for (int k=0; k<t; k++)
629 bool found = false;
630 for (uint j=0; j<smGroups.size(); j++)
632 if (m_tris[array[i][k]].smoothingGroups == smGroups[j])
634 smList[j].push_back(array[i][k]);
635 found = true;
638 if (!found)
640 smGroups.push_back(m_tris[array[i][k]].smoothingGroups);
641 smList.resize(smGroups.size());
642 smList[smGroups.size()-1].push_back(array[i][k]);
645 // now we have the list of faces for the vertex sorted by smoothing groups
648 // now duplicate the vertices so that there's only one smoothing group "per vertex"
649 if (smGroups.size() > 1)
650 for (uint j=1; j< smGroups.size(); j++)
652 m_vertices.push_back(m_vertices[i]);
653 m_normals.push_back(m_normals[i]);
654 m_uv.push_back(m_uv[i]);
655 m_tangents.push_back(m_tangents[i]);
656 m_binormals.push_back(m_binormals[i]);
658 uint ts = uint(m_vertices.size())-1;
659 for (uint h=0; h<smList[j].size(); h++)
661 if (m_tris[smList[j][h]].a == i)
662 m_tris[smList[j][h]].a = ts;
663 if (m_tris[smList[j][h]].b == i)
664 m_tris[smList[j][h]].b = ts;
665 if (m_tris[smList[j][h]].c == i)
666 m_tris[smList[j][h]].c = ts;
671 // now rebuild a face list for each vertex, since the old one is invalidated
672 for (i=0; i<array.size(); i++)
673 array[i].clear();
674 array.clear();
675 array.resize(m_vertices.size());
676 for (i=0; i<m_triangles.size(); i++)
678 uint k = m_tris[i].a;
679 array[k].push_back(i);
681 k = m_tris[i].b;
682 array[k].push_back(i);
684 k = m_tris[i].c;
685 array[k].push_back(i);
688 // now compute the normals
689 for (i=0; i<m_vertices.size(); i++)
691 temp = zero3;
692 int t = uint(array[i].size());
694 for (int k=0; k<t; k++)
696 temp.x += m_tris[array[i][k]].normal.x;
697 temp.y += m_tris[array[i][k]].normal.y;
698 temp.z += m_tris[array[i][k]].normal.z;
700 m_normals[i] = NormalizeVector(temp);
705 // copy m_tris to m_triangles
706 for (i=0; i<m_triangles.size(); i++)
708 m_triangles[i].a = m_tris[i].a;
709 m_triangles[i].b = m_tris[i].b;
710 m_triangles[i].c = m_tris[i].c;
714 void LMesh::CalcTextureSpace()
716 // a understandable description of how to do that can be found here:
717 // http://members.rogers.com/deseric/tangentspace.htm
718 // first calculate the tangent for each triangle
719 LVector3 x_vec,
720 y_vec,
721 z_vec;
722 LVector3 v1, v2;
723 for (uint i=0; i<m_triangles.size(); i++)
725 v1.x = m_vertices[m_tris[i].b].x - m_vertices[m_tris[i].a].x;
726 v1.y = m_uv[m_tris[i].b].x - m_uv[m_tris[i].a].x;
727 v1.z = m_uv[m_tris[i].b].y - m_uv[m_tris[i].a].y;
729 v2.x = m_vertices[m_tris[i].c].x - m_vertices[m_tris[i].a].x;
730 v2.y = m_uv[m_tris[i].c].x - m_uv[m_tris[i].a].x;
731 v2.z = m_uv[m_tris[i].c].y - m_uv[m_tris[i].a].y;
733 x_vec = CrossProduct(v1, v2);
735 v1.x = m_vertices[m_tris[i].b].y - m_vertices[m_tris[i].a].y;
736 v1.y = m_uv[m_tris[i].b].x - m_uv[m_tris[i].a].x;
737 v1.z = m_uv[m_tris[i].b].y - m_uv[m_tris[i].a].y;
739 v2.x = m_vertices[m_tris[i].c].y - m_vertices[m_tris[i].a].y;
740 v2.y = m_uv[m_tris[i].c].x - m_uv[m_tris[i].a].x;
741 v2.z = m_uv[m_tris[i].c].y - m_uv[m_tris[i].a].y;
743 y_vec = CrossProduct(v1, v2);
745 v1.x = m_vertices[m_tris[i].b].z - m_vertices[m_tris[i].a].z;
746 v1.y = m_uv[m_tris[i].b].x - m_uv[m_tris[i].a].x;
747 v1.z = m_uv[m_tris[i].b].y - m_uv[m_tris[i].a].y;
749 v2.x = m_vertices[m_tris[i].c].z - m_vertices[m_tris[i].a].z;
750 v2.y = m_uv[m_tris[i].c].x - m_uv[m_tris[i].a].x;
751 v2.z = m_uv[m_tris[i].c].y - m_uv[m_tris[i].a].y;
753 z_vec = CrossProduct(v1, v2);
755 m_tris[i].tangent.x = -(x_vec.y/x_vec.x);
756 m_tris[i].tangent.y = -(y_vec.y/y_vec.x);
757 m_tris[i].tangent.z = -(z_vec.y/z_vec.x);
759 m_tris[i].binormal.x = -(x_vec.z/x_vec.x);
760 m_tris[i].binormal.y = -(y_vec.z/y_vec.x);
761 m_tris[i].binormal.z = -(z_vec.z/z_vec.x);
765 // now for each vertex build a list of face that share this vertex
766 std::vector< std::vector<int> > array;
767 array.resize(m_vertices.size());
768 for (size_t i=0; i<m_triangles.size(); i++)
770 uint k = m_tris[i].a;
771 array[k].push_back(int(i));
773 k = m_tris[i].b;
774 array[k].push_back(int(i));
776 k = m_tris[i].c;
777 array[k].push_back(int(i));
780 // now average the tangents and compute the binormals as (tangent X normal)
781 for (size_t i=0; i<m_vertices.size(); i++)
783 v1 = zero3;
784 v2 = zero3;
785 int t = int(array[i].size());
787 for (int k=0; k<t; k++)
789 v1.x += m_tris[array[i][k]].tangent.x;
790 v1.y += m_tris[array[i][k]].tangent.y;
791 v1.z += m_tris[array[i][k]].tangent.z;
793 v2.x += m_tris[array[i][k]].binormal.x;
794 v2.y += m_tris[array[i][k]].binormal.y;
795 v2.z += m_tris[array[i][k]].binormal.z;
797 m_tangents[i] = NormalizeVector(v1);
798 //m_binormals[i] = NormalizeVector(v2);
800 m_binormals[i] = NormalizeVector(CrossProduct(m_tangents[i], m_normals[i]));
804 void LMesh::Optimize(LOptimizationLevel value)
806 switch (value)
808 case oNone:
809 TransformVertices();
810 break;
811 case oSimple:
812 //TransformVertices();
813 CalcNormals(false);
814 break;
815 case oFull:
816 //TransformVertices();
817 CalcNormals(true);
818 CalcTextureSpace();
819 break;
823 void LMesh::SetTri(const LTri &tri, uint index)
825 if (index >= m_triangles.size())
826 return;
827 m_tris[index] = tri;
830 LTri& LMesh::GetTri(uint index)
832 return m_tris[index];
835 uint LMesh::GetMaterial(uint index)
837 return m_materials[index];
840 uint LMesh::AddMaterial(uint id)
842 m_materials.push_back(id);
843 return uint(m_materials.size())-1;
846 uint LMesh::GetMaterialCount()
848 return uint(m_materials.size());
851 //-------------------------------------------------------
852 // LCamera implementation
853 //-------------------------------------------------------
855 LCamera::LCamera() :
856 LObject(),
857 m_pos(),
858 m_target(),
859 m_bank(0),
860 m_fov(0),
861 m_near(0),
862 m_far()
864 Clear();
867 LCamera::~LCamera()
872 void LCamera::Clear()
874 m_pos.x = m_pos.y = m_pos.z = 0.0f;
875 m_target.x = m_target.y = m_target.z = 0.0f;
876 m_fov = 80;
877 m_bank = 0;;
878 m_near = 10;
879 m_far = 10000;
882 void LCamera::SetPosition(LVector3 vec)
884 m_pos = vec;
887 LVector3 LCamera::GetPosition()
889 return m_pos;
892 void LCamera::SetTarget(LVector3 target)
894 m_target = target;
897 LVector3 LCamera::GetTarget()
899 return m_target;
902 void LCamera::SetFOV(float value)
904 m_fov = value;
907 float LCamera::GetFOV()
909 return m_fov;
912 void LCamera::SetBank(float value)
914 m_bank = value;
917 float LCamera::GetBank()
919 return m_bank;
922 void LCamera::SetNearplane(float value)
924 m_near = value;
927 float LCamera::GetNearplane()
929 return m_near;
932 void LCamera::SetFarplane(float value)
934 m_far = value;
937 float LCamera::GetFarplane()
939 return m_far;
942 //-------------------------------------------------------
943 // LLight implementation
944 //-------------------------------------------------------
946 LLight::LLight() :
947 LObject(),
948 m_pos(),
949 m_color(),
950 m_spotlight(),
951 m_target(),
952 m_hotspot(),
953 m_falloff(),
954 m_attenuationstart(),
955 m_attenuationend()
957 Clear();
960 LLight::~LLight()
965 void LLight::Clear()
967 m_pos.x = m_pos.y = m_pos.z = 0.0f;
968 m_color.r = m_color.g = m_color.b = 0.0f;
969 m_spotlight = false;
970 m_attenuationend = 100;
971 m_attenuationstart = 1000;
974 void LLight::SetPosition(LVector3 vec)
976 m_pos = vec;
979 LVector3 LLight::GetPosition()
981 return m_pos;
984 void LLight::SetColor(LColor3 color)
986 m_color = color;
989 LColor3 LLight::GetColor()
991 return m_color;
994 void LLight::SetSpotlight(bool value)
996 m_spotlight = value;
999 bool LLight::GetSpotlight()
1001 return m_spotlight;
1004 void LLight::SetTarget(LVector3 target)
1006 m_target = target;
1009 LVector3 LLight::GetTarget()
1011 return m_target;
1014 void LLight::SetHotspot(float value)
1016 m_hotspot = value;
1019 float LLight::GetHotspot()
1021 return m_hotspot;
1024 void LLight::SetFalloff(float value)
1026 m_falloff = value;
1029 float LLight::GetFalloff()
1031 return m_falloff;
1034 void LLight::SetAttenuationstart(float value)
1036 m_attenuationend = value;
1039 float LLight::GetAttenuationstart()
1041 return m_attenuationend;
1044 void LLight::SetAttenuationend(float value)
1046 m_attenuationstart = value;
1049 float LLight::GetAttenuationend()
1051 return m_attenuationstart;
1054 //-------------------------------------------------------
1055 // LImporter implementation
1056 //-------------------------------------------------------
1058 LImporter::LImporter():
1059 m_cameras(),
1060 m_lights(),
1061 m_meshes(),
1062 m_materials(),
1063 m_optLevel()
1065 Clear();
1068 LImporter::~LImporter()
1070 Clear();
1073 uint LImporter::GetMeshCount()
1075 return uint(m_meshes.size());
1078 uint LImporter::GetLightCount()
1080 return uint(m_lights.size());
1083 uint LImporter::GetMaterialCount()
1085 return uint(m_materials.size());
1088 uint LImporter::GetCameraCount()
1090 return uint(m_cameras.size());
1093 LMesh& LImporter::GetMesh(uint index)
1095 return m_meshes[index];
1098 LLight& LImporter::GetLight(uint index)
1100 return m_lights[index];
1103 LMaterial& LImporter::GetMaterial(uint index)
1105 return m_materials[index];
1108 LCamera& LImporter::GetCamera(uint index)
1110 return m_cameras[index];
1113 LMaterial* LImporter::FindMaterial(const std::string& name)
1115 for (uint i=0; i<m_materials.size(); i++)
1116 if (m_materials[i].IsObject(name))
1117 return &m_materials[i];
1118 return 0;
1121 LMesh* LImporter::FindMesh(const std::string& name)
1123 for (uint i=0; i<m_meshes.size(); i++)
1124 if (m_meshes[i].IsObject(name))
1125 return &m_meshes[i];
1126 return 0;
1129 LLight* LImporter::FindLight(const std::string& name)
1131 for (uint i=0; i<m_lights.size(); i++)
1132 if (m_lights[i].IsObject(name))
1133 return &m_lights[i];
1134 return 0;
1137 void LImporter::Clear()
1139 m_meshes.clear();
1140 m_lights.clear();
1141 m_materials.clear();
1142 m_optLevel = oFull;
1145 void LImporter::SetOptimizationLevel(LOptimizationLevel value)
1147 m_optLevel = value;
1150 LOptimizationLevel LImporter::GetOptimizationLevel()
1152 return m_optLevel;
1155 //-------------------------------------------------------
1156 // L3DS implementation
1157 //-------------------------------------------------------
1159 L3DS::L3DS() :
1160 LImporter(),
1161 m_eof(false),
1162 m_buffer(0),
1163 m_bufferSize(0),
1164 m_pos(0)
1168 L3DS::L3DS(const char *filename) :
1169 LImporter(),
1170 m_eof(false),
1171 m_buffer(0),
1172 m_bufferSize(0),
1173 m_pos(0)
1176 Load(filename);
1179 L3DS::~L3DS()
1181 if (m_bufferSize > 0)
1182 free(m_buffer);
1185 bool L3DS::Load(std::istream &is)
1187 // get length of file:
1188 is.seekg(0, std::ios::end);
1189 m_bufferSize = is.tellg();
1190 is.seekg(0, std::ios::beg);
1192 m_buffer = static_cast<unsigned char*>(calloc(m_bufferSize, 1));
1193 if (m_buffer == 0)
1195 fprintf(stderr, "L3DS::LoadFile - not enough memory (malloc failed)");
1196 return false;
1198 is.read(reinterpret_cast<char *>(m_buffer), m_bufferSize);
1199 if(is.gcount() != std::streamsize(m_bufferSize))
1201 free(m_buffer);
1202 m_bufferSize = 0;
1203 fprintf(stderr, "L3DS::LoadFile - error reading from stream");
1204 return false;
1207 Clear();
1208 bool res = Read3DS();
1209 free(m_buffer);
1210 m_buffer = 0;
1211 m_bufferSize = 0;
1212 return res;
1215 bool L3DS::Load(const char *filename)
1217 FILE *f;
1218 f = fopen(filename, "rb");
1219 if (f == 0)
1221 fprintf(stderr, "L3DS::LoadFile - cannot open file");
1222 return false;
1224 fseek(f, 0, SEEK_END);
1225 m_bufferSize = ftell(f);
1226 fseek(f, 0, SEEK_SET);
1227 m_buffer = static_cast<unsigned char *>(calloc(m_bufferSize, 1));
1228 if (m_buffer == 0)
1230 fprintf(stderr, "L3DS::LoadFile - not enough memory (malloc failed)");
1231 return false;
1233 if (fread(m_buffer, m_bufferSize, 1, f) != 1)
1235 fclose(f);
1236 free(m_buffer);
1237 m_bufferSize = 0;
1238 fprintf(stderr, "L3DS::LoadFile - error reading from file");
1239 return false;
1241 fclose(f);
1243 Clear();
1244 bool res = Read3DS();
1245 free(m_buffer);
1246 m_buffer = 0;
1247 m_bufferSize = 0;
1248 return res;
1251 short L3DS::ReadShort()
1253 if ((m_buffer!=0) && (m_bufferSize != 0) && ((m_pos+2)<m_bufferSize))
1255 short *w = reinterpret_cast<short *>(m_buffer+m_pos);
1256 short s = *w;//(short)*(m_buffer+m_pos);
1257 m_pos += 2;
1258 return s;
1260 m_eof = true;
1261 return 0;
1264 int L3DS::ReadInt()
1266 if ((m_buffer!=0) && (m_bufferSize != 0) && ((m_pos+4)<m_bufferSize))
1268 int *w = reinterpret_cast<int *>(m_buffer+m_pos);
1269 int s = *w;//(int)*(m_buffer+m_pos);
1270 m_pos += 4;
1271 return s;
1273 m_eof = true;
1274 return 0;
1277 char L3DS::ReadChar()
1279 if ((m_buffer!=0) && (m_bufferSize != 0) && ((m_pos+1)<m_bufferSize))
1281 char s = char(*(m_buffer+m_pos));
1282 m_pos += 1;
1283 return s;
1285 m_eof = true;
1286 return 0;
1289 float L3DS::ReadFloat()
1291 if ((m_buffer!=0) && (m_bufferSize != 0) && ((m_pos+4)<m_bufferSize))
1293 float *w = reinterpret_cast<float *>(m_buffer+m_pos);
1294 float s = *w;//(float)*(m_buffer+m_pos);
1295 m_pos += 4;
1296 return s;
1298 m_eof = true;
1299 return 0.0;
1302 byte L3DS::ReadByte()
1304 if ((m_buffer!=0) && (m_bufferSize != 0) && ((m_pos+1)<m_bufferSize))
1306 byte s = byte(*(m_buffer+m_pos));
1307 m_pos += 1;
1308 return s;
1310 m_eof = true;
1311 return 0;
1314 int L3DS::ReadASCIIZ(char *buf, int max_count)
1316 int count;
1317 if ((m_buffer==0) || (m_bufferSize == 0) || (m_pos>=m_bufferSize))
1319 count = 0;
1320 m_eof = true;
1321 return count;
1323 count = 0;
1324 char c = ReadChar();
1325 while ((c!=0) && (count<max_count-1))
1327 buf[count] = c;
1328 count ++;
1329 c = ReadChar();
1331 buf[count] = 0;
1332 return count;
1335 void L3DS::Seek(int offset, int origin)
1337 if (origin == SEEK_START)
1338 m_pos = offset;
1339 if (origin == SEEK_CURSOR)
1340 m_pos += offset;
1341 if (static_cast<signed>(m_pos) < 0)
1342 m_pos = 0;
1343 if (m_pos >= m_bufferSize)
1344 m_pos = m_bufferSize-1;
1345 m_eof = false;
1348 uint L3DS::Pos()
1350 return m_pos;
1353 LChunk L3DS::ReadChunk()
1355 LChunk chunk;
1356 chunk.id = ReadShort();
1357 int a = ReadInt();
1358 chunk.start = Pos();
1359 chunk.end = chunk.start+a-6;
1360 return chunk;
1363 bool L3DS::FindChunk(LChunk &target, const LChunk &parent)
1365 if (Pos() >= parent.end)
1366 return false;
1367 LChunk chunk;
1368 chunk = ReadChunk();
1369 while (( chunk.id != target.id) && (chunk.end <= parent.end))
1371 SkipChunk(chunk);
1372 if (chunk.end >= parent.end)
1373 break;
1374 unsigned short id = chunk.id;
1375 uint end = chunk.end;
1376 chunk = ReadChunk();
1377 // try to detect a endless loop amz
1378 if(id == chunk.id && end == chunk.end)
1379 break;
1381 if (chunk.id == target.id)
1383 target.start = chunk.start;
1384 target.end = chunk.end;
1385 return true;
1387 return false;
1390 void L3DS::SkipChunk(const LChunk &chunk)
1392 Seek(chunk.end, SEEK_START);
1395 void L3DS::GotoChunk(const LChunk &chunk)
1397 Seek(chunk.start, SEEK_START);
1400 LColor3 L3DS::ReadColor(const LChunk &chunk)
1402 LColor3 col = black;
1403 GotoChunk(chunk);
1404 switch (chunk.id)
1406 case COLOR_F:
1407 col.r = ReadFloat();
1408 col.g = ReadFloat();
1409 col.b = ReadFloat();
1410 break;
1411 case COLOR_24:
1412 col.r = ReadByte()/255.0f;
1413 col.g = ReadByte()/255.0f;
1414 col.b = ReadByte()/255.0f;
1415 break;
1416 case LIN_COLOR_F:
1417 col.r = ReadFloat();
1418 col.g = ReadFloat();
1419 col.b = ReadFloat();
1420 break;
1421 case LIN_COLOR_24:
1422 col.r = ReadByte()/255.0f;
1423 col.g = ReadByte()/255.0f;
1424 col.b = ReadByte()/255.0f;
1425 break;
1426 default:
1427 fprintf(stderr, "L3DS::ReadColor - error this is not a color chunk");
1429 return col;
1432 float L3DS::ReadPercentage(const LChunk &chunk)
1434 GotoChunk(chunk);
1435 switch (chunk.id)
1437 case INT_PERCENTAGE:
1438 return (ReadShort()/100.0f);
1439 case FLOAT_PERCENTAGE:
1440 return ReadFloat();
1442 fprintf(stderr, "L3DS::ReadPercentage - error, the chunk is not a percentage chunk");
1443 return 0;
1446 bool L3DS::Read3DS()
1448 LChunk mainchunk;
1449 LChunk edit;
1450 edit.id = EDIT3DS;
1451 mainchunk = ReadChunk();
1452 if (mainchunk.id != MAIN3DS)
1454 fprintf(stderr, "L3DS::Read3DS - wrong file format");
1455 return false;
1457 if (!FindChunk(edit, mainchunk))
1458 return false;
1459 LChunk obj;
1460 LChunk ml;
1462 GotoChunk(edit);
1463 obj.id = MAT_ENTRY;
1464 while (FindChunk(obj, edit))
1466 ReadMaterial(obj);
1467 SkipChunk(obj);
1469 GotoChunk(edit);
1471 obj.id = EDIT_OBJECT;
1473 while (FindChunk(obj, edit))
1475 ReadASCIIZ(m_objName, 99);
1476 ml = ReadChunk();
1477 if (ml.id == OBJ_TRIMESH)
1478 ReadMesh(ml);
1479 else
1480 if (ml.id == OBJ_LIGHT)
1481 ReadLight(ml);
1482 else
1483 if (ml.id == OBJ_CAMERA)
1484 ReadCamera(ml);
1485 SkipChunk(obj);
1489 // read the keyframer data here to find out correct object orientation
1491 LChunk keyframer;
1492 keyframer.id = KFDATA;
1494 LChunk objtrack;
1495 objtrack.id = OBJECT_NODE_TAG;
1497 GotoChunk(mainchunk);
1498 if (FindChunk(keyframer, mainchunk))
1499 { // keyframer chunk is present
1500 GotoChunk(keyframer);
1501 while (FindChunk(objtrack, keyframer))
1503 ReadKeyframeData(objtrack);
1504 SkipChunk(objtrack);
1508 for (uint i=0; i<m_meshes.size(); i++)
1509 m_meshes[i].Optimize(m_optLevel);
1510 m_pos = 0;
1511 strcpy(m_objName, "");
1512 return true;
1515 void L3DS::ReadLight(const LChunk &parent)
1517 float t;
1518 LVector3 v;
1519 LLight light;
1520 light.SetName(m_objName);
1521 v.x = ReadFloat();
1522 v.y = ReadFloat();
1523 v.z = ReadFloat();
1524 light.SetPosition(v);
1525 LChunk chunk = ReadChunk();
1526 while (chunk.end <= parent.end)
1528 switch (chunk.id)
1530 case COLOR_24:
1531 case COLOR_F:
1532 case LIN_COLOR_F:
1533 case LIN_COLOR_24:
1534 light.SetColor(ReadColor(chunk));
1535 break;
1536 case SPOTLIGHT:
1537 v.x = ReadFloat();
1538 v.y = ReadFloat();
1539 v.z = ReadFloat();
1540 light.SetTarget(v);
1541 t = ReadFloat();
1542 light.SetHotspot(t);
1543 t = ReadFloat();
1544 light.SetFalloff(t);
1545 break;
1546 case LIT_INRANGE:
1547 light.SetAttenuationstart(ReadFloat());
1548 break;
1549 case LIT_OUTRANGE:
1550 light.SetAttenuationend(ReadFloat());
1551 break;
1552 default:
1553 break;
1555 SkipChunk(chunk);
1556 if (chunk.end >= parent.end)
1557 break;
1558 chunk = ReadChunk();
1561 m_lights.push_back(light);
1564 void L3DS::ReadCamera(const LChunk &parent)
1566 LVector3 v,t;
1567 LCamera camera;
1568 camera.SetName(m_objName);
1569 v.x = ReadFloat();
1570 v.y = ReadFloat();
1571 v.z = ReadFloat();
1572 t.x = ReadFloat();
1573 t.y = ReadFloat();
1574 t.z = ReadFloat();
1575 camera.SetPosition(v);
1576 camera.SetTarget(t);
1577 camera.SetBank(ReadFloat());
1578 camera.SetFOV(2400.0f/ReadFloat());
1579 LChunk chunk = ReadChunk();
1580 while (chunk.end <= parent.end)
1582 switch (chunk.id)
1584 case CAM_RANGES:
1585 camera.SetNearplane(ReadFloat());
1586 camera.SetFarplane(ReadFloat());
1587 break;
1588 default:
1589 break;
1591 SkipChunk(chunk);
1592 if (chunk.end >= parent.end)
1593 break;
1594 chunk = ReadChunk();
1597 m_cameras.push_back(camera);
1600 void L3DS::ReadMesh(const LChunk &parent)
1602 unsigned short count, i;
1603 LVector4 p;
1604 LMatrix4 m;
1605 LVector2 t;
1606 p.w = 1.0f;
1607 LMesh mesh;
1608 mesh.SetName(m_objName);
1609 GotoChunk(parent);
1610 LChunk chunk = ReadChunk();
1611 while (chunk.end <= parent.end)
1613 switch (chunk.id)
1615 case TRI_VERTEXLIST:
1616 count = ReadShort();
1617 mesh.SetVertexArraySize(count);
1618 for (i=0; i < count; i++)
1620 p.x = ReadFloat();
1621 p.y = ReadFloat();
1622 p.z = ReadFloat();
1623 mesh.SetVertex(p, i);
1625 break;
1626 case TRI_FACEMAPPING:
1627 count = ReadShort();
1628 if (mesh.GetVertexCount() == 0)
1629 mesh.SetVertexArraySize(count);
1630 for (i=0; i < count; i++)
1632 t.x = ReadFloat();
1633 t.y = ReadFloat();
1634 mesh.SetUV(t, i);
1636 break;
1637 case TRI_FACELIST:
1638 ReadFaceList(chunk, mesh);
1639 break;
1640 case TRI_MATRIX:
1641 m._11 = ReadFloat();
1642 m._12 = ReadFloat();
1643 m._13 = ReadFloat();
1645 m._21 = ReadFloat();
1646 m._22 = ReadFloat();
1647 m._23 = ReadFloat();
1649 m._31 = ReadFloat();
1650 m._32 = ReadFloat();
1651 m._33 = ReadFloat();
1653 m._41 = ReadFloat();
1654 m._42 = ReadFloat();
1655 m._43 = ReadFloat();
1657 m._14 = 0.0f;
1658 m._24 = 0.0f;
1659 m._34 = 0.0f;
1660 m._44 = 1.0f;
1662 mesh.SetMatrix(m);
1663 break;
1664 default:
1665 break;
1667 SkipChunk(chunk);
1668 if (chunk.end >= parent.end)
1669 break;
1670 chunk = ReadChunk();
1672 m_meshes.push_back(mesh);
1675 void L3DS::ReadFaceList(const LChunk &chunk, LMesh &mesh)
1677 // variables
1678 unsigned short count, t;
1679 uint i;
1680 LTri tri;
1681 LChunk ch;
1682 char str[20];
1683 //uint mat;
1685 // consistency checks
1686 if (chunk.id != TRI_FACELIST)
1688 fprintf(stderr, "L3DS::ReadFaceList - internal error: wrong chunk passed as parameter");
1689 return;
1691 GotoChunk(chunk);
1692 tri.smoothingGroups = 1;
1693 // read the number of faces
1694 count = ReadShort();
1695 mesh.SetTriangleArraySize(count);
1696 for (i=0; i<count; i++)
1698 tri.a = ReadShort();
1699 tri.b = ReadShort();
1700 tri.c = ReadShort();
1701 ReadShort();
1702 mesh.SetTri(tri, i);
1704 // now read the optional chunks
1705 ch = ReadChunk();
1706 int mat_id;
1707 while (ch.end <= chunk.end)
1709 switch (ch.id)
1711 case TRI_MAT_GROUP:
1713 ReadASCIIZ(str, 20);
1715 LMaterial *pMat = FindMaterial(str);
1717 if(pMat != NULL)
1719 mat_id = pMat->GetID();
1721 mesh.AddMaterial(mat_id);
1724 count = ReadShort();
1725 for (i=0; i<count; i++)
1727 t = ReadShort();
1728 if(pMat != NULL)
1729 mesh.GetTri(t).materialId = mat_id;
1732 break;
1734 case TRI_SMOOTH_GROUP:
1735 for (i=0; i<mesh.GetTriangleCount(); i++)
1736 mesh.GetTri(i).smoothingGroups = ulong(ReadInt());
1737 break;
1739 SkipChunk(ch);
1740 ch = ReadChunk();
1744 void L3DS::ReadMaterial(const LChunk &parent)
1746 // variables
1747 LChunk chunk;
1748 LChunk child;
1749 char str[30];
1750 LMaterial mat;
1751 short sh;
1753 GotoChunk(parent);
1755 chunk = ReadChunk();
1756 while (chunk.end <= parent.end)
1758 switch (chunk.id)
1760 case MAT_NAME:
1761 ReadASCIIZ(str, 30);
1762 mat.SetName(str);
1763 break;
1764 case MAT_AMBIENT:
1765 child = ReadChunk();
1766 mat.SetAmbientColor(ReadColor(child));
1767 break;
1768 case MAT_DIFFUSE:
1769 child = ReadChunk();
1770 mat.SetDiffuseColor(ReadColor(child));
1771 break;
1772 case MAT_SPECULAR:
1773 child = ReadChunk();
1774 mat.SetSpecularColor(ReadColor(child));
1775 break;
1776 case MAT_SHININESS:
1777 child = ReadChunk();
1778 mat.SetShininess(ReadPercentage(child));
1779 break;
1780 case MAT_TRANSPARENCY:
1781 child = ReadChunk();
1782 mat.SetTransparency(ReadPercentage(child));
1783 break;
1784 case MAT_SHADING:
1785 sh = ReadShort();
1786 switch (sh)
1788 case 0:
1789 mat.SetShadingType(sWireframe);
1790 break;
1791 case 1:
1792 mat.SetShadingType(sFlat);
1793 break;
1794 case 2:
1795 mat.SetShadingType(sGouraud);
1796 break;
1797 case 3:
1798 mat.SetShadingType(sPhong);
1799 break;
1800 case 4:
1801 mat.SetShadingType(sMetal);
1802 break;
1804 break;
1805 case MAT_WIRE:
1806 mat.SetShadingType(sWireframe);
1807 break;
1808 case MAT_TEXMAP:
1809 ReadMap(chunk, mat.GetTextureMap1());
1810 break;
1811 case MAT_TEX2MAP:
1812 ReadMap(chunk, mat.GetTextureMap2());
1813 break;
1814 case MAT_OPACMAP:
1815 ReadMap(chunk, mat.GetOpacityMap());
1816 break;
1817 case MAT_BUMPMAP:
1818 ReadMap(chunk, mat.GetBumpMap());
1819 break;
1820 case MAT_SPECMAP:
1821 ReadMap(chunk, mat.GetSpecularMap());
1822 break;
1823 case MAT_REFLMAP:
1824 // AMZ not really a bugfix but it seems to work!
1825 #if 1
1826 ReadMap(chunk, mat.GetReflectionMap());
1827 #else
1828 child = ReadChunk();
1829 mat.GetReflectionMap().strength = ReadPercentage(child);
1830 SkipChunk(child);
1831 child = ReadChunk();
1832 if (child.id != MAT_MAPNAME)
1834 fprintf(stderr, "L3DS::ReadMaterial - error, expected chunk not found");
1835 return;
1837 ReadASCIIZ(str, 30);
1838 if (strcmp(str, "") == 0)
1839 strcpy(mat.GetReflectionMap().mapName, "auto");
1840 #endif
1841 break;
1844 SkipChunk(chunk);
1845 chunk = ReadChunk();
1847 m_materials.push_back(mat);
1848 m_materials[m_materials.size()-1].SetID(uint(m_materials.size())-1);
1851 void L3DS::ReadMap(const LChunk &chunk, LMap& map)
1853 LChunk child;
1854 char str[20];
1855 GotoChunk(chunk);
1856 child = ReadChunk();
1857 while (child.end <= chunk.end)
1859 switch (child.id)
1861 case INT_PERCENTAGE:
1862 map.strength = ReadPercentage(child);
1863 break;
1864 case MAT_MAPNAME:
1865 ReadASCIIZ(str, 20);
1866 strcpy(map.mapName, str);
1867 break;
1868 case MAT_MAP_TILING:
1869 map.tiling = ReadShort();
1870 break;
1871 case MAT_MAP_USCALE:
1872 map.uScale = ReadFloat();
1873 break;
1874 case MAT_MAP_VSCALE:
1875 map.vScale = ReadFloat();
1876 break;
1877 case MAT_MAP_UOFFSET:
1878 map.uOffset = ReadFloat();
1879 break;
1880 case MAT_MAP_VOFFSET:
1881 map.vOffset = ReadFloat();
1882 break;
1883 case MAT_MAP_ANG:
1884 map.angle = ReadFloat();
1885 break;
1887 SkipChunk(child);
1888 child = ReadChunk();
1892 void L3DS::ReadKeyframeData(const LChunk &parent)
1894 uint frames = 0;
1896 LChunk node_hdr;
1897 node_hdr.id = NODE_HDR;
1899 char str[20];
1900 LMesh *mesh;
1902 GotoChunk(parent);
1903 if (!FindChunk(node_hdr, parent))
1904 return;
1905 GotoChunk(node_hdr);
1906 ReadASCIIZ(str, 19);
1907 mesh = FindMesh(str);
1908 if (mesh == 0)
1909 return;
1910 GotoChunk(parent);
1912 // read the pivot
1913 //LVector3 pivot = zero3;
1915 LChunk pivotchunk;
1916 pivotchunk.id = PIVOT;
1917 if (FindChunk(pivotchunk, parent))
1919 GotoChunk(pivotchunk);
1920 /*pivot.x =*/ ReadFloat();
1921 /*pivot.y =*/ ReadFloat();
1922 /*pivot.z =*/ ReadFloat();
1924 GotoChunk(parent);
1926 // read frame 0 from the position track
1927 //LVector3 pos = zero3;
1929 frames = 0;
1931 LChunk poschunk;
1932 poschunk.id = POS_TRACK_TAG;
1933 if (FindChunk(poschunk, parent))
1935 GotoChunk(poschunk);
1936 // read the trackheader structure
1937 ReadShort();
1938 ReadInt();
1939 ReadInt();
1940 frames = ReadInt();
1941 if (frames > 0)
1943 ReadKeyheader();
1944 /*pos.x =*/ ReadFloat();
1945 /*pos.y =*/ ReadFloat();
1946 /*pos.z =*/ ReadFloat();
1949 GotoChunk(parent);
1951 // now read the rotation track
1952 //LVector4 rot = zero4;
1954 LChunk rotchunk;
1955 rotchunk.id = ROT_TRACK_TAG;
1957 frames = 0;
1958 if (FindChunk(rotchunk, parent))
1960 GotoChunk(rotchunk);
1961 // read the trackheader structure
1962 ReadShort();
1963 ReadInt();
1964 ReadInt();
1965 frames = ReadInt();
1966 if (frames > 0)
1968 ReadKeyheader();
1969 /*rot.x =*/ ReadFloat();
1970 /*rot.y =*/ ReadFloat();
1971 /*rot.z =*/ ReadFloat();
1972 /*rot.w =*/ ReadFloat();
1975 GotoChunk(parent);
1977 // now read the scaling chunk
1978 //LVector3 scale;
1979 //scale.x = 1;
1980 //scale.y = 1;
1981 //scale.z = 1;
1983 LChunk scalechunk;
1984 scalechunk.id = SCL_TRACK_TAG;
1986 frames = 0;
1988 if (FindChunk(scalechunk, parent))
1990 GotoChunk(scalechunk);
1991 // read the trackheader structure
1992 ReadShort();
1993 ReadInt();
1994 ReadInt();
1995 frames = ReadInt();
1996 if (frames > 0)
1998 ReadKeyheader();
1999 /*scale.x =*/ ReadFloat();
2000 /*scale.y =*/ ReadFloat();
2001 /*scale.z =*/ ReadFloat();
2004 GotoChunk(parent);
2007 long L3DS::ReadKeyheader()
2009 long frame;
2010 frame = ReadInt();
2011 short opts = ReadShort();
2012 if (opts & 32768) // 32768 is 1000000000000000 binary
2013 { // tension is present
2014 ReadFloat();
2016 if (opts & 16384) // 16384 is 0100000000000000 binary
2017 { // continuity is present
2018 ReadFloat();
2020 if (opts & 8192)
2021 { // bias info present
2022 ReadFloat();
2024 if (opts & 4096)
2025 { // "ease to" present
2026 ReadFloat();
2028 if (opts & 2048)
2029 { // "ease from" present
2030 ReadFloat();
2032 return frame;