diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CMS3DMeshFileLoader.cpp | 1636 |
1 files changed, 818 insertions, 818 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CMS3DMeshFileLoader.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CMS3DMeshFileLoader.cpp index 9a88d49..af06188 100644 --- a/libraries/irrlicht-1.8/source/Irrlicht/CMS3DMeshFileLoader.cpp +++ b/libraries/irrlicht-1.8/source/Irrlicht/CMS3DMeshFileLoader.cpp | |||
@@ -1,818 +1,818 @@ | |||
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_MS3D_LOADER_ | 6 | #ifdef _IRR_COMPILE_WITH_MS3D_LOADER_ |
7 | 7 | ||
8 | #include "IReadFile.h" | 8 | #include "IReadFile.h" |
9 | #include "os.h" | 9 | #include "os.h" |
10 | #include "CMS3DMeshFileLoader.h" | 10 | #include "CMS3DMeshFileLoader.h" |
11 | #include "CSkinnedMesh.h" | 11 | #include "CSkinnedMesh.h" |
12 | 12 | ||
13 | 13 | ||
14 | namespace irr | 14 | namespace irr |
15 | { | 15 | { |
16 | namespace scene | 16 | namespace scene |
17 | { | 17 | { |
18 | 18 | ||
19 | #ifdef _DEBUG | 19 | #ifdef _DEBUG |
20 | #define _IRR_DEBUG_MS3D_LOADER_ | 20 | #define _IRR_DEBUG_MS3D_LOADER_ |
21 | #endif | 21 | #endif |
22 | 22 | ||
23 | // byte-align structures | 23 | // byte-align structures |
24 | #include "irrpack.h" | 24 | #include "irrpack.h" |
25 | 25 | ||
26 | namespace { | 26 | namespace { |
27 | // File header | 27 | // File header |
28 | struct MS3DHeader | 28 | struct MS3DHeader |
29 | { | 29 | { |
30 | char ID[10]; | 30 | char ID[10]; |
31 | int Version; | 31 | int Version; |
32 | } PACK_STRUCT; | 32 | } PACK_STRUCT; |
33 | 33 | ||
34 | // Vertex information | 34 | // Vertex information |
35 | struct MS3DVertex | 35 | struct MS3DVertex |
36 | { | 36 | { |
37 | u8 Flags; | 37 | u8 Flags; |
38 | float Vertex[3]; | 38 | float Vertex[3]; |
39 | char BoneID; | 39 | char BoneID; |
40 | u8 RefCount; | 40 | u8 RefCount; |
41 | } PACK_STRUCT; | 41 | } PACK_STRUCT; |
42 | 42 | ||
43 | // Triangle information | 43 | // Triangle information |
44 | struct MS3DTriangle | 44 | struct MS3DTriangle |
45 | { | 45 | { |
46 | u16 Flags; | 46 | u16 Flags; |
47 | u16 VertexIndices[3]; | 47 | u16 VertexIndices[3]; |
48 | float VertexNormals[3][3]; | 48 | float VertexNormals[3][3]; |
49 | float S[3], T[3]; | 49 | float S[3], T[3]; |
50 | u8 SmoothingGroup; | 50 | u8 SmoothingGroup; |
51 | u8 GroupIndex; | 51 | u8 GroupIndex; |
52 | } PACK_STRUCT; | 52 | } PACK_STRUCT; |
53 | 53 | ||
54 | // Material information | 54 | // Material information |
55 | struct MS3DMaterial | 55 | struct MS3DMaterial |
56 | { | 56 | { |
57 | char Name[32]; | 57 | char Name[32]; |
58 | float Ambient[4]; | 58 | float Ambient[4]; |
59 | float Diffuse[4]; | 59 | float Diffuse[4]; |
60 | float Specular[4]; | 60 | float Specular[4]; |
61 | float Emissive[4]; | 61 | float Emissive[4]; |
62 | float Shininess; // 0.0f - 128.0f | 62 | float Shininess; // 0.0f - 128.0f |
63 | float Transparency; // 0.0f - 1.0f | 63 | float Transparency; // 0.0f - 1.0f |
64 | u8 Mode; // 0, 1, 2 is unused now | 64 | u8 Mode; // 0, 1, 2 is unused now |
65 | char Texture[128]; | 65 | char Texture[128]; |
66 | char Alphamap[128]; | 66 | char Alphamap[128]; |
67 | } PACK_STRUCT; | 67 | } PACK_STRUCT; |
68 | 68 | ||
69 | // Joint information | 69 | // Joint information |
70 | struct MS3DJoint | 70 | struct MS3DJoint |
71 | { | 71 | { |
72 | u8 Flags; | 72 | u8 Flags; |
73 | char Name[32]; | 73 | char Name[32]; |
74 | char ParentName[32]; | 74 | char ParentName[32]; |
75 | float Rotation[3]; | 75 | float Rotation[3]; |
76 | float Translation[3]; | 76 | float Translation[3]; |
77 | u16 NumRotationKeyframes; | 77 | u16 NumRotationKeyframes; |
78 | u16 NumTranslationKeyframes; | 78 | u16 NumTranslationKeyframes; |
79 | } PACK_STRUCT; | 79 | } PACK_STRUCT; |
80 | 80 | ||
81 | // Keyframe data | 81 | // Keyframe data |
82 | struct MS3DKeyframe | 82 | struct MS3DKeyframe |
83 | { | 83 | { |
84 | float Time; | 84 | float Time; |
85 | float Parameter[3]; | 85 | float Parameter[3]; |
86 | } PACK_STRUCT; | 86 | } PACK_STRUCT; |
87 | 87 | ||
88 | // vertex weights in 1.8.x | 88 | // vertex weights in 1.8.x |
89 | struct MS3DVertexWeights | 89 | struct MS3DVertexWeights |
90 | { | 90 | { |
91 | char boneIds[3]; | 91 | char boneIds[3]; |
92 | u8 weights[3]; | 92 | u8 weights[3]; |
93 | } PACK_STRUCT; | 93 | } PACK_STRUCT; |
94 | 94 | ||
95 | } // end namespace | 95 | } // end namespace |
96 | 96 | ||
97 | // Default alignment | 97 | // Default alignment |
98 | #include "irrunpack.h" | 98 | #include "irrunpack.h" |
99 | 99 | ||
100 | struct SGroup | 100 | struct SGroup |
101 | { | 101 | { |
102 | core::stringc Name; | 102 | core::stringc Name; |
103 | core::array<u16> VertexIds; | 103 | core::array<u16> VertexIds; |
104 | u16 MaterialIdx; | 104 | u16 MaterialIdx; |
105 | }; | 105 | }; |
106 | 106 | ||
107 | //! Constructor | 107 | //! Constructor |
108 | CMS3DMeshFileLoader::CMS3DMeshFileLoader(video::IVideoDriver *driver) | 108 | CMS3DMeshFileLoader::CMS3DMeshFileLoader(video::IVideoDriver *driver) |
109 | : Driver(driver), AnimatedMesh(0) | 109 | : Driver(driver), AnimatedMesh(0) |
110 | { | 110 | { |
111 | #ifdef _DEBUG | 111 | #ifdef _DEBUG |
112 | setDebugName("CMS3DMeshFileLoader"); | 112 | setDebugName("CMS3DMeshFileLoader"); |
113 | #endif | 113 | #endif |
114 | } | 114 | } |
115 | 115 | ||
116 | 116 | ||
117 | //! returns true if the file maybe is able to be loaded by this class | 117 | //! returns true if the file maybe is able to be loaded by this class |
118 | //! based on the file extension (e.g. ".bsp") | 118 | //! based on the file extension (e.g. ".bsp") |
119 | bool CMS3DMeshFileLoader::isALoadableFileExtension(const io::path& filename) const | 119 | bool CMS3DMeshFileLoader::isALoadableFileExtension(const io::path& filename) const |
120 | { | 120 | { |
121 | return core::hasFileExtension ( filename, "ms3d" ); | 121 | return core::hasFileExtension ( filename, "ms3d" ); |
122 | } | 122 | } |
123 | 123 | ||
124 | 124 | ||
125 | //! creates/loads an animated mesh from the file. | 125 | //! creates/loads an animated mesh from the file. |
126 | //! \return Pointer to the created mesh. Returns 0 if loading failed. | 126 | //! \return Pointer to the created mesh. Returns 0 if loading failed. |
127 | //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). | 127 | //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). |
128 | //! See IReferenceCounted::drop() for more information. | 128 | //! See IReferenceCounted::drop() for more information. |
129 | IAnimatedMesh* CMS3DMeshFileLoader::createMesh(io::IReadFile* file) | 129 | IAnimatedMesh* CMS3DMeshFileLoader::createMesh(io::IReadFile* file) |
130 | { | 130 | { |
131 | if (!file) | 131 | if (!file) |
132 | return 0; | 132 | return 0; |
133 | 133 | ||
134 | AnimatedMesh = new CSkinnedMesh(); | 134 | AnimatedMesh = new CSkinnedMesh(); |
135 | 135 | ||
136 | if ( load(file) ) | 136 | if ( load(file) ) |
137 | { | 137 | { |
138 | AnimatedMesh->finalize(); | 138 | AnimatedMesh->finalize(); |
139 | } | 139 | } |
140 | else | 140 | else |
141 | { | 141 | { |
142 | AnimatedMesh->drop(); | 142 | AnimatedMesh->drop(); |
143 | AnimatedMesh = 0; | 143 | AnimatedMesh = 0; |
144 | } | 144 | } |
145 | 145 | ||
146 | return AnimatedMesh; | 146 | return AnimatedMesh; |
147 | } | 147 | } |
148 | 148 | ||
149 | 149 | ||
150 | //! loads a milkshape file | 150 | //! loads a milkshape file |
151 | bool CMS3DMeshFileLoader::load(io::IReadFile* file) | 151 | bool CMS3DMeshFileLoader::load(io::IReadFile* file) |
152 | { | 152 | { |
153 | if (!file) | 153 | if (!file) |
154 | return false; | 154 | return false; |
155 | 155 | ||
156 | // find file size | 156 | // find file size |
157 | const long fileSize = file->getSize(); | 157 | const long fileSize = file->getSize(); |
158 | 158 | ||
159 | // read whole file | 159 | // read whole file |
160 | 160 | ||
161 | u8* buffer = new u8[fileSize]; | 161 | u8* buffer = new u8[fileSize]; |
162 | s32 read = file->read(buffer, fileSize); | 162 | s32 read = file->read(buffer, fileSize); |
163 | if (read != fileSize) | 163 | if (read != fileSize) |
164 | { | 164 | { |
165 | delete [] buffer; | 165 | delete [] buffer; |
166 | os::Printer::log("Could not read full file. Loading failed", file->getFileName(), ELL_ERROR); | 166 | os::Printer::log("Could not read full file. Loading failed", file->getFileName(), ELL_ERROR); |
167 | return false; | 167 | return false; |
168 | } | 168 | } |
169 | 169 | ||
170 | // read header | 170 | // read header |
171 | 171 | ||
172 | const u8 *pPtr = (u8*)((void*)buffer); | 172 | const u8 *pPtr = (u8*)((void*)buffer); |
173 | MS3DHeader *pHeader = (MS3DHeader*)pPtr; | 173 | MS3DHeader *pHeader = (MS3DHeader*)pPtr; |
174 | pPtr += sizeof(MS3DHeader); | 174 | pPtr += sizeof(MS3DHeader); |
175 | 175 | ||
176 | if ( strncmp( pHeader->ID, "MS3D000000", 10 ) != 0 ) | 176 | if ( strncmp( pHeader->ID, "MS3D000000", 10 ) != 0 ) |
177 | { | 177 | { |
178 | delete [] buffer; | 178 | delete [] buffer; |
179 | os::Printer::log("Not a valid Milkshape3D Model File. Loading failed", file->getFileName(), ELL_ERROR); | 179 | os::Printer::log("Not a valid Milkshape3D Model File. Loading failed", file->getFileName(), ELL_ERROR); |
180 | return false; | 180 | return false; |
181 | } | 181 | } |
182 | 182 | ||
183 | #ifdef __BIG_ENDIAN__ | 183 | #ifdef __BIG_ENDIAN__ |
184 | pHeader->Version = os::Byteswap::byteswap(pHeader->Version); | 184 | pHeader->Version = os::Byteswap::byteswap(pHeader->Version); |
185 | #endif | 185 | #endif |
186 | if ( pHeader->Version < 3 || pHeader->Version > 4 ) | 186 | if ( pHeader->Version < 3 || pHeader->Version > 4 ) |
187 | { | 187 | { |
188 | delete [] buffer; | 188 | delete [] buffer; |
189 | os::Printer::log("Only Milkshape3D version 3 and 4 (1.3 to 1.8) is supported. Loading failed", file->getFileName(), ELL_ERROR); | 189 | os::Printer::log("Only Milkshape3D version 3 and 4 (1.3 to 1.8) is supported. Loading failed", file->getFileName(), ELL_ERROR); |
190 | return false; | 190 | return false; |
191 | } | 191 | } |
192 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | 192 | #ifdef _IRR_DEBUG_MS3D_LOADER_ |
193 | os::Printer::log("Loaded header version", core::stringc(pHeader->Version).c_str()); | 193 | os::Printer::log("Loaded header version", core::stringc(pHeader->Version).c_str()); |
194 | #endif | 194 | #endif |
195 | 195 | ||
196 | // get pointers to data | 196 | // get pointers to data |
197 | 197 | ||
198 | // vertices | 198 | // vertices |
199 | u16 numVertices = *(u16*)pPtr; | 199 | u16 numVertices = *(u16*)pPtr; |
200 | #ifdef __BIG_ENDIAN__ | 200 | #ifdef __BIG_ENDIAN__ |
201 | numVertices = os::Byteswap::byteswap(numVertices); | 201 | numVertices = os::Byteswap::byteswap(numVertices); |
202 | #endif | 202 | #endif |
203 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | 203 | #ifdef _IRR_DEBUG_MS3D_LOADER_ |
204 | os::Printer::log("Load vertices", core::stringc(numVertices).c_str()); | 204 | os::Printer::log("Load vertices", core::stringc(numVertices).c_str()); |
205 | #endif | 205 | #endif |
206 | pPtr += sizeof(u16); | 206 | pPtr += sizeof(u16); |
207 | MS3DVertex *vertices = (MS3DVertex*)pPtr; | 207 | MS3DVertex *vertices = (MS3DVertex*)pPtr; |
208 | pPtr += sizeof(MS3DVertex) * numVertices; | 208 | pPtr += sizeof(MS3DVertex) * numVertices; |
209 | if (pPtr > buffer+fileSize) | 209 | if (pPtr > buffer+fileSize) |
210 | { | 210 | { |
211 | delete [] buffer; | 211 | delete [] buffer; |
212 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | 212 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); |
213 | return false; | 213 | return false; |
214 | } | 214 | } |
215 | for (u16 tmp=0; tmp<numVertices; ++tmp) | 215 | for (u16 tmp=0; tmp<numVertices; ++tmp) |
216 | { | 216 | { |
217 | #ifdef __BIG_ENDIAN__ | 217 | #ifdef __BIG_ENDIAN__ |
218 | vertices[tmp].Vertex[0] = os::Byteswap::byteswap(vertices[tmp].Vertex[0]); | 218 | vertices[tmp].Vertex[0] = os::Byteswap::byteswap(vertices[tmp].Vertex[0]); |
219 | vertices[tmp].Vertex[1] = os::Byteswap::byteswap(vertices[tmp].Vertex[1]); | 219 | vertices[tmp].Vertex[1] = os::Byteswap::byteswap(vertices[tmp].Vertex[1]); |
220 | vertices[tmp].Vertex[2] = -os::Byteswap::byteswap(vertices[tmp].Vertex[2]); | 220 | vertices[tmp].Vertex[2] = -os::Byteswap::byteswap(vertices[tmp].Vertex[2]); |
221 | #else | 221 | #else |
222 | vertices[tmp].Vertex[2] = -vertices[tmp].Vertex[2]; | 222 | vertices[tmp].Vertex[2] = -vertices[tmp].Vertex[2]; |
223 | #endif | 223 | #endif |
224 | } | 224 | } |
225 | 225 | ||
226 | // triangles | 226 | // triangles |
227 | u16 numTriangles = *(u16*)pPtr; | 227 | u16 numTriangles = *(u16*)pPtr; |
228 | #ifdef __BIG_ENDIAN__ | 228 | #ifdef __BIG_ENDIAN__ |
229 | numTriangles = os::Byteswap::byteswap(numTriangles); | 229 | numTriangles = os::Byteswap::byteswap(numTriangles); |
230 | #endif | 230 | #endif |
231 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | 231 | #ifdef _IRR_DEBUG_MS3D_LOADER_ |
232 | os::Printer::log("Load Triangles", core::stringc(numTriangles).c_str()); | 232 | os::Printer::log("Load Triangles", core::stringc(numTriangles).c_str()); |
233 | #endif | 233 | #endif |
234 | pPtr += sizeof(u16); | 234 | pPtr += sizeof(u16); |
235 | MS3DTriangle *triangles = (MS3DTriangle*)pPtr; | 235 | MS3DTriangle *triangles = (MS3DTriangle*)pPtr; |
236 | pPtr += sizeof(MS3DTriangle) * numTriangles; | 236 | pPtr += sizeof(MS3DTriangle) * numTriangles; |
237 | if (pPtr > buffer+fileSize) | 237 | if (pPtr > buffer+fileSize) |
238 | { | 238 | { |
239 | delete [] buffer; | 239 | delete [] buffer; |
240 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | 240 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); |
241 | return false; | 241 | return false; |
242 | } | 242 | } |
243 | for (u16 tmp=0; tmp<numTriangles; ++tmp) | 243 | for (u16 tmp=0; tmp<numTriangles; ++tmp) |
244 | { | 244 | { |
245 | #ifdef __BIG_ENDIAN__ | 245 | #ifdef __BIG_ENDIAN__ |
246 | triangles[tmp].Flags = os::Byteswap::byteswap(triangles[tmp].Flags); | 246 | triangles[tmp].Flags = os::Byteswap::byteswap(triangles[tmp].Flags); |
247 | for (u16 j=0; j<3; ++j) | 247 | for (u16 j=0; j<3; ++j) |
248 | { | 248 | { |
249 | triangles[tmp].VertexIndices[j] = os::Byteswap::byteswap(triangles[tmp].VertexIndices[j]); | 249 | triangles[tmp].VertexIndices[j] = os::Byteswap::byteswap(triangles[tmp].VertexIndices[j]); |
250 | triangles[tmp].VertexNormals[j][0] = os::Byteswap::byteswap(triangles[tmp].VertexNormals[j][0]); | 250 | triangles[tmp].VertexNormals[j][0] = os::Byteswap::byteswap(triangles[tmp].VertexNormals[j][0]); |
251 | triangles[tmp].VertexNormals[j][1] = os::Byteswap::byteswap(triangles[tmp].VertexNormals[j][1]); | 251 | triangles[tmp].VertexNormals[j][1] = os::Byteswap::byteswap(triangles[tmp].VertexNormals[j][1]); |
252 | triangles[tmp].VertexNormals[j][2] = -os::Byteswap::byteswap(triangles[tmp].VertexNormals[j][2]); | 252 | triangles[tmp].VertexNormals[j][2] = -os::Byteswap::byteswap(triangles[tmp].VertexNormals[j][2]); |
253 | triangles[tmp].S[j] = os::Byteswap::byteswap(triangles[tmp].S[j]); | 253 | triangles[tmp].S[j] = os::Byteswap::byteswap(triangles[tmp].S[j]); |
254 | triangles[tmp].T[j] = os::Byteswap::byteswap(triangles[tmp].T[j]); | 254 | triangles[tmp].T[j] = os::Byteswap::byteswap(triangles[tmp].T[j]); |
255 | } | 255 | } |
256 | #else | 256 | #else |
257 | triangles[tmp].VertexNormals[0][2] = -triangles[tmp].VertexNormals[0][2]; | 257 | triangles[tmp].VertexNormals[0][2] = -triangles[tmp].VertexNormals[0][2]; |
258 | triangles[tmp].VertexNormals[1][2] = -triangles[tmp].VertexNormals[1][2]; | 258 | triangles[tmp].VertexNormals[1][2] = -triangles[tmp].VertexNormals[1][2]; |
259 | triangles[tmp].VertexNormals[2][2] = -triangles[tmp].VertexNormals[2][2]; | 259 | triangles[tmp].VertexNormals[2][2] = -triangles[tmp].VertexNormals[2][2]; |
260 | #endif | 260 | #endif |
261 | } | 261 | } |
262 | 262 | ||
263 | // groups | 263 | // groups |
264 | u16 numGroups = *(u16*)pPtr; | 264 | u16 numGroups = *(u16*)pPtr; |
265 | #ifdef __BIG_ENDIAN__ | 265 | #ifdef __BIG_ENDIAN__ |
266 | numGroups = os::Byteswap::byteswap(numGroups); | 266 | numGroups = os::Byteswap::byteswap(numGroups); |
267 | #endif | 267 | #endif |
268 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | 268 | #ifdef _IRR_DEBUG_MS3D_LOADER_ |
269 | os::Printer::log("Load Groups", core::stringc(numGroups).c_str()); | 269 | os::Printer::log("Load Groups", core::stringc(numGroups).c_str()); |
270 | #endif | 270 | #endif |
271 | pPtr += sizeof(u16); | 271 | pPtr += sizeof(u16); |
272 | 272 | ||
273 | core::array<SGroup> groups; | 273 | core::array<SGroup> groups; |
274 | groups.reallocate(numGroups); | 274 | groups.reallocate(numGroups); |
275 | 275 | ||
276 | //store groups | 276 | //store groups |
277 | u32 i; | 277 | u32 i; |
278 | for (i=0; i<numGroups; ++i) | 278 | for (i=0; i<numGroups; ++i) |
279 | { | 279 | { |
280 | groups.push_back(SGroup()); | 280 | groups.push_back(SGroup()); |
281 | SGroup& grp = groups.getLast(); | 281 | SGroup& grp = groups.getLast(); |
282 | 282 | ||
283 | // The byte flag is before the name, so add 1 | 283 | // The byte flag is before the name, so add 1 |
284 | grp.Name = ((const c8*) pPtr) + 1; | 284 | grp.Name = ((const c8*) pPtr) + 1; |
285 | 285 | ||
286 | pPtr += 33; // name and 1 byte flags | 286 | pPtr += 33; // name and 1 byte flags |
287 | u16 triangleCount = *(u16*)pPtr; | 287 | u16 triangleCount = *(u16*)pPtr; |
288 | #ifdef __BIG_ENDIAN__ | 288 | #ifdef __BIG_ENDIAN__ |
289 | triangleCount = os::Byteswap::byteswap(triangleCount); | 289 | triangleCount = os::Byteswap::byteswap(triangleCount); |
290 | #endif | 290 | #endif |
291 | pPtr += sizeof(u16); | 291 | pPtr += sizeof(u16); |
292 | grp.VertexIds.reallocate(triangleCount); | 292 | grp.VertexIds.reallocate(triangleCount); |
293 | 293 | ||
294 | //pPtr += sizeof(u16) * triangleCount; // triangle indices | 294 | //pPtr += sizeof(u16) * triangleCount; // triangle indices |
295 | for (u16 j=0; j<triangleCount; ++j) | 295 | for (u16 j=0; j<triangleCount; ++j) |
296 | { | 296 | { |
297 | #ifdef __BIG_ENDIAN__ | 297 | #ifdef __BIG_ENDIAN__ |
298 | grp.VertexIds.push_back(os::Byteswap::byteswap(*(u16*)pPtr)); | 298 | grp.VertexIds.push_back(os::Byteswap::byteswap(*(u16*)pPtr)); |
299 | #else | 299 | #else |
300 | grp.VertexIds.push_back(*(u16*)pPtr); | 300 | grp.VertexIds.push_back(*(u16*)pPtr); |
301 | #endif | 301 | #endif |
302 | pPtr += sizeof (u16); | 302 | pPtr += sizeof (u16); |
303 | } | 303 | } |
304 | 304 | ||
305 | grp.MaterialIdx = *(u8*)pPtr; | 305 | grp.MaterialIdx = *(u8*)pPtr; |
306 | if (grp.MaterialIdx == 255) | 306 | if (grp.MaterialIdx == 255) |
307 | grp.MaterialIdx = 0; | 307 | grp.MaterialIdx = 0; |
308 | 308 | ||
309 | pPtr += sizeof(c8); // material index | 309 | pPtr += sizeof(c8); // material index |
310 | if (pPtr > buffer+fileSize) | 310 | if (pPtr > buffer+fileSize) |
311 | { | 311 | { |
312 | delete [] buffer; | 312 | delete [] buffer; |
313 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | 313 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); |
314 | return false; | 314 | return false; |
315 | } | 315 | } |
316 | } | 316 | } |
317 | 317 | ||
318 | // load materials | 318 | // load materials |
319 | u16 numMaterials = *(u16*)pPtr; | 319 | u16 numMaterials = *(u16*)pPtr; |
320 | #ifdef __BIG_ENDIAN__ | 320 | #ifdef __BIG_ENDIAN__ |
321 | numMaterials = os::Byteswap::byteswap(numMaterials); | 321 | numMaterials = os::Byteswap::byteswap(numMaterials); |
322 | #endif | 322 | #endif |
323 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | 323 | #ifdef _IRR_DEBUG_MS3D_LOADER_ |
324 | os::Printer::log("Load Materials", core::stringc(numMaterials).c_str()); | 324 | os::Printer::log("Load Materials", core::stringc(numMaterials).c_str()); |
325 | #endif | 325 | #endif |
326 | pPtr += sizeof(u16); | 326 | pPtr += sizeof(u16); |
327 | 327 | ||
328 | if(numMaterials == 0) | 328 | if(numMaterials == 0) |
329 | { | 329 | { |
330 | // if there are no materials, add at least one buffer | 330 | // if there are no materials, add at least one buffer |
331 | AnimatedMesh->addMeshBuffer(); | 331 | AnimatedMesh->addMeshBuffer(); |
332 | } | 332 | } |
333 | 333 | ||
334 | for (i=0; i<numMaterials; ++i) | 334 | for (i=0; i<numMaterials; ++i) |
335 | { | 335 | { |
336 | MS3DMaterial *material = (MS3DMaterial*)pPtr; | 336 | MS3DMaterial *material = (MS3DMaterial*)pPtr; |
337 | #ifdef __BIG_ENDIAN__ | 337 | #ifdef __BIG_ENDIAN__ |
338 | for (u16 j=0; j<4; ++j) | 338 | for (u16 j=0; j<4; ++j) |
339 | material->Ambient[j] = os::Byteswap::byteswap(material->Ambient[j]); | 339 | material->Ambient[j] = os::Byteswap::byteswap(material->Ambient[j]); |
340 | for (u16 j=0; j<4; ++j) | 340 | for (u16 j=0; j<4; ++j) |
341 | material->Diffuse[j] = os::Byteswap::byteswap(material->Diffuse[j]); | 341 | material->Diffuse[j] = os::Byteswap::byteswap(material->Diffuse[j]); |
342 | for (u16 j=0; j<4; ++j) | 342 | for (u16 j=0; j<4; ++j) |
343 | material->Specular[j] = os::Byteswap::byteswap(material->Specular[j]); | 343 | material->Specular[j] = os::Byteswap::byteswap(material->Specular[j]); |
344 | for (u16 j=0; j<4; ++j) | 344 | for (u16 j=0; j<4; ++j) |
345 | material->Emissive[j] = os::Byteswap::byteswap(material->Emissive[j]); | 345 | material->Emissive[j] = os::Byteswap::byteswap(material->Emissive[j]); |
346 | material->Shininess = os::Byteswap::byteswap(material->Shininess); | 346 | material->Shininess = os::Byteswap::byteswap(material->Shininess); |
347 | material->Transparency = os::Byteswap::byteswap(material->Transparency); | 347 | material->Transparency = os::Byteswap::byteswap(material->Transparency); |
348 | #endif | 348 | #endif |
349 | pPtr += sizeof(MS3DMaterial); | 349 | pPtr += sizeof(MS3DMaterial); |
350 | if (pPtr > buffer+fileSize) | 350 | if (pPtr > buffer+fileSize) |
351 | { | 351 | { |
352 | delete [] buffer; | 352 | delete [] buffer; |
353 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | 353 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); |
354 | return false; | 354 | return false; |
355 | } | 355 | } |
356 | 356 | ||
357 | scene::SSkinMeshBuffer *tmpBuffer = AnimatedMesh->addMeshBuffer(); | 357 | scene::SSkinMeshBuffer *tmpBuffer = AnimatedMesh->addMeshBuffer(); |
358 | 358 | ||
359 | tmpBuffer->Material.MaterialType = video::EMT_SOLID; | 359 | tmpBuffer->Material.MaterialType = video::EMT_SOLID; |
360 | 360 | ||
361 | tmpBuffer->Material.AmbientColor = video::SColorf(material->Ambient[0], material->Ambient[1], material->Ambient[2], material->Ambient[3]).toSColor (); | 361 | tmpBuffer->Material.AmbientColor = video::SColorf(material->Ambient[0], material->Ambient[1], material->Ambient[2], material->Ambient[3]).toSColor (); |
362 | tmpBuffer->Material.DiffuseColor = video::SColorf(material->Diffuse[0], material->Diffuse[1], material->Diffuse[2], material->Diffuse[3]).toSColor (); | 362 | tmpBuffer->Material.DiffuseColor = video::SColorf(material->Diffuse[0], material->Diffuse[1], material->Diffuse[2], material->Diffuse[3]).toSColor (); |
363 | tmpBuffer->Material.EmissiveColor = video::SColorf(material->Emissive[0], material->Emissive[1], material->Emissive[2], material->Emissive[3]).toSColor (); | 363 | tmpBuffer->Material.EmissiveColor = video::SColorf(material->Emissive[0], material->Emissive[1], material->Emissive[2], material->Emissive[3]).toSColor (); |
364 | tmpBuffer->Material.SpecularColor = video::SColorf(material->Specular[0], material->Specular[1], material->Specular[2], material->Specular[3]).toSColor (); | 364 | tmpBuffer->Material.SpecularColor = video::SColorf(material->Specular[0], material->Specular[1], material->Specular[2], material->Specular[3]).toSColor (); |
365 | tmpBuffer->Material.Shininess = material->Shininess; | 365 | tmpBuffer->Material.Shininess = material->Shininess; |
366 | 366 | ||
367 | core::stringc TexturePath(material->Texture); | 367 | core::stringc TexturePath(material->Texture); |
368 | if (TexturePath.trim()!="") | 368 | if (TexturePath.trim()!="") |
369 | { | 369 | { |
370 | TexturePath=stripPathFromString(file->getFileName(),true) + stripPathFromString(TexturePath,false); | 370 | TexturePath=stripPathFromString(file->getFileName(),true) + stripPathFromString(TexturePath,false); |
371 | tmpBuffer->Material.setTexture(0, Driver->getTexture(TexturePath)); | 371 | tmpBuffer->Material.setTexture(0, Driver->getTexture(TexturePath)); |
372 | } | 372 | } |
373 | 373 | ||
374 | core::stringc AlphamapPath=(const c8*)material->Alphamap; | 374 | core::stringc AlphamapPath=(const c8*)material->Alphamap; |
375 | if (AlphamapPath.trim()!="") | 375 | if (AlphamapPath.trim()!="") |
376 | { | 376 | { |
377 | AlphamapPath=stripPathFromString(file->getFileName(),true) + stripPathFromString(AlphamapPath,false); | 377 | AlphamapPath=stripPathFromString(file->getFileName(),true) + stripPathFromString(AlphamapPath,false); |
378 | tmpBuffer->Material.setTexture(2, Driver->getTexture(AlphamapPath)); | 378 | tmpBuffer->Material.setTexture(2, Driver->getTexture(AlphamapPath)); |
379 | } | 379 | } |
380 | } | 380 | } |
381 | 381 | ||
382 | // animation time | 382 | // animation time |
383 | f32 framesPerSecond = *(float*)pPtr; | 383 | f32 framesPerSecond = *(float*)pPtr; |
384 | #ifdef __BIG_ENDIAN__ | 384 | #ifdef __BIG_ENDIAN__ |
385 | framesPerSecond = os::Byteswap::byteswap(framesPerSecond); | 385 | framesPerSecond = os::Byteswap::byteswap(framesPerSecond); |
386 | #endif | 386 | #endif |
387 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | 387 | #ifdef _IRR_DEBUG_MS3D_LOADER_ |
388 | os::Printer::log("FPS", core::stringc(framesPerSecond).c_str()); | 388 | os::Printer::log("FPS", core::stringc(framesPerSecond).c_str()); |
389 | #endif | 389 | #endif |
390 | pPtr += sizeof(float) * 2; // fps and current time | 390 | pPtr += sizeof(float) * 2; // fps and current time |
391 | 391 | ||
392 | if (framesPerSecond<1.f) | 392 | if (framesPerSecond<1.f) |
393 | framesPerSecond=1.f; | 393 | framesPerSecond=1.f; |
394 | AnimatedMesh->setAnimationSpeed(framesPerSecond); | 394 | AnimatedMesh->setAnimationSpeed(framesPerSecond); |
395 | 395 | ||
396 | // ignore, calculated inside SkinnedMesh | 396 | // ignore, calculated inside SkinnedMesh |
397 | // s32 frameCount = *(int*)pPtr; | 397 | // s32 frameCount = *(int*)pPtr; |
398 | #ifdef __BIG_ENDIAN__ | 398 | #ifdef __BIG_ENDIAN__ |
399 | // frameCount = os::Byteswap::byteswap(frameCount); | 399 | // frameCount = os::Byteswap::byteswap(frameCount); |
400 | #endif | 400 | #endif |
401 | pPtr += sizeof(int); | 401 | pPtr += sizeof(int); |
402 | 402 | ||
403 | u16 jointCount = *(u16*)pPtr; | 403 | u16 jointCount = *(u16*)pPtr; |
404 | #ifdef __BIG_ENDIAN__ | 404 | #ifdef __BIG_ENDIAN__ |
405 | jointCount = os::Byteswap::byteswap(jointCount); | 405 | jointCount = os::Byteswap::byteswap(jointCount); |
406 | #endif | 406 | #endif |
407 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | 407 | #ifdef _IRR_DEBUG_MS3D_LOADER_ |
408 | os::Printer::log("Joints", core::stringc(jointCount).c_str()); | 408 | os::Printer::log("Joints", core::stringc(jointCount).c_str()); |
409 | #endif | 409 | #endif |
410 | pPtr += sizeof(u16); | 410 | pPtr += sizeof(u16); |
411 | if (pPtr > buffer+fileSize) | 411 | if (pPtr > buffer+fileSize) |
412 | { | 412 | { |
413 | delete [] buffer; | 413 | delete [] buffer; |
414 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | 414 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); |
415 | return false; | 415 | return false; |
416 | } | 416 | } |
417 | 417 | ||
418 | core::array<core::stringc> parentNames; | 418 | core::array<core::stringc> parentNames; |
419 | parentNames.reallocate(jointCount); | 419 | parentNames.reallocate(jointCount); |
420 | 420 | ||
421 | // load joints | 421 | // load joints |
422 | for (i=0; i<jointCount; ++i) | 422 | for (i=0; i<jointCount; ++i) |
423 | { | 423 | { |
424 | u32 j; | 424 | u32 j; |
425 | MS3DJoint *pJoint = (MS3DJoint*)pPtr; | 425 | MS3DJoint *pJoint = (MS3DJoint*)pPtr; |
426 | #ifdef __BIG_ENDIAN__ | 426 | #ifdef __BIG_ENDIAN__ |
427 | for (j=0; j<3; ++j) | 427 | for (j=0; j<3; ++j) |
428 | pJoint->Rotation[j] = os::Byteswap::byteswap(pJoint->Rotation[j]); | 428 | pJoint->Rotation[j] = os::Byteswap::byteswap(pJoint->Rotation[j]); |
429 | for (j=0; j<3; ++j) | 429 | for (j=0; j<3; ++j) |
430 | pJoint->Translation[j] = os::Byteswap::byteswap(pJoint->Translation[j]); | 430 | pJoint->Translation[j] = os::Byteswap::byteswap(pJoint->Translation[j]); |
431 | pJoint->NumRotationKeyframes= os::Byteswap::byteswap(pJoint->NumRotationKeyframes); | 431 | pJoint->NumRotationKeyframes= os::Byteswap::byteswap(pJoint->NumRotationKeyframes); |
432 | pJoint->NumTranslationKeyframes = os::Byteswap::byteswap(pJoint->NumTranslationKeyframes); | 432 | pJoint->NumTranslationKeyframes = os::Byteswap::byteswap(pJoint->NumTranslationKeyframes); |
433 | #endif | 433 | #endif |
434 | pPtr += sizeof(MS3DJoint); | 434 | pPtr += sizeof(MS3DJoint); |
435 | if (pPtr > buffer+fileSize) | 435 | if (pPtr > buffer+fileSize) |
436 | { | 436 | { |
437 | delete [] buffer; | 437 | delete [] buffer; |
438 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | 438 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); |
439 | return false; | 439 | return false; |
440 | } | 440 | } |
441 | 441 | ||
442 | ISkinnedMesh::SJoint *jnt = AnimatedMesh->addJoint(); | 442 | ISkinnedMesh::SJoint *jnt = AnimatedMesh->addJoint(); |
443 | 443 | ||
444 | jnt->Name = pJoint->Name; | 444 | jnt->Name = pJoint->Name; |
445 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | 445 | #ifdef _IRR_DEBUG_MS3D_LOADER_ |
446 | os::Printer::log("Joint", jnt->Name.c_str()); | 446 | os::Printer::log("Joint", jnt->Name.c_str()); |
447 | os::Printer::log("Rotation keyframes", core::stringc(pJoint->NumRotationKeyframes).c_str()); | 447 | os::Printer::log("Rotation keyframes", core::stringc(pJoint->NumRotationKeyframes).c_str()); |
448 | os::Printer::log("Translation keyframes", core::stringc(pJoint->NumTranslationKeyframes).c_str()); | 448 | os::Printer::log("Translation keyframes", core::stringc(pJoint->NumTranslationKeyframes).c_str()); |
449 | #endif | 449 | #endif |
450 | jnt->LocalMatrix.makeIdentity(); | 450 | jnt->LocalMatrix.makeIdentity(); |
451 | jnt->LocalMatrix.setRotationRadians( | 451 | jnt->LocalMatrix.setRotationRadians( |
452 | core::vector3df(pJoint->Rotation[0], pJoint->Rotation[1], pJoint->Rotation[2]) ); | 452 | core::vector3df(pJoint->Rotation[0], pJoint->Rotation[1], pJoint->Rotation[2]) ); |
453 | // convert right-handed to left-handed | 453 | // convert right-handed to left-handed |
454 | jnt->LocalMatrix[2]=-jnt->LocalMatrix[2]; | 454 | jnt->LocalMatrix[2]=-jnt->LocalMatrix[2]; |
455 | jnt->LocalMatrix[6]=-jnt->LocalMatrix[6]; | 455 | jnt->LocalMatrix[6]=-jnt->LocalMatrix[6]; |
456 | jnt->LocalMatrix[8]=-jnt->LocalMatrix[8]; | 456 | jnt->LocalMatrix[8]=-jnt->LocalMatrix[8]; |
457 | jnt->LocalMatrix[9]=-jnt->LocalMatrix[9]; | 457 | jnt->LocalMatrix[9]=-jnt->LocalMatrix[9]; |
458 | 458 | ||
459 | jnt->LocalMatrix.setTranslation( | 459 | jnt->LocalMatrix.setTranslation( |
460 | core::vector3df(pJoint->Translation[0], pJoint->Translation[1], -pJoint->Translation[2]) ); | 460 | core::vector3df(pJoint->Translation[0], pJoint->Translation[1], -pJoint->Translation[2]) ); |
461 | jnt->Animatedposition.set(jnt->LocalMatrix.getTranslation()); | 461 | jnt->Animatedposition.set(jnt->LocalMatrix.getTranslation()); |
462 | jnt->Animatedrotation.set(jnt->LocalMatrix.getRotationDegrees()); | 462 | jnt->Animatedrotation.set(jnt->LocalMatrix.getRotationDegrees()); |
463 | 463 | ||
464 | parentNames.push_back( (c8*)pJoint->ParentName ); | 464 | parentNames.push_back( (c8*)pJoint->ParentName ); |
465 | 465 | ||
466 | /*if (pJoint->NumRotationKeyframes || | 466 | /*if (pJoint->NumRotationKeyframes || |
467 | pJoint->NumTranslationKeyframes) | 467 | pJoint->NumTranslationKeyframes) |
468 | HasAnimation = true; | 468 | HasAnimation = true; |
469 | */ | 469 | */ |
470 | 470 | ||
471 | // get rotation keyframes | 471 | // get rotation keyframes |
472 | const u16 numRotationKeyframes = pJoint->NumRotationKeyframes; | 472 | const u16 numRotationKeyframes = pJoint->NumRotationKeyframes; |
473 | for (j=0; j < numRotationKeyframes; ++j) | 473 | for (j=0; j < numRotationKeyframes; ++j) |
474 | { | 474 | { |
475 | MS3DKeyframe* kf = (MS3DKeyframe*)pPtr; | 475 | MS3DKeyframe* kf = (MS3DKeyframe*)pPtr; |
476 | #ifdef __BIG_ENDIAN__ | 476 | #ifdef __BIG_ENDIAN__ |
477 | kf->Time = os::Byteswap::byteswap(kf->Time); | 477 | kf->Time = os::Byteswap::byteswap(kf->Time); |
478 | for (u32 l=0; l<3; ++l) | 478 | for (u32 l=0; l<3; ++l) |
479 | kf->Parameter[l] = os::Byteswap::byteswap(kf->Parameter[l]); | 479 | kf->Parameter[l] = os::Byteswap::byteswap(kf->Parameter[l]); |
480 | #endif | 480 | #endif |
481 | pPtr += sizeof(MS3DKeyframe); | 481 | pPtr += sizeof(MS3DKeyframe); |
482 | if (pPtr > buffer+fileSize) | 482 | if (pPtr > buffer+fileSize) |
483 | { | 483 | { |
484 | delete [] buffer; | 484 | delete [] buffer; |
485 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | 485 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); |
486 | return false; | 486 | return false; |
487 | } | 487 | } |
488 | 488 | ||
489 | ISkinnedMesh::SRotationKey *k=AnimatedMesh->addRotationKey(jnt); | 489 | ISkinnedMesh::SRotationKey *k=AnimatedMesh->addRotationKey(jnt); |
490 | k->frame = kf->Time * framesPerSecond-1; | 490 | k->frame = kf->Time * framesPerSecond-1; |
491 | 491 | ||
492 | core::matrix4 tmpMatrix; | 492 | core::matrix4 tmpMatrix; |
493 | 493 | ||
494 | tmpMatrix.setRotationRadians( | 494 | tmpMatrix.setRotationRadians( |
495 | core::vector3df(kf->Parameter[0], kf->Parameter[1], kf->Parameter[2]) ); | 495 | core::vector3df(kf->Parameter[0], kf->Parameter[1], kf->Parameter[2]) ); |
496 | // convert right-handed to left-handed | 496 | // convert right-handed to left-handed |
497 | tmpMatrix[2]=-tmpMatrix[2]; | 497 | tmpMatrix[2]=-tmpMatrix[2]; |
498 | tmpMatrix[6]=-tmpMatrix[6]; | 498 | tmpMatrix[6]=-tmpMatrix[6]; |
499 | tmpMatrix[8]=-tmpMatrix[8]; | 499 | tmpMatrix[8]=-tmpMatrix[8]; |
500 | tmpMatrix[9]=-tmpMatrix[9]; | 500 | tmpMatrix[9]=-tmpMatrix[9]; |
501 | 501 | ||
502 | tmpMatrix=jnt->LocalMatrix*tmpMatrix; | 502 | tmpMatrix=jnt->LocalMatrix*tmpMatrix; |
503 | 503 | ||
504 | // IRR_TEST_BROKEN_QUATERNION_USE: TODO - switched from tmpMatrix to tmpMatrix.getTransposed() for downward compatibility. | 504 | // IRR_TEST_BROKEN_QUATERNION_USE: TODO - switched from tmpMatrix to tmpMatrix.getTransposed() for downward compatibility. |
505 | // Not tested so far if this was correct or wrong before quaternion fix! | 505 | // Not tested so far if this was correct or wrong before quaternion fix! |
506 | k->rotation = core::quaternion(tmpMatrix.getTransposed()); | 506 | k->rotation = core::quaternion(tmpMatrix.getTransposed()); |
507 | } | 507 | } |
508 | 508 | ||
509 | // get translation keyframes | 509 | // get translation keyframes |
510 | const u16 numTranslationKeyframes = pJoint->NumTranslationKeyframes; | 510 | const u16 numTranslationKeyframes = pJoint->NumTranslationKeyframes; |
511 | for (j=0; j<numTranslationKeyframes; ++j) | 511 | for (j=0; j<numTranslationKeyframes; ++j) |
512 | { | 512 | { |
513 | MS3DKeyframe* kf = (MS3DKeyframe*)pPtr; | 513 | MS3DKeyframe* kf = (MS3DKeyframe*)pPtr; |
514 | #ifdef __BIG_ENDIAN__ | 514 | #ifdef __BIG_ENDIAN__ |
515 | kf->Time = os::Byteswap::byteswap(kf->Time); | 515 | kf->Time = os::Byteswap::byteswap(kf->Time); |
516 | for (u32 l=0; l<3; ++l) | 516 | for (u32 l=0; l<3; ++l) |
517 | kf->Parameter[l] = os::Byteswap::byteswap(kf->Parameter[l]); | 517 | kf->Parameter[l] = os::Byteswap::byteswap(kf->Parameter[l]); |
518 | #endif | 518 | #endif |
519 | pPtr += sizeof(MS3DKeyframe); | 519 | pPtr += sizeof(MS3DKeyframe); |
520 | if (pPtr > buffer+fileSize) | 520 | if (pPtr > buffer+fileSize) |
521 | { | 521 | { |
522 | delete [] buffer; | 522 | delete [] buffer; |
523 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | 523 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); |
524 | return false; | 524 | return false; |
525 | } | 525 | } |
526 | 526 | ||
527 | ISkinnedMesh::SPositionKey *k=AnimatedMesh->addPositionKey(jnt); | 527 | ISkinnedMesh::SPositionKey *k=AnimatedMesh->addPositionKey(jnt); |
528 | k->frame = kf->Time * framesPerSecond-1; | 528 | k->frame = kf->Time * framesPerSecond-1; |
529 | 529 | ||
530 | k->position = core::vector3df | 530 | k->position = core::vector3df |
531 | (kf->Parameter[0]+pJoint->Translation[0], | 531 | (kf->Parameter[0]+pJoint->Translation[0], |
532 | kf->Parameter[1]+pJoint->Translation[1], | 532 | kf->Parameter[1]+pJoint->Translation[1], |
533 | -kf->Parameter[2]-pJoint->Translation[2]); | 533 | -kf->Parameter[2]-pJoint->Translation[2]); |
534 | } | 534 | } |
535 | } | 535 | } |
536 | 536 | ||
537 | core::array<MS3DVertexWeights> vertexWeights; | 537 | core::array<MS3DVertexWeights> vertexWeights; |
538 | f32 weightFactor=0; | 538 | f32 weightFactor=0; |
539 | 539 | ||
540 | if (jointCount && (pHeader->Version == 4) && (pPtr < buffer+fileSize)) | 540 | if (jointCount && (pHeader->Version == 4) && (pPtr < buffer+fileSize)) |
541 | { | 541 | { |
542 | s32 subVersion = *(s32*)pPtr; // comment subVersion, always 1 | 542 | s32 subVersion = *(s32*)pPtr; // comment subVersion, always 1 |
543 | #ifdef __BIG_ENDIAN__ | 543 | #ifdef __BIG_ENDIAN__ |
544 | subVersion = os::Byteswap::byteswap(subVersion); | 544 | subVersion = os::Byteswap::byteswap(subVersion); |
545 | #endif | 545 | #endif |
546 | pPtr += sizeof(s32); | 546 | pPtr += sizeof(s32); |
547 | 547 | ||
548 | for (u32 j=0; j<4; ++j) // four comment groups | 548 | for (u32 j=0; j<4; ++j) // four comment groups |
549 | { | 549 | { |
550 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | 550 | #ifdef _IRR_DEBUG_MS3D_LOADER_ |
551 | os::Printer::log("Skipping comment group", core::stringc(j+1).c_str()); | 551 | os::Printer::log("Skipping comment group", core::stringc(j+1).c_str()); |
552 | #endif | 552 | #endif |
553 | u32 numComments = *(u32*)pPtr; | 553 | u32 numComments = *(u32*)pPtr; |
554 | #ifdef __BIG_ENDIAN__ | 554 | #ifdef __BIG_ENDIAN__ |
555 | numComments = os::Byteswap::byteswap(numComments); | 555 | numComments = os::Byteswap::byteswap(numComments); |
556 | #endif | 556 | #endif |
557 | pPtr += sizeof(u32); | 557 | pPtr += sizeof(u32); |
558 | for (i=0; i<numComments; ++i) | 558 | for (i=0; i<numComments; ++i) |
559 | { | 559 | { |
560 | // according to scorpiomidget this field does | 560 | // according to scorpiomidget this field does |
561 | // not exist for model comments. So avoid to | 561 | // not exist for model comments. So avoid to |
562 | // read it | 562 | // read it |
563 | if (j!=3) | 563 | if (j!=3) |
564 | pPtr += sizeof(s32); // index | 564 | pPtr += sizeof(s32); // index |
565 | s32 commentLength = *(s32*)pPtr; | 565 | s32 commentLength = *(s32*)pPtr; |
566 | #ifdef __BIG_ENDIAN__ | 566 | #ifdef __BIG_ENDIAN__ |
567 | commentLength = os::Byteswap::byteswap(commentLength); | 567 | commentLength = os::Byteswap::byteswap(commentLength); |
568 | #endif | 568 | #endif |
569 | pPtr += sizeof(s32); | 569 | pPtr += sizeof(s32); |
570 | pPtr += commentLength; | 570 | pPtr += commentLength; |
571 | } | 571 | } |
572 | 572 | ||
573 | if (pPtr > buffer+fileSize) | 573 | if (pPtr > buffer+fileSize) |
574 | { | 574 | { |
575 | delete [] buffer; | 575 | delete [] buffer; |
576 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | 576 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); |
577 | return false; | 577 | return false; |
578 | } | 578 | } |
579 | } | 579 | } |
580 | 580 | ||
581 | if (pPtr < buffer+fileSize) | 581 | if (pPtr < buffer+fileSize) |
582 | { | 582 | { |
583 | subVersion = *(s32*)pPtr; // vertex subVersion, 1 or 2 | 583 | subVersion = *(s32*)pPtr; // vertex subVersion, 1 or 2 |
584 | #ifdef __BIG_ENDIAN__ | 584 | #ifdef __BIG_ENDIAN__ |
585 | subVersion = os::Byteswap::byteswap(subVersion); | 585 | subVersion = os::Byteswap::byteswap(subVersion); |
586 | #endif | 586 | #endif |
587 | if (subVersion==1) | 587 | if (subVersion==1) |
588 | weightFactor=1.f/255.f; | 588 | weightFactor=1.f/255.f; |
589 | else | 589 | else |
590 | weightFactor=1.f/100.f; | 590 | weightFactor=1.f/100.f; |
591 | pPtr += sizeof(s32); | 591 | pPtr += sizeof(s32); |
592 | 592 | ||
593 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | 593 | #ifdef _IRR_DEBUG_MS3D_LOADER_ |
594 | os::Printer::log("Reading vertex weights"); | 594 | os::Printer::log("Reading vertex weights"); |
595 | #endif | 595 | #endif |
596 | // read vertex weights, ignoring data 'extra' from 1.8.2 | 596 | // read vertex weights, ignoring data 'extra' from 1.8.2 |
597 | vertexWeights.reallocate(numVertices); | 597 | vertexWeights.reallocate(numVertices); |
598 | const char offset = (subVersion==1)?6:10; | 598 | const char offset = (subVersion==1)?6:10; |
599 | for (i=0; i<numVertices; ++i) | 599 | for (i=0; i<numVertices; ++i) |
600 | { | 600 | { |
601 | vertexWeights.push_back(*(MS3DVertexWeights*)pPtr); | 601 | vertexWeights.push_back(*(MS3DVertexWeights*)pPtr); |
602 | pPtr += offset; | 602 | pPtr += offset; |
603 | } | 603 | } |
604 | 604 | ||
605 | if (pPtr > buffer+fileSize) | 605 | if (pPtr > buffer+fileSize) |
606 | { | 606 | { |
607 | delete [] buffer; | 607 | delete [] buffer; |
608 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); | 608 | os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); |
609 | return false; | 609 | return false; |
610 | } | 610 | } |
611 | } | 611 | } |
612 | 612 | ||
613 | if (pPtr < buffer+fileSize) | 613 | if (pPtr < buffer+fileSize) |
614 | { | 614 | { |
615 | subVersion = *(s32*)pPtr; // joint subVersion, 1 or 2 | 615 | subVersion = *(s32*)pPtr; // joint subVersion, 1 or 2 |
616 | #ifdef __BIG_ENDIAN__ | 616 | #ifdef __BIG_ENDIAN__ |
617 | subVersion = os::Byteswap::byteswap(subVersion); | 617 | subVersion = os::Byteswap::byteswap(subVersion); |
618 | #endif | 618 | #endif |
619 | pPtr += sizeof(s32); | 619 | pPtr += sizeof(s32); |
620 | // skip joint colors | 620 | // skip joint colors |
621 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | 621 | #ifdef _IRR_DEBUG_MS3D_LOADER_ |
622 | os::Printer::log("Skip joint color"); | 622 | os::Printer::log("Skip joint color"); |
623 | #endif | 623 | #endif |
624 | pPtr += 3*sizeof(float)*jointCount; | 624 | pPtr += 3*sizeof(float)*jointCount; |
625 | 625 | ||
626 | if (pPtr > buffer+fileSize) | 626 | if (pPtr > buffer+fileSize) |
627 | { | 627 | { |
628 | delete [] buffer; | 628 | delete [] buffer; |
629 | os::Printer::log("Loading failed. Corrupted data found", file->getFileName(), ELL_ERROR); | 629 | os::Printer::log("Loading failed. Corrupted data found", file->getFileName(), ELL_ERROR); |
630 | return false; | 630 | return false; |
631 | } | 631 | } |
632 | } | 632 | } |
633 | 633 | ||
634 | if (pPtr < buffer+fileSize) | 634 | if (pPtr < buffer+fileSize) |
635 | { | 635 | { |
636 | subVersion = *(s32*)pPtr; // model subVersion, 1 or 2 | 636 | subVersion = *(s32*)pPtr; // model subVersion, 1 or 2 |
637 | #ifdef __BIG_ENDIAN__ | 637 | #ifdef __BIG_ENDIAN__ |
638 | subVersion = os::Byteswap::byteswap(subVersion); | 638 | subVersion = os::Byteswap::byteswap(subVersion); |
639 | #endif | 639 | #endif |
640 | pPtr += sizeof(s32); | 640 | pPtr += sizeof(s32); |
641 | #ifdef _IRR_DEBUG_MS3D_LOADER_ | 641 | #ifdef _IRR_DEBUG_MS3D_LOADER_ |
642 | os::Printer::log("Skip model extra information"); | 642 | os::Printer::log("Skip model extra information"); |
643 | #endif | 643 | #endif |
644 | // now the model extra information would follow | 644 | // now the model extra information would follow |
645 | // we also skip this for now | 645 | // we also skip this for now |
646 | } | 646 | } |
647 | } | 647 | } |
648 | 648 | ||
649 | //find parent of every joint | 649 | //find parent of every joint |
650 | for (u32 jointnum=0; jointnum<AnimatedMesh->getAllJoints().size(); ++jointnum) | 650 | for (u32 jointnum=0; jointnum<AnimatedMesh->getAllJoints().size(); ++jointnum) |
651 | { | 651 | { |
652 | for (u32 j2=0; j2<AnimatedMesh->getAllJoints().size(); ++j2) | 652 | for (u32 j2=0; j2<AnimatedMesh->getAllJoints().size(); ++j2) |
653 | { | 653 | { |
654 | if (jointnum != j2 && parentNames[jointnum] == AnimatedMesh->getAllJoints()[j2]->Name ) | 654 | if (jointnum != j2 && parentNames[jointnum] == AnimatedMesh->getAllJoints()[j2]->Name ) |
655 | { | 655 | { |
656 | AnimatedMesh->getAllJoints()[j2]->Children.push_back(AnimatedMesh->getAllJoints()[jointnum]); | 656 | AnimatedMesh->getAllJoints()[j2]->Children.push_back(AnimatedMesh->getAllJoints()[jointnum]); |
657 | break; | 657 | break; |
658 | } | 658 | } |
659 | } | 659 | } |
660 | } | 660 | } |
661 | 661 | ||
662 | // create vertices and indices, attach them to the joints. | 662 | // create vertices and indices, attach them to the joints. |
663 | video::S3DVertex v; | 663 | video::S3DVertex v; |
664 | core::array<video::S3DVertex> *Vertices; | 664 | core::array<video::S3DVertex> *Vertices; |
665 | core::array<u16> Indices; | 665 | core::array<u16> Indices; |
666 | 666 | ||
667 | for (i=0; i<numTriangles; ++i) | 667 | for (i=0; i<numTriangles; ++i) |
668 | { | 668 | { |
669 | u32 tmp = groups[triangles[i].GroupIndex].MaterialIdx; | 669 | u32 tmp = groups[triangles[i].GroupIndex].MaterialIdx; |
670 | Vertices = &AnimatedMesh->getMeshBuffers()[tmp]->Vertices_Standard; | 670 | Vertices = &AnimatedMesh->getMeshBuffers()[tmp]->Vertices_Standard; |
671 | 671 | ||
672 | for (s32 j = 2; j!=-1; --j) | 672 | for (s32 j = 2; j!=-1; --j) |
673 | { | 673 | { |
674 | const u32 vertidx = triangles[i].VertexIndices[j]; | 674 | const u32 vertidx = triangles[i].VertexIndices[j]; |
675 | 675 | ||
676 | v.TCoords.X = triangles[i].S[j]; | 676 | v.TCoords.X = triangles[i].S[j]; |
677 | v.TCoords.Y = triangles[i].T[j]; | 677 | v.TCoords.Y = triangles[i].T[j]; |
678 | 678 | ||
679 | v.Normal.X = triangles[i].VertexNormals[j][0]; | 679 | v.Normal.X = triangles[i].VertexNormals[j][0]; |
680 | v.Normal.Y = triangles[i].VertexNormals[j][1]; | 680 | v.Normal.Y = triangles[i].VertexNormals[j][1]; |
681 | v.Normal.Z = triangles[i].VertexNormals[j][2]; | 681 | v.Normal.Z = triangles[i].VertexNormals[j][2]; |
682 | 682 | ||
683 | if(triangles[i].GroupIndex < groups.size() && | 683 | if(triangles[i].GroupIndex < groups.size() && |
684 | groups[triangles[i].GroupIndex].MaterialIdx < AnimatedMesh->getMeshBuffers().size()) | 684 | groups[triangles[i].GroupIndex].MaterialIdx < AnimatedMesh->getMeshBuffers().size()) |
685 | v.Color = AnimatedMesh->getMeshBuffers()[groups[triangles[i].GroupIndex].MaterialIdx]->Material.DiffuseColor; | 685 | v.Color = AnimatedMesh->getMeshBuffers()[groups[triangles[i].GroupIndex].MaterialIdx]->Material.DiffuseColor; |
686 | else | 686 | else |
687 | v.Color.set(255,255,255,255); | 687 | v.Color.set(255,255,255,255); |
688 | 688 | ||
689 | v.Pos.X = vertices[vertidx].Vertex[0]; | 689 | v.Pos.X = vertices[vertidx].Vertex[0]; |
690 | v.Pos.Y = vertices[vertidx].Vertex[1]; | 690 | v.Pos.Y = vertices[vertidx].Vertex[1]; |
691 | v.Pos.Z = vertices[vertidx].Vertex[2]; | 691 | v.Pos.Z = vertices[vertidx].Vertex[2]; |
692 | 692 | ||
693 | // check if we already have this vertex in our vertex array | 693 | // check if we already have this vertex in our vertex array |
694 | s32 index = -1; | 694 | s32 index = -1; |
695 | for (u32 iV = 0; iV < Vertices->size(); ++iV) | 695 | for (u32 iV = 0; iV < Vertices->size(); ++iV) |
696 | { | 696 | { |
697 | if (v == (*Vertices)[iV]) | 697 | if (v == (*Vertices)[iV]) |
698 | { | 698 | { |
699 | index = (s32)iV; | 699 | index = (s32)iV; |
700 | break; | 700 | break; |
701 | } | 701 | } |
702 | } | 702 | } |
703 | 703 | ||
704 | if (index == -1) | 704 | if (index == -1) |
705 | { | 705 | { |
706 | index = Vertices->size(); | 706 | index = Vertices->size(); |
707 | const u32 matidx = groups[triangles[i].GroupIndex].MaterialIdx; | 707 | const u32 matidx = groups[triangles[i].GroupIndex].MaterialIdx; |
708 | if (vertexWeights.size()==0) | 708 | if (vertexWeights.size()==0) |
709 | { | 709 | { |
710 | const s32 boneid = vertices[vertidx].BoneID; | 710 | const s32 boneid = vertices[vertidx].BoneID; |
711 | if ((u32)boneid < AnimatedMesh->getAllJoints().size()) | 711 | if ((u32)boneid < AnimatedMesh->getAllJoints().size()) |
712 | { | 712 | { |
713 | ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); | 713 | ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); |
714 | w->buffer_id = matidx; | 714 | w->buffer_id = matidx; |
715 | w->strength = 1.0f; | 715 | w->strength = 1.0f; |
716 | w->vertex_id = index; | 716 | w->vertex_id = index; |
717 | } | 717 | } |
718 | } | 718 | } |
719 | else if (jointCount) // new weights from 1.8.x | 719 | else if (jointCount) // new weights from 1.8.x |
720 | { | 720 | { |
721 | f32 sum = 1.0f; | 721 | f32 sum = 1.0f; |
722 | s32 boneid = vertices[vertidx].BoneID; | 722 | s32 boneid = vertices[vertidx].BoneID; |
723 | if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[0] != 0)) | 723 | if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[0] != 0)) |
724 | { | 724 | { |
725 | ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); | 725 | ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); |
726 | w->buffer_id = matidx; | 726 | w->buffer_id = matidx; |
727 | sum -= (w->strength = vertexWeights[vertidx].weights[0]*weightFactor); | 727 | sum -= (w->strength = vertexWeights[vertidx].weights[0]*weightFactor); |
728 | w->vertex_id = index; | 728 | w->vertex_id = index; |
729 | } | 729 | } |
730 | boneid = vertexWeights[vertidx].boneIds[0]; | 730 | boneid = vertexWeights[vertidx].boneIds[0]; |
731 | if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[1] != 0)) | 731 | if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[1] != 0)) |
732 | { | 732 | { |
733 | ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); | 733 | ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); |
734 | w->buffer_id = matidx; | 734 | w->buffer_id = matidx; |
735 | sum -= (w->strength = vertexWeights[vertidx].weights[1]*weightFactor); | 735 | sum -= (w->strength = vertexWeights[vertidx].weights[1]*weightFactor); |
736 | w->vertex_id = index; | 736 | w->vertex_id = index; |
737 | } | 737 | } |
738 | boneid = vertexWeights[vertidx].boneIds[1]; | 738 | boneid = vertexWeights[vertidx].boneIds[1]; |
739 | if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[2] != 0)) | 739 | if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[2] != 0)) |
740 | { | 740 | { |
741 | ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); | 741 | ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); |
742 | w->buffer_id = matidx; | 742 | w->buffer_id = matidx; |
743 | sum -= (w->strength = vertexWeights[vertidx].weights[2]*weightFactor); | 743 | sum -= (w->strength = vertexWeights[vertidx].weights[2]*weightFactor); |
744 | w->vertex_id = index; | 744 | w->vertex_id = index; |
745 | } | 745 | } |
746 | boneid = vertexWeights[vertidx].boneIds[2]; | 746 | boneid = vertexWeights[vertidx].boneIds[2]; |
747 | if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (sum > 0.f)) | 747 | if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (sum > 0.f)) |
748 | { | 748 | { |
749 | ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); | 749 | ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); |
750 | w->buffer_id = matidx; | 750 | w->buffer_id = matidx; |
751 | w->strength = sum; | 751 | w->strength = sum; |
752 | w->vertex_id = index; | 752 | w->vertex_id = index; |
753 | } | 753 | } |
754 | // fallback, if no bone chosen. Seems to be an error in the specs | 754 | // fallback, if no bone chosen. Seems to be an error in the specs |
755 | boneid = vertices[vertidx].BoneID; | 755 | boneid = vertices[vertidx].BoneID; |
756 | if ((sum == 1.f) && ((u32)boneid < AnimatedMesh->getAllJoints().size())) | 756 | if ((sum == 1.f) && ((u32)boneid < AnimatedMesh->getAllJoints().size())) |
757 | { | 757 | { |
758 | ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); | 758 | ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); |
759 | w->buffer_id = matidx; | 759 | w->buffer_id = matidx; |
760 | w->strength = 1.f; | 760 | w->strength = 1.f; |
761 | w->vertex_id = index; | 761 | w->vertex_id = index; |
762 | } | 762 | } |
763 | } | 763 | } |
764 | 764 | ||
765 | Vertices->push_back(v); | 765 | Vertices->push_back(v); |
766 | } | 766 | } |
767 | Indices.push_back(index); | 767 | Indices.push_back(index); |
768 | } | 768 | } |
769 | } | 769 | } |
770 | 770 | ||
771 | //create groups | 771 | //create groups |
772 | s32 iIndex = -1; | 772 | s32 iIndex = -1; |
773 | for (i=0; i<groups.size(); ++i) | 773 | for (i=0; i<groups.size(); ++i) |
774 | { | 774 | { |
775 | SGroup& grp = groups[i]; | 775 | SGroup& grp = groups[i]; |
776 | 776 | ||
777 | if (grp.MaterialIdx >= AnimatedMesh->getMeshBuffers().size()) | 777 | if (grp.MaterialIdx >= AnimatedMesh->getMeshBuffers().size()) |
778 | grp.MaterialIdx = 0; | 778 | grp.MaterialIdx = 0; |
779 | 779 | ||
780 | core::array<u16>& indices = AnimatedMesh->getMeshBuffers()[grp.MaterialIdx]->Indices; | 780 | core::array<u16>& indices = AnimatedMesh->getMeshBuffers()[grp.MaterialIdx]->Indices; |
781 | 781 | ||
782 | for (u32 k=0; k < grp.VertexIds.size(); ++k) | 782 | for (u32 k=0; k < grp.VertexIds.size(); ++k) |
783 | for (u32 l=0; l<3; ++l) | 783 | for (u32 l=0; l<3; ++l) |
784 | indices.push_back(Indices[++iIndex]); | 784 | indices.push_back(Indices[++iIndex]); |
785 | } | 785 | } |
786 | 786 | ||
787 | delete [] buffer; | 787 | delete [] buffer; |
788 | 788 | ||
789 | return true; | 789 | return true; |
790 | } | 790 | } |
791 | 791 | ||
792 | 792 | ||
793 | core::stringc CMS3DMeshFileLoader::stripPathFromString(const core::stringc& inString, bool returnPath) const | 793 | core::stringc CMS3DMeshFileLoader::stripPathFromString(const core::stringc& inString, bool returnPath) const |
794 | { | 794 | { |
795 | s32 slashIndex=inString.findLast('/'); // forward slash | 795 | s32 slashIndex=inString.findLast('/'); // forward slash |
796 | s32 backSlash=inString.findLast('\\'); // back slash | 796 | s32 backSlash=inString.findLast('\\'); // back slash |
797 | 797 | ||
798 | if (backSlash>slashIndex) slashIndex=backSlash; | 798 | if (backSlash>slashIndex) slashIndex=backSlash; |
799 | 799 | ||
800 | if (slashIndex==-1)//no slashes found | 800 | if (slashIndex==-1)//no slashes found |
801 | { | 801 | { |
802 | if (returnPath) | 802 | if (returnPath) |
803 | return core::stringc(); //no path to return | 803 | return core::stringc(); //no path to return |
804 | else | 804 | else |
805 | return inString; | 805 | return inString; |
806 | } | 806 | } |
807 | 807 | ||
808 | if (returnPath) | 808 | if (returnPath) |
809 | return inString.subString(0, slashIndex + 1); | 809 | return inString.subString(0, slashIndex + 1); |
810 | else | 810 | else |
811 | return inString.subString(slashIndex+1, inString.size() - (slashIndex+1)); | 811 | return inString.subString(slashIndex+1, inString.size() - (slashIndex+1)); |
812 | } | 812 | } |
813 | 813 | ||
814 | 814 | ||
815 | } // end namespace scene | 815 | } // end namespace scene |
816 | } // end namespace irr | 816 | } // end namespace irr |
817 | 817 | ||
818 | #endif | 818 | #endif |