aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/COBJMeshFileLoader.cpp
diff options
context:
space:
mode:
authorDavid Walter Seikel2013-01-13 18:54:10 +1000
committerDavid Walter Seikel2013-01-13 18:54:10 +1000
commit959831f4ef5a3e797f576c3de08cd65032c997ad (patch)
treee7351908be5995f0b325b2ebeaa02d5a34b82583 /libraries/irrlicht-1.8/source/Irrlicht/COBJMeshFileLoader.cpp
parentAdd info about changes to Irrlicht. (diff)
downloadSledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.zip
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.gz
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.bz2
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.xz
Remove damned ancient DOS line endings from Irrlicht. Hopefully I did not go overboard.
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/COBJMeshFileLoader.cpp')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/COBJMeshFileLoader.cpp1862
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
20namespace irr 20namespace irr
21{ 21{
22namespace scene 22namespace 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
29static const u32 WORD_BUFFER_LENGTH = 512; 29static const u32 WORD_BUFFER_LENGTH = 512;
30 30
31//! Constructor 31//! Constructor
32COBJMeshFileLoader::COBJMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs) 32COBJMeshFileLoader::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
45COBJMeshFileLoader::~COBJMeshFileLoader() 45COBJMeshFileLoader::~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")
54bool COBJMeshFileLoader::isALoadableFileExtension(const io::path& filename) const 54bool 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.
64IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) 64IAnimatedMesh* 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
322const c8* COBJMeshFileLoader::readTextures(const c8* bufPtr, const c8* const bufEnd, SObjMtl* currMaterial, const io::path& relPath) 322const 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
481void COBJMeshFileLoader::readMTL(const c8* fileName, const io::path& relPath) 481void 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
662const c8* COBJMeshFileLoader::readColor(const c8* bufPtr, video::SColor& color, const c8* const bufEnd) 662const 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
679const c8* COBJMeshFileLoader::readVec3(const c8* bufPtr, core::vector3df& vec, const c8* const bufEnd) 679const 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
695const c8* COBJMeshFileLoader::readUV(const c8* bufPtr, core::vector2df& vec, const c8* const bufEnd) 695const 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'
709const c8* COBJMeshFileLoader::readBool(const c8* bufPtr, bool& tf, const c8* const bufEnd) 709const 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
720COBJMeshFileLoader::SObjMtl* COBJMeshFileLoader::findMtl(const core::stringc& mtlName, const core::stringc& grpName) 720COBJMeshFileLoader::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
754const c8* COBJMeshFileLoader::goFirstWord(const c8* buf, const c8* const bufEnd, bool acrossNewlines) 754const 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
769const c8* COBJMeshFileLoader::goNextWord(const c8* buf, const c8* const bufEnd, bool acrossNewlines) 769const 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
780const c8* COBJMeshFileLoader::goNextLine(const c8* buf, const c8* const bufEnd) 780const 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
794u32 COBJMeshFileLoader::copyWord(c8* outBuf, const c8* const inBuf, u32 outBufLength, const c8* const bufEnd) 794u32 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
821core::stringc COBJMeshFileLoader::copyLine(const c8* inBuf, const c8* bufEnd) 821core::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
838const c8* COBJMeshFileLoader::goAndCopyNextWord(c8* outBuf, const c8* inBuf, u32 outBufLength, const c8* bufEnd) 838const 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
846bool COBJMeshFileLoader::retrieveVertexIndices(c8* vertexData, s32* idx, const c8* bufEnd, u32 vbsize, u32 vtsize, u32 vnsize) 846bool 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
915void COBJMeshFileLoader::cleanUp() 915void 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