diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/COBJMeshFileLoader.cpp | 1862 |
1 files changed, 931 insertions, 931 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/COBJMeshFileLoader.cpp b/libraries/irrlicht-1.8/source/Irrlicht/COBJMeshFileLoader.cpp index 47a4dad..2bda5e8 100644 --- a/libraries/irrlicht-1.8/source/Irrlicht/COBJMeshFileLoader.cpp +++ b/libraries/irrlicht-1.8/source/Irrlicht/COBJMeshFileLoader.cpp | |||
@@ -1,931 +1,931 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | 1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt |
2 | // This file is part of the "Irrlicht Engine". | 2 | // This file is part of the "Irrlicht Engine". |
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | 3 | // For conditions of distribution and use, see copyright notice in irrlicht.h |
4 | 4 | ||
5 | #include "IrrCompileConfig.h" | 5 | #include "IrrCompileConfig.h" |
6 | #ifdef _IRR_COMPILE_WITH_OBJ_LOADER_ | 6 | #ifdef _IRR_COMPILE_WITH_OBJ_LOADER_ |
7 | 7 | ||
8 | #include "COBJMeshFileLoader.h" | 8 | #include "COBJMeshFileLoader.h" |
9 | #include "IMeshManipulator.h" | 9 | #include "IMeshManipulator.h" |
10 | #include "IVideoDriver.h" | 10 | #include "IVideoDriver.h" |
11 | #include "SMesh.h" | 11 | #include "SMesh.h" |
12 | #include "SMeshBuffer.h" | 12 | #include "SMeshBuffer.h" |
13 | #include "SAnimatedMesh.h" | 13 | #include "SAnimatedMesh.h" |
14 | #include "IReadFile.h" | 14 | #include "IReadFile.h" |
15 | #include "IAttributes.h" | 15 | #include "IAttributes.h" |
16 | #include "fast_atof.h" | 16 | #include "fast_atof.h" |
17 | #include "coreutil.h" | 17 | #include "coreutil.h" |
18 | #include "os.h" | 18 | #include "os.h" |
19 | 19 | ||
20 | namespace irr | 20 | namespace irr |
21 | { | 21 | { |
22 | namespace scene | 22 | namespace scene |
23 | { | 23 | { |
24 | 24 | ||
25 | #ifdef _DEBUG | 25 | #ifdef _DEBUG |
26 | #define _IRR_DEBUG_OBJ_LOADER_ | 26 | #define _IRR_DEBUG_OBJ_LOADER_ |
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | static const u32 WORD_BUFFER_LENGTH = 512; | 29 | static const u32 WORD_BUFFER_LENGTH = 512; |
30 | 30 | ||
31 | //! Constructor | 31 | //! Constructor |
32 | COBJMeshFileLoader::COBJMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs) | 32 | COBJMeshFileLoader::COBJMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs) |
33 | : SceneManager(smgr), FileSystem(fs) | 33 | : SceneManager(smgr), FileSystem(fs) |
34 | { | 34 | { |
35 | #ifdef _DEBUG | 35 | #ifdef _DEBUG |
36 | setDebugName("COBJMeshFileLoader"); | 36 | setDebugName("COBJMeshFileLoader"); |
37 | #endif | 37 | #endif |
38 | 38 | ||
39 | if (FileSystem) | 39 | if (FileSystem) |
40 | FileSystem->grab(); | 40 | FileSystem->grab(); |
41 | } | 41 | } |
42 | 42 | ||
43 | 43 | ||
44 | //! destructor | 44 | //! destructor |
45 | COBJMeshFileLoader::~COBJMeshFileLoader() | 45 | COBJMeshFileLoader::~COBJMeshFileLoader() |
46 | { | 46 | { |
47 | if (FileSystem) | 47 | if (FileSystem) |
48 | FileSystem->drop(); | 48 | FileSystem->drop(); |
49 | } | 49 | } |
50 | 50 | ||
51 | 51 | ||
52 | //! returns true if the file maybe is able to be loaded by this class | 52 | //! returns true if the file maybe is able to be loaded by this class |
53 | //! based on the file extension (e.g. ".bsp") | 53 | //! based on the file extension (e.g. ".bsp") |
54 | bool COBJMeshFileLoader::isALoadableFileExtension(const io::path& filename) const | 54 | bool COBJMeshFileLoader::isALoadableFileExtension(const io::path& filename) const |
55 | { | 55 | { |
56 | return core::hasFileExtension ( filename, "obj" ); | 56 | return core::hasFileExtension ( filename, "obj" ); |
57 | } | 57 | } |
58 | 58 | ||
59 | 59 | ||
60 | //! creates/loads an animated mesh from the file. | 60 | //! creates/loads an animated mesh from the file. |
61 | //! \return Pointer to the created mesh. Returns 0 if loading failed. | 61 | //! \return Pointer to the created mesh. Returns 0 if loading failed. |
62 | //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). | 62 | //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). |
63 | //! See IReferenceCounted::drop() for more information. | 63 | //! See IReferenceCounted::drop() for more information. |
64 | IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) | 64 | IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) |
65 | { | 65 | { |
66 | const long filesize = file->getSize(); | 66 | const long filesize = file->getSize(); |
67 | if (!filesize) | 67 | if (!filesize) |
68 | return 0; | 68 | return 0; |
69 | 69 | ||
70 | const u32 WORD_BUFFER_LENGTH = 512; | 70 | const u32 WORD_BUFFER_LENGTH = 512; |
71 | 71 | ||
72 | core::array<core::vector3df> vertexBuffer; | 72 | core::array<core::vector3df> vertexBuffer; |
73 | core::array<core::vector3df> normalsBuffer; | 73 | core::array<core::vector3df> normalsBuffer; |
74 | core::array<core::vector2df> textureCoordBuffer; | 74 | core::array<core::vector2df> textureCoordBuffer; |
75 | 75 | ||
76 | SObjMtl * currMtl = new SObjMtl(); | 76 | SObjMtl * currMtl = new SObjMtl(); |
77 | Materials.push_back(currMtl); | 77 | Materials.push_back(currMtl); |
78 | u32 smoothingGroup=0; | 78 | u32 smoothingGroup=0; |
79 | 79 | ||
80 | const io::path fullName = file->getFileName(); | 80 | const io::path fullName = file->getFileName(); |
81 | const io::path relPath = FileSystem->getFileDir(fullName)+"/"; | 81 | const io::path relPath = FileSystem->getFileDir(fullName)+"/"; |
82 | 82 | ||
83 | c8* buf = new c8[filesize]; | 83 | c8* buf = new c8[filesize]; |
84 | memset(buf, 0, filesize); | 84 | memset(buf, 0, filesize); |
85 | file->read((void*)buf, filesize); | 85 | file->read((void*)buf, filesize); |
86 | const c8* const bufEnd = buf+filesize; | 86 | const c8* const bufEnd = buf+filesize; |
87 | 87 | ||
88 | // Process obj information | 88 | // Process obj information |
89 | const c8* bufPtr = buf; | 89 | const c8* bufPtr = buf; |
90 | core::stringc grpName, mtlName; | 90 | core::stringc grpName, mtlName; |
91 | bool mtlChanged=false; | 91 | bool mtlChanged=false; |
92 | bool useGroups = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_GROUPS); | 92 | bool useGroups = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_GROUPS); |
93 | bool useMaterials = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_MATERIAL_FILES); | 93 | bool useMaterials = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_MATERIAL_FILES); |
94 | while(bufPtr != bufEnd) | 94 | while(bufPtr != bufEnd) |
95 | { | 95 | { |
96 | switch(bufPtr[0]) | 96 | switch(bufPtr[0]) |
97 | { | 97 | { |
98 | case 'm': // mtllib (material) | 98 | case 'm': // mtllib (material) |
99 | { | 99 | { |
100 | if (useMaterials) | 100 | if (useMaterials) |
101 | { | 101 | { |
102 | c8 name[WORD_BUFFER_LENGTH]; | 102 | c8 name[WORD_BUFFER_LENGTH]; |
103 | bufPtr = goAndCopyNextWord(name, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 103 | bufPtr = goAndCopyNextWord(name, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
104 | #ifdef _IRR_DEBUG_OBJ_LOADER_ | 104 | #ifdef _IRR_DEBUG_OBJ_LOADER_ |
105 | os::Printer::log("Reading material file",name); | 105 | os::Printer::log("Reading material file",name); |
106 | #endif | 106 | #endif |
107 | readMTL(name, relPath); | 107 | readMTL(name, relPath); |
108 | } | 108 | } |
109 | } | 109 | } |
110 | break; | 110 | break; |
111 | 111 | ||
112 | case 'v': // v, vn, vt | 112 | case 'v': // v, vn, vt |
113 | switch(bufPtr[1]) | 113 | switch(bufPtr[1]) |
114 | { | 114 | { |
115 | case ' ': // vertex | 115 | case ' ': // vertex |
116 | { | 116 | { |
117 | core::vector3df vec; | 117 | core::vector3df vec; |
118 | bufPtr = readVec3(bufPtr, vec, bufEnd); | 118 | bufPtr = readVec3(bufPtr, vec, bufEnd); |
119 | vertexBuffer.push_back(vec); | 119 | vertexBuffer.push_back(vec); |
120 | } | 120 | } |
121 | break; | 121 | break; |
122 | 122 | ||
123 | case 'n': // normal | 123 | case 'n': // normal |
124 | { | 124 | { |
125 | core::vector3df vec; | 125 | core::vector3df vec; |
126 | bufPtr = readVec3(bufPtr, vec, bufEnd); | 126 | bufPtr = readVec3(bufPtr, vec, bufEnd); |
127 | normalsBuffer.push_back(vec); | 127 | normalsBuffer.push_back(vec); |
128 | } | 128 | } |
129 | break; | 129 | break; |
130 | 130 | ||
131 | case 't': // texcoord | 131 | case 't': // texcoord |
132 | { | 132 | { |
133 | core::vector2df vec; | 133 | core::vector2df vec; |
134 | bufPtr = readUV(bufPtr, vec, bufEnd); | 134 | bufPtr = readUV(bufPtr, vec, bufEnd); |
135 | textureCoordBuffer.push_back(vec); | 135 | textureCoordBuffer.push_back(vec); |
136 | } | 136 | } |
137 | break; | 137 | break; |
138 | } | 138 | } |
139 | break; | 139 | break; |
140 | 140 | ||
141 | case 'g': // group name | 141 | case 'g': // group name |
142 | { | 142 | { |
143 | c8 grp[WORD_BUFFER_LENGTH]; | 143 | c8 grp[WORD_BUFFER_LENGTH]; |
144 | bufPtr = goAndCopyNextWord(grp, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 144 | bufPtr = goAndCopyNextWord(grp, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
145 | #ifdef _IRR_DEBUG_OBJ_LOADER_ | 145 | #ifdef _IRR_DEBUG_OBJ_LOADER_ |
146 | os::Printer::log("Loaded group start",grp, ELL_DEBUG); | 146 | os::Printer::log("Loaded group start",grp, ELL_DEBUG); |
147 | #endif | 147 | #endif |
148 | if (useGroups) | 148 | if (useGroups) |
149 | { | 149 | { |
150 | if (0 != grp[0]) | 150 | if (0 != grp[0]) |
151 | grpName = grp; | 151 | grpName = grp; |
152 | else | 152 | else |
153 | grpName = "default"; | 153 | grpName = "default"; |
154 | } | 154 | } |
155 | mtlChanged=true; | 155 | mtlChanged=true; |
156 | } | 156 | } |
157 | break; | 157 | break; |
158 | 158 | ||
159 | case 's': // smoothing can be a group or off (equiv. to 0) | 159 | case 's': // smoothing can be a group or off (equiv. to 0) |
160 | { | 160 | { |
161 | c8 smooth[WORD_BUFFER_LENGTH]; | 161 | c8 smooth[WORD_BUFFER_LENGTH]; |
162 | bufPtr = goAndCopyNextWord(smooth, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 162 | bufPtr = goAndCopyNextWord(smooth, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
163 | #ifdef _IRR_DEBUG_OBJ_LOADER_ | 163 | #ifdef _IRR_DEBUG_OBJ_LOADER_ |
164 | os::Printer::log("Loaded smoothing group start",smooth, ELL_DEBUG); | 164 | os::Printer::log("Loaded smoothing group start",smooth, ELL_DEBUG); |
165 | #endif | 165 | #endif |
166 | if (core::stringc("off")==smooth) | 166 | if (core::stringc("off")==smooth) |
167 | smoothingGroup=0; | 167 | smoothingGroup=0; |
168 | else | 168 | else |
169 | smoothingGroup=core::strtoul10(smooth); | 169 | smoothingGroup=core::strtoul10(smooth); |
170 | } | 170 | } |
171 | break; | 171 | break; |
172 | 172 | ||
173 | case 'u': // usemtl | 173 | case 'u': // usemtl |
174 | // get name of material | 174 | // get name of material |
175 | { | 175 | { |
176 | c8 matName[WORD_BUFFER_LENGTH]; | 176 | c8 matName[WORD_BUFFER_LENGTH]; |
177 | bufPtr = goAndCopyNextWord(matName, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 177 | bufPtr = goAndCopyNextWord(matName, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
178 | #ifdef _IRR_DEBUG_OBJ_LOADER_ | 178 | #ifdef _IRR_DEBUG_OBJ_LOADER_ |
179 | os::Printer::log("Loaded material start",matName, ELL_DEBUG); | 179 | os::Printer::log("Loaded material start",matName, ELL_DEBUG); |
180 | #endif | 180 | #endif |
181 | mtlName=matName; | 181 | mtlName=matName; |
182 | mtlChanged=true; | 182 | mtlChanged=true; |
183 | } | 183 | } |
184 | break; | 184 | break; |
185 | 185 | ||
186 | case 'f': // face | 186 | case 'f': // face |
187 | { | 187 | { |
188 | c8 vertexWord[WORD_BUFFER_LENGTH]; // for retrieving vertex data | 188 | c8 vertexWord[WORD_BUFFER_LENGTH]; // for retrieving vertex data |
189 | video::S3DVertex v; | 189 | video::S3DVertex v; |
190 | // Assign vertex color from currently active material's diffuse color | 190 | // Assign vertex color from currently active material's diffuse color |
191 | if (mtlChanged) | 191 | if (mtlChanged) |
192 | { | 192 | { |
193 | // retrieve the material | 193 | // retrieve the material |
194 | SObjMtl *useMtl = findMtl(mtlName, grpName); | 194 | SObjMtl *useMtl = findMtl(mtlName, grpName); |
195 | // only change material if we found it | 195 | // only change material if we found it |
196 | if (useMtl) | 196 | if (useMtl) |
197 | currMtl = useMtl; | 197 | currMtl = useMtl; |
198 | mtlChanged=false; | 198 | mtlChanged=false; |
199 | } | 199 | } |
200 | if (currMtl) | 200 | if (currMtl) |
201 | v.Color = currMtl->Meshbuffer->Material.DiffuseColor; | 201 | v.Color = currMtl->Meshbuffer->Material.DiffuseColor; |
202 | 202 | ||
203 | // get all vertices data in this face (current line of obj file) | 203 | // get all vertices data in this face (current line of obj file) |
204 | const core::stringc wordBuffer = copyLine(bufPtr, bufEnd); | 204 | const core::stringc wordBuffer = copyLine(bufPtr, bufEnd); |
205 | const c8* linePtr = wordBuffer.c_str(); | 205 | const c8* linePtr = wordBuffer.c_str(); |
206 | const c8* const endPtr = linePtr+wordBuffer.size(); | 206 | const c8* const endPtr = linePtr+wordBuffer.size(); |
207 | 207 | ||
208 | core::array<int> faceCorners; | 208 | core::array<int> faceCorners; |
209 | faceCorners.reallocate(32); // should be large enough | 209 | faceCorners.reallocate(32); // should be large enough |
210 | 210 | ||
211 | // read in all vertices | 211 | // read in all vertices |
212 | linePtr = goNextWord(linePtr, endPtr); | 212 | linePtr = goNextWord(linePtr, endPtr); |
213 | while (0 != linePtr[0]) | 213 | while (0 != linePtr[0]) |
214 | { | 214 | { |
215 | // Array to communicate with retrieveVertexIndices() | 215 | // Array to communicate with retrieveVertexIndices() |
216 | // sends the buffer sizes and gets the actual indices | 216 | // sends the buffer sizes and gets the actual indices |
217 | // if index not set returns -1 | 217 | // if index not set returns -1 |
218 | s32 Idx[3]; | 218 | s32 Idx[3]; |
219 | Idx[1] = Idx[2] = -1; | 219 | Idx[1] = Idx[2] = -1; |
220 | 220 | ||
221 | // read in next vertex's data | 221 | // read in next vertex's data |
222 | u32 wlength = copyWord(vertexWord, linePtr, WORD_BUFFER_LENGTH, endPtr); | 222 | u32 wlength = copyWord(vertexWord, linePtr, WORD_BUFFER_LENGTH, endPtr); |
223 | // this function will also convert obj's 1-based index to c++'s 0-based index | 223 | // this function will also convert obj's 1-based index to c++'s 0-based index |
224 | retrieveVertexIndices(vertexWord, Idx, vertexWord+wlength+1, vertexBuffer.size(), textureCoordBuffer.size(), normalsBuffer.size()); | 224 | retrieveVertexIndices(vertexWord, Idx, vertexWord+wlength+1, vertexBuffer.size(), textureCoordBuffer.size(), normalsBuffer.size()); |
225 | v.Pos = vertexBuffer[Idx[0]]; | 225 | v.Pos = vertexBuffer[Idx[0]]; |
226 | if ( -1 != Idx[1] ) | 226 | if ( -1 != Idx[1] ) |
227 | v.TCoords = textureCoordBuffer[Idx[1]]; | 227 | v.TCoords = textureCoordBuffer[Idx[1]]; |
228 | else | 228 | else |
229 | v.TCoords.set(0.0f,0.0f); | 229 | v.TCoords.set(0.0f,0.0f); |
230 | if ( -1 != Idx[2] ) | 230 | if ( -1 != Idx[2] ) |
231 | v.Normal = normalsBuffer[Idx[2]]; | 231 | v.Normal = normalsBuffer[Idx[2]]; |
232 | else | 232 | else |
233 | { | 233 | { |
234 | v.Normal.set(0.0f,0.0f,0.0f); | 234 | v.Normal.set(0.0f,0.0f,0.0f); |
235 | currMtl->RecalculateNormals=true; | 235 | currMtl->RecalculateNormals=true; |
236 | } | 236 | } |
237 | 237 | ||
238 | int vertLocation; | 238 | int vertLocation; |
239 | core::map<video::S3DVertex, int>::Node* n = currMtl->VertMap.find(v); | 239 | core::map<video::S3DVertex, int>::Node* n = currMtl->VertMap.find(v); |
240 | if (n) | 240 | if (n) |
241 | { | 241 | { |
242 | vertLocation = n->getValue(); | 242 | vertLocation = n->getValue(); |
243 | } | 243 | } |
244 | else | 244 | else |
245 | { | 245 | { |
246 | currMtl->Meshbuffer->Vertices.push_back(v); | 246 | currMtl->Meshbuffer->Vertices.push_back(v); |
247 | vertLocation = currMtl->Meshbuffer->Vertices.size() -1; | 247 | vertLocation = currMtl->Meshbuffer->Vertices.size() -1; |
248 | currMtl->VertMap.insert(v, vertLocation); | 248 | currMtl->VertMap.insert(v, vertLocation); |
249 | } | 249 | } |
250 | 250 | ||
251 | faceCorners.push_back(vertLocation); | 251 | faceCorners.push_back(vertLocation); |
252 | 252 | ||
253 | // go to next vertex | 253 | // go to next vertex |
254 | linePtr = goNextWord(linePtr, endPtr); | 254 | linePtr = goNextWord(linePtr, endPtr); |
255 | } | 255 | } |
256 | 256 | ||
257 | // triangulate the face | 257 | // triangulate the face |
258 | for ( u32 i = 1; i < faceCorners.size() - 1; ++i ) | 258 | for ( u32 i = 1; i < faceCorners.size() - 1; ++i ) |
259 | { | 259 | { |
260 | // Add a triangle | 260 | // Add a triangle |
261 | currMtl->Meshbuffer->Indices.push_back( faceCorners[i+1] ); | 261 | currMtl->Meshbuffer->Indices.push_back( faceCorners[i+1] ); |
262 | currMtl->Meshbuffer->Indices.push_back( faceCorners[i] ); | 262 | currMtl->Meshbuffer->Indices.push_back( faceCorners[i] ); |
263 | currMtl->Meshbuffer->Indices.push_back( faceCorners[0] ); | 263 | currMtl->Meshbuffer->Indices.push_back( faceCorners[0] ); |
264 | } | 264 | } |
265 | faceCorners.set_used(0); // fast clear | 265 | faceCorners.set_used(0); // fast clear |
266 | faceCorners.reallocate(32); | 266 | faceCorners.reallocate(32); |
267 | } | 267 | } |
268 | break; | 268 | break; |
269 | 269 | ||
270 | case '#': // comment | 270 | case '#': // comment |
271 | default: | 271 | default: |
272 | break; | 272 | break; |
273 | } // end switch(bufPtr[0]) | 273 | } // end switch(bufPtr[0]) |
274 | // eat up rest of line | 274 | // eat up rest of line |
275 | bufPtr = goNextLine(bufPtr, bufEnd); | 275 | bufPtr = goNextLine(bufPtr, bufEnd); |
276 | } // end while(bufPtr && (bufPtr-buf<filesize)) | 276 | } // end while(bufPtr && (bufPtr-buf<filesize)) |
277 | 277 | ||
278 | SMesh* mesh = new SMesh(); | 278 | SMesh* mesh = new SMesh(); |
279 | 279 | ||
280 | // Combine all the groups (meshbuffers) into the mesh | 280 | // Combine all the groups (meshbuffers) into the mesh |
281 | for ( u32 m = 0; m < Materials.size(); ++m ) | 281 | for ( u32 m = 0; m < Materials.size(); ++m ) |
282 | { | 282 | { |
283 | if ( Materials[m]->Meshbuffer->getIndexCount() > 0 ) | 283 | if ( Materials[m]->Meshbuffer->getIndexCount() > 0 ) |
284 | { | 284 | { |
285 | Materials[m]->Meshbuffer->recalculateBoundingBox(); | 285 | Materials[m]->Meshbuffer->recalculateBoundingBox(); |
286 | if (Materials[m]->RecalculateNormals) | 286 | if (Materials[m]->RecalculateNormals) |
287 | SceneManager->getMeshManipulator()->recalculateNormals(Materials[m]->Meshbuffer); | 287 | SceneManager->getMeshManipulator()->recalculateNormals(Materials[m]->Meshbuffer); |
288 | if (Materials[m]->Meshbuffer->Material.MaterialType == video::EMT_PARALLAX_MAP_SOLID) | 288 | if (Materials[m]->Meshbuffer->Material.MaterialType == video::EMT_PARALLAX_MAP_SOLID) |
289 | { | 289 | { |
290 | SMesh tmp; | 290 | SMesh tmp; |
291 | tmp.addMeshBuffer(Materials[m]->Meshbuffer); | 291 | tmp.addMeshBuffer(Materials[m]->Meshbuffer); |
292 | IMesh* tangentMesh = SceneManager->getMeshManipulator()->createMeshWithTangents(&tmp); | 292 | IMesh* tangentMesh = SceneManager->getMeshManipulator()->createMeshWithTangents(&tmp); |
293 | mesh->addMeshBuffer(tangentMesh->getMeshBuffer(0)); | 293 | mesh->addMeshBuffer(tangentMesh->getMeshBuffer(0)); |
294 | tangentMesh->drop(); | 294 | tangentMesh->drop(); |
295 | } | 295 | } |
296 | else | 296 | else |
297 | mesh->addMeshBuffer( Materials[m]->Meshbuffer ); | 297 | mesh->addMeshBuffer( Materials[m]->Meshbuffer ); |
298 | } | 298 | } |
299 | } | 299 | } |
300 | 300 | ||
301 | // Create the Animated mesh if there's anything in the mesh | 301 | // Create the Animated mesh if there's anything in the mesh |
302 | SAnimatedMesh* animMesh = 0; | 302 | SAnimatedMesh* animMesh = 0; |
303 | if ( 0 != mesh->getMeshBufferCount() ) | 303 | if ( 0 != mesh->getMeshBufferCount() ) |
304 | { | 304 | { |
305 | mesh->recalculateBoundingBox(); | 305 | mesh->recalculateBoundingBox(); |
306 | animMesh = new SAnimatedMesh(); | 306 | animMesh = new SAnimatedMesh(); |
307 | animMesh->Type = EAMT_OBJ; | 307 | animMesh->Type = EAMT_OBJ; |
308 | animMesh->addMesh(mesh); | 308 | animMesh->addMesh(mesh); |
309 | animMesh->recalculateBoundingBox(); | 309 | animMesh->recalculateBoundingBox(); |
310 | } | 310 | } |
311 | 311 | ||
312 | // Clean up the allocate obj file contents | 312 | // Clean up the allocate obj file contents |
313 | delete [] buf; | 313 | delete [] buf; |
314 | // more cleaning up | 314 | // more cleaning up |
315 | cleanUp(); | 315 | cleanUp(); |
316 | mesh->drop(); | 316 | mesh->drop(); |
317 | 317 | ||
318 | return animMesh; | 318 | return animMesh; |
319 | } | 319 | } |
320 | 320 | ||
321 | 321 | ||
322 | const c8* COBJMeshFileLoader::readTextures(const c8* bufPtr, const c8* const bufEnd, SObjMtl* currMaterial, const io::path& relPath) | 322 | const c8* COBJMeshFileLoader::readTextures(const c8* bufPtr, const c8* const bufEnd, SObjMtl* currMaterial, const io::path& relPath) |
323 | { | 323 | { |
324 | u8 type=0; // map_Kd - diffuse color texture map | 324 | u8 type=0; // map_Kd - diffuse color texture map |
325 | // map_Ks - specular color texture map | 325 | // map_Ks - specular color texture map |
326 | // map_Ka - ambient color texture map | 326 | // map_Ka - ambient color texture map |
327 | // map_Ns - shininess texture map | 327 | // map_Ns - shininess texture map |
328 | if ((!strncmp(bufPtr,"map_bump",8)) || (!strncmp(bufPtr,"bump",4))) | 328 | if ((!strncmp(bufPtr,"map_bump",8)) || (!strncmp(bufPtr,"bump",4))) |
329 | type=1; // normal map | 329 | type=1; // normal map |
330 | else if ((!strncmp(bufPtr,"map_d",5)) || (!strncmp(bufPtr,"map_opacity",11))) | 330 | else if ((!strncmp(bufPtr,"map_d",5)) || (!strncmp(bufPtr,"map_opacity",11))) |
331 | type=2; // opacity map | 331 | type=2; // opacity map |
332 | else if (!strncmp(bufPtr,"map_refl",8)) | 332 | else if (!strncmp(bufPtr,"map_refl",8)) |
333 | type=3; // reflection map | 333 | type=3; // reflection map |
334 | // extract new material's name | 334 | // extract new material's name |
335 | c8 textureNameBuf[WORD_BUFFER_LENGTH]; | 335 | c8 textureNameBuf[WORD_BUFFER_LENGTH]; |
336 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 336 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
337 | 337 | ||
338 | f32 bumpiness = 6.0f; | 338 | f32 bumpiness = 6.0f; |
339 | bool clamp = false; | 339 | bool clamp = false; |
340 | // handle options | 340 | // handle options |
341 | while (textureNameBuf[0]=='-') | 341 | while (textureNameBuf[0]=='-') |
342 | { | 342 | { |
343 | if (!strncmp(bufPtr,"-bm",3)) | 343 | if (!strncmp(bufPtr,"-bm",3)) |
344 | { | 344 | { |
345 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 345 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
346 | currMaterial->Meshbuffer->Material.MaterialTypeParam=core::fast_atof(textureNameBuf); | 346 | currMaterial->Meshbuffer->Material.MaterialTypeParam=core::fast_atof(textureNameBuf); |
347 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 347 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
348 | continue; | 348 | continue; |
349 | } | 349 | } |
350 | else | 350 | else |
351 | if (!strncmp(bufPtr,"-blendu",7)) | 351 | if (!strncmp(bufPtr,"-blendu",7)) |
352 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 352 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
353 | else | 353 | else |
354 | if (!strncmp(bufPtr,"-blendv",7)) | 354 | if (!strncmp(bufPtr,"-blendv",7)) |
355 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 355 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
356 | else | 356 | else |
357 | if (!strncmp(bufPtr,"-cc",3)) | 357 | if (!strncmp(bufPtr,"-cc",3)) |
358 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 358 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
359 | else | 359 | else |
360 | if (!strncmp(bufPtr,"-clamp",6)) | 360 | if (!strncmp(bufPtr,"-clamp",6)) |
361 | bufPtr = readBool(bufPtr, clamp, bufEnd); | 361 | bufPtr = readBool(bufPtr, clamp, bufEnd); |
362 | else | 362 | else |
363 | if (!strncmp(bufPtr,"-texres",7)) | 363 | if (!strncmp(bufPtr,"-texres",7)) |
364 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 364 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
365 | else | 365 | else |
366 | if (!strncmp(bufPtr,"-type",5)) | 366 | if (!strncmp(bufPtr,"-type",5)) |
367 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 367 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
368 | else | 368 | else |
369 | if (!strncmp(bufPtr,"-mm",3)) | 369 | if (!strncmp(bufPtr,"-mm",3)) |
370 | { | 370 | { |
371 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 371 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
372 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 372 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
373 | } | 373 | } |
374 | else | 374 | else |
375 | if (!strncmp(bufPtr,"-o",2)) // texture coord translation | 375 | if (!strncmp(bufPtr,"-o",2)) // texture coord translation |
376 | { | 376 | { |
377 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 377 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
378 | // next parameters are optional, so skip rest of loop if no number is found | 378 | // next parameters are optional, so skip rest of loop if no number is found |
379 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 379 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
380 | if (!core::isdigit(textureNameBuf[0])) | 380 | if (!core::isdigit(textureNameBuf[0])) |
381 | continue; | 381 | continue; |
382 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 382 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
383 | if (!core::isdigit(textureNameBuf[0])) | 383 | if (!core::isdigit(textureNameBuf[0])) |
384 | continue; | 384 | continue; |
385 | } | 385 | } |
386 | else | 386 | else |
387 | if (!strncmp(bufPtr,"-s",2)) // texture coord scale | 387 | if (!strncmp(bufPtr,"-s",2)) // texture coord scale |
388 | { | 388 | { |
389 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 389 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
390 | // next parameters are optional, so skip rest of loop if no number is found | 390 | // next parameters are optional, so skip rest of loop if no number is found |
391 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 391 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
392 | if (!core::isdigit(textureNameBuf[0])) | 392 | if (!core::isdigit(textureNameBuf[0])) |
393 | continue; | 393 | continue; |
394 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 394 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
395 | if (!core::isdigit(textureNameBuf[0])) | 395 | if (!core::isdigit(textureNameBuf[0])) |
396 | continue; | 396 | continue; |
397 | } | 397 | } |
398 | else | 398 | else |
399 | if (!strncmp(bufPtr,"-t",2)) | 399 | if (!strncmp(bufPtr,"-t",2)) |
400 | { | 400 | { |
401 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 401 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
402 | // next parameters are optional, so skip rest of loop if no number is found | 402 | // next parameters are optional, so skip rest of loop if no number is found |
403 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 403 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
404 | if (!core::isdigit(textureNameBuf[0])) | 404 | if (!core::isdigit(textureNameBuf[0])) |
405 | continue; | 405 | continue; |
406 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 406 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
407 | if (!core::isdigit(textureNameBuf[0])) | 407 | if (!core::isdigit(textureNameBuf[0])) |
408 | continue; | 408 | continue; |
409 | } | 409 | } |
410 | // get next word | 410 | // get next word |
411 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 411 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
412 | } | 412 | } |
413 | 413 | ||
414 | if ((type==1) && (core::isdigit(textureNameBuf[0]))) | 414 | if ((type==1) && (core::isdigit(textureNameBuf[0]))) |
415 | { | 415 | { |
416 | currMaterial->Meshbuffer->Material.MaterialTypeParam=core::fast_atof(textureNameBuf); | 416 | currMaterial->Meshbuffer->Material.MaterialTypeParam=core::fast_atof(textureNameBuf); |
417 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 417 | bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
418 | } | 418 | } |
419 | if (clamp) | 419 | if (clamp) |
420 | currMaterial->Meshbuffer->Material.setFlag(video::EMF_TEXTURE_WRAP, video::ETC_CLAMP); | 420 | currMaterial->Meshbuffer->Material.setFlag(video::EMF_TEXTURE_WRAP, video::ETC_CLAMP); |
421 | 421 | ||
422 | io::path texname(textureNameBuf); | 422 | io::path texname(textureNameBuf); |
423 | texname.replace('\\', '/'); | 423 | texname.replace('\\', '/'); |
424 | 424 | ||
425 | video::ITexture * texture = 0; | 425 | video::ITexture * texture = 0; |
426 | bool newTexture=false; | 426 | bool newTexture=false; |
427 | if (texname.size()) | 427 | if (texname.size()) |
428 | { | 428 | { |
429 | io::path texnameWithUserPath( SceneManager->getParameters()->getAttributeAsString(OBJ_TEXTURE_PATH) ); | 429 | io::path texnameWithUserPath( SceneManager->getParameters()->getAttributeAsString(OBJ_TEXTURE_PATH) ); |
430 | if ( texnameWithUserPath.size() ) | 430 | if ( texnameWithUserPath.size() ) |
431 | { | 431 | { |
432 | texnameWithUserPath += '/'; | 432 | texnameWithUserPath += '/'; |
433 | texnameWithUserPath += texname; | 433 | texnameWithUserPath += texname; |
434 | } | 434 | } |
435 | if (FileSystem->existFile(texnameWithUserPath)) | 435 | if (FileSystem->existFile(texnameWithUserPath)) |
436 | texture = SceneManager->getVideoDriver()->getTexture(texnameWithUserPath); | 436 | texture = SceneManager->getVideoDriver()->getTexture(texnameWithUserPath); |
437 | else if (FileSystem->existFile(texname)) | 437 | else if (FileSystem->existFile(texname)) |
438 | { | 438 | { |
439 | newTexture = SceneManager->getVideoDriver()->findTexture(texname) == 0; | 439 | newTexture = SceneManager->getVideoDriver()->findTexture(texname) == 0; |
440 | texture = SceneManager->getVideoDriver()->getTexture(texname); | 440 | texture = SceneManager->getVideoDriver()->getTexture(texname); |
441 | } | 441 | } |
442 | else | 442 | else |
443 | { | 443 | { |
444 | newTexture = SceneManager->getVideoDriver()->findTexture(relPath + texname) == 0; | 444 | newTexture = SceneManager->getVideoDriver()->findTexture(relPath + texname) == 0; |
445 | // try to read in the relative path, the .obj is loaded from | 445 | // try to read in the relative path, the .obj is loaded from |
446 | texture = SceneManager->getVideoDriver()->getTexture( relPath + texname ); | 446 | texture = SceneManager->getVideoDriver()->getTexture( relPath + texname ); |
447 | } | 447 | } |
448 | } | 448 | } |
449 | if ( texture ) | 449 | if ( texture ) |
450 | { | 450 | { |
451 | if (type==0) | 451 | if (type==0) |
452 | currMaterial->Meshbuffer->Material.setTexture(0, texture); | 452 | currMaterial->Meshbuffer->Material.setTexture(0, texture); |
453 | else if (type==1) | 453 | else if (type==1) |
454 | { | 454 | { |
455 | if (newTexture) | 455 | if (newTexture) |
456 | SceneManager->getVideoDriver()->makeNormalMapTexture(texture, bumpiness); | 456 | SceneManager->getVideoDriver()->makeNormalMapTexture(texture, bumpiness); |
457 | currMaterial->Meshbuffer->Material.setTexture(1, texture); | 457 | currMaterial->Meshbuffer->Material.setTexture(1, texture); |
458 | currMaterial->Meshbuffer->Material.MaterialType=video::EMT_PARALLAX_MAP_SOLID; | 458 | currMaterial->Meshbuffer->Material.MaterialType=video::EMT_PARALLAX_MAP_SOLID; |
459 | currMaterial->Meshbuffer->Material.MaterialTypeParam=0.035f; | 459 | currMaterial->Meshbuffer->Material.MaterialTypeParam=0.035f; |
460 | } | 460 | } |
461 | else if (type==2) | 461 | else if (type==2) |
462 | { | 462 | { |
463 | currMaterial->Meshbuffer->Material.setTexture(0, texture); | 463 | currMaterial->Meshbuffer->Material.setTexture(0, texture); |
464 | currMaterial->Meshbuffer->Material.MaterialType=video::EMT_TRANSPARENT_ADD_COLOR; | 464 | currMaterial->Meshbuffer->Material.MaterialType=video::EMT_TRANSPARENT_ADD_COLOR; |
465 | } | 465 | } |
466 | else if (type==3) | 466 | else if (type==3) |
467 | { | 467 | { |
468 | // currMaterial->Meshbuffer->Material.Textures[1] = texture; | 468 | // currMaterial->Meshbuffer->Material.Textures[1] = texture; |
469 | // currMaterial->Meshbuffer->Material.MaterialType=video::EMT_REFLECTION_2_LAYER; | 469 | // currMaterial->Meshbuffer->Material.MaterialType=video::EMT_REFLECTION_2_LAYER; |
470 | } | 470 | } |
471 | // Set diffuse material color to white so as not to affect texture color | 471 | // Set diffuse material color to white so as not to affect texture color |
472 | // Because Maya set diffuse color Kd to black when you use a diffuse color map | 472 | // Because Maya set diffuse color Kd to black when you use a diffuse color map |
473 | // But is this the right thing to do? | 473 | // But is this the right thing to do? |
474 | currMaterial->Meshbuffer->Material.DiffuseColor.set( | 474 | currMaterial->Meshbuffer->Material.DiffuseColor.set( |
475 | currMaterial->Meshbuffer->Material.DiffuseColor.getAlpha(), 255, 255, 255 ); | 475 | currMaterial->Meshbuffer->Material.DiffuseColor.getAlpha(), 255, 255, 255 ); |
476 | } | 476 | } |
477 | return bufPtr; | 477 | return bufPtr; |
478 | } | 478 | } |
479 | 479 | ||
480 | 480 | ||
481 | void COBJMeshFileLoader::readMTL(const c8* fileName, const io::path& relPath) | 481 | void COBJMeshFileLoader::readMTL(const c8* fileName, const io::path& relPath) |
482 | { | 482 | { |
483 | const io::path realFile(fileName); | 483 | const io::path realFile(fileName); |
484 | io::IReadFile * mtlReader; | 484 | io::IReadFile * mtlReader; |
485 | 485 | ||
486 | if (FileSystem->existFile(realFile)) | 486 | if (FileSystem->existFile(realFile)) |
487 | mtlReader = FileSystem->createAndOpenFile(realFile); | 487 | mtlReader = FileSystem->createAndOpenFile(realFile); |
488 | else if (FileSystem->existFile(relPath + realFile)) | 488 | else if (FileSystem->existFile(relPath + realFile)) |
489 | mtlReader = FileSystem->createAndOpenFile(relPath + realFile); | 489 | mtlReader = FileSystem->createAndOpenFile(relPath + realFile); |
490 | else if (FileSystem->existFile(FileSystem->getFileBasename(realFile))) | 490 | else if (FileSystem->existFile(FileSystem->getFileBasename(realFile))) |
491 | mtlReader = FileSystem->createAndOpenFile(FileSystem->getFileBasename(realFile)); | 491 | mtlReader = FileSystem->createAndOpenFile(FileSystem->getFileBasename(realFile)); |
492 | else | 492 | else |
493 | mtlReader = FileSystem->createAndOpenFile(relPath + FileSystem->getFileBasename(realFile)); | 493 | mtlReader = FileSystem->createAndOpenFile(relPath + FileSystem->getFileBasename(realFile)); |
494 | if (!mtlReader) // fail to open and read file | 494 | if (!mtlReader) // fail to open and read file |
495 | { | 495 | { |
496 | os::Printer::log("Could not open material file", realFile, ELL_WARNING); | 496 | os::Printer::log("Could not open material file", realFile, ELL_WARNING); |
497 | return; | 497 | return; |
498 | } | 498 | } |
499 | 499 | ||
500 | const long filesize = mtlReader->getSize(); | 500 | const long filesize = mtlReader->getSize(); |
501 | if (!filesize) | 501 | if (!filesize) |
502 | { | 502 | { |
503 | os::Printer::log("Skipping empty material file", realFile, ELL_WARNING); | 503 | os::Printer::log("Skipping empty material file", realFile, ELL_WARNING); |
504 | mtlReader->drop(); | 504 | mtlReader->drop(); |
505 | return; | 505 | return; |
506 | } | 506 | } |
507 | 507 | ||
508 | c8* buf = new c8[filesize]; | 508 | c8* buf = new c8[filesize]; |
509 | mtlReader->read((void*)buf, filesize); | 509 | mtlReader->read((void*)buf, filesize); |
510 | const c8* bufEnd = buf+filesize; | 510 | const c8* bufEnd = buf+filesize; |
511 | 511 | ||
512 | SObjMtl* currMaterial = 0; | 512 | SObjMtl* currMaterial = 0; |
513 | 513 | ||
514 | const c8* bufPtr = buf; | 514 | const c8* bufPtr = buf; |
515 | while(bufPtr != bufEnd) | 515 | while(bufPtr != bufEnd) |
516 | { | 516 | { |
517 | switch(*bufPtr) | 517 | switch(*bufPtr) |
518 | { | 518 | { |
519 | case 'n': // newmtl | 519 | case 'n': // newmtl |
520 | { | 520 | { |
521 | // if there's an existing material, store it first | 521 | // if there's an existing material, store it first |
522 | if ( currMaterial ) | 522 | if ( currMaterial ) |
523 | Materials.push_back( currMaterial ); | 523 | Materials.push_back( currMaterial ); |
524 | 524 | ||
525 | // extract new material's name | 525 | // extract new material's name |
526 | c8 mtlNameBuf[WORD_BUFFER_LENGTH]; | 526 | c8 mtlNameBuf[WORD_BUFFER_LENGTH]; |
527 | bufPtr = goAndCopyNextWord(mtlNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 527 | bufPtr = goAndCopyNextWord(mtlNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
528 | 528 | ||
529 | currMaterial = new SObjMtl; | 529 | currMaterial = new SObjMtl; |
530 | currMaterial->Name = mtlNameBuf; | 530 | currMaterial->Name = mtlNameBuf; |
531 | } | 531 | } |
532 | break; | 532 | break; |
533 | case 'i': // illum - illumination | 533 | case 'i': // illum - illumination |
534 | if ( currMaterial ) | 534 | if ( currMaterial ) |
535 | { | 535 | { |
536 | const u32 COLOR_BUFFER_LENGTH = 16; | 536 | const u32 COLOR_BUFFER_LENGTH = 16; |
537 | c8 illumStr[COLOR_BUFFER_LENGTH]; | 537 | c8 illumStr[COLOR_BUFFER_LENGTH]; |
538 | 538 | ||
539 | bufPtr = goAndCopyNextWord(illumStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); | 539 | bufPtr = goAndCopyNextWord(illumStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); |
540 | currMaterial->Illumination = (c8)atol(illumStr); | 540 | currMaterial->Illumination = (c8)atol(illumStr); |
541 | } | 541 | } |
542 | break; | 542 | break; |
543 | case 'N': | 543 | case 'N': |
544 | if ( currMaterial ) | 544 | if ( currMaterial ) |
545 | { | 545 | { |
546 | switch(bufPtr[1]) | 546 | switch(bufPtr[1]) |
547 | { | 547 | { |
548 | case 's': // Ns - shininess | 548 | case 's': // Ns - shininess |
549 | { | 549 | { |
550 | const u32 COLOR_BUFFER_LENGTH = 16; | 550 | const u32 COLOR_BUFFER_LENGTH = 16; |
551 | c8 nsStr[COLOR_BUFFER_LENGTH]; | 551 | c8 nsStr[COLOR_BUFFER_LENGTH]; |
552 | 552 | ||
553 | bufPtr = goAndCopyNextWord(nsStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); | 553 | bufPtr = goAndCopyNextWord(nsStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); |
554 | f32 shininessValue = core::fast_atof(nsStr); | 554 | f32 shininessValue = core::fast_atof(nsStr); |
555 | 555 | ||
556 | // wavefront shininess is from [0, 1000], so scale for OpenGL | 556 | // wavefront shininess is from [0, 1000], so scale for OpenGL |
557 | shininessValue *= 0.128f; | 557 | shininessValue *= 0.128f; |
558 | currMaterial->Meshbuffer->Material.Shininess = shininessValue; | 558 | currMaterial->Meshbuffer->Material.Shininess = shininessValue; |
559 | } | 559 | } |
560 | break; | 560 | break; |
561 | case 'i': // Ni - refraction index | 561 | case 'i': // Ni - refraction index |
562 | { | 562 | { |
563 | c8 tmpbuf[WORD_BUFFER_LENGTH]; | 563 | c8 tmpbuf[WORD_BUFFER_LENGTH]; |
564 | bufPtr = goAndCopyNextWord(tmpbuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 564 | bufPtr = goAndCopyNextWord(tmpbuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
565 | } | 565 | } |
566 | break; | 566 | break; |
567 | } | 567 | } |
568 | } | 568 | } |
569 | break; | 569 | break; |
570 | case 'K': | 570 | case 'K': |
571 | if ( currMaterial ) | 571 | if ( currMaterial ) |
572 | { | 572 | { |
573 | switch(bufPtr[1]) | 573 | switch(bufPtr[1]) |
574 | { | 574 | { |
575 | case 'd': // Kd = diffuse | 575 | case 'd': // Kd = diffuse |
576 | { | 576 | { |
577 | bufPtr = readColor(bufPtr, currMaterial->Meshbuffer->Material.DiffuseColor, bufEnd); | 577 | bufPtr = readColor(bufPtr, currMaterial->Meshbuffer->Material.DiffuseColor, bufEnd); |
578 | 578 | ||
579 | } | 579 | } |
580 | break; | 580 | break; |
581 | 581 | ||
582 | case 's': // Ks = specular | 582 | case 's': // Ks = specular |
583 | { | 583 | { |
584 | bufPtr = readColor(bufPtr, currMaterial->Meshbuffer->Material.SpecularColor, bufEnd); | 584 | bufPtr = readColor(bufPtr, currMaterial->Meshbuffer->Material.SpecularColor, bufEnd); |
585 | } | 585 | } |
586 | break; | 586 | break; |
587 | 587 | ||
588 | case 'a': // Ka = ambience | 588 | case 'a': // Ka = ambience |
589 | { | 589 | { |
590 | bufPtr=readColor(bufPtr, currMaterial->Meshbuffer->Material.AmbientColor, bufEnd); | 590 | bufPtr=readColor(bufPtr, currMaterial->Meshbuffer->Material.AmbientColor, bufEnd); |
591 | } | 591 | } |
592 | break; | 592 | break; |
593 | case 'e': // Ke = emissive | 593 | case 'e': // Ke = emissive |
594 | { | 594 | { |
595 | bufPtr=readColor(bufPtr, currMaterial->Meshbuffer->Material.EmissiveColor, bufEnd); | 595 | bufPtr=readColor(bufPtr, currMaterial->Meshbuffer->Material.EmissiveColor, bufEnd); |
596 | } | 596 | } |
597 | break; | 597 | break; |
598 | } // end switch(bufPtr[1]) | 598 | } // end switch(bufPtr[1]) |
599 | } // end case 'K': if ( 0 != currMaterial )... | 599 | } // end case 'K': if ( 0 != currMaterial )... |
600 | break; | 600 | break; |
601 | case 'b': // bump | 601 | case 'b': // bump |
602 | case 'm': // texture maps | 602 | case 'm': // texture maps |
603 | if (currMaterial) | 603 | if (currMaterial) |
604 | { | 604 | { |
605 | bufPtr=readTextures(bufPtr, bufEnd, currMaterial, relPath); | 605 | bufPtr=readTextures(bufPtr, bufEnd, currMaterial, relPath); |
606 | } | 606 | } |
607 | break; | 607 | break; |
608 | case 'd': // d - transparency | 608 | case 'd': // d - transparency |
609 | if ( currMaterial ) | 609 | if ( currMaterial ) |
610 | { | 610 | { |
611 | const u32 COLOR_BUFFER_LENGTH = 16; | 611 | const u32 COLOR_BUFFER_LENGTH = 16; |
612 | c8 dStr[COLOR_BUFFER_LENGTH]; | 612 | c8 dStr[COLOR_BUFFER_LENGTH]; |
613 | 613 | ||
614 | bufPtr = goAndCopyNextWord(dStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); | 614 | bufPtr = goAndCopyNextWord(dStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); |
615 | f32 dValue = core::fast_atof(dStr); | 615 | f32 dValue = core::fast_atof(dStr); |
616 | 616 | ||
617 | currMaterial->Meshbuffer->Material.DiffuseColor.setAlpha( (s32)(dValue * 255) ); | 617 | currMaterial->Meshbuffer->Material.DiffuseColor.setAlpha( (s32)(dValue * 255) ); |
618 | if (dValue<1.0f) | 618 | if (dValue<1.0f) |
619 | currMaterial->Meshbuffer->Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; | 619 | currMaterial->Meshbuffer->Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; |
620 | } | 620 | } |
621 | break; | 621 | break; |
622 | case 'T': | 622 | case 'T': |
623 | if ( currMaterial ) | 623 | if ( currMaterial ) |
624 | { | 624 | { |
625 | switch ( bufPtr[1] ) | 625 | switch ( bufPtr[1] ) |
626 | { | 626 | { |
627 | case 'f': // Tf - Transmitivity | 627 | case 'f': // Tf - Transmitivity |
628 | const u32 COLOR_BUFFER_LENGTH = 16; | 628 | const u32 COLOR_BUFFER_LENGTH = 16; |
629 | c8 redStr[COLOR_BUFFER_LENGTH]; | 629 | c8 redStr[COLOR_BUFFER_LENGTH]; |
630 | c8 greenStr[COLOR_BUFFER_LENGTH]; | 630 | c8 greenStr[COLOR_BUFFER_LENGTH]; |
631 | c8 blueStr[COLOR_BUFFER_LENGTH]; | 631 | c8 blueStr[COLOR_BUFFER_LENGTH]; |
632 | 632 | ||
633 | bufPtr = goAndCopyNextWord(redStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); | 633 | bufPtr = goAndCopyNextWord(redStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); |
634 | bufPtr = goAndCopyNextWord(greenStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); | 634 | bufPtr = goAndCopyNextWord(greenStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); |
635 | bufPtr = goAndCopyNextWord(blueStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); | 635 | bufPtr = goAndCopyNextWord(blueStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); |
636 | 636 | ||
637 | f32 transparency = ( core::fast_atof(redStr) + core::fast_atof(greenStr) + core::fast_atof(blueStr) ) / 3; | 637 | f32 transparency = ( core::fast_atof(redStr) + core::fast_atof(greenStr) + core::fast_atof(blueStr) ) / 3; |
638 | 638 | ||
639 | currMaterial->Meshbuffer->Material.DiffuseColor.setAlpha( (s32)(transparency * 255) ); | 639 | currMaterial->Meshbuffer->Material.DiffuseColor.setAlpha( (s32)(transparency * 255) ); |
640 | if (transparency < 1.0f) | 640 | if (transparency < 1.0f) |
641 | currMaterial->Meshbuffer->Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; | 641 | currMaterial->Meshbuffer->Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA; |
642 | } | 642 | } |
643 | } | 643 | } |
644 | break; | 644 | break; |
645 | default: // comments or not recognised | 645 | default: // comments or not recognised |
646 | break; | 646 | break; |
647 | } // end switch(bufPtr[0]) | 647 | } // end switch(bufPtr[0]) |
648 | // go to next line | 648 | // go to next line |
649 | bufPtr = goNextLine(bufPtr, bufEnd); | 649 | bufPtr = goNextLine(bufPtr, bufEnd); |
650 | } // end while (bufPtr) | 650 | } // end while (bufPtr) |
651 | 651 | ||
652 | // end of file. if there's an existing material, store it | 652 | // end of file. if there's an existing material, store it |
653 | if ( currMaterial ) | 653 | if ( currMaterial ) |
654 | Materials.push_back( currMaterial ); | 654 | Materials.push_back( currMaterial ); |
655 | 655 | ||
656 | delete [] buf; | 656 | delete [] buf; |
657 | mtlReader->drop(); | 657 | mtlReader->drop(); |
658 | } | 658 | } |
659 | 659 | ||
660 | 660 | ||
661 | //! Read RGB color | 661 | //! Read RGB color |
662 | const c8* COBJMeshFileLoader::readColor(const c8* bufPtr, video::SColor& color, const c8* const bufEnd) | 662 | const c8* COBJMeshFileLoader::readColor(const c8* bufPtr, video::SColor& color, const c8* const bufEnd) |
663 | { | 663 | { |
664 | const u32 COLOR_BUFFER_LENGTH = 16; | 664 | const u32 COLOR_BUFFER_LENGTH = 16; |
665 | c8 colStr[COLOR_BUFFER_LENGTH]; | 665 | c8 colStr[COLOR_BUFFER_LENGTH]; |
666 | 666 | ||
667 | color.setAlpha(255); | 667 | color.setAlpha(255); |
668 | bufPtr = goAndCopyNextWord(colStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); | 668 | bufPtr = goAndCopyNextWord(colStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); |
669 | color.setRed((s32)(core::fast_atof(colStr) * 255.0f)); | 669 | color.setRed((s32)(core::fast_atof(colStr) * 255.0f)); |
670 | bufPtr = goAndCopyNextWord(colStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); | 670 | bufPtr = goAndCopyNextWord(colStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); |
671 | color.setGreen((s32)(core::fast_atof(colStr) * 255.0f)); | 671 | color.setGreen((s32)(core::fast_atof(colStr) * 255.0f)); |
672 | bufPtr = goAndCopyNextWord(colStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); | 672 | bufPtr = goAndCopyNextWord(colStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd); |
673 | color.setBlue((s32)(core::fast_atof(colStr) * 255.0f)); | 673 | color.setBlue((s32)(core::fast_atof(colStr) * 255.0f)); |
674 | return bufPtr; | 674 | return bufPtr; |
675 | } | 675 | } |
676 | 676 | ||
677 | 677 | ||
678 | //! Read 3d vector of floats | 678 | //! Read 3d vector of floats |
679 | const c8* COBJMeshFileLoader::readVec3(const c8* bufPtr, core::vector3df& vec, const c8* const bufEnd) | 679 | const c8* COBJMeshFileLoader::readVec3(const c8* bufPtr, core::vector3df& vec, const c8* const bufEnd) |
680 | { | 680 | { |
681 | const u32 WORD_BUFFER_LENGTH = 256; | 681 | const u32 WORD_BUFFER_LENGTH = 256; |
682 | c8 wordBuffer[WORD_BUFFER_LENGTH]; | 682 | c8 wordBuffer[WORD_BUFFER_LENGTH]; |
683 | 683 | ||
684 | bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 684 | bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
685 | vec.X=-core::fast_atof(wordBuffer); // change handedness | 685 | vec.X=-core::fast_atof(wordBuffer); // change handedness |
686 | bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 686 | bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
687 | vec.Y=core::fast_atof(wordBuffer); | 687 | vec.Y=core::fast_atof(wordBuffer); |
688 | bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 688 | bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
689 | vec.Z=core::fast_atof(wordBuffer); | 689 | vec.Z=core::fast_atof(wordBuffer); |
690 | return bufPtr; | 690 | return bufPtr; |
691 | } | 691 | } |
692 | 692 | ||
693 | 693 | ||
694 | //! Read 2d vector of floats | 694 | //! Read 2d vector of floats |
695 | const c8* COBJMeshFileLoader::readUV(const c8* bufPtr, core::vector2df& vec, const c8* const bufEnd) | 695 | const c8* COBJMeshFileLoader::readUV(const c8* bufPtr, core::vector2df& vec, const c8* const bufEnd) |
696 | { | 696 | { |
697 | const u32 WORD_BUFFER_LENGTH = 256; | 697 | const u32 WORD_BUFFER_LENGTH = 256; |
698 | c8 wordBuffer[WORD_BUFFER_LENGTH]; | 698 | c8 wordBuffer[WORD_BUFFER_LENGTH]; |
699 | 699 | ||
700 | bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 700 | bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
701 | vec.X=core::fast_atof(wordBuffer); | 701 | vec.X=core::fast_atof(wordBuffer); |
702 | bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd); | 702 | bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd); |
703 | vec.Y=1-core::fast_atof(wordBuffer); // change handedness | 703 | vec.Y=1-core::fast_atof(wordBuffer); // change handedness |
704 | return bufPtr; | 704 | return bufPtr; |
705 | } | 705 | } |
706 | 706 | ||
707 | 707 | ||
708 | //! Read boolean value represented as 'on' or 'off' | 708 | //! Read boolean value represented as 'on' or 'off' |
709 | const c8* COBJMeshFileLoader::readBool(const c8* bufPtr, bool& tf, const c8* const bufEnd) | 709 | const c8* COBJMeshFileLoader::readBool(const c8* bufPtr, bool& tf, const c8* const bufEnd) |
710 | { | 710 | { |
711 | const u32 BUFFER_LENGTH = 8; | 711 | const u32 BUFFER_LENGTH = 8; |
712 | c8 tfStr[BUFFER_LENGTH]; | 712 | c8 tfStr[BUFFER_LENGTH]; |
713 | 713 | ||
714 | bufPtr = goAndCopyNextWord(tfStr, bufPtr, BUFFER_LENGTH, bufEnd); | 714 | bufPtr = goAndCopyNextWord(tfStr, bufPtr, BUFFER_LENGTH, bufEnd); |
715 | tf = strcmp(tfStr, "off") != 0; | 715 | tf = strcmp(tfStr, "off") != 0; |
716 | return bufPtr; | 716 | return bufPtr; |
717 | } | 717 | } |
718 | 718 | ||
719 | 719 | ||
720 | COBJMeshFileLoader::SObjMtl* COBJMeshFileLoader::findMtl(const core::stringc& mtlName, const core::stringc& grpName) | 720 | COBJMeshFileLoader::SObjMtl* COBJMeshFileLoader::findMtl(const core::stringc& mtlName, const core::stringc& grpName) |
721 | { | 721 | { |
722 | COBJMeshFileLoader::SObjMtl* defMaterial = 0; | 722 | COBJMeshFileLoader::SObjMtl* defMaterial = 0; |
723 | // search existing Materials for best match | 723 | // search existing Materials for best match |
724 | // exact match does return immediately, only name match means a new group | 724 | // exact match does return immediately, only name match means a new group |
725 | for (u32 i = 0; i < Materials.size(); ++i) | 725 | for (u32 i = 0; i < Materials.size(); ++i) |
726 | { | 726 | { |
727 | if ( Materials[i]->Name == mtlName ) | 727 | if ( Materials[i]->Name == mtlName ) |
728 | { | 728 | { |
729 | if ( Materials[i]->Group == grpName ) | 729 | if ( Materials[i]->Group == grpName ) |
730 | return Materials[i]; | 730 | return Materials[i]; |
731 | else | 731 | else |
732 | defMaterial = Materials[i]; | 732 | defMaterial = Materials[i]; |
733 | } | 733 | } |
734 | } | 734 | } |
735 | // we found a partial match | 735 | // we found a partial match |
736 | if (defMaterial) | 736 | if (defMaterial) |
737 | { | 737 | { |
738 | Materials.push_back(new SObjMtl(*defMaterial)); | 738 | Materials.push_back(new SObjMtl(*defMaterial)); |
739 | Materials.getLast()->Group = grpName; | 739 | Materials.getLast()->Group = grpName; |
740 | return Materials.getLast(); | 740 | return Materials.getLast(); |
741 | } | 741 | } |
742 | // we found a new group for a non-existant material | 742 | // we found a new group for a non-existant material |
743 | else if (grpName.size()) | 743 | else if (grpName.size()) |
744 | { | 744 | { |
745 | Materials.push_back(new SObjMtl(*Materials[0])); | 745 | Materials.push_back(new SObjMtl(*Materials[0])); |
746 | Materials.getLast()->Group = grpName; | 746 | Materials.getLast()->Group = grpName; |
747 | return Materials.getLast(); | 747 | return Materials.getLast(); |
748 | } | 748 | } |
749 | return 0; | 749 | return 0; |
750 | } | 750 | } |
751 | 751 | ||
752 | 752 | ||
753 | //! skip space characters and stop on first non-space | 753 | //! skip space characters and stop on first non-space |
754 | const c8* COBJMeshFileLoader::goFirstWord(const c8* buf, const c8* const bufEnd, bool acrossNewlines) | 754 | const c8* COBJMeshFileLoader::goFirstWord(const c8* buf, const c8* const bufEnd, bool acrossNewlines) |
755 | { | 755 | { |
756 | // skip space characters | 756 | // skip space characters |
757 | if (acrossNewlines) | 757 | if (acrossNewlines) |
758 | while((buf != bufEnd) && core::isspace(*buf)) | 758 | while((buf != bufEnd) && core::isspace(*buf)) |
759 | ++buf; | 759 | ++buf; |
760 | else | 760 | else |
761 | while((buf != bufEnd) && core::isspace(*buf) && (*buf != '\n')) | 761 | while((buf != bufEnd) && core::isspace(*buf) && (*buf != '\n')) |
762 | ++buf; | 762 | ++buf; |
763 | 763 | ||
764 | return buf; | 764 | return buf; |
765 | } | 765 | } |
766 | 766 | ||
767 | 767 | ||
768 | //! skip current word and stop at beginning of next one | 768 | //! skip current word and stop at beginning of next one |
769 | const c8* COBJMeshFileLoader::goNextWord(const c8* buf, const c8* const bufEnd, bool acrossNewlines) | 769 | const c8* COBJMeshFileLoader::goNextWord(const c8* buf, const c8* const bufEnd, bool acrossNewlines) |
770 | { | 770 | { |
771 | // skip current word | 771 | // skip current word |
772 | while(( buf != bufEnd ) && !core::isspace(*buf)) | 772 | while(( buf != bufEnd ) && !core::isspace(*buf)) |
773 | ++buf; | 773 | ++buf; |
774 | 774 | ||
775 | return goFirstWord(buf, bufEnd, acrossNewlines); | 775 | return goFirstWord(buf, bufEnd, acrossNewlines); |
776 | } | 776 | } |
777 | 777 | ||
778 | 778 | ||
779 | //! Read until line break is reached and stop at the next non-space character | 779 | //! Read until line break is reached and stop at the next non-space character |
780 | const c8* COBJMeshFileLoader::goNextLine(const c8* buf, const c8* const bufEnd) | 780 | const c8* COBJMeshFileLoader::goNextLine(const c8* buf, const c8* const bufEnd) |
781 | { | 781 | { |
782 | // look for newline characters | 782 | // look for newline characters |
783 | while(buf != bufEnd) | 783 | while(buf != bufEnd) |
784 | { | 784 | { |
785 | // found it, so leave | 785 | // found it, so leave |
786 | if (*buf=='\n' || *buf=='\r') | 786 | if (*buf=='\n' || *buf=='\r') |
787 | break; | 787 | break; |
788 | ++buf; | 788 | ++buf; |
789 | } | 789 | } |
790 | return goFirstWord(buf, bufEnd); | 790 | return goFirstWord(buf, bufEnd); |
791 | } | 791 | } |
792 | 792 | ||
793 | 793 | ||
794 | u32 COBJMeshFileLoader::copyWord(c8* outBuf, const c8* const inBuf, u32 outBufLength, const c8* const bufEnd) | 794 | u32 COBJMeshFileLoader::copyWord(c8* outBuf, const c8* const inBuf, u32 outBufLength, const c8* const bufEnd) |
795 | { | 795 | { |
796 | if (!outBufLength) | 796 | if (!outBufLength) |
797 | return 0; | 797 | return 0; |
798 | if (!inBuf) | 798 | if (!inBuf) |
799 | { | 799 | { |
800 | *outBuf = 0; | 800 | *outBuf = 0; |
801 | return 0; | 801 | return 0; |
802 | } | 802 | } |
803 | 803 | ||
804 | u32 i = 0; | 804 | u32 i = 0; |
805 | while(inBuf[i]) | 805 | while(inBuf[i]) |
806 | { | 806 | { |
807 | if (core::isspace(inBuf[i]) || &(inBuf[i]) == bufEnd) | 807 | if (core::isspace(inBuf[i]) || &(inBuf[i]) == bufEnd) |
808 | break; | 808 | break; |
809 | ++i; | 809 | ++i; |
810 | } | 810 | } |
811 | 811 | ||
812 | u32 length = core::min_(i, outBufLength-1); | 812 | u32 length = core::min_(i, outBufLength-1); |
813 | for (u32 j=0; j<length; ++j) | 813 | for (u32 j=0; j<length; ++j) |
814 | outBuf[j] = inBuf[j]; | 814 | outBuf[j] = inBuf[j]; |
815 | 815 | ||
816 | outBuf[length] = 0; | 816 | outBuf[length] = 0; |
817 | return length; | 817 | return length; |
818 | } | 818 | } |
819 | 819 | ||
820 | 820 | ||
821 | core::stringc COBJMeshFileLoader::copyLine(const c8* inBuf, const c8* bufEnd) | 821 | core::stringc COBJMeshFileLoader::copyLine(const c8* inBuf, const c8* bufEnd) |
822 | { | 822 | { |
823 | if (!inBuf) | 823 | if (!inBuf) |
824 | return core::stringc(); | 824 | return core::stringc(); |
825 | 825 | ||
826 | const c8* ptr = inBuf; | 826 | const c8* ptr = inBuf; |
827 | while (ptr<bufEnd) | 827 | while (ptr<bufEnd) |
828 | { | 828 | { |
829 | if (*ptr=='\n' || *ptr=='\r') | 829 | if (*ptr=='\n' || *ptr=='\r') |
830 | break; | 830 | break; |
831 | ++ptr; | 831 | ++ptr; |
832 | } | 832 | } |
833 | // we must avoid the +1 in case the array is used up | 833 | // we must avoid the +1 in case the array is used up |
834 | return core::stringc(inBuf, (u32)(ptr-inBuf+((ptr < bufEnd) ? 1 : 0))); | 834 | return core::stringc(inBuf, (u32)(ptr-inBuf+((ptr < bufEnd) ? 1 : 0))); |
835 | } | 835 | } |
836 | 836 | ||
837 | 837 | ||
838 | const c8* COBJMeshFileLoader::goAndCopyNextWord(c8* outBuf, const c8* inBuf, u32 outBufLength, const c8* bufEnd) | 838 | const c8* COBJMeshFileLoader::goAndCopyNextWord(c8* outBuf, const c8* inBuf, u32 outBufLength, const c8* bufEnd) |
839 | { | 839 | { |
840 | inBuf = goNextWord(inBuf, bufEnd, false); | 840 | inBuf = goNextWord(inBuf, bufEnd, false); |
841 | copyWord(outBuf, inBuf, outBufLength, bufEnd); | 841 | copyWord(outBuf, inBuf, outBufLength, bufEnd); |
842 | return inBuf; | 842 | return inBuf; |
843 | } | 843 | } |
844 | 844 | ||
845 | 845 | ||
846 | bool COBJMeshFileLoader::retrieveVertexIndices(c8* vertexData, s32* idx, const c8* bufEnd, u32 vbsize, u32 vtsize, u32 vnsize) | 846 | bool COBJMeshFileLoader::retrieveVertexIndices(c8* vertexData, s32* idx, const c8* bufEnd, u32 vbsize, u32 vtsize, u32 vnsize) |
847 | { | 847 | { |
848 | c8 word[16] = ""; | 848 | c8 word[16] = ""; |
849 | const c8* p = goFirstWord(vertexData, bufEnd); | 849 | const c8* p = goFirstWord(vertexData, bufEnd); |
850 | u32 idxType = 0; // 0 = posIdx, 1 = texcoordIdx, 2 = normalIdx | 850 | u32 idxType = 0; // 0 = posIdx, 1 = texcoordIdx, 2 = normalIdx |
851 | 851 | ||
852 | u32 i = 0; | 852 | u32 i = 0; |
853 | while ( p != bufEnd ) | 853 | while ( p != bufEnd ) |
854 | { | 854 | { |
855 | if ( ( core::isdigit(*p)) || (*p == '-') ) | 855 | if ( ( core::isdigit(*p)) || (*p == '-') ) |
856 | { | 856 | { |
857 | // build up the number | 857 | // build up the number |
858 | word[i++] = *p; | 858 | word[i++] = *p; |
859 | } | 859 | } |
860 | else if ( *p == '/' || *p == ' ' || *p == '\0' ) | 860 | else if ( *p == '/' || *p == ' ' || *p == '\0' ) |
861 | { | 861 | { |
862 | // number is completed. Convert and store it | 862 | // number is completed. Convert and store it |
863 | word[i] = '\0'; | 863 | word[i] = '\0'; |
864 | // if no number was found index will become 0 and later on -1 by decrement | 864 | // if no number was found index will become 0 and later on -1 by decrement |
865 | idx[idxType] = core::strtol10(word); | 865 | idx[idxType] = core::strtol10(word); |
866 | if (idx[idxType]<0) | 866 | if (idx[idxType]<0) |
867 | { | 867 | { |
868 | switch (idxType) | 868 | switch (idxType) |
869 | { | 869 | { |
870 | case 0: | 870 | case 0: |
871 | idx[idxType] += vbsize; | 871 | idx[idxType] += vbsize; |
872 | break; | 872 | break; |
873 | case 1: | 873 | case 1: |
874 | idx[idxType] += vtsize; | 874 | idx[idxType] += vtsize; |
875 | break; | 875 | break; |
876 | case 2: | 876 | case 2: |
877 | idx[idxType] += vnsize; | 877 | idx[idxType] += vnsize; |
878 | break; | 878 | break; |
879 | } | 879 | } |
880 | } | 880 | } |
881 | else | 881 | else |
882 | idx[idxType]-=1; | 882 | idx[idxType]-=1; |
883 | 883 | ||
884 | // reset the word | 884 | // reset the word |
885 | word[0] = '\0'; | 885 | word[0] = '\0'; |
886 | i = 0; | 886 | i = 0; |
887 | 887 | ||
888 | // go to the next kind of index type | 888 | // go to the next kind of index type |
889 | if (*p == '/') | 889 | if (*p == '/') |
890 | { | 890 | { |
891 | if ( ++idxType > 2 ) | 891 | if ( ++idxType > 2 ) |
892 | { | 892 | { |
893 | // error checking, shouldn't reach here unless file is wrong | 893 | // error checking, shouldn't reach here unless file is wrong |
894 | idxType = 0; | 894 | idxType = 0; |
895 | } | 895 | } |
896 | } | 896 | } |
897 | else | 897 | else |
898 | { | 898 | { |
899 | // set all missing values to disable (=-1) | 899 | // set all missing values to disable (=-1) |
900 | while (++idxType < 3) | 900 | while (++idxType < 3) |
901 | idx[idxType]=-1; | 901 | idx[idxType]=-1; |
902 | ++p; | 902 | ++p; |
903 | break; // while | 903 | break; // while |
904 | } | 904 | } |
905 | } | 905 | } |
906 | 906 | ||
907 | // go to the next char | 907 | // go to the next char |
908 | ++p; | 908 | ++p; |
909 | } | 909 | } |
910 | 910 | ||
911 | return true; | 911 | return true; |
912 | } | 912 | } |
913 | 913 | ||
914 | 914 | ||
915 | void COBJMeshFileLoader::cleanUp() | 915 | void COBJMeshFileLoader::cleanUp() |
916 | { | 916 | { |
917 | for (u32 i=0; i < Materials.size(); ++i ) | 917 | for (u32 i=0; i < Materials.size(); ++i ) |
918 | { | 918 | { |
919 | Materials[i]->Meshbuffer->drop(); | 919 | Materials[i]->Meshbuffer->drop(); |
920 | delete Materials[i]; | 920 | delete Materials[i]; |
921 | } | 921 | } |
922 | 922 | ||
923 | Materials.clear(); | 923 | Materials.clear(); |
924 | } | 924 | } |
925 | 925 | ||
926 | 926 | ||
927 | } // end namespace scene | 927 | } // end namespace scene |
928 | } // end namespace irr | 928 | } // end namespace irr |
929 | 929 | ||
930 | #endif // _IRR_COMPILE_WITH_OBJ_LOADER_ | 930 | #endif // _IRR_COMPILE_WITH_OBJ_LOADER_ |
931 | 931 | ||