Retour
Version Originale

./aip/1.8aipmod/source/Irrlicht/CLWOMeshFileLoader.cpp :


// Copyright (C) 2007-2011 Nikolaus Gebhardt

// This file is part of the "Irrlicht Engine".

// For conditions of distribution and use, see copyright notice in irrlicht.h


#include "CLWOMeshFileLoader.h"
#include "os.h"
#include "SAnimatedMesh.h"
#include "SMesh.h"
#include "IReadFile.h"
#include "ISceneManager.h"
#include "IFileSystem.h"
#include "IVideoDriver.h"
#include "IMeshManipulator.h"

namespace irr
{
namespace scene
{

#ifdef _DEBUG
#define LWO_READER_DEBUG
#endif

#define charsToUIntD(a, b, c, d) ((a << 24) | (b << 16) | (c << 8) | d)
inline unsigned int charsToUInt(const char *str)
{
	return (str[0] << 24) | (str[1] << 16) | (str[2] << 8) | str[3];
}


struct tLWOTextureInfo
{
	tLWOTextureInfo() : UVTag(0), DUVTag(0), Flags(0), WidthWrap(2),
			HeightWrap(2), OpacType(0), Color(0xffffffff),
			Value(0.0f), AntiAliasing(1.0f), Opacity(1.0f),
			Axis(255), Projection(0), Active(false) {}
	core::stringc Type;
	core::stringc Map;
	core::stringc AlphaMap;
	core::stringc UVname;
	u16 UVTag;
	u16 DUVTag;
	u16 Flags;
	u16 WidthWrap;
	u16 HeightWrap;
	u16 OpacType;
	u16 IParam[3];
	core::vector3df Size;
	core::vector3df Center;
	core::vector3df Falloff;
	core::vector3df Velocity;
	video::SColor Color;
	f32 Value;
	f32 AntiAliasing;
	f32 Opacity;
	f32 FParam[3];
	u8 Axis;
	u8 Projection;
	bool Active;
};

struct CLWOMeshFileLoader::tLWOMaterial
{
	tLWOMaterial() : Meshbuffer(0), TagType(0), Flags(0), ReflMode(3), TranspMode(3),
		Glow(0), AlphaMode(2), Luminance(0.0f), Diffuse(1.0f), Specular(0.0f),
		Reflection(0.0f), Transparency(0.0f), Translucency(0.0f),
		Sharpness(0.0f), ReflSeamAngle(0.0f), ReflBlur(0.0f),
		RefrIndex(1.0f), TranspBlur(0.0f), SmoothingAngle(0.0f),
		EdgeTransparency(0.0f), HighlightColor(0.0f), ColorFilter(0.0f),
		AdditiveTransparency(0.0f), GlowIntensity(0.0f), GlowSize(0.0f),
		AlphaValue(0.0f), VertexColorIntensity(0.0f), VertexColor() {}

	core::stringc Name;
	scene::SMeshBuffer *Meshbuffer;
	core::stringc ReflMap;
	u16 TagType;
	u16 Flags;
	u16 ReflMode;
	u16 TranspMode;
	u16 Glow;
	u16 AlphaMode;
	f32 Luminance;
	f32 Diffuse;
	f32 Specular;
	f32 Reflection;
	f32 Transparency;
	f32 Translucency;
	f32 Sharpness;
	f32 ReflSeamAngle;
	f32 ReflBlur;
	f32 RefrIndex;
	f32 TranspBlur;
	f32 SmoothingAngle;
	f32 EdgeTransparency;
	f32 HighlightColor;
	f32 ColorFilter;
	f32 AdditiveTransparency;
	f32 GlowIntensity;
	f32 GlowSize;
	f32 AlphaValue;
	f32 VertexColorIntensity;
	video::SColorf VertexColor;
	u32 Envelope[23];
	tLWOTextureInfo Texture[7];
};

struct tLWOLayerInfo
{
	u16 Number;
	u16 Parent;
	u16 Flags;
	bool Active;
	core::stringc Name;
	core::vector3df Pivot;
};


//! Constructor

CLWOMeshFileLoader::CLWOMeshFileLoader(scene::ISceneManager* smgr,
		io::IFileSystem* fs)
: SceneManager(smgr), FileSystem(fs), File(0), Mesh(0)
{
	#ifdef _DEBUG
	setDebugName("CLWOMeshFileLoader");
	#endif
}


//! destructor

CLWOMeshFileLoader::~CLWOMeshFileLoader()
{
	if (Mesh)
		Mesh->drop();
}


//! returns true if the file maybe is able to be loaded by this class

//! based on the file extension (e.g. ".bsp")

bool CLWOMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
{
	return core::hasFileExtension(filename, "lwo");
}


//! creates/loads an animated mesh from the file.

IAnimatedMesh* CLWOMeshFileLoader::createMesh(io::IReadFile* file)
{
	File = file;

	if (Mesh)
		Mesh->drop();

	Mesh = new SMesh();

	if (!readFileHeader())
		return 0;

	if (!readChunks())
		return 0;

#ifdef LWO_READER_DEBUG
	os::Printer::log("LWO loader: Creating geometry.");
	os::Printer::log("LWO loader: Assigning UV maps.");
#endif
	u32 i;
	for (i=0; i<Materials.size(); ++i)
	{
		u16 uvTag;
		for (u32 j=0; j<2; ++j) // max 2 texture coords

		{
			if (Materials[i]->Texture[j].UVname.size())
			{
				for (uvTag=0; uvTag<UvName.size(); ++uvTag)
				{
					if (Materials[i]->Texture[j].UVname == UvName[uvTag])
					{
						Materials[i]->Texture[j].UVTag=uvTag;
						break;
					}
				}
				for (uvTag=0; uvTag<DUvName.size(); ++uvTag)
				{
					if (Materials[i]->Texture[j].UVname == DUvName[uvTag])
					{
						Materials[i]->Texture[j].DUVTag=uvTag;
						break;
					}
				}
			}
		}
	}
#ifdef LWO_READER_DEBUG
	os::Printer::log("LWO loader: Creating polys.");
#endif
	// create actual geometry for lwo2

	if (FormatVersion==2)
	{
		core::array<u32>vertexCount;
		vertexCount.reallocate(Materials.size());
		for (i=0; i<Materials.size(); ++i)
			vertexCount.push_back(0);
		for (u32 polyIndex=0; polyIndex<Indices.size(); ++polyIndex)
			vertexCount[MaterialMapping[polyIndex]] += Indices[polyIndex].size();
		for (i=0; i<Materials.size(); ++i)
		{
			Materials[i]->Meshbuffer->Vertices.reallocate(vertexCount[i]);
			Materials[i]->Meshbuffer->Indices.reallocate(vertexCount[i]);
		}
	}
	// create actual geometry for lwo2

	for (u32 polyIndex=0; polyIndex<Indices.size(); ++polyIndex)
	{
		const u16 tag = MaterialMapping[polyIndex];
		scene::SMeshBuffer *mb=Materials[tag]->Meshbuffer;
		const core::array<u32>& poly = Indices[polyIndex];
		const u32 polySize=poly.size();
		const u16 uvTag = Materials[tag]->Texture[0].UVTag;
		const u16 duvTag = Materials[tag]->Texture[0].DUVTag;
		video::S3DVertex vertex;
		vertex.Color=0xffffffff;
		const u32 vertCount=mb->Vertices.size();
		for (u32 i=0; i<polySize; ++i)
		{
			const u32 j=poly[i];
			vertex.Pos=Points[j];
			if (uvTag<UvIndex.size())
			{
				for (u32 uvsearch=0; uvsearch < UvIndex[uvTag].size(); ++uvsearch)
				{
					if(j==UvIndex[uvTag][uvsearch])
					{
						vertex.TCoords=TCoords[uvTag][uvsearch];
						break;
					}
				}
				if (duvTag<DUvName.size())
				{
					for (u32 polysearch = 0; polysearch < VmPolyPointsIndex[duvTag].size(); polysearch += 2)
					{
						if (polyIndex==VmPolyPointsIndex[duvTag][polysearch] && j==VmPolyPointsIndex[duvTag][polysearch+1])
						{
							vertex.TCoords=VmCoordsIndex[duvTag][polysearch/2];
							break;
						}
					}
				}
			}
			mb->Vertices.push_back(vertex);
		}
		// triangulate as trifan

		if (polySize>2)
		{
			for (u32 i=1; i<polySize-1; ++i)
			{
				mb->Indices.push_back(vertCount);
				mb->Indices.push_back(vertCount+i);
				mb->Indices.push_back(vertCount+i+1);
			}
		}
	}
#ifdef LWO_READER_DEBUG
	os::Printer::log("LWO loader: Fixing meshbuffers.");
#endif
	for (u32 i=0; i<Materials.size(); ++i)
	{
#ifdef LWO_READER_DEBUG
		os::Printer::log("LWO loader: Material name", Materials[i]->Name);
		os::Printer::log("LWO loader: Vertex count", core::stringc(Materials[i]->Meshbuffer->Vertices.size()));
#endif
		if (!Materials[i]->Meshbuffer->Vertices.size())
		{
			Materials[i]->Meshbuffer->drop();
			delete Materials[i];
			continue;
		}
		for (u32 j=0; j<Materials[i]->Meshbuffer->Vertices.size(); ++j)
			Materials[i]->Meshbuffer->Vertices[j].Color=Materials[i]->Meshbuffer->Material.DiffuseColor;
		Materials[i]->Meshbuffer->recalculateBoundingBox();

		// load textures

		video::SMaterial& irrMat=Materials[i]->Meshbuffer->Material;
		if (Materials[i]->Texture[0].Map != "") // diffuse

			irrMat.setTexture(0,loadTexture(Materials[i]->Texture[0].Map));
		if (Materials[i]->Texture[3].Map != "") // reflection

		{
#ifdef LWO_READER_DEBUG
			os::Printer::log("LWO loader: loading reflection texture.");
#endif
			video::ITexture* reflTexture = loadTexture(Materials[i]->Texture[3].Map);
			if (reflTexture && irrMat.getTexture(0))
				irrMat.setTexture(1, irrMat.getTexture(0));
			irrMat.setTexture(0, reflTexture);
			irrMat.MaterialType=video::EMT_REFLECTION_2_LAYER;
		}
		if (Materials[i]->Texture[4].Map != "") // transparency

		{
#ifdef LWO_READER_DEBUG
			os::Printer::log("LWO loader: loading transparency texture.");
#endif
			video::ITexture* transTexture = loadTexture(Materials[i]->Texture[4].Map);
			if (transTexture && irrMat.getTexture(0))
				irrMat.setTexture(1, irrMat.getTexture(0));
			irrMat.setTexture(0, transTexture);
			irrMat.MaterialType=video::EMT_TRANSPARENT_ADD_COLOR;
		}
		if (Materials[i]->Texture[6].Map != "") // bump

		{
#ifdef LWO_READER_DEBUG
			os::Printer::log("LWO loader: loading bump texture.");
#endif
			const u8 pos = irrMat.getTexture(0)?1:0;
			irrMat.setTexture(pos, loadTexture(Materials[i]->Texture[6].Map));
			if (irrMat.getTexture(pos))
			{
	//			SceneManager->getVideoDriver()->makeNormalMapTexture(irrMat.getTexture(1));

	//			irrMat.MaterialType=video::EMT_NORMAL_MAP_SOLID;

			}
		}

		// cope with planar mapping texture coords

		if (Materials[i]->Texture[0].Projection != 5)
		{
			if (FormatVersion!=2)
			{
				if (Materials[i]->Texture[0].Flags&1)
					Materials[i]->Texture[0].Axis=0;
				else if (Materials[i]->Texture[0].Flags&2)
					Materials[i]->Texture[0].Axis=1;
				else if (Materials[i]->Texture[0].Flags&4)
					Materials[i]->Texture[0].Axis=2;
			}
			// if no axis given choose the dominant one

			else if (Materials[i]->Texture[0].Axis>2)
			{
				if (Materials[i]->Meshbuffer->getBoundingBox().getExtent().Y<Materials[i]->Meshbuffer->getBoundingBox().getExtent().X)
				{
					if (Materials[i]->Meshbuffer->getBoundingBox().getExtent().Y<Materials[i]->Meshbuffer->getBoundingBox().getExtent().Z)
						Materials[i]->Texture[0].Axis=1;
					else
						Materials[i]->Texture[0].Axis=2;
				}
				else
				{
					if (Materials[i]->Meshbuffer->getBoundingBox().getExtent().X<Materials[i]->Meshbuffer->getBoundingBox().getExtent().Z)
						Materials[i]->Texture[0].Axis=0;
					else
						Materials[i]->Texture[0].Axis=2;
				}
			}
			// get the resolution for this axis

			f32 resolutionS = core::reciprocal(Materials[i]->Texture[0].Size.Z);
			f32 resolutionT = core::reciprocal(Materials[i]->Texture[0].Size.Y);
			if (Materials[i]->Texture[0].Axis==1)
			{
				resolutionS = core::reciprocal(Materials[i]->Texture[0].Size.X);
				resolutionT = core::reciprocal(Materials[i]->Texture[0].Size.Z);
			}
			else if (Materials[i]->Texture[0].Axis==2)
			{
				resolutionS = core::reciprocal(Materials[i]->Texture[0].Size.X);
				resolutionT = core::reciprocal(Materials[i]->Texture[0].Size.Y);
			}
			// use the two-way planar mapping

			SceneManager->getMeshManipulator()->makePlanarTextureMapping(Materials[i]->Meshbuffer, resolutionS, resolutionT, Materials[i]->Texture[0].Axis, Materials[i]->Texture[0].Center);
		}

		// add bump maps

		if (Materials[i]->Meshbuffer->Material.MaterialType==video::EMT_NORMAL_MAP_SOLID)
		{
			SMesh* tmpmesh = new SMesh();
			tmpmesh->addMeshBuffer(Materials[i]->Meshbuffer);
			SceneManager->getMeshManipulator()->createMeshWithTangents(tmpmesh, true, true);
			Mesh->addMeshBuffer(tmpmesh->getMeshBuffer(0));
			tmpmesh->getMeshBuffer(0)->drop();
			tmpmesh->drop();
		}
		else
		{
			SceneManager->getMeshManipulator()->recalculateNormals(Materials[i]->Meshbuffer);
			Mesh->addMeshBuffer(Materials[i]->Meshbuffer);
		}
		Materials[i]->Meshbuffer->drop();
		// clear the material array elements

		delete Materials[i];
	}
	Mesh->recalculateBoundingBox();

	SAnimatedMesh* am = new SAnimatedMesh();
	am->Type = EAMT_3DS;
	am->addMesh(Mesh);
	am->recalculateBoundingBox();
	Mesh->drop();
	Mesh = 0;

	Points.clear();
	Indices.clear();
	MaterialMapping.clear();
	TCoords.clear();
	Materials.clear();
	Images.clear();
	VmPolyPointsIndex.clear();
	VmCoordsIndex.clear();
	UvIndex.clear();
	UvName.clear();

	return am;
}


bool CLWOMeshFileLoader::readChunks()
{
	s32 lastPos;
	u32 size;
	unsigned int uiType;
	char type[5];
	type[4]=0;
	tLWOLayerInfo layer;

	while(File->getPos()<File->getSize())
	{
		File->read(&type, 4);
		//Convert 4-char string to 4-byte integer

		//Makes it possible to do a switch statement

		uiType = charsToUInt(type);
		File->read(&size, 4);
#ifndef __BIG_ENDIAN__
		size=os::Byteswap::byteswap(size);
#endif
		lastPos=File->getPos();

		switch(uiType)
		{
			case charsToUIntD('L','A','Y','R'):
				{
#ifdef LWO_READER_DEBUG
					os::Printer::log("LWO loader: loading layer.");
#endif
					u16 tmp16;
					File->read(&tmp16, 2); // number

					File->read(&tmp16, 2); // flags

					size -= 4;
#ifndef __BIG_ENDIAN__
					tmp16=os::Byteswap::byteswap(tmp16);
#endif
					if (((FormatVersion==1)&&(tmp16!=1)) ||
						((FormatVersion==2)&&(tmp16&1)))
						layer.Active=false;
					else
						layer.Active=true;
					if (FormatVersion==2)
						size -= readVec(layer.Pivot);
					size -= readString(layer.Name);
					if (size)
					{
						File->read(&tmp16, 2);
#ifndef __BIG_ENDIAN__
						tmp16=os::Byteswap::byteswap(tmp16);
#endif
						layer.Parent = tmp16;
					}
				}
				break;
			case charsToUIntD('P','N','T','S'):
				{
#ifdef LWO_READER_DEBUG
					os::Printer::log("LWO loader: loading points.");
#endif
					core::vector3df vec;
					Points.clear();
					const u32 tmpsize = size/12;
					Points.reallocate(tmpsize);
					for (u32 i=0; i<tmpsize; ++i)
					{
						readVec(vec);
						Points.push_back(vec);
					}
				}
				break;
			case charsToUIntD('V','M','A','P'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading Vertex mapping.");
#endif
				readVertexMapping(size);
				break;
			case charsToUIntD('P','O','L','S'):
			case charsToUIntD('P','T','C','H'): // TODO: should be a subdivison mesh

#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading polygons.");
#endif
				if (FormatVersion!=2)
					readObj1(size);
				else
					readObj2(size);
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: Done loading polygons.");
#endif
				break;
			case charsToUIntD('T','A','G','S'):
			case charsToUIntD('S','R','F','S'):
				{
#ifdef LWO_READER_DEBUG
					os::Printer::log("LWO loader: loading surface names.");
#endif
					while (size!=0)
					{
						tLWOMaterial *mat=new tLWOMaterial();
						mat->Name="";
						mat->Meshbuffer=new scene::SMeshBuffer();
						size -= readString(mat->Name);
						if (FormatVersion!=2)
							mat->TagType = 1; // format 2 has more types

						Materials.push_back(mat);
					}
				}
				break;
			case charsToUIntD('P','T','A','G'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading tag mapping.");
#endif
				readTagMapping(size);
				break;
			case charsToUIntD('V','M','A','D'): // discontinuous vertex mapping, i.e. additional texcoords

#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading Vertex mapping VMAD.");
#endif
				readDiscVertexMapping(size);
//			case charsToUIntD('V','M','P','A'):

//			case charsToUIntD('E','N','V','L'):

				break;
			case charsToUIntD('C','L','I','P'):
				{
#ifdef LWO_READER_DEBUG
					os::Printer::log("LWO loader: loading clips.");
#endif
					u32 index;
					u16 subsize;
					File->read(&index, 4);
#ifndef __BIG_ENDIAN__
					index=os::Byteswap::byteswap(index);
#endif
					size -= 4;
					while (size != 0)
					{
						File->read(&type, 4);
						File->read(&subsize, 2);
#ifndef __BIG_ENDIAN__
						subsize=os::Byteswap::byteswap(subsize);
#endif
						size -= 6;
						if (strncmp(type, "STIL", 4))
						{
							File->seek(subsize, true);
							size -= subsize;
							continue;
						}
						core::stringc path;
						size -= readString(path, subsize);
	#ifdef LWO_READER_DEBUG
						os::Printer::log("LWO loader: loaded clip", path.c_str());
	#endif
						Images.push_back(path);
					}
				}
				break;
			case charsToUIntD('S','U','R','F'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading material.");
#endif
				readMat(size);
				break;
			case charsToUIntD('B','B','O','X'):
				{
#ifdef LWO_READER_DEBUG
					os::Printer::log("LWO loader: loading bbox.");
#endif
					// not stored

					core::vector3df vec;
					for (u32 i=0; i<2; ++i)
						readVec(vec);
					size -= 24;
				}
				break;
			case charsToUIntD('D','E','S','C'):
			case charsToUIntD('T','E','X','T'):
				{
					core::stringc text;
					size -= readString(text, size);
#ifdef LWO_READER_DEBUG
					os::Printer::log("LWO loader text", text);
#endif
				}
				break;
			// not needed

			case charsToUIntD('I','C','O','N'):
			// not yet supported

			case charsToUIntD('P','C','H','S'):
			case charsToUIntD('C','R','V','S'):
			default:
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: skipping ", type);
#endif
				//Go to next chunk

				File->seek(lastPos + size, false);
				break;
		}
	}
	return true;
}


void CLWOMeshFileLoader::readObj1(u32 size)
{
	u32 pos;
	u16 numVerts, vertIndex;
	s16 material;
	video::S3DVertex vertex;
	vertex.Color=0xffffffff;

	while (size!=0)
	{
		File->read(&numVerts, 2);
#ifndef __BIG_ENDIAN__
		numVerts=os::Byteswap::byteswap(numVerts);
#endif
		pos=File->getPos();
		// skip forward to material number

		File->seek(2*numVerts, true);
		File->read(&material, 2);
#ifndef __BIG_ENDIAN__
		material=os::Byteswap::byteswap(material);
#endif
		size -=2*numVerts+4;
		// detail meshes ?

		scene::SMeshBuffer *mb;
		if (material<0)
			mb=Materials[-material-1]->Meshbuffer;
		else
			mb=Materials[material-1]->Meshbuffer;
		// back to vertex list start

		File->seek(pos, false);

		const u16 vertCount=mb->Vertices.size();
		for (u16 i=0; i<numVerts; ++i)
		{
			File->read(&vertIndex, 2);
#ifndef __BIG_ENDIAN__
			vertIndex=os::Byteswap::byteswap(vertIndex);
#endif
			vertex.Pos=Points[vertIndex];
			mb->Vertices.push_back(vertex);
		}
		for (u16 i=1; i<numVerts-1; ++i)
		{
			mb->Indices.push_back(vertCount);
			mb->Indices.push_back(vertCount+i);
			mb->Indices.push_back(vertCount+i+1);
		}
		// skip material number and detail surface count

		// detail surface can be read just as a normal one now

		if (material<0)
			File->read(&material, 2);
		File->read(&material, 2);
	}
}


void CLWOMeshFileLoader::readVertexMapping(u32 size)
{
	char type[5]={0};
	u16 dimension;
	core::stringc name;
	File->read(&type, 4);
#ifdef LWO_READER_DEBUG
	os::Printer::log("LWO loader: Vertex map type", type);
#endif
	File->read(&dimension,2);
#ifndef __BIG_ENDIAN__
	dimension=os::Byteswap::byteswap(dimension);
#endif
	size -= 6;
	size -= readString(name);
#ifdef LWO_READER_DEBUG
	os::Printer::log("LWO loader: Vertex map", name.c_str());
#endif
	if (strncmp(type, "TXUV", 4)) // also support RGB, RGBA, WGHT, ...

	{
		File->seek(size, true);
		return;
	}
	UvName.push_back(name);

	TCoords.push_back(core::array<core::vector2df>());
	core::array<core::vector2df>& UvCoords=TCoords.getLast();
	UvCoords.reallocate(Points.size());
	UvIndex.push_back(core::array<u32>());
	core::array<u32>& UvPointsArray=UvIndex.getLast();
	UvPointsArray.reallocate(Points.size());

	u32 index;
	core::vector2df tcoord;
	while (size)
	{
		size -= readVX(index);
		File->read(&tcoord.X, 4);
		File->read(&tcoord.Y, 4);
		size -= 8;
#ifndef __BIG_ENDIAN__
		index=os::Byteswap::byteswap(index);
		tcoord.X=os::Byteswap::byteswap(tcoord.X);
		tcoord.Y=os::Byteswap::byteswap(tcoord.Y);
#endif
		UvCoords.push_back(tcoord);
		UvPointsArray.push_back(index);
	}
#ifdef LWO_READER_DEBUG
	os::Printer::log("LWO loader: UvCoords", core::stringc(UvCoords.size()));
#endif
}


void CLWOMeshFileLoader::readDiscVertexMapping(u32 size)
{
	char type[5]={0};
	u16 dimension;
	core::stringc name;
	File->read(&type, 4);
#ifdef LWO_READER_DEBUG
	os::Printer::log("LWO loader: Discontinuous vertex map type", type);
#endif
	File->read(&dimension,2);
#ifndef __BIG_ENDIAN__
	dimension=os::Byteswap::byteswap(dimension);
#endif
	size -= 6;
	size -= readString(name);
#ifdef LWO_READER_DEBUG
	os::Printer::log("LWO loader: Discontinuous vertex map", name.c_str());
#endif
	if (strncmp(type, "TXUV", 4))
	{
		File->seek(size, true);
		return;
	}
	DUvName.push_back(name);
	VmPolyPointsIndex.push_back(core::array<u32>());
	core::array<u32>& VmPolyPoints=VmPolyPointsIndex.getLast();

	VmCoordsIndex.push_back(core::array<core::vector2df>());
	core::array<core::vector2df>& VmCoords=VmCoordsIndex.getLast();

	u32 vmpolys;
	u32 vmpoints;
	core::vector2df vmcoords;
	while (size)
	{
		size-=readVX(vmpoints);
		size-=readVX(vmpolys);
		File->read(&vmcoords.X, 4);
		File->read(&vmcoords.Y, 4);
		size -= 8;
#ifndef __BIG_ENDIAN__
		vmpoints=os::Byteswap::byteswap(vmpoints);
		vmpolys=os::Byteswap::byteswap(vmpolys);
		vmcoords.X=os::Byteswap::byteswap(vmcoords.X);
		vmcoords.Y=os::Byteswap::byteswap(vmcoords.Y);
#endif
		VmCoords.push_back(vmcoords);
		VmPolyPoints.push_back(vmpolys);
		VmPolyPoints.push_back(vmpoints);
	}
#ifdef LWO_READER_DEBUG
	os::Printer::log("LWO loader: VmCoords", core::stringc(VmCoords.size()));
#endif
}


void CLWOMeshFileLoader::readTagMapping(u32 size)
{
	char type[5];
	type[4]=0;
	File->read(&type, 4);
	size -= 4;
	if ((strncmp(type, "SURF", 4))||(Indices.size()==0))
	{
		File->seek(size, true);
		return;
	}

	while (size!=0)
	{
		u16 tag;
		u32 polyIndex;
		size-=readVX(polyIndex);
		File->read(&tag, 2);
#ifndef __BIG_ENDIAN__
		tag=os::Byteswap::byteswap(tag);
#endif
		size -= 2;
		MaterialMapping[polyIndex]=tag;
		Materials[tag]->TagType=1;
	}
}


void CLWOMeshFileLoader::readObj2(u32 size)
{
	char type[5];
	type[4]=0;
	File->read(&type, 4);
	size -= 4;
	Indices.clear();
	if (strncmp(type, "FACE", 4)) // also possible are splines, subdivision patches, metaballs, and bones

	{
		File->seek(size, true);
		return;
	}
	u16 numVerts=0;
	while (size!=0)
	{
		File->read(&numVerts, 2);
#ifndef __BIG_ENDIAN__
		numVerts=os::Byteswap::byteswap(numVerts);
#endif
		// mask out flags

		numVerts &= 0x03FF;

		size -= 2;
		Indices.push_back(core::array<u32>());
		u32 vertIndex;
		core::array<u32>& polyArray = Indices.getLast();
		polyArray.reallocate(numVerts);
		for (u16 i=0; i<numVerts; ++i)
		{
			size -= readVX(vertIndex);
			polyArray.push_back(vertIndex);
		}
	}
	MaterialMapping.reallocate(Indices.size());
	for (u32 j=0; j<Indices.size(); ++j)
		MaterialMapping.push_back(0);
}


void CLWOMeshFileLoader::readMat(u32 size)
{
	core::stringc name;

	tLWOMaterial* mat=0;
	size -= readString(name);
#ifdef LWO_READER_DEBUG
	os::Printer::log("LWO loader: material name", name.c_str());
#endif
	for (u32 i=0; i<Materials.size(); ++i)
	{
		if ((Materials[i]->TagType==1) && (Materials[i]->Name==name))
		{
			mat=Materials[i];
			break;
		}
	}
	if (!mat)
	{
		File->seek(size, true);
		return;
	}
	if (FormatVersion==2)
		size -= readString(name);

	video::SMaterial& irrMat=mat->Meshbuffer->Material;

	u8 currTexture=0;
	while (size!=0)
	{
		char type[5];
		type[4]=0;
		u32 uiType;
		u32 tmp32;
		u16 subsize, tmp16;
		f32 tmpf32;
		File->read(&type, 4);
		//Convert 4-char string to 4-byte integer

		//Makes it possible to do a switch statement

		uiType = charsToUInt(type);
		File->read(&subsize, 2);
#ifndef __BIG_ENDIAN__
		subsize=os::Byteswap::byteswap(subsize);
#endif
		size -= 6;
		switch (uiType)
		{
			case charsToUIntD('C','O','L','R'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading Ambient color.");
#endif
				{
					s32 colSize = readColor(irrMat.DiffuseColor);
					irrMat.AmbientColor=irrMat.DiffuseColor;
					size -= colSize;
					subsize -= colSize;
					if (FormatVersion==2)
						size -= readVX(mat->Envelope[0]);
				}
				break;
			case charsToUIntD('D','I','F','F'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading Diffuse color.");
#endif
				{
					if (FormatVersion==2)
					{
						File->read(&mat->Diffuse, 4);
#ifndef __BIG_ENDIAN__
						mat->Diffuse=os::Byteswap::byteswap(mat->Diffuse);
#endif
						size -= 4;
						subsize -= 4;
						size -= readVX(mat->Envelope[1]);
					}
					else
					{
						File->read(&tmp16, 2);
#ifndef __BIG_ENDIAN__
						tmp16=os::Byteswap::byteswap(tmp16);
#endif
						mat->Diffuse=tmp16/256.0f;
						size -= 2;
						subsize -= 2;
					}
				}
				break;
			case charsToUIntD('V','D','I','F'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading Diffuse color.");
#endif
				{
					File->read(&mat->Diffuse, 4);
#ifndef __BIG_ENDIAN__
					mat->Diffuse=os::Byteswap::byteswap(mat->Diffuse);
#endif
					size -= 4;
				}
				break;
			case charsToUIntD('L','U','M','I'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading luminance.");
#endif
				{
					if (FormatVersion==2)
					{
						File->read(&mat->Luminance, 4);
#ifndef __BIG_ENDIAN__
						mat->Luminance=os::Byteswap::byteswap(mat->Luminance);
#endif
						size -= 4;
						subsize -= 4;
						size -= readVX(mat->Envelope[2]);
					}
					else
					{
						File->read(&tmp16, 2);
#ifndef __BIG_ENDIAN__
						tmp16=os::Byteswap::byteswap(tmp16);
#endif
						mat->Luminance=tmp16/256.0f;
						size -= 2;
						subsize -= 2;
					}				}
				break;
			case charsToUIntD('V','L','U','M'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading luminance.");
#endif
				{
					File->read(&mat->Luminance, 4);
#ifndef __BIG_ENDIAN__
					mat->Luminance=os::Byteswap::byteswap(mat->Luminance);
#endif
					size -= 4;
				}
				break;
			case charsToUIntD('S','P','E','C'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading specular.");
#endif
				{
					if (FormatVersion==2)
					{
						File->read(&mat->Specular, 4);
#ifndef __BIG_ENDIAN__
						mat->Specular=os::Byteswap::byteswap(mat->Specular);
#endif
						size -= 4;
						subsize -= 4;
						size -= readVX(mat->Envelope[3]);
					}
					else
					{
						File->read(&tmp16, 2);
#ifndef __BIG_ENDIAN__
						tmp16=os::Byteswap::byteswap(tmp16);
#endif
						mat->Specular=tmp16/256.0f;;
						size -= 2;
						subsize -= 2;
					}
				}
				break;
			case charsToUIntD('V','S','P','C'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading specular.");
#endif
				{
					File->read(&mat->Specular, 4);
#ifndef __BIG_ENDIAN__
					mat->Specular=os::Byteswap::byteswap(mat->Specular);
#endif
					size -= 4;
				}
				break;
			case charsToUIntD('R','E','F','L'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading reflection.");
#endif
				{
					if (FormatVersion==2)
					{
						File->read(&mat->Reflection, 4);
#ifndef __BIG_ENDIAN__
						mat->Reflection=os::Byteswap::byteswap(mat->Reflection);
#endif
						size -= 4;
						subsize -= 4;
						size -= readVX(mat->Envelope[4]);
					}
					else
					{
						File->read(&tmp16, 2);
#ifndef __BIG_ENDIAN__
						tmp16=os::Byteswap::byteswap(tmp16);
#endif
						mat->Reflection=tmp16/256.0f;
						size -= 2;
						subsize -= 2;
					}
				}
				break;
			case charsToUIntD('V','R','F','L'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading reflection.");
#endif
				{
					File->read(&mat->Reflection, 4);
#ifndef __BIG_ENDIAN__
					mat->Reflection=os::Byteswap::byteswap(mat->Reflection);
#endif
					size -= 4;
				}
				break;
			case charsToUIntD('T','R','A','N'):
				{
					if (FormatVersion==2)
					{
						File->read(&mat->Transparency, 4);
#ifndef __BIG_ENDIAN__
						mat->Transparency=os::Byteswap::byteswap(mat->Transparency);
#endif
						size -= 4;
						subsize -= 4;
						size -= readVX(mat->Envelope[5]);
					}
					else
					{
						File->read(&tmp16, 2);
#ifndef __BIG_ENDIAN__
						tmp16=os::Byteswap::byteswap(tmp16);
#endif
						mat->Transparency=tmp16/256.0f;
						size -= 2;
						subsize -= 2;
					}
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading transparency", core::stringc(mat->Transparency).c_str());
#endif
				}
				break;
			case charsToUIntD('V','T','R','N'):
				{
					File->read(&mat->Transparency, 4);
#ifndef __BIG_ENDIAN__
					mat->Transparency=os::Byteswap::byteswap(mat->Transparency);
#endif
					size -= 4;
				}
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading transparency", core::stringc(mat->Transparency).c_str());
#endif
				break;
			case charsToUIntD('T','R','N','L'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading translucency.");
#endif
				{
					File->read(&mat->Translucency, 4);
#ifndef __BIG_ENDIAN__
					mat->Translucency=os::Byteswap::byteswap(mat->Translucency);
#endif
					size -= 4;
					subsize -= 4;
					if (FormatVersion==2)
						size -= readVX(mat->Envelope[6]);
				}
				break;
			case charsToUIntD('G','L','O','S'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading glossy.");
#endif
				{
					if (FormatVersion == 2)
					{
						File->read(&irrMat.Shininess, 4);
#ifndef __BIG_ENDIAN__
						irrMat.Shininess=os::Byteswap::byteswap(irrMat.Shininess);
#endif
						size -= 4;
						subsize -= 4;
						size -= readVX(mat->Envelope[7]);
					}
					else
					{
						File->read(&tmp16, 2);
#ifndef __BIG_ENDIAN__
						tmp16=os::Byteswap::byteswap(tmp16);
#endif
						irrMat.Shininess=tmp16/16.f;
						size -= 2;
						subsize -= 2;
					}
				}
				break;
			case charsToUIntD('S','H','R','P'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading sharpness.");
#endif
				{
					File->read(&mat->Sharpness, 4);
#ifndef __BIG_ENDIAN__
					mat->Sharpness=os::Byteswap::byteswap(mat->Sharpness);
#endif
					size -= 4;
					subsize -= 4;
					if (FormatVersion==2)
						size -= readVX(mat->Envelope[8]);
				}
				break;
			case charsToUIntD('B','U','M','P'):
			case charsToUIntD('T','A','M','P'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading bumpiness.");
#endif
				{
					File->read(&tmpf32, 4);
#ifndef __BIG_ENDIAN__
						tmpf32=os::Byteswap::byteswap(tmpf32);
#endif
					if (currTexture==6)
						irrMat.MaterialTypeParam=tmpf32;
					size -= 4;
					subsize -= 4;
					if (FormatVersion==2)
						size -= readVX(mat->Envelope[9]);
				}
				break;
			case charsToUIntD('S','I','D','E'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading backface culled.");
#endif
				{
					File->read(&tmp16, 2);
#ifndef __BIG_ENDIAN__
					tmp16=os::Byteswap::byteswap(tmp16);
#endif
					if (tmp16==1)
						irrMat.BackfaceCulling=true;
					else if (tmp16==3)
						irrMat.BackfaceCulling=false;
					size -= 2;
				}
				break;
			case charsToUIntD('S','M','A','N'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading smoothing angle.");
#endif
				{
					File->read(&mat->SmoothingAngle, 4);
#ifndef __BIG_ENDIAN__
					mat->SmoothingAngle=os::Byteswap::byteswap(mat->SmoothingAngle);
#endif
					size -= 4;
				}
				break;
			case charsToUIntD('R','F','O','P'):
			case charsToUIntD('R','F','L','T'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading reflection mode.");
#endif
				{
					File->read(&mat->ReflMode, 2);
#ifndef __BIG_ENDIAN__
					mat->ReflMode=os::Byteswap::byteswap(mat->ReflMode);
#endif
					size -= 2;
				}
				break;
			case charsToUIntD('R','I','M','G'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading reflection map.");
#endif
				{
					if (FormatVersion==2)
					{
						size -= readVX(tmp32);
						if (tmp32)
							mat->ReflMap=Images[tmp32-1];
					}
					else
						size -= readString(mat->ReflMap, size);
				}
				break;
			case charsToUIntD('R','S','A','N'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading reflection seam angle.");
#endif
				{
					File->read(&mat->ReflSeamAngle, 4);
#ifndef __BIG_ENDIAN__
					mat->ReflSeamAngle=os::Byteswap::byteswap(mat->ReflSeamAngle);
#endif
					size -= 4;
					if (FormatVersion==2)
						size -= readVX(mat->Envelope[10]);
				}
				break;
			case charsToUIntD('R','B','L','R'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading reflection blur.");
#endif
				{
					File->read(&mat->ReflBlur, 4);
#ifndef __BIG_ENDIAN__
					mat->ReflBlur=os::Byteswap::byteswap(mat->ReflBlur);
#endif
					size -= 4;
					if (FormatVersion==2)
						size -= readVX(mat->Envelope[11]);
				}
				break;
			case charsToUIntD('R','I','N','D'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading refraction index.");
#endif
				{
					File->read(&mat->RefrIndex, 4);
#ifndef __BIG_ENDIAN__
					mat->RefrIndex=os::Byteswap::byteswap(mat->RefrIndex);
#endif
					size -= 4;
					subsize -= 4;
					if (FormatVersion==2)
						size -= readVX(mat->Envelope[12]);
				}
				break;
			case charsToUIntD('T','R','O','P'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading refraction options.");
#endif
				{
					File->read(&mat->TranspMode, 2);
#ifndef __BIG_ENDIAN__
					mat->TranspMode=os::Byteswap::byteswap(mat->TranspMode);
#endif
					size -= 2;
				}
				break;
			case charsToUIntD('T','I','M','G'):
				{
					if (FormatVersion==2)
					{
#ifdef LWO_READER_DEBUG
						os::Printer::log("LWO loader: loading refraction map.");
#endif
						size -= readVX(tmp32);
#ifndef __BIG_ENDIAN__
						tmp32=os::Byteswap::byteswap(tmp32);
#endif
						if (tmp32)
							mat->Texture[currTexture].Map=Images[tmp32-1];
					}
					else
					{
						size -= readString(mat->Texture[currTexture].Map, size);
#ifdef LWO_READER_DEBUG
						os::Printer::log("LWO loader: loading image", mat->Texture[currTexture].Map.c_str());
#endif
					}
				}
				break;
			case charsToUIntD('T','B','L','R'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading transparency blur.");
#endif
				{
					File->read(&mat->TranspBlur, 4);
#ifndef __BIG_ENDIAN__
					mat->TranspBlur=os::Byteswap::byteswap(mat->TranspBlur);
#endif
					size -= 4;
					if (FormatVersion==2)
						size -= readVX(mat->Envelope[13]);
				}
				break;
			case charsToUIntD('C','L','R','H'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading highlight color.");
#endif
				{
					File->read(&mat->HighlightColor, 4);
#ifndef __BIG_ENDIAN__
					mat->HighlightColor=os::Byteswap::byteswap(mat->HighlightColor);
#endif
					size -= 4;
					if (FormatVersion==2)
						size -= readVX(mat->Envelope[14]);
				}
				break;
			case charsToUIntD('C','L','R','F'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading color filter.");
#endif
				{
					File->read(&mat->ColorFilter, 4);
#ifndef __BIG_ENDIAN__
					mat->ColorFilter=os::Byteswap::byteswap(mat->ColorFilter);
#endif
					size -= 4;
					if (FormatVersion==2)
						size -= readVX(mat->Envelope[15]);
				}
				break;
			case charsToUIntD('A','D','T','R'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading additive transparency.");
#endif
				{
					File->read(&mat->AdditiveTransparency, 4);
#ifndef __BIG_ENDIAN__
					mat->AdditiveTransparency=os::Byteswap::byteswap(mat->AdditiveTransparency);
#endif
					size -= 4;
					if (FormatVersion==2)
						size -= readVX(mat->Envelope[16]);
				}
				break;
			case charsToUIntD('G','L','O','W'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading glow.");
#endif
				{
					if (FormatVersion==0)
					{
						File->read(&mat->GlowIntensity, 4);
#ifndef __BIG_ENDIAN__
						mat->GlowIntensity=os::Byteswap::byteswap(mat->GlowIntensity);
#endif
						size -= 4;
					}
					else
					{
						File->read(&mat->Glow, 2);
#ifndef __BIG_ENDIAN__
						mat->Glow=os::Byteswap::byteswap(mat->Glow);
#endif
						size -= 2;
						File->read(&mat->GlowIntensity, 4);
#ifndef __BIG_ENDIAN__
						mat->GlowIntensity=os::Byteswap::byteswap(mat->GlowIntensity);
#endif
						size -= 4;
						if (FormatVersion==2)
							size -= readVX(mat->Envelope[17]);
						File->read(&mat->GlowSize, 4);
#ifndef __BIG_ENDIAN__
						mat->GlowSize=os::Byteswap::byteswap(mat->GlowSize);
#endif
						size -= 4;
						if (FormatVersion==2)
							size -= readVX(mat->Envelope[18]);
					}
				}
				break;
			case charsToUIntD('G','V','A','L'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading glow intensity.");
#endif
				{
					File->read(&mat->GlowIntensity, 4);
#ifndef __BIG_ENDIAN__
					mat->GlowIntensity=os::Byteswap::byteswap(mat->GlowIntensity);
#endif
					size -= 4;
					if (FormatVersion==2)
						size -= readVX(mat->Envelope[17]);
				}
				break;
			case charsToUIntD('L','I','N','E'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading isWireframe.");
#endif
				{
					File->read(&tmp16, 2);
#ifndef __BIG_ENDIAN__
					tmp16=os::Byteswap::byteswap(tmp16);
#endif
					if (tmp16&1)
						irrMat.Wireframe=true;
					size -= 2;
					if (size!=0)
					{
						File->read(&irrMat.Thickness, 4);
#ifndef __BIG_ENDIAN__
						irrMat.Thickness=os::Byteswap::byteswap(irrMat.Thickness);
#endif
						size -= 4;
						if (FormatVersion==2)
							size -= readVX(mat->Envelope[19]);
					}
					if (size!=0)
					{
						video::SColor lineColor;
						size -= readColor(lineColor);
						if (FormatVersion==2)
							size -= readVX(mat->Envelope[20]);
					}
				}
				break;
			case charsToUIntD('A','L','P','H'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading alpha mode.");
#endif
				{
					File->read(&mat->AlphaMode, 2);
#ifndef __BIG_ENDIAN__
					mat->AlphaMode=os::Byteswap::byteswap(mat->AlphaMode);
#endif
					size -= 2;
					File->read(&mat->AlphaValue, 4);
#ifndef __BIG_ENDIAN__
					mat->AlphaValue=os::Byteswap::byteswap(mat->AlphaValue);
#endif
					size -= 4;
				}
				break;
			case charsToUIntD('V','C','O','L'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading vertex color.");
#endif
				{
					File->read(&mat->VertexColorIntensity, 4);
#ifndef __BIG_ENDIAN__
					mat->VertexColorIntensity=os::Byteswap::byteswap(mat->VertexColorIntensity);
#endif
					size -= 4;
					if (FormatVersion==2)
						size -= readVX(mat->Envelope[21]);
					File->read(&tmp32, 4); // skip type

					size -= 4;
					core::stringc tmpname;
					size -= readString(tmpname, size);
//					mat->VertexColor = getColorVMAP(tmpname);

				}
				break;
			case charsToUIntD('F','L','A','G'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading flag.");
#endif
				{
					File->read(&mat->Flags, 2);
#ifndef __BIG_ENDIAN__
					mat->Flags=os::Byteswap::byteswap(mat->Flags);
#endif
					if (mat->Flags&1)
						mat->Luminance=1.0f;
					if (mat->Flags&256)
						irrMat.BackfaceCulling=false;
					size -= 2;
				}
				break;
			case charsToUIntD('E','D','G','E'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading edge.");
#endif
				{
					File->read(&mat->EdgeTransparency, 4);
#ifndef __BIG_ENDIAN__
					mat->EdgeTransparency=os::Byteswap::byteswap(mat->EdgeTransparency);
#endif
					size -= 4;
				}
				break;
			case charsToUIntD('C','T','E','X'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading ctex.");
#endif
				currTexture=0;
				size -= readString(mat->Texture[currTexture].Type, size);
				break;
			case charsToUIntD('D','T','E','X'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading dtex.");
#endif
				currTexture=1;
				size -= readString(mat->Texture[currTexture].Type, size);
				break;
			case charsToUIntD('S','T','E','X'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading stex.");
#endif
				currTexture=2;
				size -= readString(mat->Texture[currTexture].Type, size);
				break;
			case charsToUIntD('R','T','E','X'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading rtex.");
#endif
				currTexture=3;
				size -= readString(mat->Texture[currTexture].Type, size);
				break;
			case charsToUIntD('T','T','E','X'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading ttex.");
#endif
				currTexture=4;
				size -= readString(mat->Texture[currTexture].Type, size);
				break;
			case charsToUIntD('L','T','E','X'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading ltex.");
#endif
				currTexture=5;
				size -= readString(mat->Texture[currTexture].Type, size);
				break;
			case charsToUIntD('B','T','E','X'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading btex.");
#endif
				currTexture=6;
				size -= readString(mat->Texture[currTexture].Type, size);
				break;
			case charsToUIntD('T','A','L','P'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading alpha map.");
#endif
				size -= readString(mat->Texture[currTexture].AlphaMap, size);
				break;
			case charsToUIntD('T','F','L','G'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading texture flag.");
#endif
				{
					File->read(&mat->Texture[currTexture].Flags, 2);
#ifndef __BIG_ENDIAN__
					mat->Texture[currTexture].Flags=os::Byteswap::byteswap(mat->Texture[currTexture].Flags);
#endif
					size -= 2;
				}
				break;
			case charsToUIntD('E','N','A','B'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading isEnabled.");
#endif
				{
					File->read(&tmp16, 2);
#ifndef __BIG_ENDIAN__
					tmp16=os::Byteswap::byteswap(tmp16);
#endif
					mat->Texture[currTexture].Active=(tmp16!=0);
					size -= 2;
				}
				break;
			case charsToUIntD('W','R','A','P'):
			case charsToUIntD('T','W','R','P'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading texture wrap.");
#endif
				{
					File->read(&mat->Texture[currTexture].WidthWrap, 2);
#ifndef __BIG_ENDIAN__
					mat->Texture[currTexture].WidthWrap=os::Byteswap::byteswap(mat->Texture[currTexture].WidthWrap);
#endif
					File->read(&mat->Texture[currTexture].HeightWrap, 2);
#ifndef __BIG_ENDIAN__
					mat->Texture[currTexture].HeightWrap=os::Byteswap::byteswap(mat->Texture[currTexture].HeightWrap);
#endif
					size -= 4;
				}
				break;
			case charsToUIntD('T','V','E','L'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading texture velocity.");
#endif
				size -= readVec(mat->Texture[currTexture].Velocity);
				break;
			case charsToUIntD('T','C','L','R'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading texture color.");
#endif
				size -= readColor(mat->Texture[currTexture].Color);
				break;
			case charsToUIntD('A','A','S','T'):
			case charsToUIntD('T','A','A','S'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading texture antialias.");
#endif
				{
					tmp16=0;
					if (FormatVersion==2)
					{
						File->read(&tmp16, 2);
#ifndef __BIG_ENDIAN__
						tmp16=os::Byteswap::byteswap(tmp16);
#endif
						size -= 2;
					}
					File->read(&mat->Texture[currTexture].AntiAliasing, 4);
#ifndef __BIG_ENDIAN__
					mat->Texture[currTexture].AntiAliasing=os::Byteswap::byteswap(mat->Texture[currTexture].AntiAliasing);
#endif
					if (tmp16 & ~0x01)
						mat->Texture[currTexture].AntiAliasing=0.0f; // disabled

					size -= 4;
				}
				break;
			case charsToUIntD('T','O','P','C'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading texture opacity.");
#endif
				{
					File->read(&mat->Texture[currTexture].Opacity, 4);
#ifndef __BIG_ENDIAN__
					mat->Texture[currTexture].Opacity=os::Byteswap::byteswap(mat->Texture[currTexture].Opacity);
#endif
					size -= 4;
				}
				break;
			case charsToUIntD('O','P','A','C'):
				{
#ifdef LWO_READER_DEBUG
					os::Printer::log("LWO loader: loading texture opacity and type.");
#endif
					File->read(&mat->Texture[currTexture].OpacType, 2);
#ifndef __BIG_ENDIAN__
					mat->Texture[currTexture].OpacType=os::Byteswap::byteswap(mat->Texture[currTexture].OpacType);
#endif
					File->read(&mat->Texture[currTexture].Opacity, 4);
#ifndef __BIG_ENDIAN__
					mat->Texture[currTexture].Opacity=os::Byteswap::byteswap(mat->Texture[currTexture].Opacity);
#endif
					size -= 6;
					subsize -= 6;
					if (FormatVersion==2)
						size -= readVX(mat->Envelope[22]);
				}
				break;
			case charsToUIntD('A','X','I','S'):
				{
					File->read(&tmp16, 2);
#ifndef __BIG_ENDIAN__
					tmp16=os::Byteswap::byteswap(tmp16);
#endif
					mat->Texture[currTexture].Axis=(u8)tmp16;
					size -= 2;
#ifdef LWO_READER_DEBUG
					os::Printer::log("LWO loader: loading axis value", core::stringc(tmp16).c_str());
#endif
				}
				break;
			case charsToUIntD('T','M','A','P'): // empty separation chunk

				break;
			case charsToUIntD('T','C','T','R'):
			case charsToUIntD('C','N','T','R'):
				{
					core::vector3df& center=mat->Texture[currTexture].Center;
					size -= readVec(center);
					if (FormatVersion==2)
						size -= readVX(mat->Envelope[22]);
#ifdef LWO_READER_DEBUG
					os::Printer::log("LWO loader: loading texture center", (core::stringc(center.X)+" "+core::stringc(center.Y)+" "+core::stringc(center.Z)).c_str());
#endif
				}
				break;
			case charsToUIntD('T','S','I','Z'):
			case charsToUIntD('S','I','Z','E'):
				{
					core::vector3df& tsize=mat->Texture[currTexture].Size;
					size -= readVec(tsize);
					if (FormatVersion==2)
						size -= readVX(mat->Envelope[22]);
#ifdef LWO_READER_DEBUG
					os::Printer::log("LWO loader: loading texture size", (core::stringc(tsize.X)+" "+core::stringc(tsize.Y)+" "+core::stringc(tsize.Z)).c_str());
#endif
				}
				break;
			case charsToUIntD('R','O','T','A'):
				{
					core::vector3df rotation;
					size -= readVec(rotation);
					if (FormatVersion==2)
						size -= readVX(mat->Envelope[22]);
#ifdef LWO_READER_DEBUG
					os::Printer::log("LWO loader: loading texture rotation", (core::stringc(rotation.X)+" "+core::stringc(rotation.Y)+" "+core::stringc(rotation.Z)).c_str());
#endif
				}
				break;
			case charsToUIntD('O','R','E','F'):
				{
					core::stringc tmpname;
					size -= readString(tmpname);
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: texture reference object", tmpname.c_str());
#endif
				}
				break;
			case charsToUIntD('T','F','A','L'):
			case charsToUIntD('F','A','L','L'):
				{
					if (FormatVersion==2)
					{
						u16 tmp16;
						File->read(&tmp16, 2);
						size -= 2;
#ifndef __BIG_ENDIAN__
						tmp16=os::Byteswap::byteswap(tmp16);
#endif
					}

					core::vector3df& falloff=mat->Texture[currTexture].Falloff;
					size -= readVec(falloff);
					if (FormatVersion==2)
						size -= readVX(mat->Envelope[22]);
#ifdef LWO_READER_DEBUG
					os::Printer::log("LWO loader: loading texture falloff");
#endif
				}
				break;
			case charsToUIntD('C','S','Y','S'):
				{
					u16 tmp16;
					File->read(&tmp16, 2);
					size -= 2;
#ifndef __BIG_ENDIAN__
					tmp16=os::Byteswap::byteswap(tmp16);
#endif
#ifdef LWO_READER_DEBUG
					os::Printer::log("LWO loader: texture coordinate system", tmp16==0?"object coords":"world coords");
#endif
				}
				break;
			case charsToUIntD('T','V','A','L'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading texture value.");
#endif
				{
					File->read(&tmp16, 2);
#ifndef __BIG_ENDIAN__
					tmp16=os::Byteswap::byteswap(tmp16);
#endif
					mat->Texture[currTexture].Value=tmp16/256.0f;
					size -= 2;
				}
				break;
			case charsToUIntD('T','F','P','0'):
			case charsToUIntD('T','S','P','0'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading texture param 0.");
#endif
				{
					File->read(&mat->Texture[currTexture].FParam[0], 4);
#ifndef __BIG_ENDIAN__
					mat->Texture[currTexture].FParam[0]=os::Byteswap::byteswap(mat->Texture[currTexture].FParam[0]);
#endif
					size -= 4;
				}
				break;
			case charsToUIntD('T','F','P','1'):
			case charsToUIntD('T','S','P','1'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading texture param 1.");
#endif
				{
					File->read(&mat->Texture[currTexture].FParam[1], 4);
#ifndef __BIG_ENDIAN__
					mat->Texture[currTexture].FParam[1]=os::Byteswap::byteswap(mat->Texture[currTexture].FParam[1]);
#endif
					size -= 4;
				}
				break;
			case charsToUIntD('T','F','P','2'):
			case charsToUIntD('T','S','P','2'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading texture param 2.");
#endif
				{
					File->read(&mat->Texture[currTexture].FParam[2], 4);
#ifndef __BIG_ENDIAN__
					mat->Texture[currTexture].FParam[2]=os::Byteswap::byteswap(mat->Texture[currTexture].FParam[2]);
#endif
					size -= 4;
				}
				break;
			case charsToUIntD('T','F','R','Q'):
			case charsToUIntD('T','I','P','0'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading texture iparam 0.");
#endif
				{
					File->read(&mat->Texture[currTexture].IParam[0], 2);
#ifndef __BIG_ENDIAN__
					mat->Texture[currTexture].IParam[0]=os::Byteswap::byteswap(mat->Texture[currTexture].IParam[0]);
#endif
					size -= 2;
				}
				break;
			case charsToUIntD('T','I','P','1'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading texture param 1.");
#endif
				{
					File->read(&mat->Texture[currTexture].IParam[1], 2);
#ifndef __BIG_ENDIAN__
					mat->Texture[currTexture].IParam[1]=os::Byteswap::byteswap(mat->Texture[currTexture].IParam[1]);
#endif
					size -= 2;
				}
				break;
			case charsToUIntD('T','I','P','2'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading texture param 2.");
#endif
				{
					File->read(&mat->Texture[currTexture].IParam[2], 2);
#ifndef __BIG_ENDIAN__
					mat->Texture[currTexture].IParam[2]=os::Byteswap::byteswap(mat->Texture[currTexture].IParam[2]);
#endif
					size -= 2;
				}
				break;
			case charsToUIntD('V','M','A','P'):
				{
					size -= readString(mat->Texture[currTexture].UVname);
#ifdef LWO_READER_DEBUG
					os::Printer::log("LWO loader: loading material vmap binding",mat->Texture[currTexture].UVname.c_str());
#endif
				}
				break;
			case charsToUIntD('B','L','O','K'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading blok.");
#endif
				{
					core::stringc ordinal;
					File->read(&type, 4);
					File->read(&subsize, 2);
#ifndef __BIG_ENDIAN__
					subsize=os::Byteswap::byteswap(subsize);
#endif
					size -= 6;
					size -= readString(ordinal, size);
				}
				break;
			case charsToUIntD('C','H','A','N'):
				{
					File->read(&type, 4);
					size -= 4;
					if (!strncmp(type, "COLR", 4))
						currTexture=0;
					else if (!strncmp(type, "DIFF", 4))
						currTexture=1;
					else if (!strncmp(type, "LUMI", 4))
						currTexture=5;
					else if (!strncmp(type, "SPEC", 4))
						currTexture=2;
					else if (!strncmp(type, "REFL", 4))
						currTexture=3;
					else if (!strncmp(type, "TRAN", 4))
						currTexture=4;
					else if (!strncmp(type, "BUMP", 4))
						currTexture=6;
				}
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading channel ", type);
#endif
				break;
			case charsToUIntD('I','M','A','G'):
#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading channel map.");
#endif
				{
					u16 index;
					File->read(&index, 2);
#ifndef __BIG_ENDIAN__
					index=os::Byteswap::byteswap(index);
#endif
					size -= 2;
					if (index)
						mat->Texture[currTexture].Map=Images[index-1];
				}
				break;
			case charsToUIntD('P','R','O','J'): // define the projection type

#ifdef LWO_READER_DEBUG
				os::Printer::log("LWO loader: loading channel projection type.");
#endif
				{
					u16 index;
					File->read(&index, 2);
#ifndef __BIG_ENDIAN__
					index=os::Byteswap::byteswap(index);
#endif
					size -= 2;
#ifdef LWO_READER_DEBUG
					if (index != 5)
						os::Printer::log("LWO loader: wrong channel projection type", core::stringc(index).c_str());
#endif
					mat->Texture[currTexture].Projection=(u8)index;
				}
				break;
			case charsToUIntD('W','R','P','W'): // for cylindrical and spherical projections

			case charsToUIntD('W','R','P','H'): // for cylindrical and spherical projections

			default:
				{
#ifdef LWO_READER_DEBUG
					os::Printer::log("LWO loader: skipping ", core::stringc((char*)&uiType, 4));
#endif
					File->seek(subsize, true);
					size -= subsize;
				}
		}
	}

	if (mat->Transparency != 0.f)
	{
		irrMat.MaterialType=video::EMT_TRANSPARENT_ADD_COLOR;
	}
}


u32 CLWOMeshFileLoader::readColor(video::SColor& color)
{
	if (FormatVersion!=2)
	{
		u8 colorComponent;
		File->read(&colorComponent, 1);
		color.setRed(colorComponent);
		File->read(&colorComponent, 1);
		color.setGreen(colorComponent);
		File->read(&colorComponent, 1);
		color.setBlue(colorComponent);
		// unknown value

		File->read(&colorComponent, 1);
		return 4;
	}
	else
	{
		video::SColorf col;
		File->read(&col.r, 4);
#ifndef __BIG_ENDIAN__
		col.r=os::Byteswap::byteswap(col.r);
#endif
		File->read(&col.g, 4);
#ifndef __BIG_ENDIAN__
		col.g=os::Byteswap::byteswap(col.g);
#endif
		File->read(&col.b, 4);
#ifndef __BIG_ENDIAN__
		col.b=os::Byteswap::byteswap(col.b);
#endif
		color=col.toSColor();
		return 12;
	}
}

u32 CLWOMeshFileLoader::readString(core::stringc& name, u32 size)
{
	c8 c;

	name="";
	if (size)
		name.reserve(size);
	File->read(&c, 1);
	while (c)
	{
		name.append(c);
		File->read(&c, 1);
	}
	// read extra 0 upon odd file position

	if (File->getPos() & 0x1)
	{
		File->read(&c, 1);
		return (name.size()+2);
	}
	return (name.size()+1);
}


u32 CLWOMeshFileLoader::readVec(core::vector3df& vec)
{
	File->read(&vec.X, 4);
#ifndef __BIG_ENDIAN__
	vec.X=os::Byteswap::byteswap(vec.X);
#endif
	File->read(&vec.Y, 4);
#ifndef __BIG_ENDIAN__
	vec.Y=os::Byteswap::byteswap(vec.Y);
#endif
	File->read(&vec.Z, 4);
#ifndef __BIG_ENDIAN__
	vec.Z=os::Byteswap::byteswap(vec.Z);
#endif
	return 12;
}


u32 CLWOMeshFileLoader::readVX(u32& num)
{
	u16 tmpIndex;

	File->read(&tmpIndex, 2);
#ifndef __BIG_ENDIAN__
	tmpIndex=os::Byteswap::byteswap(tmpIndex);
#endif
	num=tmpIndex;
	if (num >= 0xFF00)
	{
		File->read(&tmpIndex, 2);
#ifndef __BIG_ENDIAN__
		tmpIndex=os::Byteswap::byteswap(tmpIndex);
#endif
		num=((num << 16)|tmpIndex) & ~0xFF000000;
		return 4;
	}
	return 2;
}


bool CLWOMeshFileLoader::readFileHeader()
{
	u32 Id;

	File->read(&Id, 4);
#ifndef __BIG_ENDIAN__
	Id=os::Byteswap::byteswap(Id);
#endif
	if (Id != 0x464f524d) // FORM

		return false;

	//skip the file length

	File->read(&Id, 4);

	File->read(&Id, 4);
#ifndef __BIG_ENDIAN__
	Id=os::Byteswap::byteswap(Id);
#endif
	// Currently supported: LWOB, LWLO, LWO2

	switch (Id)
	{
		case 0x4c574f42:
			FormatVersion = 0; // LWOB

		break;
		case 0x4c574c4f:
			FormatVersion = 1; // LWLO

		break;
		case 0x4c574f32:
			FormatVersion = 2; // LWO2

		break;
		default:
			return false; // unsupported

	}

	return true;
}


video::ITexture* CLWOMeshFileLoader::loadTexture(const core::stringc& file)
{
	video::IVideoDriver* driver = SceneManager->getVideoDriver();

	if (FileSystem->existFile(file))
		return driver->getTexture(file);

	core::stringc strippedName=FileSystem->getFileBasename(file);
	if (FileSystem->existFile(strippedName))
		return driver->getTexture(strippedName);
	core::stringc newpath = FileSystem->getFileDir(File->getFileName());
	newpath.append("/");
	newpath.append(strippedName);
	if (FileSystem->existFile(newpath))
		return driver->getTexture(newpath);
	os::Printer::log("Could not load texture", file.c_str(), ELL_WARNING);

	return 0;
}


} // end namespace scene

} // end namespace irr


Options Liens officiels Caractéristiques Statistiques Communauté
Corrections
irrlicht
irrklang
irredit
irrxml
xhtml 1.0
css 2.1
Propulsé par FluxBB
Traduit par FluxBB.fr
881 membres
1427 sujets
11117 messages
Dernier membre inscrit: Bidule
20 invités en ligne
Aucun membre connecté
RSS Feed