diff options
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CXMeshFileLoader.cpp')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CXMeshFileLoader.cpp | 4838 |
1 files changed, 2419 insertions, 2419 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CXMeshFileLoader.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CXMeshFileLoader.cpp index 595e911..1c67434 100644 --- a/libraries/irrlicht-1.8/source/Irrlicht/CXMeshFileLoader.cpp +++ b/libraries/irrlicht-1.8/source/Irrlicht/CXMeshFileLoader.cpp | |||
@@ -1,2419 +1,2419 @@ | |||
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 | 6 | ||
7 | #ifdef _IRR_COMPILE_WITH_X_LOADER_ | 7 | #ifdef _IRR_COMPILE_WITH_X_LOADER_ |
8 | 8 | ||
9 | #include "CXMeshFileLoader.h" | 9 | #include "CXMeshFileLoader.h" |
10 | #include "os.h" | 10 | #include "os.h" |
11 | 11 | ||
12 | #include "fast_atof.h" | 12 | #include "fast_atof.h" |
13 | #include "coreutil.h" | 13 | #include "coreutil.h" |
14 | #include "ISceneManager.h" | 14 | #include "ISceneManager.h" |
15 | #include "IVideoDriver.h" | 15 | #include "IVideoDriver.h" |
16 | #include "IFileSystem.h" | 16 | #include "IFileSystem.h" |
17 | #include "IReadFile.h" | 17 | #include "IReadFile.h" |
18 | 18 | ||
19 | #ifdef _DEBUG | 19 | #ifdef _DEBUG |
20 | #define _XREADER_DEBUG | 20 | #define _XREADER_DEBUG |
21 | #endif | 21 | #endif |
22 | //#define BETTER_MESHBUFFER_SPLITTING_FOR_X | 22 | //#define BETTER_MESHBUFFER_SPLITTING_FOR_X |
23 | 23 | ||
24 | namespace irr | 24 | namespace irr |
25 | { | 25 | { |
26 | namespace scene | 26 | namespace scene |
27 | { | 27 | { |
28 | 28 | ||
29 | //! Constructor | 29 | //! Constructor |
30 | CXMeshFileLoader::CXMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs) | 30 | CXMeshFileLoader::CXMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs) |
31 | : SceneManager(smgr), FileSystem(fs), AllJoints(0), AnimatedMesh(0), | 31 | : SceneManager(smgr), FileSystem(fs), AllJoints(0), AnimatedMesh(0), |
32 | Buffer(0), P(0), End(0), BinaryNumCount(0), Line(0), | 32 | Buffer(0), P(0), End(0), BinaryNumCount(0), Line(0), |
33 | CurFrame(0), MajorVersion(0), MinorVersion(0), BinaryFormat(false), FloatSize(0) | 33 | CurFrame(0), MajorVersion(0), MinorVersion(0), BinaryFormat(false), FloatSize(0) |
34 | { | 34 | { |
35 | #ifdef _DEBUG | 35 | #ifdef _DEBUG |
36 | setDebugName("CXMeshFileLoader"); | 36 | setDebugName("CXMeshFileLoader"); |
37 | #endif | 37 | #endif |
38 | } | 38 | } |
39 | 39 | ||
40 | 40 | ||
41 | //! returns true if the file maybe is able to be loaded by this class | 41 | //! returns true if the file maybe is able to be loaded by this class |
42 | //! based on the file extension (e.g. ".bsp") | 42 | //! based on the file extension (e.g. ".bsp") |
43 | bool CXMeshFileLoader::isALoadableFileExtension(const io::path& filename) const | 43 | bool CXMeshFileLoader::isALoadableFileExtension(const io::path& filename) const |
44 | { | 44 | { |
45 | return core::hasFileExtension ( filename, "x" ); | 45 | return core::hasFileExtension ( filename, "x" ); |
46 | } | 46 | } |
47 | 47 | ||
48 | 48 | ||
49 | //! creates/loads an animated mesh from the file. | 49 | //! creates/loads an animated mesh from the file. |
50 | //! \return Pointer to the created mesh. Returns 0 if loading failed. | 50 | //! \return Pointer to the created mesh. Returns 0 if loading failed. |
51 | //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). | 51 | //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). |
52 | //! See IReferenceCounted::drop() for more information. | 52 | //! See IReferenceCounted::drop() for more information. |
53 | IAnimatedMesh* CXMeshFileLoader::createMesh(io::IReadFile* f) | 53 | IAnimatedMesh* CXMeshFileLoader::createMesh(io::IReadFile* f) |
54 | { | 54 | { |
55 | if (!f) | 55 | if (!f) |
56 | return 0; | 56 | return 0; |
57 | 57 | ||
58 | #ifdef _XREADER_DEBUG | 58 | #ifdef _XREADER_DEBUG |
59 | u32 time = os::Timer::getRealTime(); | 59 | u32 time = os::Timer::getRealTime(); |
60 | #endif | 60 | #endif |
61 | 61 | ||
62 | AnimatedMesh = new CSkinnedMesh(); | 62 | AnimatedMesh = new CSkinnedMesh(); |
63 | 63 | ||
64 | if (load(f)) | 64 | if (load(f)) |
65 | { | 65 | { |
66 | AnimatedMesh->finalize(); | 66 | AnimatedMesh->finalize(); |
67 | } | 67 | } |
68 | else | 68 | else |
69 | { | 69 | { |
70 | AnimatedMesh->drop(); | 70 | AnimatedMesh->drop(); |
71 | AnimatedMesh = 0; | 71 | AnimatedMesh = 0; |
72 | } | 72 | } |
73 | #ifdef _XREADER_DEBUG | 73 | #ifdef _XREADER_DEBUG |
74 | time = os::Timer::getRealTime() - time; | 74 | time = os::Timer::getRealTime() - time; |
75 | core::stringc tmpString = "Time to load "; | 75 | core::stringc tmpString = "Time to load "; |
76 | tmpString += BinaryFormat ? "binary" : "ascii"; | 76 | tmpString += BinaryFormat ? "binary" : "ascii"; |
77 | tmpString += " X file: "; | 77 | tmpString += " X file: "; |
78 | tmpString += time; | 78 | tmpString += time; |
79 | tmpString += "ms"; | 79 | tmpString += "ms"; |
80 | os::Printer::log(tmpString.c_str()); | 80 | os::Printer::log(tmpString.c_str()); |
81 | #endif | 81 | #endif |
82 | //Clear up | 82 | //Clear up |
83 | 83 | ||
84 | MajorVersion=0; | 84 | MajorVersion=0; |
85 | MinorVersion=0; | 85 | MinorVersion=0; |
86 | BinaryFormat=0; | 86 | BinaryFormat=0; |
87 | BinaryNumCount=0; | 87 | BinaryNumCount=0; |
88 | FloatSize=0; | 88 | FloatSize=0; |
89 | P=0; | 89 | P=0; |
90 | End=0; | 90 | End=0; |
91 | CurFrame=0; | 91 | CurFrame=0; |
92 | TemplateMaterials.clear(); | 92 | TemplateMaterials.clear(); |
93 | 93 | ||
94 | delete [] Buffer; | 94 | delete [] Buffer; |
95 | Buffer = 0; | 95 | Buffer = 0; |
96 | 96 | ||
97 | for (u32 i=0; i<Meshes.size(); ++i) | 97 | for (u32 i=0; i<Meshes.size(); ++i) |
98 | delete Meshes[i]; | 98 | delete Meshes[i]; |
99 | Meshes.clear(); | 99 | Meshes.clear(); |
100 | 100 | ||
101 | return AnimatedMesh; | 101 | return AnimatedMesh; |
102 | } | 102 | } |
103 | 103 | ||
104 | 104 | ||
105 | bool CXMeshFileLoader::load(io::IReadFile* file) | 105 | bool CXMeshFileLoader::load(io::IReadFile* file) |
106 | { | 106 | { |
107 | if (!readFileIntoMemory(file)) | 107 | if (!readFileIntoMemory(file)) |
108 | return false; | 108 | return false; |
109 | 109 | ||
110 | if (!parseFile()) | 110 | if (!parseFile()) |
111 | return false; | 111 | return false; |
112 | 112 | ||
113 | for (u32 n=0; n<Meshes.size(); ++n) | 113 | for (u32 n=0; n<Meshes.size(); ++n) |
114 | { | 114 | { |
115 | SXMesh *mesh=Meshes[n]; | 115 | SXMesh *mesh=Meshes[n]; |
116 | 116 | ||
117 | // default material if nothing loaded | 117 | // default material if nothing loaded |
118 | if (!mesh->Materials.size()) | 118 | if (!mesh->Materials.size()) |
119 | { | 119 | { |
120 | mesh->Materials.push_back(video::SMaterial()); | 120 | mesh->Materials.push_back(video::SMaterial()); |
121 | mesh->Materials[0].DiffuseColor.set(0xff777777); | 121 | mesh->Materials[0].DiffuseColor.set(0xff777777); |
122 | mesh->Materials[0].Shininess=0.f; | 122 | mesh->Materials[0].Shininess=0.f; |
123 | mesh->Materials[0].SpecularColor.set(0xff777777); | 123 | mesh->Materials[0].SpecularColor.set(0xff777777); |
124 | mesh->Materials[0].EmissiveColor.set(0xff000000); | 124 | mesh->Materials[0].EmissiveColor.set(0xff000000); |
125 | } | 125 | } |
126 | 126 | ||
127 | u32 i; | 127 | u32 i; |
128 | 128 | ||
129 | mesh->Buffers.reallocate(mesh->Materials.size()); | 129 | mesh->Buffers.reallocate(mesh->Materials.size()); |
130 | #ifndef BETTER_MESHBUFFER_SPLITTING_FOR_X | 130 | #ifndef BETTER_MESHBUFFER_SPLITTING_FOR_X |
131 | const u32 bufferOffset = AnimatedMesh->getMeshBufferCount(); | 131 | const u32 bufferOffset = AnimatedMesh->getMeshBufferCount(); |
132 | #endif | 132 | #endif |
133 | for (i=0; i<mesh->Materials.size(); ++i) | 133 | for (i=0; i<mesh->Materials.size(); ++i) |
134 | { | 134 | { |
135 | mesh->Buffers.push_back( AnimatedMesh->addMeshBuffer() ); | 135 | mesh->Buffers.push_back( AnimatedMesh->addMeshBuffer() ); |
136 | mesh->Buffers.getLast()->Material = mesh->Materials[i]; | 136 | mesh->Buffers.getLast()->Material = mesh->Materials[i]; |
137 | 137 | ||
138 | if (!mesh->HasSkinning) | 138 | if (!mesh->HasSkinning) |
139 | { | 139 | { |
140 | //Set up rigid animation | 140 | //Set up rigid animation |
141 | if (mesh->AttachedJointID!=-1) | 141 | if (mesh->AttachedJointID!=-1) |
142 | { | 142 | { |
143 | AnimatedMesh->getAllJoints()[mesh->AttachedJointID]->AttachedMeshes.push_back( AnimatedMesh->getMeshBuffers().size()-1 ); | 143 | AnimatedMesh->getAllJoints()[mesh->AttachedJointID]->AttachedMeshes.push_back( AnimatedMesh->getMeshBuffers().size()-1 ); |
144 | } | 144 | } |
145 | } | 145 | } |
146 | } | 146 | } |
147 | 147 | ||
148 | if (!mesh->FaceMaterialIndices.size()) | 148 | if (!mesh->FaceMaterialIndices.size()) |
149 | { | 149 | { |
150 | mesh->FaceMaterialIndices.set_used(mesh->Indices.size() / 3); | 150 | mesh->FaceMaterialIndices.set_used(mesh->Indices.size() / 3); |
151 | for (i=0; i<mesh->FaceMaterialIndices.size(); ++i) | 151 | for (i=0; i<mesh->FaceMaterialIndices.size(); ++i) |
152 | mesh->FaceMaterialIndices[i]=0; | 152 | mesh->FaceMaterialIndices[i]=0; |
153 | } | 153 | } |
154 | 154 | ||
155 | if (!mesh->HasVertexColors) | 155 | if (!mesh->HasVertexColors) |
156 | { | 156 | { |
157 | for (u32 j=0;j<mesh->FaceMaterialIndices.size();++j) | 157 | for (u32 j=0;j<mesh->FaceMaterialIndices.size();++j) |
158 | { | 158 | { |
159 | for (u32 id=j*3+0;id<=j*3+2;++id) | 159 | for (u32 id=j*3+0;id<=j*3+2;++id) |
160 | { | 160 | { |
161 | mesh->Vertices[ mesh->Indices[id] ].Color = mesh->Buffers[mesh->FaceMaterialIndices[j]]->Material.DiffuseColor; | 161 | mesh->Vertices[ mesh->Indices[id] ].Color = mesh->Buffers[mesh->FaceMaterialIndices[j]]->Material.DiffuseColor; |
162 | } | 162 | } |
163 | } | 163 | } |
164 | } | 164 | } |
165 | 165 | ||
166 | #ifdef BETTER_MESHBUFFER_SPLITTING_FOR_X | 166 | #ifdef BETTER_MESHBUFFER_SPLITTING_FOR_X |
167 | { | 167 | { |
168 | //the same vertex can be used in many different meshbuffers, but it's slow to work out | 168 | //the same vertex can be used in many different meshbuffers, but it's slow to work out |
169 | 169 | ||
170 | core::array< core::array< u32 > > verticesLinkIndex; | 170 | core::array< core::array< u32 > > verticesLinkIndex; |
171 | verticesLinkIndex.reallocate(mesh->Vertices.size()); | 171 | verticesLinkIndex.reallocate(mesh->Vertices.size()); |
172 | core::array< core::array< u16 > > verticesLinkBuffer; | 172 | core::array< core::array< u16 > > verticesLinkBuffer; |
173 | verticesLinkBuffer.reallocate(mesh->Vertices.size()); | 173 | verticesLinkBuffer.reallocate(mesh->Vertices.size()); |
174 | 174 | ||
175 | for (i=0;i<mesh->Vertices.size();++i) | 175 | for (i=0;i<mesh->Vertices.size();++i) |
176 | { | 176 | { |
177 | verticesLinkIndex.push_back( core::array< u32 >() ); | 177 | verticesLinkIndex.push_back( core::array< u32 >() ); |
178 | verticesLinkBuffer.push_back( core::array< u16 >() ); | 178 | verticesLinkBuffer.push_back( core::array< u16 >() ); |
179 | } | 179 | } |
180 | 180 | ||
181 | for (i=0;i<mesh->FaceMaterialIndices.size();++i) | 181 | for (i=0;i<mesh->FaceMaterialIndices.size();++i) |
182 | { | 182 | { |
183 | for (u32 id=i*3+0;id<=i*3+2;++id) | 183 | for (u32 id=i*3+0;id<=i*3+2;++id) |
184 | { | 184 | { |
185 | core::array< u16 > &Array=verticesLinkBuffer[ mesh->Indices[id] ]; | 185 | core::array< u16 > &Array=verticesLinkBuffer[ mesh->Indices[id] ]; |
186 | bool found=false; | 186 | bool found=false; |
187 | 187 | ||
188 | for (u32 j=0; j < Array.size(); ++j) | 188 | for (u32 j=0; j < Array.size(); ++j) |
189 | { | 189 | { |
190 | if (Array[j]==mesh->FaceMaterialIndices[i]) | 190 | if (Array[j]==mesh->FaceMaterialIndices[i]) |
191 | { | 191 | { |
192 | found=true; | 192 | found=true; |
193 | break; | 193 | break; |
194 | } | 194 | } |
195 | } | 195 | } |
196 | 196 | ||
197 | if (!found) | 197 | if (!found) |
198 | Array.push_back( mesh->FaceMaterialIndices[i] ); | 198 | Array.push_back( mesh->FaceMaterialIndices[i] ); |
199 | } | 199 | } |
200 | } | 200 | } |
201 | 201 | ||
202 | for (i=0;i<verticesLinkBuffer.size();++i) | 202 | for (i=0;i<verticesLinkBuffer.size();++i) |
203 | { | 203 | { |
204 | if (!verticesLinkBuffer[i].size()) | 204 | if (!verticesLinkBuffer[i].size()) |
205 | verticesLinkBuffer[i].push_back(0); | 205 | verticesLinkBuffer[i].push_back(0); |
206 | } | 206 | } |
207 | 207 | ||
208 | for (i=0;i<mesh->Vertices.size();++i) | 208 | for (i=0;i<mesh->Vertices.size();++i) |
209 | { | 209 | { |
210 | core::array< u16 > &Array = verticesLinkBuffer[i]; | 210 | core::array< u16 > &Array = verticesLinkBuffer[i]; |
211 | verticesLinkIndex[i].reallocate(Array.size()); | 211 | verticesLinkIndex[i].reallocate(Array.size()); |
212 | for (u32 j=0; j < Array.size(); ++j) | 212 | for (u32 j=0; j < Array.size(); ++j) |
213 | { | 213 | { |
214 | scene::SSkinMeshBuffer *buffer = mesh->Buffers[ Array[j] ]; | 214 | scene::SSkinMeshBuffer *buffer = mesh->Buffers[ Array[j] ]; |
215 | verticesLinkIndex[i].push_back( buffer->Vertices_Standard.size() ); | 215 | verticesLinkIndex[i].push_back( buffer->Vertices_Standard.size() ); |
216 | buffer->Vertices_Standard.push_back( mesh->Vertices[i] ); | 216 | buffer->Vertices_Standard.push_back( mesh->Vertices[i] ); |
217 | } | 217 | } |
218 | } | 218 | } |
219 | 219 | ||
220 | for (i=0;i<mesh->FaceMaterialIndices.size();++i) | 220 | for (i=0;i<mesh->FaceMaterialIndices.size();++i) |
221 | { | 221 | { |
222 | scene::SSkinMeshBuffer *buffer=mesh->Buffers[ mesh->FaceMaterialIndices[i] ]; | 222 | scene::SSkinMeshBuffer *buffer=mesh->Buffers[ mesh->FaceMaterialIndices[i] ]; |
223 | 223 | ||
224 | for (u32 id=i*3+0;id<=i*3+2;++id) | 224 | for (u32 id=i*3+0;id<=i*3+2;++id) |
225 | { | 225 | { |
226 | core::array< u16 > &Array=verticesLinkBuffer[ mesh->Indices[id] ]; | 226 | core::array< u16 > &Array=verticesLinkBuffer[ mesh->Indices[id] ]; |
227 | 227 | ||
228 | for (u32 j=0;j< Array.size() ;++j) | 228 | for (u32 j=0;j< Array.size() ;++j) |
229 | { | 229 | { |
230 | if ( Array[j]== mesh->FaceMaterialIndices[i] ) | 230 | if ( Array[j]== mesh->FaceMaterialIndices[i] ) |
231 | buffer->Indices.push_back( verticesLinkIndex[ mesh->Indices[id] ][j] ); | 231 | buffer->Indices.push_back( verticesLinkIndex[ mesh->Indices[id] ][j] ); |
232 | } | 232 | } |
233 | } | 233 | } |
234 | } | 234 | } |
235 | 235 | ||
236 | for (u32 j=0;j<mesh->WeightJoint.size();++j) | 236 | for (u32 j=0;j<mesh->WeightJoint.size();++j) |
237 | { | 237 | { |
238 | ISkinnedMesh::SJoint* joint = AnimatedMesh->getAllJoints()[mesh->WeightJoint[j]]; | 238 | ISkinnedMesh::SJoint* joint = AnimatedMesh->getAllJoints()[mesh->WeightJoint[j]]; |
239 | ISkinnedMesh::SWeight& weight = joint->Weights[mesh->WeightNum[j]]; | 239 | ISkinnedMesh::SWeight& weight = joint->Weights[mesh->WeightNum[j]]; |
240 | 240 | ||
241 | u32 id = weight.vertex_id; | 241 | u32 id = weight.vertex_id; |
242 | 242 | ||
243 | if (id>=verticesLinkIndex.size()) | 243 | if (id>=verticesLinkIndex.size()) |
244 | { | 244 | { |
245 | os::Printer::log("X loader: Weight id out of range", ELL_WARNING); | 245 | os::Printer::log("X loader: Weight id out of range", ELL_WARNING); |
246 | id=0; | 246 | id=0; |
247 | weight.strength=0.f; | 247 | weight.strength=0.f; |
248 | } | 248 | } |
249 | 249 | ||
250 | if (verticesLinkBuffer[id].size()==1) | 250 | if (verticesLinkBuffer[id].size()==1) |
251 | { | 251 | { |
252 | weight.vertex_id=verticesLinkIndex[id][0]; | 252 | weight.vertex_id=verticesLinkIndex[id][0]; |
253 | weight.buffer_id=verticesLinkBuffer[id][0]; | 253 | weight.buffer_id=verticesLinkBuffer[id][0]; |
254 | } | 254 | } |
255 | else if (verticesLinkBuffer[id].size() != 0) | 255 | else if (verticesLinkBuffer[id].size() != 0) |
256 | { | 256 | { |
257 | for (u32 k=1; k < verticesLinkBuffer[id].size(); ++k) | 257 | for (u32 k=1; k < verticesLinkBuffer[id].size(); ++k) |
258 | { | 258 | { |
259 | ISkinnedMesh::SWeight* WeightClone = AnimatedMesh->addWeight(joint); | 259 | ISkinnedMesh::SWeight* WeightClone = AnimatedMesh->addWeight(joint); |
260 | WeightClone->strength = weight.strength; | 260 | WeightClone->strength = weight.strength; |
261 | WeightClone->vertex_id = verticesLinkIndex[id][k]; | 261 | WeightClone->vertex_id = verticesLinkIndex[id][k]; |
262 | WeightClone->buffer_id = verticesLinkBuffer[id][k]; | 262 | WeightClone->buffer_id = verticesLinkBuffer[id][k]; |
263 | } | 263 | } |
264 | } | 264 | } |
265 | } | 265 | } |
266 | } | 266 | } |
267 | #else | 267 | #else |
268 | { | 268 | { |
269 | core::array< u32 > verticesLinkIndex; | 269 | core::array< u32 > verticesLinkIndex; |
270 | core::array< s16 > verticesLinkBuffer; | 270 | core::array< s16 > verticesLinkBuffer; |
271 | verticesLinkBuffer.set_used(mesh->Vertices.size()); | 271 | verticesLinkBuffer.set_used(mesh->Vertices.size()); |
272 | 272 | ||
273 | // init with 0 | 273 | // init with 0 |
274 | for (i=0;i<mesh->Vertices.size();++i) | 274 | for (i=0;i<mesh->Vertices.size();++i) |
275 | { | 275 | { |
276 | // watch out for vertices which are not part of the mesh | 276 | // watch out for vertices which are not part of the mesh |
277 | // they will keep the -1 and can lead to out-of-bounds access | 277 | // they will keep the -1 and can lead to out-of-bounds access |
278 | verticesLinkBuffer[i]=-1; | 278 | verticesLinkBuffer[i]=-1; |
279 | } | 279 | } |
280 | 280 | ||
281 | bool warned = false; | 281 | bool warned = false; |
282 | // store meshbuffer number per vertex | 282 | // store meshbuffer number per vertex |
283 | for (i=0;i<mesh->FaceMaterialIndices.size();++i) | 283 | for (i=0;i<mesh->FaceMaterialIndices.size();++i) |
284 | { | 284 | { |
285 | for (u32 id=i*3+0;id<=i*3+2;++id) | 285 | for (u32 id=i*3+0;id<=i*3+2;++id) |
286 | { | 286 | { |
287 | if ((verticesLinkBuffer[mesh->Indices[id]] != -1) && (verticesLinkBuffer[mesh->Indices[id]] != (s16)mesh->FaceMaterialIndices[i])) | 287 | if ((verticesLinkBuffer[mesh->Indices[id]] != -1) && (verticesLinkBuffer[mesh->Indices[id]] != (s16)mesh->FaceMaterialIndices[i])) |
288 | { | 288 | { |
289 | if (!warned) | 289 | if (!warned) |
290 | { | 290 | { |
291 | os::Printer::log("X loader", "Duplicated vertex, animation might be corrupted.", ELL_WARNING); | 291 | os::Printer::log("X loader", "Duplicated vertex, animation might be corrupted.", ELL_WARNING); |
292 | warned=true; | 292 | warned=true; |
293 | } | 293 | } |
294 | const u32 tmp = mesh->Vertices.size(); | 294 | const u32 tmp = mesh->Vertices.size(); |
295 | mesh->Vertices.push_back(mesh->Vertices[ mesh->Indices[id] ]); | 295 | mesh->Vertices.push_back(mesh->Vertices[ mesh->Indices[id] ]); |
296 | mesh->Indices[id] = tmp; | 296 | mesh->Indices[id] = tmp; |
297 | verticesLinkBuffer.set_used(mesh->Vertices.size()); | 297 | verticesLinkBuffer.set_used(mesh->Vertices.size()); |
298 | } | 298 | } |
299 | verticesLinkBuffer[ mesh->Indices[id] ] = mesh->FaceMaterialIndices[i]; | 299 | verticesLinkBuffer[ mesh->Indices[id] ] = mesh->FaceMaterialIndices[i]; |
300 | } | 300 | } |
301 | } | 301 | } |
302 | 302 | ||
303 | if (mesh->FaceMaterialIndices.size() != 0) | 303 | if (mesh->FaceMaterialIndices.size() != 0) |
304 | { | 304 | { |
305 | // store vertices in buffers and remember relation in verticesLinkIndex | 305 | // store vertices in buffers and remember relation in verticesLinkIndex |
306 | u32* vCountArray = new u32[mesh->Buffers.size()]; | 306 | u32* vCountArray = new u32[mesh->Buffers.size()]; |
307 | memset(vCountArray, 0, mesh->Buffers.size()*sizeof(u32)); | 307 | memset(vCountArray, 0, mesh->Buffers.size()*sizeof(u32)); |
308 | // count vertices in each buffer and reallocate | 308 | // count vertices in each buffer and reallocate |
309 | for (i=0; i<mesh->Vertices.size(); ++i) | 309 | for (i=0; i<mesh->Vertices.size(); ++i) |
310 | { | 310 | { |
311 | if (verticesLinkBuffer[i] != -1) | 311 | if (verticesLinkBuffer[i] != -1) |
312 | ++vCountArray[verticesLinkBuffer[i]]; | 312 | ++vCountArray[verticesLinkBuffer[i]]; |
313 | } | 313 | } |
314 | if (mesh->TCoords2.size()) | 314 | if (mesh->TCoords2.size()) |
315 | { | 315 | { |
316 | for (i=0; i!=mesh->Buffers.size(); ++i) | 316 | for (i=0; i!=mesh->Buffers.size(); ++i) |
317 | { | 317 | { |
318 | mesh->Buffers[i]->Vertices_2TCoords.reallocate(vCountArray[i]); | 318 | mesh->Buffers[i]->Vertices_2TCoords.reallocate(vCountArray[i]); |
319 | mesh->Buffers[i]->VertexType=video::EVT_2TCOORDS; | 319 | mesh->Buffers[i]->VertexType=video::EVT_2TCOORDS; |
320 | } | 320 | } |
321 | } | 321 | } |
322 | else | 322 | else |
323 | { | 323 | { |
324 | for (i=0; i!=mesh->Buffers.size(); ++i) | 324 | for (i=0; i!=mesh->Buffers.size(); ++i) |
325 | mesh->Buffers[i]->Vertices_Standard.reallocate(vCountArray[i]); | 325 | mesh->Buffers[i]->Vertices_Standard.reallocate(vCountArray[i]); |
326 | } | 326 | } |
327 | 327 | ||
328 | verticesLinkIndex.set_used(mesh->Vertices.size()); | 328 | verticesLinkIndex.set_used(mesh->Vertices.size()); |
329 | // actually store vertices | 329 | // actually store vertices |
330 | for (i=0; i<mesh->Vertices.size(); ++i) | 330 | for (i=0; i<mesh->Vertices.size(); ++i) |
331 | { | 331 | { |
332 | // if a vertex is missing for some reason, just skip it | 332 | // if a vertex is missing for some reason, just skip it |
333 | if (verticesLinkBuffer[i]==-1) | 333 | if (verticesLinkBuffer[i]==-1) |
334 | continue; | 334 | continue; |
335 | scene::SSkinMeshBuffer *buffer = mesh->Buffers[ verticesLinkBuffer[i] ]; | 335 | scene::SSkinMeshBuffer *buffer = mesh->Buffers[ verticesLinkBuffer[i] ]; |
336 | 336 | ||
337 | if (mesh->TCoords2.size()) | 337 | if (mesh->TCoords2.size()) |
338 | { | 338 | { |
339 | verticesLinkIndex[i] = buffer->Vertices_2TCoords.size(); | 339 | verticesLinkIndex[i] = buffer->Vertices_2TCoords.size(); |
340 | buffer->Vertices_2TCoords.push_back( mesh->Vertices[i] ); | 340 | buffer->Vertices_2TCoords.push_back( mesh->Vertices[i] ); |
341 | // We have a problem with correct tcoord2 handling here | 341 | // We have a problem with correct tcoord2 handling here |
342 | // crash fixed for now by checking the values | 342 | // crash fixed for now by checking the values |
343 | buffer->Vertices_2TCoords.getLast().TCoords2=(i<mesh->TCoords2.size())?mesh->TCoords2[i]:mesh->Vertices[i].TCoords; | 343 | buffer->Vertices_2TCoords.getLast().TCoords2=(i<mesh->TCoords2.size())?mesh->TCoords2[i]:mesh->Vertices[i].TCoords; |
344 | } | 344 | } |
345 | else | 345 | else |
346 | { | 346 | { |
347 | verticesLinkIndex[i] = buffer->Vertices_Standard.size(); | 347 | verticesLinkIndex[i] = buffer->Vertices_Standard.size(); |
348 | buffer->Vertices_Standard.push_back( mesh->Vertices[i] ); | 348 | buffer->Vertices_Standard.push_back( mesh->Vertices[i] ); |
349 | } | 349 | } |
350 | } | 350 | } |
351 | 351 | ||
352 | // count indices per buffer and reallocate | 352 | // count indices per buffer and reallocate |
353 | memset(vCountArray, 0, mesh->Buffers.size()*sizeof(u32)); | 353 | memset(vCountArray, 0, mesh->Buffers.size()*sizeof(u32)); |
354 | for (i=0; i<mesh->FaceMaterialIndices.size(); ++i) | 354 | for (i=0; i<mesh->FaceMaterialIndices.size(); ++i) |
355 | ++vCountArray[ mesh->FaceMaterialIndices[i] ]; | 355 | ++vCountArray[ mesh->FaceMaterialIndices[i] ]; |
356 | for (i=0; i!=mesh->Buffers.size(); ++i) | 356 | for (i=0; i!=mesh->Buffers.size(); ++i) |
357 | mesh->Buffers[i]->Indices.reallocate(vCountArray[i]); | 357 | mesh->Buffers[i]->Indices.reallocate(vCountArray[i]); |
358 | delete [] vCountArray; | 358 | delete [] vCountArray; |
359 | // create indices per buffer | 359 | // create indices per buffer |
360 | for (i=0; i<mesh->FaceMaterialIndices.size(); ++i) | 360 | for (i=0; i<mesh->FaceMaterialIndices.size(); ++i) |
361 | { | 361 | { |
362 | scene::SSkinMeshBuffer *buffer = mesh->Buffers[ mesh->FaceMaterialIndices[i] ]; | 362 | scene::SSkinMeshBuffer *buffer = mesh->Buffers[ mesh->FaceMaterialIndices[i] ]; |
363 | for (u32 id=i*3+0; id!=i*3+3; ++id) | 363 | for (u32 id=i*3+0; id!=i*3+3; ++id) |
364 | { | 364 | { |
365 | buffer->Indices.push_back( verticesLinkIndex[ mesh->Indices[id] ] ); | 365 | buffer->Indices.push_back( verticesLinkIndex[ mesh->Indices[id] ] ); |
366 | } | 366 | } |
367 | } | 367 | } |
368 | } | 368 | } |
369 | 369 | ||
370 | for (u32 j=0; j<mesh->WeightJoint.size(); ++j) | 370 | for (u32 j=0; j<mesh->WeightJoint.size(); ++j) |
371 | { | 371 | { |
372 | ISkinnedMesh::SWeight& weight = (AnimatedMesh->getAllJoints()[mesh->WeightJoint[j]]->Weights[mesh->WeightNum[j]]); | 372 | ISkinnedMesh::SWeight& weight = (AnimatedMesh->getAllJoints()[mesh->WeightJoint[j]]->Weights[mesh->WeightNum[j]]); |
373 | 373 | ||
374 | u32 id = weight.vertex_id; | 374 | u32 id = weight.vertex_id; |
375 | 375 | ||
376 | if (id>=verticesLinkIndex.size()) | 376 | if (id>=verticesLinkIndex.size()) |
377 | { | 377 | { |
378 | os::Printer::log("X loader: Weight id out of range", ELL_WARNING); | 378 | os::Printer::log("X loader: Weight id out of range", ELL_WARNING); |
379 | id=0; | 379 | id=0; |
380 | weight.strength=0.f; | 380 | weight.strength=0.f; |
381 | } | 381 | } |
382 | 382 | ||
383 | weight.vertex_id=verticesLinkIndex[id]; | 383 | weight.vertex_id=verticesLinkIndex[id]; |
384 | weight.buffer_id=verticesLinkBuffer[id] + bufferOffset; | 384 | weight.buffer_id=verticesLinkBuffer[id] + bufferOffset; |
385 | } | 385 | } |
386 | } | 386 | } |
387 | #endif | 387 | #endif |
388 | 388 | ||
389 | } | 389 | } |
390 | 390 | ||
391 | return true; | 391 | return true; |
392 | } | 392 | } |
393 | 393 | ||
394 | 394 | ||
395 | //! Reads file into memory | 395 | //! Reads file into memory |
396 | bool CXMeshFileLoader::readFileIntoMemory(io::IReadFile* file) | 396 | bool CXMeshFileLoader::readFileIntoMemory(io::IReadFile* file) |
397 | { | 397 | { |
398 | const long size = file->getSize(); | 398 | const long size = file->getSize(); |
399 | if (size < 12) | 399 | if (size < 12) |
400 | { | 400 | { |
401 | os::Printer::log("X File is too small.", ELL_WARNING); | 401 | os::Printer::log("X File is too small.", ELL_WARNING); |
402 | return false; | 402 | return false; |
403 | } | 403 | } |
404 | 404 | ||
405 | Buffer = new c8[size]; | 405 | Buffer = new c8[size]; |
406 | 406 | ||
407 | //! read all into memory | 407 | //! read all into memory |
408 | if (file->read(Buffer, size) != size) | 408 | if (file->read(Buffer, size) != size) |
409 | { | 409 | { |
410 | os::Printer::log("Could not read from x file.", ELL_WARNING); | 410 | os::Printer::log("Could not read from x file.", ELL_WARNING); |
411 | return false; | 411 | return false; |
412 | } | 412 | } |
413 | 413 | ||
414 | Line = 1; | 414 | Line = 1; |
415 | End = Buffer + size; | 415 | End = Buffer + size; |
416 | 416 | ||
417 | //! check header "xof " | 417 | //! check header "xof " |
418 | if (strncmp(Buffer, "xof ", 4)!=0) | 418 | if (strncmp(Buffer, "xof ", 4)!=0) |
419 | { | 419 | { |
420 | os::Printer::log("Not an x file, wrong header.", ELL_WARNING); | 420 | os::Printer::log("Not an x file, wrong header.", ELL_WARNING); |
421 | return false; | 421 | return false; |
422 | } | 422 | } |
423 | 423 | ||
424 | //! read minor and major version, e.g. 0302 or 0303 | 424 | //! read minor and major version, e.g. 0302 or 0303 |
425 | c8 tmp[3]; | 425 | c8 tmp[3]; |
426 | tmp[0] = Buffer[4]; | 426 | tmp[0] = Buffer[4]; |
427 | tmp[1] = Buffer[5]; | 427 | tmp[1] = Buffer[5]; |
428 | tmp[2] = 0x0; | 428 | tmp[2] = 0x0; |
429 | MajorVersion = core::strtoul10(tmp); | 429 | MajorVersion = core::strtoul10(tmp); |
430 | 430 | ||
431 | tmp[0] = Buffer[6]; | 431 | tmp[0] = Buffer[6]; |
432 | tmp[1] = Buffer[7]; | 432 | tmp[1] = Buffer[7]; |
433 | MinorVersion = core::strtoul10(tmp); | 433 | MinorVersion = core::strtoul10(tmp); |
434 | 434 | ||
435 | //! read format | 435 | //! read format |
436 | if (strncmp(&Buffer[8], "txt ", 4) ==0) | 436 | if (strncmp(&Buffer[8], "txt ", 4) ==0) |
437 | BinaryFormat = false; | 437 | BinaryFormat = false; |
438 | else if (strncmp(&Buffer[8], "bin ", 4) ==0) | 438 | else if (strncmp(&Buffer[8], "bin ", 4) ==0) |
439 | BinaryFormat = true; | 439 | BinaryFormat = true; |
440 | else | 440 | else |
441 | { | 441 | { |
442 | os::Printer::log("Only uncompressed x files currently supported.", ELL_WARNING); | 442 | os::Printer::log("Only uncompressed x files currently supported.", ELL_WARNING); |
443 | return false; | 443 | return false; |
444 | } | 444 | } |
445 | BinaryNumCount=0; | 445 | BinaryNumCount=0; |
446 | 446 | ||
447 | //! read float size | 447 | //! read float size |
448 | if (strncmp(&Buffer[12], "0032", 4) ==0) | 448 | if (strncmp(&Buffer[12], "0032", 4) ==0) |
449 | FloatSize = 4; | 449 | FloatSize = 4; |
450 | else if (strncmp(&Buffer[12], "0064", 4) ==0) | 450 | else if (strncmp(&Buffer[12], "0064", 4) ==0) |
451 | FloatSize = 8; | 451 | FloatSize = 8; |
452 | else | 452 | else |
453 | { | 453 | { |
454 | os::Printer::log("Float size not supported.", ELL_WARNING); | 454 | os::Printer::log("Float size not supported.", ELL_WARNING); |
455 | return false; | 455 | return false; |
456 | } | 456 | } |
457 | 457 | ||
458 | P = &Buffer[16]; | 458 | P = &Buffer[16]; |
459 | 459 | ||
460 | readUntilEndOfLine(); | 460 | readUntilEndOfLine(); |
461 | FilePath = FileSystem->getFileDir(file->getFileName()) + "/"; | 461 | FilePath = FileSystem->getFileDir(file->getFileName()) + "/"; |
462 | 462 | ||
463 | return true; | 463 | return true; |
464 | } | 464 | } |
465 | 465 | ||
466 | 466 | ||
467 | //! Parses the file | 467 | //! Parses the file |
468 | bool CXMeshFileLoader::parseFile() | 468 | bool CXMeshFileLoader::parseFile() |
469 | { | 469 | { |
470 | while(parseDataObject()) | 470 | while(parseDataObject()) |
471 | { | 471 | { |
472 | // loop | 472 | // loop |
473 | } | 473 | } |
474 | 474 | ||
475 | return true; | 475 | return true; |
476 | } | 476 | } |
477 | 477 | ||
478 | 478 | ||
479 | //! Parses the next Data object in the file | 479 | //! Parses the next Data object in the file |
480 | bool CXMeshFileLoader::parseDataObject() | 480 | bool CXMeshFileLoader::parseDataObject() |
481 | { | 481 | { |
482 | core::stringc objectName = getNextToken(); | 482 | core::stringc objectName = getNextToken(); |
483 | 483 | ||
484 | if (objectName.size() == 0) | 484 | if (objectName.size() == 0) |
485 | return false; | 485 | return false; |
486 | 486 | ||
487 | // parse specific object | 487 | // parse specific object |
488 | #ifdef _XREADER_DEBUG | 488 | #ifdef _XREADER_DEBUG |
489 | os::Printer::log("debug DataObject:", objectName.c_str(), ELL_DEBUG); | 489 | os::Printer::log("debug DataObject:", objectName.c_str(), ELL_DEBUG); |
490 | #endif | 490 | #endif |
491 | 491 | ||
492 | if (objectName == "template") | 492 | if (objectName == "template") |
493 | return parseDataObjectTemplate(); | 493 | return parseDataObjectTemplate(); |
494 | else | 494 | else |
495 | if (objectName == "Frame") | 495 | if (objectName == "Frame") |
496 | { | 496 | { |
497 | return parseDataObjectFrame( 0 ); | 497 | return parseDataObjectFrame( 0 ); |
498 | } | 498 | } |
499 | else | 499 | else |
500 | if (objectName == "Mesh") | 500 | if (objectName == "Mesh") |
501 | { | 501 | { |
502 | // some meshes have no frames at all | 502 | // some meshes have no frames at all |
503 | //CurFrame = AnimatedMesh->addJoint(0); | 503 | //CurFrame = AnimatedMesh->addJoint(0); |
504 | 504 | ||
505 | SXMesh *mesh=new SXMesh; | 505 | SXMesh *mesh=new SXMesh; |
506 | 506 | ||
507 | //mesh->Buffer=AnimatedMesh->addMeshBuffer(); | 507 | //mesh->Buffer=AnimatedMesh->addMeshBuffer(); |
508 | Meshes.push_back(mesh); | 508 | Meshes.push_back(mesh); |
509 | 509 | ||
510 | return parseDataObjectMesh(*mesh); | 510 | return parseDataObjectMesh(*mesh); |
511 | } | 511 | } |
512 | else | 512 | else |
513 | if (objectName == "AnimationSet") | 513 | if (objectName == "AnimationSet") |
514 | { | 514 | { |
515 | return parseDataObjectAnimationSet(); | 515 | return parseDataObjectAnimationSet(); |
516 | } | 516 | } |
517 | else | 517 | else |
518 | if (objectName == "Material") | 518 | if (objectName == "Material") |
519 | { | 519 | { |
520 | // template materials now available thanks to joeWright | 520 | // template materials now available thanks to joeWright |
521 | TemplateMaterials.push_back(SXTemplateMaterial()); | 521 | TemplateMaterials.push_back(SXTemplateMaterial()); |
522 | TemplateMaterials.getLast().Name = getNextToken(); | 522 | TemplateMaterials.getLast().Name = getNextToken(); |
523 | return parseDataObjectMaterial(TemplateMaterials.getLast().Material); | 523 | return parseDataObjectMaterial(TemplateMaterials.getLast().Material); |
524 | } | 524 | } |
525 | else | 525 | else |
526 | if (objectName == "}") | 526 | if (objectName == "}") |
527 | { | 527 | { |
528 | os::Printer::log("} found in dataObject", ELL_WARNING); | 528 | os::Printer::log("} found in dataObject", ELL_WARNING); |
529 | return true; | 529 | return true; |
530 | } | 530 | } |
531 | 531 | ||
532 | os::Printer::log("Unknown data object in animation of .x file", objectName.c_str(), ELL_WARNING); | 532 | os::Printer::log("Unknown data object in animation of .x file", objectName.c_str(), ELL_WARNING); |
533 | 533 | ||
534 | return parseUnknownDataObject(); | 534 | return parseUnknownDataObject(); |
535 | } | 535 | } |
536 | 536 | ||
537 | 537 | ||
538 | bool CXMeshFileLoader::parseDataObjectTemplate() | 538 | bool CXMeshFileLoader::parseDataObjectTemplate() |
539 | { | 539 | { |
540 | #ifdef _XREADER_DEBUG | 540 | #ifdef _XREADER_DEBUG |
541 | os::Printer::log("CXFileReader: Reading template", ELL_DEBUG); | 541 | os::Printer::log("CXFileReader: Reading template", ELL_DEBUG); |
542 | #endif | 542 | #endif |
543 | 543 | ||
544 | // parse a template data object. Currently not stored. | 544 | // parse a template data object. Currently not stored. |
545 | core::stringc name; | 545 | core::stringc name; |
546 | 546 | ||
547 | if (!readHeadOfDataObject(&name)) | 547 | if (!readHeadOfDataObject(&name)) |
548 | { | 548 | { |
549 | os::Printer::log("Left delimiter in template data object missing.", | 549 | os::Printer::log("Left delimiter in template data object missing.", |
550 | name.c_str(), ELL_WARNING); | 550 | name.c_str(), ELL_WARNING); |
551 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 551 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
552 | return false; | 552 | return false; |
553 | } | 553 | } |
554 | 554 | ||
555 | // read GUID | 555 | // read GUID |
556 | getNextToken(); | 556 | getNextToken(); |
557 | 557 | ||
558 | // read and ignore data members | 558 | // read and ignore data members |
559 | while(true) | 559 | while(true) |
560 | { | 560 | { |
561 | core::stringc s = getNextToken(); | 561 | core::stringc s = getNextToken(); |
562 | 562 | ||
563 | if (s == "}") | 563 | if (s == "}") |
564 | break; | 564 | break; |
565 | 565 | ||
566 | if (s.size() == 0) | 566 | if (s.size() == 0) |
567 | return false; | 567 | return false; |
568 | } | 568 | } |
569 | 569 | ||
570 | return true; | 570 | return true; |
571 | } | 571 | } |
572 | 572 | ||
573 | 573 | ||
574 | bool CXMeshFileLoader::parseDataObjectFrame(CSkinnedMesh::SJoint *Parent) | 574 | bool CXMeshFileLoader::parseDataObjectFrame(CSkinnedMesh::SJoint *Parent) |
575 | { | 575 | { |
576 | #ifdef _XREADER_DEBUG | 576 | #ifdef _XREADER_DEBUG |
577 | os::Printer::log("CXFileReader: Reading frame", ELL_DEBUG); | 577 | os::Printer::log("CXFileReader: Reading frame", ELL_DEBUG); |
578 | #endif | 578 | #endif |
579 | 579 | ||
580 | // A coordinate frame, or "frame of reference." The Frame template | 580 | // A coordinate frame, or "frame of reference." The Frame template |
581 | // is open and can contain any object. The Direct3D extensions (D3DX) | 581 | // is open and can contain any object. The Direct3D extensions (D3DX) |
582 | // mesh-loading functions recognize Mesh, FrameTransformMatrix, and | 582 | // mesh-loading functions recognize Mesh, FrameTransformMatrix, and |
583 | // Frame template instances as child objects when loading a Frame | 583 | // Frame template instances as child objects when loading a Frame |
584 | // instance. | 584 | // instance. |
585 | 585 | ||
586 | u32 JointID=0; | 586 | u32 JointID=0; |
587 | 587 | ||
588 | core::stringc name; | 588 | core::stringc name; |
589 | 589 | ||
590 | if (!readHeadOfDataObject(&name)) | 590 | if (!readHeadOfDataObject(&name)) |
591 | { | 591 | { |
592 | os::Printer::log("No opening brace in Frame found in x file", ELL_WARNING); | 592 | os::Printer::log("No opening brace in Frame found in x file", ELL_WARNING); |
593 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 593 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
594 | return false; | 594 | return false; |
595 | } | 595 | } |
596 | 596 | ||
597 | CSkinnedMesh::SJoint *joint=0; | 597 | CSkinnedMesh::SJoint *joint=0; |
598 | 598 | ||
599 | if (name.size()) | 599 | if (name.size()) |
600 | { | 600 | { |
601 | for (u32 n=0; n < AnimatedMesh->getAllJoints().size(); ++n) | 601 | for (u32 n=0; n < AnimatedMesh->getAllJoints().size(); ++n) |
602 | { | 602 | { |
603 | if (AnimatedMesh->getAllJoints()[n]->Name==name) | 603 | if (AnimatedMesh->getAllJoints()[n]->Name==name) |
604 | { | 604 | { |
605 | joint=AnimatedMesh->getAllJoints()[n]; | 605 | joint=AnimatedMesh->getAllJoints()[n]; |
606 | JointID=n; | 606 | JointID=n; |
607 | break; | 607 | break; |
608 | } | 608 | } |
609 | } | 609 | } |
610 | } | 610 | } |
611 | 611 | ||
612 | if (!joint) | 612 | if (!joint) |
613 | { | 613 | { |
614 | #ifdef _XREADER_DEBUG | 614 | #ifdef _XREADER_DEBUG |
615 | os::Printer::log("creating joint ", name.c_str(), ELL_DEBUG); | 615 | os::Printer::log("creating joint ", name.c_str(), ELL_DEBUG); |
616 | #endif | 616 | #endif |
617 | joint=AnimatedMesh->addJoint(Parent); | 617 | joint=AnimatedMesh->addJoint(Parent); |
618 | joint->Name=name; | 618 | joint->Name=name; |
619 | JointID=AnimatedMesh->getAllJoints().size()-1; | 619 | JointID=AnimatedMesh->getAllJoints().size()-1; |
620 | } | 620 | } |
621 | else | 621 | else |
622 | { | 622 | { |
623 | #ifdef _XREADER_DEBUG | 623 | #ifdef _XREADER_DEBUG |
624 | os::Printer::log("using joint ", name.c_str(), ELL_DEBUG); | 624 | os::Printer::log("using joint ", name.c_str(), ELL_DEBUG); |
625 | #endif | 625 | #endif |
626 | if (Parent) | 626 | if (Parent) |
627 | Parent->Children.push_back(joint); | 627 | Parent->Children.push_back(joint); |
628 | } | 628 | } |
629 | 629 | ||
630 | // Now inside a frame. | 630 | // Now inside a frame. |
631 | // read tokens until closing brace is reached. | 631 | // read tokens until closing brace is reached. |
632 | 632 | ||
633 | while(true) | 633 | while(true) |
634 | { | 634 | { |
635 | core::stringc objectName = getNextToken(); | 635 | core::stringc objectName = getNextToken(); |
636 | 636 | ||
637 | #ifdef _XREADER_DEBUG | 637 | #ifdef _XREADER_DEBUG |
638 | os::Printer::log("debug DataObject in frame:", objectName.c_str(), ELL_DEBUG); | 638 | os::Printer::log("debug DataObject in frame:", objectName.c_str(), ELL_DEBUG); |
639 | #endif | 639 | #endif |
640 | 640 | ||
641 | if (objectName.size() == 0) | 641 | if (objectName.size() == 0) |
642 | { | 642 | { |
643 | os::Printer::log("Unexpected ending found in Frame in x file.", ELL_WARNING); | 643 | os::Printer::log("Unexpected ending found in Frame in x file.", ELL_WARNING); |
644 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 644 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
645 | return false; | 645 | return false; |
646 | } | 646 | } |
647 | else | 647 | else |
648 | if (objectName == "}") | 648 | if (objectName == "}") |
649 | { | 649 | { |
650 | break; // frame finished | 650 | break; // frame finished |
651 | } | 651 | } |
652 | else | 652 | else |
653 | if (objectName == "Frame") | 653 | if (objectName == "Frame") |
654 | { | 654 | { |
655 | 655 | ||
656 | if (!parseDataObjectFrame(joint)) | 656 | if (!parseDataObjectFrame(joint)) |
657 | return false; | 657 | return false; |
658 | } | 658 | } |
659 | else | 659 | else |
660 | if (objectName == "FrameTransformMatrix") | 660 | if (objectName == "FrameTransformMatrix") |
661 | { | 661 | { |
662 | if (!parseDataObjectTransformationMatrix(joint->LocalMatrix)) | 662 | if (!parseDataObjectTransformationMatrix(joint->LocalMatrix)) |
663 | return false; | 663 | return false; |
664 | 664 | ||
665 | //joint->LocalAnimatedMatrix | 665 | //joint->LocalAnimatedMatrix |
666 | //joint->LocalAnimatedMatrix.makeInverse(); | 666 | //joint->LocalAnimatedMatrix.makeInverse(); |
667 | //joint->LocalMatrix=tmp*joint->LocalAnimatedMatrix; | 667 | //joint->LocalMatrix=tmp*joint->LocalAnimatedMatrix; |
668 | } | 668 | } |
669 | else | 669 | else |
670 | if (objectName == "Mesh") | 670 | if (objectName == "Mesh") |
671 | { | 671 | { |
672 | /* | 672 | /* |
673 | frame.Meshes.push_back(SXMesh()); | 673 | frame.Meshes.push_back(SXMesh()); |
674 | if (!parseDataObjectMesh(frame.Meshes.getLast())) | 674 | if (!parseDataObjectMesh(frame.Meshes.getLast())) |
675 | return false; | 675 | return false; |
676 | */ | 676 | */ |
677 | SXMesh *mesh=new SXMesh; | 677 | SXMesh *mesh=new SXMesh; |
678 | 678 | ||
679 | mesh->AttachedJointID=JointID; | 679 | mesh->AttachedJointID=JointID; |
680 | 680 | ||
681 | Meshes.push_back(mesh); | 681 | Meshes.push_back(mesh); |
682 | 682 | ||
683 | if (!parseDataObjectMesh(*mesh)) | 683 | if (!parseDataObjectMesh(*mesh)) |
684 | return false; | 684 | return false; |
685 | } | 685 | } |
686 | else | 686 | else |
687 | { | 687 | { |
688 | os::Printer::log("Unknown data object in frame in x file", objectName.c_str(), ELL_WARNING); | 688 | os::Printer::log("Unknown data object in frame in x file", objectName.c_str(), ELL_WARNING); |
689 | if (!parseUnknownDataObject()) | 689 | if (!parseUnknownDataObject()) |
690 | return false; | 690 | return false; |
691 | } | 691 | } |
692 | } | 692 | } |
693 | 693 | ||
694 | return true; | 694 | return true; |
695 | } | 695 | } |
696 | 696 | ||
697 | 697 | ||
698 | bool CXMeshFileLoader::parseDataObjectTransformationMatrix(core::matrix4 &mat) | 698 | bool CXMeshFileLoader::parseDataObjectTransformationMatrix(core::matrix4 &mat) |
699 | { | 699 | { |
700 | #ifdef _XREADER_DEBUG | 700 | #ifdef _XREADER_DEBUG |
701 | os::Printer::log("CXFileReader: Reading Transformation Matrix", ELL_DEBUG); | 701 | os::Printer::log("CXFileReader: Reading Transformation Matrix", ELL_DEBUG); |
702 | #endif | 702 | #endif |
703 | 703 | ||
704 | if (!readHeadOfDataObject()) | 704 | if (!readHeadOfDataObject()) |
705 | { | 705 | { |
706 | os::Printer::log("No opening brace in Transformation Matrix found in x file", ELL_WARNING); | 706 | os::Printer::log("No opening brace in Transformation Matrix found in x file", ELL_WARNING); |
707 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 707 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
708 | return false; | 708 | return false; |
709 | } | 709 | } |
710 | 710 | ||
711 | readMatrix(mat); | 711 | readMatrix(mat); |
712 | 712 | ||
713 | if (!checkForOneFollowingSemicolons()) | 713 | if (!checkForOneFollowingSemicolons()) |
714 | { | 714 | { |
715 | os::Printer::log("No finishing semicolon in Transformation Matrix found in x file", ELL_WARNING); | 715 | os::Printer::log("No finishing semicolon in Transformation Matrix found in x file", ELL_WARNING); |
716 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 716 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
717 | } | 717 | } |
718 | 718 | ||
719 | if (!checkForClosingBrace()) | 719 | if (!checkForClosingBrace()) |
720 | { | 720 | { |
721 | os::Printer::log("No closing brace in Transformation Matrix found in x file", ELL_WARNING); | 721 | os::Printer::log("No closing brace in Transformation Matrix found in x file", ELL_WARNING); |
722 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 722 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
723 | return false; | 723 | return false; |
724 | } | 724 | } |
725 | 725 | ||
726 | return true; | 726 | return true; |
727 | } | 727 | } |
728 | 728 | ||
729 | 729 | ||
730 | bool CXMeshFileLoader::parseDataObjectMesh(SXMesh &mesh) | 730 | bool CXMeshFileLoader::parseDataObjectMesh(SXMesh &mesh) |
731 | { | 731 | { |
732 | core::stringc name; | 732 | core::stringc name; |
733 | 733 | ||
734 | if (!readHeadOfDataObject(&name)) | 734 | if (!readHeadOfDataObject(&name)) |
735 | { | 735 | { |
736 | #ifdef _XREADER_DEBUG | 736 | #ifdef _XREADER_DEBUG |
737 | os::Printer::log("CXFileReader: Reading mesh", ELL_DEBUG); | 737 | os::Printer::log("CXFileReader: Reading mesh", ELL_DEBUG); |
738 | #endif | 738 | #endif |
739 | os::Printer::log("No opening brace in Mesh found in x file", ELL_WARNING); | 739 | os::Printer::log("No opening brace in Mesh found in x file", ELL_WARNING); |
740 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 740 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
741 | return false; | 741 | return false; |
742 | } | 742 | } |
743 | 743 | ||
744 | #ifdef _XREADER_DEBUG | 744 | #ifdef _XREADER_DEBUG |
745 | os::Printer::log("CXFileReader: Reading mesh", name.c_str(), ELL_DEBUG); | 745 | os::Printer::log("CXFileReader: Reading mesh", name.c_str(), ELL_DEBUG); |
746 | #endif | 746 | #endif |
747 | 747 | ||
748 | // read vertex count | 748 | // read vertex count |
749 | const u32 nVertices = readInt(); | 749 | const u32 nVertices = readInt(); |
750 | 750 | ||
751 | // read vertices | 751 | // read vertices |
752 | mesh.Vertices.set_used(nVertices); | 752 | mesh.Vertices.set_used(nVertices); |
753 | for (u32 n=0; n<nVertices; ++n) | 753 | for (u32 n=0; n<nVertices; ++n) |
754 | { | 754 | { |
755 | readVector3(mesh.Vertices[n].Pos); | 755 | readVector3(mesh.Vertices[n].Pos); |
756 | mesh.Vertices[n].Color=0xFFFFFFFF; | 756 | mesh.Vertices[n].Color=0xFFFFFFFF; |
757 | } | 757 | } |
758 | 758 | ||
759 | if (!checkForTwoFollowingSemicolons()) | 759 | if (!checkForTwoFollowingSemicolons()) |
760 | { | 760 | { |
761 | os::Printer::log("No finishing semicolon in Mesh Vertex Array found in x file", ELL_WARNING); | 761 | os::Printer::log("No finishing semicolon in Mesh Vertex Array found in x file", ELL_WARNING); |
762 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 762 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
763 | } | 763 | } |
764 | 764 | ||
765 | // read faces | 765 | // read faces |
766 | const u32 nFaces = readInt(); | 766 | const u32 nFaces = readInt(); |
767 | 767 | ||
768 | mesh.Indices.set_used(nFaces * 3); | 768 | mesh.Indices.set_used(nFaces * 3); |
769 | mesh.IndexCountPerFace.set_used(nFaces); | 769 | mesh.IndexCountPerFace.set_used(nFaces); |
770 | 770 | ||
771 | core::array<u32> polygonfaces; | 771 | core::array<u32> polygonfaces; |
772 | u32 currentIndex = 0; | 772 | u32 currentIndex = 0; |
773 | 773 | ||
774 | for (u32 k=0; k<nFaces; ++k) | 774 | for (u32 k=0; k<nFaces; ++k) |
775 | { | 775 | { |
776 | const u32 fcnt = readInt(); | 776 | const u32 fcnt = readInt(); |
777 | 777 | ||
778 | if (fcnt != 3) | 778 | if (fcnt != 3) |
779 | { | 779 | { |
780 | if (fcnt < 3) | 780 | if (fcnt < 3) |
781 | { | 781 | { |
782 | os::Printer::log("Invalid face count (<3) found in Mesh x file reader.", ELL_WARNING); | 782 | os::Printer::log("Invalid face count (<3) found in Mesh x file reader.", ELL_WARNING); |
783 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 783 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
784 | return false; | 784 | return false; |
785 | } | 785 | } |
786 | 786 | ||
787 | // read face indices | 787 | // read face indices |
788 | polygonfaces.set_used(fcnt); | 788 | polygonfaces.set_used(fcnt); |
789 | u32 triangles = (fcnt-2); | 789 | u32 triangles = (fcnt-2); |
790 | mesh.Indices.set_used(mesh.Indices.size() + ((triangles-1)*3)); | 790 | mesh.Indices.set_used(mesh.Indices.size() + ((triangles-1)*3)); |
791 | mesh.IndexCountPerFace[k] = (u16)(triangles * 3); | 791 | mesh.IndexCountPerFace[k] = (u16)(triangles * 3); |
792 | 792 | ||
793 | for (u32 f=0; f<fcnt; ++f) | 793 | for (u32 f=0; f<fcnt; ++f) |
794 | polygonfaces[f] = readInt(); | 794 | polygonfaces[f] = readInt(); |
795 | 795 | ||
796 | for (u32 jk=0; jk<triangles; ++jk) | 796 | for (u32 jk=0; jk<triangles; ++jk) |
797 | { | 797 | { |
798 | mesh.Indices[currentIndex++] = polygonfaces[0]; | 798 | mesh.Indices[currentIndex++] = polygonfaces[0]; |
799 | mesh.Indices[currentIndex++] = polygonfaces[jk+1]; | 799 | mesh.Indices[currentIndex++] = polygonfaces[jk+1]; |
800 | mesh.Indices[currentIndex++] = polygonfaces[jk+2]; | 800 | mesh.Indices[currentIndex++] = polygonfaces[jk+2]; |
801 | } | 801 | } |
802 | 802 | ||
803 | // TODO: change face indices in material list | 803 | // TODO: change face indices in material list |
804 | } | 804 | } |
805 | else | 805 | else |
806 | { | 806 | { |
807 | mesh.Indices[currentIndex++] = readInt(); | 807 | mesh.Indices[currentIndex++] = readInt(); |
808 | mesh.Indices[currentIndex++] = readInt(); | 808 | mesh.Indices[currentIndex++] = readInt(); |
809 | mesh.Indices[currentIndex++] = readInt(); | 809 | mesh.Indices[currentIndex++] = readInt(); |
810 | mesh.IndexCountPerFace[k] = 3; | 810 | mesh.IndexCountPerFace[k] = 3; |
811 | } | 811 | } |
812 | } | 812 | } |
813 | 813 | ||
814 | if (!checkForTwoFollowingSemicolons()) | 814 | if (!checkForTwoFollowingSemicolons()) |
815 | { | 815 | { |
816 | os::Printer::log("No finishing semicolon in Mesh Face Array found in x file", ELL_WARNING); | 816 | os::Printer::log("No finishing semicolon in Mesh Face Array found in x file", ELL_WARNING); |
817 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 817 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
818 | } | 818 | } |
819 | 819 | ||
820 | // here, other data objects may follow | 820 | // here, other data objects may follow |
821 | 821 | ||
822 | while(true) | 822 | while(true) |
823 | { | 823 | { |
824 | core::stringc objectName = getNextToken(); | 824 | core::stringc objectName = getNextToken(); |
825 | 825 | ||
826 | if (objectName.size() == 0) | 826 | if (objectName.size() == 0) |
827 | { | 827 | { |
828 | os::Printer::log("Unexpected ending found in Mesh in x file.", ELL_WARNING); | 828 | os::Printer::log("Unexpected ending found in Mesh in x file.", ELL_WARNING); |
829 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 829 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
830 | return false; | 830 | return false; |
831 | } | 831 | } |
832 | else | 832 | else |
833 | if (objectName == "}") | 833 | if (objectName == "}") |
834 | { | 834 | { |
835 | break; // mesh finished | 835 | break; // mesh finished |
836 | } | 836 | } |
837 | 837 | ||
838 | #ifdef _XREADER_DEBUG | 838 | #ifdef _XREADER_DEBUG |
839 | os::Printer::log("debug DataObject in mesh:", objectName.c_str(), ELL_DEBUG); | 839 | os::Printer::log("debug DataObject in mesh:", objectName.c_str(), ELL_DEBUG); |
840 | #endif | 840 | #endif |
841 | 841 | ||
842 | if (objectName == "MeshNormals") | 842 | if (objectName == "MeshNormals") |
843 | { | 843 | { |
844 | if (!parseDataObjectMeshNormals(mesh)) | 844 | if (!parseDataObjectMeshNormals(mesh)) |
845 | return false; | 845 | return false; |
846 | } | 846 | } |
847 | else | 847 | else |
848 | if (objectName == "MeshTextureCoords") | 848 | if (objectName == "MeshTextureCoords") |
849 | { | 849 | { |
850 | if (!parseDataObjectMeshTextureCoords(mesh)) | 850 | if (!parseDataObjectMeshTextureCoords(mesh)) |
851 | return false; | 851 | return false; |
852 | } | 852 | } |
853 | else | 853 | else |
854 | if (objectName == "MeshVertexColors") | 854 | if (objectName == "MeshVertexColors") |
855 | { | 855 | { |
856 | if (!parseDataObjectMeshVertexColors(mesh)) | 856 | if (!parseDataObjectMeshVertexColors(mesh)) |
857 | return false; | 857 | return false; |
858 | } | 858 | } |
859 | else | 859 | else |
860 | if (objectName == "MeshMaterialList") | 860 | if (objectName == "MeshMaterialList") |
861 | { | 861 | { |
862 | if (!parseDataObjectMeshMaterialList(mesh)) | 862 | if (!parseDataObjectMeshMaterialList(mesh)) |
863 | return false; | 863 | return false; |
864 | } | 864 | } |
865 | else | 865 | else |
866 | if (objectName == "VertexDuplicationIndices") | 866 | if (objectName == "VertexDuplicationIndices") |
867 | { | 867 | { |
868 | // we'll ignore vertex duplication indices | 868 | // we'll ignore vertex duplication indices |
869 | // TODO: read them | 869 | // TODO: read them |
870 | if (!parseUnknownDataObject()) | 870 | if (!parseUnknownDataObject()) |
871 | return false; | 871 | return false; |
872 | } | 872 | } |
873 | else | 873 | else |
874 | if (objectName == "DeclData") | 874 | if (objectName == "DeclData") |
875 | { | 875 | { |
876 | // arbitrary vertex attributes | 876 | // arbitrary vertex attributes |
877 | // first comes the number of element definitions | 877 | // first comes the number of element definitions |
878 | // then the vertex element type definitions | 878 | // then the vertex element type definitions |
879 | // with format type;tesselator;semantics;usageindex | 879 | // with format type;tesselator;semantics;usageindex |
880 | // we want to support 2;0;6;0 == tangent | 880 | // we want to support 2;0;6;0 == tangent |
881 | // 2;0;7;0 == binormal | 881 | // 2;0;7;0 == binormal |
882 | // 2;0;3;0 == normal | 882 | // 2;0;3;0 == normal |
883 | // 1/2;0;5;0 == 1st uv coord | 883 | // 1/2;0;5;0 == 1st uv coord |
884 | // and 1/2;0;5;1 == 2nd uv coord | 884 | // and 1/2;0;5;1 == 2nd uv coord |
885 | // type==2 is 3xf32, type==1 is 2xf32 | 885 | // type==2 is 3xf32, type==1 is 2xf32 |
886 | u32 j; | 886 | u32 j; |
887 | const u32 dcnt = readInt(); | 887 | const u32 dcnt = readInt(); |
888 | u16 size = 0; | 888 | u16 size = 0; |
889 | s16 normalpos = -1; | 889 | s16 normalpos = -1; |
890 | s16 uvpos = -1; | 890 | s16 uvpos = -1; |
891 | s16 uv2pos = -1; | 891 | s16 uv2pos = -1; |
892 | s16 tangentpos = -1; | 892 | s16 tangentpos = -1; |
893 | s16 binormalpos = -1; | 893 | s16 binormalpos = -1; |
894 | s16 normaltype = -1; | 894 | s16 normaltype = -1; |
895 | s16 uvtype = -1; | 895 | s16 uvtype = -1; |
896 | s16 uv2type = -1; | 896 | s16 uv2type = -1; |
897 | s16 tangenttype = -1; | 897 | s16 tangenttype = -1; |
898 | s16 binormaltype = -1; | 898 | s16 binormaltype = -1; |
899 | for (j=0; j<dcnt; ++j) | 899 | for (j=0; j<dcnt; ++j) |
900 | { | 900 | { |
901 | const u32 type = readInt(); | 901 | const u32 type = readInt(); |
902 | //const u32 tesselator = readInt(); | 902 | //const u32 tesselator = readInt(); |
903 | readInt(); | 903 | readInt(); |
904 | const u32 semantics = readInt(); | 904 | const u32 semantics = readInt(); |
905 | const u32 index = readInt(); | 905 | const u32 index = readInt(); |
906 | switch (semantics) | 906 | switch (semantics) |
907 | { | 907 | { |
908 | case 3: | 908 | case 3: |
909 | normalpos = size; | 909 | normalpos = size; |
910 | normaltype = type; | 910 | normaltype = type; |
911 | break; | 911 | break; |
912 | case 5: | 912 | case 5: |
913 | if (index==0) | 913 | if (index==0) |
914 | { | 914 | { |
915 | uvpos = size; | 915 | uvpos = size; |
916 | uvtype = type; | 916 | uvtype = type; |
917 | } | 917 | } |
918 | else if (index==1) | 918 | else if (index==1) |
919 | { | 919 | { |
920 | uv2pos = size; | 920 | uv2pos = size; |
921 | uv2type = type; | 921 | uv2type = type; |
922 | } | 922 | } |
923 | break; | 923 | break; |
924 | case 6: | 924 | case 6: |
925 | tangentpos = size; | 925 | tangentpos = size; |
926 | tangenttype = type; | 926 | tangenttype = type; |
927 | break; | 927 | break; |
928 | case 7: | 928 | case 7: |
929 | binormalpos = size; | 929 | binormalpos = size; |
930 | binormaltype = type; | 930 | binormaltype = type; |
931 | break; | 931 | break; |
932 | default: | 932 | default: |
933 | break; | 933 | break; |
934 | } | 934 | } |
935 | switch (type) | 935 | switch (type) |
936 | { | 936 | { |
937 | case 0: | 937 | case 0: |
938 | size += 4; | 938 | size += 4; |
939 | break; | 939 | break; |
940 | case 1: | 940 | case 1: |
941 | size += 8; | 941 | size += 8; |
942 | break; | 942 | break; |
943 | case 2: | 943 | case 2: |
944 | size += 12; | 944 | size += 12; |
945 | break; | 945 | break; |
946 | case 3: | 946 | case 3: |
947 | size += 16; | 947 | size += 16; |
948 | break; | 948 | break; |
949 | case 4: | 949 | case 4: |
950 | case 5: | 950 | case 5: |
951 | case 6: | 951 | case 6: |
952 | size += 4; | 952 | size += 4; |
953 | break; | 953 | break; |
954 | case 7: | 954 | case 7: |
955 | size += 8; | 955 | size += 8; |
956 | break; | 956 | break; |
957 | case 8: | 957 | case 8: |
958 | case 9: | 958 | case 9: |
959 | size += 4; | 959 | size += 4; |
960 | break; | 960 | break; |
961 | case 10: | 961 | case 10: |
962 | size += 8; | 962 | size += 8; |
963 | break; | 963 | break; |
964 | case 11: | 964 | case 11: |
965 | size += 4; | 965 | size += 4; |
966 | break; | 966 | break; |
967 | case 12: | 967 | case 12: |
968 | size += 8; | 968 | size += 8; |
969 | break; | 969 | break; |
970 | case 13: | 970 | case 13: |
971 | size += 4; | 971 | size += 4; |
972 | break; | 972 | break; |
973 | case 14: | 973 | case 14: |
974 | size += 4; | 974 | size += 4; |
975 | break; | 975 | break; |
976 | case 15: | 976 | case 15: |
977 | size += 4; | 977 | size += 4; |
978 | break; | 978 | break; |
979 | case 16: | 979 | case 16: |
980 | size += 8; | 980 | size += 8; |
981 | break; | 981 | break; |
982 | } | 982 | } |
983 | } | 983 | } |
984 | const u32 datasize = readInt(); | 984 | const u32 datasize = readInt(); |
985 | u32* data = new u32[datasize]; | 985 | u32* data = new u32[datasize]; |
986 | for (j=0; j<datasize; ++j) | 986 | for (j=0; j<datasize; ++j) |
987 | data[j]=readInt(); | 987 | data[j]=readInt(); |
988 | 988 | ||
989 | if (!checkForOneFollowingSemicolons()) | 989 | if (!checkForOneFollowingSemicolons()) |
990 | { | 990 | { |
991 | os::Printer::log("No finishing semicolon in DeclData found.", ELL_WARNING); | 991 | os::Printer::log("No finishing semicolon in DeclData found.", ELL_WARNING); |
992 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 992 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
993 | } | 993 | } |
994 | if (!checkForClosingBrace()) | 994 | if (!checkForClosingBrace()) |
995 | { | 995 | { |
996 | os::Printer::log("No closing brace in DeclData.", ELL_WARNING); | 996 | os::Printer::log("No closing brace in DeclData.", ELL_WARNING); |
997 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 997 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
998 | delete [] data; | 998 | delete [] data; |
999 | return false; | 999 | return false; |
1000 | } | 1000 | } |
1001 | u8* dataptr = (u8*) data; | 1001 | u8* dataptr = (u8*) data; |
1002 | if ((uv2pos != -1) && (uv2type == 1)) | 1002 | if ((uv2pos != -1) && (uv2type == 1)) |
1003 | mesh.TCoords2.reallocate(mesh.Vertices.size()); | 1003 | mesh.TCoords2.reallocate(mesh.Vertices.size()); |
1004 | for (j=0; j<mesh.Vertices.size(); ++j) | 1004 | for (j=0; j<mesh.Vertices.size(); ++j) |
1005 | { | 1005 | { |
1006 | if ((normalpos != -1) && (normaltype == 2)) | 1006 | if ((normalpos != -1) && (normaltype == 2)) |
1007 | mesh.Vertices[j].Normal.set(*((core::vector3df*)(dataptr+normalpos))); | 1007 | mesh.Vertices[j].Normal.set(*((core::vector3df*)(dataptr+normalpos))); |
1008 | if ((uvpos != -1) && (uvtype == 1)) | 1008 | if ((uvpos != -1) && (uvtype == 1)) |
1009 | mesh.Vertices[j].TCoords.set(*((core::vector2df*)(dataptr+uvpos))); | 1009 | mesh.Vertices[j].TCoords.set(*((core::vector2df*)(dataptr+uvpos))); |
1010 | if ((uv2pos != -1) && (uv2type == 1)) | 1010 | if ((uv2pos != -1) && (uv2type == 1)) |
1011 | mesh.TCoords2.push_back(*((core::vector2df*)(dataptr+uv2pos))); | 1011 | mesh.TCoords2.push_back(*((core::vector2df*)(dataptr+uv2pos))); |
1012 | dataptr += size; | 1012 | dataptr += size; |
1013 | } | 1013 | } |
1014 | delete [] data; | 1014 | delete [] data; |
1015 | } | 1015 | } |
1016 | else | 1016 | else |
1017 | if (objectName == "FVFData") | 1017 | if (objectName == "FVFData") |
1018 | { | 1018 | { |
1019 | if (!readHeadOfDataObject()) | 1019 | if (!readHeadOfDataObject()) |
1020 | { | 1020 | { |
1021 | os::Printer::log("No starting brace in FVFData found.", ELL_WARNING); | 1021 | os::Printer::log("No starting brace in FVFData found.", ELL_WARNING); |
1022 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1022 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1023 | return false; | 1023 | return false; |
1024 | } | 1024 | } |
1025 | const u32 dataformat = readInt(); | 1025 | const u32 dataformat = readInt(); |
1026 | const u32 datasize = readInt(); | 1026 | const u32 datasize = readInt(); |
1027 | u32* data = new u32[datasize]; | 1027 | u32* data = new u32[datasize]; |
1028 | for (u32 j=0; j<datasize; ++j) | 1028 | for (u32 j=0; j<datasize; ++j) |
1029 | data[j]=readInt(); | 1029 | data[j]=readInt(); |
1030 | if (dataformat&0x102) // 2nd uv set | 1030 | if (dataformat&0x102) // 2nd uv set |
1031 | { | 1031 | { |
1032 | mesh.TCoords2.reallocate(mesh.Vertices.size()); | 1032 | mesh.TCoords2.reallocate(mesh.Vertices.size()); |
1033 | u8* dataptr = (u8*) data; | 1033 | u8* dataptr = (u8*) data; |
1034 | const u32 size=((dataformat>>8)&0xf)*sizeof(core::vector2df); | 1034 | const u32 size=((dataformat>>8)&0xf)*sizeof(core::vector2df); |
1035 | for (u32 j=0; j<mesh.Vertices.size(); ++j) | 1035 | for (u32 j=0; j<mesh.Vertices.size(); ++j) |
1036 | { | 1036 | { |
1037 | mesh.TCoords2.push_back(*((core::vector2df*)(dataptr))); | 1037 | mesh.TCoords2.push_back(*((core::vector2df*)(dataptr))); |
1038 | dataptr += size; | 1038 | dataptr += size; |
1039 | } | 1039 | } |
1040 | } | 1040 | } |
1041 | delete [] data; | 1041 | delete [] data; |
1042 | if (!checkForOneFollowingSemicolons()) | 1042 | if (!checkForOneFollowingSemicolons()) |
1043 | { | 1043 | { |
1044 | os::Printer::log("No finishing semicolon in FVFData found.", ELL_WARNING); | 1044 | os::Printer::log("No finishing semicolon in FVFData found.", ELL_WARNING); |
1045 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1045 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1046 | } | 1046 | } |
1047 | if (!checkForClosingBrace()) | 1047 | if (!checkForClosingBrace()) |
1048 | { | 1048 | { |
1049 | os::Printer::log("No closing brace in FVFData found in x file", ELL_WARNING); | 1049 | os::Printer::log("No closing brace in FVFData found in x file", ELL_WARNING); |
1050 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1050 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1051 | return false; | 1051 | return false; |
1052 | } | 1052 | } |
1053 | } | 1053 | } |
1054 | else | 1054 | else |
1055 | if (objectName == "XSkinMeshHeader") | 1055 | if (objectName == "XSkinMeshHeader") |
1056 | { | 1056 | { |
1057 | if (!parseDataObjectSkinMeshHeader(mesh)) | 1057 | if (!parseDataObjectSkinMeshHeader(mesh)) |
1058 | return false; | 1058 | return false; |
1059 | } | 1059 | } |
1060 | else | 1060 | else |
1061 | if (objectName == "SkinWeights") | 1061 | if (objectName == "SkinWeights") |
1062 | { | 1062 | { |
1063 | //mesh.SkinWeights.push_back(SXSkinWeight()); | 1063 | //mesh.SkinWeights.push_back(SXSkinWeight()); |
1064 | //if (!parseDataObjectSkinWeights(mesh.SkinWeights.getLast())) | 1064 | //if (!parseDataObjectSkinWeights(mesh.SkinWeights.getLast())) |
1065 | if (!parseDataObjectSkinWeights(mesh)) | 1065 | if (!parseDataObjectSkinWeights(mesh)) |
1066 | return false; | 1066 | return false; |
1067 | } | 1067 | } |
1068 | else | 1068 | else |
1069 | { | 1069 | { |
1070 | os::Printer::log("Unknown data object in mesh in x file", objectName.c_str(), ELL_WARNING); | 1070 | os::Printer::log("Unknown data object in mesh in x file", objectName.c_str(), ELL_WARNING); |
1071 | if (!parseUnknownDataObject()) | 1071 | if (!parseUnknownDataObject()) |
1072 | return false; | 1072 | return false; |
1073 | } | 1073 | } |
1074 | } | 1074 | } |
1075 | 1075 | ||
1076 | return true; | 1076 | return true; |
1077 | } | 1077 | } |
1078 | 1078 | ||
1079 | 1079 | ||
1080 | bool CXMeshFileLoader::parseDataObjectSkinWeights(SXMesh &mesh) | 1080 | bool CXMeshFileLoader::parseDataObjectSkinWeights(SXMesh &mesh) |
1081 | { | 1081 | { |
1082 | #ifdef _XREADER_DEBUG | 1082 | #ifdef _XREADER_DEBUG |
1083 | os::Printer::log("CXFileReader: Reading mesh skin weights", ELL_DEBUG); | 1083 | os::Printer::log("CXFileReader: Reading mesh skin weights", ELL_DEBUG); |
1084 | #endif | 1084 | #endif |
1085 | 1085 | ||
1086 | if (!readHeadOfDataObject()) | 1086 | if (!readHeadOfDataObject()) |
1087 | { | 1087 | { |
1088 | os::Printer::log("No opening brace in Skin Weights found in .x file", ELL_WARNING); | 1088 | os::Printer::log("No opening brace in Skin Weights found in .x file", ELL_WARNING); |
1089 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1089 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1090 | return false; | 1090 | return false; |
1091 | } | 1091 | } |
1092 | 1092 | ||
1093 | core::stringc TransformNodeName; | 1093 | core::stringc TransformNodeName; |
1094 | 1094 | ||
1095 | if (!getNextTokenAsString(TransformNodeName)) | 1095 | if (!getNextTokenAsString(TransformNodeName)) |
1096 | { | 1096 | { |
1097 | os::Printer::log("Unknown syntax while reading transfrom node name string in .x file", ELL_WARNING); | 1097 | os::Printer::log("Unknown syntax while reading transfrom node name string in .x file", ELL_WARNING); |
1098 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1098 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1099 | return false; | 1099 | return false; |
1100 | } | 1100 | } |
1101 | 1101 | ||
1102 | mesh.HasSkinning=true; | 1102 | mesh.HasSkinning=true; |
1103 | 1103 | ||
1104 | CSkinnedMesh::SJoint *joint=0; | 1104 | CSkinnedMesh::SJoint *joint=0; |
1105 | 1105 | ||
1106 | u32 n; | 1106 | u32 n; |
1107 | for (n=0; n < AnimatedMesh->getAllJoints().size(); ++n) | 1107 | for (n=0; n < AnimatedMesh->getAllJoints().size(); ++n) |
1108 | { | 1108 | { |
1109 | if (AnimatedMesh->getAllJoints()[n]->Name==TransformNodeName) | 1109 | if (AnimatedMesh->getAllJoints()[n]->Name==TransformNodeName) |
1110 | { | 1110 | { |
1111 | joint=AnimatedMesh->getAllJoints()[n]; | 1111 | joint=AnimatedMesh->getAllJoints()[n]; |
1112 | break; | 1112 | break; |
1113 | } | 1113 | } |
1114 | } | 1114 | } |
1115 | 1115 | ||
1116 | if (!joint) | 1116 | if (!joint) |
1117 | { | 1117 | { |
1118 | #ifdef _XREADER_DEBUG | 1118 | #ifdef _XREADER_DEBUG |
1119 | os::Printer::log("creating joint for skinning ", TransformNodeName.c_str(), ELL_DEBUG); | 1119 | os::Printer::log("creating joint for skinning ", TransformNodeName.c_str(), ELL_DEBUG); |
1120 | #endif | 1120 | #endif |
1121 | n = AnimatedMesh->getAllJoints().size(); | 1121 | n = AnimatedMesh->getAllJoints().size(); |
1122 | joint=AnimatedMesh->addJoint(0); | 1122 | joint=AnimatedMesh->addJoint(0); |
1123 | joint->Name=TransformNodeName; | 1123 | joint->Name=TransformNodeName; |
1124 | } | 1124 | } |
1125 | 1125 | ||
1126 | // read vertex weights | 1126 | // read vertex weights |
1127 | const u32 nWeights = readInt(); | 1127 | const u32 nWeights = readInt(); |
1128 | 1128 | ||
1129 | // read vertex indices | 1129 | // read vertex indices |
1130 | u32 i; | 1130 | u32 i; |
1131 | 1131 | ||
1132 | const u32 jointStart = joint->Weights.size(); | 1132 | const u32 jointStart = joint->Weights.size(); |
1133 | joint->Weights.reallocate(jointStart+nWeights); | 1133 | joint->Weights.reallocate(jointStart+nWeights); |
1134 | 1134 | ||
1135 | mesh.WeightJoint.reallocate( mesh.WeightJoint.size() + nWeights ); | 1135 | mesh.WeightJoint.reallocate( mesh.WeightJoint.size() + nWeights ); |
1136 | mesh.WeightNum.reallocate( mesh.WeightNum.size() + nWeights ); | 1136 | mesh.WeightNum.reallocate( mesh.WeightNum.size() + nWeights ); |
1137 | 1137 | ||
1138 | for (i=0; i<nWeights; ++i) | 1138 | for (i=0; i<nWeights; ++i) |
1139 | { | 1139 | { |
1140 | mesh.WeightJoint.push_back(n); | 1140 | mesh.WeightJoint.push_back(n); |
1141 | mesh.WeightNum.push_back(joint->Weights.size()); | 1141 | mesh.WeightNum.push_back(joint->Weights.size()); |
1142 | 1142 | ||
1143 | CSkinnedMesh::SWeight *weight=AnimatedMesh->addWeight(joint); | 1143 | CSkinnedMesh::SWeight *weight=AnimatedMesh->addWeight(joint); |
1144 | 1144 | ||
1145 | weight->buffer_id=0; | 1145 | weight->buffer_id=0; |
1146 | weight->vertex_id=readInt(); | 1146 | weight->vertex_id=readInt(); |
1147 | } | 1147 | } |
1148 | 1148 | ||
1149 | // read vertex weights | 1149 | // read vertex weights |
1150 | 1150 | ||
1151 | for (i=jointStart; i<jointStart+nWeights; ++i) | 1151 | for (i=jointStart; i<jointStart+nWeights; ++i) |
1152 | joint->Weights[i].strength = readFloat(); | 1152 | joint->Weights[i].strength = readFloat(); |
1153 | 1153 | ||
1154 | // read matrix offset | 1154 | // read matrix offset |
1155 | 1155 | ||
1156 | // transforms the mesh vertices to the space of the bone | 1156 | // transforms the mesh vertices to the space of the bone |
1157 | // When concatenated to the bone's transform, this provides the | 1157 | // When concatenated to the bone's transform, this provides the |
1158 | // world space coordinates of the mesh as affected by the bone | 1158 | // world space coordinates of the mesh as affected by the bone |
1159 | core::matrix4& MatrixOffset = joint->GlobalInversedMatrix; | 1159 | core::matrix4& MatrixOffset = joint->GlobalInversedMatrix; |
1160 | 1160 | ||
1161 | readMatrix(MatrixOffset); | 1161 | readMatrix(MatrixOffset); |
1162 | 1162 | ||
1163 | if (!checkForOneFollowingSemicolons()) | 1163 | if (!checkForOneFollowingSemicolons()) |
1164 | { | 1164 | { |
1165 | os::Printer::log("No finishing semicolon in Skin Weights found in x file", ELL_WARNING); | 1165 | os::Printer::log("No finishing semicolon in Skin Weights found in x file", ELL_WARNING); |
1166 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1166 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1167 | } | 1167 | } |
1168 | 1168 | ||
1169 | if (!checkForClosingBrace()) | 1169 | if (!checkForClosingBrace()) |
1170 | { | 1170 | { |
1171 | os::Printer::log("No closing brace in Skin Weights found in x file", ELL_WARNING); | 1171 | os::Printer::log("No closing brace in Skin Weights found in x file", ELL_WARNING); |
1172 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1172 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1173 | return false; | 1173 | return false; |
1174 | } | 1174 | } |
1175 | 1175 | ||
1176 | return true; | 1176 | return true; |
1177 | } | 1177 | } |
1178 | 1178 | ||
1179 | 1179 | ||
1180 | bool CXMeshFileLoader::parseDataObjectSkinMeshHeader(SXMesh& mesh) | 1180 | bool CXMeshFileLoader::parseDataObjectSkinMeshHeader(SXMesh& mesh) |
1181 | { | 1181 | { |
1182 | #ifdef _XREADER_DEBUG | 1182 | #ifdef _XREADER_DEBUG |
1183 | os::Printer::log("CXFileReader: Reading skin mesh header", ELL_DEBUG); | 1183 | os::Printer::log("CXFileReader: Reading skin mesh header", ELL_DEBUG); |
1184 | #endif | 1184 | #endif |
1185 | 1185 | ||
1186 | if (!readHeadOfDataObject()) | 1186 | if (!readHeadOfDataObject()) |
1187 | { | 1187 | { |
1188 | os::Printer::log("No opening brace in Skin Mesh header found in .x file", ELL_WARNING); | 1188 | os::Printer::log("No opening brace in Skin Mesh header found in .x file", ELL_WARNING); |
1189 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1189 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1190 | return false; | 1190 | return false; |
1191 | } | 1191 | } |
1192 | 1192 | ||
1193 | mesh.MaxSkinWeightsPerVertex = readInt(); | 1193 | mesh.MaxSkinWeightsPerVertex = readInt(); |
1194 | mesh.MaxSkinWeightsPerFace = readInt(); | 1194 | mesh.MaxSkinWeightsPerFace = readInt(); |
1195 | mesh.BoneCount = readInt(); | 1195 | mesh.BoneCount = readInt(); |
1196 | 1196 | ||
1197 | if (!BinaryFormat) | 1197 | if (!BinaryFormat) |
1198 | getNextToken(); // skip semicolon | 1198 | getNextToken(); // skip semicolon |
1199 | 1199 | ||
1200 | if (!checkForClosingBrace()) | 1200 | if (!checkForClosingBrace()) |
1201 | { | 1201 | { |
1202 | os::Printer::log("No closing brace in skin mesh header in x file", ELL_WARNING); | 1202 | os::Printer::log("No closing brace in skin mesh header in x file", ELL_WARNING); |
1203 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1203 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1204 | return false; | 1204 | return false; |
1205 | } | 1205 | } |
1206 | 1206 | ||
1207 | return true; | 1207 | return true; |
1208 | } | 1208 | } |
1209 | 1209 | ||
1210 | 1210 | ||
1211 | bool CXMeshFileLoader::parseDataObjectMeshNormals(SXMesh &mesh) | 1211 | bool CXMeshFileLoader::parseDataObjectMeshNormals(SXMesh &mesh) |
1212 | { | 1212 | { |
1213 | #ifdef _XREADER_DEBUG | 1213 | #ifdef _XREADER_DEBUG |
1214 | os::Printer::log("CXFileReader: reading mesh normals", ELL_DEBUG); | 1214 | os::Printer::log("CXFileReader: reading mesh normals", ELL_DEBUG); |
1215 | #endif | 1215 | #endif |
1216 | 1216 | ||
1217 | if (!readHeadOfDataObject()) | 1217 | if (!readHeadOfDataObject()) |
1218 | { | 1218 | { |
1219 | os::Printer::log("No opening brace in Mesh Normals found in x file", ELL_WARNING); | 1219 | os::Printer::log("No opening brace in Mesh Normals found in x file", ELL_WARNING); |
1220 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1220 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1221 | return false; | 1221 | return false; |
1222 | } | 1222 | } |
1223 | 1223 | ||
1224 | // read count | 1224 | // read count |
1225 | const u32 nNormals = readInt(); | 1225 | const u32 nNormals = readInt(); |
1226 | core::array<core::vector3df> normals; | 1226 | core::array<core::vector3df> normals; |
1227 | normals.set_used(nNormals); | 1227 | normals.set_used(nNormals); |
1228 | 1228 | ||
1229 | // read normals | 1229 | // read normals |
1230 | for (u32 i=0; i<nNormals; ++i) | 1230 | for (u32 i=0; i<nNormals; ++i) |
1231 | readVector3(normals[i]); | 1231 | readVector3(normals[i]); |
1232 | 1232 | ||
1233 | if (!checkForTwoFollowingSemicolons()) | 1233 | if (!checkForTwoFollowingSemicolons()) |
1234 | { | 1234 | { |
1235 | os::Printer::log("No finishing semicolon in Mesh Normals Array found in x file", ELL_WARNING); | 1235 | os::Printer::log("No finishing semicolon in Mesh Normals Array found in x file", ELL_WARNING); |
1236 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1236 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1237 | } | 1237 | } |
1238 | 1238 | ||
1239 | core::array<u32> normalIndices; | 1239 | core::array<u32> normalIndices; |
1240 | normalIndices.set_used(mesh.Indices.size()); | 1240 | normalIndices.set_used(mesh.Indices.size()); |
1241 | 1241 | ||
1242 | // read face normal indices | 1242 | // read face normal indices |
1243 | const u32 nFNormals = readInt(); | 1243 | const u32 nFNormals = readInt(); |
1244 | 1244 | ||
1245 | u32 normalidx = 0; | 1245 | u32 normalidx = 0; |
1246 | core::array<u32> polygonfaces; | 1246 | core::array<u32> polygonfaces; |
1247 | for (u32 k=0; k<nFNormals; ++k) | 1247 | for (u32 k=0; k<nFNormals; ++k) |
1248 | { | 1248 | { |
1249 | const u32 fcnt = readInt(); | 1249 | const u32 fcnt = readInt(); |
1250 | u32 triangles = fcnt - 2; | 1250 | u32 triangles = fcnt - 2; |
1251 | u32 indexcount = triangles * 3; | 1251 | u32 indexcount = triangles * 3; |
1252 | 1252 | ||
1253 | if (indexcount != mesh.IndexCountPerFace[k]) | 1253 | if (indexcount != mesh.IndexCountPerFace[k]) |
1254 | { | 1254 | { |
1255 | os::Printer::log("Not matching normal and face index count found in x file", ELL_WARNING); | 1255 | os::Printer::log("Not matching normal and face index count found in x file", ELL_WARNING); |
1256 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1256 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1257 | return false; | 1257 | return false; |
1258 | } | 1258 | } |
1259 | 1259 | ||
1260 | if (indexcount == 3) | 1260 | if (indexcount == 3) |
1261 | { | 1261 | { |
1262 | // default, only one triangle in this face | 1262 | // default, only one triangle in this face |
1263 | for (u32 h=0; h<3; ++h) | 1263 | for (u32 h=0; h<3; ++h) |
1264 | { | 1264 | { |
1265 | const u32 normalnum = readInt(); | 1265 | const u32 normalnum = readInt(); |
1266 | mesh.Vertices[mesh.Indices[normalidx++]].Normal.set(normals[normalnum]); | 1266 | mesh.Vertices[mesh.Indices[normalidx++]].Normal.set(normals[normalnum]); |
1267 | } | 1267 | } |
1268 | } | 1268 | } |
1269 | else | 1269 | else |
1270 | { | 1270 | { |
1271 | polygonfaces.set_used(fcnt); | 1271 | polygonfaces.set_used(fcnt); |
1272 | // multiple triangles in this face | 1272 | // multiple triangles in this face |
1273 | for (u32 h=0; h<fcnt; ++h) | 1273 | for (u32 h=0; h<fcnt; ++h) |
1274 | polygonfaces[h] = readInt(); | 1274 | polygonfaces[h] = readInt(); |
1275 | 1275 | ||
1276 | for (u32 jk=0; jk<triangles; ++jk) | 1276 | for (u32 jk=0; jk<triangles; ++jk) |
1277 | { | 1277 | { |
1278 | mesh.Vertices[mesh.Indices[normalidx++]].Normal.set(normals[polygonfaces[0]]); | 1278 | mesh.Vertices[mesh.Indices[normalidx++]].Normal.set(normals[polygonfaces[0]]); |
1279 | mesh.Vertices[mesh.Indices[normalidx++]].Normal.set(normals[polygonfaces[jk+1]]); | 1279 | mesh.Vertices[mesh.Indices[normalidx++]].Normal.set(normals[polygonfaces[jk+1]]); |
1280 | mesh.Vertices[mesh.Indices[normalidx++]].Normal.set(normals[polygonfaces[jk+2]]); | 1280 | mesh.Vertices[mesh.Indices[normalidx++]].Normal.set(normals[polygonfaces[jk+2]]); |
1281 | } | 1281 | } |
1282 | } | 1282 | } |
1283 | } | 1283 | } |
1284 | 1284 | ||
1285 | if (!checkForTwoFollowingSemicolons()) | 1285 | if (!checkForTwoFollowingSemicolons()) |
1286 | { | 1286 | { |
1287 | os::Printer::log("No finishing semicolon in Mesh Face Normals Array found in x file", ELL_WARNING); | 1287 | os::Printer::log("No finishing semicolon in Mesh Face Normals Array found in x file", ELL_WARNING); |
1288 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1288 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1289 | } | 1289 | } |
1290 | 1290 | ||
1291 | if (!checkForClosingBrace()) | 1291 | if (!checkForClosingBrace()) |
1292 | { | 1292 | { |
1293 | os::Printer::log("No closing brace in Mesh Normals found in x file", ELL_WARNING); | 1293 | os::Printer::log("No closing brace in Mesh Normals found in x file", ELL_WARNING); |
1294 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1294 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1295 | return false; | 1295 | return false; |
1296 | } | 1296 | } |
1297 | 1297 | ||
1298 | return true; | 1298 | return true; |
1299 | } | 1299 | } |
1300 | 1300 | ||
1301 | 1301 | ||
1302 | bool CXMeshFileLoader::parseDataObjectMeshTextureCoords(SXMesh &mesh) | 1302 | bool CXMeshFileLoader::parseDataObjectMeshTextureCoords(SXMesh &mesh) |
1303 | { | 1303 | { |
1304 | #ifdef _XREADER_DEBUG | 1304 | #ifdef _XREADER_DEBUG |
1305 | os::Printer::log("CXFileReader: reading mesh texture coordinates", ELL_DEBUG); | 1305 | os::Printer::log("CXFileReader: reading mesh texture coordinates", ELL_DEBUG); |
1306 | #endif | 1306 | #endif |
1307 | 1307 | ||
1308 | if (!readHeadOfDataObject()) | 1308 | if (!readHeadOfDataObject()) |
1309 | { | 1309 | { |
1310 | os::Printer::log("No opening brace in Mesh Texture Coordinates found in x file", ELL_WARNING); | 1310 | os::Printer::log("No opening brace in Mesh Texture Coordinates found in x file", ELL_WARNING); |
1311 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1311 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1312 | return false; | 1312 | return false; |
1313 | } | 1313 | } |
1314 | 1314 | ||
1315 | const u32 nCoords = readInt(); | 1315 | const u32 nCoords = readInt(); |
1316 | for (u32 i=0; i<nCoords; ++i) | 1316 | for (u32 i=0; i<nCoords; ++i) |
1317 | readVector2(mesh.Vertices[i].TCoords); | 1317 | readVector2(mesh.Vertices[i].TCoords); |
1318 | 1318 | ||
1319 | if (!checkForTwoFollowingSemicolons()) | 1319 | if (!checkForTwoFollowingSemicolons()) |
1320 | { | 1320 | { |
1321 | os::Printer::log("No finishing semicolon in Mesh Texture Coordinates Array found in x file", ELL_WARNING); | 1321 | os::Printer::log("No finishing semicolon in Mesh Texture Coordinates Array found in x file", ELL_WARNING); |
1322 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1322 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1323 | } | 1323 | } |
1324 | 1324 | ||
1325 | if (!checkForClosingBrace()) | 1325 | if (!checkForClosingBrace()) |
1326 | { | 1326 | { |
1327 | os::Printer::log("No closing brace in Mesh Texture Coordinates Array found in x file", ELL_WARNING); | 1327 | os::Printer::log("No closing brace in Mesh Texture Coordinates Array found in x file", ELL_WARNING); |
1328 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1328 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1329 | return false; | 1329 | return false; |
1330 | } | 1330 | } |
1331 | 1331 | ||
1332 | return true; | 1332 | return true; |
1333 | } | 1333 | } |
1334 | 1334 | ||
1335 | 1335 | ||
1336 | bool CXMeshFileLoader::parseDataObjectMeshVertexColors(SXMesh &mesh) | 1336 | bool CXMeshFileLoader::parseDataObjectMeshVertexColors(SXMesh &mesh) |
1337 | { | 1337 | { |
1338 | #ifdef _XREADER_DEBUG | 1338 | #ifdef _XREADER_DEBUG |
1339 | os::Printer::log("CXFileReader: reading mesh vertex colors", ELL_DEBUG); | 1339 | os::Printer::log("CXFileReader: reading mesh vertex colors", ELL_DEBUG); |
1340 | #endif | 1340 | #endif |
1341 | 1341 | ||
1342 | if (!readHeadOfDataObject()) | 1342 | if (!readHeadOfDataObject()) |
1343 | { | 1343 | { |
1344 | os::Printer::log("No opening brace for Mesh Vertex Colors found in x file", ELL_WARNING); | 1344 | os::Printer::log("No opening brace for Mesh Vertex Colors found in x file", ELL_WARNING); |
1345 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1345 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1346 | return false; | 1346 | return false; |
1347 | } | 1347 | } |
1348 | 1348 | ||
1349 | mesh.HasVertexColors=true; | 1349 | mesh.HasVertexColors=true; |
1350 | const u32 nColors = readInt(); | 1350 | const u32 nColors = readInt(); |
1351 | for (u32 i=0; i<nColors; ++i) | 1351 | for (u32 i=0; i<nColors; ++i) |
1352 | { | 1352 | { |
1353 | const u32 Index=readInt(); | 1353 | const u32 Index=readInt(); |
1354 | if (Index>=mesh.Vertices.size()) | 1354 | if (Index>=mesh.Vertices.size()) |
1355 | { | 1355 | { |
1356 | os::Printer::log("index value in parseDataObjectMeshVertexColors out of bounds", ELL_WARNING); | 1356 | os::Printer::log("index value in parseDataObjectMeshVertexColors out of bounds", ELL_WARNING); |
1357 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1357 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1358 | return false; | 1358 | return false; |
1359 | } | 1359 | } |
1360 | readRGBA(mesh.Vertices[Index].Color); | 1360 | readRGBA(mesh.Vertices[Index].Color); |
1361 | checkForOneFollowingSemicolons(); | 1361 | checkForOneFollowingSemicolons(); |
1362 | } | 1362 | } |
1363 | 1363 | ||
1364 | if (!checkForOneFollowingSemicolons()) | 1364 | if (!checkForOneFollowingSemicolons()) |
1365 | { | 1365 | { |
1366 | os::Printer::log("No finishing semicolon in Mesh Vertex Colors Array found in x file", ELL_WARNING); | 1366 | os::Printer::log("No finishing semicolon in Mesh Vertex Colors Array found in x file", ELL_WARNING); |
1367 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1367 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1368 | } | 1368 | } |
1369 | 1369 | ||
1370 | if (!checkForClosingBrace()) | 1370 | if (!checkForClosingBrace()) |
1371 | { | 1371 | { |
1372 | os::Printer::log("No closing brace in Mesh Texture Coordinates Array found in x file", ELL_WARNING); | 1372 | os::Printer::log("No closing brace in Mesh Texture Coordinates Array found in x file", ELL_WARNING); |
1373 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1373 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1374 | return false; | 1374 | return false; |
1375 | } | 1375 | } |
1376 | 1376 | ||
1377 | return true; | 1377 | return true; |
1378 | } | 1378 | } |
1379 | 1379 | ||
1380 | 1380 | ||
1381 | bool CXMeshFileLoader::parseDataObjectMeshMaterialList(SXMesh &mesh) | 1381 | bool CXMeshFileLoader::parseDataObjectMeshMaterialList(SXMesh &mesh) |
1382 | { | 1382 | { |
1383 | #ifdef _XREADER_DEBUG | 1383 | #ifdef _XREADER_DEBUG |
1384 | os::Printer::log("CXFileReader: Reading mesh material list", ELL_DEBUG); | 1384 | os::Printer::log("CXFileReader: Reading mesh material list", ELL_DEBUG); |
1385 | #endif | 1385 | #endif |
1386 | 1386 | ||
1387 | if (!readHeadOfDataObject()) | 1387 | if (!readHeadOfDataObject()) |
1388 | { | 1388 | { |
1389 | os::Printer::log("No opening brace in Mesh Material List found in x file", ELL_WARNING); | 1389 | os::Printer::log("No opening brace in Mesh Material List found in x file", ELL_WARNING); |
1390 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1390 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1391 | return false; | 1391 | return false; |
1392 | } | 1392 | } |
1393 | 1393 | ||
1394 | // read material count | 1394 | // read material count |
1395 | mesh.Materials.reallocate(readInt()); | 1395 | mesh.Materials.reallocate(readInt()); |
1396 | 1396 | ||
1397 | // read non triangulated face material index count | 1397 | // read non triangulated face material index count |
1398 | const u32 nFaceIndices = readInt(); | 1398 | const u32 nFaceIndices = readInt(); |
1399 | 1399 | ||
1400 | // There seems to be a compact representation of "all faces the same material" | 1400 | // There seems to be a compact representation of "all faces the same material" |
1401 | // being represented as 1;1;0;; which means 1 material, 1 face with first material | 1401 | // being represented as 1;1;0;; which means 1 material, 1 face with first material |
1402 | // all the other faces have to obey then, so check is disabled | 1402 | // all the other faces have to obey then, so check is disabled |
1403 | //if (nFaceIndices != mesh.IndexCountPerFace.size()) | 1403 | //if (nFaceIndices != mesh.IndexCountPerFace.size()) |
1404 | // os::Printer::log("Index count per face not equal to face material index count in x file.", ELL_WARNING); | 1404 | // os::Printer::log("Index count per face not equal to face material index count in x file.", ELL_WARNING); |
1405 | 1405 | ||
1406 | // read non triangulated face indices and create triangulated ones | 1406 | // read non triangulated face indices and create triangulated ones |
1407 | mesh.FaceMaterialIndices.set_used( mesh.Indices.size() / 3); | 1407 | mesh.FaceMaterialIndices.set_used( mesh.Indices.size() / 3); |
1408 | u32 triangulatedindex = 0; | 1408 | u32 triangulatedindex = 0; |
1409 | u32 ind = 0; | 1409 | u32 ind = 0; |
1410 | for (u32 tfi=0; tfi<mesh.IndexCountPerFace.size(); ++tfi) | 1410 | for (u32 tfi=0; tfi<mesh.IndexCountPerFace.size(); ++tfi) |
1411 | { | 1411 | { |
1412 | if (tfi<nFaceIndices) | 1412 | if (tfi<nFaceIndices) |
1413 | ind = readInt(); | 1413 | ind = readInt(); |
1414 | const u32 fc = mesh.IndexCountPerFace[tfi]/3; | 1414 | const u32 fc = mesh.IndexCountPerFace[tfi]/3; |
1415 | for (u32 k=0; k<fc; ++k) | 1415 | for (u32 k=0; k<fc; ++k) |
1416 | mesh.FaceMaterialIndices[triangulatedindex++] = ind; | 1416 | mesh.FaceMaterialIndices[triangulatedindex++] = ind; |
1417 | } | 1417 | } |
1418 | 1418 | ||
1419 | // in version 03.02, the face indices end with two semicolons. | 1419 | // in version 03.02, the face indices end with two semicolons. |
1420 | // commented out version check, as version 03.03 exported from blender also has 2 semicolons | 1420 | // commented out version check, as version 03.03 exported from blender also has 2 semicolons |
1421 | if (!BinaryFormat) // && MajorVersion == 3 && MinorVersion <= 2) | 1421 | if (!BinaryFormat) // && MajorVersion == 3 && MinorVersion <= 2) |
1422 | { | 1422 | { |
1423 | if (P[0] == ';') | 1423 | if (P[0] == ';') |
1424 | ++P; | 1424 | ++P; |
1425 | } | 1425 | } |
1426 | 1426 | ||
1427 | // read following data objects | 1427 | // read following data objects |
1428 | 1428 | ||
1429 | while(true) | 1429 | while(true) |
1430 | { | 1430 | { |
1431 | core::stringc objectName = getNextToken(); | 1431 | core::stringc objectName = getNextToken(); |
1432 | 1432 | ||
1433 | if (objectName.size() == 0) | 1433 | if (objectName.size() == 0) |
1434 | { | 1434 | { |
1435 | os::Printer::log("Unexpected ending found in Mesh Material list in .x file.", ELL_WARNING); | 1435 | os::Printer::log("Unexpected ending found in Mesh Material list in .x file.", ELL_WARNING); |
1436 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1436 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1437 | return false; | 1437 | return false; |
1438 | } | 1438 | } |
1439 | else | 1439 | else |
1440 | if (objectName == "}") | 1440 | if (objectName == "}") |
1441 | { | 1441 | { |
1442 | break; // material list finished | 1442 | break; // material list finished |
1443 | } | 1443 | } |
1444 | else | 1444 | else |
1445 | if (objectName == "{") | 1445 | if (objectName == "{") |
1446 | { | 1446 | { |
1447 | // template materials now available thanks to joeWright | 1447 | // template materials now available thanks to joeWright |
1448 | objectName = getNextToken(); | 1448 | objectName = getNextToken(); |
1449 | for (u32 i=0; i<TemplateMaterials.size(); ++i) | 1449 | for (u32 i=0; i<TemplateMaterials.size(); ++i) |
1450 | if (TemplateMaterials[i].Name == objectName) | 1450 | if (TemplateMaterials[i].Name == objectName) |
1451 | mesh.Materials.push_back(TemplateMaterials[i].Material); | 1451 | mesh.Materials.push_back(TemplateMaterials[i].Material); |
1452 | getNextToken(); // skip } | 1452 | getNextToken(); // skip } |
1453 | } | 1453 | } |
1454 | else | 1454 | else |
1455 | if (objectName == "Material") | 1455 | if (objectName == "Material") |
1456 | { | 1456 | { |
1457 | mesh.Materials.push_back(video::SMaterial()); | 1457 | mesh.Materials.push_back(video::SMaterial()); |
1458 | if (!parseDataObjectMaterial(mesh.Materials.getLast())) | 1458 | if (!parseDataObjectMaterial(mesh.Materials.getLast())) |
1459 | return false; | 1459 | return false; |
1460 | } | 1460 | } |
1461 | else | 1461 | else |
1462 | if (objectName == ";") | 1462 | if (objectName == ";") |
1463 | { | 1463 | { |
1464 | // ignore | 1464 | // ignore |
1465 | } | 1465 | } |
1466 | else | 1466 | else |
1467 | { | 1467 | { |
1468 | os::Printer::log("Unknown data object in material list in x file", objectName.c_str(), ELL_WARNING); | 1468 | os::Printer::log("Unknown data object in material list in x file", objectName.c_str(), ELL_WARNING); |
1469 | if (!parseUnknownDataObject()) | 1469 | if (!parseUnknownDataObject()) |
1470 | return false; | 1470 | return false; |
1471 | } | 1471 | } |
1472 | } | 1472 | } |
1473 | return true; | 1473 | return true; |
1474 | } | 1474 | } |
1475 | 1475 | ||
1476 | 1476 | ||
1477 | bool CXMeshFileLoader::parseDataObjectMaterial(video::SMaterial& material) | 1477 | bool CXMeshFileLoader::parseDataObjectMaterial(video::SMaterial& material) |
1478 | { | 1478 | { |
1479 | #ifdef _XREADER_DEBUG | 1479 | #ifdef _XREADER_DEBUG |
1480 | os::Printer::log("CXFileReader: Reading mesh material", ELL_DEBUG); | 1480 | os::Printer::log("CXFileReader: Reading mesh material", ELL_DEBUG); |
1481 | #endif | 1481 | #endif |
1482 | 1482 | ||
1483 | if (!readHeadOfDataObject()) | 1483 | if (!readHeadOfDataObject()) |
1484 | { | 1484 | { |
1485 | os::Printer::log("No opening brace in Mesh Material found in .x file", ELL_WARNING); | 1485 | os::Printer::log("No opening brace in Mesh Material found in .x file", ELL_WARNING); |
1486 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1486 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1487 | return false; | 1487 | return false; |
1488 | } | 1488 | } |
1489 | 1489 | ||
1490 | // read RGBA | 1490 | // read RGBA |
1491 | readRGBA(material.DiffuseColor); checkForOneFollowingSemicolons(); | 1491 | readRGBA(material.DiffuseColor); checkForOneFollowingSemicolons(); |
1492 | 1492 | ||
1493 | // read power | 1493 | // read power |
1494 | material.Shininess = readFloat(); | 1494 | material.Shininess = readFloat(); |
1495 | 1495 | ||
1496 | // read specular | 1496 | // read specular |
1497 | readRGB(material.SpecularColor); checkForOneFollowingSemicolons(); | 1497 | readRGB(material.SpecularColor); checkForOneFollowingSemicolons(); |
1498 | 1498 | ||
1499 | // read emissive | 1499 | // read emissive |
1500 | readRGB(material.EmissiveColor); checkForOneFollowingSemicolons(); | 1500 | readRGB(material.EmissiveColor); checkForOneFollowingSemicolons(); |
1501 | 1501 | ||
1502 | // read other data objects | 1502 | // read other data objects |
1503 | int textureLayer=0; | 1503 | int textureLayer=0; |
1504 | while(true) | 1504 | while(true) |
1505 | { | 1505 | { |
1506 | core::stringc objectName = getNextToken(); | 1506 | core::stringc objectName = getNextToken(); |
1507 | 1507 | ||
1508 | if (objectName.size() == 0) | 1508 | if (objectName.size() == 0) |
1509 | { | 1509 | { |
1510 | os::Printer::log("Unexpected ending found in Mesh Material in .x file.", ELL_WARNING); | 1510 | os::Printer::log("Unexpected ending found in Mesh Material in .x file.", ELL_WARNING); |
1511 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1511 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1512 | return false; | 1512 | return false; |
1513 | } | 1513 | } |
1514 | else | 1514 | else |
1515 | if (objectName == "}") | 1515 | if (objectName == "}") |
1516 | { | 1516 | { |
1517 | break; // material finished | 1517 | break; // material finished |
1518 | } | 1518 | } |
1519 | else | 1519 | else |
1520 | if (objectName.equals_ignore_case("TextureFilename")) | 1520 | if (objectName.equals_ignore_case("TextureFilename")) |
1521 | { | 1521 | { |
1522 | // some exporters write "TextureFileName" instead. | 1522 | // some exporters write "TextureFileName" instead. |
1523 | core::stringc TextureFileName; | 1523 | core::stringc TextureFileName; |
1524 | if (!parseDataObjectTextureFilename(TextureFileName)) | 1524 | if (!parseDataObjectTextureFilename(TextureFileName)) |
1525 | return false; | 1525 | return false; |
1526 | 1526 | ||
1527 | // original name | 1527 | // original name |
1528 | if (FileSystem->existFile(TextureFileName)) | 1528 | if (FileSystem->existFile(TextureFileName)) |
1529 | material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(TextureFileName)); | 1529 | material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(TextureFileName)); |
1530 | // mesh path | 1530 | // mesh path |
1531 | else | 1531 | else |
1532 | { | 1532 | { |
1533 | TextureFileName=FilePath + FileSystem->getFileBasename(TextureFileName); | 1533 | TextureFileName=FilePath + FileSystem->getFileBasename(TextureFileName); |
1534 | if (FileSystem->existFile(TextureFileName)) | 1534 | if (FileSystem->existFile(TextureFileName)) |
1535 | material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(TextureFileName)); | 1535 | material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(TextureFileName)); |
1536 | // working directory | 1536 | // working directory |
1537 | else | 1537 | else |
1538 | material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(FileSystem->getFileBasename(TextureFileName))); | 1538 | material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(FileSystem->getFileBasename(TextureFileName))); |
1539 | } | 1539 | } |
1540 | ++textureLayer; | 1540 | ++textureLayer; |
1541 | if (textureLayer==2) | 1541 | if (textureLayer==2) |
1542 | material.MaterialType=video::EMT_LIGHTMAP; | 1542 | material.MaterialType=video::EMT_LIGHTMAP; |
1543 | } | 1543 | } |
1544 | else | 1544 | else |
1545 | if (objectName.equals_ignore_case("NormalmapFilename")) | 1545 | if (objectName.equals_ignore_case("NormalmapFilename")) |
1546 | { | 1546 | { |
1547 | // some exporters write "NormalmapFileName" instead. | 1547 | // some exporters write "NormalmapFileName" instead. |
1548 | core::stringc TextureFileName; | 1548 | core::stringc TextureFileName; |
1549 | if (!parseDataObjectTextureFilename(TextureFileName)) | 1549 | if (!parseDataObjectTextureFilename(TextureFileName)) |
1550 | return false; | 1550 | return false; |
1551 | 1551 | ||
1552 | // original name | 1552 | // original name |
1553 | if (FileSystem->existFile(TextureFileName)) | 1553 | if (FileSystem->existFile(TextureFileName)) |
1554 | material.setTexture(1, SceneManager->getVideoDriver()->getTexture(TextureFileName)); | 1554 | material.setTexture(1, SceneManager->getVideoDriver()->getTexture(TextureFileName)); |
1555 | // mesh path | 1555 | // mesh path |
1556 | else | 1556 | else |
1557 | { | 1557 | { |
1558 | TextureFileName=FilePath + FileSystem->getFileBasename(TextureFileName); | 1558 | TextureFileName=FilePath + FileSystem->getFileBasename(TextureFileName); |
1559 | if (FileSystem->existFile(TextureFileName)) | 1559 | if (FileSystem->existFile(TextureFileName)) |
1560 | material.setTexture(1, SceneManager->getVideoDriver()->getTexture(TextureFileName)); | 1560 | material.setTexture(1, SceneManager->getVideoDriver()->getTexture(TextureFileName)); |
1561 | // working directory | 1561 | // working directory |
1562 | else | 1562 | else |
1563 | material.setTexture(1, SceneManager->getVideoDriver()->getTexture(FileSystem->getFileBasename(TextureFileName))); | 1563 | material.setTexture(1, SceneManager->getVideoDriver()->getTexture(FileSystem->getFileBasename(TextureFileName))); |
1564 | } | 1564 | } |
1565 | if (textureLayer==1) | 1565 | if (textureLayer==1) |
1566 | ++textureLayer; | 1566 | ++textureLayer; |
1567 | } | 1567 | } |
1568 | else | 1568 | else |
1569 | { | 1569 | { |
1570 | os::Printer::log("Unknown data object in material in .x file", objectName.c_str(), ELL_WARNING); | 1570 | os::Printer::log("Unknown data object in material in .x file", objectName.c_str(), ELL_WARNING); |
1571 | if (!parseUnknownDataObject()) | 1571 | if (!parseUnknownDataObject()) |
1572 | return false; | 1572 | return false; |
1573 | } | 1573 | } |
1574 | } | 1574 | } |
1575 | 1575 | ||
1576 | return true; | 1576 | return true; |
1577 | } | 1577 | } |
1578 | 1578 | ||
1579 | 1579 | ||
1580 | bool CXMeshFileLoader::parseDataObjectAnimationSet() | 1580 | bool CXMeshFileLoader::parseDataObjectAnimationSet() |
1581 | { | 1581 | { |
1582 | #ifdef _XREADER_DEBUG | 1582 | #ifdef _XREADER_DEBUG |
1583 | os::Printer::log("CXFileReader: Reading animation set", ELL_DEBUG); | 1583 | os::Printer::log("CXFileReader: Reading animation set", ELL_DEBUG); |
1584 | #endif | 1584 | #endif |
1585 | 1585 | ||
1586 | core::stringc AnimationName; | 1586 | core::stringc AnimationName; |
1587 | 1587 | ||
1588 | if (!readHeadOfDataObject(&AnimationName)) | 1588 | if (!readHeadOfDataObject(&AnimationName)) |
1589 | { | 1589 | { |
1590 | os::Printer::log("No opening brace in Animation Set found in x file", ELL_WARNING); | 1590 | os::Printer::log("No opening brace in Animation Set found in x file", ELL_WARNING); |
1591 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1591 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1592 | return false; | 1592 | return false; |
1593 | } | 1593 | } |
1594 | os::Printer::log("Reading animationset ", AnimationName, ELL_DEBUG); | 1594 | os::Printer::log("Reading animationset ", AnimationName, ELL_DEBUG); |
1595 | 1595 | ||
1596 | while(true) | 1596 | while(true) |
1597 | { | 1597 | { |
1598 | core::stringc objectName = getNextToken(); | 1598 | core::stringc objectName = getNextToken(); |
1599 | 1599 | ||
1600 | if (objectName.size() == 0) | 1600 | if (objectName.size() == 0) |
1601 | { | 1601 | { |
1602 | os::Printer::log("Unexpected ending found in Animation set in x file.", ELL_WARNING); | 1602 | os::Printer::log("Unexpected ending found in Animation set in x file.", ELL_WARNING); |
1603 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1603 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1604 | return false; | 1604 | return false; |
1605 | } | 1605 | } |
1606 | else | 1606 | else |
1607 | if (objectName == "}") | 1607 | if (objectName == "}") |
1608 | { | 1608 | { |
1609 | break; // animation set finished | 1609 | break; // animation set finished |
1610 | } | 1610 | } |
1611 | else | 1611 | else |
1612 | if (objectName == "Animation") | 1612 | if (objectName == "Animation") |
1613 | { | 1613 | { |
1614 | if (!parseDataObjectAnimation()) | 1614 | if (!parseDataObjectAnimation()) |
1615 | return false; | 1615 | return false; |
1616 | } | 1616 | } |
1617 | else | 1617 | else |
1618 | { | 1618 | { |
1619 | os::Printer::log("Unknown data object in animation set in x file", objectName.c_str(), ELL_WARNING); | 1619 | os::Printer::log("Unknown data object in animation set in x file", objectName.c_str(), ELL_WARNING); |
1620 | if (!parseUnknownDataObject()) | 1620 | if (!parseUnknownDataObject()) |
1621 | return false; | 1621 | return false; |
1622 | } | 1622 | } |
1623 | } | 1623 | } |
1624 | return true; | 1624 | return true; |
1625 | } | 1625 | } |
1626 | 1626 | ||
1627 | 1627 | ||
1628 | bool CXMeshFileLoader::parseDataObjectAnimation() | 1628 | bool CXMeshFileLoader::parseDataObjectAnimation() |
1629 | { | 1629 | { |
1630 | #ifdef _XREADER_DEBUG | 1630 | #ifdef _XREADER_DEBUG |
1631 | os::Printer::log("CXFileReader: reading animation", ELL_DEBUG); | 1631 | os::Printer::log("CXFileReader: reading animation", ELL_DEBUG); |
1632 | #endif | 1632 | #endif |
1633 | 1633 | ||
1634 | if (!readHeadOfDataObject()) | 1634 | if (!readHeadOfDataObject()) |
1635 | { | 1635 | { |
1636 | os::Printer::log("No opening brace in Animation found in x file", ELL_WARNING); | 1636 | os::Printer::log("No opening brace in Animation found in x file", ELL_WARNING); |
1637 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1637 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1638 | return false; | 1638 | return false; |
1639 | } | 1639 | } |
1640 | 1640 | ||
1641 | //anim.closed = true; | 1641 | //anim.closed = true; |
1642 | //anim.linearPositionQuality = true; | 1642 | //anim.linearPositionQuality = true; |
1643 | CSkinnedMesh::SJoint animationDump; | 1643 | CSkinnedMesh::SJoint animationDump; |
1644 | 1644 | ||
1645 | core::stringc FrameName; | 1645 | core::stringc FrameName; |
1646 | 1646 | ||
1647 | while(true) | 1647 | while(true) |
1648 | { | 1648 | { |
1649 | core::stringc objectName = getNextToken(); | 1649 | core::stringc objectName = getNextToken(); |
1650 | 1650 | ||
1651 | if (objectName.size() == 0) | 1651 | if (objectName.size() == 0) |
1652 | { | 1652 | { |
1653 | os::Printer::log("Unexpected ending found in Animation in x file.", ELL_WARNING); | 1653 | os::Printer::log("Unexpected ending found in Animation in x file.", ELL_WARNING); |
1654 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1654 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1655 | return false; | 1655 | return false; |
1656 | } | 1656 | } |
1657 | else | 1657 | else |
1658 | if (objectName == "}") | 1658 | if (objectName == "}") |
1659 | { | 1659 | { |
1660 | break; // animation finished | 1660 | break; // animation finished |
1661 | } | 1661 | } |
1662 | else | 1662 | else |
1663 | if (objectName == "AnimationKey") | 1663 | if (objectName == "AnimationKey") |
1664 | { | 1664 | { |
1665 | if (!parseDataObjectAnimationKey(&animationDump)) | 1665 | if (!parseDataObjectAnimationKey(&animationDump)) |
1666 | return false; | 1666 | return false; |
1667 | } | 1667 | } |
1668 | else | 1668 | else |
1669 | if (objectName == "AnimationOptions") | 1669 | if (objectName == "AnimationOptions") |
1670 | { | 1670 | { |
1671 | //TODO: parse options. | 1671 | //TODO: parse options. |
1672 | if (!parseUnknownDataObject()) | 1672 | if (!parseUnknownDataObject()) |
1673 | return false; | 1673 | return false; |
1674 | } | 1674 | } |
1675 | else | 1675 | else |
1676 | if (objectName == "{") | 1676 | if (objectName == "{") |
1677 | { | 1677 | { |
1678 | // read frame name | 1678 | // read frame name |
1679 | FrameName = getNextToken(); | 1679 | FrameName = getNextToken(); |
1680 | 1680 | ||
1681 | if (!checkForClosingBrace()) | 1681 | if (!checkForClosingBrace()) |
1682 | { | 1682 | { |
1683 | os::Printer::log("Unexpected ending found in Animation in x file.", ELL_WARNING); | 1683 | os::Printer::log("Unexpected ending found in Animation in x file.", ELL_WARNING); |
1684 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1684 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1685 | return false; | 1685 | return false; |
1686 | } | 1686 | } |
1687 | } | 1687 | } |
1688 | else | 1688 | else |
1689 | { | 1689 | { |
1690 | os::Printer::log("Unknown data object in animation in x file", objectName.c_str(), ELL_WARNING); | 1690 | os::Printer::log("Unknown data object in animation in x file", objectName.c_str(), ELL_WARNING); |
1691 | if (!parseUnknownDataObject()) | 1691 | if (!parseUnknownDataObject()) |
1692 | return false; | 1692 | return false; |
1693 | } | 1693 | } |
1694 | } | 1694 | } |
1695 | 1695 | ||
1696 | if (FrameName.size() != 0) | 1696 | if (FrameName.size() != 0) |
1697 | { | 1697 | { |
1698 | #ifdef _XREADER_DEBUG | 1698 | #ifdef _XREADER_DEBUG |
1699 | os::Printer::log("frame name", FrameName.c_str(), ELL_DEBUG); | 1699 | os::Printer::log("frame name", FrameName.c_str(), ELL_DEBUG); |
1700 | #endif | 1700 | #endif |
1701 | CSkinnedMesh::SJoint *joint=0; | 1701 | CSkinnedMesh::SJoint *joint=0; |
1702 | 1702 | ||
1703 | u32 n; | 1703 | u32 n; |
1704 | for (n=0; n < AnimatedMesh->getAllJoints().size(); ++n) | 1704 | for (n=0; n < AnimatedMesh->getAllJoints().size(); ++n) |
1705 | { | 1705 | { |
1706 | if (AnimatedMesh->getAllJoints()[n]->Name==FrameName) | 1706 | if (AnimatedMesh->getAllJoints()[n]->Name==FrameName) |
1707 | { | 1707 | { |
1708 | joint=AnimatedMesh->getAllJoints()[n]; | 1708 | joint=AnimatedMesh->getAllJoints()[n]; |
1709 | break; | 1709 | break; |
1710 | } | 1710 | } |
1711 | } | 1711 | } |
1712 | 1712 | ||
1713 | if (!joint) | 1713 | if (!joint) |
1714 | { | 1714 | { |
1715 | #ifdef _XREADER_DEBUG | 1715 | #ifdef _XREADER_DEBUG |
1716 | os::Printer::log("creating joint for animation ", FrameName.c_str(), ELL_DEBUG); | 1716 | os::Printer::log("creating joint for animation ", FrameName.c_str(), ELL_DEBUG); |
1717 | #endif | 1717 | #endif |
1718 | joint=AnimatedMesh->addJoint(0); | 1718 | joint=AnimatedMesh->addJoint(0); |
1719 | joint->Name=FrameName; | 1719 | joint->Name=FrameName; |
1720 | } | 1720 | } |
1721 | 1721 | ||
1722 | joint->PositionKeys.reallocate(joint->PositionKeys.size()+animationDump.PositionKeys.size()); | 1722 | joint->PositionKeys.reallocate(joint->PositionKeys.size()+animationDump.PositionKeys.size()); |
1723 | for (n=0; n<animationDump.PositionKeys.size(); ++n) | 1723 | for (n=0; n<animationDump.PositionKeys.size(); ++n) |
1724 | { | 1724 | { |
1725 | joint->PositionKeys.push_back(animationDump.PositionKeys[n]); | 1725 | joint->PositionKeys.push_back(animationDump.PositionKeys[n]); |
1726 | } | 1726 | } |
1727 | 1727 | ||
1728 | joint->ScaleKeys.reallocate(joint->ScaleKeys.size()+animationDump.ScaleKeys.size()); | 1728 | joint->ScaleKeys.reallocate(joint->ScaleKeys.size()+animationDump.ScaleKeys.size()); |
1729 | for (n=0; n<animationDump.ScaleKeys.size(); ++n) | 1729 | for (n=0; n<animationDump.ScaleKeys.size(); ++n) |
1730 | { | 1730 | { |
1731 | joint->ScaleKeys.push_back(animationDump.ScaleKeys[n]); | 1731 | joint->ScaleKeys.push_back(animationDump.ScaleKeys[n]); |
1732 | } | 1732 | } |
1733 | 1733 | ||
1734 | joint->RotationKeys.reallocate(joint->RotationKeys.size()+animationDump.RotationKeys.size()); | 1734 | joint->RotationKeys.reallocate(joint->RotationKeys.size()+animationDump.RotationKeys.size()); |
1735 | for (n=0; n<animationDump.RotationKeys.size(); ++n) | 1735 | for (n=0; n<animationDump.RotationKeys.size(); ++n) |
1736 | { | 1736 | { |
1737 | joint->RotationKeys.push_back(animationDump.RotationKeys[n]); | 1737 | joint->RotationKeys.push_back(animationDump.RotationKeys[n]); |
1738 | } | 1738 | } |
1739 | } | 1739 | } |
1740 | else | 1740 | else |
1741 | os::Printer::log("joint name was never given", ELL_WARNING); | 1741 | os::Printer::log("joint name was never given", ELL_WARNING); |
1742 | 1742 | ||
1743 | return true; | 1743 | return true; |
1744 | } | 1744 | } |
1745 | 1745 | ||
1746 | 1746 | ||
1747 | bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint) | 1747 | bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint) |
1748 | { | 1748 | { |
1749 | #ifdef _XREADER_DEBUG | 1749 | #ifdef _XREADER_DEBUG |
1750 | os::Printer::log("CXFileReader: reading animation key", ELL_DEBUG); | 1750 | os::Printer::log("CXFileReader: reading animation key", ELL_DEBUG); |
1751 | #endif | 1751 | #endif |
1752 | 1752 | ||
1753 | if (!readHeadOfDataObject()) | 1753 | if (!readHeadOfDataObject()) |
1754 | { | 1754 | { |
1755 | os::Printer::log("No opening brace in Animation Key found in x file", ELL_WARNING); | 1755 | os::Printer::log("No opening brace in Animation Key found in x file", ELL_WARNING); |
1756 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1756 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1757 | return false; | 1757 | return false; |
1758 | } | 1758 | } |
1759 | 1759 | ||
1760 | // read key type | 1760 | // read key type |
1761 | 1761 | ||
1762 | const u32 keyType = readInt(); | 1762 | const u32 keyType = readInt(); |
1763 | 1763 | ||
1764 | if (keyType > 4) | 1764 | if (keyType > 4) |
1765 | { | 1765 | { |
1766 | os::Printer::log("Unknown key type found in Animation Key in x file", ELL_WARNING); | 1766 | os::Printer::log("Unknown key type found in Animation Key in x file", ELL_WARNING); |
1767 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1767 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1768 | return false; | 1768 | return false; |
1769 | } | 1769 | } |
1770 | 1770 | ||
1771 | // read number of keys | 1771 | // read number of keys |
1772 | const u32 numberOfKeys = readInt(); | 1772 | const u32 numberOfKeys = readInt(); |
1773 | 1773 | ||
1774 | // eat the semicolon after the "0". if there are keys present, readInt() | 1774 | // eat the semicolon after the "0". if there are keys present, readInt() |
1775 | // does this for us. If there aren't, we need to do it explicitly | 1775 | // does this for us. If there aren't, we need to do it explicitly |
1776 | if (numberOfKeys == 0) | 1776 | if (numberOfKeys == 0) |
1777 | checkForOneFollowingSemicolons(); | 1777 | checkForOneFollowingSemicolons(); |
1778 | 1778 | ||
1779 | for (u32 i=0; i<numberOfKeys; ++i) | 1779 | for (u32 i=0; i<numberOfKeys; ++i) |
1780 | { | 1780 | { |
1781 | // read time | 1781 | // read time |
1782 | const f32 time = (f32)readInt(); | 1782 | const f32 time = (f32)readInt(); |
1783 | 1783 | ||
1784 | // read keys | 1784 | // read keys |
1785 | switch(keyType) | 1785 | switch(keyType) |
1786 | { | 1786 | { |
1787 | case 0: //rotation | 1787 | case 0: //rotation |
1788 | { | 1788 | { |
1789 | //read quaternions | 1789 | //read quaternions |
1790 | 1790 | ||
1791 | // read count | 1791 | // read count |
1792 | if (readInt() != 4) | 1792 | if (readInt() != 4) |
1793 | { | 1793 | { |
1794 | os::Printer::log("Expected 4 numbers in animation key in x file", ELL_WARNING); | 1794 | os::Printer::log("Expected 4 numbers in animation key in x file", ELL_WARNING); |
1795 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1795 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1796 | return false; | 1796 | return false; |
1797 | } | 1797 | } |
1798 | 1798 | ||
1799 | f32 W = -readFloat(); | 1799 | f32 W = -readFloat(); |
1800 | f32 X = -readFloat(); | 1800 | f32 X = -readFloat(); |
1801 | f32 Y = -readFloat(); | 1801 | f32 Y = -readFloat(); |
1802 | f32 Z = -readFloat(); | 1802 | f32 Z = -readFloat(); |
1803 | 1803 | ||
1804 | if (!checkForTwoFollowingSemicolons()) | 1804 | if (!checkForTwoFollowingSemicolons()) |
1805 | { | 1805 | { |
1806 | os::Printer::log("No finishing semicolon after quaternion animation key in x file", ELL_WARNING); | 1806 | os::Printer::log("No finishing semicolon after quaternion animation key in x file", ELL_WARNING); |
1807 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1807 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1808 | } | 1808 | } |
1809 | 1809 | ||
1810 | ISkinnedMesh::SRotationKey *key=AnimatedMesh->addRotationKey(joint); | 1810 | ISkinnedMesh::SRotationKey *key=AnimatedMesh->addRotationKey(joint); |
1811 | key->frame=time; | 1811 | key->frame=time; |
1812 | key->rotation.set(X,Y,Z,W); | 1812 | key->rotation.set(X,Y,Z,W); |
1813 | } | 1813 | } |
1814 | break; | 1814 | break; |
1815 | case 1: //scale | 1815 | case 1: //scale |
1816 | case 2: //position | 1816 | case 2: //position |
1817 | { | 1817 | { |
1818 | // read vectors | 1818 | // read vectors |
1819 | 1819 | ||
1820 | // read count | 1820 | // read count |
1821 | if (readInt() != 3) | 1821 | if (readInt() != 3) |
1822 | { | 1822 | { |
1823 | os::Printer::log("Expected 3 numbers in animation key in x file", ELL_WARNING); | 1823 | os::Printer::log("Expected 3 numbers in animation key in x file", ELL_WARNING); |
1824 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1824 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1825 | return false; | 1825 | return false; |
1826 | } | 1826 | } |
1827 | 1827 | ||
1828 | core::vector3df vector; | 1828 | core::vector3df vector; |
1829 | readVector3(vector); | 1829 | readVector3(vector); |
1830 | 1830 | ||
1831 | if (!checkForTwoFollowingSemicolons()) | 1831 | if (!checkForTwoFollowingSemicolons()) |
1832 | { | 1832 | { |
1833 | os::Printer::log("No finishing semicolon after vector animation key in x file", ELL_WARNING); | 1833 | os::Printer::log("No finishing semicolon after vector animation key in x file", ELL_WARNING); |
1834 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1834 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1835 | } | 1835 | } |
1836 | 1836 | ||
1837 | if (keyType==2) | 1837 | if (keyType==2) |
1838 | { | 1838 | { |
1839 | ISkinnedMesh::SPositionKey *key=AnimatedMesh->addPositionKey(joint); | 1839 | ISkinnedMesh::SPositionKey *key=AnimatedMesh->addPositionKey(joint); |
1840 | key->frame=time; | 1840 | key->frame=time; |
1841 | key->position=vector; | 1841 | key->position=vector; |
1842 | } | 1842 | } |
1843 | else | 1843 | else |
1844 | { | 1844 | { |
1845 | ISkinnedMesh::SScaleKey *key=AnimatedMesh->addScaleKey(joint); | 1845 | ISkinnedMesh::SScaleKey *key=AnimatedMesh->addScaleKey(joint); |
1846 | key->frame=time; | 1846 | key->frame=time; |
1847 | key->scale=vector; | 1847 | key->scale=vector; |
1848 | } | 1848 | } |
1849 | } | 1849 | } |
1850 | break; | 1850 | break; |
1851 | case 3: | 1851 | case 3: |
1852 | case 4: | 1852 | case 4: |
1853 | { | 1853 | { |
1854 | // read matrix | 1854 | // read matrix |
1855 | 1855 | ||
1856 | // read count | 1856 | // read count |
1857 | if (readInt() != 16) | 1857 | if (readInt() != 16) |
1858 | { | 1858 | { |
1859 | os::Printer::log("Expected 16 numbers in animation key in x file", ELL_WARNING); | 1859 | os::Printer::log("Expected 16 numbers in animation key in x file", ELL_WARNING); |
1860 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1860 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1861 | return false; | 1861 | return false; |
1862 | } | 1862 | } |
1863 | 1863 | ||
1864 | // read matrix | 1864 | // read matrix |
1865 | core::matrix4 mat(core::matrix4::EM4CONST_NOTHING); | 1865 | core::matrix4 mat(core::matrix4::EM4CONST_NOTHING); |
1866 | readMatrix(mat); | 1866 | readMatrix(mat); |
1867 | 1867 | ||
1868 | //mat=joint->LocalMatrix*mat; | 1868 | //mat=joint->LocalMatrix*mat; |
1869 | 1869 | ||
1870 | if (!checkForOneFollowingSemicolons()) | 1870 | if (!checkForOneFollowingSemicolons()) |
1871 | { | 1871 | { |
1872 | os::Printer::log("No finishing semicolon after matrix animation key in x file", ELL_WARNING); | 1872 | os::Printer::log("No finishing semicolon after matrix animation key in x file", ELL_WARNING); |
1873 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1873 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1874 | } | 1874 | } |
1875 | 1875 | ||
1876 | //core::vector3df rotation = mat.getRotationDegrees(); | 1876 | //core::vector3df rotation = mat.getRotationDegrees(); |
1877 | 1877 | ||
1878 | ISkinnedMesh::SRotationKey *keyR=AnimatedMesh->addRotationKey(joint); | 1878 | ISkinnedMesh::SRotationKey *keyR=AnimatedMesh->addRotationKey(joint); |
1879 | keyR->frame=time; | 1879 | keyR->frame=time; |
1880 | 1880 | ||
1881 | // IRR_TEST_BROKEN_QUATERNION_USE: TODO - switched from mat to mat.getTransposed() for downward compatibility. | 1881 | // IRR_TEST_BROKEN_QUATERNION_USE: TODO - switched from mat to mat.getTransposed() for downward compatibility. |
1882 | // Not tested so far if this was correct or wrong before quaternion fix! | 1882 | // Not tested so far if this was correct or wrong before quaternion fix! |
1883 | keyR->rotation= core::quaternion(mat.getTransposed()); | 1883 | keyR->rotation= core::quaternion(mat.getTransposed()); |
1884 | 1884 | ||
1885 | ISkinnedMesh::SPositionKey *keyP=AnimatedMesh->addPositionKey(joint); | 1885 | ISkinnedMesh::SPositionKey *keyP=AnimatedMesh->addPositionKey(joint); |
1886 | keyP->frame=time; | 1886 | keyP->frame=time; |
1887 | keyP->position=mat.getTranslation(); | 1887 | keyP->position=mat.getTranslation(); |
1888 | 1888 | ||
1889 | /* | 1889 | /* |
1890 | core::vector3df scale=mat.getScale(); | 1890 | core::vector3df scale=mat.getScale(); |
1891 | 1891 | ||
1892 | if (scale.X==0) | 1892 | if (scale.X==0) |
1893 | scale.X=1; | 1893 | scale.X=1; |
1894 | if (scale.Y==0) | 1894 | if (scale.Y==0) |
1895 | scale.Y=1; | 1895 | scale.Y=1; |
1896 | if (scale.Z==0) | 1896 | if (scale.Z==0) |
1897 | scale.Z=1; | 1897 | scale.Z=1; |
1898 | ISkinnedMesh::SScaleKey *keyS=AnimatedMesh->addScaleKey(joint); | 1898 | ISkinnedMesh::SScaleKey *keyS=AnimatedMesh->addScaleKey(joint); |
1899 | keyS->frame=time; | 1899 | keyS->frame=time; |
1900 | keyS->scale=scale; | 1900 | keyS->scale=scale; |
1901 | */ | 1901 | */ |
1902 | } | 1902 | } |
1903 | break; | 1903 | break; |
1904 | } // end switch | 1904 | } // end switch |
1905 | } | 1905 | } |
1906 | 1906 | ||
1907 | if (!checkForOneFollowingSemicolons()) | 1907 | if (!checkForOneFollowingSemicolons()) |
1908 | --P; | 1908 | --P; |
1909 | 1909 | ||
1910 | if (!checkForClosingBrace()) | 1910 | if (!checkForClosingBrace()) |
1911 | { | 1911 | { |
1912 | os::Printer::log("No closing brace in animation key in x file", ELL_WARNING); | 1912 | os::Printer::log("No closing brace in animation key in x file", ELL_WARNING); |
1913 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1913 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1914 | return false; | 1914 | return false; |
1915 | } | 1915 | } |
1916 | 1916 | ||
1917 | return true; | 1917 | return true; |
1918 | } | 1918 | } |
1919 | 1919 | ||
1920 | 1920 | ||
1921 | bool CXMeshFileLoader::parseDataObjectTextureFilename(core::stringc& texturename) | 1921 | bool CXMeshFileLoader::parseDataObjectTextureFilename(core::stringc& texturename) |
1922 | { | 1922 | { |
1923 | #ifdef _XREADER_DEBUG | 1923 | #ifdef _XREADER_DEBUG |
1924 | os::Printer::log("CXFileReader: reading texture filename", ELL_DEBUG); | 1924 | os::Printer::log("CXFileReader: reading texture filename", ELL_DEBUG); |
1925 | #endif | 1925 | #endif |
1926 | 1926 | ||
1927 | if (!readHeadOfDataObject()) | 1927 | if (!readHeadOfDataObject()) |
1928 | { | 1928 | { |
1929 | os::Printer::log("No opening brace in Texture filename found in x file", ELL_WARNING); | 1929 | os::Printer::log("No opening brace in Texture filename found in x file", ELL_WARNING); |
1930 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1930 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1931 | return false; | 1931 | return false; |
1932 | } | 1932 | } |
1933 | 1933 | ||
1934 | if (!getNextTokenAsString(texturename)) | 1934 | if (!getNextTokenAsString(texturename)) |
1935 | { | 1935 | { |
1936 | os::Printer::log("Unknown syntax while reading texture filename string in x file", ELL_WARNING); | 1936 | os::Printer::log("Unknown syntax while reading texture filename string in x file", ELL_WARNING); |
1937 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1937 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1938 | return false; | 1938 | return false; |
1939 | } | 1939 | } |
1940 | 1940 | ||
1941 | if (!checkForClosingBrace()) | 1941 | if (!checkForClosingBrace()) |
1942 | { | 1942 | { |
1943 | os::Printer::log("No closing brace in Texture filename found in x file", ELL_WARNING); | 1943 | os::Printer::log("No closing brace in Texture filename found in x file", ELL_WARNING); |
1944 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); | 1944 | os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); |
1945 | return false; | 1945 | return false; |
1946 | } | 1946 | } |
1947 | 1947 | ||
1948 | return true; | 1948 | return true; |
1949 | } | 1949 | } |
1950 | 1950 | ||
1951 | 1951 | ||
1952 | bool CXMeshFileLoader::parseUnknownDataObject() | 1952 | bool CXMeshFileLoader::parseUnknownDataObject() |
1953 | { | 1953 | { |
1954 | // find opening delimiter | 1954 | // find opening delimiter |
1955 | while(true) | 1955 | while(true) |
1956 | { | 1956 | { |
1957 | core::stringc t = getNextToken(); | 1957 | core::stringc t = getNextToken(); |
1958 | 1958 | ||
1959 | if (t.size() == 0) | 1959 | if (t.size() == 0) |
1960 | return false; | 1960 | return false; |
1961 | 1961 | ||
1962 | if (t == "{") | 1962 | if (t == "{") |
1963 | break; | 1963 | break; |
1964 | } | 1964 | } |
1965 | 1965 | ||
1966 | u32 counter = 1; | 1966 | u32 counter = 1; |
1967 | 1967 | ||
1968 | // parse until closing delimiter | 1968 | // parse until closing delimiter |
1969 | 1969 | ||
1970 | while(counter) | 1970 | while(counter) |
1971 | { | 1971 | { |
1972 | core::stringc t = getNextToken(); | 1972 | core::stringc t = getNextToken(); |
1973 | 1973 | ||
1974 | if (t.size() == 0) | 1974 | if (t.size() == 0) |
1975 | return false; | 1975 | return false; |
1976 | 1976 | ||
1977 | if (t == "{") | 1977 | if (t == "{") |
1978 | ++counter; | 1978 | ++counter; |
1979 | else | 1979 | else |
1980 | if (t == "}") | 1980 | if (t == "}") |
1981 | --counter; | 1981 | --counter; |
1982 | } | 1982 | } |
1983 | 1983 | ||
1984 | return true; | 1984 | return true; |
1985 | } | 1985 | } |
1986 | 1986 | ||
1987 | 1987 | ||
1988 | //! checks for closing curly brace, returns false if not there | 1988 | //! checks for closing curly brace, returns false if not there |
1989 | bool CXMeshFileLoader::checkForClosingBrace() | 1989 | bool CXMeshFileLoader::checkForClosingBrace() |
1990 | { | 1990 | { |
1991 | return (getNextToken() == "}"); | 1991 | return (getNextToken() == "}"); |
1992 | } | 1992 | } |
1993 | 1993 | ||
1994 | 1994 | ||
1995 | //! checks for one following semicolon, returns false if not there | 1995 | //! checks for one following semicolon, returns false if not there |
1996 | bool CXMeshFileLoader::checkForOneFollowingSemicolons() | 1996 | bool CXMeshFileLoader::checkForOneFollowingSemicolons() |
1997 | { | 1997 | { |
1998 | if (BinaryFormat) | 1998 | if (BinaryFormat) |
1999 | return true; | 1999 | return true; |
2000 | 2000 | ||
2001 | if (getNextToken() == ";") | 2001 | if (getNextToken() == ";") |
2002 | return true; | 2002 | return true; |
2003 | else | 2003 | else |
2004 | { | 2004 | { |
2005 | --P; | 2005 | --P; |
2006 | return false; | 2006 | return false; |
2007 | } | 2007 | } |
2008 | } | 2008 | } |
2009 | 2009 | ||
2010 | 2010 | ||
2011 | //! checks for two following semicolons, returns false if they are not there | 2011 | //! checks for two following semicolons, returns false if they are not there |
2012 | bool CXMeshFileLoader::checkForTwoFollowingSemicolons() | 2012 | bool CXMeshFileLoader::checkForTwoFollowingSemicolons() |
2013 | { | 2013 | { |
2014 | if (BinaryFormat) | 2014 | if (BinaryFormat) |
2015 | return true; | 2015 | return true; |
2016 | 2016 | ||
2017 | for (u32 k=0; k<2; ++k) | 2017 | for (u32 k=0; k<2; ++k) |
2018 | { | 2018 | { |
2019 | if (getNextToken() != ";") | 2019 | if (getNextToken() != ";") |
2020 | { | 2020 | { |
2021 | --P; | 2021 | --P; |
2022 | return false; | 2022 | return false; |
2023 | } | 2023 | } |
2024 | } | 2024 | } |
2025 | 2025 | ||
2026 | return true; | 2026 | return true; |
2027 | } | 2027 | } |
2028 | 2028 | ||
2029 | 2029 | ||
2030 | //! reads header of dataobject including the opening brace. | 2030 | //! reads header of dataobject including the opening brace. |
2031 | //! returns false if error happened, and writes name of object | 2031 | //! returns false if error happened, and writes name of object |
2032 | //! if there is one | 2032 | //! if there is one |
2033 | bool CXMeshFileLoader::readHeadOfDataObject(core::stringc* outname) | 2033 | bool CXMeshFileLoader::readHeadOfDataObject(core::stringc* outname) |
2034 | { | 2034 | { |
2035 | core::stringc nameOrBrace = getNextToken(); | 2035 | core::stringc nameOrBrace = getNextToken(); |
2036 | if (nameOrBrace != "{") | 2036 | if (nameOrBrace != "{") |
2037 | { | 2037 | { |
2038 | if (outname) | 2038 | if (outname) |
2039 | (*outname) = nameOrBrace; | 2039 | (*outname) = nameOrBrace; |
2040 | 2040 | ||
2041 | if (getNextToken() != "{") | 2041 | if (getNextToken() != "{") |
2042 | return false; | 2042 | return false; |
2043 | } | 2043 | } |
2044 | 2044 | ||
2045 | return true; | 2045 | return true; |
2046 | } | 2046 | } |
2047 | 2047 | ||
2048 | 2048 | ||
2049 | //! returns next parseable token. Returns empty string if no token there | 2049 | //! returns next parseable token. Returns empty string if no token there |
2050 | core::stringc CXMeshFileLoader::getNextToken() | 2050 | core::stringc CXMeshFileLoader::getNextToken() |
2051 | { | 2051 | { |
2052 | core::stringc s; | 2052 | core::stringc s; |
2053 | 2053 | ||
2054 | // process binary-formatted file | 2054 | // process binary-formatted file |
2055 | if (BinaryFormat) | 2055 | if (BinaryFormat) |
2056 | { | 2056 | { |
2057 | // in binary mode it will only return NAME and STRING token | 2057 | // in binary mode it will only return NAME and STRING token |
2058 | // and (correctly) skip over other tokens. | 2058 | // and (correctly) skip over other tokens. |
2059 | 2059 | ||
2060 | s16 tok = readBinWord(); | 2060 | s16 tok = readBinWord(); |
2061 | u32 len; | 2061 | u32 len; |
2062 | 2062 | ||
2063 | // standalone tokens | 2063 | // standalone tokens |
2064 | switch (tok) { | 2064 | switch (tok) { |
2065 | case 1: | 2065 | case 1: |
2066 | // name token | 2066 | // name token |
2067 | len = readBinDWord(); | 2067 | len = readBinDWord(); |
2068 | s = core::stringc(P, len); | 2068 | s = core::stringc(P, len); |
2069 | P += len; | 2069 | P += len; |
2070 | return s; | 2070 | return s; |
2071 | case 2: | 2071 | case 2: |
2072 | // string token | 2072 | // string token |
2073 | len = readBinDWord(); | 2073 | len = readBinDWord(); |
2074 | s = core::stringc(P, len); | 2074 | s = core::stringc(P, len); |
2075 | P += (len + 2); | 2075 | P += (len + 2); |
2076 | return s; | 2076 | return s; |
2077 | case 3: | 2077 | case 3: |
2078 | // integer token | 2078 | // integer token |
2079 | P += 4; | 2079 | P += 4; |
2080 | return "<integer>"; | 2080 | return "<integer>"; |
2081 | case 5: | 2081 | case 5: |
2082 | // GUID token | 2082 | // GUID token |
2083 | P += 16; | 2083 | P += 16; |
2084 | return "<guid>"; | 2084 | return "<guid>"; |
2085 | case 6: | 2085 | case 6: |
2086 | len = readBinDWord(); | 2086 | len = readBinDWord(); |
2087 | P += (len * 4); | 2087 | P += (len * 4); |
2088 | return "<int_list>"; | 2088 | return "<int_list>"; |
2089 | case 7: | 2089 | case 7: |
2090 | len = readBinDWord(); | 2090 | len = readBinDWord(); |
2091 | P += (len * FloatSize); | 2091 | P += (len * FloatSize); |
2092 | return "<flt_list>"; | 2092 | return "<flt_list>"; |
2093 | case 0x0a: | 2093 | case 0x0a: |
2094 | return "{"; | 2094 | return "{"; |
2095 | case 0x0b: | 2095 | case 0x0b: |
2096 | return "}"; | 2096 | return "}"; |
2097 | case 0x0c: | 2097 | case 0x0c: |
2098 | return "("; | 2098 | return "("; |
2099 | case 0x0d: | 2099 | case 0x0d: |
2100 | return ")"; | 2100 | return ")"; |
2101 | case 0x0e: | 2101 | case 0x0e: |
2102 | return "["; | 2102 | return "["; |
2103 | case 0x0f: | 2103 | case 0x0f: |
2104 | return "]"; | 2104 | return "]"; |
2105 | case 0x10: | 2105 | case 0x10: |
2106 | return "<"; | 2106 | return "<"; |
2107 | case 0x11: | 2107 | case 0x11: |
2108 | return ">"; | 2108 | return ">"; |
2109 | case 0x12: | 2109 | case 0x12: |
2110 | return "."; | 2110 | return "."; |
2111 | case 0x13: | 2111 | case 0x13: |
2112 | return ","; | 2112 | return ","; |
2113 | case 0x14: | 2113 | case 0x14: |
2114 | return ";"; | 2114 | return ";"; |
2115 | case 0x1f: | 2115 | case 0x1f: |
2116 | return "template"; | 2116 | return "template"; |
2117 | case 0x28: | 2117 | case 0x28: |
2118 | return "WORD"; | 2118 | return "WORD"; |
2119 | case 0x29: | 2119 | case 0x29: |
2120 | return "DWORD"; | 2120 | return "DWORD"; |
2121 | case 0x2a: | 2121 | case 0x2a: |
2122 | return "FLOAT"; | 2122 | return "FLOAT"; |
2123 | case 0x2b: | 2123 | case 0x2b: |
2124 | return "DOUBLE"; | 2124 | return "DOUBLE"; |
2125 | case 0x2c: | 2125 | case 0x2c: |
2126 | return "CHAR"; | 2126 | return "CHAR"; |
2127 | case 0x2d: | 2127 | case 0x2d: |
2128 | return "UCHAR"; | 2128 | return "UCHAR"; |
2129 | case 0x2e: | 2129 | case 0x2e: |
2130 | return "SWORD"; | 2130 | return "SWORD"; |
2131 | case 0x2f: | 2131 | case 0x2f: |
2132 | return "SDWORD"; | 2132 | return "SDWORD"; |
2133 | case 0x30: | 2133 | case 0x30: |
2134 | return "void"; | 2134 | return "void"; |
2135 | case 0x31: | 2135 | case 0x31: |
2136 | return "string"; | 2136 | return "string"; |
2137 | case 0x32: | 2137 | case 0x32: |
2138 | return "unicode"; | 2138 | return "unicode"; |
2139 | case 0x33: | 2139 | case 0x33: |
2140 | return "cstring"; | 2140 | return "cstring"; |
2141 | case 0x34: | 2141 | case 0x34: |
2142 | return "array"; | 2142 | return "array"; |
2143 | } | 2143 | } |
2144 | } | 2144 | } |
2145 | // process text-formatted file | 2145 | // process text-formatted file |
2146 | else | 2146 | else |
2147 | { | 2147 | { |
2148 | findNextNoneWhiteSpace(); | 2148 | findNextNoneWhiteSpace(); |
2149 | 2149 | ||
2150 | if (P >= End) | 2150 | if (P >= End) |
2151 | return s; | 2151 | return s; |
2152 | 2152 | ||
2153 | while((P < End) && !core::isspace(P[0])) | 2153 | while((P < End) && !core::isspace(P[0])) |
2154 | { | 2154 | { |
2155 | // either keep token delimiters when already holding a token, or return if first valid char | 2155 | // either keep token delimiters when already holding a token, or return if first valid char |
2156 | if (P[0]==';' || P[0]=='}' || P[0]=='{' || P[0]==',') | 2156 | if (P[0]==';' || P[0]=='}' || P[0]=='{' || P[0]==',') |
2157 | { | 2157 | { |
2158 | if (!s.size()) | 2158 | if (!s.size()) |
2159 | { | 2159 | { |
2160 | s.append(P[0]); | 2160 | s.append(P[0]); |
2161 | ++P; | 2161 | ++P; |
2162 | } | 2162 | } |
2163 | break; // stop for delimiter | 2163 | break; // stop for delimiter |
2164 | } | 2164 | } |
2165 | s.append(P[0]); | 2165 | s.append(P[0]); |
2166 | ++P; | 2166 | ++P; |
2167 | } | 2167 | } |
2168 | } | 2168 | } |
2169 | return s; | 2169 | return s; |
2170 | } | 2170 | } |
2171 | 2171 | ||
2172 | 2172 | ||
2173 | //! places pointer to next begin of a token, which must be a number, | 2173 | //! places pointer to next begin of a token, which must be a number, |
2174 | // and ignores comments | 2174 | // and ignores comments |
2175 | void CXMeshFileLoader::findNextNoneWhiteSpaceNumber() | 2175 | void CXMeshFileLoader::findNextNoneWhiteSpaceNumber() |
2176 | { | 2176 | { |
2177 | if (BinaryFormat) | 2177 | if (BinaryFormat) |
2178 | return; | 2178 | return; |
2179 | 2179 | ||
2180 | while((P < End) && (P[0] != '-') && (P[0] != '.') && | 2180 | while((P < End) && (P[0] != '-') && (P[0] != '.') && |
2181 | !( core::isdigit(P[0]))) | 2181 | !( core::isdigit(P[0]))) |
2182 | { | 2182 | { |
2183 | // check if this is a comment | 2183 | // check if this is a comment |
2184 | if ((P[0] == '/' && P[1] == '/') || P[0] == '#') | 2184 | if ((P[0] == '/' && P[1] == '/') || P[0] == '#') |
2185 | readUntilEndOfLine(); | 2185 | readUntilEndOfLine(); |
2186 | else | 2186 | else |
2187 | ++P; | 2187 | ++P; |
2188 | } | 2188 | } |
2189 | } | 2189 | } |
2190 | 2190 | ||
2191 | 2191 | ||
2192 | // places pointer to next begin of a token, and ignores comments | 2192 | // places pointer to next begin of a token, and ignores comments |
2193 | void CXMeshFileLoader::findNextNoneWhiteSpace() | 2193 | void CXMeshFileLoader::findNextNoneWhiteSpace() |
2194 | { | 2194 | { |
2195 | if (BinaryFormat) | 2195 | if (BinaryFormat) |
2196 | return; | 2196 | return; |
2197 | 2197 | ||
2198 | while(true) | 2198 | while(true) |
2199 | { | 2199 | { |
2200 | while((P < End) && core::isspace(P[0])) | 2200 | while((P < End) && core::isspace(P[0])) |
2201 | { | 2201 | { |
2202 | if (*P=='\n') | 2202 | if (*P=='\n') |
2203 | ++Line; | 2203 | ++Line; |
2204 | ++P; | 2204 | ++P; |
2205 | } | 2205 | } |
2206 | 2206 | ||
2207 | if (P >= End) | 2207 | if (P >= End) |
2208 | return; | 2208 | return; |
2209 | 2209 | ||
2210 | // check if this is a comment | 2210 | // check if this is a comment |
2211 | if ((P[0] == '/' && P[1] == '/') || | 2211 | if ((P[0] == '/' && P[1] == '/') || |
2212 | P[0] == '#') | 2212 | P[0] == '#') |
2213 | readUntilEndOfLine(); | 2213 | readUntilEndOfLine(); |
2214 | else | 2214 | else |
2215 | break; | 2215 | break; |
2216 | } | 2216 | } |
2217 | } | 2217 | } |
2218 | 2218 | ||
2219 | 2219 | ||
2220 | //! reads a x file style string | 2220 | //! reads a x file style string |
2221 | bool CXMeshFileLoader::getNextTokenAsString(core::stringc& out) | 2221 | bool CXMeshFileLoader::getNextTokenAsString(core::stringc& out) |
2222 | { | 2222 | { |
2223 | if (BinaryFormat) | 2223 | if (BinaryFormat) |
2224 | { | 2224 | { |
2225 | out=getNextToken(); | 2225 | out=getNextToken(); |
2226 | return true; | 2226 | return true; |
2227 | } | 2227 | } |
2228 | findNextNoneWhiteSpace(); | 2228 | findNextNoneWhiteSpace(); |
2229 | 2229 | ||
2230 | if (P >= End) | 2230 | if (P >= End) |
2231 | return false; | 2231 | return false; |
2232 | 2232 | ||
2233 | if (P[0] != '"') | 2233 | if (P[0] != '"') |
2234 | return false; | 2234 | return false; |
2235 | ++P; | 2235 | ++P; |
2236 | 2236 | ||
2237 | while(P < End && P[0]!='"') | 2237 | while(P < End && P[0]!='"') |
2238 | { | 2238 | { |
2239 | out.append(P[0]); | 2239 | out.append(P[0]); |
2240 | ++P; | 2240 | ++P; |
2241 | } | 2241 | } |
2242 | 2242 | ||
2243 | if ( P[1] != ';' || P[0] != '"') | 2243 | if ( P[1] != ';' || P[0] != '"') |
2244 | return false; | 2244 | return false; |
2245 | P+=2; | 2245 | P+=2; |
2246 | 2246 | ||
2247 | return true; | 2247 | return true; |
2248 | } | 2248 | } |
2249 | 2249 | ||
2250 | 2250 | ||
2251 | void CXMeshFileLoader::readUntilEndOfLine() | 2251 | void CXMeshFileLoader::readUntilEndOfLine() |
2252 | { | 2252 | { |
2253 | if (BinaryFormat) | 2253 | if (BinaryFormat) |
2254 | return; | 2254 | return; |
2255 | 2255 | ||
2256 | while(P < End) | 2256 | while(P < End) |
2257 | { | 2257 | { |
2258 | if (P[0] == '\n' || P[0] == '\r') | 2258 | if (P[0] == '\n' || P[0] == '\r') |
2259 | { | 2259 | { |
2260 | ++P; | 2260 | ++P; |
2261 | ++Line; | 2261 | ++Line; |
2262 | return; | 2262 | return; |
2263 | } | 2263 | } |
2264 | 2264 | ||
2265 | ++P; | 2265 | ++P; |
2266 | } | 2266 | } |
2267 | } | 2267 | } |
2268 | 2268 | ||
2269 | 2269 | ||
2270 | u16 CXMeshFileLoader::readBinWord() | 2270 | u16 CXMeshFileLoader::readBinWord() |
2271 | { | 2271 | { |
2272 | #ifdef __BIG_ENDIAN__ | 2272 | #ifdef __BIG_ENDIAN__ |
2273 | const u16 tmp = os::Byteswap::byteswap(*(u16 *)P); | 2273 | const u16 tmp = os::Byteswap::byteswap(*(u16 *)P); |
2274 | #else | 2274 | #else |
2275 | const u16 tmp = *(u16 *)P; | 2275 | const u16 tmp = *(u16 *)P; |
2276 | #endif | 2276 | #endif |
2277 | P += 2; | 2277 | P += 2; |
2278 | return tmp; | 2278 | return tmp; |
2279 | } | 2279 | } |
2280 | 2280 | ||
2281 | 2281 | ||
2282 | u32 CXMeshFileLoader::readBinDWord() | 2282 | u32 CXMeshFileLoader::readBinDWord() |
2283 | { | 2283 | { |
2284 | #ifdef __BIG_ENDIAN__ | 2284 | #ifdef __BIG_ENDIAN__ |
2285 | const u32 tmp = os::Byteswap::byteswap(*(u32 *)P); | 2285 | const u32 tmp = os::Byteswap::byteswap(*(u32 *)P); |
2286 | #else | 2286 | #else |
2287 | const u32 tmp = *(u32 *)P; | 2287 | const u32 tmp = *(u32 *)P; |
2288 | #endif | 2288 | #endif |
2289 | P += 4; | 2289 | P += 4; |
2290 | return tmp; | 2290 | return tmp; |
2291 | } | 2291 | } |
2292 | 2292 | ||
2293 | 2293 | ||
2294 | u32 CXMeshFileLoader::readInt() | 2294 | u32 CXMeshFileLoader::readInt() |
2295 | { | 2295 | { |
2296 | if (BinaryFormat) | 2296 | if (BinaryFormat) |
2297 | { | 2297 | { |
2298 | if (!BinaryNumCount) | 2298 | if (!BinaryNumCount) |
2299 | { | 2299 | { |
2300 | const u16 tmp = readBinWord(); // 0x06 or 0x03 | 2300 | const u16 tmp = readBinWord(); // 0x06 or 0x03 |
2301 | if (tmp == 0x06) | 2301 | if (tmp == 0x06) |
2302 | BinaryNumCount = readBinDWord(); | 2302 | BinaryNumCount = readBinDWord(); |
2303 | else | 2303 | else |
2304 | BinaryNumCount = 1; // single int | 2304 | BinaryNumCount = 1; // single int |
2305 | } | 2305 | } |
2306 | --BinaryNumCount; | 2306 | --BinaryNumCount; |
2307 | return readBinDWord(); | 2307 | return readBinDWord(); |
2308 | } | 2308 | } |
2309 | else | 2309 | else |
2310 | { | 2310 | { |
2311 | findNextNoneWhiteSpaceNumber(); | 2311 | findNextNoneWhiteSpaceNumber(); |
2312 | return core::strtoul10(P, &P); | 2312 | return core::strtoul10(P, &P); |
2313 | } | 2313 | } |
2314 | } | 2314 | } |
2315 | 2315 | ||
2316 | 2316 | ||
2317 | f32 CXMeshFileLoader::readFloat() | 2317 | f32 CXMeshFileLoader::readFloat() |
2318 | { | 2318 | { |
2319 | if (BinaryFormat) | 2319 | if (BinaryFormat) |
2320 | { | 2320 | { |
2321 | if (!BinaryNumCount) | 2321 | if (!BinaryNumCount) |
2322 | { | 2322 | { |
2323 | const u16 tmp = readBinWord(); // 0x07 or 0x42 | 2323 | const u16 tmp = readBinWord(); // 0x07 or 0x42 |
2324 | if (tmp == 0x07) | 2324 | if (tmp == 0x07) |
2325 | BinaryNumCount = readBinDWord(); | 2325 | BinaryNumCount = readBinDWord(); |
2326 | else | 2326 | else |
2327 | BinaryNumCount = 1; // single int | 2327 | BinaryNumCount = 1; // single int |
2328 | } | 2328 | } |
2329 | --BinaryNumCount; | 2329 | --BinaryNumCount; |
2330 | if (FloatSize == 8) | 2330 | if (FloatSize == 8) |
2331 | { | 2331 | { |
2332 | #ifdef __BIG_ENDIAN__ | 2332 | #ifdef __BIG_ENDIAN__ |
2333 | //TODO: Check if data is properly converted here | 2333 | //TODO: Check if data is properly converted here |
2334 | f32 ctmp[2]; | 2334 | f32 ctmp[2]; |
2335 | ctmp[1] = os::Byteswap::byteswap(*(f32*)P); | 2335 | ctmp[1] = os::Byteswap::byteswap(*(f32*)P); |
2336 | ctmp[0] = os::Byteswap::byteswap(*(f32*)P+4); | 2336 | ctmp[0] = os::Byteswap::byteswap(*(f32*)P+4); |
2337 | const f32 tmp = (f32)(*(f64*)(void*)ctmp); | 2337 | const f32 tmp = (f32)(*(f64*)(void*)ctmp); |
2338 | #else | 2338 | #else |
2339 | const f32 tmp = (f32)(*(f64 *)P); | 2339 | const f32 tmp = (f32)(*(f64 *)P); |
2340 | #endif | 2340 | #endif |
2341 | P += 8; | 2341 | P += 8; |
2342 | return tmp; | 2342 | return tmp; |
2343 | } | 2343 | } |
2344 | else | 2344 | else |
2345 | { | 2345 | { |
2346 | #ifdef __BIG_ENDIAN__ | 2346 | #ifdef __BIG_ENDIAN__ |
2347 | const f32 tmp = os::Byteswap::byteswap(*(f32 *)P); | 2347 | const f32 tmp = os::Byteswap::byteswap(*(f32 *)P); |
2348 | #else | 2348 | #else |
2349 | const f32 tmp = *(f32 *)P; | 2349 | const f32 tmp = *(f32 *)P; |
2350 | #endif | 2350 | #endif |
2351 | P += 4; | 2351 | P += 4; |
2352 | return tmp; | 2352 | return tmp; |
2353 | } | 2353 | } |
2354 | } | 2354 | } |
2355 | findNextNoneWhiteSpaceNumber(); | 2355 | findNextNoneWhiteSpaceNumber(); |
2356 | f32 ftmp; | 2356 | f32 ftmp; |
2357 | P = core::fast_atof_move(P, ftmp); | 2357 | P = core::fast_atof_move(P, ftmp); |
2358 | return ftmp; | 2358 | return ftmp; |
2359 | } | 2359 | } |
2360 | 2360 | ||
2361 | 2361 | ||
2362 | // read 2-dimensional vector. Stops at semicolon after second value for text file format | 2362 | // read 2-dimensional vector. Stops at semicolon after second value for text file format |
2363 | bool CXMeshFileLoader::readVector2(core::vector2df& vec) | 2363 | bool CXMeshFileLoader::readVector2(core::vector2df& vec) |
2364 | { | 2364 | { |
2365 | vec.X = readFloat(); | 2365 | vec.X = readFloat(); |
2366 | vec.Y = readFloat(); | 2366 | vec.Y = readFloat(); |
2367 | return true; | 2367 | return true; |
2368 | } | 2368 | } |
2369 | 2369 | ||
2370 | 2370 | ||
2371 | // read 3-dimensional vector. Stops at semicolon after third value for text file format | 2371 | // read 3-dimensional vector. Stops at semicolon after third value for text file format |
2372 | bool CXMeshFileLoader::readVector3(core::vector3df& vec) | 2372 | bool CXMeshFileLoader::readVector3(core::vector3df& vec) |
2373 | { | 2373 | { |
2374 | vec.X = readFloat(); | 2374 | vec.X = readFloat(); |
2375 | vec.Y = readFloat(); | 2375 | vec.Y = readFloat(); |
2376 | vec.Z = readFloat(); | 2376 | vec.Z = readFloat(); |
2377 | return true; | 2377 | return true; |
2378 | } | 2378 | } |
2379 | 2379 | ||
2380 | 2380 | ||
2381 | // read color without alpha value. Stops after second semicolon after blue value | 2381 | // read color without alpha value. Stops after second semicolon after blue value |
2382 | bool CXMeshFileLoader::readRGB(video::SColor& color) | 2382 | bool CXMeshFileLoader::readRGB(video::SColor& color) |
2383 | { | 2383 | { |
2384 | video::SColorf tmpColor; | 2384 | video::SColorf tmpColor; |
2385 | tmpColor.r = readFloat(); | 2385 | tmpColor.r = readFloat(); |
2386 | tmpColor.g = readFloat(); | 2386 | tmpColor.g = readFloat(); |
2387 | tmpColor.b = readFloat(); | 2387 | tmpColor.b = readFloat(); |
2388 | color = tmpColor.toSColor(); | 2388 | color = tmpColor.toSColor(); |
2389 | return checkForOneFollowingSemicolons(); | 2389 | return checkForOneFollowingSemicolons(); |
2390 | } | 2390 | } |
2391 | 2391 | ||
2392 | 2392 | ||
2393 | // read color with alpha value. Stops after second semicolon after blue value | 2393 | // read color with alpha value. Stops after second semicolon after blue value |
2394 | bool CXMeshFileLoader::readRGBA(video::SColor& color) | 2394 | bool CXMeshFileLoader::readRGBA(video::SColor& color) |
2395 | { | 2395 | { |
2396 | video::SColorf tmpColor; | 2396 | video::SColorf tmpColor; |
2397 | tmpColor.r = readFloat(); | 2397 | tmpColor.r = readFloat(); |
2398 | tmpColor.g = readFloat(); | 2398 | tmpColor.g = readFloat(); |
2399 | tmpColor.b = readFloat(); | 2399 | tmpColor.b = readFloat(); |
2400 | tmpColor.a = readFloat(); | 2400 | tmpColor.a = readFloat(); |
2401 | color = tmpColor.toSColor(); | 2401 | color = tmpColor.toSColor(); |
2402 | return checkForOneFollowingSemicolons(); | 2402 | return checkForOneFollowingSemicolons(); |
2403 | } | 2403 | } |
2404 | 2404 | ||
2405 | 2405 | ||
2406 | // read matrix from list of floats | 2406 | // read matrix from list of floats |
2407 | bool CXMeshFileLoader::readMatrix(core::matrix4& mat) | 2407 | bool CXMeshFileLoader::readMatrix(core::matrix4& mat) |
2408 | { | 2408 | { |
2409 | for (u32 i=0; i<16; ++i) | 2409 | for (u32 i=0; i<16; ++i) |
2410 | mat[i] = readFloat(); | 2410 | mat[i] = readFloat(); |
2411 | return checkForOneFollowingSemicolons(); | 2411 | return checkForOneFollowingSemicolons(); |
2412 | } | 2412 | } |
2413 | 2413 | ||
2414 | 2414 | ||
2415 | } // end namespace scene | 2415 | } // end namespace scene |
2416 | } // end namespace irr | 2416 | } // end namespace irr |
2417 | 2417 | ||
2418 | #endif // _IRR_COMPILE_WITH_X_LOADER_ | 2418 | #endif // _IRR_COMPILE_WITH_X_LOADER_ |
2419 | 2419 | ||