Browse Source

LWOB loader nearly finished, LWO2 is WIP (many hours with the hex editor to come ...). Added test models for LWOB. Cleaned up the 3DS loader, overloaded ASSIMP_stricmp for std::string.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@109 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
aramis_acg 17 years ago
parent
commit
0148d06678

+ 47 - 95
code/3DSLoader.cpp

@@ -114,24 +114,20 @@ void Dot3DSImporter::InternReadFile(
 
 	// Check whether we can read from the file
 	if( file.get() == NULL)
-	{
-		throw new ImportErrorException( "Failed to open file " + pFile + ".");
-	}
+		throw new ImportErrorException( "Failed to open 3DS file " + pFile + ".");
 
 	// check whether the .3ds file is large enough to contain
 	// at least one chunk.
 	size_t fileSize = file->FileSize();
 	if( fileSize < 16)
-	{
 		throw new ImportErrorException( "3DS File is too small.");
-	}
 
 	this->mScene = new Dot3DS::Scene();
 
 	// allocate storage and copy the contents of the file to a memory buffer
-	this->mBuffer = new unsigned char[fileSize];
-	file->Read( mBuffer, 1, fileSize);
-	this->mCurrent = this->mBuffer;
+	std::vector<unsigned char> mBuffer2(fileSize);
+	file->Read( &mBuffer2[0], 1, fileSize);
+	this->mCurrent = this->mBuffer = &mBuffer2[0];
 	this->mLast = this->mBuffer+fileSize;
 
 	// initialize members
@@ -146,51 +142,39 @@ void Dot3DSImporter::InternReadFile(
 	this->bHasBG = false;
 
 	int iRemaining = (unsigned int)fileSize;
+	this->ParseMainChunk(iRemaining);
 
-	// parse the file
-	try
+	// Generate an unique set of vertices/indices for
+	// all meshes contained in the file
+	for (std::vector<Dot3DS::Mesh>::iterator
+		i =  this->mScene->mMeshes.begin();
+		i != this->mScene->mMeshes.end();++i)
 	{
-		this->ParseMainChunk(iRemaining);
+		// TODO: see function body
+		this->CheckIndices(&(*i));
+		this->MakeUnique(&(*i));
 
-		// Generate an unique set of vertices/indices for
-		// all meshes contained in the file
-		for (std::vector<Dot3DS::Mesh>::iterator
-			i =  this->mScene->mMeshes.begin();
-			i != this->mScene->mMeshes.end();++i)
-		{
-			// TODO: see function body
-			this->CheckIndices(&(*i));
-			this->MakeUnique(&(*i));
-
-			// first generate normals for the mesh
-			this->GenNormals(&(*i));
-		}
-
-		// Apply scaling and offsets to all texture coordinates
-		TextureTransform::ApplyScaleNOffset(this->mScene->mMaterials);
+		// first generate normals for the mesh
+		this->GenNormals(&(*i));
+	}
 
-		// Replace all occurences of the default material with a valid material.
-		// Generate it if no material containing DEFAULT in its name has been
-		// found in the file
-		this->ReplaceDefaultMaterial();
+	// Apply scaling and offsets to all texture coordinates
+	TextureTransform::ApplyScaleNOffset(this->mScene->mMaterials);
 
-		// Convert the scene from our internal representation to an aiScene object
-		this->ConvertScene(pScene);
+	// Replace all occurences of the default material with a valid material.
+	// Generate it if no material containing DEFAULT in its name has been
+	// found in the file
+	this->ReplaceDefaultMaterial();
 
-		// Generate the node graph for the scene. This is a little bit
-		// tricky since we'll need to split some meshes into submeshes
-		this->GenerateNodeGraph(pScene);
+	// Convert the scene from our internal representation to an aiScene object
+	this->ConvertScene(pScene);
 
-		// Now apply a master scaling factor to the scene
-		this->ApplyMasterScale(pScene);
+	// Generate the node graph for the scene. This is a little bit
+	// tricky since we'll need to split some meshes into submeshes
+	this->GenerateNodeGraph(pScene);
 
-	}
-	catch ( ImportErrorException* ex)
-	{
-		delete[] this->mBuffer;AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
-		throw ex;
-	}
-	delete[] this->mBuffer;AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
+	// Now apply a master scaling factor to the scene
+	this->ApplyMasterScale(pScene);
 }
 // ------------------------------------------------------------------------------------------------
 void Dot3DSImporter::ApplyMasterScale(aiScene* pScene)
@@ -250,8 +234,6 @@ void Dot3DSImporter::ParseMainChunk(int& piRemaining)
 	switch (psChunk->Flag)
 	{
 	case Dot3DSFile::CHUNK_MAIN:
-	//case 0x444d: // bugfix
-
 		this->ParseEditorChunk(iRemaining);
 		break;
 	};
@@ -274,11 +256,8 @@ void Dot3DSImporter::ParseEditorChunk(int& piRemaining)
 	const Dot3DSFile::Chunk* psChunk;
 
 	this->ReadChunk(&psChunk);
-	
-
 	const unsigned char* pcCur = this->mCurrent;
-	const unsigned char* pcCurNext = pcCur + (psChunk->Size 
-		- sizeof(Dot3DSFile::Chunk));
+	const unsigned char* pcCurNext = pcCur + (psChunk->Size - sizeof(Dot3DSFile::Chunk));
 
 	// get chunk type
 	int iRemaining = (psChunk->Size - sizeof(Dot3DSFile::Chunk));
@@ -331,11 +310,8 @@ void Dot3DSImporter::ParseObjectChunk(int& piRemaining)
 	const Dot3DSFile::Chunk* psChunk;
 
 	this->ReadChunk(&psChunk);
-	
-
 	const unsigned char* pcCur = this->mCurrent;
-	const unsigned char* pcCurNext = pcCur + (psChunk->Size 
-		- sizeof(Dot3DSFile::Chunk));
+	const unsigned char* pcCurNext = pcCur + (psChunk->Size - sizeof(Dot3DSFile::Chunk));
 
 	const unsigned char* sz = this->mCurrent;
 	unsigned int iCnt = 0;
@@ -384,9 +360,7 @@ void Dot3DSImporter::ParseObjectChunk(int& piRemaining)
 			}
 		break;
 
-
 	case Dot3DSFile::CHUNK_BIT_MAP:
-
 		this->mBackgroundImage = std::string((const char*)this->mCurrent);
 		break;
 
@@ -438,11 +412,8 @@ void Dot3DSImporter::ParseChunk(int& piRemaining)
 	const Dot3DSFile::Chunk* psChunk;
 
 	this->ReadChunk(&psChunk);
-	
-
 	const unsigned char* pcCur = this->mCurrent;
-	const unsigned char* pcCurNext = pcCur + (psChunk->Size 
-		- sizeof(Dot3DSFile::Chunk));
+	const unsigned char* pcCurNext = pcCur + (psChunk->Size - sizeof(Dot3DSFile::Chunk));
 
 	// get chunk type
 	int iRemaining = (psChunk->Size - sizeof(Dot3DSFile::Chunk));
@@ -473,11 +444,8 @@ void Dot3DSImporter::ParseKeyframeChunk(int& piRemaining)
 	const Dot3DSFile::Chunk* psChunk;
 
 	this->ReadChunk(&psChunk);
-	
-
 	const unsigned char* pcCur = this->mCurrent;
-	const unsigned char* pcCurNext = pcCur + (psChunk->Size 
-		- sizeof(Dot3DSFile::Chunk));
+	const unsigned char* pcCurNext = pcCur + (psChunk->Size - sizeof(Dot3DSFile::Chunk));
 
 	// get chunk type
 	int iRemaining = (psChunk->Size - sizeof(Dot3DSFile::Chunk));
@@ -512,8 +480,7 @@ void Dot3DSImporter::InverseNodeSearch(Dot3DS::Node* pcNode,Dot3DS::Node* pcCurr
 	}
 	if (pcCurrent->mHierarchyPos == pcNode->mHierarchyPos)
 	{
-		if(NULL != pcCurrent->mParent)
-			pcCurrent->mParent->push_back(pcNode);
+		if(pcCurrent->mParent)pcCurrent->mParent->push_back(pcNode);
 		else pcCurrent->push_back(pcNode);
 		return;
 	}
@@ -535,7 +502,6 @@ void Dot3DSImporter::ParseHierarchyChunk(int& piRemaining)
 	const unsigned char* sz = (unsigned char*)this->mCurrent;
 	unsigned int iCnt = 0;
 	uint16_t iHierarchy;
-//	uint16_t iTemp;
 	Dot3DS::Node* pcNode;
 	switch (psChunk->Flag)
 	{
@@ -754,11 +720,8 @@ void Dot3DSImporter::ParseFaceChunk(int& piRemaining)
 	Dot3DS::Mesh& mMesh = this->mScene->mMeshes.back();
 
 	this->ReadChunk(&psChunk);
-	
-
 	const unsigned char* pcCur = this->mCurrent;
-	const unsigned char* pcCurNext = pcCur + (psChunk->Size 
-		- sizeof(Dot3DSFile::Chunk));
+	const unsigned char* pcCurNext = pcCur + (psChunk->Size - sizeof(Dot3DSFile::Chunk));
 
 	// get chunk type
 	const unsigned char* sz = this->mCurrent;
@@ -855,11 +818,8 @@ void Dot3DSImporter::ParseMeshChunk(int& piRemaining)
 	Dot3DS::Mesh& mMesh = this->mScene->mMeshes.back();
 
 	this->ReadChunk(&psChunk);
-	
-
 	const unsigned char* pcCur = this->mCurrent;
-	const unsigned char* pcCurNext = pcCur + (psChunk->Size 
-		- sizeof(Dot3DSFile::Chunk));
+	const unsigned char* pcCurNext = pcCur + (psChunk->Size - sizeof(Dot3DSFile::Chunk));
 
 	// get chunk type
 	const unsigned char* sz = this->mCurrent;
@@ -884,8 +844,6 @@ void Dot3DSImporter::ParseMeshChunk(int& piRemaining)
 		break;
 	case Dot3DSFile::CHUNK_TRMATRIX:
 		{
-		// http://www.gamedev.net/community/forums/topic.asp?topic_id=263063
-		// http://www.gamedev.net/community/forums/topic.asp?topic_id=392310
 		pf = (float*)this->mCurrent;
 		this->mCurrent += 12 * sizeof(float);
 
@@ -901,7 +859,6 @@ void Dot3DSImporter::ParseMeshChunk(int& piRemaining)
 		mMesh.mMat.a4 = pf[9];
 		mMesh.mMat.b4 = pf[10];
 		mMesh.mMat.c4 = pf[11];
-		//mMesh.mMat.Transpose(); // todo ----
 
 		// now check whether the matrix has got a negative determinant
 		// If yes, we need to flip all vertices' x axis ....
@@ -941,15 +898,6 @@ void Dot3DSImporter::ParseMeshChunk(int& piRemaining)
 		}
 		break;
 
-#if 0
-	case Dot3DSFile::CHUNK_TXTINFO:
-
-		// for debugging purposes. Read two bytes to determine the mapping type
-		iNum = *((uint16_t*)this->mCurrent);
-		this->mCurrent += sizeof(uint16_t);
-	break;
-#endif
-
 	case Dot3DSFile::CHUNK_FACELIST:
 
 		iNum = *((uint16_t*)this->mCurrent);
@@ -996,11 +944,8 @@ void Dot3DSImporter::ParseMaterialChunk(int& piRemaining)
 	const Dot3DSFile::Chunk* psChunk;
 
 	this->ReadChunk(&psChunk);
-	
-
 	const unsigned char* pcCur = this->mCurrent;
-	const unsigned char* pcCurNext = pcCur + (psChunk->Size 
-		- sizeof(Dot3DSFile::Chunk));
+	const unsigned char* pcCurNext = pcCur + (psChunk->Size - sizeof(Dot3DSFile::Chunk));
 
 	// get chunk type
 	const unsigned char* sz = this->mCurrent;
@@ -1018,11 +963,14 @@ void Dot3DSImporter::ParseMaterialChunk(int& piRemaining)
 		// truncate it.
 		while (*sz++ != '\0')
 		{
-			if (sz > pcCurNext-1)break;
+			if (sz > pcCurNext-1)
+			{
+				DefaultLogger::get()->error("Material name string is too long");
+				break;
+			}
 			++iCnt;
 		}
-		this->mScene->mMaterials.back().mName = std::string(
-			(const char*)this->mCurrent,iCnt);
+		this->mScene->mMaterials.back().mName = std::string((const char*)this->mCurrent,iCnt);
 		break;
 	case Dot3DSFile::CHUNK_MAT_DIFFUSE:
 		pc = &this->mScene->mMaterials.back().mDiffuse;
@@ -1030,6 +978,7 @@ void Dot3DSImporter::ParseMaterialChunk(int& piRemaining)
 		if (is_qnan(pc->r))
 		{
 			// color chunk is invalid. Simply ignore it
+			DefaultLogger::get()->error("Unable to read DIFFUSE chunk");
 			pc->r = pc->g = pc->b = 1.0f;
 		}
 		break;
@@ -1039,6 +988,7 @@ void Dot3DSImporter::ParseMaterialChunk(int& piRemaining)
 		if (is_qnan(pc->r))
 		{
 			// color chunk is invalid. Simply ignore it
+			DefaultLogger::get()->error("Unable to read SPECULAR chunk");
 			pc->r = pc->g = pc->b = 1.0f;
 		}
 		break;
@@ -1048,6 +998,7 @@ void Dot3DSImporter::ParseMaterialChunk(int& piRemaining)
 		if (is_qnan(pc->r))
 		{
 			// color chunk is invalid. Simply ignore it
+			DefaultLogger::get()->error("Unable to read AMBIENT chunk");
 			pc->r = pc->g = pc->b = 1.0f;
 		}
 		break;
@@ -1058,6 +1009,7 @@ void Dot3DSImporter::ParseMaterialChunk(int& piRemaining)
 		{
 			// color chunk is invalid. Simply ignore it
 			// EMISSSIVE TO 0|0|0
+			DefaultLogger::get()->error("Unable to read EMISSIVE chunk");
 			pc->r = pc->g = pc->b = 0.0f;
 		}
 		break;

+ 2 - 4
code/ASELoader.cpp

@@ -392,8 +392,7 @@ void ASEImporter::BuildNodes()
 			{
 				continue;
 			}
-			if (szMyName[1].length() == szMyName2[0].length() &&
-				0 == ASSIMP_stricmp ( szMyName[1].c_str(), szMyName2[0].c_str()))
+			if (!ASSIMP_stricmp ( szMyName[1], szMyName2[0]))
 			{
 				bKnowParent = true;
 				break;
@@ -403,8 +402,7 @@ void ASEImporter::BuildNodes()
 			// that has already been handled and added to the list
 			if (i2 < i)
 			{
-				if (szMyName[1].length() == szMyName2[1].length() &&
-					0 == ASSIMP_stricmp ( szMyName[1].c_str(), szMyName2[1].c_str()))
+				if (ASSIMP_stricmp ( szMyName[1], szMyName2[1]))
 				{
 					bKnowParent = true;
 					break;

+ 1 - 1
code/CalcTangentsProcess.cpp

@@ -88,7 +88,7 @@ void CalcTangentsProcess::SetupProperties(const Importer* pImp)
 	// get the current value of the property
 	this->configMaxAngle = pImp->GetProperty(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE,45000) / 1000.0f;
 	this->configMaxAngle = std::max(std::min(this->configMaxAngle,180.0f),0.0f);
-	this->configMaxAngle *= 0.0174532925f;
+	this->configMaxAngle = AI_DEG_TO_RAD(this->configMaxAngle);
 }
 
 // ------------------------------------------------------------------------------------------------

+ 1 - 1
code/GenVertexNormalsProcess.cpp

@@ -78,7 +78,7 @@ void GenVertexNormalsProcess::SetupProperties(const Importer* pImp)
 	// get the current value of the property
 	this->configMaxAngle = pImp->GetProperty(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,180000) / 1000.0f;
 	this->configMaxAngle = std::max(std::min(this->configMaxAngle,180.0f),0.0f);
-	this->configMaxAngle *= 0.0174532925f;
+	this->configMaxAngle = AI_DEG_TO_RAD(this->configMaxAngle);
 }
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.

+ 41 - 1
code/LWOFileData.h

@@ -51,6 +51,7 @@ Original copyright notice: "Ernie Wright  17 Sep 00"
 
 
 #include "IFF.h"
+#include <vector>
 #include "../include/aiMesh.h"
 
 namespace Assimp {
@@ -239,6 +240,29 @@ struct Face : public aiFace
 	unsigned int surfaceIndex;
 };
 
+// ---------------------------------------------------------------------------
+/** \brief LWO2 gradient keyframe
+ */
+struct GradientKey
+{
+	aiColor4D color;
+	float value;
+};
+
+// ---------------------------------------------------------------------------
+/** \brief Data structure for a LWO2 gradient
+ */
+struct GradientInfo
+{
+	GradientInfo()
+		: mStart(0.0f)
+		, mEnd(1.0f)
+	{}
+
+	float mStart,mEnd;
+	bool mRepeat;
+	std::vector<GradientKey> mKeys;
+};
 
 
 // ---------------------------------------------------------------------------
@@ -255,6 +279,14 @@ struct Texture
 
 	//! Strength of the texture
 	float mStrength;
+
+
+	/*************** SPECIFIC TO LWO2 *********************/
+	uint32_t type; // type of the texture
+
+	
+	GradientInfo mGradient;
+	// todo ... maybe support for procedurals?
 };
 
 
@@ -285,7 +317,7 @@ struct Surface
 	float mDiffuseValue,mSpecularValue,mTransparency,mGlossiness;
 
 	//! Maximum angle between two adjacent triangles
-	//! that they can be smoothed
+	//! that they can be smoothed - in degrees
 	float mMaximumSmoothAngle;
 
 	//! Textures
@@ -293,6 +325,14 @@ struct Surface
 		mBumpTexture,mTransparencyTexture;
 };
 
+// ---------------------------------------------------------------------------
+#define AI_LWO_VALIDATE_CHUNK_LENGTH(length,name,size) \
+	if (length < size) \
+	{ \
+		DefaultLogger::get()->warn("LWO: "#name" chunk is too small"); \
+		break; \
+	} \
+
 }}
 
 

+ 56 - 156
code/LWOLoader.cpp

@@ -44,22 +44,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // internal headers
 #include "LWOLoader.h"
 #include "MaterialSystem.h"
+#include "StringComparison.h"
 #include "ByteSwap.h"
 
 // public assimp headers
 #include "../include/IOStream.h"
 #include "../include/IOSystem.h"
-#include "../include/aiMesh.h"
 #include "../include/aiScene.h"
 #include "../include/aiAssert.h"
 #include "../include/DefaultLogger.h"
+#include "../include/assimp.hpp"
 
 // boost headers
 #include <boost/scoped_ptr.hpp>
 
 using namespace Assimp;
 
-
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 LWOImporter::LWOImporter()
@@ -92,6 +92,13 @@ bool LWOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
 	return true;
 }
 // ------------------------------------------------------------------------------------------------
+// Setup configuration properties
+void LWOImporter::SetupProperties(const Importer* pImp)
+{
+	this->configGradientResX = pImp->GetProperty(AI_CONFIG_IMPORT_LWO_GRADIENT_RESX,512);
+	this->configGradientResY = pImp->GetProperty(AI_CONFIG_IMPORT_LWO_GRADIENT_RESY,512);
+}
+// ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure. 
 void LWOImporter::InternReadFile( const std::string& pFile, 
 	aiScene* pScene, 
@@ -134,10 +141,18 @@ void LWOImporter::InternReadFile( const std::string& pFile,
 	mSurfaces = &_mSurfaces;
 
 	// old lightwave file format (prior to v6)
-	if (AI_LWO_FOURCC_LWOB == fileType)this->LoadLWOBFile();
+	if (AI_LWO_FOURCC_LWOB == fileType)
+	{
+		mIsLWO2 = false;
+		this->LoadLWOBFile();
+	}
 
 	// new lightwave format
-	else if (AI_LWO_FOURCC_LWO2 == fileType)this->LoadLWO2File();
+	else if (AI_LWO_FOURCC_LWO2 == fileType)
+	{
+		mIsLWO2 = true;
+		this->LoadLWO2File();
+	}
 
 	// we don't know this format
 	else 
@@ -198,6 +213,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
 		// generate the mesh 
 		aiMesh* mesh = pScene->mMeshes[p] = new aiMesh();
 		mesh->mNumFaces = sorted.size();
+		mesh->mMaxSmoothingAngle = AI_DEG_TO_RAD((*mSurfaces)[i].mMaximumSmoothAngle);
 
 		for (SortedRep::const_iterator it = sorted.begin(), end = sorted.end();
 			it != end;++it)
@@ -259,15 +275,40 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat
 	if (surf.mSpecularValue && surf.mGlossiness)
 	{
 		// this is only an assumption, needs to be confirmed.
-		/*if (16.0f >= surf.mGlossiness)surf.mGlossiness = 10.0f;
-		else if (64.0f >= surf.mGlossiness)surf.mGlossiness = 14.0f;
-		else if (256.0f >= surf.mGlossiness)surf.mGlossiness = 20.0f;
-		else surf.mGlossiness = 24.0f;*/
+		// the values have been tweaked by hand and seem to be correct.
+		float fGloss;
+		if (mIsLWO2)fGloss = surf.mGlossiness * 0.8f;
+		else
+		{
+			if (16.0f >= surf.mGlossiness)fGloss = 6.0f;
+			else if (64.0f >= surf.mGlossiness)fGloss = 20.0f;
+			else if (256.0f >= surf.mGlossiness)fGloss = 50.0f;
+			else fGloss = 80.0f;
+		}
 
 		pcMat->AddProperty<float>(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH);
-		pcMat->AddProperty<float>(&surf.mGlossiness,1,AI_MATKEY_SHININESS);
+		pcMat->AddProperty<float>(&fGloss,1,AI_MATKEY_SHININESS);
 	}
 
+	// (the diffuse value is just a scaling factor)
+	aiColor3D clr = surf.mColor;
+	clr.r *= surf.mDiffuseValue;
+	clr.g *= surf.mDiffuseValue;
+	clr.b *= surf.mDiffuseValue;
+	pcMat->AddProperty<aiColor3D>(&surf.mColor,1,AI_MATKEY_COLOR_DIFFUSE);
+
+	// specular color
+	clr.r = surf.mSpecularValue;
+	clr.g = surf.mSpecularValue;
+	clr.b = surf.mSpecularValue;
+	pcMat->AddProperty<aiColor3D>(&surf.mColor,1,AI_MATKEY_COLOR_SPECULAR);
+
+	// opacity
+	float f = 1.0f-surf.mTransparency;
+	pcMat->AddProperty<float>(&f,1,AI_MATKEY_OPACITY);
+
+	// now handle all textures ...
+	// TODO
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -334,7 +375,9 @@ void LWOImporter::ResolveTags()
 	{
 		for (unsigned int i = 0; i < mSurfaces->size();++i)
 		{
-			if ((*mTags)[a] == (*mSurfaces)[i].mName)
+			const std::string& c = (*mTags)[a];
+			const std::string& d = (*mSurfaces)[i].mName;
+			if (!ASSIMP_stricmp(c,d))
 			{
 				(*mMapping)[a] = i;
 				break;
@@ -352,7 +395,7 @@ void LWOImporter::ParseString(std::string& out,unsigned int max)
 	{
 		if (++iCursor > max)
 		{
-			DefaultLogger::get()->warn("LWOB: Invalid file, texture name (TIMG) is too long");
+			DefaultLogger::get()->warn("LWOB: Invalid file, string is is too long");
 			break;
 		}
 		++in;
@@ -372,14 +415,6 @@ void LWOImporter::AdjustTexturePath(std::string& out)
 	}
 }
 
-// ------------------------------------------------------------------------------------------------
-#define AI_LWO_VALIDATE_CHUNK_LENGTH(length,name,size) \
-	if (length < size) \
-	{ \
-		DefaultLogger::get()->warn("LWO: "#name" chunk is too small"); \
-		break; \
-	} \
-
 // ------------------------------------------------------------------------------------------------
 void LWOImporter::LoadLWOTags(unsigned int size)
 {
@@ -387,149 +422,14 @@ void LWOImporter::LoadLWOTags(unsigned int size)
 	const char* const szEnd = szLast+size;
 	while (szCur < szEnd)
 	{
-		if (!(*szCur++))
+		if (!(*szCur))
 		{
 			const unsigned int len = unsigned int(szCur-szLast);
 			mTags->push_back(std::string(szLast,len));
 			szCur += len & 1;
 			szLast = szCur;
 		}
-	}
-}
-
-// ------------------------------------------------------------------------------------------------
-void LWOImporter::LoadLWOBSurface(unsigned int size)
-{
-	LE_NCONST uint8_t* const end = mFileBuffer + size;
-
-	uint32_t iCursor = 0;
-	mSurfaces->push_back( LWO::Surface () );
-	LWO::Surface& surf = mSurfaces->back();
-	LWO::Texture* pTex = NULL;
-
-	// at first we'll need to read the name of the surface
-	LE_NCONST uint8_t* sz = mFileBuffer;
-	while (*mFileBuffer)
-	{
-		if (++mFileBuffer > end)throw new ImportErrorException("LWOB: Invalid file, surface name is too long");
-	}
-	unsigned int len = unsigned int (mFileBuffer-sz);
-	surf.mName = std::string((const char*)sz,len);
-	mFileBuffer++;
-	if (!(len & 1))++mFileBuffer; // skip one byte if the length of the surface name is odd
-	while (true)
-	{
-		if (mFileBuffer + 6 > end)
-			break;
-
-		// no proper IFF header here - the chunk length is specified as int16
-		uint32_t head_type		= *((LE_NCONST uint32_t*)mFileBuffer);mFileBuffer+=4;
-		uint16_t head_length	= *((LE_NCONST uint16_t*)mFileBuffer);mFileBuffer+=2;
-		AI_LSWAP4(head_type);
-		AI_LSWAP2(head_length);
-		if (mFileBuffer + head_length > end)
-		{
-			throw new ImportErrorException("LWOB: Invalid file, the size attribute of "
-				"a surface sub chunk points behind the end of the file");
-		}
-		LE_NCONST uint8_t* const next = mFileBuffer+head_length;
-		switch (head_type)
-		{
-			// diffuse color
-		case AI_LWO_COLR:
-			{
-				AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,COLR,3);
-				surf.mColor.r = *mFileBuffer++ / 255.0f;
-				surf.mColor.g = *mFileBuffer++ / 255.0f;
-				surf.mColor.b = *mFileBuffer   / 255.0f;
-				break;
-			}
-			// diffuse strength ... hopefully
-		case AI_LWO_DIFF:
-			{
-				AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,DIFF,2);
-				AI_LSWAP2(mFileBuffer);
-				surf.mDiffuseValue = *((int16_t*)mFileBuffer) / 255.0f;
-				break;
-			}
-			// specular strength ... hopefully
-		case AI_LWO_SPEC:
-			{
-				AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,SPEC,2);
-				AI_LSWAP2(mFileBuffer);
-				surf.mSpecularValue = *((int16_t*)mFileBuffer) / 255.0f;
-				break;
-			}
-		// transparency
-		case AI_LWO_TRAN:
-			{
-				AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,TRAN,2);
-				AI_LSWAP2(mFileBuffer);
-				surf.mTransparency = *((int16_t*)mFileBuffer) / 255.0f;
-				break;
-			}
-		// glossiness
-		case AI_LWO_GLOS:
-			{
-				AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,GLOS,2);
-				AI_LSWAP2(mFileBuffer);
-				surf.mGlossiness = float(*((int16_t*)mFileBuffer));
-				break;
-			}
-		// color texture
-		case AI_LWO_CTEX:
-			{
-				pTex = &surf.mColorTexture;
-				break;
-			}
-		// diffuse texture
-		case AI_LWO_DTEX:
-			{
-				pTex = &surf.mDiffuseTexture;
-				break;
-			}
-		// specular texture
-		case AI_LWO_STEX:
-			{
-				pTex = &surf.mSpecularTexture;
-				break;
-			}
-		// bump texture
-		case AI_LWO_BTEX:
-			{
-				pTex = &surf.mBumpTexture;
-				break;
-			}
-		// transparency texture
-		case AI_LWO_TTEX:
-			{
-				pTex = &surf.mTransparencyTexture;
-				break;
-			}
-			// texture path
-		case AI_LWO_TIMG:
-			{
-				if (pTex)
-				{
-					ParseString(pTex->mFileName,head_length);	
-					AdjustTexturePath(pTex->mFileName);
-					mFileBuffer += pTex->mFileName.length();
-				}
-				else DefaultLogger::get()->warn("LWOB: TIMG tag was encuntered although "
-					"there was no xTEX tag before");
-				break;
-			}
-		// texture strength
-		case AI_LWO_TVAL:
-			{
-				AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,TVAL,1);
-				if (pTex)pTex->mStrength = *mFileBuffer / 255.0f;
-				else DefaultLogger::get()->warn("LWOB: TVAL tag was encuntered "
-					"although there was no xTEX tag before");
-				break;
-			}
-		}
-		mFileBuffer = next;
+		szCur++;
 	}
 }
 

+ 56 - 4
code/LWOLoader.h

@@ -49,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "MaterialSystem.h"
 
 #include <vector>
+struct aiTexture;
 
 namespace Assimp	{
 using namespace LWO;
@@ -74,6 +75,14 @@ public:
 	* See BaseImporter::CanRead() for details.	*/
 	bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
 
+
+	// -------------------------------------------------------------------
+	/** Called prior to ReadFile().
+	* The function is a request to the importer to update its configuration
+	* basing on the Importer's configuration property list.
+	*/
+	void SetupProperties(const Importer* pImp);
+
 protected:
 
 	// -------------------------------------------------------------------
@@ -95,22 +104,49 @@ protected:
 
 	// -------------------------------------------------------------------
 	/** Loads a LWO file in the older LWOB format (LW < 6)
-	*/
+	 */
 	void LoadLWOBFile();
 
 	// -------------------------------------------------------------------
 	/** Loads a LWO file in the newer LWO2 format (LW >= 6)
-	*/
+	 */
 	void LoadLWO2File();
 
 	// -------------------------------------------------------------------
 	/** Loads a surface chunk from an LWOB file
-	*/
+	 *  @param size Maximum size to be read, in bytes.  
+	 */
 	void LoadLWOBSurface(unsigned int size);
 
+	// -------------------------------------------------------------------
+	/** Loads a surface chunk from an LWO2 file
+	 *  @param size Maximum size to be read, in bytes.  
+	 */
+	void LoadLWO2Surface(unsigned int size);
+
+	// -------------------------------------------------------------------
+	/** Loads a texture block from a LWO2 file.
+	 *  @param size Maximum size to be read, in bytes.  
+	 *  @param type Type of the texture block - PROC, GRAD or IMAP
+	 */
+	void LoadLWO2TextureBlock(uint32_t type, unsigned int size );
+
+	// -------------------------------------------------------------------
+	/** Loads an image map from a LWO2 file
+	 *  @param size Maximum size to be read, in bytes.  
+	 *  @param tex Texture object to be filled
+	 */
+	void LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex );
+	void LoadLWO2Gradient(unsigned int size, LWO::Texture& tex );
+	void LoadLWO2Procedural(unsigned int size, LWO::Texture& tex );
+
+	// loads the header - used by thethree functions above
+	void LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex );
+
 	// -------------------------------------------------------------------
 	/** Loads the LWO tag list from the file
-	*/
+	 *  @param size Maximum size to be read, in bytes.  
+	 */
 	void LoadLWOTags(unsigned int size);
 
 	// -------------------------------------------------------------------
@@ -119,6 +155,17 @@ protected:
 	*/
 	void ResolveTags();
 
+	// -------------------------------------------------------------------
+	/** Computes a proper texture form a procedural gradient
+	 *  description.
+	 *  @param grad Gradient description
+     *  @param out List of output textures. The new texture should
+	 *    be added to the list, if the conversion was successful.
+	 *  @return true if successful
+	*/
+	bool ComputeGradientTexture(LWO::GradientInfo& grad,
+		std::vector<aiTexture*>& out);
+
 
 	typedef std::vector<aiVector3D>		PointList;
 	typedef std::vector<LWO::Face>		FaceList;
@@ -162,6 +209,9 @@ private:
 
 protected:
 
+	/** true if the file is a LWO2 file*/
+	bool mIsLWO2;
+
 	/** Temporary point list from the file */
 	PointList* mTempPoints;
 
@@ -187,6 +237,8 @@ protected:
 	/** Output scene */
 	aiScene* pScene;
 
+	/** Configuration option: X and Y size of gradient maps */
+	unsigned int configGradientResX,configGradientResY;
 };
 
 } // end of namespace Assimp

+ 337 - 0
code/LWOMaterial.cpp

@@ -0,0 +1,337 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Implementation of the material oart of the LWO importer class */
+
+// internal headers
+#include "LWOLoader.h"
+#include "MaterialSystem.h"
+#include "ByteSwap.h"
+
+// public assimp headers
+#include "../include/IOStream.h"
+#include "../include/IOSystem.h"
+#include "../include/aiScene.h"
+#include "../include/aiAssert.h"
+#include "../include/DefaultLogger.h"
+
+// boost headers
+#include <boost/scoped_ptr.hpp>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+void LWOImporter::LoadLWOBSurface(unsigned int size)
+{
+	LE_NCONST uint8_t* const end = mFileBuffer + size;
+
+	uint32_t iCursor = 0;
+	mSurfaces->push_back( LWO::Surface () );
+	LWO::Surface& surf = mSurfaces->back();
+	LWO::Texture* pTex = NULL;
+
+	ParseString(surf.mName,size);
+	mFileBuffer+=surf.mName.length()+1;
+	// skip one byte if the length of the surface name is odd
+	if (!(surf.mName.length() & 1))++mFileBuffer; 
+	while (true)
+	{
+		if (mFileBuffer + 6 > end)break;
+
+		// no proper IFF header here - the chunk length is specified as int16
+		uint32_t head_type		= *((LE_NCONST uint32_t*)mFileBuffer);mFileBuffer+=4;
+		uint16_t head_length	= *((LE_NCONST uint16_t*)mFileBuffer);mFileBuffer+=2;
+		AI_LSWAP4(head_type);
+		AI_LSWAP2(head_length);
+		if (mFileBuffer + head_length > end)
+		{
+			throw new ImportErrorException("LWOB: Invalid file, the size attribute of "
+				"a surface sub chunk points behind the end of the file");
+		}
+		LE_NCONST uint8_t* const next = mFileBuffer+head_length;
+		switch (head_type)
+		{
+			// diffuse color
+		case AI_LWO_COLR:
+			{
+				AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,COLR,3);
+				surf.mColor.r = *mFileBuffer++ / 255.0f;
+				surf.mColor.g = *mFileBuffer++ / 255.0f;
+				surf.mColor.b = *mFileBuffer   / 255.0f;
+				break;
+			}
+			// diffuse strength ... hopefully
+		case AI_LWO_DIFF:
+			{
+				AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,DIFF,2);
+				AI_LSWAP2P(mFileBuffer);
+				surf.mDiffuseValue = *((int16_t*)mFileBuffer) / 255.0f;
+				break;
+			}
+			// specular strength ... hopefully
+		case AI_LWO_SPEC:
+			{
+				AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,SPEC,2);
+				AI_LSWAP2P(mFileBuffer);
+				surf.mSpecularValue = *((int16_t*)mFileBuffer) / 255.0f;
+				break;
+			}
+		// transparency
+		case AI_LWO_TRAN:
+			{
+				AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,TRAN,2);
+				AI_LSWAP2P(mFileBuffer);
+				surf.mTransparency = *((int16_t*)mFileBuffer) / 255.0f;
+				break;
+			}
+		// glossiness
+		case AI_LWO_GLOS:
+			{
+				AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,GLOS,2);
+				AI_LSWAP2P(mFileBuffer);
+				surf.mGlossiness = float(*((int16_t*)mFileBuffer));
+				break;
+			}
+		// color texture
+		case AI_LWO_CTEX:
+			{
+				pTex = &surf.mColorTexture;
+				break;
+			}
+		// diffuse texture
+		case AI_LWO_DTEX:
+			{
+				pTex = &surf.mDiffuseTexture;
+				break;
+			}
+		// specular texture
+		case AI_LWO_STEX:
+			{
+				pTex = &surf.mSpecularTexture;
+				break;
+			}
+		// bump texture
+		case AI_LWO_BTEX:
+			{
+				pTex = &surf.mBumpTexture;
+				break;
+			}
+		// transparency texture
+		case AI_LWO_TTEX:
+			{
+				pTex = &surf.mTransparencyTexture;
+				break;
+			}
+			// texture path
+		case AI_LWO_TIMG:
+			{
+				if (pTex)
+				{
+					ParseString(pTex->mFileName,head_length);	
+					AdjustTexturePath(pTex->mFileName);
+					mFileBuffer += pTex->mFileName.length();
+				}
+				else DefaultLogger::get()->warn("LWOB: TIMG tag was encuntered although "
+					"there was no xTEX tag before");
+				break;
+			}
+		// texture strength
+		case AI_LWO_TVAL:
+			{
+				AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,TVAL,1);
+				if (pTex)pTex->mStrength = *mFileBuffer / 255.0f;
+				else DefaultLogger::get()->warn("LWOB: TVAL tag was encuntered "
+					"although there was no xTEX tag before");
+				break;
+			}
+		}
+		mFileBuffer = next;
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
+{
+	LE_NCONST uint8_t* const end = mFileBuffer + size;
+}
+
+// ------------------------------------------------------------------------------------------------
+void LWOImporter::LoadLWO2Procedural(unsigned int size, LWO::Texture& tex )
+{
+	LE_NCONST uint8_t* const end = mFileBuffer + size;
+}
+
+// ------------------------------------------------------------------------------------------------
+void LWOImporter::LoadLWO2Gradient(unsigned int size, LWO::Texture& tex  )
+{
+	LE_NCONST uint8_t* const end = mFileBuffer + size;
+}
+
+// ------------------------------------------------------------------------------------------------
+void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex )
+{
+	LE_NCONST uint8_t* const end = mFileBuffer + size;
+}
+
+// ------------------------------------------------------------------------------------------------
+void LWOImporter::LoadLWO2TextureBlock(uint32_t type, unsigned int size )
+{
+	LE_NCONST uint8_t* const end = mFileBuffer + size;
+
+	LWO::Surface& surf = mSurfaces->back();
+	LWO::Texture tex;
+
+	// now get the exact type of the texture
+}
+
+// ------------------------------------------------------------------------------------------------
+void LWOImporter::LoadLWO2Surface(unsigned int size)
+{
+	LE_NCONST uint8_t* const end = mFileBuffer + size;
+
+	mSurfaces->push_back( LWO::Surface () );
+	LWO::Surface& surf = mSurfaces->back();
+
+	ParseString(surf.mName,size);
+	mFileBuffer+=surf.mName.length()+1;
+	 // skip one byte if the length of the surface name is odd
+	if (!(surf.mName.length() & 1))++mFileBuffer;
+	while (true)
+	{
+		if (mFileBuffer + 6 > end)break;
+
+		// no proper IFF header here - the chunk length is specified as int16
+		uint32_t head_type		= *((LE_NCONST uint32_t*)mFileBuffer);mFileBuffer+=4;
+		uint16_t head_length	= *((LE_NCONST uint16_t*)mFileBuffer);mFileBuffer+=2;
+		AI_LSWAP4(head_type);
+		AI_LSWAP2(head_length);
+		if (mFileBuffer + head_length > end)
+		{
+			throw new ImportErrorException("LWO2: Invalid file, the size attribute of "
+				"a surface sub chunk points behind the end of the file");
+		}
+		LE_NCONST uint8_t* const next = mFileBuffer+head_length;
+		switch (head_type)
+		{
+			// diffuse color
+		case AI_LWO_COLR:
+			{
+				AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,COLR,12);
+				surf.mColor.r = ((float*)mFileBuffer)[0];
+				surf.mColor.g = ((float*)mFileBuffer)[1];
+				surf.mColor.b = ((float*)mFileBuffer)[2];
+				AI_LSWAP4(surf.mColor.r);
+				AI_LSWAP4(surf.mColor.g);
+				AI_LSWAP4(surf.mColor.b);
+				break;
+			}
+			// diffuse strength ... hopefully
+		case AI_LWO_DIFF:
+			{
+				AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,DIFF,4);
+				surf.mDiffuseValue = *((float*)mFileBuffer);
+				AI_LSWAP4(surf.mDiffuseValue);
+				break;
+			}
+			// specular strength ... hopefully
+		case AI_LWO_SPEC:
+			{
+				AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,SPEC,4);
+				surf.mSpecularValue = *((float*)mFileBuffer);
+				AI_LSWAP4(surf.mSpecularValue);
+				break;
+			}
+			// transparency
+		case AI_LWO_TRAN:
+			{
+				AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,TRAN,4);
+				surf.mTransparency = *((float*)mFileBuffer);
+				AI_LSWAP4(surf.mTransparency);
+				break;
+			}
+			// glossiness
+		case AI_LWO_GLOS:
+			{
+				AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,GLOS,4);
+				surf.mGlossiness = *((float*)mFileBuffer);
+				AI_LSWAP4(surf.mGlossiness);
+				break;
+			}
+			// surface bock entry
+		case AI_LWO_BLOK:
+			{
+				AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,BLOK,4);
+				uint32_t type = *((uint32_t*)mFileBuffer);
+				AI_LSWAP4(type);
+
+				switch (type)
+				{
+				case AI_LWO_IMAP:
+				case AI_LWO_PROC:
+				case AI_LWO_GRAD:
+					mFileBuffer+=4;
+					LoadLWO2TextureBlock(type,head_length-4);
+					break;
+				};
+
+				break;
+			}
+		}
+		mFileBuffer = next;
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+bool LWOImporter::ComputeGradientTexture(LWO::GradientInfo& grad,
+	std::vector<aiTexture*>& out)
+{
+	aiTexture* tex = new aiTexture();
+
+	tex->mHeight = configGradientResY;
+	tex->mWidth = configGradientResX;
+	unsigned int numPixels;
+	tex->pcData = new aiTexel[numPixels = tex->mHeight * tex->mWidth];
+
+	// to be implemented ...
+
+	out.push_back(tex);
+	return true;
+}

+ 21 - 26
code/STLLoader.cpp

@@ -109,10 +109,13 @@ void STLImporter::InternReadFile(
 
 	// allocate storage and copy the contents of the file to a memory buffer
 	// (terminate it with zero)
-	this->mBuffer = new char[fileSize+1];
+	std::vector<char> mBuffer2(fileSize+1);
+	
+	file->Read(&mBuffer2[0], 1, fileSize);
+	mBuffer2[fileSize] = '\0';
+
 	this->pScene = pScene;
-	file->Read( (void*)mBuffer, 1, fileSize);
-	const_cast<char*>(this->mBuffer)[fileSize] = '\0';
+	this->mBuffer = &mBuffer2[0];
 
 	// the default vertex color is white
 	clrColorDefault.r = clrColorDefault.g = clrColorDefault.b = clrColorDefault.a = 1.0f;
@@ -130,32 +133,24 @@ void STLImporter::InternReadFile(
 	pScene->mRootNode->mMeshes[0] = 0;
 
 	bool bMatClr = false;
-	try
-	{
-		// check whether the file starts with 'solid' -
-		// in this case we can simply assume it IS a text file. finished.
-		if (!::strncmp(mBuffer,"solid",5))
-			this->LoadASCIIFile();
-		else bMatClr = this->LoadBinaryFile();
-
-		// now copy faces
-		pMesh->mFaces = new aiFace[pMesh->mNumFaces];
-		for (unsigned int i = 0, p = 0; i < pMesh->mNumFaces;++i)
-		{
-			aiFace& face = pMesh->mFaces[i];
-			face.mIndices = new unsigned int[face.mNumIndices = 3];
-			for (unsigned int o = 0; o < 3;++o,++p)
-				face.mIndices[o] = p;
-		}
-	}
-	catch (ImportErrorException* ex)
+
+	// check whether the file starts with 'solid' -
+	// in this case we can simply assume it IS a text file. finished.
+	if (!::strncmp(mBuffer,"solid",5))
+		this->LoadASCIIFile();
+	else bMatClr = this->LoadBinaryFile();
+
+	// now copy faces
+	pMesh->mFaces = new aiFace[pMesh->mNumFaces];
+	for (unsigned int i = 0, p = 0; i < pMesh->mNumFaces;++i)
 	{
-		delete[] this->mBuffer;AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
-		throw ex;
+		aiFace& face = pMesh->mFaces[i];
+		face.mIndices = new unsigned int[face.mNumIndices = 3];
+		for (unsigned int o = 0; o < 3;++o,++p)
+			face.mIndices[o] = p;
 	}
 
-	// create a single default material - everything white, as
-	// we have vertex colors
+	// create a single default material - everything white, as we have vertex colors
 	MaterialHelper* pcMat = new MaterialHelper();
 	aiString s;
 	s.Set(AI_DEFAULT_MATERIAL_NAME);

+ 9 - 1
code/StringComparison.h

@@ -81,6 +81,14 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2)
 #endif
 }
 
+// ---------------------------------------------------------------------------
+inline int ASSIMP_stricmp(const std::string& a, const std::string& b)
+{
+	int i = (int)b.length()-(int)a.length();
+	if (i)return i;
+	return ASSIMP_stricmp(a.c_str(),b.c_str());
+}
+
 // ---------------------------------------------------------------------------
 /** \brief Helper function to do platform independent string comparison.
  *
@@ -121,6 +129,6 @@ inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n)
 	}
 #endif
 }
-};
+}
 
 #endif // !  AI_STRINGCOMPARISON_H_INC

+ 11 - 0
include/aiConfig.h

@@ -105,6 +105,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #define AI_CONFIG_IMPORT_3DS_IGNORE_PIVOT	"imp.3ds.nopivot"
 
+// ---------------------------------------------------------------------------
+/** \brief Sets the resolution of gradient textures generated by
+ *     the LWO loader.
+ *
+ * LightWave represents the gradients with infinite detail,
+ * but for use in realtime the loader computes replacement textures.
+ * The default size is 512 * 512.
+ */
+#define AI_CONFIG_IMPORT_LWO_GRADIENT_RESX	"imp.lwo.gradres_x"
+#define AI_CONFIG_IMPORT_LWO_GRADIENT_RESY	"imp.lwo.gradres_y"
+
 // ---------------------------------------------------------------------------
 /** \brief Specifies the maximum angle that may be between two vertex tangents
  *         that their tangents and bitangents are smoothed.

+ 3 - 0
include/aiDefines.h

@@ -107,4 +107,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_MATH_PI		(3.1415926538)
 #define AI_MATH_TWO_PI	(AI_MATH_PI * 2.0)
 
+#define AI_DEG_TO_RAD(x) (x*0.0174532925f)
+#define AI_RAD_TO_DEG(x) (x*57.2957795f)
+
 #endif // !! AI_DEFINES_H_INC

+ 1 - 1
include/aiMesh.h

@@ -356,7 +356,7 @@ struct aiMesh
 	 */
 	unsigned int mMaterialIndex;
 
-	/** The maximum vertex smooth angle for the mesh.
+	/** The maximum vertex smooth angle for the mesh, in radians
 	 *  If the angle between two vertex normals is larger,
 	 *  the vertex normals should not be smoothed. The GenVertexNormals-Step
 	 *  takes care of this value. The angle is specified in radians.

BIN
test/LWOFiles/LWO2/sphere_with_gradient.lwo


BIN
test/LWOFiles/LWOB/sphere_with_mat_gloss_10pc.lwo


BIN
test/LWOFiles/LWOB/sphere_with_mat_gloss_50pc.lwo


+ 4 - 0
workspaces/vc8/assimp.vcproj

@@ -1325,6 +1325,10 @@
 					RelativePath="..\..\code\LWOLoader.cpp"
 					>
 				</File>
+				<File
+					RelativePath="..\..\code\LWOMaterial.cpp"
+					>
+				</File>
 			</Filter>
 			<Filter
 				Name="MDC"