1 // copyright (c) 2001 Lev Povalahev
8 #include "OSG3DSLoader.h"
10 //using namespace std;
12 //-------------------------------------------------------
14 //-------------------------------------------------------
16 #define SEEK_START 1900
17 #define SEEK_CURSOR 1901
21 #define COLOR_F 0x0010
22 #define COLOR_24 0x0011
23 #define LIN_COLOR_24 0x0012
24 #define LIN_COLOR_F 0x0013
27 #define INT_PERCENTAGE 0x0030
28 #define FLOAT_PERCENTAGE 0x0031
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
39 #define OBJECT_NODE_TAG 0xB002
40 #define NODE_HDR 0xB010
42 #define POS_TRACK_TAG 0xB020
43 #define ROT_TRACK_TAG 0xB021
44 #define SCL_TRACK_TAG 0xB022
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
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
)
126 LVector3
AddVectors(const LVector3
&a
, const LVector3
&b
)
135 LVector3
SubtractVectors(const LVector3
&a
, const LVector3
&b
)
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
);
162 LVector3
CrossProduct(const LVector3
&a
, const LVector3
&b
)
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
;
171 void LoadIdentityMatrix(LMatrix4
&m
)
194 LVector4
VectorByMatrix(const LMatrix4
&m
, const LVector4
&vec
)
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
;
215 //-------------------------------------------------------
216 // LObject implementation
217 //-------------------------------------------------------
229 void LObject::SetName(const std::string
& value
)
234 const std::string
& LObject::GetName()
239 bool LObject::IsObject(const std::string
&name
)
241 return (m_name
== name
);
245 //-------------------------------------------------------
246 // LMaterial implementation
247 //-------------------------------------------------------
249 LMaterial::LMaterial() :
252 m_texMap1 (emptyMap
),
253 m_texMap2 (emptyMap
),
254 m_opacMap (emptyMap
),
255 m_reflMap (emptyMap
),
256 m_bumpMap (emptyMap
),
257 m_specMap (emptyMap
),
267 LMaterial::~LMaterial()
272 uint
LMaterial::GetID()
277 LMap
& LMaterial::GetTextureMap1()
282 LMap
& LMaterial::GetTextureMap2()
287 LMap
& LMaterial::GetOpacityMap()
292 LMap
& LMaterial::GetSpecularMap()
297 LMap
& LMaterial::GetBumpMap()
302 LMap
& LMaterial::GetReflectionMap()
307 LColor3
LMaterial::GetAmbientColor()
312 LColor3
LMaterial::GetDiffuseColor()
317 LColor3
LMaterial::GetSpecularColor()
322 float LMaterial::GetShininess()
327 float LMaterial::GetTransparency()
329 return m_transparency
;
332 LShading
LMaterial::GetShadingType()
337 void LMaterial::SetID(uint value
)
342 void LMaterial::SetAmbientColor(const LColor3
&color
)
347 void LMaterial::SetDiffuseColor(const LColor3
&color
)
352 void LMaterial::SetSpecularColor(const LColor3
&color
)
357 void LMaterial::SetShininess(float value
)
366 void LMaterial::SetTransparency(float value
)
368 m_transparency
= value
;
369 if (m_transparency
< 0)
371 if (m_transparency
> 1)
375 void LMaterial::SetShadingType(LShading shading
)
380 //-------------------------------------------------------
381 // LMesh implementation
382 //-------------------------------------------------------
398 // the material ID array
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
);
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
)
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())
477 m_vertices
[index
] = vec
;
480 void LMesh::SetNormal(const LVector3
&vec
, uint index
)
482 if (index
>= m_vertices
.size())
484 m_normals
[index
] = vec
;
487 void LMesh::SetUV(const LVector2
&vec
, uint index
)
489 if (index
>= m_vertices
.size())
494 void LMesh::SetTangent(const LVector3
&vec
, uint index
)
496 if (index
>= m_vertices
.size())
498 m_tangents
[index
] = vec
;
501 void LMesh::SetBinormal(const LVector3
&vec
, uint index
)
503 if (index
>= m_vertices
.size())
505 m_binormals
[index
] = vec
;
508 const LTriangle
& LMesh::GetTriangle(uint index
)
510 return m_triangles
[index
];
513 LTriangle2
LMesh::GetTriangle2(uint index
)
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
);
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
;
543 LMatrix4
LMesh::GetMatrix()
548 void LMesh::SetMatrix(LMatrix4 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
)
562 // first calculate the face normals
563 for (i
=0; i
<m_triangles
.size(); i
++)
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
);
579 array
[k
].push_back(i
);
582 array
[k
].push_back(i
);
587 if (!useSmoothingGroups
)
589 // now calculate the normals without using smoothing groups
590 for (i
=0; i
<m_vertices
.size(); i
++)
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
);
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());
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
++)
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
]);
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
++)
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
);
682 array
[k
].push_back(i
);
685 array
[k
].push_back(i
);
688 // now compute the normals
689 for (i
=0; i
<m_vertices
.size(); i
++)
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
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
));
774 array
[k
].push_back(int(i
));
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
++)
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
)
812 //TransformVertices();
816 //TransformVertices();
823 void LMesh::SetTri(const LTri
&tri
, uint index
)
825 if (index
>= m_triangles
.size())
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 //-------------------------------------------------------
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
;
882 void LCamera::SetPosition(LVector3 vec
)
887 LVector3
LCamera::GetPosition()
892 void LCamera::SetTarget(LVector3 target
)
897 LVector3
LCamera::GetTarget()
902 void LCamera::SetFOV(float value
)
907 float LCamera::GetFOV()
912 void LCamera::SetBank(float value
)
917 float LCamera::GetBank()
922 void LCamera::SetNearplane(float value
)
927 float LCamera::GetNearplane()
932 void LCamera::SetFarplane(float value
)
937 float LCamera::GetFarplane()
942 //-------------------------------------------------------
943 // LLight implementation
944 //-------------------------------------------------------
954 m_attenuationstart(),
967 m_pos
.x
= m_pos
.y
= m_pos
.z
= 0.0f
;
968 m_color
.r
= m_color
.g
= m_color
.b
= 0.0f
;
970 m_attenuationend
= 100;
971 m_attenuationstart
= 1000;
974 void LLight::SetPosition(LVector3 vec
)
979 LVector3
LLight::GetPosition()
984 void LLight::SetColor(LColor3 color
)
989 LColor3
LLight::GetColor()
994 void LLight::SetSpotlight(bool value
)
999 bool LLight::GetSpotlight()
1004 void LLight::SetTarget(LVector3 target
)
1009 LVector3
LLight::GetTarget()
1014 void LLight::SetHotspot(float value
)
1019 float LLight::GetHotspot()
1024 void LLight::SetFalloff(float value
)
1029 float LLight::GetFalloff()
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():
1068 LImporter::~LImporter()
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
];
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
];
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
];
1137 void LImporter::Clear()
1141 m_materials
.clear();
1145 void LImporter::SetOptimizationLevel(LOptimizationLevel value
)
1150 LOptimizationLevel
LImporter::GetOptimizationLevel()
1155 //-------------------------------------------------------
1156 // L3DS implementation
1157 //-------------------------------------------------------
1168 L3DS::L3DS(const char *filename
) :
1181 if (m_bufferSize
> 0)
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));
1195 fprintf(stderr
, "L3DS::LoadFile - not enough memory (malloc failed)");
1198 is
.read(reinterpret_cast<char *>(m_buffer
), m_bufferSize
);
1199 if(is
.gcount() != std::streamsize(m_bufferSize
))
1203 fprintf(stderr
, "L3DS::LoadFile - error reading from stream");
1208 bool res
= Read3DS();
1215 bool L3DS::Load(const char *filename
)
1218 f
= fopen(filename
, "rb");
1221 fprintf(stderr
, "L3DS::LoadFile - cannot open file");
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));
1230 fprintf(stderr
, "L3DS::LoadFile - not enough memory (malloc failed)");
1233 if (fread(m_buffer
, m_bufferSize
, 1, f
) != 1)
1238 fprintf(stderr
, "L3DS::LoadFile - error reading from file");
1244 bool res
= Read3DS();
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);
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);
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
));
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);
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
));
1314 int L3DS::ReadASCIIZ(char *buf
, int max_count
)
1317 if ((m_buffer
==0) || (m_bufferSize
== 0) || (m_pos
>=m_bufferSize
))
1324 char c
= ReadChar();
1325 while ((c
!=0) && (count
<max_count
-1))
1335 void L3DS::Seek(int offset
, int origin
)
1337 if (origin
== SEEK_START
)
1339 if (origin
== SEEK_CURSOR
)
1341 if (static_cast<signed>(m_pos
) < 0)
1343 if (m_pos
>= m_bufferSize
)
1344 m_pos
= m_bufferSize
-1;
1353 LChunk
L3DS::ReadChunk()
1356 chunk
.id
= ReadShort();
1358 chunk
.start
= Pos();
1359 chunk
.end
= chunk
.start
+a
-6;
1363 bool L3DS::FindChunk(LChunk
&target
, const LChunk
&parent
)
1365 if (Pos() >= parent
.end
)
1368 chunk
= ReadChunk();
1369 while (( chunk
.id
!= target
.id
) && (chunk
.end
<= parent
.end
))
1372 if (chunk
.end
>= parent
.end
)
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
)
1381 if (chunk
.id
== target
.id
)
1383 target
.start
= chunk
.start
;
1384 target
.end
= chunk
.end
;
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
;
1407 col
.r
= ReadFloat();
1408 col
.g
= ReadFloat();
1409 col
.b
= ReadFloat();
1412 col
.r
= ReadByte()/255.0f
;
1413 col
.g
= ReadByte()/255.0f
;
1414 col
.b
= ReadByte()/255.0f
;
1417 col
.r
= ReadFloat();
1418 col
.g
= ReadFloat();
1419 col
.b
= ReadFloat();
1422 col
.r
= ReadByte()/255.0f
;
1423 col
.g
= ReadByte()/255.0f
;
1424 col
.b
= ReadByte()/255.0f
;
1427 fprintf(stderr
, "L3DS::ReadColor - error this is not a color chunk");
1432 float L3DS::ReadPercentage(const LChunk
&chunk
)
1437 case INT_PERCENTAGE
:
1438 return (ReadShort()/100.0f
);
1439 case FLOAT_PERCENTAGE
:
1442 fprintf(stderr
, "L3DS::ReadPercentage - error, the chunk is not a percentage chunk");
1446 bool L3DS::Read3DS()
1451 mainchunk
= ReadChunk();
1452 if (mainchunk
.id
!= MAIN3DS
)
1454 fprintf(stderr
, "L3DS::Read3DS - wrong file format");
1457 if (!FindChunk(edit
, mainchunk
))
1464 while (FindChunk(obj
, edit
))
1471 obj
.id
= EDIT_OBJECT
;
1473 while (FindChunk(obj
, edit
))
1475 ReadASCIIZ(m_objName
, 99);
1477 if (ml
.id
== OBJ_TRIMESH
)
1480 if (ml
.id
== OBJ_LIGHT
)
1483 if (ml
.id
== OBJ_CAMERA
)
1489 // read the keyframer data here to find out correct object orientation
1492 keyframer
.id
= KFDATA
;
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
);
1511 strcpy(m_objName
, "");
1515 void L3DS::ReadLight(const LChunk
&parent
)
1520 light
.SetName(m_objName
);
1524 light
.SetPosition(v
);
1525 LChunk chunk
= ReadChunk();
1526 while (chunk
.end
<= parent
.end
)
1534 light
.SetColor(ReadColor(chunk
));
1542 light
.SetHotspot(t
);
1544 light
.SetFalloff(t
);
1547 light
.SetAttenuationstart(ReadFloat());
1550 light
.SetAttenuationend(ReadFloat());
1556 if (chunk
.end
>= parent
.end
)
1558 chunk
= ReadChunk();
1561 m_lights
.push_back(light
);
1564 void L3DS::ReadCamera(const LChunk
&parent
)
1568 camera
.SetName(m_objName
);
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
)
1585 camera
.SetNearplane(ReadFloat());
1586 camera
.SetFarplane(ReadFloat());
1592 if (chunk
.end
>= parent
.end
)
1594 chunk
= ReadChunk();
1597 m_cameras
.push_back(camera
);
1600 void L3DS::ReadMesh(const LChunk
&parent
)
1602 unsigned short count
, i
;
1608 mesh
.SetName(m_objName
);
1610 LChunk chunk
= ReadChunk();
1611 while (chunk
.end
<= parent
.end
)
1615 case TRI_VERTEXLIST
:
1616 count
= ReadShort();
1617 mesh
.SetVertexArraySize(count
);
1618 for (i
=0; i
< count
; i
++)
1623 mesh
.SetVertex(p
, i
);
1626 case TRI_FACEMAPPING
:
1627 count
= ReadShort();
1628 if (mesh
.GetVertexCount() == 0)
1629 mesh
.SetVertexArraySize(count
);
1630 for (i
=0; i
< count
; i
++)
1638 ReadFaceList(chunk
, mesh
);
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();
1668 if (chunk
.end
>= parent
.end
)
1670 chunk
= ReadChunk();
1672 m_meshes
.push_back(mesh
);
1675 void L3DS::ReadFaceList(const LChunk
&chunk
, LMesh
&mesh
)
1678 unsigned short count
, t
;
1685 // consistency checks
1686 if (chunk
.id
!= TRI_FACELIST
)
1688 fprintf(stderr
, "L3DS::ReadFaceList - internal error: wrong chunk passed as parameter");
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();
1702 mesh
.SetTri(tri
, i
);
1704 // now read the optional chunks
1707 while (ch
.end
<= chunk
.end
)
1713 ReadASCIIZ(str
, 20);
1715 LMaterial
*pMat
= FindMaterial(str
);
1719 mat_id
= pMat
->GetID();
1721 mesh
.AddMaterial(mat_id
);
1724 count
= ReadShort();
1725 for (i
=0; i
<count
; i
++)
1729 mesh
.GetTri(t
).materialId
= mat_id
;
1734 case TRI_SMOOTH_GROUP
:
1735 for (i
=0; i
<mesh
.GetTriangleCount(); i
++)
1736 mesh
.GetTri(i
).smoothingGroups
= ulong(ReadInt());
1744 void L3DS::ReadMaterial(const LChunk
&parent
)
1755 chunk
= ReadChunk();
1756 while (chunk
.end
<= parent
.end
)
1761 ReadASCIIZ(str
, 30);
1765 child
= ReadChunk();
1766 mat
.SetAmbientColor(ReadColor(child
));
1769 child
= ReadChunk();
1770 mat
.SetDiffuseColor(ReadColor(child
));
1773 child
= ReadChunk();
1774 mat
.SetSpecularColor(ReadColor(child
));
1777 child
= ReadChunk();
1778 mat
.SetShininess(ReadPercentage(child
));
1780 case MAT_TRANSPARENCY
:
1781 child
= ReadChunk();
1782 mat
.SetTransparency(ReadPercentage(child
));
1789 mat
.SetShadingType(sWireframe
);
1792 mat
.SetShadingType(sFlat
);
1795 mat
.SetShadingType(sGouraud
);
1798 mat
.SetShadingType(sPhong
);
1801 mat
.SetShadingType(sMetal
);
1806 mat
.SetShadingType(sWireframe
);
1809 ReadMap(chunk
, mat
.GetTextureMap1());
1812 ReadMap(chunk
, mat
.GetTextureMap2());
1815 ReadMap(chunk
, mat
.GetOpacityMap());
1818 ReadMap(chunk
, mat
.GetBumpMap());
1821 ReadMap(chunk
, mat
.GetSpecularMap());
1824 // AMZ not really a bugfix but it seems to work!
1826 ReadMap(chunk
, mat
.GetReflectionMap());
1828 child
= ReadChunk();
1829 mat
.GetReflectionMap().strength
= ReadPercentage(child
);
1831 child
= ReadChunk();
1832 if (child
.id
!= MAT_MAPNAME
)
1834 fprintf(stderr
, "L3DS::ReadMaterial - error, expected chunk not found");
1837 ReadASCIIZ(str
, 30);
1838 if (strcmp(str
, "") == 0)
1839 strcpy(mat
.GetReflectionMap().mapName
, "auto");
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
)
1856 child
= ReadChunk();
1857 while (child
.end
<= chunk
.end
)
1861 case INT_PERCENTAGE
:
1862 map
.strength
= ReadPercentage(child
);
1865 ReadASCIIZ(str
, 20);
1866 strcpy(map
.mapName
, str
);
1868 case MAT_MAP_TILING
:
1869 map
.tiling
= ReadShort();
1871 case MAT_MAP_USCALE
:
1872 map
.uScale
= ReadFloat();
1874 case MAT_MAP_VSCALE
:
1875 map
.vScale
= ReadFloat();
1877 case MAT_MAP_UOFFSET
:
1878 map
.uOffset
= ReadFloat();
1880 case MAT_MAP_VOFFSET
:
1881 map
.vOffset
= ReadFloat();
1884 map
.angle
= ReadFloat();
1888 child
= ReadChunk();
1892 void L3DS::ReadKeyframeData(const LChunk
&parent
)
1897 node_hdr
.id
= NODE_HDR
;
1903 if (!FindChunk(node_hdr
, parent
))
1905 GotoChunk(node_hdr
);
1906 ReadASCIIZ(str
, 19);
1907 mesh
= FindMesh(str
);
1913 //LVector3 pivot = zero3;
1916 pivotchunk
.id
= PIVOT
;
1917 if (FindChunk(pivotchunk
, parent
))
1919 GotoChunk(pivotchunk
);
1920 /*pivot.x =*/ ReadFloat();
1921 /*pivot.y =*/ ReadFloat();
1922 /*pivot.z =*/ ReadFloat();
1926 // read frame 0 from the position track
1927 //LVector3 pos = zero3;
1932 poschunk
.id
= POS_TRACK_TAG
;
1933 if (FindChunk(poschunk
, parent
))
1935 GotoChunk(poschunk
);
1936 // read the trackheader structure
1944 /*pos.x =*/ ReadFloat();
1945 /*pos.y =*/ ReadFloat();
1946 /*pos.z =*/ ReadFloat();
1951 // now read the rotation track
1952 //LVector4 rot = zero4;
1955 rotchunk
.id
= ROT_TRACK_TAG
;
1958 if (FindChunk(rotchunk
, parent
))
1960 GotoChunk(rotchunk
);
1961 // read the trackheader structure
1969 /*rot.x =*/ ReadFloat();
1970 /*rot.y =*/ ReadFloat();
1971 /*rot.z =*/ ReadFloat();
1972 /*rot.w =*/ ReadFloat();
1977 // now read the scaling chunk
1984 scalechunk
.id
= SCL_TRACK_TAG
;
1988 if (FindChunk(scalechunk
, parent
))
1990 GotoChunk(scalechunk
);
1991 // read the trackheader structure
1999 /*scale.x =*/ ReadFloat();
2000 /*scale.y =*/ ReadFloat();
2001 /*scale.z =*/ ReadFloat();
2007 long L3DS::ReadKeyheader()
2011 short opts
= ReadShort();
2012 if (opts
& 32768) // 32768 is 1000000000000000 binary
2013 { // tension is present
2016 if (opts
& 16384) // 16384 is 0100000000000000 binary
2017 { // continuity is present
2021 { // bias info present
2025 { // "ease to" present
2029 { // "ease from" present