1 // Copyright (C) 2007-2012 Nikolaus Gebhardt
2 // This file is part of the "Irrlicht Engine".
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
4 
5 #include "CLWOMeshFileLoader.h"
6 #include "os.h"
7 #include "SAnimatedMesh.h"
8 #include "SMesh.h"
9 #include "IReadFile.h"
10 #include "ISceneManager.h"
11 #include "IFileSystem.h"
12 #include "IVideoDriver.h"
13 #include "IMeshManipulator.h"
14 
15 namespace irr
16 {
17 namespace scene
18 {
19 
20 #ifdef _DEBUG
21 #define LWO_READER_DEBUG
22 #endif
23 
24 #define charsToUIntD(a, b, c, d) ((a << 24) | (b << 16) | (c << 8) | d)
charsToUInt(const char * str)25 inline unsigned int charsToUInt(const char *str)
26 {
27 	return (str[0] << 24) | (str[1] << 16) | (str[2] << 8) | str[3];
28 }
29 
30 
31 struct tLWOTextureInfo
32 {
tLWOTextureInfoirr::scene::tLWOTextureInfo33 	tLWOTextureInfo() : UVTag(0), DUVTag(0), Flags(0), WidthWrap(2),
34 			HeightWrap(2), OpacType(0), Color(0xffffffff),
35 			Value(0.0f), AntiAliasing(1.0f), Opacity(1.0f),
36 			Axis(255), Projection(0), Active(false) {}
37 	core::stringc Type;
38 	core::stringc Map;
39 	core::stringc AlphaMap;
40 	core::stringc UVname;
41 	u16 UVTag;
42 	u16 DUVTag;
43 	u16 Flags;
44 	u16 WidthWrap;
45 	u16 HeightWrap;
46 	u16 OpacType;
47 	u16 IParam[3];
48 	core::vector3df Size;
49 	core::vector3df Center;
50 	core::vector3df Falloff;
51 	core::vector3df Velocity;
52 	video::SColor Color;
53 	f32 Value;
54 	f32 AntiAliasing;
55 	f32 Opacity;
56 	f32 FParam[3];
57 	u8 Axis;
58 	u8 Projection;
59 	bool Active;
60 };
61 
62 struct CLWOMeshFileLoader::tLWOMaterial
63 {
tLWOMaterialirr::scene::CLWOMeshFileLoader::tLWOMaterial64 	tLWOMaterial() : Meshbuffer(0), TagType(0), Flags(0), ReflMode(3), TranspMode(3),
65 		Glow(0), AlphaMode(2), Luminance(0.0f), Diffuse(1.0f), Specular(0.0f),
66 		Reflection(0.0f), Transparency(0.0f), Translucency(0.0f),
67 		Sharpness(0.0f), ReflSeamAngle(0.0f), ReflBlur(0.0f),
68 		RefrIndex(1.0f), TranspBlur(0.0f), SmoothingAngle(0.0f),
69 		EdgeTransparency(0.0f), HighlightColor(0.0f), ColorFilter(0.0f),
70 		AdditiveTransparency(0.0f), GlowIntensity(0.0f), GlowSize(0.0f),
71 		AlphaValue(0.0f), VertexColorIntensity(0.0f), VertexColor() {}
72 
73 	core::stringc Name;
74 	scene::SMeshBuffer *Meshbuffer;
75 	core::stringc ReflMap;
76 	u16 TagType;
77 	u16 Flags;
78 	u16 ReflMode;
79 	u16 TranspMode;
80 	u16 Glow;
81 	u16 AlphaMode;
82 	f32 Luminance;
83 	f32 Diffuse;
84 	f32 Specular;
85 	f32 Reflection;
86 	f32 Transparency;
87 	f32 Translucency;
88 	f32 Sharpness;
89 	f32 ReflSeamAngle;
90 	f32 ReflBlur;
91 	f32 RefrIndex;
92 	f32 TranspBlur;
93 	f32 SmoothingAngle;
94 	f32 EdgeTransparency;
95 	f32 HighlightColor;
96 	f32 ColorFilter;
97 	f32 AdditiveTransparency;
98 	f32 GlowIntensity;
99 	f32 GlowSize;
100 	f32 AlphaValue;
101 	f32 VertexColorIntensity;
102 	video::SColorf VertexColor;
103 	u32 Envelope[23];
104 	tLWOTextureInfo Texture[7];
105 };
106 
107 struct tLWOLayerInfo
108 {
109 	u16 Number;
110 	u16 Parent;
111 	u16 Flags;
112 	bool Active;
113 	core::stringc Name;
114 	core::vector3df Pivot;
115 };
116 
117 
118 //! Constructor
CLWOMeshFileLoader(scene::ISceneManager * smgr,io::IFileSystem * fs)119 CLWOMeshFileLoader::CLWOMeshFileLoader(scene::ISceneManager* smgr,
120 		io::IFileSystem* fs)
121 : SceneManager(smgr), FileSystem(fs), File(0), Mesh(0)
122 {
123 	#ifdef _DEBUG
124 	setDebugName("CLWOMeshFileLoader");
125 	#endif
126 }
127 
128 
129 //! destructor
~CLWOMeshFileLoader()130 CLWOMeshFileLoader::~CLWOMeshFileLoader()
131 {
132 	if (Mesh)
133 		Mesh->drop();
134 }
135 
136 
137 //! returns true if the file maybe is able to be loaded by this class
138 //! based on the file extension (e.g. ".bsp")
isALoadableFileExtension(const io::path & filename) const139 bool CLWOMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
140 {
141 	return core::hasFileExtension(filename, "lwo");
142 }
143 
144 
145 //! creates/loads an animated mesh from the file.
createMesh(io::IReadFile * file)146 IAnimatedMesh* CLWOMeshFileLoader::createMesh(io::IReadFile* file)
147 {
148 	File = file;
149 
150 	if (Mesh)
151 		Mesh->drop();
152 
153 	Mesh = new SMesh();
154 
155 	if (!readFileHeader())
156 		return 0;
157 
158 	if (!readChunks())
159 		return 0;
160 
161 #ifdef LWO_READER_DEBUG
162 	os::Printer::log("LWO loader: Creating geometry.");
163 	os::Printer::log("LWO loader: Assigning UV maps.");
164 #endif
165 	u32 i;
166 	for (i=0; i<Materials.size(); ++i)
167 	{
168 		u16 uvTag;
169 		for (u32 j=0; j<2; ++j) // max 2 texture coords
170 		{
171 			if (Materials[i]->Texture[j].UVname.size())
172 			{
173 				for (uvTag=0; uvTag<UvName.size(); ++uvTag)
174 				{
175 					if (Materials[i]->Texture[j].UVname == UvName[uvTag])
176 					{
177 						Materials[i]->Texture[j].UVTag=uvTag;
178 						break;
179 					}
180 				}
181 				for (uvTag=0; uvTag<DUvName.size(); ++uvTag)
182 				{
183 					if (Materials[i]->Texture[j].UVname == DUvName[uvTag])
184 					{
185 						Materials[i]->Texture[j].DUVTag=uvTag;
186 						break;
187 					}
188 				}
189 			}
190 		}
191 	}
192 #ifdef LWO_READER_DEBUG
193 	os::Printer::log("LWO loader: Creating polys.");
194 #endif
195 	// create actual geometry for lwo2
196 	if (FormatVersion==2)
197 	{
198 		core::array<u32> vertexCount;
199 		vertexCount.reallocate(Materials.size());
200 		for (i=0; i<Materials.size(); ++i)
201 			vertexCount.push_back(0);
202 		for (u32 polyIndex=0; polyIndex<Indices.size(); ++polyIndex)
203 			vertexCount[MaterialMapping[polyIndex]] += Indices[polyIndex].size();
204 		for (i=0; i<Materials.size(); ++i)
205 		{
206 			Materials[i]->Meshbuffer->Vertices.reallocate(vertexCount[i]);
207 			Materials[i]->Meshbuffer->Indices.reallocate(vertexCount[i]);
208 		}
209 	}
210 	// create actual geometry for lwo2
211 	for (u32 polyIndex=0; polyIndex<Indices.size(); ++polyIndex)
212 	{
213 		const u16 tag = MaterialMapping[polyIndex];
214 		scene::SMeshBuffer *mb=Materials[tag]->Meshbuffer;
215 		const core::array<u32>& poly = Indices[polyIndex];
216 		const u32 polySize=poly.size();
217 		const u16 uvTag = Materials[tag]->Texture[0].UVTag;
218 		const u16 duvTag = Materials[tag]->Texture[0].DUVTag;
219 		video::S3DVertex vertex;
220 		vertex.Color=0xffffffff;
221 		const u32 vertCount=mb->Vertices.size();
222 		for (u32 i=0; i<polySize; ++i)
223 		{
224 			const u32 j=poly[i];
225 			vertex.Pos=Points[j];
226 			if (uvTag<UvIndex.size())
227 			{
228 				for (u32 uvsearch=0; uvsearch < UvIndex[uvTag].size(); ++uvsearch)
229 				{
230 					if(j==UvIndex[uvTag][uvsearch])
231 					{
232 						vertex.TCoords=TCoords[uvTag][uvsearch];
233 						break;
234 					}
235 				}
236 				if (duvTag<DUvName.size())
237 				{
238 					for (u32 polysearch = 0; polysearch < VmPolyPointsIndex[duvTag].size(); polysearch += 2)
239 					{
240 						if (polyIndex==VmPolyPointsIndex[duvTag][polysearch] && j==VmPolyPointsIndex[duvTag][polysearch+1])
241 						{
242 							vertex.TCoords=VmCoordsIndex[duvTag][polysearch/2];
243 							break;
244 						}
245 					}
246 				}
247 			}
248 			mb->Vertices.push_back(vertex);
249 		}
250 		// triangulate as trifan
251 		if (polySize>2)
252 		{
253 			for (u32 i=1; i<polySize-1; ++i)
254 			{
255 				mb->Indices.push_back(vertCount);
256 				mb->Indices.push_back(vertCount+i);
257 				mb->Indices.push_back(vertCount+i+1);
258 			}
259 		}
260 	}
261 #ifdef LWO_READER_DEBUG
262 	os::Printer::log("LWO loader: Fixing meshbuffers.");
263 #endif
264 	for (u32 i=0; i<Materials.size(); ++i)
265 	{
266 #ifdef LWO_READER_DEBUG
267 		os::Printer::log("LWO loader: Material name", Materials[i]->Name);
268 		os::Printer::log("LWO loader: Vertex count", core::stringc(Materials[i]->Meshbuffer->Vertices.size()));
269 #endif
270 		if (!Materials[i]->Meshbuffer->Vertices.size())
271 		{
272 			Materials[i]->Meshbuffer->drop();
273 			delete Materials[i];
274 			continue;
275 		}
276 		for (u32 j=0; j<Materials[i]->Meshbuffer->Vertices.size(); ++j)
277 			Materials[i]->Meshbuffer->Vertices[j].Color=Materials[i]->Meshbuffer->Material.DiffuseColor;
278 		Materials[i]->Meshbuffer->recalculateBoundingBox();
279 
280 		// load textures
281 		video::SMaterial& irrMat=Materials[i]->Meshbuffer->Material;
282 		if (Materials[i]->Texture[0].Map != "") // diffuse
283 			irrMat.setTexture(0,loadTexture(Materials[i]->Texture[0].Map));
284 		if (Materials[i]->Texture[3].Map != "") // reflection
285 		{
286 #ifdef LWO_READER_DEBUG
287 			os::Printer::log("LWO loader: loading reflection texture.");
288 #endif
289 			video::ITexture* reflTexture = loadTexture(Materials[i]->Texture[3].Map);
290 			if (reflTexture && irrMat.getTexture(0))
291 				irrMat.setTexture(1, irrMat.getTexture(0));
292 			irrMat.setTexture(0, reflTexture);
293 			irrMat.MaterialType=video::EMT_REFLECTION_2_LAYER;
294 		}
295 		if (Materials[i]->Texture[4].Map != "") // transparency
296 		{
297 #ifdef LWO_READER_DEBUG
298 			os::Printer::log("LWO loader: loading transparency texture.");
299 #endif
300 			video::ITexture* transTexture = loadTexture(Materials[i]->Texture[4].Map);
301 			if (transTexture && irrMat.getTexture(0))
302 				irrMat.setTexture(1, irrMat.getTexture(0));
303 			irrMat.setTexture(0, transTexture);
304 			irrMat.MaterialType=video::EMT_TRANSPARENT_ADD_COLOR;
305 		}
306 		if (Materials[i]->Texture[6].Map != "") // bump
307 		{
308 #ifdef LWO_READER_DEBUG
309 			os::Printer::log("LWO loader: loading bump texture.");
310 #endif
311 			const u8 pos = irrMat.getTexture(0)?1:0;
312 			irrMat.setTexture(pos, loadTexture(Materials[i]->Texture[6].Map));
313 			if (irrMat.getTexture(pos))
314 			{
315 	//			SceneManager->getVideoDriver()->makeNormalMapTexture(irrMat.getTexture(1));
316 	//			irrMat.MaterialType=video::EMT_NORMAL_MAP_SOLID;
317 			}
318 		}
319 
320 		// cope with planar mapping texture coords
321 		if (Materials[i]->Texture[0].Projection != 5)
322 		{
323 			if (FormatVersion!=2)
324 			{
325 				if (Materials[i]->Texture[0].Flags&1)
326 					Materials[i]->Texture[0].Axis=0;
327 				else if (Materials[i]->Texture[0].Flags&2)
328 					Materials[i]->Texture[0].Axis=1;
329 				else if (Materials[i]->Texture[0].Flags&4)
330 					Materials[i]->Texture[0].Axis=2;
331 			}
332 			// if no axis given choose the dominant one
333 			else if (Materials[i]->Texture[0].Axis>2)
334 			{
335 				if (Materials[i]->Meshbuffer->getBoundingBox().getExtent().Y<Materials[i]->Meshbuffer->getBoundingBox().getExtent().X)
336 				{
337 					if (Materials[i]->Meshbuffer->getBoundingBox().getExtent().Y<Materials[i]->Meshbuffer->getBoundingBox().getExtent().Z)
338 						Materials[i]->Texture[0].Axis=1;
339 					else
340 						Materials[i]->Texture[0].Axis=2;
341 				}
342 				else
343 				{
344 					if (Materials[i]->Meshbuffer->getBoundingBox().getExtent().X<Materials[i]->Meshbuffer->getBoundingBox().getExtent().Z)
345 						Materials[i]->Texture[0].Axis=0;
346 					else
347 						Materials[i]->Texture[0].Axis=2;
348 				}
349 			}
350 			// get the resolution for this axis
351 			f32 resolutionS = core::reciprocal(Materials[i]->Texture[0].Size.Z);
352 			f32 resolutionT = core::reciprocal(Materials[i]->Texture[0].Size.Y);
353 			if (Materials[i]->Texture[0].Axis==1)
354 			{
355 				resolutionS = core::reciprocal(Materials[i]->Texture[0].Size.X);
356 				resolutionT = core::reciprocal(Materials[i]->Texture[0].Size.Z);
357 			}
358 			else if (Materials[i]->Texture[0].Axis==2)
359 			{
360 				resolutionS = core::reciprocal(Materials[i]->Texture[0].Size.X);
361 				resolutionT = core::reciprocal(Materials[i]->Texture[0].Size.Y);
362 			}
363 			// use the two-way planar mapping
364 			SceneManager->getMeshManipulator()->makePlanarTextureMapping(Materials[i]->Meshbuffer, resolutionS, resolutionT, Materials[i]->Texture[0].Axis, Materials[i]->Texture[0].Center);
365 		}
366 
367 		// add bump maps
368 		if (Materials[i]->Meshbuffer->Material.MaterialType==video::EMT_NORMAL_MAP_SOLID)
369 		{
370 			SMesh* tmpmesh = new SMesh();
371 			tmpmesh->addMeshBuffer(Materials[i]->Meshbuffer);
372 			SceneManager->getMeshManipulator()->createMeshWithTangents(tmpmesh, true, true);
373 			Mesh->addMeshBuffer(tmpmesh->getMeshBuffer(0));
374 			tmpmesh->getMeshBuffer(0)->drop();
375 			tmpmesh->drop();
376 		}
377 		else
378 		{
379 			SceneManager->getMeshManipulator()->recalculateNormals(Materials[i]->Meshbuffer);
380 			Mesh->addMeshBuffer(Materials[i]->Meshbuffer);
381 		}
382 		Materials[i]->Meshbuffer->drop();
383 		// clear the material array elements
384 		delete Materials[i];
385 	}
386 	Mesh->recalculateBoundingBox();
387 
388 	SAnimatedMesh* am = new SAnimatedMesh();
389 	am->Type = EAMT_3DS;
390 	am->addMesh(Mesh);
391 	am->recalculateBoundingBox();
392 	Mesh->drop();
393 	Mesh = 0;
394 
395 	Points.clear();
396 	Indices.clear();
397 	MaterialMapping.clear();
398 	TCoords.clear();
399 	Materials.clear();
400 	Images.clear();
401 	VmPolyPointsIndex.clear();
402 	VmCoordsIndex.clear();
403 	UvIndex.clear();
404 	UvName.clear();
405 
406 	return am;
407 }
408 
409 
readChunks()410 bool CLWOMeshFileLoader::readChunks()
411 {
412 	s32 lastPos;
413 	u32 size;
414 	unsigned int uiType;
415 	char type[5];
416 	type[4]=0;
417 	tLWOLayerInfo layer;
418 
419 	while(File->getPos()<File->getSize())
420 	{
421 		File->read(&type, 4);
422 		//Convert 4-char string to 4-byte integer
423 		//Makes it possible to do a switch statement
424 		uiType = charsToUInt(type);
425 		File->read(&size, 4);
426 #ifndef __BIG_ENDIAN__
427 		size=os::Byteswap::byteswap(size);
428 #endif
429 		lastPos=File->getPos();
430 
431 		switch(uiType)
432 		{
433 			case charsToUIntD('L','A','Y','R'):
434 				{
435 #ifdef LWO_READER_DEBUG
436 					os::Printer::log("LWO loader: loading layer.");
437 #endif
438 					u16 tmp16;
439 					File->read(&tmp16, 2); // number
440 					File->read(&tmp16, 2); // flags
441 					size -= 4;
442 #ifndef __BIG_ENDIAN__
443 					tmp16=os::Byteswap::byteswap(tmp16);
444 #endif
445 					if (((FormatVersion==1)&&(tmp16!=1)) ||
446 						((FormatVersion==2)&&(tmp16&1)))
447 						layer.Active=false;
448 					else
449 						layer.Active=true;
450 					if (FormatVersion==2)
451 						size -= readVec(layer.Pivot);
452 					size -= readString(layer.Name);
453 					if (size)
454 					{
455 						File->read(&tmp16, 2);
456 #ifndef __BIG_ENDIAN__
457 						tmp16=os::Byteswap::byteswap(tmp16);
458 #endif
459 						layer.Parent = tmp16;
460 					}
461 				}
462 				break;
463 			case charsToUIntD('P','N','T','S'):
464 				{
465 #ifdef LWO_READER_DEBUG
466 					os::Printer::log("LWO loader: loading points.");
467 #endif
468 					core::vector3df vec;
469 					Points.clear();
470 					const u32 tmpsize = size/12;
471 					Points.reallocate(tmpsize);
472 					for (u32 i=0; i<tmpsize; ++i)
473 					{
474 						readVec(vec);
475 						Points.push_back(vec);
476 					}
477 				}
478 				break;
479 			case charsToUIntD('V','M','A','P'):
480 #ifdef LWO_READER_DEBUG
481 				os::Printer::log("LWO loader: loading Vertex mapping.");
482 #endif
483 				readVertexMapping(size);
484 				break;
485 			case charsToUIntD('P','O','L','S'):
486 			case charsToUIntD('P','T','C','H'): // TODO: should be a subdivison mesh
487 #ifdef LWO_READER_DEBUG
488 				os::Printer::log("LWO loader: loading polygons.");
489 #endif
490 				if (FormatVersion!=2)
491 					readObj1(size);
492 				else
493 					readObj2(size);
494 #ifdef LWO_READER_DEBUG
495 				os::Printer::log("LWO loader: Done loading polygons.");
496 #endif
497 				break;
498 			case charsToUIntD('T','A','G','S'):
499 			case charsToUIntD('S','R','F','S'):
500 				{
501 #ifdef LWO_READER_DEBUG
502 					os::Printer::log("LWO loader: loading surface names.");
503 #endif
504 					while (size!=0)
505 					{
506 						tLWOMaterial *mat=new tLWOMaterial();
507 						mat->Name="";
508 						mat->Meshbuffer=new scene::SMeshBuffer();
509 						size -= readString(mat->Name);
510 						if (FormatVersion!=2)
511 							mat->TagType = 1; // format 2 has more types
512 						Materials.push_back(mat);
513 					}
514 				}
515 				break;
516 			case charsToUIntD('P','T','A','G'):
517 #ifdef LWO_READER_DEBUG
518 				os::Printer::log("LWO loader: loading tag mapping.");
519 #endif
520 				readTagMapping(size);
521 				break;
522 			case charsToUIntD('V','M','A','D'): // discontinuous vertex mapping, i.e. additional texcoords
523 #ifdef LWO_READER_DEBUG
524 				os::Printer::log("LWO loader: loading Vertex mapping VMAD.");
525 #endif
526 				readDiscVertexMapping(size);
527 //			case charsToUIntD('V','M','P','A'):
528 //			case charsToUIntD('E','N','V','L'):
529 				break;
530 			case charsToUIntD('C','L','I','P'):
531 				{
532 #ifdef LWO_READER_DEBUG
533 					os::Printer::log("LWO loader: loading clips.");
534 #endif
535 					u32 index;
536 					u16 subsize;
537 					File->read(&index, 4);
538 #ifndef __BIG_ENDIAN__
539 					index=os::Byteswap::byteswap(index);
540 #endif
541 					size -= 4;
542 					while (size != 0)
543 					{
544 						File->read(&type, 4);
545 						File->read(&subsize, 2);
546 #ifndef __BIG_ENDIAN__
547 						subsize=os::Byteswap::byteswap(subsize);
548 #endif
549 						size -= 6;
550 						if (strncmp(type, "STIL", 4))
551 						{
552 							File->seek(subsize, true);
553 							size -= subsize;
554 							continue;
555 						}
556 						core::stringc path;
557 						size -= readString(path, subsize);
558 	#ifdef LWO_READER_DEBUG
559 						os::Printer::log("LWO loader: loaded clip", path.c_str());
560 	#endif
561 						Images.push_back(path);
562 					}
563 				}
564 				break;
565 			case charsToUIntD('S','U','R','F'):
566 #ifdef LWO_READER_DEBUG
567 				os::Printer::log("LWO loader: loading material.");
568 #endif
569 				readMat(size);
570 				break;
571 			case charsToUIntD('B','B','O','X'):
572 				{
573 #ifdef LWO_READER_DEBUG
574 					os::Printer::log("LWO loader: loading bbox.");
575 #endif
576 					// not stored
577 					core::vector3df vec;
578 					for (u32 i=0; i<2; ++i)
579 						readVec(vec);
580 					size -= 24;
581 				}
582 				break;
583 			case charsToUIntD('D','E','S','C'):
584 			case charsToUIntD('T','E','X','T'):
585 				{
586 					core::stringc text;
587 					size -= readString(text, size);
588 #ifdef LWO_READER_DEBUG
589 					os::Printer::log("LWO loader text", text);
590 #endif
591 				}
592 				break;
593 			// not needed
594 			case charsToUIntD('I','C','O','N'):
595 			// not yet supported
596 			case charsToUIntD('P','C','H','S'):
597 			case charsToUIntD('C','R','V','S'):
598 			default:
599 #ifdef LWO_READER_DEBUG
600 				os::Printer::log("LWO loader: skipping ", type);
601 #endif
602 				//Go to next chunk
603 				File->seek(lastPos + size, false);
604 				break;
605 		}
606 	}
607 	return true;
608 }
609 
610 
readObj1(u32 size)611 void CLWOMeshFileLoader::readObj1(u32 size)
612 {
613 	u32 pos;
614 	u16 numVerts, vertIndex;
615 	s16 material;
616 	video::S3DVertex vertex;
617 	vertex.Color=0xffffffff;
618 
619 	while (size!=0)
620 	{
621 		File->read(&numVerts, 2);
622 #ifndef __BIG_ENDIAN__
623 		numVerts=os::Byteswap::byteswap(numVerts);
624 #endif
625 		pos=File->getPos();
626 		// skip forward to material number
627 		File->seek(2*numVerts, true);
628 		File->read(&material, 2);
629 #ifndef __BIG_ENDIAN__
630 		material=os::Byteswap::byteswap(material);
631 #endif
632 		size -=2*numVerts+4;
633 		// detail meshes ?
634 		scene::SMeshBuffer *mb;
635 		if (material<0)
636 			mb=Materials[-material-1]->Meshbuffer;
637 		else
638 			mb=Materials[material-1]->Meshbuffer;
639 		// back to vertex list start
640 		File->seek(pos, false);
641 
642 		const u16 vertCount=mb->Vertices.size();
643 		for (u16 i=0; i<numVerts; ++i)
644 		{
645 			File->read(&vertIndex, 2);
646 #ifndef __BIG_ENDIAN__
647 			vertIndex=os::Byteswap::byteswap(vertIndex);
648 #endif
649 			vertex.Pos=Points[vertIndex];
650 			mb->Vertices.push_back(vertex);
651 		}
652 		for (u16 i=1; i<numVerts-1; ++i)
653 		{
654 			mb->Indices.push_back(vertCount);
655 			mb->Indices.push_back(vertCount+i);
656 			mb->Indices.push_back(vertCount+i+1);
657 		}
658 		// skip material number and detail surface count
659 		// detail surface can be read just as a normal one now
660 		if (material<0)
661 			File->read(&material, 2);
662 		File->read(&material, 2);
663 	}
664 }
665 
666 
readVertexMapping(u32 size)667 void CLWOMeshFileLoader::readVertexMapping(u32 size)
668 {
669 	char type[5]={0};
670 	u16 dimension;
671 	core::stringc name;
672 	File->read(&type, 4);
673 #ifdef LWO_READER_DEBUG
674 	os::Printer::log("LWO loader: Vertex map type", type);
675 #endif
676 	File->read(&dimension,2);
677 #ifndef __BIG_ENDIAN__
678 	dimension=os::Byteswap::byteswap(dimension);
679 #endif
680 	size -= 6;
681 	size -= readString(name);
682 #ifdef LWO_READER_DEBUG
683 	os::Printer::log("LWO loader: Vertex map", name.c_str());
684 #endif
685 	if (strncmp(type, "TXUV", 4)) // also support RGB, RGBA, WGHT, ...
686 	{
687 		File->seek(size, true);
688 		return;
689 	}
690 	UvName.push_back(name);
691 
692 	TCoords.push_back(core::array<core::vector2df>());
693 	core::array<core::vector2df>& UvCoords=TCoords.getLast();
694 	UvCoords.reallocate(Points.size());
695 	UvIndex.push_back(core::array<u32>());
696 	core::array<u32>& UvPointsArray=UvIndex.getLast();
697 	UvPointsArray.reallocate(Points.size());
698 
699 	u32 index;
700 	core::vector2df tcoord;
701 	while (size)
702 	{
703 		size -= readVX(index);
704 		File->read(&tcoord.X, 4);
705 		File->read(&tcoord.Y, 4);
706 		size -= 8;
707 #ifndef __BIG_ENDIAN__
708 		index=os::Byteswap::byteswap(index);
709 		tcoord.X=os::Byteswap::byteswap(tcoord.X);
710 		tcoord.Y=os::Byteswap::byteswap(tcoord.Y);
711 #endif
712 		UvCoords.push_back(tcoord);
713 		UvPointsArray.push_back(index);
714 	}
715 #ifdef LWO_READER_DEBUG
716 	os::Printer::log("LWO loader: UvCoords", core::stringc(UvCoords.size()));
717 #endif
718 }
719 
720 
readDiscVertexMapping(u32 size)721 void CLWOMeshFileLoader::readDiscVertexMapping(u32 size)
722 {
723 	char type[5]={0};
724 	u16 dimension;
725 	core::stringc name;
726 	File->read(&type, 4);
727 #ifdef LWO_READER_DEBUG
728 	os::Printer::log("LWO loader: Discontinuous vertex map type", type);
729 #endif
730 	File->read(&dimension,2);
731 #ifndef __BIG_ENDIAN__
732 	dimension=os::Byteswap::byteswap(dimension);
733 #endif
734 	size -= 6;
735 	size -= readString(name);
736 #ifdef LWO_READER_DEBUG
737 	os::Printer::log("LWO loader: Discontinuous vertex map", name.c_str());
738 #endif
739 	if (strncmp(type, "TXUV", 4))
740 	{
741 		File->seek(size, true);
742 		return;
743 	}
744 	DUvName.push_back(name);
745 	VmPolyPointsIndex.push_back(core::array<u32>());
746 	core::array<u32>& VmPolyPoints=VmPolyPointsIndex.getLast();
747 
748 	VmCoordsIndex.push_back(core::array<core::vector2df>());
749 	core::array<core::vector2df>& VmCoords=VmCoordsIndex.getLast();
750 
751 	u32 vmpolys;
752 	u32 vmpoints;
753 	core::vector2df vmcoords;
754 	while (size)
755 	{
756 		size-=readVX(vmpoints);
757 		size-=readVX(vmpolys);
758 		File->read(&vmcoords.X, 4);
759 		File->read(&vmcoords.Y, 4);
760 		size -= 8;
761 #ifndef __BIG_ENDIAN__
762 		vmpoints=os::Byteswap::byteswap(vmpoints);
763 		vmpolys=os::Byteswap::byteswap(vmpolys);
764 		vmcoords.X=os::Byteswap::byteswap(vmcoords.X);
765 		vmcoords.Y=os::Byteswap::byteswap(vmcoords.Y);
766 #endif
767 		VmCoords.push_back(vmcoords);
768 		VmPolyPoints.push_back(vmpolys);
769 		VmPolyPoints.push_back(vmpoints);
770 	}
771 #ifdef LWO_READER_DEBUG
772 	os::Printer::log("LWO loader: VmCoords", core::stringc(VmCoords.size()));
773 #endif
774 }
775 
776 
readTagMapping(u32 size)777 void CLWOMeshFileLoader::readTagMapping(u32 size)
778 {
779 	char type[5];
780 	type[4]=0;
781 	File->read(&type, 4);
782 	size -= 4;
783 	if ((strncmp(type, "SURF", 4))||(Indices.size()==0))
784 	{
785 		File->seek(size, true);
786 		return;
787 	}
788 
789 	while (size!=0)
790 	{
791 		u16 tag;
792 		u32 polyIndex;
793 		size-=readVX(polyIndex);
794 		File->read(&tag, 2);
795 #ifndef __BIG_ENDIAN__
796 		tag=os::Byteswap::byteswap(tag);
797 #endif
798 		size -= 2;
799 		MaterialMapping[polyIndex]=tag;
800 		Materials[tag]->TagType=1;
801 	}
802 }
803 
804 
readObj2(u32 size)805 void CLWOMeshFileLoader::readObj2(u32 size)
806 {
807 	char type[5];
808 	type[4]=0;
809 	File->read(&type, 4);
810 	size -= 4;
811 	Indices.clear();
812 	if (strncmp(type, "FACE", 4)) // also possible are splines, subdivision patches, metaballs, and bones
813 	{
814 		File->seek(size, true);
815 		return;
816 	}
817 	u16 numVerts=0;
818 	while (size!=0)
819 	{
820 		File->read(&numVerts, 2);
821 #ifndef __BIG_ENDIAN__
822 		numVerts=os::Byteswap::byteswap(numVerts);
823 #endif
824 		// mask out flags
825 		numVerts &= 0x03FF;
826 
827 		size -= 2;
828 		Indices.push_back(core::array<u32>());
829 		u32 vertIndex;
830 		core::array<u32>& polyArray = Indices.getLast();
831 		polyArray.reallocate(numVerts);
832 		for (u16 i=0; i<numVerts; ++i)
833 		{
834 			size -= readVX(vertIndex);
835 			polyArray.push_back(vertIndex);
836 		}
837 	}
838 	MaterialMapping.reallocate(Indices.size());
839 	for (u32 j=0; j<Indices.size(); ++j)
840 		MaterialMapping.push_back(0);
841 }
842 
843 
readMat(u32 size)844 void CLWOMeshFileLoader::readMat(u32 size)
845 {
846 	core::stringc name;
847 
848 	tLWOMaterial* mat=0;
849 	size -= readString(name);
850 #ifdef LWO_READER_DEBUG
851 	os::Printer::log("LWO loader: material name", name.c_str());
852 #endif
853 	for (u32 i=0; i<Materials.size(); ++i)
854 	{
855 		if ((Materials[i]->TagType==1) && (Materials[i]->Name==name))
856 		{
857 			mat=Materials[i];
858 			break;
859 		}
860 	}
861 	if (!mat)
862 	{
863 		File->seek(size, true);
864 		return;
865 	}
866 	if (FormatVersion==2)
867 		size -= readString(name);
868 
869 	video::SMaterial& irrMat=mat->Meshbuffer->Material;
870 
871 	u8 currTexture=0;
872 	while (size!=0)
873 	{
874 		char type[5];
875 		type[4]=0;
876 		u32 uiType;
877 		u32 tmp32;
878 		u16 subsize, tmp16;
879 		f32 tmpf32;
880 		File->read(&type, 4);
881 		//Convert 4-char string to 4-byte integer
882 		//Makes it possible to do a switch statement
883 		uiType = charsToUInt(type);
884 		File->read(&subsize, 2);
885 #ifndef __BIG_ENDIAN__
886 		subsize=os::Byteswap::byteswap(subsize);
887 #endif
888 		size -= 6;
889 		switch (uiType)
890 		{
891 			case charsToUIntD('C','O','L','R'):
892 #ifdef LWO_READER_DEBUG
893 				os::Printer::log("LWO loader: loading Ambient color.");
894 #endif
895 				{
896 					s32 colSize = readColor(irrMat.DiffuseColor);
897 					irrMat.AmbientColor=irrMat.DiffuseColor;
898 					size -= colSize;
899 					subsize -= colSize;
900 					if (FormatVersion==2)
901 						size -= readVX(mat->Envelope[0]);
902 				}
903 				break;
904 			case charsToUIntD('D','I','F','F'):
905 #ifdef LWO_READER_DEBUG
906 				os::Printer::log("LWO loader: loading Diffuse color.");
907 #endif
908 				{
909 					if (FormatVersion==2)
910 					{
911 						File->read(&mat->Diffuse, 4);
912 #ifndef __BIG_ENDIAN__
913 						mat->Diffuse=os::Byteswap::byteswap(mat->Diffuse);
914 #endif
915 						size -= 4;
916 						subsize -= 4;
917 						size -= readVX(mat->Envelope[1]);
918 					}
919 					else
920 					{
921 						File->read(&tmp16, 2);
922 #ifndef __BIG_ENDIAN__
923 						tmp16=os::Byteswap::byteswap(tmp16);
924 #endif
925 						mat->Diffuse=tmp16/256.0f;
926 						size -= 2;
927 						subsize -= 2;
928 					}
929 				}
930 				break;
931 			case charsToUIntD('V','D','I','F'):
932 #ifdef LWO_READER_DEBUG
933 				os::Printer::log("LWO loader: loading Diffuse color.");
934 #endif
935 				{
936 					File->read(&mat->Diffuse, 4);
937 #ifndef __BIG_ENDIAN__
938 					mat->Diffuse=os::Byteswap::byteswap(mat->Diffuse);
939 #endif
940 					size -= 4;
941 				}
942 				break;
943 			case charsToUIntD('L','U','M','I'):
944 #ifdef LWO_READER_DEBUG
945 				os::Printer::log("LWO loader: loading luminance.");
946 #endif
947 				{
948 					if (FormatVersion==2)
949 					{
950 						File->read(&mat->Luminance, 4);
951 #ifndef __BIG_ENDIAN__
952 						mat->Luminance=os::Byteswap::byteswap(mat->Luminance);
953 #endif
954 						size -= 4;
955 						subsize -= 4;
956 						size -= readVX(mat->Envelope[2]);
957 					}
958 					else
959 					{
960 						File->read(&tmp16, 2);
961 #ifndef __BIG_ENDIAN__
962 						tmp16=os::Byteswap::byteswap(tmp16);
963 #endif
964 						mat->Luminance=tmp16/256.0f;
965 						size -= 2;
966 						subsize -= 2;
967 					}				}
968 				break;
969 			case charsToUIntD('V','L','U','M'):
970 #ifdef LWO_READER_DEBUG
971 				os::Printer::log("LWO loader: loading luminance.");
972 #endif
973 				{
974 					File->read(&mat->Luminance, 4);
975 #ifndef __BIG_ENDIAN__
976 					mat->Luminance=os::Byteswap::byteswap(mat->Luminance);
977 #endif
978 					size -= 4;
979 				}
980 				break;
981 			case charsToUIntD('S','P','E','C'):
982 #ifdef LWO_READER_DEBUG
983 				os::Printer::log("LWO loader: loading specular.");
984 #endif
985 				{
986 					if (FormatVersion==2)
987 					{
988 						File->read(&mat->Specular, 4);
989 #ifndef __BIG_ENDIAN__
990 						mat->Specular=os::Byteswap::byteswap(mat->Specular);
991 #endif
992 						size -= 4;
993 						subsize -= 4;
994 						size -= readVX(mat->Envelope[3]);
995 					}
996 					else
997 					{
998 						File->read(&tmp16, 2);
999 #ifndef __BIG_ENDIAN__
1000 						tmp16=os::Byteswap::byteswap(tmp16);
1001 #endif
1002 						mat->Specular=tmp16/256.0f;;
1003 						size -= 2;
1004 						subsize -= 2;
1005 					}
1006 				}
1007 				break;
1008 			case charsToUIntD('V','S','P','C'):
1009 #ifdef LWO_READER_DEBUG
1010 				os::Printer::log("LWO loader: loading specular.");
1011 #endif
1012 				{
1013 					File->read(&mat->Specular, 4);
1014 #ifndef __BIG_ENDIAN__
1015 					mat->Specular=os::Byteswap::byteswap(mat->Specular);
1016 #endif
1017 					size -= 4;
1018 				}
1019 				break;
1020 			case charsToUIntD('R','E','F','L'):
1021 #ifdef LWO_READER_DEBUG
1022 				os::Printer::log("LWO loader: loading reflection.");
1023 #endif
1024 				{
1025 					if (FormatVersion==2)
1026 					{
1027 						File->read(&mat->Reflection, 4);
1028 #ifndef __BIG_ENDIAN__
1029 						mat->Reflection=os::Byteswap::byteswap(mat->Reflection);
1030 #endif
1031 						size -= 4;
1032 						subsize -= 4;
1033 						size -= readVX(mat->Envelope[4]);
1034 					}
1035 					else
1036 					{
1037 						File->read(&tmp16, 2);
1038 #ifndef __BIG_ENDIAN__
1039 						tmp16=os::Byteswap::byteswap(tmp16);
1040 #endif
1041 						mat->Reflection=tmp16/256.0f;
1042 						size -= 2;
1043 						subsize -= 2;
1044 					}
1045 				}
1046 				break;
1047 			case charsToUIntD('V','R','F','L'):
1048 #ifdef LWO_READER_DEBUG
1049 				os::Printer::log("LWO loader: loading reflection.");
1050 #endif
1051 				{
1052 					File->read(&mat->Reflection, 4);
1053 #ifndef __BIG_ENDIAN__
1054 					mat->Reflection=os::Byteswap::byteswap(mat->Reflection);
1055 #endif
1056 					size -= 4;
1057 				}
1058 				break;
1059 			case charsToUIntD('T','R','A','N'):
1060 				{
1061 					if (FormatVersion==2)
1062 					{
1063 						File->read(&mat->Transparency, 4);
1064 #ifndef __BIG_ENDIAN__
1065 						mat->Transparency=os::Byteswap::byteswap(mat->Transparency);
1066 #endif
1067 						size -= 4;
1068 						subsize -= 4;
1069 						size -= readVX(mat->Envelope[5]);
1070 					}
1071 					else
1072 					{
1073 						File->read(&tmp16, 2);
1074 #ifndef __BIG_ENDIAN__
1075 						tmp16=os::Byteswap::byteswap(tmp16);
1076 #endif
1077 						mat->Transparency=tmp16/256.0f;
1078 						size -= 2;
1079 						subsize -= 2;
1080 					}
1081 #ifdef LWO_READER_DEBUG
1082 				os::Printer::log("LWO loader: loading transparency", core::stringc(mat->Transparency).c_str());
1083 #endif
1084 				}
1085 				break;
1086 			case charsToUIntD('V','T','R','N'):
1087 				{
1088 					File->read(&mat->Transparency, 4);
1089 #ifndef __BIG_ENDIAN__
1090 					mat->Transparency=os::Byteswap::byteswap(mat->Transparency);
1091 #endif
1092 					size -= 4;
1093 				}
1094 #ifdef LWO_READER_DEBUG
1095 				os::Printer::log("LWO loader: loading transparency", core::stringc(mat->Transparency).c_str());
1096 #endif
1097 				break;
1098 			case charsToUIntD('T','R','N','L'):
1099 #ifdef LWO_READER_DEBUG
1100 				os::Printer::log("LWO loader: loading translucency.");
1101 #endif
1102 				{
1103 					File->read(&mat->Translucency, 4);
1104 #ifndef __BIG_ENDIAN__
1105 					mat->Translucency=os::Byteswap::byteswap(mat->Translucency);
1106 #endif
1107 					size -= 4;
1108 					subsize -= 4;
1109 					if (FormatVersion==2)
1110 						size -= readVX(mat->Envelope[6]);
1111 				}
1112 				break;
1113 			case charsToUIntD('G','L','O','S'):
1114 #ifdef LWO_READER_DEBUG
1115 				os::Printer::log("LWO loader: loading glossy.");
1116 #endif
1117 				{
1118 					if (FormatVersion == 2)
1119 					{
1120 						File->read(&irrMat.Shininess, 4);
1121 #ifndef __BIG_ENDIAN__
1122 						irrMat.Shininess=os::Byteswap::byteswap(irrMat.Shininess);
1123 #endif
1124 						size -= 4;
1125 						subsize -= 4;
1126 						size -= readVX(mat->Envelope[7]);
1127 					}
1128 					else
1129 					{
1130 						File->read(&tmp16, 2);
1131 #ifndef __BIG_ENDIAN__
1132 						tmp16=os::Byteswap::byteswap(tmp16);
1133 #endif
1134 						irrMat.Shininess=tmp16/16.f;
1135 						size -= 2;
1136 						subsize -= 2;
1137 					}
1138 				}
1139 				break;
1140 			case charsToUIntD('S','H','R','P'):
1141 #ifdef LWO_READER_DEBUG
1142 				os::Printer::log("LWO loader: loading sharpness.");
1143 #endif
1144 				{
1145 					File->read(&mat->Sharpness, 4);
1146 #ifndef __BIG_ENDIAN__
1147 					mat->Sharpness=os::Byteswap::byteswap(mat->Sharpness);
1148 #endif
1149 					size -= 4;
1150 					subsize -= 4;
1151 					if (FormatVersion==2)
1152 						size -= readVX(mat->Envelope[8]);
1153 				}
1154 				break;
1155 			case charsToUIntD('B','U','M','P'):
1156 			case charsToUIntD('T','A','M','P'):
1157 #ifdef LWO_READER_DEBUG
1158 				os::Printer::log("LWO loader: loading bumpiness.");
1159 #endif
1160 				{
1161 					File->read(&tmpf32, 4);
1162 #ifndef __BIG_ENDIAN__
1163 						tmpf32=os::Byteswap::byteswap(tmpf32);
1164 #endif
1165 					if (currTexture==6)
1166 						irrMat.MaterialTypeParam=tmpf32;
1167 					size -= 4;
1168 					subsize -= 4;
1169 					if (FormatVersion==2)
1170 						size -= readVX(mat->Envelope[9]);
1171 				}
1172 				break;
1173 			case charsToUIntD('S','I','D','E'):
1174 #ifdef LWO_READER_DEBUG
1175 				os::Printer::log("LWO loader: loading backface culled.");
1176 #endif
1177 				{
1178 					File->read(&tmp16, 2);
1179 #ifndef __BIG_ENDIAN__
1180 					tmp16=os::Byteswap::byteswap(tmp16);
1181 #endif
1182 					if (tmp16==1)
1183 						irrMat.BackfaceCulling=true;
1184 					else if (tmp16==3)
1185 						irrMat.BackfaceCulling=false;
1186 					size -= 2;
1187 				}
1188 				break;
1189 			case charsToUIntD('S','M','A','N'):
1190 #ifdef LWO_READER_DEBUG
1191 				os::Printer::log("LWO loader: loading smoothing angle.");
1192 #endif
1193 				{
1194 					File->read(&mat->SmoothingAngle, 4);
1195 #ifndef __BIG_ENDIAN__
1196 					mat->SmoothingAngle=os::Byteswap::byteswap(mat->SmoothingAngle);
1197 #endif
1198 					size -= 4;
1199 				}
1200 				break;
1201 			case charsToUIntD('R','F','O','P'):
1202 			case charsToUIntD('R','F','L','T'):
1203 #ifdef LWO_READER_DEBUG
1204 				os::Printer::log("LWO loader: loading reflection mode.");
1205 #endif
1206 				{
1207 					File->read(&mat->ReflMode, 2);
1208 #ifndef __BIG_ENDIAN__
1209 					mat->ReflMode=os::Byteswap::byteswap(mat->ReflMode);
1210 #endif
1211 					size -= 2;
1212 				}
1213 				break;
1214 			case charsToUIntD('R','I','M','G'):
1215 #ifdef LWO_READER_DEBUG
1216 				os::Printer::log("LWO loader: loading reflection map.");
1217 #endif
1218 				{
1219 					if (FormatVersion==2)
1220 					{
1221 						size -= readVX(tmp32);
1222 						if (tmp32)
1223 							mat->ReflMap=Images[tmp32-1];
1224 					}
1225 					else
1226 						size -= readString(mat->ReflMap, size);
1227 				}
1228 				break;
1229 			case charsToUIntD('R','S','A','N'):
1230 #ifdef LWO_READER_DEBUG
1231 				os::Printer::log("LWO loader: loading reflection seam angle.");
1232 #endif
1233 				{
1234 					File->read(&mat->ReflSeamAngle, 4);
1235 #ifndef __BIG_ENDIAN__
1236 					mat->ReflSeamAngle=os::Byteswap::byteswap(mat->ReflSeamAngle);
1237 #endif
1238 					size -= 4;
1239 					if (FormatVersion==2)
1240 						size -= readVX(mat->Envelope[10]);
1241 				}
1242 				break;
1243 			case charsToUIntD('R','B','L','R'):
1244 #ifdef LWO_READER_DEBUG
1245 				os::Printer::log("LWO loader: loading reflection blur.");
1246 #endif
1247 				{
1248 					File->read(&mat->ReflBlur, 4);
1249 #ifndef __BIG_ENDIAN__
1250 					mat->ReflBlur=os::Byteswap::byteswap(mat->ReflBlur);
1251 #endif
1252 					size -= 4;
1253 					if (FormatVersion==2)
1254 						size -= readVX(mat->Envelope[11]);
1255 				}
1256 				break;
1257 			case charsToUIntD('R','I','N','D'):
1258 #ifdef LWO_READER_DEBUG
1259 				os::Printer::log("LWO loader: loading refraction index.");
1260 #endif
1261 				{
1262 					File->read(&mat->RefrIndex, 4);
1263 #ifndef __BIG_ENDIAN__
1264 					mat->RefrIndex=os::Byteswap::byteswap(mat->RefrIndex);
1265 #endif
1266 					size -= 4;
1267 					subsize -= 4;
1268 					if (FormatVersion==2)
1269 						size -= readVX(mat->Envelope[12]);
1270 				}
1271 				break;
1272 			case charsToUIntD('T','R','O','P'):
1273 #ifdef LWO_READER_DEBUG
1274 				os::Printer::log("LWO loader: loading refraction options.");
1275 #endif
1276 				{
1277 					File->read(&mat->TranspMode, 2);
1278 #ifndef __BIG_ENDIAN__
1279 					mat->TranspMode=os::Byteswap::byteswap(mat->TranspMode);
1280 #endif
1281 					size -= 2;
1282 				}
1283 				break;
1284 			case charsToUIntD('T','I','M','G'):
1285 				{
1286 					if (FormatVersion==2)
1287 					{
1288 #ifdef LWO_READER_DEBUG
1289 						os::Printer::log("LWO loader: loading refraction map.");
1290 #endif
1291 						size -= readVX(tmp32);
1292 #ifndef __BIG_ENDIAN__
1293 						tmp32=os::Byteswap::byteswap(tmp32);
1294 #endif
1295 						if (tmp32)
1296 							mat->Texture[currTexture].Map=Images[tmp32-1];
1297 					}
1298 					else
1299 					{
1300 						size -= readString(mat->Texture[currTexture].Map, size);
1301 #ifdef LWO_READER_DEBUG
1302 						os::Printer::log("LWO loader: loading image", mat->Texture[currTexture].Map.c_str());
1303 #endif
1304 					}
1305 				}
1306 				break;
1307 			case charsToUIntD('T','B','L','R'):
1308 #ifdef LWO_READER_DEBUG
1309 				os::Printer::log("LWO loader: loading transparency blur.");
1310 #endif
1311 				{
1312 					File->read(&mat->TranspBlur, 4);
1313 #ifndef __BIG_ENDIAN__
1314 					mat->TranspBlur=os::Byteswap::byteswap(mat->TranspBlur);
1315 #endif
1316 					size -= 4;
1317 					if (FormatVersion==2)
1318 						size -= readVX(mat->Envelope[13]);
1319 				}
1320 				break;
1321 			case charsToUIntD('C','L','R','H'):
1322 #ifdef LWO_READER_DEBUG
1323 				os::Printer::log("LWO loader: loading highlight color.");
1324 #endif
1325 				{
1326 					File->read(&mat->HighlightColor, 4);
1327 #ifndef __BIG_ENDIAN__
1328 					mat->HighlightColor=os::Byteswap::byteswap(mat->HighlightColor);
1329 #endif
1330 					size -= 4;
1331 					if (FormatVersion==2)
1332 						size -= readVX(mat->Envelope[14]);
1333 				}
1334 				break;
1335 			case charsToUIntD('C','L','R','F'):
1336 #ifdef LWO_READER_DEBUG
1337 				os::Printer::log("LWO loader: loading color filter.");
1338 #endif
1339 				{
1340 					File->read(&mat->ColorFilter, 4);
1341 #ifndef __BIG_ENDIAN__
1342 					mat->ColorFilter=os::Byteswap::byteswap(mat->ColorFilter);
1343 #endif
1344 					size -= 4;
1345 					if (FormatVersion==2)
1346 						size -= readVX(mat->Envelope[15]);
1347 				}
1348 				break;
1349 			case charsToUIntD('A','D','T','R'):
1350 #ifdef LWO_READER_DEBUG
1351 				os::Printer::log("LWO loader: loading additive transparency.");
1352 #endif
1353 				{
1354 					File->read(&mat->AdditiveTransparency, 4);
1355 #ifndef __BIG_ENDIAN__
1356 					mat->AdditiveTransparency=os::Byteswap::byteswap(mat->AdditiveTransparency);
1357 #endif
1358 					size -= 4;
1359 					if (FormatVersion==2)
1360 						size -= readVX(mat->Envelope[16]);
1361 				}
1362 				break;
1363 			case charsToUIntD('G','L','O','W'):
1364 #ifdef LWO_READER_DEBUG
1365 				os::Printer::log("LWO loader: loading glow.");
1366 #endif
1367 				{
1368 					if (FormatVersion==0)
1369 					{
1370 						File->read(&mat->GlowIntensity, 4);
1371 #ifndef __BIG_ENDIAN__
1372 						mat->GlowIntensity=os::Byteswap::byteswap(mat->GlowIntensity);
1373 #endif
1374 						size -= 4;
1375 					}
1376 					else
1377 					{
1378 						File->read(&mat->Glow, 2);
1379 #ifndef __BIG_ENDIAN__
1380 						mat->Glow=os::Byteswap::byteswap(mat->Glow);
1381 #endif
1382 						size -= 2;
1383 						File->read(&mat->GlowIntensity, 4);
1384 #ifndef __BIG_ENDIAN__
1385 						mat->GlowIntensity=os::Byteswap::byteswap(mat->GlowIntensity);
1386 #endif
1387 						size -= 4;
1388 						if (FormatVersion==2)
1389 							size -= readVX(mat->Envelope[17]);
1390 						File->read(&mat->GlowSize, 4);
1391 #ifndef __BIG_ENDIAN__
1392 						mat->GlowSize=os::Byteswap::byteswap(mat->GlowSize);
1393 #endif
1394 						size -= 4;
1395 						if (FormatVersion==2)
1396 							size -= readVX(mat->Envelope[18]);
1397 					}
1398 				}
1399 				break;
1400 			case charsToUIntD('G','V','A','L'):
1401 #ifdef LWO_READER_DEBUG
1402 				os::Printer::log("LWO loader: loading glow intensity.");
1403 #endif
1404 				{
1405 					File->read(&mat->GlowIntensity, 4);
1406 #ifndef __BIG_ENDIAN__
1407 					mat->GlowIntensity=os::Byteswap::byteswap(mat->GlowIntensity);
1408 #endif
1409 					size -= 4;
1410 					if (FormatVersion==2)
1411 						size -= readVX(mat->Envelope[17]);
1412 				}
1413 				break;
1414 			case charsToUIntD('L','I','N','E'):
1415 #ifdef LWO_READER_DEBUG
1416 				os::Printer::log("LWO loader: loading isWireframe.");
1417 #endif
1418 				{
1419 					File->read(&tmp16, 2);
1420 #ifndef __BIG_ENDIAN__
1421 					tmp16=os::Byteswap::byteswap(tmp16);
1422 #endif
1423 					if (tmp16&1)
1424 						irrMat.Wireframe=true;
1425 					size -= 2;
1426 					if (size!=0)
1427 					{
1428 						File->read(&irrMat.Thickness, 4);
1429 #ifndef __BIG_ENDIAN__
1430 						irrMat.Thickness=os::Byteswap::byteswap(irrMat.Thickness);
1431 #endif
1432 						size -= 4;
1433 						if (FormatVersion==2)
1434 							size -= readVX(mat->Envelope[19]);
1435 					}
1436 					if (size!=0)
1437 					{
1438 						video::SColor lineColor;
1439 						size -= readColor(lineColor);
1440 						if (FormatVersion==2)
1441 							size -= readVX(mat->Envelope[20]);
1442 					}
1443 				}
1444 				break;
1445 			case charsToUIntD('A','L','P','H'):
1446 #ifdef LWO_READER_DEBUG
1447 				os::Printer::log("LWO loader: loading alpha mode.");
1448 #endif
1449 				{
1450 					File->read(&mat->AlphaMode, 2);
1451 #ifndef __BIG_ENDIAN__
1452 					mat->AlphaMode=os::Byteswap::byteswap(mat->AlphaMode);
1453 #endif
1454 					size -= 2;
1455 					File->read(&mat->AlphaValue, 4);
1456 #ifndef __BIG_ENDIAN__
1457 					mat->AlphaValue=os::Byteswap::byteswap(mat->AlphaValue);
1458 #endif
1459 					size -= 4;
1460 				}
1461 				break;
1462 			case charsToUIntD('V','C','O','L'):
1463 #ifdef LWO_READER_DEBUG
1464 				os::Printer::log("LWO loader: loading vertex color.");
1465 #endif
1466 				{
1467 					File->read(&mat->VertexColorIntensity, 4);
1468 #ifndef __BIG_ENDIAN__
1469 					mat->VertexColorIntensity=os::Byteswap::byteswap(mat->VertexColorIntensity);
1470 #endif
1471 					size -= 4;
1472 					if (FormatVersion==2)
1473 						size -= readVX(mat->Envelope[21]);
1474 					File->read(&tmp32, 4); // skip type
1475 					size -= 4;
1476 					core::stringc tmpname;
1477 					size -= readString(tmpname, size);
1478 //					mat->VertexColor = getColorVMAP(tmpname);
1479 				}
1480 				break;
1481 			case charsToUIntD('F','L','A','G'):
1482 #ifdef LWO_READER_DEBUG
1483 				os::Printer::log("LWO loader: loading flag.");
1484 #endif
1485 				{
1486 					File->read(&mat->Flags, 2);
1487 #ifndef __BIG_ENDIAN__
1488 					mat->Flags=os::Byteswap::byteswap(mat->Flags);
1489 #endif
1490 					if (mat->Flags&1)
1491 						mat->Luminance=1.0f;
1492 					if (mat->Flags&256)
1493 						irrMat.BackfaceCulling=false;
1494 					size -= 2;
1495 				}
1496 				break;
1497 			case charsToUIntD('E','D','G','E'):
1498 #ifdef LWO_READER_DEBUG
1499 				os::Printer::log("LWO loader: loading edge.");
1500 #endif
1501 				{
1502 					File->read(&mat->EdgeTransparency, 4);
1503 #ifndef __BIG_ENDIAN__
1504 					mat->EdgeTransparency=os::Byteswap::byteswap(mat->EdgeTransparency);
1505 #endif
1506 					size -= 4;
1507 				}
1508 				break;
1509 			case charsToUIntD('C','T','E','X'):
1510 #ifdef LWO_READER_DEBUG
1511 				os::Printer::log("LWO loader: loading ctex.");
1512 #endif
1513 				currTexture=0;
1514 				size -= readString(mat->Texture[currTexture].Type, size);
1515 				break;
1516 			case charsToUIntD('D','T','E','X'):
1517 #ifdef LWO_READER_DEBUG
1518 				os::Printer::log("LWO loader: loading dtex.");
1519 #endif
1520 				currTexture=1;
1521 				size -= readString(mat->Texture[currTexture].Type, size);
1522 				break;
1523 			case charsToUIntD('S','T','E','X'):
1524 #ifdef LWO_READER_DEBUG
1525 				os::Printer::log("LWO loader: loading stex.");
1526 #endif
1527 				currTexture=2;
1528 				size -= readString(mat->Texture[currTexture].Type, size);
1529 				break;
1530 			case charsToUIntD('R','T','E','X'):
1531 #ifdef LWO_READER_DEBUG
1532 				os::Printer::log("LWO loader: loading rtex.");
1533 #endif
1534 				currTexture=3;
1535 				size -= readString(mat->Texture[currTexture].Type, size);
1536 				break;
1537 			case charsToUIntD('T','T','E','X'):
1538 #ifdef LWO_READER_DEBUG
1539 				os::Printer::log("LWO loader: loading ttex.");
1540 #endif
1541 				currTexture=4;
1542 				size -= readString(mat->Texture[currTexture].Type, size);
1543 				break;
1544 			case charsToUIntD('L','T','E','X'):
1545 #ifdef LWO_READER_DEBUG
1546 				os::Printer::log("LWO loader: loading ltex.");
1547 #endif
1548 				currTexture=5;
1549 				size -= readString(mat->Texture[currTexture].Type, size);
1550 				break;
1551 			case charsToUIntD('B','T','E','X'):
1552 #ifdef LWO_READER_DEBUG
1553 				os::Printer::log("LWO loader: loading btex.");
1554 #endif
1555 				currTexture=6;
1556 				size -= readString(mat->Texture[currTexture].Type, size);
1557 				break;
1558 			case charsToUIntD('T','A','L','P'):
1559 #ifdef LWO_READER_DEBUG
1560 				os::Printer::log("LWO loader: loading alpha map.");
1561 #endif
1562 				size -= readString(mat->Texture[currTexture].AlphaMap, size);
1563 				break;
1564 			case charsToUIntD('T','F','L','G'):
1565 #ifdef LWO_READER_DEBUG
1566 				os::Printer::log("LWO loader: loading texture flag.");
1567 #endif
1568 				{
1569 					File->read(&mat->Texture[currTexture].Flags, 2);
1570 #ifndef __BIG_ENDIAN__
1571 					mat->Texture[currTexture].Flags=os::Byteswap::byteswap(mat->Texture[currTexture].Flags);
1572 #endif
1573 					size -= 2;
1574 				}
1575 				break;
1576 			case charsToUIntD('E','N','A','B'):
1577 #ifdef LWO_READER_DEBUG
1578 				os::Printer::log("LWO loader: loading isEnabled.");
1579 #endif
1580 				{
1581 					File->read(&tmp16, 2);
1582 #ifndef __BIG_ENDIAN__
1583 					tmp16=os::Byteswap::byteswap(tmp16);
1584 #endif
1585 					mat->Texture[currTexture].Active=(tmp16!=0);
1586 					size -= 2;
1587 				}
1588 				break;
1589 			case charsToUIntD('W','R','A','P'):
1590 			case charsToUIntD('T','W','R','P'):
1591 #ifdef LWO_READER_DEBUG
1592 				os::Printer::log("LWO loader: loading texture wrap.");
1593 #endif
1594 				{
1595 					File->read(&mat->Texture[currTexture].WidthWrap, 2);
1596 #ifndef __BIG_ENDIAN__
1597 					mat->Texture[currTexture].WidthWrap=os::Byteswap::byteswap(mat->Texture[currTexture].WidthWrap);
1598 #endif
1599 					File->read(&mat->Texture[currTexture].HeightWrap, 2);
1600 #ifndef __BIG_ENDIAN__
1601 					mat->Texture[currTexture].HeightWrap=os::Byteswap::byteswap(mat->Texture[currTexture].HeightWrap);
1602 #endif
1603 					size -= 4;
1604 				}
1605 				break;
1606 			case charsToUIntD('T','V','E','L'):
1607 #ifdef LWO_READER_DEBUG
1608 				os::Printer::log("LWO loader: loading texture velocity.");
1609 #endif
1610 				size -= readVec(mat->Texture[currTexture].Velocity);
1611 				break;
1612 			case charsToUIntD('T','C','L','R'):
1613 #ifdef LWO_READER_DEBUG
1614 				os::Printer::log("LWO loader: loading texture color.");
1615 #endif
1616 				size -= readColor(mat->Texture[currTexture].Color);
1617 				break;
1618 			case charsToUIntD('A','A','S','T'):
1619 			case charsToUIntD('T','A','A','S'):
1620 #ifdef LWO_READER_DEBUG
1621 				os::Printer::log("LWO loader: loading texture antialias.");
1622 #endif
1623 				{
1624 					tmp16=0;
1625 					if (FormatVersion==2)
1626 					{
1627 						File->read(&tmp16, 2);
1628 #ifndef __BIG_ENDIAN__
1629 						tmp16=os::Byteswap::byteswap(tmp16);
1630 #endif
1631 						size -= 2;
1632 					}
1633 					File->read(&mat->Texture[currTexture].AntiAliasing, 4);
1634 #ifndef __BIG_ENDIAN__
1635 					mat->Texture[currTexture].AntiAliasing=os::Byteswap::byteswap(mat->Texture[currTexture].AntiAliasing);
1636 #endif
1637 					if (tmp16 & ~0x01)
1638 						mat->Texture[currTexture].AntiAliasing=0.0f; // disabled
1639 					size -= 4;
1640 				}
1641 				break;
1642 			case charsToUIntD('T','O','P','C'):
1643 #ifdef LWO_READER_DEBUG
1644 				os::Printer::log("LWO loader: loading texture opacity.");
1645 #endif
1646 				{
1647 					File->read(&mat->Texture[currTexture].Opacity, 4);
1648 #ifndef __BIG_ENDIAN__
1649 					mat->Texture[currTexture].Opacity=os::Byteswap::byteswap(mat->Texture[currTexture].Opacity);
1650 #endif
1651 					size -= 4;
1652 				}
1653 				break;
1654 			case charsToUIntD('O','P','A','C'):
1655 				{
1656 #ifdef LWO_READER_DEBUG
1657 					os::Printer::log("LWO loader: loading texture opacity and type.");
1658 #endif
1659 					File->read(&mat->Texture[currTexture].OpacType, 2);
1660 #ifndef __BIG_ENDIAN__
1661 					mat->Texture[currTexture].OpacType=os::Byteswap::byteswap(mat->Texture[currTexture].OpacType);
1662 #endif
1663 					File->read(&mat->Texture[currTexture].Opacity, 4);
1664 #ifndef __BIG_ENDIAN__
1665 					mat->Texture[currTexture].Opacity=os::Byteswap::byteswap(mat->Texture[currTexture].Opacity);
1666 #endif
1667 					size -= 6;
1668 					subsize -= 6;
1669 					if (FormatVersion==2)
1670 						size -= readVX(mat->Envelope[22]);
1671 				}
1672 				break;
1673 			case charsToUIntD('A','X','I','S'):
1674 				{
1675 					File->read(&tmp16, 2);
1676 #ifndef __BIG_ENDIAN__
1677 					tmp16=os::Byteswap::byteswap(tmp16);
1678 #endif
1679 					mat->Texture[currTexture].Axis=(u8)tmp16;
1680 					size -= 2;
1681 #ifdef LWO_READER_DEBUG
1682 					os::Printer::log("LWO loader: loading axis value", core::stringc(tmp16).c_str());
1683 #endif
1684 				}
1685 				break;
1686 			case charsToUIntD('T','M','A','P'): // empty separation chunk
1687 				break;
1688 			case charsToUIntD('T','C','T','R'):
1689 			case charsToUIntD('C','N','T','R'):
1690 				{
1691 					core::vector3df& center=mat->Texture[currTexture].Center;
1692 					size -= readVec(center);
1693 					if (FormatVersion==2)
1694 						size -= readVX(mat->Envelope[22]);
1695 #ifdef LWO_READER_DEBUG
1696 					os::Printer::log("LWO loader: loading texture center", (core::stringc(center.X)+" "+core::stringc(center.Y)+" "+core::stringc(center.Z)).c_str());
1697 #endif
1698 				}
1699 				break;
1700 			case charsToUIntD('T','S','I','Z'):
1701 			case charsToUIntD('S','I','Z','E'):
1702 				{
1703 					core::vector3df& tsize=mat->Texture[currTexture].Size;
1704 					size -= readVec(tsize);
1705 					if (FormatVersion==2)
1706 						size -= readVX(mat->Envelope[22]);
1707 #ifdef LWO_READER_DEBUG
1708 					os::Printer::log("LWO loader: loading texture size", (core::stringc(tsize.X)+" "+core::stringc(tsize.Y)+" "+core::stringc(tsize.Z)).c_str());
1709 #endif
1710 				}
1711 				break;
1712 			case charsToUIntD('R','O','T','A'):
1713 				{
1714 					core::vector3df rotation;
1715 					size -= readVec(rotation);
1716 					if (FormatVersion==2)
1717 						size -= readVX(mat->Envelope[22]);
1718 #ifdef LWO_READER_DEBUG
1719 					os::Printer::log("LWO loader: loading texture rotation", (core::stringc(rotation.X)+" "+core::stringc(rotation.Y)+" "+core::stringc(rotation.Z)).c_str());
1720 #endif
1721 				}
1722 				break;
1723 			case charsToUIntD('O','R','E','F'):
1724 				{
1725 					core::stringc tmpname;
1726 					size -= readString(tmpname);
1727 #ifdef LWO_READER_DEBUG
1728 				os::Printer::log("LWO loader: texture reference object", tmpname.c_str());
1729 #endif
1730 				}
1731 				break;
1732 			case charsToUIntD('T','F','A','L'):
1733 			case charsToUIntD('F','A','L','L'):
1734 				{
1735 					if (FormatVersion==2)
1736 					{
1737 						u16 tmp16;
1738 						File->read(&tmp16, 2);
1739 						size -= 2;
1740 #ifndef __BIG_ENDIAN__
1741 						tmp16=os::Byteswap::byteswap(tmp16);
1742 #endif
1743 					}
1744 
1745 					core::vector3df& falloff=mat->Texture[currTexture].Falloff;
1746 					size -= readVec(falloff);
1747 					if (FormatVersion==2)
1748 						size -= readVX(mat->Envelope[22]);
1749 #ifdef LWO_READER_DEBUG
1750 					os::Printer::log("LWO loader: loading texture falloff");
1751 #endif
1752 				}
1753 				break;
1754 			case charsToUIntD('C','S','Y','S'):
1755 				{
1756 					u16 tmp16;
1757 					File->read(&tmp16, 2);
1758 					size -= 2;
1759 #ifndef __BIG_ENDIAN__
1760 					tmp16=os::Byteswap::byteswap(tmp16);
1761 #endif
1762 #ifdef LWO_READER_DEBUG
1763 					os::Printer::log("LWO loader: texture coordinate system", tmp16==0?"object coords":"world coords");
1764 #endif
1765 				}
1766 				break;
1767 			case charsToUIntD('T','V','A','L'):
1768 #ifdef LWO_READER_DEBUG
1769 				os::Printer::log("LWO loader: loading texture value.");
1770 #endif
1771 				{
1772 					File->read(&tmp16, 2);
1773 #ifndef __BIG_ENDIAN__
1774 					tmp16=os::Byteswap::byteswap(tmp16);
1775 #endif
1776 					mat->Texture[currTexture].Value=tmp16/256.0f;
1777 					size -= 2;
1778 				}
1779 				break;
1780 			case charsToUIntD('T','F','P','0'):
1781 			case charsToUIntD('T','S','P','0'):
1782 #ifdef LWO_READER_DEBUG
1783 				os::Printer::log("LWO loader: loading texture param 0.");
1784 #endif
1785 				{
1786 					File->read(&mat->Texture[currTexture].FParam[0], 4);
1787 #ifndef __BIG_ENDIAN__
1788 					mat->Texture[currTexture].FParam[0]=os::Byteswap::byteswap(mat->Texture[currTexture].FParam[0]);
1789 #endif
1790 					size -= 4;
1791 				}
1792 				break;
1793 			case charsToUIntD('T','F','P','1'):
1794 			case charsToUIntD('T','S','P','1'):
1795 #ifdef LWO_READER_DEBUG
1796 				os::Printer::log("LWO loader: loading texture param 1.");
1797 #endif
1798 				{
1799 					File->read(&mat->Texture[currTexture].FParam[1], 4);
1800 #ifndef __BIG_ENDIAN__
1801 					mat->Texture[currTexture].FParam[1]=os::Byteswap::byteswap(mat->Texture[currTexture].FParam[1]);
1802 #endif
1803 					size -= 4;
1804 				}
1805 				break;
1806 			case charsToUIntD('T','F','P','2'):
1807 			case charsToUIntD('T','S','P','2'):
1808 #ifdef LWO_READER_DEBUG
1809 				os::Printer::log("LWO loader: loading texture param 2.");
1810 #endif
1811 				{
1812 					File->read(&mat->Texture[currTexture].FParam[2], 4);
1813 #ifndef __BIG_ENDIAN__
1814 					mat->Texture[currTexture].FParam[2]=os::Byteswap::byteswap(mat->Texture[currTexture].FParam[2]);
1815 #endif
1816 					size -= 4;
1817 				}
1818 				break;
1819 			case charsToUIntD('T','F','R','Q'):
1820 			case charsToUIntD('T','I','P','0'):
1821 #ifdef LWO_READER_DEBUG
1822 				os::Printer::log("LWO loader: loading texture iparam 0.");
1823 #endif
1824 				{
1825 					File->read(&mat->Texture[currTexture].IParam[0], 2);
1826 #ifndef __BIG_ENDIAN__
1827 					mat->Texture[currTexture].IParam[0]=os::Byteswap::byteswap(mat->Texture[currTexture].IParam[0]);
1828 #endif
1829 					size -= 2;
1830 				}
1831 				break;
1832 			case charsToUIntD('T','I','P','1'):
1833 #ifdef LWO_READER_DEBUG
1834 				os::Printer::log("LWO loader: loading texture param 1.");
1835 #endif
1836 				{
1837 					File->read(&mat->Texture[currTexture].IParam[1], 2);
1838 #ifndef __BIG_ENDIAN__
1839 					mat->Texture[currTexture].IParam[1]=os::Byteswap::byteswap(mat->Texture[currTexture].IParam[1]);
1840 #endif
1841 					size -= 2;
1842 				}
1843 				break;
1844 			case charsToUIntD('T','I','P','2'):
1845 #ifdef LWO_READER_DEBUG
1846 				os::Printer::log("LWO loader: loading texture param 2.");
1847 #endif
1848 				{
1849 					File->read(&mat->Texture[currTexture].IParam[2], 2);
1850 #ifndef __BIG_ENDIAN__
1851 					mat->Texture[currTexture].IParam[2]=os::Byteswap::byteswap(mat->Texture[currTexture].IParam[2]);
1852 #endif
1853 					size -= 2;
1854 				}
1855 				break;
1856 			case charsToUIntD('V','M','A','P'):
1857 				{
1858 					size -= readString(mat->Texture[currTexture].UVname);
1859 #ifdef LWO_READER_DEBUG
1860 					os::Printer::log("LWO loader: loading material vmap binding",mat->Texture[currTexture].UVname.c_str());
1861 #endif
1862 				}
1863 				break;
1864 			case charsToUIntD('B','L','O','K'):
1865 #ifdef LWO_READER_DEBUG
1866 				os::Printer::log("LWO loader: loading blok.");
1867 #endif
1868 				{
1869 					core::stringc ordinal;
1870 					File->read(&type, 4);
1871 					File->read(&subsize, 2);
1872 #ifndef __BIG_ENDIAN__
1873 					subsize=os::Byteswap::byteswap(subsize);
1874 #endif
1875 					size -= 6;
1876 					size -= readString(ordinal, size);
1877 				}
1878 				break;
1879 			case charsToUIntD('C','H','A','N'):
1880 				{
1881 					File->read(&type, 4);
1882 					size -= 4;
1883 					if (!strncmp(type, "COLR", 4))
1884 						currTexture=0;
1885 					else if (!strncmp(type, "DIFF", 4))
1886 						currTexture=1;
1887 					else if (!strncmp(type, "LUMI", 4))
1888 						currTexture=5;
1889 					else if (!strncmp(type, "SPEC", 4))
1890 						currTexture=2;
1891 					else if (!strncmp(type, "REFL", 4))
1892 						currTexture=3;
1893 					else if (!strncmp(type, "TRAN", 4))
1894 						currTexture=4;
1895 					else if (!strncmp(type, "BUMP", 4))
1896 						currTexture=6;
1897 				}
1898 #ifdef LWO_READER_DEBUG
1899 				os::Printer::log("LWO loader: loading channel ", type);
1900 #endif
1901 				break;
1902 			case charsToUIntD('I','M','A','G'):
1903 #ifdef LWO_READER_DEBUG
1904 				os::Printer::log("LWO loader: loading channel map.");
1905 #endif
1906 				{
1907 					u16 index;
1908 					File->read(&index, 2);
1909 #ifndef __BIG_ENDIAN__
1910 					index=os::Byteswap::byteswap(index);
1911 #endif
1912 					size -= 2;
1913 					if (index)
1914 						mat->Texture[currTexture].Map=Images[index-1];
1915 				}
1916 				break;
1917 			case charsToUIntD('P','R','O','J'): // define the projection type
1918 #ifdef LWO_READER_DEBUG
1919 				os::Printer::log("LWO loader: loading channel projection type.");
1920 #endif
1921 				{
1922 					u16 index;
1923 					File->read(&index, 2);
1924 #ifndef __BIG_ENDIAN__
1925 					index=os::Byteswap::byteswap(index);
1926 #endif
1927 					size -= 2;
1928 #ifdef LWO_READER_DEBUG
1929 					if (index != 5)
1930 						os::Printer::log("LWO loader: wrong channel projection type", core::stringc(index).c_str());
1931 #endif
1932 					mat->Texture[currTexture].Projection=(u8)index;
1933 				}
1934 				break;
1935 			case charsToUIntD('W','R','P','W'): // for cylindrical and spherical projections
1936 			case charsToUIntD('W','R','P','H'): // for cylindrical and spherical projections
1937 			default:
1938 				{
1939 #ifdef LWO_READER_DEBUG
1940 					os::Printer::log("LWO loader: skipping ", core::stringc((char*)&uiType, 4));
1941 #endif
1942 					File->seek(subsize, true);
1943 					size -= subsize;
1944 				}
1945 		}
1946 	}
1947 
1948 	if (mat->Transparency != 0.f)
1949 	{
1950 		irrMat.MaterialType=video::EMT_TRANSPARENT_ADD_COLOR;
1951 	}
1952 }
1953 
1954 
readColor(video::SColor & color)1955 u32 CLWOMeshFileLoader::readColor(video::SColor& color)
1956 {
1957 	if (FormatVersion!=2)
1958 	{
1959 		u8 colorComponent;
1960 		File->read(&colorComponent, 1);
1961 		color.setRed(colorComponent);
1962 		File->read(&colorComponent, 1);
1963 		color.setGreen(colorComponent);
1964 		File->read(&colorComponent, 1);
1965 		color.setBlue(colorComponent);
1966 		// unknown value
1967 		File->read(&colorComponent, 1);
1968 		return 4;
1969 	}
1970 	else
1971 	{
1972 		video::SColorf col;
1973 		File->read(&col.r, 4);
1974 #ifndef __BIG_ENDIAN__
1975 		col.r=os::Byteswap::byteswap(col.r);
1976 #endif
1977 		File->read(&col.g, 4);
1978 #ifndef __BIG_ENDIAN__
1979 		col.g=os::Byteswap::byteswap(col.g);
1980 #endif
1981 		File->read(&col.b, 4);
1982 #ifndef __BIG_ENDIAN__
1983 		col.b=os::Byteswap::byteswap(col.b);
1984 #endif
1985 		color=col.toSColor();
1986 		return 12;
1987 	}
1988 }
1989 
readString(core::stringc & name,u32 size)1990 u32 CLWOMeshFileLoader::readString(core::stringc& name, u32 size)
1991 {
1992 	c8 c;
1993 
1994 	name="";
1995 	if (size)
1996 		name.reserve(size);
1997 	File->read(&c, 1);
1998 	while (c)
1999 	{
2000 		name.append(c);
2001 		File->read(&c, 1);
2002 	}
2003 	// read extra 0 upon odd file position
2004 	if (File->getPos() & 0x1)
2005 	{
2006 		File->read(&c, 1);
2007 		return (name.size()+2);
2008 	}
2009 	return (name.size()+1);
2010 }
2011 
2012 
readVec(core::vector3df & vec)2013 u32 CLWOMeshFileLoader::readVec(core::vector3df& vec)
2014 {
2015 	File->read(&vec.X, 4);
2016 #ifndef __BIG_ENDIAN__
2017 	vec.X=os::Byteswap::byteswap(vec.X);
2018 #endif
2019 	File->read(&vec.Y, 4);
2020 #ifndef __BIG_ENDIAN__
2021 	vec.Y=os::Byteswap::byteswap(vec.Y);
2022 #endif
2023 	File->read(&vec.Z, 4);
2024 #ifndef __BIG_ENDIAN__
2025 	vec.Z=os::Byteswap::byteswap(vec.Z);
2026 #endif
2027 	return 12;
2028 }
2029 
2030 
readVX(u32 & num)2031 u32 CLWOMeshFileLoader::readVX(u32& num)
2032 {
2033 	u16 tmpIndex;
2034 
2035 	File->read(&tmpIndex, 2);
2036 #ifndef __BIG_ENDIAN__
2037 	tmpIndex=os::Byteswap::byteswap(tmpIndex);
2038 #endif
2039 	num=tmpIndex;
2040 	if (num >= 0xFF00)
2041 	{
2042 		File->read(&tmpIndex, 2);
2043 #ifndef __BIG_ENDIAN__
2044 		tmpIndex=os::Byteswap::byteswap(tmpIndex);
2045 #endif
2046 		num=((num << 16)|tmpIndex) & ~0xFF000000;
2047 		return 4;
2048 	}
2049 	return 2;
2050 }
2051 
2052 
readFileHeader()2053 bool CLWOMeshFileLoader::readFileHeader()
2054 {
2055 	u32 Id;
2056 
2057 	File->read(&Id, 4);
2058 #ifndef __BIG_ENDIAN__
2059 	Id=os::Byteswap::byteswap(Id);
2060 #endif
2061 	if (Id != 0x464f524d) // FORM
2062 		return false;
2063 
2064 	//skip the file length
2065 	File->read(&Id, 4);
2066 
2067 	File->read(&Id, 4);
2068 #ifndef __BIG_ENDIAN__
2069 	Id=os::Byteswap::byteswap(Id);
2070 #endif
2071 	// Currently supported: LWOB, LWLO, LWO2
2072 	switch (Id)
2073 	{
2074 		case 0x4c574f42:
2075 			FormatVersion = 0; // LWOB
2076 		break;
2077 		case 0x4c574c4f:
2078 			FormatVersion = 1; // LWLO
2079 		break;
2080 		case 0x4c574f32:
2081 			FormatVersion = 2; // LWO2
2082 		break;
2083 		default:
2084 			return false; // unsupported
2085 	}
2086 
2087 	return true;
2088 }
2089 
2090 
loadTexture(const core::stringc & file)2091 video::ITexture* CLWOMeshFileLoader::loadTexture(const core::stringc& file)
2092 {
2093 	video::IVideoDriver* driver = SceneManager->getVideoDriver();
2094 
2095 	if (FileSystem->existFile(file))
2096 		return driver->getTexture(file);
2097 
2098 	core::stringc strippedName=FileSystem->getFileBasename(file);
2099 	if (FileSystem->existFile(strippedName))
2100 		return driver->getTexture(strippedName);
2101 	core::stringc newpath = FileSystem->getFileDir(File->getFileName());
2102 	newpath.append("/");
2103 	newpath.append(strippedName);
2104 	if (FileSystem->existFile(newpath))
2105 		return driver->getTexture(newpath);
2106 	os::Printer::log("Could not load texture", file.c_str(), ELL_WARNING);
2107 
2108 	return 0;
2109 }
2110 
2111 
2112 } // end namespace scene
2113 } // end namespace irr
2114 
2115