diff options
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/C3DSMeshFileLoader.cpp')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/C3DSMeshFileLoader.cpp | 2792 |
1 files changed, 1396 insertions, 1396 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/C3DSMeshFileLoader.cpp b/libraries/irrlicht-1.8/source/Irrlicht/C3DSMeshFileLoader.cpp index cc59c4d..e1f312d 100644 --- a/libraries/irrlicht-1.8/source/Irrlicht/C3DSMeshFileLoader.cpp +++ b/libraries/irrlicht-1.8/source/Irrlicht/C3DSMeshFileLoader.cpp | |||
@@ -1,1396 +1,1396 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | 1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt |
2 | // This file is part of the "Irrlicht Engine". | 2 | // This file is part of the "Irrlicht Engine". |
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | 3 | // For conditions of distribution and use, see copyright notice in irrlicht.h |
4 | 4 | ||
5 | #include "IrrCompileConfig.h" | 5 | #include "IrrCompileConfig.h" |
6 | #ifdef _IRR_COMPILE_WITH_3DS_LOADER_ | 6 | #ifdef _IRR_COMPILE_WITH_3DS_LOADER_ |
7 | 7 | ||
8 | #include "C3DSMeshFileLoader.h" | 8 | #include "C3DSMeshFileLoader.h" |
9 | #include "os.h" | 9 | #include "os.h" |
10 | #include "SMeshBuffer.h" | 10 | #include "SMeshBuffer.h" |
11 | #include "SAnimatedMesh.h" | 11 | #include "SAnimatedMesh.h" |
12 | #include "IReadFile.h" | 12 | #include "IReadFile.h" |
13 | #include "IVideoDriver.h" | 13 | #include "IVideoDriver.h" |
14 | #include "IMeshManipulator.h" | 14 | #include "IMeshManipulator.h" |
15 | 15 | ||
16 | #ifdef _DEBUG | 16 | #ifdef _DEBUG |
17 | #define _IRR_DEBUG_3DS_LOADER_ | 17 | #define _IRR_DEBUG_3DS_LOADER_ |
18 | #endif | 18 | #endif |
19 | 19 | ||
20 | namespace irr | 20 | namespace irr |
21 | { | 21 | { |
22 | namespace scene | 22 | namespace scene |
23 | { | 23 | { |
24 | 24 | ||
25 | 25 | ||
26 | namespace | 26 | namespace |
27 | { | 27 | { |
28 | enum e3DSChunk | 28 | enum e3DSChunk |
29 | { | 29 | { |
30 | // Primary chunk | 30 | // Primary chunk |
31 | C3DS_MAIN3DS = 0x4D4D, | 31 | C3DS_MAIN3DS = 0x4D4D, |
32 | 32 | ||
33 | // Main Chunks | 33 | // Main Chunks |
34 | C3DS_EDIT3DS = 0x3D3D, | 34 | C3DS_EDIT3DS = 0x3D3D, |
35 | C3DS_KEYF3DS = 0xB000, | 35 | C3DS_KEYF3DS = 0xB000, |
36 | C3DS_VERSION = 0x0002, | 36 | C3DS_VERSION = 0x0002, |
37 | C3DS_MESHVERSION = 0x3D3E, | 37 | C3DS_MESHVERSION = 0x3D3E, |
38 | 38 | ||
39 | // sub chunks of C3DS_EDIT3DS | 39 | // sub chunks of C3DS_EDIT3DS |
40 | C3DS_EDIT_MATERIAL = 0xAFFF, | 40 | C3DS_EDIT_MATERIAL = 0xAFFF, |
41 | C3DS_EDIT_OBJECT = 0x4000, | 41 | C3DS_EDIT_OBJECT = 0x4000, |
42 | 42 | ||
43 | // sub chunks of C3DS_EDIT_MATERIAL | 43 | // sub chunks of C3DS_EDIT_MATERIAL |
44 | C3DS_MATNAME = 0xA000, | 44 | C3DS_MATNAME = 0xA000, |
45 | C3DS_MATAMBIENT = 0xA010, | 45 | C3DS_MATAMBIENT = 0xA010, |
46 | C3DS_MATDIFFUSE = 0xA020, | 46 | C3DS_MATDIFFUSE = 0xA020, |
47 | C3DS_MATSPECULAR = 0xA030, | 47 | C3DS_MATSPECULAR = 0xA030, |
48 | C3DS_MATSHININESS = 0xA040, | 48 | C3DS_MATSHININESS = 0xA040, |
49 | C3DS_MATSHIN2PCT = 0xA041, | 49 | C3DS_MATSHIN2PCT = 0xA041, |
50 | C3DS_TRANSPARENCY = 0xA050, | 50 | C3DS_TRANSPARENCY = 0xA050, |
51 | C3DS_TRANSPARENCY_FALLOFF = 0xA052, | 51 | C3DS_TRANSPARENCY_FALLOFF = 0xA052, |
52 | C3DS_REFL_BLUR = 0xA053, | 52 | C3DS_REFL_BLUR = 0xA053, |
53 | C3DS_TWO_SIDE = 0xA081, | 53 | C3DS_TWO_SIDE = 0xA081, |
54 | C3DS_WIRE = 0xA085, | 54 | C3DS_WIRE = 0xA085, |
55 | C3DS_SHADING = 0xA100, | 55 | C3DS_SHADING = 0xA100, |
56 | C3DS_MATTEXMAP = 0xA200, | 56 | C3DS_MATTEXMAP = 0xA200, |
57 | C3DS_MATSPECMAP = 0xA204, | 57 | C3DS_MATSPECMAP = 0xA204, |
58 | C3DS_MATOPACMAP = 0xA210, | 58 | C3DS_MATOPACMAP = 0xA210, |
59 | C3DS_MATREFLMAP = 0xA220, | 59 | C3DS_MATREFLMAP = 0xA220, |
60 | C3DS_MATBUMPMAP = 0xA230, | 60 | C3DS_MATBUMPMAP = 0xA230, |
61 | C3DS_MATMAPFILE = 0xA300, | 61 | C3DS_MATMAPFILE = 0xA300, |
62 | C3DS_MAT_TEXTILING = 0xA351, | 62 | C3DS_MAT_TEXTILING = 0xA351, |
63 | C3DS_MAT_USCALE = 0xA354, | 63 | C3DS_MAT_USCALE = 0xA354, |
64 | C3DS_MAT_VSCALE = 0xA356, | 64 | C3DS_MAT_VSCALE = 0xA356, |
65 | C3DS_MAT_UOFFSET = 0xA358, | 65 | C3DS_MAT_UOFFSET = 0xA358, |
66 | C3DS_MAT_VOFFSET = 0xA35A, | 66 | C3DS_MAT_VOFFSET = 0xA35A, |
67 | 67 | ||
68 | // subs of C3DS_EDIT_OBJECT | 68 | // subs of C3DS_EDIT_OBJECT |
69 | C3DS_OBJTRIMESH = 0x4100, | 69 | C3DS_OBJTRIMESH = 0x4100, |
70 | 70 | ||
71 | // subs of C3DS_OBJTRIMESH | 71 | // subs of C3DS_OBJTRIMESH |
72 | C3DS_TRIVERT = 0x4110, | 72 | C3DS_TRIVERT = 0x4110, |
73 | C3DS_POINTFLAGARRAY= 0x4111, | 73 | C3DS_POINTFLAGARRAY= 0x4111, |
74 | C3DS_TRIFACE = 0x4120, | 74 | C3DS_TRIFACE = 0x4120, |
75 | C3DS_TRIFACEMAT = 0x4130, | 75 | C3DS_TRIFACEMAT = 0x4130, |
76 | C3DS_TRIUV = 0x4140, | 76 | C3DS_TRIUV = 0x4140, |
77 | C3DS_TRISMOOTH = 0x4150, | 77 | C3DS_TRISMOOTH = 0x4150, |
78 | C3DS_TRIMATRIX = 0x4160, | 78 | C3DS_TRIMATRIX = 0x4160, |
79 | C3DS_MESHCOLOR = 0x4165, | 79 | C3DS_MESHCOLOR = 0x4165, |
80 | C3DS_DIRECT_LIGHT = 0x4600, | 80 | C3DS_DIRECT_LIGHT = 0x4600, |
81 | C3DS_DL_INNER_RANGE= 0x4659, | 81 | C3DS_DL_INNER_RANGE= 0x4659, |
82 | C3DS_DL_OUTER_RANGE= 0x465A, | 82 | C3DS_DL_OUTER_RANGE= 0x465A, |
83 | C3DS_DL_MULTIPLIER = 0x465B, | 83 | C3DS_DL_MULTIPLIER = 0x465B, |
84 | C3DS_CAMERA = 0x4700, | 84 | C3DS_CAMERA = 0x4700, |
85 | C3DS_CAM_SEE_CONE = 0x4710, | 85 | C3DS_CAM_SEE_CONE = 0x4710, |
86 | C3DS_CAM_RANGES = 0x4720, | 86 | C3DS_CAM_RANGES = 0x4720, |
87 | 87 | ||
88 | // subs of C3DS_KEYF3DS | 88 | // subs of C3DS_KEYF3DS |
89 | C3DS_KF_HDR = 0xB00A, | 89 | C3DS_KF_HDR = 0xB00A, |
90 | C3DS_AMBIENT_TAG = 0xB001, | 90 | C3DS_AMBIENT_TAG = 0xB001, |
91 | C3DS_OBJECT_TAG = 0xB002, | 91 | C3DS_OBJECT_TAG = 0xB002, |
92 | C3DS_CAMERA_TAG = 0xB003, | 92 | C3DS_CAMERA_TAG = 0xB003, |
93 | C3DS_TARGET_TAG = 0xB004, | 93 | C3DS_TARGET_TAG = 0xB004, |
94 | C3DS_LIGHTNODE_TAG = 0xB005, | 94 | C3DS_LIGHTNODE_TAG = 0xB005, |
95 | C3DS_KF_SEG = 0xB008, | 95 | C3DS_KF_SEG = 0xB008, |
96 | C3DS_KF_CURTIME = 0xB009, | 96 | C3DS_KF_CURTIME = 0xB009, |
97 | C3DS_KF_NODE_HDR = 0xB010, | 97 | C3DS_KF_NODE_HDR = 0xB010, |
98 | C3DS_PIVOTPOINT = 0xB013, | 98 | C3DS_PIVOTPOINT = 0xB013, |
99 | C3DS_BOUNDBOX = 0xB014, | 99 | C3DS_BOUNDBOX = 0xB014, |
100 | C3DS_MORPH_SMOOTH = 0xB015, | 100 | C3DS_MORPH_SMOOTH = 0xB015, |
101 | C3DS_POS_TRACK_TAG = 0xB020, | 101 | C3DS_POS_TRACK_TAG = 0xB020, |
102 | C3DS_ROT_TRACK_TAG = 0xB021, | 102 | C3DS_ROT_TRACK_TAG = 0xB021, |
103 | C3DS_SCL_TRACK_TAG = 0xB022, | 103 | C3DS_SCL_TRACK_TAG = 0xB022, |
104 | C3DS_NODE_ID = 0xB030, | 104 | C3DS_NODE_ID = 0xB030, |
105 | 105 | ||
106 | // Viewport definitions | 106 | // Viewport definitions |
107 | C3DS_VIEWPORT_LAYOUT = 0x7001, | 107 | C3DS_VIEWPORT_LAYOUT = 0x7001, |
108 | C3DS_VIEWPORT_DATA = 0x7011, | 108 | C3DS_VIEWPORT_DATA = 0x7011, |
109 | C3DS_VIEWPORT_DATA_3 = 0x7012, | 109 | C3DS_VIEWPORT_DATA_3 = 0x7012, |
110 | C3DS_VIEWPORT_SIZE = 0x7020, | 110 | C3DS_VIEWPORT_SIZE = 0x7020, |
111 | 111 | ||
112 | // different color chunk types | 112 | // different color chunk types |
113 | C3DS_COL_RGB = 0x0010, | 113 | C3DS_COL_RGB = 0x0010, |
114 | C3DS_COL_TRU = 0x0011, | 114 | C3DS_COL_TRU = 0x0011, |
115 | C3DS_COL_LIN_24 = 0x0012, | 115 | C3DS_COL_LIN_24 = 0x0012, |
116 | C3DS_COL_LIN_F = 0x0013, | 116 | C3DS_COL_LIN_F = 0x0013, |
117 | 117 | ||
118 | // percentage chunk types | 118 | // percentage chunk types |
119 | C3DS_PERCENTAGE_I = 0x0030, | 119 | C3DS_PERCENTAGE_I = 0x0030, |
120 | C3DS_PERCENTAGE_F = 0x0031, | 120 | C3DS_PERCENTAGE_F = 0x0031, |
121 | 121 | ||
122 | C3DS_CHUNK_MAX = 0xFFFF | 122 | C3DS_CHUNK_MAX = 0xFFFF |
123 | }; | 123 | }; |
124 | } | 124 | } |
125 | 125 | ||
126 | 126 | ||
127 | //! Constructor | 127 | //! Constructor |
128 | C3DSMeshFileLoader::C3DSMeshFileLoader(ISceneManager* smgr, io::IFileSystem* fs) | 128 | C3DSMeshFileLoader::C3DSMeshFileLoader(ISceneManager* smgr, io::IFileSystem* fs) |
129 | : SceneManager(smgr), FileSystem(fs), Vertices(0), Indices(0), SmoothingGroups(0), TCoords(0), | 129 | : SceneManager(smgr), FileSystem(fs), Vertices(0), Indices(0), SmoothingGroups(0), TCoords(0), |
130 | CountVertices(0), CountFaces(0), CountTCoords(0), Mesh(0) | 130 | CountVertices(0), CountFaces(0), CountTCoords(0), Mesh(0) |
131 | { | 131 | { |
132 | 132 | ||
133 | #ifdef _DEBUG | 133 | #ifdef _DEBUG |
134 | setDebugName("C3DSMeshFileLoader"); | 134 | setDebugName("C3DSMeshFileLoader"); |
135 | #endif | 135 | #endif |
136 | 136 | ||
137 | if (FileSystem) | 137 | if (FileSystem) |
138 | FileSystem->grab(); | 138 | FileSystem->grab(); |
139 | } | 139 | } |
140 | 140 | ||
141 | 141 | ||
142 | //! destructor | 142 | //! destructor |
143 | C3DSMeshFileLoader::~C3DSMeshFileLoader() | 143 | C3DSMeshFileLoader::~C3DSMeshFileLoader() |
144 | { | 144 | { |
145 | cleanUp(); | 145 | cleanUp(); |
146 | 146 | ||
147 | if (FileSystem) | 147 | if (FileSystem) |
148 | FileSystem->drop(); | 148 | FileSystem->drop(); |
149 | 149 | ||
150 | if (Mesh) | 150 | if (Mesh) |
151 | Mesh->drop(); | 151 | Mesh->drop(); |
152 | } | 152 | } |
153 | 153 | ||
154 | 154 | ||
155 | //! returns true if the file maybe is able to be loaded by this class | 155 | //! returns true if the file maybe is able to be loaded by this class |
156 | //! based on the file extension (e.g. ".bsp") | 156 | //! based on the file extension (e.g. ".bsp") |
157 | bool C3DSMeshFileLoader::isALoadableFileExtension(const io::path& filename) const | 157 | bool C3DSMeshFileLoader::isALoadableFileExtension(const io::path& filename) const |
158 | { | 158 | { |
159 | return core::hasFileExtension ( filename, "3ds" ); | 159 | return core::hasFileExtension ( filename, "3ds" ); |
160 | } | 160 | } |
161 | 161 | ||
162 | 162 | ||
163 | //! creates/loads an animated mesh from the file. | 163 | //! creates/loads an animated mesh from the file. |
164 | //! \return Pointer to the created mesh. Returns 0 if loading failed. | 164 | //! \return Pointer to the created mesh. Returns 0 if loading failed. |
165 | //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). | 165 | //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). |
166 | //! See IReferenceCounted::drop() for more information. | 166 | //! See IReferenceCounted::drop() for more information. |
167 | IAnimatedMesh* C3DSMeshFileLoader::createMesh(io::IReadFile* file) | 167 | IAnimatedMesh* C3DSMeshFileLoader::createMesh(io::IReadFile* file) |
168 | { | 168 | { |
169 | ChunkData data; | 169 | ChunkData data; |
170 | 170 | ||
171 | readChunkData(file, data); | 171 | readChunkData(file, data); |
172 | 172 | ||
173 | if (data.header.id != C3DS_MAIN3DS ) | 173 | if (data.header.id != C3DS_MAIN3DS ) |
174 | return 0; | 174 | return 0; |
175 | 175 | ||
176 | CurrentMaterial.clear(); | 176 | CurrentMaterial.clear(); |
177 | Materials.clear(); | 177 | Materials.clear(); |
178 | MeshBufferNames.clear(); | 178 | MeshBufferNames.clear(); |
179 | cleanUp(); | 179 | cleanUp(); |
180 | 180 | ||
181 | if (Mesh) | 181 | if (Mesh) |
182 | Mesh->drop(); | 182 | Mesh->drop(); |
183 | 183 | ||
184 | Mesh = new SMesh(); | 184 | Mesh = new SMesh(); |
185 | 185 | ||
186 | if (readChunk(file, &data)) | 186 | if (readChunk(file, &data)) |
187 | { | 187 | { |
188 | // success | 188 | // success |
189 | 189 | ||
190 | for (u32 i=0; i<Mesh->getMeshBufferCount(); ++i) | 190 | for (u32 i=0; i<Mesh->getMeshBufferCount(); ++i) |
191 | { | 191 | { |
192 | SMeshBuffer* mb = ((SMeshBuffer*)Mesh->getMeshBuffer(i)); | 192 | SMeshBuffer* mb = ((SMeshBuffer*)Mesh->getMeshBuffer(i)); |
193 | // drop empty buffers | 193 | // drop empty buffers |
194 | if (mb->getIndexCount() == 0 || mb->getVertexCount() == 0) | 194 | if (mb->getIndexCount() == 0 || mb->getVertexCount() == 0) |
195 | { | 195 | { |
196 | Mesh->MeshBuffers.erase(i--); | 196 | Mesh->MeshBuffers.erase(i--); |
197 | mb->drop(); | 197 | mb->drop(); |
198 | } | 198 | } |
199 | else | 199 | else |
200 | { | 200 | { |
201 | if (mb->Material.MaterialType == video::EMT_PARALLAX_MAP_SOLID) | 201 | if (mb->Material.MaterialType == video::EMT_PARALLAX_MAP_SOLID) |
202 | { | 202 | { |
203 | SMesh tmp; | 203 | SMesh tmp; |
204 | tmp.addMeshBuffer(mb); | 204 | tmp.addMeshBuffer(mb); |
205 | mb->drop(); | 205 | mb->drop(); |
206 | IMesh* tangentMesh = SceneManager->getMeshManipulator()->createMeshWithTangents(&tmp); | 206 | IMesh* tangentMesh = SceneManager->getMeshManipulator()->createMeshWithTangents(&tmp); |
207 | Mesh->MeshBuffers[i]=tangentMesh->getMeshBuffer(0); | 207 | Mesh->MeshBuffers[i]=tangentMesh->getMeshBuffer(0); |
208 | // we need to grab because we replace the buffer manually. | 208 | // we need to grab because we replace the buffer manually. |
209 | Mesh->MeshBuffers[i]->grab(); | 209 | Mesh->MeshBuffers[i]->grab(); |
210 | // clean up intermediate mesh struct | 210 | // clean up intermediate mesh struct |
211 | tangentMesh->drop(); | 211 | tangentMesh->drop(); |
212 | } | 212 | } |
213 | Mesh->MeshBuffers[i]->recalculateBoundingBox(); | 213 | Mesh->MeshBuffers[i]->recalculateBoundingBox(); |
214 | } | 214 | } |
215 | } | 215 | } |
216 | 216 | ||
217 | Mesh->recalculateBoundingBox(); | 217 | Mesh->recalculateBoundingBox(); |
218 | 218 | ||
219 | SAnimatedMesh* am = new SAnimatedMesh(); | 219 | SAnimatedMesh* am = new SAnimatedMesh(); |
220 | am->Type = EAMT_3DS; | 220 | am->Type = EAMT_3DS; |
221 | am->addMesh(Mesh); | 221 | am->addMesh(Mesh); |
222 | am->recalculateBoundingBox(); | 222 | am->recalculateBoundingBox(); |
223 | Mesh->drop(); | 223 | Mesh->drop(); |
224 | Mesh = 0; | 224 | Mesh = 0; |
225 | return am; | 225 | return am; |
226 | } | 226 | } |
227 | 227 | ||
228 | Mesh->drop(); | 228 | Mesh->drop(); |
229 | Mesh = 0; | 229 | Mesh = 0; |
230 | 230 | ||
231 | return 0; | 231 | return 0; |
232 | } | 232 | } |
233 | 233 | ||
234 | 234 | ||
235 | bool C3DSMeshFileLoader::readPercentageChunk(io::IReadFile* file, | 235 | bool C3DSMeshFileLoader::readPercentageChunk(io::IReadFile* file, |
236 | ChunkData* chunk, f32& percentage) | 236 | ChunkData* chunk, f32& percentage) |
237 | { | 237 | { |
238 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 238 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
239 | os::Printer::log("Load percentage chunk.", ELL_DEBUG); | 239 | os::Printer::log("Load percentage chunk.", ELL_DEBUG); |
240 | #endif | 240 | #endif |
241 | 241 | ||
242 | ChunkData data; | 242 | ChunkData data; |
243 | readChunkData(file, data); | 243 | readChunkData(file, data); |
244 | 244 | ||
245 | short intpercentage; | 245 | short intpercentage; |
246 | float fpercentage; | 246 | float fpercentage; |
247 | 247 | ||
248 | switch(data.header.id) | 248 | switch(data.header.id) |
249 | { | 249 | { |
250 | case C3DS_PERCENTAGE_I: | 250 | case C3DS_PERCENTAGE_I: |
251 | { | 251 | { |
252 | // read short | 252 | // read short |
253 | file->read(&intpercentage, 2); | 253 | file->read(&intpercentage, 2); |
254 | #ifdef __BIG_ENDIAN__ | 254 | #ifdef __BIG_ENDIAN__ |
255 | intpercentage = os::Byteswap::byteswap(intpercentage); | 255 | intpercentage = os::Byteswap::byteswap(intpercentage); |
256 | #endif | 256 | #endif |
257 | percentage=intpercentage/100.0f; | 257 | percentage=intpercentage/100.0f; |
258 | data.read += 2; | 258 | data.read += 2; |
259 | } | 259 | } |
260 | break; | 260 | break; |
261 | case C3DS_PERCENTAGE_F: | 261 | case C3DS_PERCENTAGE_F: |
262 | { | 262 | { |
263 | // read float | 263 | // read float |
264 | file->read(&fpercentage, sizeof(float)); | 264 | file->read(&fpercentage, sizeof(float)); |
265 | data.read += sizeof(float); | 265 | data.read += sizeof(float); |
266 | #ifdef __BIG_ENDIAN__ | 266 | #ifdef __BIG_ENDIAN__ |
267 | percentage = os::Byteswap::byteswap(fpercentage); | 267 | percentage = os::Byteswap::byteswap(fpercentage); |
268 | #else | 268 | #else |
269 | percentage = (f32)fpercentage; | 269 | percentage = (f32)fpercentage; |
270 | #endif | 270 | #endif |
271 | } | 271 | } |
272 | break; | 272 | break; |
273 | default: | 273 | default: |
274 | { | 274 | { |
275 | // unknown percentage chunk | 275 | // unknown percentage chunk |
276 | os::Printer::log("Unknown percentage chunk in 3Ds file.", ELL_WARNING); | 276 | os::Printer::log("Unknown percentage chunk in 3Ds file.", ELL_WARNING); |
277 | file->seek(data.header.length - data.read, true); | 277 | file->seek(data.header.length - data.read, true); |
278 | data.read += data.header.length - data.read; | 278 | data.read += data.header.length - data.read; |
279 | } | 279 | } |
280 | } | 280 | } |
281 | 281 | ||
282 | chunk->read += data.read; | 282 | chunk->read += data.read; |
283 | 283 | ||
284 | return true; | 284 | return true; |
285 | } | 285 | } |
286 | 286 | ||
287 | bool C3DSMeshFileLoader::readColorChunk(io::IReadFile* file, ChunkData* chunk, | 287 | bool C3DSMeshFileLoader::readColorChunk(io::IReadFile* file, ChunkData* chunk, |
288 | video::SColor& out) | 288 | video::SColor& out) |
289 | { | 289 | { |
290 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 290 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
291 | os::Printer::log("Load color chunk.", ELL_DEBUG); | 291 | os::Printer::log("Load color chunk.", ELL_DEBUG); |
292 | #endif | 292 | #endif |
293 | ChunkData data; | 293 | ChunkData data; |
294 | readChunkData(file, data); | 294 | readChunkData(file, data); |
295 | 295 | ||
296 | u8 c[3]; | 296 | u8 c[3]; |
297 | f32 cf[3]; | 297 | f32 cf[3]; |
298 | 298 | ||
299 | switch(data.header.id) | 299 | switch(data.header.id) |
300 | { | 300 | { |
301 | case C3DS_COL_TRU: | 301 | case C3DS_COL_TRU: |
302 | case C3DS_COL_LIN_24: | 302 | case C3DS_COL_LIN_24: |
303 | { | 303 | { |
304 | // read 8 bit data | 304 | // read 8 bit data |
305 | file->read(c, sizeof(c)); | 305 | file->read(c, sizeof(c)); |
306 | out.set(255, c[0], c[1], c[2]); | 306 | out.set(255, c[0], c[1], c[2]); |
307 | data.read += sizeof(c); | 307 | data.read += sizeof(c); |
308 | } | 308 | } |
309 | break; | 309 | break; |
310 | case C3DS_COL_RGB: | 310 | case C3DS_COL_RGB: |
311 | case C3DS_COL_LIN_F: | 311 | case C3DS_COL_LIN_F: |
312 | { | 312 | { |
313 | // read float data | 313 | // read float data |
314 | file->read(cf, sizeof(cf)); | 314 | file->read(cf, sizeof(cf)); |
315 | #ifdef __BIG_ENDIAN__ | 315 | #ifdef __BIG_ENDIAN__ |
316 | cf[0] = os::Byteswap::byteswap(cf[0]); | 316 | cf[0] = os::Byteswap::byteswap(cf[0]); |
317 | cf[1] = os::Byteswap::byteswap(cf[1]); | 317 | cf[1] = os::Byteswap::byteswap(cf[1]); |
318 | cf[2] = os::Byteswap::byteswap(cf[2]); | 318 | cf[2] = os::Byteswap::byteswap(cf[2]); |
319 | #endif | 319 | #endif |
320 | out.set(255, (s32)(cf[0]*255.0f), (s32)(cf[1]*255.0f), (s32)(cf[2]*255.0f)); | 320 | out.set(255, (s32)(cf[0]*255.0f), (s32)(cf[1]*255.0f), (s32)(cf[2]*255.0f)); |
321 | data.read += sizeof(cf); | 321 | data.read += sizeof(cf); |
322 | } | 322 | } |
323 | break; | 323 | break; |
324 | default: | 324 | default: |
325 | { | 325 | { |
326 | // unknown color chunk size | 326 | // unknown color chunk size |
327 | os::Printer::log("Unknown size of color chunk in 3Ds file.", ELL_WARNING); | 327 | os::Printer::log("Unknown size of color chunk in 3Ds file.", ELL_WARNING); |
328 | file->seek(data.header.length - data.read, true); | 328 | file->seek(data.header.length - data.read, true); |
329 | data.read += data.header.length - data.read; | 329 | data.read += data.header.length - data.read; |
330 | } | 330 | } |
331 | } | 331 | } |
332 | 332 | ||
333 | chunk->read += data.read; | 333 | chunk->read += data.read; |
334 | 334 | ||
335 | return true; | 335 | return true; |
336 | } | 336 | } |
337 | 337 | ||
338 | 338 | ||
339 | bool C3DSMeshFileLoader::readMaterialChunk(io::IReadFile* file, ChunkData* parent) | 339 | bool C3DSMeshFileLoader::readMaterialChunk(io::IReadFile* file, ChunkData* parent) |
340 | { | 340 | { |
341 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 341 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
342 | os::Printer::log("Load material chunk.", ELL_DEBUG); | 342 | os::Printer::log("Load material chunk.", ELL_DEBUG); |
343 | #endif | 343 | #endif |
344 | u16 matSection=0; | 344 | u16 matSection=0; |
345 | 345 | ||
346 | while(parent->read < parent->header.length) | 346 | while(parent->read < parent->header.length) |
347 | { | 347 | { |
348 | ChunkData data; | 348 | ChunkData data; |
349 | readChunkData(file, data); | 349 | readChunkData(file, data); |
350 | 350 | ||
351 | switch(data.header.id) | 351 | switch(data.header.id) |
352 | { | 352 | { |
353 | case C3DS_MATNAME: | 353 | case C3DS_MATNAME: |
354 | { | 354 | { |
355 | c8* c = new c8[data.header.length - data.read]; | 355 | c8* c = new c8[data.header.length - data.read]; |
356 | file->read(c, data.header.length - data.read); | 356 | file->read(c, data.header.length - data.read); |
357 | 357 | ||
358 | if (strlen(c)) | 358 | if (strlen(c)) |
359 | CurrentMaterial.Name = c; | 359 | CurrentMaterial.Name = c; |
360 | 360 | ||
361 | data.read += data.header.length - data.read; | 361 | data.read += data.header.length - data.read; |
362 | delete [] c; | 362 | delete [] c; |
363 | } | 363 | } |
364 | break; | 364 | break; |
365 | case C3DS_MATAMBIENT: | 365 | case C3DS_MATAMBIENT: |
366 | readColorChunk(file, &data, CurrentMaterial.Material.AmbientColor); | 366 | readColorChunk(file, &data, CurrentMaterial.Material.AmbientColor); |
367 | break; | 367 | break; |
368 | case C3DS_MATDIFFUSE: | 368 | case C3DS_MATDIFFUSE: |
369 | readColorChunk(file, &data, CurrentMaterial.Material.DiffuseColor); | 369 | readColorChunk(file, &data, CurrentMaterial.Material.DiffuseColor); |
370 | break; | 370 | break; |
371 | case C3DS_MATSPECULAR: | 371 | case C3DS_MATSPECULAR: |
372 | readColorChunk(file, &data, CurrentMaterial.Material.SpecularColor); | 372 | readColorChunk(file, &data, CurrentMaterial.Material.SpecularColor); |
373 | break; | 373 | break; |
374 | case C3DS_MATSHININESS: | 374 | case C3DS_MATSHININESS: |
375 | readPercentageChunk(file, &data, CurrentMaterial.Material.Shininess); | 375 | readPercentageChunk(file, &data, CurrentMaterial.Material.Shininess); |
376 | CurrentMaterial.Material.Shininess = (1.f-CurrentMaterial.Material.Shininess)*128.f; | 376 | CurrentMaterial.Material.Shininess = (1.f-CurrentMaterial.Material.Shininess)*128.f; |
377 | break; | 377 | break; |
378 | case C3DS_TRANSPARENCY: | 378 | case C3DS_TRANSPARENCY: |
379 | { | 379 | { |
380 | f32 percentage; | 380 | f32 percentage; |
381 | readPercentageChunk(file, &data, percentage); | 381 | readPercentageChunk(file, &data, percentage); |
382 | if (percentage>0.0f) | 382 | if (percentage>0.0f) |
383 | { | 383 | { |
384 | CurrentMaterial.Material.MaterialTypeParam=percentage; | 384 | CurrentMaterial.Material.MaterialTypeParam=percentage; |
385 | CurrentMaterial.Material.MaterialType=video::EMT_TRANSPARENT_VERTEX_ALPHA; | 385 | CurrentMaterial.Material.MaterialType=video::EMT_TRANSPARENT_VERTEX_ALPHA; |
386 | } | 386 | } |
387 | else | 387 | else |
388 | { | 388 | { |
389 | CurrentMaterial.Material.MaterialType=video::EMT_SOLID; | 389 | CurrentMaterial.Material.MaterialType=video::EMT_SOLID; |
390 | } | 390 | } |
391 | } | 391 | } |
392 | break; | 392 | break; |
393 | case C3DS_WIRE: | 393 | case C3DS_WIRE: |
394 | CurrentMaterial.Material.Wireframe=true; | 394 | CurrentMaterial.Material.Wireframe=true; |
395 | break; | 395 | break; |
396 | case C3DS_TWO_SIDE: | 396 | case C3DS_TWO_SIDE: |
397 | CurrentMaterial.Material.BackfaceCulling=false; | 397 | CurrentMaterial.Material.BackfaceCulling=false; |
398 | break; | 398 | break; |
399 | case C3DS_SHADING: | 399 | case C3DS_SHADING: |
400 | { | 400 | { |
401 | s16 flags; | 401 | s16 flags; |
402 | file->read(&flags, 2); | 402 | file->read(&flags, 2); |
403 | #ifdef __BIG_ENDIAN__ | 403 | #ifdef __BIG_ENDIAN__ |
404 | flags = os::Byteswap::byteswap(flags); | 404 | flags = os::Byteswap::byteswap(flags); |
405 | #endif | 405 | #endif |
406 | switch (flags) | 406 | switch (flags) |
407 | { | 407 | { |
408 | case 0: | 408 | case 0: |
409 | CurrentMaterial.Material.Wireframe=true; | 409 | CurrentMaterial.Material.Wireframe=true; |
410 | break; | 410 | break; |
411 | case 1: | 411 | case 1: |
412 | CurrentMaterial.Material.Wireframe=false; | 412 | CurrentMaterial.Material.Wireframe=false; |
413 | CurrentMaterial.Material.GouraudShading=false; | 413 | CurrentMaterial.Material.GouraudShading=false; |
414 | break; | 414 | break; |
415 | case 2: | 415 | case 2: |
416 | CurrentMaterial.Material.Wireframe=false; | 416 | CurrentMaterial.Material.Wireframe=false; |
417 | CurrentMaterial.Material.GouraudShading=true; | 417 | CurrentMaterial.Material.GouraudShading=true; |
418 | break; | 418 | break; |
419 | default: | 419 | default: |
420 | // phong and metal missing | 420 | // phong and metal missing |
421 | break; | 421 | break; |
422 | } | 422 | } |
423 | data.read += data.header.length - data.read; | 423 | data.read += data.header.length - data.read; |
424 | } | 424 | } |
425 | break; | 425 | break; |
426 | case C3DS_MATTEXMAP: | 426 | case C3DS_MATTEXMAP: |
427 | case C3DS_MATSPECMAP: | 427 | case C3DS_MATSPECMAP: |
428 | case C3DS_MATOPACMAP: | 428 | case C3DS_MATOPACMAP: |
429 | case C3DS_MATREFLMAP: | 429 | case C3DS_MATREFLMAP: |
430 | case C3DS_MATBUMPMAP: | 430 | case C3DS_MATBUMPMAP: |
431 | { | 431 | { |
432 | matSection=data.header.id; | 432 | matSection=data.header.id; |
433 | // Should contain a percentage chunk, but does | 433 | // Should contain a percentage chunk, but does |
434 | // not always have it | 434 | // not always have it |
435 | s16 testval; | 435 | s16 testval; |
436 | const long pos = file->getPos(); | 436 | const long pos = file->getPos(); |
437 | file->read(&testval, 2); | 437 | file->read(&testval, 2); |
438 | #ifdef __BIG_ENDIAN__ | 438 | #ifdef __BIG_ENDIAN__ |
439 | testval = os::Byteswap::byteswap(testval); | 439 | testval = os::Byteswap::byteswap(testval); |
440 | #endif | 440 | #endif |
441 | file->seek(pos, false); | 441 | file->seek(pos, false); |
442 | if ((testval == C3DS_PERCENTAGE_I) || | 442 | if ((testval == C3DS_PERCENTAGE_I) || |
443 | (testval == C3DS_PERCENTAGE_F)) | 443 | (testval == C3DS_PERCENTAGE_F)) |
444 | switch (matSection) | 444 | switch (matSection) |
445 | { | 445 | { |
446 | case C3DS_MATTEXMAP: | 446 | case C3DS_MATTEXMAP: |
447 | readPercentageChunk(file, &data, CurrentMaterial.Strength[0]); | 447 | readPercentageChunk(file, &data, CurrentMaterial.Strength[0]); |
448 | break; | 448 | break; |
449 | case C3DS_MATSPECMAP: | 449 | case C3DS_MATSPECMAP: |
450 | readPercentageChunk(file, &data, CurrentMaterial.Strength[1]); | 450 | readPercentageChunk(file, &data, CurrentMaterial.Strength[1]); |
451 | break; | 451 | break; |
452 | case C3DS_MATOPACMAP: | 452 | case C3DS_MATOPACMAP: |
453 | readPercentageChunk(file, &data, CurrentMaterial.Strength[2]); | 453 | readPercentageChunk(file, &data, CurrentMaterial.Strength[2]); |
454 | break; | 454 | break; |
455 | case C3DS_MATBUMPMAP: | 455 | case C3DS_MATBUMPMAP: |
456 | readPercentageChunk(file, &data, CurrentMaterial.Strength[4]); | 456 | readPercentageChunk(file, &data, CurrentMaterial.Strength[4]); |
457 | break; | 457 | break; |
458 | } | 458 | } |
459 | } | 459 | } |
460 | break; | 460 | break; |
461 | case C3DS_MATMAPFILE: | 461 | case C3DS_MATMAPFILE: |
462 | { | 462 | { |
463 | // read texture file name | 463 | // read texture file name |
464 | c8* c = new c8[data.header.length - data.read]; | 464 | c8* c = new c8[data.header.length - data.read]; |
465 | file->read(c, data.header.length - data.read); | 465 | file->read(c, data.header.length - data.read); |
466 | switch (matSection) | 466 | switch (matSection) |
467 | { | 467 | { |
468 | case C3DS_MATTEXMAP: | 468 | case C3DS_MATTEXMAP: |
469 | CurrentMaterial.Filename[0] = c; | 469 | CurrentMaterial.Filename[0] = c; |
470 | break; | 470 | break; |
471 | case C3DS_MATSPECMAP: | 471 | case C3DS_MATSPECMAP: |
472 | CurrentMaterial.Filename[1] = c; | 472 | CurrentMaterial.Filename[1] = c; |
473 | break; | 473 | break; |
474 | case C3DS_MATOPACMAP: | 474 | case C3DS_MATOPACMAP: |
475 | CurrentMaterial.Filename[2] = c; | 475 | CurrentMaterial.Filename[2] = c; |
476 | break; | 476 | break; |
477 | case C3DS_MATREFLMAP: | 477 | case C3DS_MATREFLMAP: |
478 | CurrentMaterial.Filename[3] = c; | 478 | CurrentMaterial.Filename[3] = c; |
479 | break; | 479 | break; |
480 | case C3DS_MATBUMPMAP: | 480 | case C3DS_MATBUMPMAP: |
481 | CurrentMaterial.Filename[4] = c; | 481 | CurrentMaterial.Filename[4] = c; |
482 | break; | 482 | break; |
483 | } | 483 | } |
484 | data.read += data.header.length - data.read; | 484 | data.read += data.header.length - data.read; |
485 | delete [] c; | 485 | delete [] c; |
486 | } | 486 | } |
487 | break; | 487 | break; |
488 | case C3DS_MAT_TEXTILING: | 488 | case C3DS_MAT_TEXTILING: |
489 | { | 489 | { |
490 | s16 flags; | 490 | s16 flags; |
491 | file->read(&flags, 2); | 491 | file->read(&flags, 2); |
492 | #ifdef __BIG_ENDIAN__ | 492 | #ifdef __BIG_ENDIAN__ |
493 | flags = os::Byteswap::byteswap(flags); | 493 | flags = os::Byteswap::byteswap(flags); |
494 | #endif | 494 | #endif |
495 | data.read += 2; | 495 | data.read += 2; |
496 | } | 496 | } |
497 | break; | 497 | break; |
498 | case C3DS_MAT_USCALE: | 498 | case C3DS_MAT_USCALE: |
499 | case C3DS_MAT_VSCALE: | 499 | case C3DS_MAT_VSCALE: |
500 | case C3DS_MAT_UOFFSET: | 500 | case C3DS_MAT_UOFFSET: |
501 | case C3DS_MAT_VOFFSET: | 501 | case C3DS_MAT_VOFFSET: |
502 | { | 502 | { |
503 | f32 value; | 503 | f32 value; |
504 | file->read(&value, 4); | 504 | file->read(&value, 4); |
505 | #ifdef __BIG_ENDIAN__ | 505 | #ifdef __BIG_ENDIAN__ |
506 | value = os::Byteswap::byteswap(value); | 506 | value = os::Byteswap::byteswap(value); |
507 | #endif | 507 | #endif |
508 | u32 i=0; | 508 | u32 i=0; |
509 | if (matSection != C3DS_MATTEXMAP) | 509 | if (matSection != C3DS_MATTEXMAP) |
510 | i=1; | 510 | i=1; |
511 | u32 j=0,k=0; | 511 | u32 j=0,k=0; |
512 | if (data.header.id == C3DS_MAT_VSCALE) | 512 | if (data.header.id == C3DS_MAT_VSCALE) |
513 | { | 513 | { |
514 | j=1; | 514 | j=1; |
515 | k=1; | 515 | k=1; |
516 | } | 516 | } |
517 | else if (data.header.id == C3DS_MAT_UOFFSET) | 517 | else if (data.header.id == C3DS_MAT_UOFFSET) |
518 | { | 518 | { |
519 | j=2; | 519 | j=2; |
520 | k=0; | 520 | k=0; |
521 | } | 521 | } |
522 | else if (data.header.id == C3DS_MAT_VOFFSET) | 522 | else if (data.header.id == C3DS_MAT_VOFFSET) |
523 | { | 523 | { |
524 | j=2; | 524 | j=2; |
525 | k=1; | 525 | k=1; |
526 | } | 526 | } |
527 | CurrentMaterial.Material.getTextureMatrix(i)(j,k)=value; | 527 | CurrentMaterial.Material.getTextureMatrix(i)(j,k)=value; |
528 | 528 | ||
529 | data.read += 4; | 529 | data.read += 4; |
530 | } | 530 | } |
531 | break; | 531 | break; |
532 | default: | 532 | default: |
533 | // ignore chunk | 533 | // ignore chunk |
534 | file->seek(data.header.length - data.read, true); | 534 | file->seek(data.header.length - data.read, true); |
535 | data.read += data.header.length - data.read; | 535 | data.read += data.header.length - data.read; |
536 | } | 536 | } |
537 | 537 | ||
538 | parent->read += data.read; | 538 | parent->read += data.read; |
539 | } | 539 | } |
540 | 540 | ||
541 | Materials.push_back(CurrentMaterial); | 541 | Materials.push_back(CurrentMaterial); |
542 | CurrentMaterial.clear(); | 542 | CurrentMaterial.clear(); |
543 | 543 | ||
544 | return true; | 544 | return true; |
545 | } | 545 | } |
546 | 546 | ||
547 | 547 | ||
548 | 548 | ||
549 | bool C3DSMeshFileLoader::readTrackChunk(io::IReadFile* file, ChunkData& data, | 549 | bool C3DSMeshFileLoader::readTrackChunk(io::IReadFile* file, ChunkData& data, |
550 | IMeshBuffer* mb, const core::vector3df& pivot) | 550 | IMeshBuffer* mb, const core::vector3df& pivot) |
551 | { | 551 | { |
552 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 552 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
553 | os::Printer::log("Load track chunk.", ELL_DEBUG); | 553 | os::Printer::log("Load track chunk.", ELL_DEBUG); |
554 | #endif | 554 | #endif |
555 | u16 flags; | 555 | u16 flags; |
556 | u32 flags2; | 556 | u32 flags2; |
557 | // Track flags | 557 | // Track flags |
558 | file->read(&flags, 2); | 558 | file->read(&flags, 2); |
559 | #ifdef __BIG_ENDIAN__ | 559 | #ifdef __BIG_ENDIAN__ |
560 | flags = os::Byteswap::byteswap(flags); | 560 | flags = os::Byteswap::byteswap(flags); |
561 | #endif | 561 | #endif |
562 | file->read(&flags2, 4); | 562 | file->read(&flags2, 4); |
563 | #ifdef __BIG_ENDIAN__ | 563 | #ifdef __BIG_ENDIAN__ |
564 | flags2 = os::Byteswap::byteswap(flags2); | 564 | flags2 = os::Byteswap::byteswap(flags2); |
565 | #endif | 565 | #endif |
566 | file->read(&flags2, 4); | 566 | file->read(&flags2, 4); |
567 | #ifdef __BIG_ENDIAN__ | 567 | #ifdef __BIG_ENDIAN__ |
568 | flags2 = os::Byteswap::byteswap(flags2); | 568 | flags2 = os::Byteswap::byteswap(flags2); |
569 | #endif | 569 | #endif |
570 | // Num keys | 570 | // Num keys |
571 | file->read(&flags2, 4); | 571 | file->read(&flags2, 4); |
572 | #ifdef __BIG_ENDIAN__ | 572 | #ifdef __BIG_ENDIAN__ |
573 | flags2 = os::Byteswap::byteswap(flags2); | 573 | flags2 = os::Byteswap::byteswap(flags2); |
574 | #endif | 574 | #endif |
575 | file->read(&flags2, 4); | 575 | file->read(&flags2, 4); |
576 | #ifdef __BIG_ENDIAN__ | 576 | #ifdef __BIG_ENDIAN__ |
577 | flags2 = os::Byteswap::byteswap(flags2); | 577 | flags2 = os::Byteswap::byteswap(flags2); |
578 | #endif | 578 | #endif |
579 | // TCB flags | 579 | // TCB flags |
580 | file->read(&flags, 2); | 580 | file->read(&flags, 2); |
581 | #ifdef __BIG_ENDIAN__ | 581 | #ifdef __BIG_ENDIAN__ |
582 | flags = os::Byteswap::byteswap(flags); | 582 | flags = os::Byteswap::byteswap(flags); |
583 | #endif | 583 | #endif |
584 | data.read += 20; | 584 | data.read += 20; |
585 | 585 | ||
586 | f32 angle=0.0f; | 586 | f32 angle=0.0f; |
587 | if (data.header.id== C3DS_ROT_TRACK_TAG) | 587 | if (data.header.id== C3DS_ROT_TRACK_TAG) |
588 | { | 588 | { |
589 | // Angle | 589 | // Angle |
590 | file->read(&angle, sizeof(f32)); | 590 | file->read(&angle, sizeof(f32)); |
591 | #ifdef __BIG_ENDIAN__ | 591 | #ifdef __BIG_ENDIAN__ |
592 | angle = os::Byteswap::byteswap(angle); | 592 | angle = os::Byteswap::byteswap(angle); |
593 | #endif | 593 | #endif |
594 | data.read += sizeof(f32); | 594 | data.read += sizeof(f32); |
595 | } | 595 | } |
596 | core::vector3df vec; | 596 | core::vector3df vec; |
597 | file->read(&vec.X, sizeof(f32)); | 597 | file->read(&vec.X, sizeof(f32)); |
598 | file->read(&vec.Y, sizeof(f32)); | 598 | file->read(&vec.Y, sizeof(f32)); |
599 | file->read(&vec.Z, sizeof(f32)); | 599 | file->read(&vec.Z, sizeof(f32)); |
600 | #ifdef __BIG_ENDIAN__ | 600 | #ifdef __BIG_ENDIAN__ |
601 | vec.X = os::Byteswap::byteswap(vec.X); | 601 | vec.X = os::Byteswap::byteswap(vec.X); |
602 | vec.Y = os::Byteswap::byteswap(vec.Y); | 602 | vec.Y = os::Byteswap::byteswap(vec.Y); |
603 | vec.Z = os::Byteswap::byteswap(vec.Z); | 603 | vec.Z = os::Byteswap::byteswap(vec.Z); |
604 | #endif | 604 | #endif |
605 | data.read += 12; | 605 | data.read += 12; |
606 | vec-=pivot; | 606 | vec-=pivot; |
607 | 607 | ||
608 | // apply transformation to mesh buffer | 608 | // apply transformation to mesh buffer |
609 | if (false)//mb) | 609 | if (false)//mb) |
610 | { | 610 | { |
611 | video::S3DVertex *vertices=(video::S3DVertex*)mb->getVertices(); | 611 | video::S3DVertex *vertices=(video::S3DVertex*)mb->getVertices(); |
612 | if (data.header.id==C3DS_POS_TRACK_TAG) | 612 | if (data.header.id==C3DS_POS_TRACK_TAG) |
613 | { | 613 | { |
614 | for (u32 i=0; i<mb->getVertexCount(); ++i) | 614 | for (u32 i=0; i<mb->getVertexCount(); ++i) |
615 | vertices[i].Pos+=vec; | 615 | vertices[i].Pos+=vec; |
616 | } | 616 | } |
617 | else if (data.header.id==C3DS_ROT_TRACK_TAG) | 617 | else if (data.header.id==C3DS_ROT_TRACK_TAG) |
618 | { | 618 | { |
619 | //TODO | 619 | //TODO |
620 | } | 620 | } |
621 | else if (data.header.id==C3DS_SCL_TRACK_TAG) | 621 | else if (data.header.id==C3DS_SCL_TRACK_TAG) |
622 | { | 622 | { |
623 | //TODO | 623 | //TODO |
624 | } | 624 | } |
625 | } | 625 | } |
626 | // skip further frames | 626 | // skip further frames |
627 | file->seek(data.header.length - data.read, true); | 627 | file->seek(data.header.length - data.read, true); |
628 | data.read += data.header.length - data.read; | 628 | data.read += data.header.length - data.read; |
629 | return true; | 629 | return true; |
630 | } | 630 | } |
631 | 631 | ||
632 | 632 | ||
633 | bool C3DSMeshFileLoader::readFrameChunk(io::IReadFile* file, ChunkData* parent) | 633 | bool C3DSMeshFileLoader::readFrameChunk(io::IReadFile* file, ChunkData* parent) |
634 | { | 634 | { |
635 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 635 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
636 | os::Printer::log("Load frame chunk.", ELL_DEBUG); | 636 | os::Printer::log("Load frame chunk.", ELL_DEBUG); |
637 | #endif | 637 | #endif |
638 | ChunkData data; | 638 | ChunkData data; |
639 | 639 | ||
640 | //KF_HDR is always at the beginning | 640 | //KF_HDR is always at the beginning |
641 | readChunkData(file, data); | 641 | readChunkData(file, data); |
642 | if (data.header.id != C3DS_KF_HDR) | 642 | if (data.header.id != C3DS_KF_HDR) |
643 | return false; | 643 | return false; |
644 | else | 644 | else |
645 | { | 645 | { |
646 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 646 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
647 | os::Printer::log("Load keyframe header.", ELL_DEBUG); | 647 | os::Printer::log("Load keyframe header.", ELL_DEBUG); |
648 | #endif | 648 | #endif |
649 | u16 version; | 649 | u16 version; |
650 | file->read(&version, 2); | 650 | file->read(&version, 2); |
651 | #ifdef __BIG_ENDIAN__ | 651 | #ifdef __BIG_ENDIAN__ |
652 | version = os::Byteswap::byteswap(version); | 652 | version = os::Byteswap::byteswap(version); |
653 | #endif | 653 | #endif |
654 | core::stringc name; | 654 | core::stringc name; |
655 | readString(file, data, name); | 655 | readString(file, data, name); |
656 | u32 flags; | 656 | u32 flags; |
657 | file->read(&flags, 4); | 657 | file->read(&flags, 4); |
658 | #ifdef __BIG_ENDIAN__ | 658 | #ifdef __BIG_ENDIAN__ |
659 | flags = os::Byteswap::byteswap(flags); | 659 | flags = os::Byteswap::byteswap(flags); |
660 | #endif | 660 | #endif |
661 | 661 | ||
662 | data.read += 4; | 662 | data.read += 4; |
663 | parent->read += data.read; | 663 | parent->read += data.read; |
664 | } | 664 | } |
665 | data.read=0; | 665 | data.read=0; |
666 | 666 | ||
667 | IMeshBuffer* mb=0; | 667 | IMeshBuffer* mb=0; |
668 | core::vector3df pivot,bboxCenter; | 668 | core::vector3df pivot,bboxCenter; |
669 | while(parent->read < parent->header.length) | 669 | while(parent->read < parent->header.length) |
670 | { | 670 | { |
671 | readChunkData(file, data); | 671 | readChunkData(file, data); |
672 | 672 | ||
673 | switch(data.header.id) | 673 | switch(data.header.id) |
674 | { | 674 | { |
675 | case C3DS_OBJECT_TAG: | 675 | case C3DS_OBJECT_TAG: |
676 | { | 676 | { |
677 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 677 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
678 | os::Printer::log("Load object tag.", ELL_DEBUG); | 678 | os::Printer::log("Load object tag.", ELL_DEBUG); |
679 | #endif | 679 | #endif |
680 | mb=0; | 680 | mb=0; |
681 | pivot.set(0.0f, 0.0f, 0.0f); | 681 | pivot.set(0.0f, 0.0f, 0.0f); |
682 | } | 682 | } |
683 | break; | 683 | break; |
684 | case C3DS_KF_SEG: | 684 | case C3DS_KF_SEG: |
685 | { | 685 | { |
686 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 686 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
687 | os::Printer::log("Load keyframe segment.", ELL_DEBUG); | 687 | os::Printer::log("Load keyframe segment.", ELL_DEBUG); |
688 | #endif | 688 | #endif |
689 | u32 flags; | 689 | u32 flags; |
690 | file->read(&flags, 4); | 690 | file->read(&flags, 4); |
691 | #ifdef __BIG_ENDIAN__ | 691 | #ifdef __BIG_ENDIAN__ |
692 | flags = os::Byteswap::byteswap(flags); | 692 | flags = os::Byteswap::byteswap(flags); |
693 | #endif | 693 | #endif |
694 | file->read(&flags, 4); | 694 | file->read(&flags, 4); |
695 | #ifdef __BIG_ENDIAN__ | 695 | #ifdef __BIG_ENDIAN__ |
696 | flags = os::Byteswap::byteswap(flags); | 696 | flags = os::Byteswap::byteswap(flags); |
697 | #endif | 697 | #endif |
698 | data.read += 8; | 698 | data.read += 8; |
699 | } | 699 | } |
700 | break; | 700 | break; |
701 | case C3DS_KF_NODE_HDR: | 701 | case C3DS_KF_NODE_HDR: |
702 | { | 702 | { |
703 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 703 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
704 | os::Printer::log("Load keyframe node header.", ELL_DEBUG); | 704 | os::Printer::log("Load keyframe node header.", ELL_DEBUG); |
705 | #endif | 705 | #endif |
706 | s16 flags; | 706 | s16 flags; |
707 | c8* c = new c8[data.header.length - data.read-6]; | 707 | c8* c = new c8[data.header.length - data.read-6]; |
708 | file->read(c, data.header.length - data.read-6); | 708 | file->read(c, data.header.length - data.read-6); |
709 | 709 | ||
710 | // search mesh buffer to apply these transformations to | 710 | // search mesh buffer to apply these transformations to |
711 | for (u32 i=0; i<MeshBufferNames.size(); ++i) | 711 | for (u32 i=0; i<MeshBufferNames.size(); ++i) |
712 | { | 712 | { |
713 | if (MeshBufferNames[i]==c) | 713 | if (MeshBufferNames[i]==c) |
714 | { | 714 | { |
715 | mb=Mesh->getMeshBuffer(i); | 715 | mb=Mesh->getMeshBuffer(i); |
716 | break; | 716 | break; |
717 | } | 717 | } |
718 | } | 718 | } |
719 | 719 | ||
720 | file->read(&flags, 2); | 720 | file->read(&flags, 2); |
721 | #ifdef __BIG_ENDIAN__ | 721 | #ifdef __BIG_ENDIAN__ |
722 | flags = os::Byteswap::byteswap(flags); | 722 | flags = os::Byteswap::byteswap(flags); |
723 | #endif | 723 | #endif |
724 | file->read(&flags, 2); | 724 | file->read(&flags, 2); |
725 | #ifdef __BIG_ENDIAN__ | 725 | #ifdef __BIG_ENDIAN__ |
726 | flags = os::Byteswap::byteswap(flags); | 726 | flags = os::Byteswap::byteswap(flags); |
727 | #endif | 727 | #endif |
728 | file->read(&flags, 2); | 728 | file->read(&flags, 2); |
729 | #ifdef __BIG_ENDIAN__ | 729 | #ifdef __BIG_ENDIAN__ |
730 | flags = os::Byteswap::byteswap(flags); | 730 | flags = os::Byteswap::byteswap(flags); |
731 | #endif | 731 | #endif |
732 | data.read += data.header.length - data.read; | 732 | data.read += data.header.length - data.read; |
733 | delete [] c; | 733 | delete [] c; |
734 | } | 734 | } |
735 | break; | 735 | break; |
736 | case C3DS_KF_CURTIME: | 736 | case C3DS_KF_CURTIME: |
737 | { | 737 | { |
738 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 738 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
739 | os::Printer::log("Load keyframe current time.", ELL_DEBUG); | 739 | os::Printer::log("Load keyframe current time.", ELL_DEBUG); |
740 | #endif | 740 | #endif |
741 | u32 flags; | 741 | u32 flags; |
742 | file->read(&flags, 4); | 742 | file->read(&flags, 4); |
743 | #ifdef __BIG_ENDIAN__ | 743 | #ifdef __BIG_ENDIAN__ |
744 | flags = os::Byteswap::byteswap(flags); | 744 | flags = os::Byteswap::byteswap(flags); |
745 | #endif | 745 | #endif |
746 | data.read += 4; | 746 | data.read += 4; |
747 | } | 747 | } |
748 | break; | 748 | break; |
749 | case C3DS_NODE_ID: | 749 | case C3DS_NODE_ID: |
750 | { | 750 | { |
751 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 751 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
752 | os::Printer::log("Load node ID.", ELL_DEBUG); | 752 | os::Printer::log("Load node ID.", ELL_DEBUG); |
753 | #endif | 753 | #endif |
754 | u16 flags; | 754 | u16 flags; |
755 | file->read(&flags, 2); | 755 | file->read(&flags, 2); |
756 | #ifdef __BIG_ENDIAN__ | 756 | #ifdef __BIG_ENDIAN__ |
757 | flags = os::Byteswap::byteswap(flags); | 757 | flags = os::Byteswap::byteswap(flags); |
758 | #endif | 758 | #endif |
759 | data.read += 2; | 759 | data.read += 2; |
760 | } | 760 | } |
761 | break; | 761 | break; |
762 | case C3DS_PIVOTPOINT: | 762 | case C3DS_PIVOTPOINT: |
763 | { | 763 | { |
764 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 764 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
765 | os::Printer::log("Load pivot point.", ELL_DEBUG); | 765 | os::Printer::log("Load pivot point.", ELL_DEBUG); |
766 | #endif | 766 | #endif |
767 | file->read(&pivot.X, sizeof(f32)); | 767 | file->read(&pivot.X, sizeof(f32)); |
768 | file->read(&pivot.Y, sizeof(f32)); | 768 | file->read(&pivot.Y, sizeof(f32)); |
769 | file->read(&pivot.Z, sizeof(f32)); | 769 | file->read(&pivot.Z, sizeof(f32)); |
770 | #ifdef __BIG_ENDIAN__ | 770 | #ifdef __BIG_ENDIAN__ |
771 | pivot.X = os::Byteswap::byteswap(pivot.X); | 771 | pivot.X = os::Byteswap::byteswap(pivot.X); |
772 | pivot.Y = os::Byteswap::byteswap(pivot.Y); | 772 | pivot.Y = os::Byteswap::byteswap(pivot.Y); |
773 | pivot.Z = os::Byteswap::byteswap(pivot.Z); | 773 | pivot.Z = os::Byteswap::byteswap(pivot.Z); |
774 | #endif | 774 | #endif |
775 | data.read += 12; | 775 | data.read += 12; |
776 | } | 776 | } |
777 | break; | 777 | break; |
778 | case C3DS_BOUNDBOX: | 778 | case C3DS_BOUNDBOX: |
779 | { | 779 | { |
780 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 780 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
781 | os::Printer::log("Load bounding box.", ELL_DEBUG); | 781 | os::Printer::log("Load bounding box.", ELL_DEBUG); |
782 | #endif | 782 | #endif |
783 | core::aabbox3df bbox; | 783 | core::aabbox3df bbox; |
784 | // abuse bboxCenter as temporary variable | 784 | // abuse bboxCenter as temporary variable |
785 | file->read(&bboxCenter.X, sizeof(f32)); | 785 | file->read(&bboxCenter.X, sizeof(f32)); |
786 | file->read(&bboxCenter.Y, sizeof(f32)); | 786 | file->read(&bboxCenter.Y, sizeof(f32)); |
787 | file->read(&bboxCenter.Z, sizeof(f32)); | 787 | file->read(&bboxCenter.Z, sizeof(f32)); |
788 | #ifdef __BIG_ENDIAN__ | 788 | #ifdef __BIG_ENDIAN__ |
789 | bboxCenter.X = os::Byteswap::byteswap(bboxCenter.X); | 789 | bboxCenter.X = os::Byteswap::byteswap(bboxCenter.X); |
790 | bboxCenter.Y = os::Byteswap::byteswap(bboxCenter.Y); | 790 | bboxCenter.Y = os::Byteswap::byteswap(bboxCenter.Y); |
791 | bboxCenter.Z = os::Byteswap::byteswap(bboxCenter.Z); | 791 | bboxCenter.Z = os::Byteswap::byteswap(bboxCenter.Z); |
792 | #endif | 792 | #endif |
793 | bbox.reset(bboxCenter); | 793 | bbox.reset(bboxCenter); |
794 | file->read(&bboxCenter.X, sizeof(f32)); | 794 | file->read(&bboxCenter.X, sizeof(f32)); |
795 | file->read(&bboxCenter.Y, sizeof(f32)); | 795 | file->read(&bboxCenter.Y, sizeof(f32)); |
796 | file->read(&bboxCenter.Z, sizeof(f32)); | 796 | file->read(&bboxCenter.Z, sizeof(f32)); |
797 | #ifdef __BIG_ENDIAN__ | 797 | #ifdef __BIG_ENDIAN__ |
798 | bboxCenter.X = os::Byteswap::byteswap(bboxCenter.X); | 798 | bboxCenter.X = os::Byteswap::byteswap(bboxCenter.X); |
799 | bboxCenter.Y = os::Byteswap::byteswap(bboxCenter.Y); | 799 | bboxCenter.Y = os::Byteswap::byteswap(bboxCenter.Y); |
800 | bboxCenter.Z = os::Byteswap::byteswap(bboxCenter.Z); | 800 | bboxCenter.Z = os::Byteswap::byteswap(bboxCenter.Z); |
801 | #endif | 801 | #endif |
802 | bbox.addInternalPoint(bboxCenter); | 802 | bbox.addInternalPoint(bboxCenter); |
803 | bboxCenter=bbox.getCenter(); | 803 | bboxCenter=bbox.getCenter(); |
804 | data.read += 24; | 804 | data.read += 24; |
805 | } | 805 | } |
806 | break; | 806 | break; |
807 | case C3DS_MORPH_SMOOTH: | 807 | case C3DS_MORPH_SMOOTH: |
808 | { | 808 | { |
809 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 809 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
810 | os::Printer::log("Load morph smooth.", ELL_DEBUG); | 810 | os::Printer::log("Load morph smooth.", ELL_DEBUG); |
811 | #endif | 811 | #endif |
812 | f32 flag; | 812 | f32 flag; |
813 | file->read(&flag, 4); | 813 | file->read(&flag, 4); |
814 | #ifdef __BIG_ENDIAN__ | 814 | #ifdef __BIG_ENDIAN__ |
815 | flag = os::Byteswap::byteswap(flag); | 815 | flag = os::Byteswap::byteswap(flag); |
816 | #endif | 816 | #endif |
817 | data.read += 4; | 817 | data.read += 4; |
818 | } | 818 | } |
819 | break; | 819 | break; |
820 | case C3DS_POS_TRACK_TAG: | 820 | case C3DS_POS_TRACK_TAG: |
821 | case C3DS_ROT_TRACK_TAG: | 821 | case C3DS_ROT_TRACK_TAG: |
822 | case C3DS_SCL_TRACK_TAG: | 822 | case C3DS_SCL_TRACK_TAG: |
823 | readTrackChunk(file, data, mb, bboxCenter-pivot); | 823 | readTrackChunk(file, data, mb, bboxCenter-pivot); |
824 | break; | 824 | break; |
825 | default: | 825 | default: |
826 | // ignore chunk | 826 | // ignore chunk |
827 | file->seek(data.header.length - data.read, true); | 827 | file->seek(data.header.length - data.read, true); |
828 | data.read += data.header.length - data.read; | 828 | data.read += data.header.length - data.read; |
829 | } | 829 | } |
830 | 830 | ||
831 | parent->read += data.read; | 831 | parent->read += data.read; |
832 | data.read=0; | 832 | data.read=0; |
833 | } | 833 | } |
834 | 834 | ||
835 | return true; | 835 | return true; |
836 | } | 836 | } |
837 | 837 | ||
838 | 838 | ||
839 | bool C3DSMeshFileLoader::readChunk(io::IReadFile* file, ChunkData* parent) | 839 | bool C3DSMeshFileLoader::readChunk(io::IReadFile* file, ChunkData* parent) |
840 | { | 840 | { |
841 | while(parent->read < parent->header.length) | 841 | while(parent->read < parent->header.length) |
842 | { | 842 | { |
843 | ChunkData data; | 843 | ChunkData data; |
844 | readChunkData(file, data); | 844 | readChunkData(file, data); |
845 | 845 | ||
846 | switch(data.header.id) | 846 | switch(data.header.id) |
847 | { | 847 | { |
848 | case C3DS_VERSION: | 848 | case C3DS_VERSION: |
849 | { | 849 | { |
850 | u16 version; | 850 | u16 version; |
851 | file->read(&version, sizeof(u16)); | 851 | file->read(&version, sizeof(u16)); |
852 | #ifdef __BIG_ENDIAN__ | 852 | #ifdef __BIG_ENDIAN__ |
853 | version = os::Byteswap::byteswap(version); | 853 | version = os::Byteswap::byteswap(version); |
854 | #endif | 854 | #endif |
855 | file->seek(data.header.length - data.read - 2, true); | 855 | file->seek(data.header.length - data.read - 2, true); |
856 | data.read += data.header.length - data.read; | 856 | data.read += data.header.length - data.read; |
857 | if (version != 0x03) | 857 | if (version != 0x03) |
858 | os::Printer::log("3ds file version is other than 3.", ELL_ERROR); | 858 | os::Printer::log("3ds file version is other than 3.", ELL_ERROR); |
859 | } | 859 | } |
860 | break; | 860 | break; |
861 | case C3DS_EDIT_MATERIAL: | 861 | case C3DS_EDIT_MATERIAL: |
862 | readMaterialChunk(file, &data); | 862 | readMaterialChunk(file, &data); |
863 | break; | 863 | break; |
864 | case C3DS_KEYF3DS: | 864 | case C3DS_KEYF3DS: |
865 | readFrameChunk(file, &data); | 865 | readFrameChunk(file, &data); |
866 | break; | 866 | break; |
867 | case C3DS_EDIT3DS: | 867 | case C3DS_EDIT3DS: |
868 | break; | 868 | break; |
869 | case C3DS_MESHVERSION: | 869 | case C3DS_MESHVERSION: |
870 | case 0x01: | 870 | case 0x01: |
871 | { | 871 | { |
872 | u32 version; | 872 | u32 version; |
873 | file->read(&version, sizeof(u32)); | 873 | file->read(&version, sizeof(u32)); |
874 | #ifdef __BIG_ENDIAN__ | 874 | #ifdef __BIG_ENDIAN__ |
875 | version = os::Byteswap::byteswap(version); | 875 | version = os::Byteswap::byteswap(version); |
876 | #endif | 876 | #endif |
877 | data.read += sizeof(u32); | 877 | data.read += sizeof(u32); |
878 | } | 878 | } |
879 | break; | 879 | break; |
880 | case C3DS_EDIT_OBJECT: | 880 | case C3DS_EDIT_OBJECT: |
881 | { | 881 | { |
882 | core::stringc name; | 882 | core::stringc name; |
883 | readString(file, data, name); | 883 | readString(file, data, name); |
884 | readObjectChunk(file, &data); | 884 | readObjectChunk(file, &data); |
885 | composeObject(file, name); | 885 | composeObject(file, name); |
886 | } | 886 | } |
887 | break; | 887 | break; |
888 | 888 | ||
889 | default: | 889 | default: |
890 | // ignore chunk | 890 | // ignore chunk |
891 | file->seek(data.header.length - data.read, true); | 891 | file->seek(data.header.length - data.read, true); |
892 | data.read += data.header.length - data.read; | 892 | data.read += data.header.length - data.read; |
893 | } | 893 | } |
894 | 894 | ||
895 | parent->read += data.read; | 895 | parent->read += data.read; |
896 | } | 896 | } |
897 | 897 | ||
898 | return true; | 898 | return true; |
899 | } | 899 | } |
900 | 900 | ||
901 | 901 | ||
902 | bool C3DSMeshFileLoader::readObjectChunk(io::IReadFile* file, ChunkData* parent) | 902 | bool C3DSMeshFileLoader::readObjectChunk(io::IReadFile* file, ChunkData* parent) |
903 | { | 903 | { |
904 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 904 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
905 | os::Printer::log("Load object chunk.", ELL_DEBUG); | 905 | os::Printer::log("Load object chunk.", ELL_DEBUG); |
906 | #endif | 906 | #endif |
907 | while(parent->read < parent->header.length) | 907 | while(parent->read < parent->header.length) |
908 | { | 908 | { |
909 | ChunkData data; | 909 | ChunkData data; |
910 | readChunkData(file, data); | 910 | readChunkData(file, data); |
911 | 911 | ||
912 | switch(data.header.id) | 912 | switch(data.header.id) |
913 | { | 913 | { |
914 | case C3DS_OBJTRIMESH: | 914 | case C3DS_OBJTRIMESH: |
915 | readObjectChunk(file, &data); | 915 | readObjectChunk(file, &data); |
916 | break; | 916 | break; |
917 | 917 | ||
918 | case C3DS_TRIVERT: | 918 | case C3DS_TRIVERT: |
919 | readVertices(file, data); | 919 | readVertices(file, data); |
920 | break; | 920 | break; |
921 | 921 | ||
922 | case C3DS_POINTFLAGARRAY: | 922 | case C3DS_POINTFLAGARRAY: |
923 | { | 923 | { |
924 | u16 numVertex, flags; | 924 | u16 numVertex, flags; |
925 | file->read(&numVertex, sizeof(u16)); | 925 | file->read(&numVertex, sizeof(u16)); |
926 | #ifdef __BIG_ENDIAN__ | 926 | #ifdef __BIG_ENDIAN__ |
927 | numVertex= os::Byteswap::byteswap(numVertex); | 927 | numVertex= os::Byteswap::byteswap(numVertex); |
928 | #endif | 928 | #endif |
929 | for (u16 i=0; i<numVertex; ++i) | 929 | for (u16 i=0; i<numVertex; ++i) |
930 | { | 930 | { |
931 | file->read(&flags, sizeof(u16)); | 931 | file->read(&flags, sizeof(u16)); |
932 | #ifdef __BIG_ENDIAN__ | 932 | #ifdef __BIG_ENDIAN__ |
933 | flags = os::Byteswap::byteswap(flags); | 933 | flags = os::Byteswap::byteswap(flags); |
934 | #endif | 934 | #endif |
935 | } | 935 | } |
936 | data.read += (numVertex+1)*sizeof(u16); | 936 | data.read += (numVertex+1)*sizeof(u16); |
937 | } | 937 | } |
938 | break; | 938 | break; |
939 | 939 | ||
940 | case C3DS_TRIFACE: | 940 | case C3DS_TRIFACE: |
941 | readIndices(file, data); | 941 | readIndices(file, data); |
942 | readObjectChunk(file, &data); // read smooth and material groups | 942 | readObjectChunk(file, &data); // read smooth and material groups |
943 | break; | 943 | break; |
944 | 944 | ||
945 | case C3DS_TRIFACEMAT: | 945 | case C3DS_TRIFACEMAT: |
946 | readMaterialGroup(file, data); | 946 | readMaterialGroup(file, data); |
947 | break; | 947 | break; |
948 | 948 | ||
949 | case C3DS_TRIUV: // getting texture coordinates | 949 | case C3DS_TRIUV: // getting texture coordinates |
950 | readTextureCoords(file, data); | 950 | readTextureCoords(file, data); |
951 | break; | 951 | break; |
952 | 952 | ||
953 | case C3DS_TRIMATRIX: | 953 | case C3DS_TRIMATRIX: |
954 | { | 954 | { |
955 | f32 mat[4][3]; | 955 | f32 mat[4][3]; |
956 | file->read(&mat, 12*sizeof(f32)); | 956 | file->read(&mat, 12*sizeof(f32)); |
957 | TransformationMatrix.makeIdentity(); | 957 | TransformationMatrix.makeIdentity(); |
958 | for (int i=0; i<4; ++i) | 958 | for (int i=0; i<4; ++i) |
959 | { | 959 | { |
960 | for (int j=0; j<3; ++j) | 960 | for (int j=0; j<3; ++j) |
961 | { | 961 | { |
962 | #ifdef __BIG_ENDIAN__ | 962 | #ifdef __BIG_ENDIAN__ |
963 | TransformationMatrix(i,j)=os::Byteswap::byteswap(mat[i][j]); | 963 | TransformationMatrix(i,j)=os::Byteswap::byteswap(mat[i][j]); |
964 | #else | 964 | #else |
965 | TransformationMatrix(i,j)=mat[i][j]; | 965 | TransformationMatrix(i,j)=mat[i][j]; |
966 | #endif | 966 | #endif |
967 | } | 967 | } |
968 | } | 968 | } |
969 | data.read += 12*sizeof(f32); | 969 | data.read += 12*sizeof(f32); |
970 | } | 970 | } |
971 | break; | 971 | break; |
972 | case C3DS_MESHCOLOR: | 972 | case C3DS_MESHCOLOR: |
973 | { | 973 | { |
974 | u8 flag; | 974 | u8 flag; |
975 | file->read(&flag, sizeof(u8)); | 975 | file->read(&flag, sizeof(u8)); |
976 | ++data.read; | 976 | ++data.read; |
977 | } | 977 | } |
978 | break; | 978 | break; |
979 | case C3DS_TRISMOOTH: // TODO | 979 | case C3DS_TRISMOOTH: // TODO |
980 | { | 980 | { |
981 | SmoothingGroups = new u32[CountFaces]; | 981 | SmoothingGroups = new u32[CountFaces]; |
982 | file->read(SmoothingGroups, CountFaces*sizeof(u32)); | 982 | file->read(SmoothingGroups, CountFaces*sizeof(u32)); |
983 | #ifdef __BIG_ENDIAN__ | 983 | #ifdef __BIG_ENDIAN__ |
984 | for (u16 i=0; i<CountFaces; ++i) | 984 | for (u16 i=0; i<CountFaces; ++i) |
985 | SmoothingGroups[i] = os::Byteswap::byteswap(SmoothingGroups[i]); | 985 | SmoothingGroups[i] = os::Byteswap::byteswap(SmoothingGroups[i]); |
986 | #endif | 986 | #endif |
987 | data.read += CountFaces*sizeof(u32); | 987 | data.read += CountFaces*sizeof(u32); |
988 | } | 988 | } |
989 | break; | 989 | break; |
990 | 990 | ||
991 | default: | 991 | default: |
992 | // ignore chunk | 992 | // ignore chunk |
993 | file->seek(data.header.length - data.read, true); | 993 | file->seek(data.header.length - data.read, true); |
994 | data.read += data.header.length - data.read; | 994 | data.read += data.header.length - data.read; |
995 | } | 995 | } |
996 | 996 | ||
997 | parent->read += data.read; | 997 | parent->read += data.read; |
998 | } | 998 | } |
999 | 999 | ||
1000 | return true; | 1000 | return true; |
1001 | } | 1001 | } |
1002 | 1002 | ||
1003 | 1003 | ||
1004 | void C3DSMeshFileLoader::composeObject(io::IReadFile* file, const core::stringc& name) | 1004 | void C3DSMeshFileLoader::composeObject(io::IReadFile* file, const core::stringc& name) |
1005 | { | 1005 | { |
1006 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 1006 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
1007 | os::Printer::log("Compose object.", ELL_DEBUG); | 1007 | os::Printer::log("Compose object.", ELL_DEBUG); |
1008 | #endif | 1008 | #endif |
1009 | if (Mesh->getMeshBufferCount() != Materials.size()) | 1009 | if (Mesh->getMeshBufferCount() != Materials.size()) |
1010 | loadMaterials(file); | 1010 | loadMaterials(file); |
1011 | 1011 | ||
1012 | if (MaterialGroups.empty()) | 1012 | if (MaterialGroups.empty()) |
1013 | { | 1013 | { |
1014 | // no material group, so add all | 1014 | // no material group, so add all |
1015 | SMaterialGroup group; | 1015 | SMaterialGroup group; |
1016 | group.faceCount = CountFaces; | 1016 | group.faceCount = CountFaces; |
1017 | group.faces = new u16[group.faceCount]; | 1017 | group.faces = new u16[group.faceCount]; |
1018 | for (u32 i=0; i<group.faceCount; ++i) | 1018 | for (u32 i=0; i<group.faceCount; ++i) |
1019 | group.faces[i] = i; | 1019 | group.faces[i] = i; |
1020 | MaterialGroups.push_back(group); | 1020 | MaterialGroups.push_back(group); |
1021 | 1021 | ||
1022 | // if we've got no material, add one without a texture | 1022 | // if we've got no material, add one without a texture |
1023 | if (Materials.empty()) | 1023 | if (Materials.empty()) |
1024 | { | 1024 | { |
1025 | SCurrentMaterial m; | 1025 | SCurrentMaterial m; |
1026 | Materials.push_back(m); | 1026 | Materials.push_back(m); |
1027 | SMeshBuffer* mb = new scene::SMeshBuffer(); | 1027 | SMeshBuffer* mb = new scene::SMeshBuffer(); |
1028 | Mesh->addMeshBuffer(mb); | 1028 | Mesh->addMeshBuffer(mb); |
1029 | mb->getMaterial() = Materials[0].Material; | 1029 | mb->getMaterial() = Materials[0].Material; |
1030 | mb->drop(); | 1030 | mb->drop(); |
1031 | // add an empty mesh buffer name | 1031 | // add an empty mesh buffer name |
1032 | MeshBufferNames.push_back(""); | 1032 | MeshBufferNames.push_back(""); |
1033 | } | 1033 | } |
1034 | } | 1034 | } |
1035 | 1035 | ||
1036 | for (u32 i=0; i<MaterialGroups.size(); ++i) | 1036 | for (u32 i=0; i<MaterialGroups.size(); ++i) |
1037 | { | 1037 | { |
1038 | SMeshBuffer* mb = 0; | 1038 | SMeshBuffer* mb = 0; |
1039 | video::SMaterial* mat=0; | 1039 | video::SMaterial* mat=0; |
1040 | u32 mbPos; | 1040 | u32 mbPos; |
1041 | // -3 because we add three vertices at once | 1041 | // -3 because we add three vertices at once |
1042 | u32 maxPrimitives = core::min_(SceneManager->getVideoDriver()->getMaximalPrimitiveCount(), (u32)((1<<16)-1))-3; // currently hardcoded s16 max value for index pointers | 1042 | u32 maxPrimitives = core::min_(SceneManager->getVideoDriver()->getMaximalPrimitiveCount(), (u32)((1<<16)-1))-3; // currently hardcoded s16 max value for index pointers |
1043 | 1043 | ||
1044 | // find mesh buffer for this group | 1044 | // find mesh buffer for this group |
1045 | for (mbPos=0; mbPos<Materials.size(); ++mbPos) | 1045 | for (mbPos=0; mbPos<Materials.size(); ++mbPos) |
1046 | { | 1046 | { |
1047 | if (MaterialGroups[i].MaterialName == Materials[mbPos].Name) | 1047 | if (MaterialGroups[i].MaterialName == Materials[mbPos].Name) |
1048 | { | 1048 | { |
1049 | mb = (SMeshBuffer*)Mesh->getMeshBuffer(mbPos); | 1049 | mb = (SMeshBuffer*)Mesh->getMeshBuffer(mbPos); |
1050 | mat=&Materials[mbPos].Material; | 1050 | mat=&Materials[mbPos].Material; |
1051 | MeshBufferNames[mbPos]=name; | 1051 | MeshBufferNames[mbPos]=name; |
1052 | break; | 1052 | break; |
1053 | } | 1053 | } |
1054 | } | 1054 | } |
1055 | 1055 | ||
1056 | if (mb != 0) | 1056 | if (mb != 0) |
1057 | { | 1057 | { |
1058 | // add geometry to the buffer. | 1058 | // add geometry to the buffer. |
1059 | 1059 | ||
1060 | video::S3DVertex vtx; | 1060 | video::S3DVertex vtx; |
1061 | core::vector3df vec; | 1061 | core::vector3df vec; |
1062 | vtx.Color=mat->DiffuseColor; | 1062 | vtx.Color=mat->DiffuseColor; |
1063 | if (mat->MaterialType==video::EMT_TRANSPARENT_VERTEX_ALPHA) | 1063 | if (mat->MaterialType==video::EMT_TRANSPARENT_VERTEX_ALPHA) |
1064 | { | 1064 | { |
1065 | vtx.Color.setAlpha((int)(255.0f*mat->MaterialTypeParam)); | 1065 | vtx.Color.setAlpha((int)(255.0f*mat->MaterialTypeParam)); |
1066 | } | 1066 | } |
1067 | vtx.Normal.set(0,0,0); | 1067 | vtx.Normal.set(0,0,0); |
1068 | 1068 | ||
1069 | for (s32 f=0; f<MaterialGroups[i].faceCount; ++f) | 1069 | for (s32 f=0; f<MaterialGroups[i].faceCount; ++f) |
1070 | { | 1070 | { |
1071 | u32 vtxCount = mb->Vertices.size(); | 1071 | u32 vtxCount = mb->Vertices.size(); |
1072 | if (vtxCount>maxPrimitives) | 1072 | if (vtxCount>maxPrimitives) |
1073 | { | 1073 | { |
1074 | IMeshBuffer* tmp = mb; | 1074 | IMeshBuffer* tmp = mb; |
1075 | mb = new SMeshBuffer(); | 1075 | mb = new SMeshBuffer(); |
1076 | Mesh->addMeshBuffer(mb); | 1076 | Mesh->addMeshBuffer(mb); |
1077 | mb->drop(); | 1077 | mb->drop(); |
1078 | Mesh->MeshBuffers[mbPos] = Mesh->MeshBuffers.getLast(); | 1078 | Mesh->MeshBuffers[mbPos] = Mesh->MeshBuffers.getLast(); |
1079 | Mesh->MeshBuffers[Mesh->MeshBuffers.size()-1] = tmp; | 1079 | Mesh->MeshBuffers[Mesh->MeshBuffers.size()-1] = tmp; |
1080 | mb->getMaterial() = tmp->getMaterial(); | 1080 | mb->getMaterial() = tmp->getMaterial(); |
1081 | vtxCount=0; | 1081 | vtxCount=0; |
1082 | } | 1082 | } |
1083 | 1083 | ||
1084 | for (s32 v=0; v<3; ++v) | 1084 | for (s32 v=0; v<3; ++v) |
1085 | { | 1085 | { |
1086 | s32 idx = Indices[MaterialGroups[i].faces[f]*4 +v]; | 1086 | s32 idx = Indices[MaterialGroups[i].faces[f]*4 +v]; |
1087 | 1087 | ||
1088 | if (CountVertices > idx) | 1088 | if (CountVertices > idx) |
1089 | { | 1089 | { |
1090 | vtx.Pos.X = Vertices[idx*3 + 0]; | 1090 | vtx.Pos.X = Vertices[idx*3 + 0]; |
1091 | vtx.Pos.Z = Vertices[idx*3 + 1]; | 1091 | vtx.Pos.Z = Vertices[idx*3 + 1]; |
1092 | vtx.Pos.Y = Vertices[idx*3 + 2]; | 1092 | vtx.Pos.Y = Vertices[idx*3 + 2]; |
1093 | // TransformationMatrix.transformVect(vtx.Pos); | 1093 | // TransformationMatrix.transformVect(vtx.Pos); |
1094 | } | 1094 | } |
1095 | 1095 | ||
1096 | if (CountTCoords > idx) | 1096 | if (CountTCoords > idx) |
1097 | { | 1097 | { |
1098 | vtx.TCoords.X = TCoords[idx*2 + 0]; | 1098 | vtx.TCoords.X = TCoords[idx*2 + 0]; |
1099 | vtx.TCoords.Y = 1.0f -TCoords[idx*2 + 1]; | 1099 | vtx.TCoords.Y = 1.0f -TCoords[idx*2 + 1]; |
1100 | } | 1100 | } |
1101 | 1101 | ||
1102 | mb->Vertices.push_back(vtx); | 1102 | mb->Vertices.push_back(vtx); |
1103 | } | 1103 | } |
1104 | 1104 | ||
1105 | // compute normal | 1105 | // compute normal |
1106 | core::plane3d<f32> pl(mb->Vertices[vtxCount].Pos, mb->Vertices[vtxCount+2].Pos, | 1106 | core::plane3d<f32> pl(mb->Vertices[vtxCount].Pos, mb->Vertices[vtxCount+2].Pos, |
1107 | mb->Vertices[vtxCount+1].Pos); | 1107 | mb->Vertices[vtxCount+1].Pos); |
1108 | 1108 | ||
1109 | mb->Vertices[vtxCount].Normal = pl.Normal; | 1109 | mb->Vertices[vtxCount].Normal = pl.Normal; |
1110 | mb->Vertices[vtxCount+1].Normal = pl.Normal; | 1110 | mb->Vertices[vtxCount+1].Normal = pl.Normal; |
1111 | mb->Vertices[vtxCount+2].Normal = pl.Normal; | 1111 | mb->Vertices[vtxCount+2].Normal = pl.Normal; |
1112 | 1112 | ||
1113 | // add indices | 1113 | // add indices |
1114 | 1114 | ||
1115 | mb->Indices.push_back(vtxCount); | 1115 | mb->Indices.push_back(vtxCount); |
1116 | mb->Indices.push_back(vtxCount+2); | 1116 | mb->Indices.push_back(vtxCount+2); |
1117 | mb->Indices.push_back(vtxCount+1); | 1117 | mb->Indices.push_back(vtxCount+1); |
1118 | } | 1118 | } |
1119 | } | 1119 | } |
1120 | else | 1120 | else |
1121 | os::Printer::log("Found no matching material for Group in 3ds file.", ELL_WARNING); | 1121 | os::Printer::log("Found no matching material for Group in 3ds file.", ELL_WARNING); |
1122 | } | 1122 | } |
1123 | 1123 | ||
1124 | cleanUp(); | 1124 | cleanUp(); |
1125 | } | 1125 | } |
1126 | 1126 | ||
1127 | 1127 | ||
1128 | void C3DSMeshFileLoader::loadMaterials(io::IReadFile* file) | 1128 | void C3DSMeshFileLoader::loadMaterials(io::IReadFile* file) |
1129 | { | 1129 | { |
1130 | // create a mesh buffer for every material | 1130 | // create a mesh buffer for every material |
1131 | core::stringc modelFilename = file->getFileName(); | 1131 | core::stringc modelFilename = file->getFileName(); |
1132 | 1132 | ||
1133 | if (Materials.empty()) | 1133 | if (Materials.empty()) |
1134 | os::Printer::log("No materials found in 3ds file.", ELL_INFORMATION); | 1134 | os::Printer::log("No materials found in 3ds file.", ELL_INFORMATION); |
1135 | 1135 | ||
1136 | MeshBufferNames.reallocate(Materials.size()); | 1136 | MeshBufferNames.reallocate(Materials.size()); |
1137 | for (u32 i=0; i<Materials.size(); ++i) | 1137 | for (u32 i=0; i<Materials.size(); ++i) |
1138 | { | 1138 | { |
1139 | MeshBufferNames.push_back(""); | 1139 | MeshBufferNames.push_back(""); |
1140 | SMeshBuffer* m = new scene::SMeshBuffer(); | 1140 | SMeshBuffer* m = new scene::SMeshBuffer(); |
1141 | Mesh->addMeshBuffer(m); | 1141 | Mesh->addMeshBuffer(m); |
1142 | 1142 | ||
1143 | m->getMaterial() = Materials[i].Material; | 1143 | m->getMaterial() = Materials[i].Material; |
1144 | if (Materials[i].Filename[0].size()) | 1144 | if (Materials[i].Filename[0].size()) |
1145 | { | 1145 | { |
1146 | video::ITexture* texture = 0; | 1146 | video::ITexture* texture = 0; |
1147 | if (FileSystem->existFile(Materials[i].Filename[0])) | 1147 | if (FileSystem->existFile(Materials[i].Filename[0])) |
1148 | texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[0]); | 1148 | texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[0]); |
1149 | if (!texture) | 1149 | if (!texture) |
1150 | { | 1150 | { |
1151 | const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[0]); | 1151 | const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[0]); |
1152 | if (FileSystem->existFile(fname)) | 1152 | if (FileSystem->existFile(fname)) |
1153 | texture = SceneManager->getVideoDriver()->getTexture(fname); | 1153 | texture = SceneManager->getVideoDriver()->getTexture(fname); |
1154 | } | 1154 | } |
1155 | if (!texture) | 1155 | if (!texture) |
1156 | os::Printer::log("Could not load a texture for entry in 3ds file", | 1156 | os::Printer::log("Could not load a texture for entry in 3ds file", |
1157 | Materials[i].Filename[0].c_str(), ELL_WARNING); | 1157 | Materials[i].Filename[0].c_str(), ELL_WARNING); |
1158 | else | 1158 | else |
1159 | m->getMaterial().setTexture(0, texture); | 1159 | m->getMaterial().setTexture(0, texture); |
1160 | } | 1160 | } |
1161 | 1161 | ||
1162 | if (Materials[i].Filename[2].size()) | 1162 | if (Materials[i].Filename[2].size()) |
1163 | { | 1163 | { |
1164 | video::ITexture* texture = 0; | 1164 | video::ITexture* texture = 0; |
1165 | if (FileSystem->existFile(Materials[i].Filename[2])) | 1165 | if (FileSystem->existFile(Materials[i].Filename[2])) |
1166 | texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[2]); | 1166 | texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[2]); |
1167 | if (!texture) | 1167 | if (!texture) |
1168 | { | 1168 | { |
1169 | const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[2]); | 1169 | const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[2]); |
1170 | if (FileSystem->existFile(fname)) | 1170 | if (FileSystem->existFile(fname)) |
1171 | texture = SceneManager->getVideoDriver()->getTexture(fname); | 1171 | texture = SceneManager->getVideoDriver()->getTexture(fname); |
1172 | } | 1172 | } |
1173 | if (!texture) | 1173 | if (!texture) |
1174 | { | 1174 | { |
1175 | os::Printer::log("Could not load a texture for entry in 3ds file", | 1175 | os::Printer::log("Could not load a texture for entry in 3ds file", |
1176 | Materials[i].Filename[2].c_str(), ELL_WARNING); | 1176 | Materials[i].Filename[2].c_str(), ELL_WARNING); |
1177 | } | 1177 | } |
1178 | else | 1178 | else |
1179 | { | 1179 | { |
1180 | m->getMaterial().setTexture(0, texture); | 1180 | m->getMaterial().setTexture(0, texture); |
1181 | m->getMaterial().MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; | 1181 | m->getMaterial().MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; |
1182 | } | 1182 | } |
1183 | } | 1183 | } |
1184 | 1184 | ||
1185 | if (Materials[i].Filename[3].size()) | 1185 | if (Materials[i].Filename[3].size()) |
1186 | { | 1186 | { |
1187 | video::ITexture* texture = 0; | 1187 | video::ITexture* texture = 0; |
1188 | if (FileSystem->existFile(Materials[i].Filename[3])) | 1188 | if (FileSystem->existFile(Materials[i].Filename[3])) |
1189 | texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[3]); | 1189 | texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[3]); |
1190 | if (!texture) | 1190 | if (!texture) |
1191 | { | 1191 | { |
1192 | const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[3]); | 1192 | const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[3]); |
1193 | if (FileSystem->existFile(fname)) | 1193 | if (FileSystem->existFile(fname)) |
1194 | texture = SceneManager->getVideoDriver()->getTexture(fname); | 1194 | texture = SceneManager->getVideoDriver()->getTexture(fname); |
1195 | } | 1195 | } |
1196 | 1196 | ||
1197 | if (!texture) | 1197 | if (!texture) |
1198 | { | 1198 | { |
1199 | os::Printer::log("Could not load a texture for entry in 3ds file", | 1199 | os::Printer::log("Could not load a texture for entry in 3ds file", |
1200 | Materials[i].Filename[3].c_str(), ELL_WARNING); | 1200 | Materials[i].Filename[3].c_str(), ELL_WARNING); |
1201 | } | 1201 | } |
1202 | else | 1202 | else |
1203 | { | 1203 | { |
1204 | m->getMaterial().setTexture(1, m->getMaterial().getTexture(0)); | 1204 | m->getMaterial().setTexture(1, m->getMaterial().getTexture(0)); |
1205 | m->getMaterial().setTexture(0, texture); | 1205 | m->getMaterial().setTexture(0, texture); |
1206 | m->getMaterial().MaterialType = video::EMT_REFLECTION_2_LAYER; | 1206 | m->getMaterial().MaterialType = video::EMT_REFLECTION_2_LAYER; |
1207 | } | 1207 | } |
1208 | } | 1208 | } |
1209 | 1209 | ||
1210 | if (Materials[i].Filename[4].size()) | 1210 | if (Materials[i].Filename[4].size()) |
1211 | { | 1211 | { |
1212 | video::ITexture* texture = 0; | 1212 | video::ITexture* texture = 0; |
1213 | if (FileSystem->existFile(Materials[i].Filename[4])) | 1213 | if (FileSystem->existFile(Materials[i].Filename[4])) |
1214 | texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[4]); | 1214 | texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[4]); |
1215 | if (!texture) | 1215 | if (!texture) |
1216 | { | 1216 | { |
1217 | const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[4]); | 1217 | const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[4]); |
1218 | if (FileSystem->existFile(fname)) | 1218 | if (FileSystem->existFile(fname)) |
1219 | texture = SceneManager->getVideoDriver()->getTexture(fname); | 1219 | texture = SceneManager->getVideoDriver()->getTexture(fname); |
1220 | } | 1220 | } |
1221 | if (!texture) | 1221 | if (!texture) |
1222 | os::Printer::log("Could not load a texture for entry in 3ds file", | 1222 | os::Printer::log("Could not load a texture for entry in 3ds file", |
1223 | Materials[i].Filename[4].c_str(), ELL_WARNING); | 1223 | Materials[i].Filename[4].c_str(), ELL_WARNING); |
1224 | else | 1224 | else |
1225 | { | 1225 | { |
1226 | m->getMaterial().setTexture(1, texture); | 1226 | m->getMaterial().setTexture(1, texture); |
1227 | SceneManager->getVideoDriver()->makeNormalMapTexture(texture, Materials[i].Strength[4]*10.f); | 1227 | SceneManager->getVideoDriver()->makeNormalMapTexture(texture, Materials[i].Strength[4]*10.f); |
1228 | m->getMaterial().MaterialType=video::EMT_PARALLAX_MAP_SOLID; | 1228 | m->getMaterial().MaterialType=video::EMT_PARALLAX_MAP_SOLID; |
1229 | m->getMaterial().MaterialTypeParam=.035f; | 1229 | m->getMaterial().MaterialTypeParam=.035f; |
1230 | } | 1230 | } |
1231 | } | 1231 | } |
1232 | 1232 | ||
1233 | m->drop(); | 1233 | m->drop(); |
1234 | } | 1234 | } |
1235 | } | 1235 | } |
1236 | 1236 | ||
1237 | 1237 | ||
1238 | void C3DSMeshFileLoader::cleanUp() | 1238 | void C3DSMeshFileLoader::cleanUp() |
1239 | { | 1239 | { |
1240 | delete [] Vertices; | 1240 | delete [] Vertices; |
1241 | CountVertices = 0; | 1241 | CountVertices = 0; |
1242 | Vertices = 0; | 1242 | Vertices = 0; |
1243 | delete [] Indices; | 1243 | delete [] Indices; |
1244 | Indices = 0; | 1244 | Indices = 0; |
1245 | CountFaces = 0; | 1245 | CountFaces = 0; |
1246 | delete [] SmoothingGroups; | 1246 | delete [] SmoothingGroups; |
1247 | SmoothingGroups = 0; | 1247 | SmoothingGroups = 0; |
1248 | delete [] TCoords; | 1248 | delete [] TCoords; |
1249 | TCoords = 0; | 1249 | TCoords = 0; |
1250 | CountTCoords = 0; | 1250 | CountTCoords = 0; |
1251 | 1251 | ||
1252 | MaterialGroups.clear(); | 1252 | MaterialGroups.clear(); |
1253 | } | 1253 | } |
1254 | 1254 | ||
1255 | 1255 | ||
1256 | void C3DSMeshFileLoader::readTextureCoords(io::IReadFile* file, ChunkData& data) | 1256 | void C3DSMeshFileLoader::readTextureCoords(io::IReadFile* file, ChunkData& data) |
1257 | { | 1257 | { |
1258 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 1258 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
1259 | os::Printer::log("Load texture coords.", ELL_DEBUG); | 1259 | os::Printer::log("Load texture coords.", ELL_DEBUG); |
1260 | #endif | 1260 | #endif |
1261 | file->read(&CountTCoords, sizeof(CountTCoords)); | 1261 | file->read(&CountTCoords, sizeof(CountTCoords)); |
1262 | #ifdef __BIG_ENDIAN__ | 1262 | #ifdef __BIG_ENDIAN__ |
1263 | CountTCoords = os::Byteswap::byteswap(CountTCoords); | 1263 | CountTCoords = os::Byteswap::byteswap(CountTCoords); |
1264 | #endif | 1264 | #endif |
1265 | data.read += sizeof(CountTCoords); | 1265 | data.read += sizeof(CountTCoords); |
1266 | 1266 | ||
1267 | s32 tcoordsBufferByteSize = CountTCoords * sizeof(f32) * 2; | 1267 | s32 tcoordsBufferByteSize = CountTCoords * sizeof(f32) * 2; |
1268 | 1268 | ||
1269 | if (data.header.length - data.read != tcoordsBufferByteSize) | 1269 | if (data.header.length - data.read != tcoordsBufferByteSize) |
1270 | { | 1270 | { |
1271 | os::Printer::log("Invalid size of tcoords found in 3ds file.", ELL_WARNING); | 1271 | os::Printer::log("Invalid size of tcoords found in 3ds file.", ELL_WARNING); |
1272 | return; | 1272 | return; |
1273 | } | 1273 | } |
1274 | 1274 | ||
1275 | TCoords = new f32[CountTCoords * 3]; | 1275 | TCoords = new f32[CountTCoords * 3]; |
1276 | file->read(TCoords, tcoordsBufferByteSize); | 1276 | file->read(TCoords, tcoordsBufferByteSize); |
1277 | #ifdef __BIG_ENDIAN__ | 1277 | #ifdef __BIG_ENDIAN__ |
1278 | for (int i=0;i<CountTCoords*2;i++) TCoords[i] = os::Byteswap::byteswap(TCoords[i]); | 1278 | for (int i=0;i<CountTCoords*2;i++) TCoords[i] = os::Byteswap::byteswap(TCoords[i]); |
1279 | #endif | 1279 | #endif |
1280 | data.read += tcoordsBufferByteSize; | 1280 | data.read += tcoordsBufferByteSize; |
1281 | } | 1281 | } |
1282 | 1282 | ||
1283 | 1283 | ||
1284 | void C3DSMeshFileLoader::readMaterialGroup(io::IReadFile* file, ChunkData& data) | 1284 | void C3DSMeshFileLoader::readMaterialGroup(io::IReadFile* file, ChunkData& data) |
1285 | { | 1285 | { |
1286 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 1286 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
1287 | os::Printer::log("Load material group.", ELL_DEBUG); | 1287 | os::Printer::log("Load material group.", ELL_DEBUG); |
1288 | #endif | 1288 | #endif |
1289 | SMaterialGroup group; | 1289 | SMaterialGroup group; |
1290 | 1290 | ||
1291 | readString(file, data, group.MaterialName); | 1291 | readString(file, data, group.MaterialName); |
1292 | 1292 | ||
1293 | file->read(&group.faceCount, sizeof(group.faceCount)); | 1293 | file->read(&group.faceCount, sizeof(group.faceCount)); |
1294 | #ifdef __BIG_ENDIAN__ | 1294 | #ifdef __BIG_ENDIAN__ |
1295 | group.faceCount = os::Byteswap::byteswap(group.faceCount); | 1295 | group.faceCount = os::Byteswap::byteswap(group.faceCount); |
1296 | #endif | 1296 | #endif |
1297 | data.read += sizeof(group.faceCount); | 1297 | data.read += sizeof(group.faceCount); |
1298 | 1298 | ||
1299 | // read faces | 1299 | // read faces |
1300 | group.faces = new u16[group.faceCount]; | 1300 | group.faces = new u16[group.faceCount]; |
1301 | file->read(group.faces, sizeof(u16) * group.faceCount); | 1301 | file->read(group.faces, sizeof(u16) * group.faceCount); |
1302 | #ifdef __BIG_ENDIAN__ | 1302 | #ifdef __BIG_ENDIAN__ |
1303 | for (u32 i=0;i<group.faceCount;++i) | 1303 | for (u32 i=0;i<group.faceCount;++i) |
1304 | group.faces[i] = os::Byteswap::byteswap(group.faces[i]); | 1304 | group.faces[i] = os::Byteswap::byteswap(group.faces[i]); |
1305 | #endif | 1305 | #endif |
1306 | data.read += sizeof(u16) * group.faceCount; | 1306 | data.read += sizeof(u16) * group.faceCount; |
1307 | 1307 | ||
1308 | MaterialGroups.push_back(group); | 1308 | MaterialGroups.push_back(group); |
1309 | } | 1309 | } |
1310 | 1310 | ||
1311 | 1311 | ||
1312 | void C3DSMeshFileLoader::readIndices(io::IReadFile* file, ChunkData& data) | 1312 | void C3DSMeshFileLoader::readIndices(io::IReadFile* file, ChunkData& data) |
1313 | { | 1313 | { |
1314 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 1314 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
1315 | os::Printer::log("Load indices.", ELL_DEBUG); | 1315 | os::Printer::log("Load indices.", ELL_DEBUG); |
1316 | #endif | 1316 | #endif |
1317 | file->read(&CountFaces, sizeof(CountFaces)); | 1317 | file->read(&CountFaces, sizeof(CountFaces)); |
1318 | #ifdef __BIG_ENDIAN__ | 1318 | #ifdef __BIG_ENDIAN__ |
1319 | CountFaces = os::Byteswap::byteswap(CountFaces); | 1319 | CountFaces = os::Byteswap::byteswap(CountFaces); |
1320 | #endif | 1320 | #endif |
1321 | data.read += sizeof(CountFaces); | 1321 | data.read += sizeof(CountFaces); |
1322 | 1322 | ||
1323 | s32 indexBufferByteSize = CountFaces * sizeof(u16) * 4; | 1323 | s32 indexBufferByteSize = CountFaces * sizeof(u16) * 4; |
1324 | 1324 | ||
1325 | // Indices are u16s. | 1325 | // Indices are u16s. |
1326 | // After every 3 Indices in the array, there follows an edge flag. | 1326 | // After every 3 Indices in the array, there follows an edge flag. |
1327 | Indices = new u16[CountFaces * 4]; | 1327 | Indices = new u16[CountFaces * 4]; |
1328 | file->read(Indices, indexBufferByteSize); | 1328 | file->read(Indices, indexBufferByteSize); |
1329 | #ifdef __BIG_ENDIAN__ | 1329 | #ifdef __BIG_ENDIAN__ |
1330 | for (int i=0;i<CountFaces*4;++i) | 1330 | for (int i=0;i<CountFaces*4;++i) |
1331 | Indices[i] = os::Byteswap::byteswap(Indices[i]); | 1331 | Indices[i] = os::Byteswap::byteswap(Indices[i]); |
1332 | #endif | 1332 | #endif |
1333 | data.read += indexBufferByteSize; | 1333 | data.read += indexBufferByteSize; |
1334 | } | 1334 | } |
1335 | 1335 | ||
1336 | 1336 | ||
1337 | void C3DSMeshFileLoader::readVertices(io::IReadFile* file, ChunkData& data) | 1337 | void C3DSMeshFileLoader::readVertices(io::IReadFile* file, ChunkData& data) |
1338 | { | 1338 | { |
1339 | #ifdef _IRR_DEBUG_3DS_LOADER_ | 1339 | #ifdef _IRR_DEBUG_3DS_LOADER_ |
1340 | os::Printer::log("Load vertices.", ELL_DEBUG); | 1340 | os::Printer::log("Load vertices.", ELL_DEBUG); |
1341 | #endif | 1341 | #endif |
1342 | file->read(&CountVertices, sizeof(CountVertices)); | 1342 | file->read(&CountVertices, sizeof(CountVertices)); |
1343 | #ifdef __BIG_ENDIAN__ | 1343 | #ifdef __BIG_ENDIAN__ |
1344 | CountVertices = os::Byteswap::byteswap(CountVertices); | 1344 | CountVertices = os::Byteswap::byteswap(CountVertices); |
1345 | #endif | 1345 | #endif |
1346 | data.read += sizeof(CountVertices); | 1346 | data.read += sizeof(CountVertices); |
1347 | 1347 | ||
1348 | const s32 vertexBufferByteSize = CountVertices * sizeof(f32) * 3; | 1348 | const s32 vertexBufferByteSize = CountVertices * sizeof(f32) * 3; |
1349 | 1349 | ||
1350 | if (data.header.length - data.read != vertexBufferByteSize) | 1350 | if (data.header.length - data.read != vertexBufferByteSize) |
1351 | { | 1351 | { |
1352 | os::Printer::log("Invalid size of vertices found in 3ds file", core::stringc(CountVertices), ELL_ERROR); | 1352 | os::Printer::log("Invalid size of vertices found in 3ds file", core::stringc(CountVertices), ELL_ERROR); |
1353 | return; | 1353 | return; |
1354 | } | 1354 | } |
1355 | 1355 | ||
1356 | Vertices = new f32[CountVertices * 3]; | 1356 | Vertices = new f32[CountVertices * 3]; |
1357 | file->read(Vertices, vertexBufferByteSize); | 1357 | file->read(Vertices, vertexBufferByteSize); |
1358 | #ifdef __BIG_ENDIAN__ | 1358 | #ifdef __BIG_ENDIAN__ |
1359 | for (int i=0;i<CountVertices*3;i++) | 1359 | for (int i=0;i<CountVertices*3;i++) |
1360 | Vertices[i] = os::Byteswap::byteswap(Vertices[i]); | 1360 | Vertices[i] = os::Byteswap::byteswap(Vertices[i]); |
1361 | #endif | 1361 | #endif |
1362 | data.read += vertexBufferByteSize; | 1362 | data.read += vertexBufferByteSize; |
1363 | } | 1363 | } |
1364 | 1364 | ||
1365 | 1365 | ||
1366 | void C3DSMeshFileLoader::readChunkData(io::IReadFile* file, ChunkData& data) | 1366 | void C3DSMeshFileLoader::readChunkData(io::IReadFile* file, ChunkData& data) |
1367 | { | 1367 | { |
1368 | file->read(&data.header, sizeof(ChunkHeader)); | 1368 | file->read(&data.header, sizeof(ChunkHeader)); |
1369 | #ifdef __BIG_ENDIAN__ | 1369 | #ifdef __BIG_ENDIAN__ |
1370 | data.header.id = os::Byteswap::byteswap(data.header.id); | 1370 | data.header.id = os::Byteswap::byteswap(data.header.id); |
1371 | data.header.length = os::Byteswap::byteswap(data.header.length); | 1371 | data.header.length = os::Byteswap::byteswap(data.header.length); |
1372 | #endif | 1372 | #endif |
1373 | data.read += sizeof(ChunkHeader); | 1373 | data.read += sizeof(ChunkHeader); |
1374 | } | 1374 | } |
1375 | 1375 | ||
1376 | 1376 | ||
1377 | void C3DSMeshFileLoader::readString(io::IReadFile* file, ChunkData& data, core::stringc& out) | 1377 | void C3DSMeshFileLoader::readString(io::IReadFile* file, ChunkData& data, core::stringc& out) |
1378 | { | 1378 | { |
1379 | c8 c = 1; | 1379 | c8 c = 1; |
1380 | out = ""; | 1380 | out = ""; |
1381 | 1381 | ||
1382 | while (c) | 1382 | while (c) |
1383 | { | 1383 | { |
1384 | file->read(&c, sizeof(c8)); | 1384 | file->read(&c, sizeof(c8)); |
1385 | if (c) | 1385 | if (c) |
1386 | out.append(c); | 1386 | out.append(c); |
1387 | } | 1387 | } |
1388 | data.read+=out.size()+1; | 1388 | data.read+=out.size()+1; |
1389 | } | 1389 | } |
1390 | 1390 | ||
1391 | 1391 | ||
1392 | } // end namespace scene | 1392 | } // end namespace scene |
1393 | } // end namespace irr | 1393 | } // end namespace irr |
1394 | 1394 | ||
1395 | #endif // _IRR_COMPILE_WITH_3DS_LOADER_ | 1395 | #endif // _IRR_COMPILE_WITH_3DS_LOADER_ |
1396 | 1396 | ||