浏览代码

Finalized material system. Fixed texture coordinate transformation. Improvements to the ASE loaders, normals for the 3DS loader fixed. First try to load bones for MDL7 models (first try = failure ;-)).

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@54 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
aramis_acg 17 年之前
父节点
当前提交
8b2ca95419

+ 54 - 2
code/3DSConverter.cpp

@@ -258,8 +258,15 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat,
 	if (Dot3DS::Dot3DSFile::Phong == oldMat.mShading || 
 	if (Dot3DS::Dot3DSFile::Phong == oldMat.mShading || 
 		Dot3DS::Dot3DSFile::Metal == oldMat.mShading)
 		Dot3DS::Dot3DSFile::Metal == oldMat.mShading)
 	{
 	{
-		mat.AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
-		mat.AddProperty( &oldMat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH);
+		if (!oldMat.mSpecularExponent || !oldMat.mShininessStrength)
+		{
+			oldMat.mShading = Dot3DS::Dot3DSFile::Gouraud;
+		}
+		else
+		{
+			mat.AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
+			mat.AddProperty( &oldMat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH);
+		}
 	}
 	}
 
 
 	// opacity
 	// opacity
@@ -268,6 +275,13 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat,
 	// bump height scaling
 	// bump height scaling
 	mat.AddProperty<float>( &oldMat.mBumpHeight,1,AI_MATKEY_BUMPSCALING);
 	mat.AddProperty<float>( &oldMat.mBumpHeight,1,AI_MATKEY_BUMPSCALING);
 
 
+	// two sided rendering?
+	if (oldMat.mTwoSided)
+	{
+		int i = 0;
+		mat.AddProperty<int>(&i,1,AI_MATKEY_TWOSIDED);
+	}
+
 	// shading mode
 	// shading mode
 	aiShadingMode eShading = aiShadingMode_NoShading;
 	aiShadingMode eShading = aiShadingMode_NoShading;
 	switch (oldMat.mShading)
 	switch (oldMat.mShading)
@@ -308,6 +322,13 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat,
 
 
 		if (is_not_qnan(oldMat.sTexDiffuse.mTextureBlend))
 		if (is_not_qnan(oldMat.sTexDiffuse.mTextureBlend))
 			mat.AddProperty<float>( &oldMat.sTexDiffuse.mTextureBlend, 1, AI_MATKEY_TEXBLEND_DIFFUSE(0));
 			mat.AddProperty<float>( &oldMat.sTexDiffuse.mTextureBlend, 1, AI_MATKEY_TEXBLEND_DIFFUSE(0));
+
+		if (aiTextureMapMode_Clamp != oldMat.sTexDiffuse.mMapMode)
+		{
+			int i = (int)oldMat.sTexSpecular.mMapMode;
+			mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0));
+			mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0));
+		}
 	}
 	}
 	if( oldMat.sTexSpecular.mMapName.length() > 0)
 	if( oldMat.sTexSpecular.mMapName.length() > 0)
 	{
 	{
@@ -317,6 +338,13 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat,
 
 
 		if (is_not_qnan(oldMat.sTexSpecular.mTextureBlend))
 		if (is_not_qnan(oldMat.sTexSpecular.mTextureBlend))
 			mat.AddProperty<float>( &oldMat.sTexSpecular.mTextureBlend, 1, AI_MATKEY_TEXBLEND_SPECULAR(0));
 			mat.AddProperty<float>( &oldMat.sTexSpecular.mTextureBlend, 1, AI_MATKEY_TEXBLEND_SPECULAR(0));
+
+		if (aiTextureMapMode_Clamp != oldMat.sTexSpecular.mMapMode)
+		{
+			int i = (int)oldMat.sTexSpecular.mMapMode;
+			mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_U_SPECULAR(0));
+			mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_V_SPECULAR(0));
+		}
 	}
 	}
 	if( oldMat.sTexOpacity.mMapName.length() > 0)
 	if( oldMat.sTexOpacity.mMapName.length() > 0)
 	{
 	{
@@ -326,6 +354,12 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat,
 
 
 		if (is_not_qnan(oldMat.sTexOpacity.mTextureBlend))
 		if (is_not_qnan(oldMat.sTexOpacity.mTextureBlend))
 			mat.AddProperty<float>( &oldMat.sTexOpacity.mTextureBlend, 1,AI_MATKEY_TEXBLEND_OPACITY(0));
 			mat.AddProperty<float>( &oldMat.sTexOpacity.mTextureBlend, 1,AI_MATKEY_TEXBLEND_OPACITY(0));
+		if (aiTextureMapMode_Clamp != oldMat.sTexOpacity.mMapMode)
+		{
+			int i = (int)oldMat.sTexOpacity.mMapMode;
+			mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_U_OPACITY(0));
+			mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_V_OPACITY(0));
+		}
 	}
 	}
 	if( oldMat.sTexEmissive.mMapName.length() > 0)
 	if( oldMat.sTexEmissive.mMapName.length() > 0)
 	{
 	{
@@ -335,6 +369,12 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat,
 
 
 		if (is_not_qnan(oldMat.sTexEmissive.mTextureBlend))
 		if (is_not_qnan(oldMat.sTexEmissive.mTextureBlend))
 			mat.AddProperty<float>( &oldMat.sTexEmissive.mTextureBlend, 1, AI_MATKEY_TEXBLEND_EMISSIVE(0));
 			mat.AddProperty<float>( &oldMat.sTexEmissive.mTextureBlend, 1, AI_MATKEY_TEXBLEND_EMISSIVE(0));
+		if (aiTextureMapMode_Clamp != oldMat.sTexEmissive.mMapMode)
+		{
+			int i = (int)oldMat.sTexEmissive.mMapMode;
+			mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_U_EMISSIVE(0));
+			mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_V_EMISSIVE(0));
+		}
 	}
 	}
 	if( oldMat.sTexBump.mMapName.length() > 0)
 	if( oldMat.sTexBump.mMapName.length() > 0)
 	{
 	{
@@ -344,6 +384,12 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat,
 
 
 		if (is_not_qnan(oldMat.sTexBump.mTextureBlend))
 		if (is_not_qnan(oldMat.sTexBump.mTextureBlend))
 			mat.AddProperty<float>( &oldMat.sTexBump.mTextureBlend, 1, AI_MATKEY_TEXBLEND_HEIGHT(0));
 			mat.AddProperty<float>( &oldMat.sTexBump.mTextureBlend, 1, AI_MATKEY_TEXBLEND_HEIGHT(0));
+		if (aiTextureMapMode_Clamp != oldMat.sTexBump.mMapMode)
+		{
+			int i = (int)oldMat.sTexBump.mMapMode;
+			mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_U_HEIGHT(0));
+			mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_V_HEIGHT(0));
+		}
 	}
 	}
 	if( oldMat.sTexShininess.mMapName.length() > 0)
 	if( oldMat.sTexShininess.mMapName.length() > 0)
 	{
 	{
@@ -353,6 +399,12 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat,
 
 
 		if (is_not_qnan(oldMat.sTexShininess.mTextureBlend))
 		if (is_not_qnan(oldMat.sTexShininess.mTextureBlend))
 			mat.AddProperty<float>( &oldMat.sTexShininess.mTextureBlend, 1, AI_MATKEY_TEXBLEND_SHININESS(0));
 			mat.AddProperty<float>( &oldMat.sTexShininess.mTextureBlend, 1, AI_MATKEY_TEXBLEND_SHININESS(0));
+		if (aiTextureMapMode_Clamp != oldMat.sTexShininess.mMapMode)
+		{
+			int i = (int)oldMat.sTexShininess.mMapMode;
+			mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_U_SHININESS(0));
+			mat.AddProperty<int>(&i,1,AI_MATKEY_MAPPINGMODE_V_SHININESS(0));
+		}
 	}
 	}
 
 
 	// store the name of the material itself, too
 	// store the name of the material itself, too

+ 22 - 9
code/3DSHelper.h

@@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "../include/aiQuaternion.h"
 #include "../include/aiQuaternion.h"
 #include "../include/aiMesh.h"
 #include "../include/aiMesh.h"
 #include "../include/aiAnim.h"
 #include "../include/aiAnim.h"
+#include "../include/aiMaterial.h"
 
 
 #include "SpatialSort.h"
 #include "SpatialSort.h"
 
 
@@ -263,8 +264,14 @@ public:
 			// Assumed to be in radians.
 			// Assumed to be in radians.
 			CHUNK_MAT_MAP_ANG = 0xA35C,
 			CHUNK_MAT_MAP_ANG = 0xA35C,
 
 
+			// Tiling flags for 3DS files
+			CHUNK_MAT_MAP_TILING = 0xa351,
+
 			// Specifies the file name of a texture
 			// Specifies the file name of a texture
 			CHUNK_MAPFILE   = 0xA300,
 			CHUNK_MAPFILE   = 0xA300,
+
+			// Specifies whether a materail requires two-sided rendering
+			CHUNK_MAT_TWO_SIDE = 0xA081,  
 		// **************************************************************
 		// **************************************************************
 
 
 		// Main keyframer chunk. Contains translation/rotation/scaling data
 		// Main keyframer chunk. Contains translation/rotation/scaling data
@@ -338,7 +345,8 @@ struct Texture
 		mOffsetU(0.0f),
 		mOffsetU(0.0f),
 		mOffsetV(0.0f),
 		mOffsetV(0.0f),
 		mRotation(0.0f),
 		mRotation(0.0f),
-		iUVSrc(0)
+		iUVSrc(0),
+		mMapMode(aiTextureMapMode_Wrap)
 	{
 	{
 		mTextureBlend = std::numeric_limits<float>::quiet_NaN();
 		mTextureBlend = std::numeric_limits<float>::quiet_NaN();
 	}
 	}
@@ -355,6 +363,9 @@ struct Texture
 	float mOffsetV;
 	float mOffsetV;
 	float mRotation;
 	float mRotation;
 
 
+	//! Specifies the mapping mode to be used for the texture
+	aiTextureMapMode mMapMode;
+
 	//! Used internally
 	//! Used internally
 	bool bPrivate;
 	bool bPrivate;
 	int iUVSrc;
 	int iUVSrc;
@@ -372,11 +383,13 @@ struct Material
 	mBumpHeight			(1.0f),
 	mBumpHeight			(1.0f),
 	iBakeUVTransform	(0),
 	iBakeUVTransform	(0),
 	pcSingleTexture		(NULL),
 	pcSingleTexture		(NULL),
-	mShininessStrength	(1.0f)
+	mShininessStrength	(1.0f),
+	mTwoSided			(false)
 	{
 	{
 		static int iCnt = 0;
 		static int iCnt = 0;
-		std::stringstream ss(mName);
+		std::stringstream ss;
 		ss << "$$_UNNAMED_" << iCnt++ << "_$$"; 
 		ss << "$$_UNNAMED_" << iCnt++ << "_$$"; 
+		ss >> mName;
 	}
 	}
 
 
 	//! Name of the material
 	//! Name of the material
@@ -395,7 +408,6 @@ struct Material
 	Dot3DSFile::shadetype3ds mShading;
 	Dot3DSFile::shadetype3ds mShading;
 	//! Opacity of the material
 	//! Opacity of the material
 	float mTransparency;
 	float mTransparency;
-
 	//! Diffuse texture channel
 	//! Diffuse texture channel
 	Texture sTexDiffuse;
 	Texture sTexDiffuse;
 	//! Opacity texture channel
 	//! Opacity texture channel
@@ -408,16 +420,15 @@ struct Material
 	Texture sTexEmissive;
 	Texture sTexEmissive;
 	//! Shininess texture channel
 	//! Shininess texture channel
 	Texture sTexShininess;
 	Texture sTexShininess;
-	
 	//! Scaling factor for the bump values
 	//! Scaling factor for the bump values
 	float mBumpHeight;
 	float mBumpHeight;
-
 	//! Emissive color
 	//! Emissive color
 	aiColor3D mEmissive;
 	aiColor3D mEmissive;
-
 	//! Ambient texture channel
 	//! Ambient texture channel
 	//! (used by the ASE format)
 	//! (used by the ASE format)
 	Texture sTexAmbient;
 	Texture sTexAmbient;
+	//! True if the material must be rendered from two sides
+	bool mTwoSided;
 
 
 	//! Used internally
 	//! Used internally
 	unsigned int iBakeUVTransform;
 	unsigned int iBakeUVTransform;
@@ -431,8 +442,9 @@ struct Mesh
 	Mesh()
 	Mesh()
 	{
 	{
 		static int iCnt = 0;
 		static int iCnt = 0;
-		std::stringstream ss(mName);
+		std::stringstream ss;
 		ss << "$$_UNNAMED_" << iCnt++ << "_$$"; 
 		ss << "$$_UNNAMED_" << iCnt++ << "_$$"; 
+		ss >> mName;
 	}
 	}
 
 
 	//! Name of the mesh
 	//! Name of the mesh
@@ -469,8 +481,9 @@ struct Node
 
 
 	{
 	{
 		static int iCnt = 0;
 		static int iCnt = 0;
-		std::stringstream ss(mName);
+		std::stringstream ss;
 		ss << "$$_UNNAMED_" << iCnt++ << "_$$"; 
 		ss << "$$_UNNAMED_" << iCnt++ << "_$$"; 
+		ss >> mName;
 
 
 		mHierarchyPos = 0;
 		mHierarchyPos = 0;
 		mHierarchyIndex = 0;
 		mHierarchyIndex = 0;

+ 26 - 6
code/3DSLoader.cpp

@@ -1096,6 +1096,10 @@ void Dot3DSImporter::ParseMaterialChunk(int* piRemaining)
 		this->mCurrent += sizeof(uint16_t);
 		this->mCurrent += sizeof(uint16_t);
 		break;
 		break;
 
 
+	case Dot3DSFile::CHUNK_MAT_TWO_SIDE:
+		this->mScene->mMaterials.back().mTwoSided = true;
+		break;
+
 	case Dot3DSFile::CHUNK_MAT_SHININESS:
 	case Dot3DSFile::CHUNK_MAT_SHININESS:
 		pcf = &this->mScene->mMaterials.back().mSpecularExponent;
 		pcf = &this->mScene->mMaterials.back().mSpecularExponent;
 		*pcf = this->ParsePercentageChunk();
 		*pcf = this->ParsePercentageChunk();
@@ -1203,21 +1207,23 @@ void Dot3DSImporter::ParseTextureChunk(int* piRemaining,Dot3DS::Texture* pcOut)
 		pcOut->mScaleU = *((float*)this->mCurrent);
 		pcOut->mScaleU = *((float*)this->mCurrent);
 		if (0.0f == pcOut->mScaleU)
 		if (0.0f == pcOut->mScaleU)
 		{
 		{
-			DefaultLogger::get()->warn("Inverse texture coordinate scaling in the "
-				"x direction is zero. This would be a division through zero. ");
+			DefaultLogger::get()->warn("Texture coordinate scaling in the "
+				"x direction is zero. Assuming this should be 1.0 ... ");
 			pcOut->mScaleU = 1.0f;
 			pcOut->mScaleU = 1.0f;
 		}
 		}
-		pcOut->mScaleU = 1.0f / pcOut->mScaleU;
+		// NOTE: some docs state it is 1/u, others say it is u ... ARGHH!
+		//pcOut->mScaleU = 1.0f / pcOut->mScaleU;
 		break;
 		break;
 	case Dot3DSFile::CHUNK_MAT_MAP_VSCALE:
 	case Dot3DSFile::CHUNK_MAT_MAP_VSCALE:
 		pcOut->mScaleV = *((float*)this->mCurrent);
 		pcOut->mScaleV = *((float*)this->mCurrent);
 		if (0.0f == pcOut->mScaleV)
 		if (0.0f == pcOut->mScaleV)
 		{
 		{
-			DefaultLogger::get()->warn("Inverse texture coordinate scaling in the "
-				"y direction is zero. This would be a division through zero. ");
+			DefaultLogger::get()->warn("Texture coordinate scaling in the "
+				"y direction is zero. Assuming this should be 1.0 ... ");
 			pcOut->mScaleV = 1.0f;
 			pcOut->mScaleV = 1.0f;
 		}
 		}
-		pcOut->mScaleV = 1.0f / pcOut->mScaleV;
+		// NOTE: some docs state it is 1/v, others say it is v ... ARGHH!
+		//pcOut->mScaleV = 1.0f / pcOut->mScaleV;
 		break;
 		break;
 	case Dot3DSFile::CHUNK_MAT_MAP_UOFFSET:
 	case Dot3DSFile::CHUNK_MAT_MAP_UOFFSET:
 		pcOut->mOffsetU = *((float*)this->mCurrent);
 		pcOut->mOffsetU = *((float*)this->mCurrent);
@@ -1228,6 +1234,20 @@ void Dot3DSImporter::ParseTextureChunk(int* piRemaining,Dot3DS::Texture* pcOut)
 	case Dot3DSFile::CHUNK_MAT_MAP_ANG:
 	case Dot3DSFile::CHUNK_MAT_MAP_ANG:
 		pcOut->mRotation = *((float*)this->mCurrent);
 		pcOut->mRotation = *((float*)this->mCurrent);
 		break;
 		break;
+	case Dot3DSFile::CHUNK_MAT_MAP_TILING:
+		uint16_t iFlags = *((uint16_t*)this->mCurrent);
+
+		// check whether the mirror flag is set
+		if (iFlags & 0x2u)
+		{
+			pcOut->mMapMode = aiTextureMapMode_Mirror;
+		}
+		// assume that "decal" means clamping ...
+		else if (iFlags & 0x10u && iFlags & 0x1u)
+		{
+			pcOut->mMapMode = aiTextureMapMode_Clamp;
+		}
+		break;
 	};
 	};
 
 
 	// Go to the starting position of the next chunk on this level
 	// Go to the starting position of the next chunk on this level

+ 52 - 0
code/ASELoader.cpp

@@ -128,6 +128,13 @@ void ASEImporter::InternReadFile(
 	this->mParser = new ASE::Parser((const char*)this->mBuffer);
 	this->mParser = new ASE::Parser((const char*)this->mBuffer);
 	this->mParser->Parse();
 	this->mParser->Parse();
 
 
+	// if absolutely no material has been loaded from the file
+	// we need to generate a default material
+	if (this->mParser->m_vMaterials.empty())
+	{
+		this->GenerateDefaultMaterial();
+	}
+
 	// process all meshes
 	// process all meshes
 	std::vector<aiMesh*> avOutMeshes;
 	std::vector<aiMesh*> avOutMeshes;
 	avOutMeshes.reserve(this->mParser->m_vMeshes.size()*2);
 	avOutMeshes.reserve(this->mParser->m_vMeshes.size()*2);
@@ -171,6 +178,21 @@ void ASEImporter::InternReadFile(
 	return;
 	return;
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
+void ASEImporter::GenerateDefaultMaterial()
+{
+	ai_assert(NULL != this->mParser);
+
+	// add a simple material without sub materials to the parser's list
+	this->mParser->m_vMaterials.push_back ( ASE::Material() );
+	ASE::Material& mat = this->mParser->m_vMaterials.back();
+
+	mat.mDiffuse = aiColor3D(0.5f,0.5f,0.5f);
+	mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f);
+	mat.mAmbient = aiColor3D(0.05f,0.05f,0.05f);
+	mat.mShading = Dot3DSFile::Gouraud;
+	mat.mName = "$$$ASE_DEFAULT";
+}
+// ------------------------------------------------------------------------------------------------
 void ASEImporter::AddNodes(aiScene* pcScene,aiNode* pcParent,
 void ASEImporter::AddNodes(aiScene* pcScene,aiNode* pcParent,
 	const char* szName)
 	const char* szName)
 {
 {
@@ -953,6 +975,7 @@ void ASEImporter::BuildMaterialIndices(aiScene* pcScene)
 	// allocate the output material array
 	// allocate the output material array
 	pcScene->mNumMaterials = iNum;
 	pcScene->mNumMaterials = iNum;
 	pcScene->mMaterials = new aiMaterial*[pcScene->mNumMaterials];
 	pcScene->mMaterials = new aiMaterial*[pcScene->mNumMaterials];
+	Dot3DS::Material** pcIntMaterials = new Dot3DS::Material*[pcScene->mNumMaterials];
 
 
 	iNum = 0;
 	iNum = 0;
 	for (unsigned int iMat = 0; iMat < this->mParser->m_vMaterials.size();++iMat)
 	for (unsigned int iMat = 0; iMat < this->mParser->m_vMaterials.size();++iMat)
@@ -962,6 +985,9 @@ void ASEImporter::BuildMaterialIndices(aiScene* pcScene)
 			ai_assert(NULL != this->mParser->m_vMaterials[iMat].pcInstance);
 			ai_assert(NULL != this->mParser->m_vMaterials[iMat].pcInstance);
 			pcScene->mMaterials[iNum] = this->mParser->m_vMaterials[iMat].pcInstance;
 			pcScene->mMaterials[iNum] = this->mParser->m_vMaterials[iMat].pcInstance;
 
 
+			// store the internal material, too
+			pcIntMaterials[iNum] = &this->mParser->m_vMaterials[iMat];
+
 			// iterate through all meshes and search for one which is using
 			// iterate through all meshes and search for one which is using
 			// this top-level material index
 			// this top-level material index
 			for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh)
 			for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh)
@@ -983,6 +1009,9 @@ void ASEImporter::BuildMaterialIndices(aiScene* pcScene)
 				pcScene->mMaterials[iNum] = this->mParser->m_vMaterials[iMat].
 				pcScene->mMaterials[iNum] = this->mParser->m_vMaterials[iMat].
 					avSubMaterials[iSubMat].pcInstance;
 					avSubMaterials[iSubMat].pcInstance;
 
 
+				// store the internal material, too
+				pcIntMaterials[iNum] = &this->mParser->m_vMaterials[iMat].avSubMaterials[iSubMat];
+
 				// iterate through all meshes and search for one which is using
 				// iterate through all meshes and search for one which is using
 				// this sub-level material index
 				// this sub-level material index
 				for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh)
 				for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh)
@@ -998,6 +1027,29 @@ void ASEImporter::BuildMaterialIndices(aiScene* pcScene)
 			}
 			}
 		}
 		}
 	}
 	}
+	// prepare for the next step
+	for (unsigned int hans = 0; hans < pcScene->mNumMaterials;++hans)
+	{
+		TextureTransform::ApplyScaleNOffset(this->mParser->m_vMaterials[hans]);
+	}
+
+	// now we need to iterate through all meshes,
+	// generating correct texture coordinates and material uv indices
+	for (unsigned int curie = 0; curie < pcScene->mNumMeshes;++curie)
+	{
+		aiMesh* pcMesh = pcScene->mMeshes[curie];
+
+		// apply texture coordinate transformations
+		TextureTransform::BakeScaleNOffset(pcMesh,pcIntMaterials[pcMesh->mMaterialIndex]);
+	}
+	for (unsigned int hans = 0; hans < pcScene->mNumMaterials;++hans)
+	{
+		// setup the correct UV indices for each material
+		TextureTransform::SetupMatUVSrc(pcScene->mMaterials[hans],
+			pcIntMaterials[hans]);
+	}
+	delete[] pcIntMaterials;
+
 	// finished!
 	// finished!
 	return;
 	return;
 }
 }

+ 7 - 0
code/ASELoader.h

@@ -149,6 +149,13 @@ protected:
 	void AddNodes(aiScene* pcScene,aiNode* pcParent,
 	void AddNodes(aiScene* pcScene,aiNode* pcParent,
 		const char* szName);
 		const char* szName);
 
 
+	// -------------------------------------------------------------------
+	/** Generate a default material and add it to the parser's list
+	 *  Called if no material has been found in the file (rare for ASE,
+	 *  but not impossible)
+	 */
+	void GenerateDefaultMaterial();
+
 protected:
 protected:
 
 
 	/** Parser instance */
 	/** Parser instance */

+ 45 - 14
code/ASEParser.cpp

@@ -1544,20 +1544,30 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV4MeshFace(ASE::Face& out)
 void Parser::ParseLV4MeshFace(ASE::Face& out)
-{
+{	
 	// skip spaces and tabs
 	// skip spaces and tabs
 	if(!SkipSpaces(this->m_szFile,&this->m_szFile))
 	if(!SkipSpaces(this->m_szFile,&this->m_szFile))
-		BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL [#1]")
+	{
+		this->LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL [#1]");
+		this->SkipToNextToken();
+		return;
+	}
 
 
 	// parse the face index
 	// parse the face index
 	out.iFace = strtol10(this->m_szFile,&this->m_szFile);
 	out.iFace = strtol10(this->m_szFile,&this->m_szFile);
 
 
 	// next character should be ':'
 	// next character should be ':'
-	if(!SkipSpaces(this->m_szFile,&this->m_szFile) || ':' != *this->m_szFile)
-		BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]")
+	if(!SkipSpaces(this->m_szFile,&this->m_szFile))
+	{
+		// FIX: there are some ASE files which haven't got : here ....
+		this->LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]");
+		this->SkipToNextToken();
+		return;
+	}
+	// FIX: there are some ASE files which haven't got : here ....
+	if(':' == *this->m_szFile)++this->m_szFile;
 
 
 	// parse all mesh indices
 	// parse all mesh indices
-	++this->m_szFile;
 	for (unsigned int i = 0; i < 3;++i)
 	for (unsigned int i = 0; i < 3;++i)
 	{
 	{
 		unsigned int iIndex = 0;
 		unsigned int iIndex = 0;
@@ -1565,7 +1575,10 @@ void Parser::ParseLV4MeshFace(ASE::Face& out)
 		{
 		{
 			// LOG 
 			// LOG 
 __EARTHQUAKE_XXL:
 __EARTHQUAKE_XXL:
-			BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL. A,B or C expected [#3]")
+			this->LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. "
+				"A,B or C expected [#3]");
+			this->SkipToNextToken();
+			return;
 		}
 		}
 		switch (*this->m_szFile)
 		switch (*this->m_szFile)
 		{
 		{
@@ -1586,13 +1599,21 @@ __EARTHQUAKE_XXL:
 
 
 		// next character should be ':'
 		// next character should be ':'
 		if(!SkipSpaces(this->m_szFile,&this->m_szFile) || ':' != *this->m_szFile)
 		if(!SkipSpaces(this->m_szFile,&this->m_szFile) || ':' != *this->m_szFile)
-			BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]")
+		{
+			this->LogWarning("Unable to parse *MESH_FACE Element: "
+				"Unexpected EOL. \':\' expected [#2]");
+			this->SkipToNextToken();
+			return;
+		}
 
 
 		++this->m_szFile;
 		++this->m_szFile;
-
 		if(!SkipSpaces(this->m_szFile,&this->m_szFile))
 		if(!SkipSpaces(this->m_szFile,&this->m_szFile))
-			BLUBB("Unable to parse *MESH_FACE Element: Unexpected EOL. Vertex index ecpected [#4]")
-
+		{
+			this->LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. "
+				"Vertex index ecpected [#4]");
+			this->SkipToNextToken();
+			return;
+		}
 		out.mIndices[iIndex] = strtol10(this->m_szFile,&this->m_szFile);
 		out.mIndices[iIndex] = strtol10(this->m_szFile,&this->m_szFile);
 	}
 	}
 
 
@@ -1609,11 +1630,17 @@ __EARTHQUAKE_XXL:
 	}
 	}
 
 
 	// parse the smoothing group of the face
 	// parse the smoothing group of the face
-	if (0 == strncmp(this->m_szFile,"*MESH_SMOOTHING",15) && IsSpaceOrNewLine(*(this->m_szFile+15)))
+	if (0 == strncmp(this->m_szFile,"*MESH_SMOOTHING",15) && 
+		IsSpaceOrNewLine(*(this->m_szFile+15)))
 	{
 	{
 		this->m_szFile+=16;
 		this->m_szFile+=16;
 		if(!SkipSpaces(this->m_szFile,&this->m_szFile))
 		if(!SkipSpaces(this->m_szFile,&this->m_szFile))
-			BLUBB("Unable to parse *MESH_SMOOTHING Element: Unexpected EOL. Smoothing group(s) expected [#5]")
+		{
+			this->LogWarning("Unable to parse *MESH_SMOOTHING Element: "
+				"Unexpected EOL. Smoothing group(s) expected [#5]");
+			this->SkipToNextToken();
+			return;
+		}
 		
 		
 		// parse smoothing groups until we don_t anymore see commas
 		// parse smoothing groups until we don_t anymore see commas
 		// FIX: There needn't always be a value, sad but true
 		// FIX: There needn't always be a value, sad but true
@@ -1649,10 +1676,14 @@ __EARTHQUAKE_XXL:
 	{
 	{
 		this->m_szFile+=12;
 		this->m_szFile+=12;
 		if(!SkipSpaces(this->m_szFile,&this->m_szFile))
 		if(!SkipSpaces(this->m_szFile,&this->m_szFile))
-			BLUBB("Unable to parse *MESH_MTLID Element: Unexpected EOL. Material index expected [#6]")
+		{
+			this->LogWarning("Unable to parse *MESH_MTLID Element: Unexpected EOL. "
+				"Material index expected [#6]");
+			this->SkipToNextToken();
+			return;
+		}
 		out.iMaterial = strtol10(this->m_szFile,&this->m_szFile);
 		out.iMaterial = strtol10(this->m_szFile,&this->m_szFile);
 	}
 	}
-	//this->SkipToNextToken();
 	return;
 	return;
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 1 - 1
code/MDLFileData.h

@@ -548,7 +548,7 @@ struct Vertex_MDL4
 struct Vertex_MDL7
 struct Vertex_MDL7
 {
 {
 	float	x,y,z;
 	float	x,y,z;
-	uint16_t vertindex;	
+	uint16_t vertindex;	// = bone index
 	union {
 	union {
 		uint16_t norm162index;
 		uint16_t norm162index;
 		float norm[3];
 		float norm[3];

+ 90 - 2
code/MDLLoader.cpp

@@ -1282,6 +1282,72 @@ void MDLImporter::ValidateHeader_GameStudioA7(const MDL::Header_MDL7* pcHeader)
 	return;
 	return;
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
+void MDLImporter::CalculateAbsBoneAnimMatrices(const MDL::Bone_MDL7* pcBones,
+	aiBone** apcOutBones)
+{
+	ai_assert(NULL != pcBones);
+	ai_assert(NULL != apcOutBones);
+
+	const MDL::Header_MDL7* pcHeader = (const MDL::Header_MDL7*)this->m_pcHeader;
+
+	// first find the bone that has NO parent, calculate the
+	// animation matrix for it, then go on and search for the next parent
+	// index (0) and so on until we can't find a new node.
+
+	std::vector<bool> abHadMe;
+	abHadMe.resize(pcHeader->bones_num,false);
+
+	uint16_t iParent = 0xffff;
+	int32_t iIterations = 0;
+	while (iIterations++ < pcHeader->bones_num)
+	{
+		for (int32_t iBone = 0; iBone < pcHeader->bones_num;++iBone)
+		{
+			if (abHadMe[iBone])continue;
+			const MDL::Bone_MDL7* pcBone = &pcBones[iBone];
+			abHadMe[iBone] = true;
+	
+			if (iParent == pcBone->parent_index)
+			{
+				// yeah, calculate my matrix! I'm happy now
+
+				/************************************************************
+				The animation matrix is then calculated the following way:
+
+				vector3 bPos = <absolute bone position>
+				matrix44 laM;   // local animation matrix
+				sphrvector key_rotate = <bone rotation>
+		
+				matrix44 m1,m2;
+				create_trans_matrix(m1, -bPos.x, -bPos.y, -bPos.z);
+				create_trans_matrix(m2, -bPos.x, -bPos.y, -bPos.z);
+
+				create_rotation_matrix(laM,key_rotate);
+
+				laM = sm1 * laM;
+				laM = laM * sm2;
+			    *************************************************************/
+				aiVector3D vAbsPos;
+				if (0xffff != iParent)
+				{
+					const aiBone* pcParentBone = apcOutBones[iParent];
+					vAbsPos.x = pcParentBone->mOffsetMatrix.a3;
+					vAbsPos.y = pcParentBone->mOffsetMatrix.b3;
+					vAbsPos.z = pcParentBone->mOffsetMatrix.c3;
+				}
+				vAbsPos.x -= pcBone->x; // TODO: + or -?
+				vAbsPos.y -= pcBone->y;
+				vAbsPos.z -= pcBone->z;
+				aiBone* pcOutBone = apcOutBones[iBone];
+				pcOutBone->mOffsetMatrix.a3 = vAbsPos.x;
+				pcOutBone->mOffsetMatrix.b3 = vAbsPos.y;
+				pcOutBone->mOffsetMatrix.c3 = vAbsPos.z;
+			}
+		}
+		++iParent;
+	}
+}
+// ------------------------------------------------------------------------------------------------
 void MDLImporter::InternReadFile_GameStudioA7( )
 void MDLImporter::InternReadFile_GameStudioA7( )
 {
 {
 	ai_assert(NULL != pScene);
 	ai_assert(NULL != pScene);
@@ -1294,8 +1360,30 @@ void MDLImporter::InternReadFile_GameStudioA7( )
 	// sizes that are expected by the loader to be constant 
 	// sizes that are expected by the loader to be constant 
 	this->ValidateHeader_GameStudioA7(pcHeader);
 	this->ValidateHeader_GameStudioA7(pcHeader);
 
 
-	// skip all bones
-	szCurrent += sizeof(MDL::Bone_MDL7) * pcHeader->bones_num;
+	// load all bones (they are shared by all groups, so
+	// we'll need to add them to all groups later)
+	const MDL::Bone_MDL7* pcBones = (const MDL::Bone_MDL7*)szCurrent;
+	szCurrent += pcHeader->bones_num * pcHeader->bone_stc_size;
+
+	aiBone** apcBonesOut = NULL;
+	unsigned int iNumBonesOut = 0;
+	if (pcHeader->bone_stc_size != sizeof(MDL::Bone_MDL7))
+	{
+		DefaultLogger::get()->warn("[3DGS MDL7] Unknown size of bone data structure. "
+			"Ignoring bones ...");
+	}
+	else
+	{
+		// create an output bone array
+		iNumBonesOut = pcHeader->bones_num;
+		apcBonesOut = new aiBone*[iNumBonesOut];
+		for (unsigned int crank = 0; crank < iNumBonesOut;++crank)
+			apcBonesOut[crank] = new aiBone();
+
+		// and calculate absolute bone animation matrices
+		// aiBone.mTransformation member
+		this->CalculateAbsBoneAnimMatrices(pcBones,apcBonesOut);
+	}
 
 
 	// allocate a material list
 	// allocate a material list
 	std::vector<MaterialHelper*> pcMats;
 	std::vector<MaterialHelper*> pcMats;

+ 8 - 0
code/MDLLoader.h

@@ -211,6 +211,14 @@ protected:
 		const std::vector<aiVector3D>& vTextureCoords2);
 		const std::vector<aiVector3D>& vTextureCoords2);
 
 
 
 
+	// -------------------------------------------------------------------
+	/** Calculate absolute bone animation matrices for each bone
+	 * \param pcBones Pointer to the bone section in the file
+	 * \param apcOutBones Output bones array
+	 */
+	void CalculateAbsBoneAnimMatrices(const MDL::Bone_MDL7* pcBones,
+		aiBone** apcOutBones);
+
 	// -------------------------------------------------------------------
 	// -------------------------------------------------------------------
 	/** Try to load a  palette from the current directory (colormap.lmp)
 	/** Try to load a  palette from the current directory (colormap.lmp)
 	 *  If it is not found the default palette of Quake1 is returned
 	 *  If it is not found the default palette of Quake1 is returned

+ 66 - 25
code/MaterialSystem.cpp

@@ -369,7 +369,8 @@ aiReturn aiGetMaterialTexture(const aiMaterial* pcMat,
 	aiString* szOut,
 	aiString* szOut,
 	unsigned int* piUVIndex,
 	unsigned int* piUVIndex,
 	float* pfBlendFactor,
 	float* pfBlendFactor,
-	aiTextureOp* peTextureOp)
+	aiTextureOp* peTextureOp,
+	aiTextureMapMode* peMapMode)
 {
 {
 	ai_assert(NULL != pcMat);
 	ai_assert(NULL != pcMat);
 	ai_assert(NULL != szOut);
 	ai_assert(NULL != szOut);
@@ -378,55 +379,80 @@ aiReturn aiGetMaterialTexture(const aiMaterial* pcMat,
 	const char* szUVBase;
 	const char* szUVBase;
 	const char* szBlendBase;
 	const char* szBlendBase;
 	const char* szOpBase;
 	const char* szOpBase;
+	const char* aszMapModeBase[3];
 	switch (iTexType)
 	switch (iTexType)
 	{
 	{
 	case AI_TEXTYPE_DIFFUSE:
 	case AI_TEXTYPE_DIFFUSE:
-		szPathBase = AI_MATKEY_TEXTURE_DIFFUSE_;
-		szUVBase = AI_MATKEY_UVWSRC_DIFFUSE_;
+		szPathBase	= AI_MATKEY_TEXTURE_DIFFUSE_;
+		szUVBase	= AI_MATKEY_UVWSRC_DIFFUSE_;
 		szBlendBase = AI_MATKEY_TEXBLEND_DIFFUSE_;
 		szBlendBase = AI_MATKEY_TEXBLEND_DIFFUSE_;
-		szOpBase = AI_MATKEY_TEXOP_DIFFUSE_;
+		szOpBase	= AI_MATKEY_TEXOP_DIFFUSE_;
+		aszMapModeBase[0] = AI_MATKEY_MAPPINGMODE_U_DIFFUSE_;
+		aszMapModeBase[1] = AI_MATKEY_MAPPINGMODE_V_DIFFUSE_;
+		aszMapModeBase[2] = AI_MATKEY_MAPPINGMODE_W_DIFFUSE_;
 		break;
 		break;
 	case AI_TEXTYPE_SPECULAR:
 	case AI_TEXTYPE_SPECULAR:
-		szPathBase = AI_MATKEY_TEXTURE_SPECULAR_;
-		szUVBase = AI_MATKEY_UVWSRC_SPECULAR_;
+		szPathBase	= AI_MATKEY_TEXTURE_SPECULAR_;
+		szUVBase	= AI_MATKEY_UVWSRC_SPECULAR_;
 		szBlendBase = AI_MATKEY_TEXBLEND_SPECULAR_;
 		szBlendBase = AI_MATKEY_TEXBLEND_SPECULAR_;
-		szOpBase = AI_MATKEY_TEXOP_SPECULAR_;
+		szOpBase	= AI_MATKEY_TEXOP_SPECULAR_;
+		aszMapModeBase[0] = AI_MATKEY_MAPPINGMODE_U_SPECULAR_;
+		aszMapModeBase[1] = AI_MATKEY_MAPPINGMODE_V_SPECULAR_;
+		aszMapModeBase[2] = AI_MATKEY_MAPPINGMODE_W_SPECULAR_;
 		break;
 		break;
 	case AI_TEXTYPE_AMBIENT:
 	case AI_TEXTYPE_AMBIENT:
-		szPathBase = AI_MATKEY_TEXTURE_AMBIENT_;
-		szUVBase = AI_MATKEY_UVWSRC_AMBIENT_;
+		szPathBase	= AI_MATKEY_TEXTURE_AMBIENT_;
+		szUVBase	= AI_MATKEY_UVWSRC_AMBIENT_;
 		szBlendBase = AI_MATKEY_TEXBLEND_AMBIENT_;
 		szBlendBase = AI_MATKEY_TEXBLEND_AMBIENT_;
-		szOpBase = AI_MATKEY_TEXOP_AMBIENT_;
+		szOpBase	= AI_MATKEY_TEXOP_AMBIENT_;
+		aszMapModeBase[0] = AI_MATKEY_MAPPINGMODE_U_AMBIENT_;
+		aszMapModeBase[1] = AI_MATKEY_MAPPINGMODE_V_AMBIENT_;
+		aszMapModeBase[2] = AI_MATKEY_MAPPINGMODE_W_AMBIENT_;
 		break;
 		break;
 	case AI_TEXTYPE_EMISSIVE:
 	case AI_TEXTYPE_EMISSIVE:
-		szPathBase = AI_MATKEY_TEXTURE_EMISSIVE_;
-		szUVBase = AI_MATKEY_UVWSRC_EMISSIVE_;
+		szPathBase	= AI_MATKEY_TEXTURE_EMISSIVE_;
+		szUVBase	= AI_MATKEY_UVWSRC_EMISSIVE_;
 		szBlendBase = AI_MATKEY_TEXBLEND_EMISSIVE_;
 		szBlendBase = AI_MATKEY_TEXBLEND_EMISSIVE_;
-		szOpBase = AI_MATKEY_TEXOP_EMISSIVE_;
+		szOpBase	= AI_MATKEY_TEXOP_EMISSIVE_;
+		aszMapModeBase[0] = AI_MATKEY_MAPPINGMODE_U_EMISSIVE_;
+		aszMapModeBase[1] = AI_MATKEY_MAPPINGMODE_V_EMISSIVE_;
+		aszMapModeBase[2] = AI_MATKEY_MAPPINGMODE_W_EMISSIVE_;
 		break;
 		break;
 	case AI_TEXTYPE_HEIGHT:
 	case AI_TEXTYPE_HEIGHT:
-		szPathBase = AI_MATKEY_TEXTURE_HEIGHT_;
-		szUVBase = AI_MATKEY_UVWSRC_HEIGHT_;
+		szPathBase	= AI_MATKEY_TEXTURE_HEIGHT_;
+		szUVBase	= AI_MATKEY_UVWSRC_HEIGHT_;
 		szBlendBase = AI_MATKEY_TEXBLEND_HEIGHT_;
 		szBlendBase = AI_MATKEY_TEXBLEND_HEIGHT_;
-		szOpBase = AI_MATKEY_TEXOP_HEIGHT_;
+		szOpBase	= AI_MATKEY_TEXOP_HEIGHT_;
+		aszMapModeBase[0] = AI_MATKEY_MAPPINGMODE_U_HEIGHT_;
+		aszMapModeBase[1] = AI_MATKEY_MAPPINGMODE_V_HEIGHT_;
+		aszMapModeBase[2] = AI_MATKEY_MAPPINGMODE_W_HEIGHT_;
 		break;
 		break;
 	case AI_TEXTYPE_NORMALS:
 	case AI_TEXTYPE_NORMALS:
-		szPathBase = AI_MATKEY_TEXTURE_NORMALS_;
-		szUVBase = AI_MATKEY_UVWSRC_NORMALS_;
+		szPathBase	= AI_MATKEY_TEXTURE_NORMALS_;
+		szUVBase	= AI_MATKEY_UVWSRC_NORMALS_;
 		szBlendBase = AI_MATKEY_TEXBLEND_NORMALS_;
 		szBlendBase = AI_MATKEY_TEXBLEND_NORMALS_;
-		szOpBase = AI_MATKEY_TEXOP_NORMALS_;
+		szOpBase	= AI_MATKEY_TEXOP_NORMALS_;
+		aszMapModeBase[0] = AI_MATKEY_MAPPINGMODE_U_NORMALS_;
+		aszMapModeBase[1] = AI_MATKEY_MAPPINGMODE_V_NORMALS_;
+		aszMapModeBase[2] = AI_MATKEY_MAPPINGMODE_W_NORMALS_;
 		break;
 		break;
 	case AI_TEXTYPE_SHININESS:
 	case AI_TEXTYPE_SHININESS:
-		szPathBase = AI_MATKEY_TEXTURE_SHININESS_;
-		szUVBase = AI_MATKEY_UVWSRC_SHININESS_;
+		szPathBase	= AI_MATKEY_TEXTURE_SHININESS_;
+		szUVBase	= AI_MATKEY_UVWSRC_SHININESS_;
 		szBlendBase = AI_MATKEY_TEXBLEND_SHININESS_;
 		szBlendBase = AI_MATKEY_TEXBLEND_SHININESS_;
-		szOpBase = AI_MATKEY_TEXOP_SHININESS_;
+		szOpBase	= AI_MATKEY_TEXOP_SHININESS_;
+		aszMapModeBase[0] = AI_MATKEY_MAPPINGMODE_U_SHININESS_;
+		aszMapModeBase[1] = AI_MATKEY_MAPPINGMODE_V_SHININESS_;
+		aszMapModeBase[2] = AI_MATKEY_MAPPINGMODE_W_SHININESS_;
 		break;
 		break;
 	case AI_TEXTYPE_OPACITY:
 	case AI_TEXTYPE_OPACITY:
-		szPathBase = AI_MATKEY_TEXTURE_OPACITY_;
-		szUVBase = AI_MATKEY_UVWSRC_OPACITY_;
+		szPathBase	= AI_MATKEY_TEXTURE_OPACITY_;
+		szUVBase	= AI_MATKEY_UVWSRC_OPACITY_;
 		szBlendBase = AI_MATKEY_TEXBLEND_OPACITY_;
 		szBlendBase = AI_MATKEY_TEXBLEND_OPACITY_;
-		szOpBase = AI_MATKEY_TEXOP_OPACITY_;
+		szOpBase	= AI_MATKEY_TEXOP_OPACITY_;
+		aszMapModeBase[0] = AI_MATKEY_MAPPINGMODE_U_OPACITY_;
+		aszMapModeBase[1] = AI_MATKEY_MAPPINGMODE_V_OPACITY_;
+		aszMapModeBase[2] = AI_MATKEY_MAPPINGMODE_W_OPACITY_;
 		break;
 		break;
 	default: return AI_FAILURE;
 	default: return AI_FAILURE;
 	};
 	};
@@ -470,6 +496,21 @@ aiReturn aiGetMaterialTexture(const aiMaterial* pcMat,
 
 
 		*peTextureOp = op;
 		*peTextureOp = op;
 	}
 	}
+
+	// get the texture mapping modes for the texture
+	if (peMapMode)
+	{
+		aiTextureMapMode eMode;
+		for (unsigned int q = 0; q < 3;++q)
+		{
+			sprintf(szKey,"%s[%i]",aszMapModeBase[q],iIndex);
+			if (AI_SUCCESS != aiGetMaterialInteger(pcMat,szKey,(int*)&eMode))
+			{
+				eMode = aiTextureMapMode_Wrap;
+			}
+			peMapMode[q] = eMode;
+		}
+	}
 	return AI_SUCCESS;
 	return AI_SUCCESS;
 }
 }
 
 

+ 214 - 89
code/TextureTransform.cpp

@@ -55,28 +55,90 @@ namespace Assimp
 void TextureTransform::PreProcessUVTransform(
 void TextureTransform::PreProcessUVTransform(
 	Dot3DS::Texture& rcIn)
 	Dot3DS::Texture& rcIn)
 {
 {
-	if (rcIn.mOffsetU && 0.0f == fmodf(rcIn.mOffsetU, 1.0f ))
+	std::string s;
+	std::stringstream ss;
+	int iField;
+
+	if (rcIn.mOffsetU)
 	{
 	{
-		DefaultLogger::get()->warn("Texture coordinate offset in the x direction "
-			"is a multiple of 1. This is redundant ...");
-		rcIn.mOffsetU = 1.0f;
+		if (iField = (int)rcIn.mOffsetU)
+		{
+			if (aiTextureMapMode_Wrap == rcIn.mMapMode)
+			{
+				float fNew = rcIn.mOffsetU-(float)iField;
+				ss << "[wrap] Found texture coordinate U offset " << rcIn.mOffsetU << ". "
+					"This can be optimized to " << fNew;
+				ss >> s;
+				DefaultLogger::get()->info(s);
+				rcIn.mOffsetU = fNew;
+			}
+			else if (aiTextureMapMode_Mirror == rcIn.mMapMode)
+			{
+				if (0 != (iField % 2))iField--;
+				float fNew = rcIn.mOffsetU-(float)iField;
+
+				ss << "[mirror] Found texture coordinate U offset " << rcIn.mOffsetU << ". "
+					"This can be optimized to " << fNew;
+				ss >> s;
+				DefaultLogger::get()->info(s);
+				rcIn.mOffsetU = fNew;
+			}
+			else if (aiTextureMapMode_Clamp == rcIn.mMapMode)
+			{
+				ss << "[clamp] Found texture coordinate U offset " << rcIn.mOffsetU << ". "
+					"This can be clamped to 1.0f";
+				ss >> s;
+				DefaultLogger::get()->info(s);
+				rcIn.mOffsetU = 1.0f;
+			}
+		}
 	}
 	}
-	if (rcIn.mOffsetV && 0.0f == fmodf(rcIn.mOffsetV, 1.0f ))
+	if (rcIn.mOffsetV)
 	{
 	{
-		DefaultLogger::get()->warn("Texture coordinate offset in the y direction "
-				"is a multiple of 1. This is redundant ...");
-		rcIn.mOffsetV = 1.0f;
+		if (iField = (int)rcIn.mOffsetV)
+		{
+			if (aiTextureMapMode_Wrap == rcIn.mMapMode)
+			{
+				float fNew = rcIn.mOffsetV-(float)iField;
+				ss << "[wrap] Found texture coordinate V offset " << rcIn.mOffsetV << ". "
+					"This can be optimized to " << fNew;
+				ss >> s;
+				DefaultLogger::get()->info(s);
+				rcIn.mOffsetV = fNew;
+			}
+			else if (aiTextureMapMode_Mirror == rcIn.mMapMode)
+			{
+				if (0 != (iField % 2))iField--;
+				float fNew = rcIn.mOffsetV-(float)iField;
+
+				ss << "[mirror] Found texture coordinate V offset " << rcIn.mOffsetV << ". "
+					"This can be optimized to " << fNew;
+				ss >> s;
+				DefaultLogger::get()->info(s);
+				rcIn.mOffsetV = fNew;
+			}
+			else if (aiTextureMapMode_Clamp == rcIn.mMapMode)
+			{
+				ss << "[clamp] Found texture coordinate V offset " << rcIn.mOffsetV << ". "
+					"This can be clamped to 1.0f";
+				ss >> s;
+				DefaultLogger::get()->info(s);
+				rcIn.mOffsetV = 1.0f;
+			}
+		}
 	}
 	}
 	if (rcIn.mRotation)
 	if (rcIn.mRotation)
 	{
 	{
-		const float f =  fmodf(rcIn.mRotation,2.0f * 3.141592653f );
-		if (f <= 0.05f && f >= -0.05f)
+		if (iField = (int)(rcIn.mRotation / 3.141592654f))
 		{
 		{
-			DefaultLogger::get()->warn("Texture coordinate rotation is a multiple "
-				"of 2 * PI. This is redundant");
-			rcIn.mRotation = 0.0f;
+			float fNew = rcIn.mRotation-(float)iField*3.141592654f;
+			ss << "[wrap] Found texture coordinate rotation " << rcIn.mRotation << ". "
+				"This can be optimized to " << fNew;
+			DefaultLogger::get()->info(s);
+			rcIn.mRotation = fNew;
 		}
 		}
 	}
 	}
+	return;
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void TextureTransform::AddToList(std::vector<STransformVecInfo>& rasVec,
 void TextureTransform::AddToList(std::vector<STransformVecInfo>& rasVec,
@@ -94,7 +156,8 @@ void TextureTransform::AddToList(std::vector<STransformVecInfo>& rasVec,
 			(*i).fOffsetV == pcTex->mOffsetV && 
 			(*i).fOffsetV == pcTex->mOffsetV && 
 			(*i).fScaleU  == pcTex->mScaleU  &&
 			(*i).fScaleU  == pcTex->mScaleU  &&
 			(*i).fScaleV  == pcTex->mScaleV  &&
 			(*i).fScaleV  == pcTex->mScaleV  &&
-			(*i).fRotation == pcTex->mRotation)
+			(*i).fRotation == pcTex->mRotation &&
+			(*i).iUVIndex == pcTex->iUVSrc)
 		{
 		{
 			(*i).pcTextures.push_back(pcTex);
 			(*i).pcTextures.push_back(pcTex);
 			return;
 			return;
@@ -107,8 +170,12 @@ void TextureTransform::AddToList(std::vector<STransformVecInfo>& rasVec,
 	sInfo.fOffsetU = pcTex->mOffsetU;
 	sInfo.fOffsetU = pcTex->mOffsetU;
 	sInfo.fOffsetV = pcTex->mOffsetV;
 	sInfo.fOffsetV = pcTex->mOffsetV;
 	sInfo.fRotation = pcTex->mRotation;
 	sInfo.fRotation = pcTex->mRotation;
+	sInfo.iUVIndex = pcTex->iUVSrc;
+
+	// add the texture to the list
 	sInfo.pcTextures.push_back(pcTex);
 	sInfo.pcTextures.push_back(pcTex);
 
 
+	// and add the transformation itself to the second list
 	rasVec.push_back(sInfo);
 	rasVec.push_back(sInfo);
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -116,6 +183,7 @@ void TextureTransform::ApplyScaleNOffset(Dot3DS::Material& material)
 {
 {
 	unsigned int iCnt = 0;
 	unsigned int iCnt = 0;
 	Dot3DS::Texture* pcTexture = NULL;
 	Dot3DS::Texture* pcTexture = NULL;
+
 	// diffuse texture
 	// diffuse texture
 	if (material.sTexDiffuse.mMapName.length())
 	if (material.sTexDiffuse.mMapName.length())
 	{
 	{
@@ -200,7 +268,7 @@ void TextureTransform::ApplyScaleNOffset(Dot3DS::Material& material)
 		// coordinate sets of all meshes referencing *this* material
 		// coordinate sets of all meshes referencing *this* material
 		// However, we can't do it  now. We need to wait until
 		// However, we can't do it  now. We need to wait until
 		// everything is sorted by materials.
 		// everything is sorted by materials.
-		if (1 == iCnt)
+		if (1 == iCnt && 0 == pcTexture->iUVSrc)
 		{
 		{
 			material.iBakeUVTransform = 1;
 			material.iBakeUVTransform = 1;
 			material.pcSingleTexture = pcTexture;
 			material.pcSingleTexture = pcTexture;
@@ -213,7 +281,7 @@ void TextureTransform::ApplyScaleNOffset(Dot3DS::Material& material)
 	}
 	}
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void TextureTransform::ApplyScaleNOffset(std::vector<Dot3DS::Material> materials)
+void TextureTransform::ApplyScaleNOffset(std::vector<Dot3DS::Material>& materials)
 {
 {
 	unsigned int iNum = 0;
 	unsigned int iNum = 0;
 	for (std::vector<Dot3DS::Material>::iterator
 	for (std::vector<Dot3DS::Material>::iterator
@@ -234,15 +302,19 @@ void TextureTransform::BakeScaleNOffset(
 	if (!pcMesh->mTextureCoords[0])return;
 	if (!pcMesh->mTextureCoords[0])return;
 	if (1 == pcSrc->iBakeUVTransform)
 	if (1 == pcSrc->iBakeUVTransform)
 	{
 	{
-		std::string s;
-		std::stringstream ss(s);
-		ss << "Transforming existing UV channel. Source UV: " << 0 
-			<< " OffsetU: " << pcSrc->pcSingleTexture->mOffsetU
-			<< " OffsetV: " << pcSrc->pcSingleTexture->mOffsetV
-			<< " ScaleU: " << pcSrc->pcSingleTexture->mScaleU
-			<< " ScaleV: " << pcSrc->pcSingleTexture->mScaleV
-			<< " Rotation (rad): " << pcSrc->pcSingleTexture->mRotation;
-		DefaultLogger::get()->info(s);
+		char szTemp[512];
+		sprintf(szTemp,"Transforming existing UV channel. Source UV: %i" 
+			" OffsetU: %f" 
+			" OffsetV: %f" 
+			" ScaleU: %f" 
+			" ScaleV: %f" 
+			" Rotation (rad): %f",0,
+			pcSrc->pcSingleTexture->mOffsetU,
+			pcSrc->pcSingleTexture->mOffsetV,
+			pcSrc->pcSingleTexture->mScaleU,
+			pcSrc->pcSingleTexture->mScaleV,
+			pcSrc->pcSingleTexture->mRotation);
+		DefaultLogger::get()->info(std::string(szTemp));
 
 
 		if (!pcSrc->pcSingleTexture->mRotation)
 		if (!pcSrc->pcSingleTexture->mRotation)
 		{
 		{
@@ -279,6 +351,19 @@ void TextureTransform::BakeScaleNOffset(
 	}
 	}
 	else if (2 == pcSrc->iBakeUVTransform)
 	else if (2 == pcSrc->iBakeUVTransform)
 	{
 	{
+		// first save all texture coordinate sets
+		aiVector3D* apvOriginalSets[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+		for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
+		{
+			apvOriginalSets[i] = pcMesh->mTextureCoords[i];
+		}
+		unsigned int iNextEmpty = 0;
+		while (pcMesh->mTextureCoords[++iNextEmpty]);
+
+		aiVector3D* apvOutputSets[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+		for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
+			apvOutputSets[i] = NULL;
+
 		// now we need to find all textures in the material
 		// now we need to find all textures in the material
 		// which require scaling/offset operations
 		// which require scaling/offset operations
 		std::vector<STransformVecInfo> sOps;
 		std::vector<STransformVecInfo> sOps;
@@ -290,108 +375,148 @@ void TextureTransform::BakeScaleNOffset(
 		AddToList(sOps,&pcSrc->sTexShininess);
 		AddToList(sOps,&pcSrc->sTexShininess);
 		AddToList(sOps,&pcSrc->sTexAmbient);
 		AddToList(sOps,&pcSrc->sTexAmbient);
 
 
-		const aiVector3D* _pvBase;
-		if (0.0f == sOps[0].fOffsetU && 0.0f == sOps[0].fOffsetV &&
-			1.0f == sOps[0].fScaleU  && 1.0f == sOps[0].fScaleV &&
-			0.0f == sOps[0].fRotation)
+		// check the list and find out how many we won't be able
+		// to generate.
+		std::vector<STransformVecInfo*> sFilteredOps;
+		unsigned int iNumUntransformed = 0;
+		sFilteredOps.reserve(sOps.size());
 		{
 		{
-			// we'll have an unmodified set, so we can use *this* one
-			_pvBase = pcMesh->mTextureCoords[0];
-		}
-		else
-		{
-			_pvBase = new aiVector3D[pcMesh->mNumVertices];
-			memcpy(const_cast<aiVector3D*>(_pvBase),pcMesh->mTextureCoords[0],
-				pcMesh->mNumVertices * sizeof(aiVector3D));
-		}
-
-		unsigned int iCnt = 0;
-		for (std::vector<STransformVecInfo>::iterator
-			i =  sOps.begin();
-			i != sOps.end();++i,++iCnt)
-		{
-			if (!pcMesh->mTextureCoords[iCnt])
+			std::vector<STransformVecInfo*> sWishList;
+			sWishList.reserve(sOps.size());
+			for (unsigned int iUV = 0; iUV < AI_MAX_NUMBER_OF_TEXTURECOORDS;++iUV)
 			{
 			{
-				pcMesh->mTextureCoords[iCnt] = new aiVector3D[pcMesh->mNumVertices];
+				for (std::vector<STransformVecInfo>::iterator
+					i =  sOps.begin();
+					i != sOps.end();++i)
+				{
+					if (iUV != (*i).iUVIndex)continue;
+					if ((*i).IsUntransformed())
+					{
+						sFilteredOps.push_back(&(*i));
+					}
+					else sWishList.push_back(&(*i));
+				}
 			}
 			}
+			// are we able to generate all?
+			const int iDiff = AI_MAX_NUMBER_OF_TEXTURECOORDS-(int)
+				(sWishList.size()+sFilteredOps.size());
 
 
-			// more than 4 UV texture channels are not available
-			if (iCnt >= AI_MAX_NUMBER_OF_TEXTURECOORDS)
+			iNumUntransformed  = (unsigned int)sFilteredOps.size();
+			if (0 >= iDiff)
 			{
 			{
-				for (std::vector<Dot3DS::Texture*>::iterator
-					a =  (*i).pcTextures.begin();
-					a != (*i).pcTextures.end();++a)
+				DefaultLogger::get()->warn("There are too many combinations of different "
+					"UV transformation operations to generate an own UV channel for each "
+					"(maximum is AI_MAX_NUMBER_OF_TEXTURECOORDS = 4 or 6). "
+					"An untransformed UV channel will be used for all remaining transformations");
+				
+				std::vector<STransformVecInfo*>::const_iterator nash =  sWishList.begin();
+				for (;nash != sWishList.end()-iDiff;++nash)
 				{
 				{
-					(*a)->iUVSrc = 0;
+					sFilteredOps.push_back(*nash);
 				}
 				}
-				DefaultLogger::get()->error("There are too many "
-					"combinations of different UV scaling/offset/rotation operations "
-					"to generate an UV channel for each (maximum is 4). Using the "
-					"first UV channel ...");
-				continue;
 			}
 			}
+			else
+			{
+				for (std::vector<STransformVecInfo*>::const_iterator
+					nash =  sWishList.begin();
+					nash != sWishList.end();++nash)sFilteredOps.push_back(*nash);
+			}
+		}
 
 
-			std::string s;
-			std::stringstream ss(s);
-			ss << "Generating additional UV channel. Source UV: " << 0 
-				<< " OffsetU: " << (*i).fOffsetU
-				<< " OffsetV: " << (*i).fOffsetV
-				<< " ScaleU: " << (*i).fScaleU
-				<< " ScaleV: " << (*i).fScaleV
-				<< " Rotation (rad): " << (*i).fRotation;
-			DefaultLogger::get()->info(s);
+		// now fill in all output IV indices
+		unsigned int iNum = 0;
+		for (std::vector<STransformVecInfo*>::iterator
+			bogart =  sFilteredOps.begin();
+			bogart != sFilteredOps.end();++bogart,++iNum)
+		{
+			(**bogart).iUVIndex = iNum;
+		}
 
 
-			const aiVector3D* pvBase = _pvBase;
+		iNum = 0;
+		for (; iNum < iNumUntransformed; ++iNum)
+			pcMesh->mTextureCoords[iNum] = apvOriginalSets[iNum];
+
+		// now generate the texture coordinate sets
+		for (std::vector<STransformVecInfo*>::iterator
+			i =  sFilteredOps.begin()+iNumUntransformed;
+			i != sFilteredOps.end();++i,++iNum)
+		{
+			const aiVector3D* _pvBase = apvOriginalSets[(**i).iUVIndex];
+			aiVector3D* _pvOut = new aiVector3D[pcMesh->mNumVertices];
+			pcMesh->mTextureCoords[iNum] = _pvOut;
+
+			char szTemp[512];
+			sprintf(szTemp,"Generating additional UV channel. Source UV: %i" 
+				" OffsetU: %f" 
+				" OffsetV: %f" 
+				" ScaleU: %f" 
+				" ScaleV: %f" 
+				" Rotation (rad): %f",0,
+				(**i).fOffsetU,
+				(**i).fOffsetV,
+				(**i).fScaleU,
+				(**i).fScaleV,
+				(**i).fRotation);
+			DefaultLogger::get()->info(std::string(szTemp));
 
 
-			if (0.0f == (*i).fRotation)
+			const aiVector3D* pvBase = _pvBase;
+			aiVector3D* pvOut = _pvOut;
+			if (0.0f == (**i).fRotation)
 			{
 			{
 				for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
 				for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
 				{
 				{
 					// scaling
 					// scaling
-					pcMesh->mTextureCoords[iCnt][n].x = pvBase->x * (*i).fScaleU;
-					pcMesh->mTextureCoords[iCnt][n].y = pvBase->y * (*i).fScaleV;
+					pvOut->x = pvBase->x * (**i).fScaleU;
+					pvOut->y = pvBase->y * (**i).fScaleV;
 
 
 					// offset
 					// offset
-					pcMesh->mTextureCoords[iCnt][n].x += (*i).fOffsetU;
-					pcMesh->mTextureCoords[iCnt][n].y += (*i).fOffsetV;
+					pvOut->x += (**i).fOffsetU;
+					pvOut->y += (**i).fOffsetV;
 
 
 					pvBase++;
 					pvBase++;
+					pvOut++;
 				}
 				}
 			}
 			}
 			else
 			else
 			{
 			{
-				const float fSin = sinf((*i).fRotation);
-				const float fCos = cosf((*i).fRotation);
+				const float fSin = sinf((**i).fRotation);
+				const float fCos = cosf((**i).fRotation);
 				for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
 				for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
 				{
 				{
 					// scaling
 					// scaling
-					pcMesh->mTextureCoords[iCnt][n].x = pvBase->x * (*i).fScaleU;
-					pcMesh->mTextureCoords[iCnt][n].y = pvBase->y * (*i).fScaleV;
+					pvOut->x = pvBase->x * (**i).fScaleU;
+					pvOut->y = pvBase->y * (**i).fScaleV;
 
 
 					// rotation
 					// rotation
-					pcMesh->mTextureCoords[iCnt][n].x *= fCos;
-					pcMesh->mTextureCoords[iCnt][n].y *= fSin;
+					pvOut->x *= fCos;
+					pvOut->y *= fSin;
 
 
 					// offset
 					// offset
-					pcMesh->mTextureCoords[iCnt][n].x += (*i).fOffsetU;
-					pcMesh->mTextureCoords[iCnt][n].y += (*i).fOffsetV;
+					pvOut->x += (**i).fOffsetU;
+					pvOut->y += (**i).fOffsetV;
 
 
 					pvBase++;
 					pvBase++;
+					pvOut++;
 				}
 				}
 			}
 			}
-			// setup the UV source index for each texture
-			for (std::vector<Dot3DS::Texture*>::iterator
-				a =  (*i).pcTextures.begin();
-				a != (*i).pcTextures.end();++a)
+		}
+
+		// now check which source texture coordinate sets
+		// can be deleted because they're not anymore required
+		for (iNum = 0; iNum < AI_MAX_NUMBER_OF_TEXTURECOORDS;++iNum)
+		{
+			for (unsigned int z = 0; z < iNumUntransformed;++z)
 			{
 			{
-				(*a)->iUVSrc = iCnt;
+				if (apvOriginalSets[iNum] == pcMesh->mTextureCoords[z])
+				{
+					apvOriginalSets[iNum] = NULL;
+					break;
+				}
 			}
 			}
+			if (apvOriginalSets[iNum])delete[] apvOriginalSets[iNum];
 		}
 		}
-
-		// release temporary storage
-		if (_pvBase != pcMesh->mTextureCoords[0])
-			delete[] _pvBase;
 	}
 	}
+	return;
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void TextureTransform::SetupMatUVSrc (aiMaterial* pcMat, const Dot3DS::Material* pcMatIn)
 void TextureTransform::SetupMatUVSrc (aiMaterial* pcMat, const Dot3DS::Material* pcMatIn)

+ 23 - 1
code/TextureTransform.h

@@ -61,6 +61,15 @@ using namespace Assimp::Dot3DS;
 */
 */
 struct STransformVecInfo 
 struct STransformVecInfo 
 {
 {
+	//! Construction. The resulting matrix is the identity
+	STransformVecInfo ()
+		: 
+		fScaleU(1.0f),fScaleV(1.0f),
+		fOffsetU(0.0f),fOffsetV(0.0f),
+		fRotation(0.0f),
+		iUVIndex(0)
+	{}
+
 	//! Texture coordinate scaling in the x-direction 
 	//! Texture coordinate scaling in the x-direction 
 	float fScaleU;
 	float fScaleU;
 	//! Texture coordinate scaling in the y-direction 
 	//! Texture coordinate scaling in the y-direction 
@@ -72,11 +81,24 @@ struct STransformVecInfo
 	//! Texture coordinate rotation, clockwise, in radians
 	//! Texture coordinate rotation, clockwise, in radians
 	float fRotation;
 	float fRotation;
 
 
+	//! Source texture coordinate index
+	unsigned int iUVIndex;
+
+
 	//! List of all textures that use this texture
 	//! List of all textures that use this texture
 	//! coordinate transformations
 	//! coordinate transformations
 	std::vector<Dot3DS::Texture*> pcTextures; 
 	std::vector<Dot3DS::Texture*> pcTextures; 
 
 
 
 
+	// -------------------------------------------------------------------
+	/** Returns whether this is an untransformed texture coordinate set
+	*/
+	inline bool IsUntransformed() const
+	{
+		return 1.0f == fScaleU && 1.0f == fScaleV &&
+			!fOffsetU && !fOffsetV && !fRotation;
+	}
+
 	// -------------------------------------------------------------------
 	// -------------------------------------------------------------------
 	/** Build a 3x3 matrix from the transformations
 	/** Build a 3x3 matrix from the transformations
 	*/
 	*/
@@ -153,7 +175,7 @@ public:
 	 *  for a material
 	 *  for a material
 	 * \param materials List of materials to be processed
 	 * \param materials List of materials to be processed
 	*/
 	*/
-	static void ApplyScaleNOffset(std::vector<Dot3DS::Material> materials);
+	static void ApplyScaleNOffset(std::vector<Dot3DS::Material>& materials);
 
 
 	// -------------------------------------------------------------------
 	// -------------------------------------------------------------------
 	/** Get a full list of all texture coordinate offsets required
 	/** Get a full list of all texture coordinate offsets required

+ 463 - 197
include/aiMaterial.h

@@ -59,21 +59,21 @@ extern "C" {
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 enum aiPropertyTypeInfo
 enum aiPropertyTypeInfo
 {
 {
-	/** Array of single-precision floats
-	*/
-	aiPTI_Float = 0x1,
+    /** Array of single-precision floats
+    */
+    aiPTI_Float = 0x1,
 
 
-	/** aiString data structure
-	*/
-	aiPTI_String = 0x3,
+    /** aiString data structure
+    */
+    aiPTI_String = 0x3,
 
 
-	/** Array of Integers
-	*/
-	aiPTI_Integer = 0x4,
+    /** Array of Integers
+    */
+    aiPTI_Integer = 0x4,
 
 
-	/** Simple binary buffer
-	*/
-	aiPTI_Buffer = 0x5,
+    /** Simple binary buffer
+    */
+    aiPTI_Buffer = 0x5,
 };
 };
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -83,29 +83,51 @@ enum aiPropertyTypeInfo
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 enum aiTextureOp
 enum aiTextureOp
 {
 {
-	/** T = T1 * T2
-	 */
-	aiTextureOp_Multiply = 0x0,
+    /** T = T1 * T2
+     */
+    aiTextureOp_Multiply = 0x0,
 
 
-	/** T = T1 + T2
-	 */
-	aiTextureOp_Add = 0x1,
+    /** T = T1 + T2
+     */
+    aiTextureOp_Add = 0x1,
 
 
-	/** T = T1 - T2
-	 */
-	aiTextureOp_Subtract = 0x2,
+    /** T = T1 - T2
+     */
+    aiTextureOp_Subtract = 0x2,
 
 
-	/** T = T1 / T2
-	 */
-	aiTextureOp_Divide = 0x3,
+    /** T = T1 / T2
+     */
+    aiTextureOp_Divide = 0x3,
 
 
-	/** T = (T1 + T2) - (T1 * T2)
-	 */
-	aiTextureOp_SmoothAdd = 0x4,
+    /** T = (T1 + T2) - (T1 * T2)
+     */
+    aiTextureOp_SmoothAdd = 0x4,
 
 
-	/** T = T1 + (T2-0.5)
-	 */
-	aiTextureOp_SignedAdd = 0x5
+    /** T = T1 + (T2-0.5)
+     */
+    aiTextureOp_SignedAdd = 0x5
+};
+
+// ---------------------------------------------------------------------------
+/** Defines texture mapping for use within the material system.
+*
+*/
+// ---------------------------------------------------------------------------
+enum aiTextureMapMode
+{
+    /** A texture coordinate u|v is translated to u%1|v%1 
+     */
+    aiTextureMapMode_Wrap = 0x0,
+
+    /** Texture coordinates outside the area formed by 1|1 and 0|0
+     *  are clamped to the nearest valid value on an axis
+     */
+    aiTextureMapMode_Clamp = 0x1,
+
+    /** A texture coordinate u|v becomes u%1|v%1 if (u-(u%1))%2 is zero and
+     *  1-(u%1)|1-(v%1) otherwise
+     */
+    aiTextureMapMode_Mirror = 0x2
 };
 };
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -120,59 +142,59 @@ enum aiTextureOp
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 enum aiShadingMode
 enum aiShadingMode
 {
 {
-	/** Flat shading. Shading is done on per-face base, 
-	*  diffuse only.
-	*/
-	aiShadingMode_Flat = 0x1,
-
-	/** Diffuse gouraud shading. Shading on per-vertex base
-	*/
-	aiShadingMode_Gouraud =	0x2,
-
-	/** Diffuse/Specular Phong-Shading
-	*
-	*  Shading is applied on per-pixel base. This is the
-	*  slowest algorithm, but generates the best results.
-	*/
-	aiShadingMode_Phong = 0x3,
-
-	/** Diffuse/Specular Phong-Blinn-Shading
-	*
-	*  Shading is applied on per-pixel base. This is a little
-	*  bit faster than phong and in some cases even
-	*  more realistic
-	*/
-	aiShadingMode_Blinn	= 0x4,
-
-	/** Toon-Shading per pixel
-	*
-	*  Shading is applied on per-pixel base. The output looks
-	*  like a comic. Often combined with edge detection.
-	*/
-	aiShadingMode_Toon = 0x5,
-
-	/** OrenNayar-Shading per pixel
-	*
-	*  Extension to standard lambertian shading, taking the
-	*  roughness of the material into account
-	*	
-	*/
-	aiShadingMode_OrenNayar = 0x6,
-
-	/** Minnaert-Shading per pixel
-	*
-	*  Extension to standard lambertian shading, taking the
-	*  "darkness" of the material into account
-	*/
-	aiShadingMode_Minnaert = 0x7,
-
-	/** CookTorrance-Shading per pixel
-	*/
-	aiShadingMode_CookTorrance = 0x8,
-
-	/** No shading at all
-	*/
-	aiShadingMode_NoShading = 0x8
+    /** Flat shading. Shading is done on per-face base, 
+    *  diffuse only.
+    */
+    aiShadingMode_Flat = 0x1,
+
+    /** Diffuse gouraud shading. Shading on per-vertex base
+    */
+    aiShadingMode_Gouraud =	0x2,
+
+    /** Diffuse/Specular Phong-Shading
+    *
+    *  Shading is applied on per-pixel base. This is the
+    *  slowest algorithm, but generates the best results.
+    */
+    aiShadingMode_Phong = 0x3,
+
+    /** Diffuse/Specular Phong-Blinn-Shading
+    *
+    *  Shading is applied on per-pixel base. This is a little
+    *  bit faster than phong and in some cases even
+    *  more realistic
+    */
+    aiShadingMode_Blinn	= 0x4,
+
+    /** Toon-Shading per pixel
+    *
+    *  Shading is applied on per-pixel base. The output looks
+    *  like a comic. Often combined with edge detection.
+    */
+    aiShadingMode_Toon = 0x5,
+
+    /** OrenNayar-Shading per pixel
+    *
+    *  Extension to standard lambertian shading, taking the
+    *  roughness of the material into account
+    *	
+    */
+    aiShadingMode_OrenNayar = 0x6,
+
+    /** Minnaert-Shading per pixel
+    *
+    *  Extension to standard lambertian shading, taking the
+    *  "darkness" of the material into account
+    */
+    aiShadingMode_Minnaert = 0x7,
+
+    /** CookTorrance-Shading per pixel
+    */
+    aiShadingMode_CookTorrance = 0x8,
+
+    /** No shading at all
+    */
+    aiShadingMode_NoShading = 0x8
 };
 };
 
 
 
 
@@ -184,31 +206,31 @@ enum aiShadingMode
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 struct aiMaterialProperty
 struct aiMaterialProperty
 {
 {
-	/** Specifies the name of the property (key)
-	*
-	*	Keys are case insensitive.
-	*/
-	C_STRUCT aiString* mKey;
-
-	/**	Size of the buffer mData is pointing to, in bytes
-	*/
-	unsigned int mDataLength;
-
-	/** Type information for the property.
-	*
-	*  Defines the data layout inside the
-	*  data buffer. This is used by the library
-	*  internally to perform debug checks.
-	*/
-	aiPropertyTypeInfo mType;
-
-	/**	Binary buffer to hold the property's value
-	*
-	*  The buffer has no terminal character. However,
-	*  if a string is stored inside it may use 0 as terminal,
-	*  but it would be contained in mDataLength.
-	*/
-	char* mData;
+    /** Specifies the name of the property (key)
+    *
+    *	Keys are case insensitive.
+    */
+    C_STRUCT aiString* mKey;
+
+    /**	Size of the buffer mData is pointing to, in bytes
+    */
+    unsigned int mDataLength;
+
+    /** Type information for the property.
+    *
+    *  Defines the data layout inside the
+    *  data buffer. This is used by the library
+    *  internally to perform debug checks.
+    */
+    aiPropertyTypeInfo mType;
+
+    /**	Binary buffer to hold the property's value
+    *
+    *  The buffer has no terminal character. However,
+    *  if a string is stored inside it may use 0 as terminal,
+    *  but it would be contained in mDataLength.
+    */
+    char* mData;
 };
 };
 
 
 
 
@@ -225,157 +247,261 @@ struct aiMaterial
 {
 {
 #ifdef __cplusplus
 #ifdef __cplusplus
 protected:
 protected:
-	aiMaterial() {}
+    aiMaterial() {}
 public:
 public:
 #endif // __cplusplus
 #endif // __cplusplus
 
 
-	/** List of all material properties loaded.
-	*/
-	C_STRUCT aiMaterialProperty** mProperties;
+    /** List of all material properties loaded.
+    */
+    C_STRUCT aiMaterialProperty** mProperties;
 
 
-	/** Number of properties loaded
-	*/
-	unsigned int mNumProperties;
-	unsigned int mNumAllocated;
+    /** Number of properties loaded
+    */
+    unsigned int mNumProperties;
+    unsigned int mNumAllocated;
 };
 };
 
 
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 /** @def AI_MATKEY_NAME
 /** @def AI_MATKEY_NAME
-*  Defines the name of the material (aiString)
+ *  Defines the name of the material 
+ * <br>
+ * <b>Type:</b> string (aiString)<br>
+ * <b>Default value:</b> none <br>
 */
 */
 #define AI_MATKEY_NAME "$mat.name"
 #define AI_MATKEY_NAME "$mat.name"
 
 
+// ---------------------------------------------------------------------------
+/** @def AI_MATKEY_TWOSIDED
+ *  Indicates that the material must be rendered two-sided
+ * <br>
+ * <b>Type:</b> int <br>
+ * <b>Default value:</b> 0 <br>
+*/
+#define AI_MATKEY_TWOSIDED "$mat.twosided"
+
 /** @def AI_MATKEY_SHADING_MODE
 /** @def AI_MATKEY_SHADING_MODE
-*  Defines the shading model to use (aiShadingMode)
+ *  Defines the shading model to use (aiShadingMode)
+ * <br>
+ * <b>Type:</b> int (aiShadingMode)<br>
+ * <b>Default value:</b> aiShadingMode_Gouraud <br>
 */
 */
 #define AI_MATKEY_SHADING_MODEL "$mat.shadingm"
 #define AI_MATKEY_SHADING_MODEL "$mat.shadingm"
 
 
 /** @def AI_MATKEY_ENABLE_WIREFRAM
 /** @def AI_MATKEY_ENABLE_WIREFRAM
-*  Integer property. 1 to enable wireframe for rendering
+ *  Integer property. 1 to enable wireframe for rendering
+ * <br>
+ * <b>Type:</b> int <br>
+ * <b>Default value:</b> 0 <br>
 */
 */
 #define AI_MATKEY_ENABLE_WIREFRAME "$mat.wireframe"
 #define AI_MATKEY_ENABLE_WIREFRAME "$mat.wireframe"
 
 
 /** @def AI_MATKEY_OPACITY
 /** @def AI_MATKEY_OPACITY
-*  Defines the base opacity of the material
+ *  Defines the base opacity of the material
+ * <br>
+ * <b>Type:</b> float<br>
+ * <b>Default value:</b> 1.0f <br>
 */
 */
 #define AI_MATKEY_OPACITY "$mat.opacity"
 #define AI_MATKEY_OPACITY "$mat.opacity"
 
 
 /** @def AI_MATKEY_BUMPSCALING
 /** @def AI_MATKEY_BUMPSCALING
-*  Defines the height scaling of a bump map (for stuff like Parallax
-*  Occlusion Mapping)
+ *  Defines the height scaling of a bump map (for stuff like Parallax
+ *  Occlusion Mapping)
+ * <br>
+ * <b>Type:</b> float<br>
+ * <b>Default value:</b> 1.0f <br>
 */
 */
 #define AI_MATKEY_BUMPSCALING "$mat.bumpscaling"
 #define AI_MATKEY_BUMPSCALING "$mat.bumpscaling"
 
 
 /** @def AI_MATKEY_SHININESS
 /** @def AI_MATKEY_SHININESS
-*  Defines the base shininess of the material
-*  This is the exponent of the phong shading equation.
+ *  Defines the base shininess of the material
+ *  This is the exponent of the phong shading equation.
+ * <br>
+ * <b>Type:</b> float<br>
+ * <b>Default value:</b> 0.0f <br>
 */
 */
 #define AI_MATKEY_SHININESS "$mat.shininess"
 #define AI_MATKEY_SHININESS "$mat.shininess"
 
 
 /** @def AI_MATKEY_SHININESS_STRENGTH
 /** @def AI_MATKEY_SHININESS_STRENGTH
-*  Defines the strength of the specular highlight.
+ * Defines the strength of the specular highlight.
+ * This is simply a multiplier to the specular color of a material
+ * <br>
+ * <b>Type:</b> float<br>
+ * <b>Default value:</b> 1.0f <br>
 */
 */
 #define AI_MATKEY_SHININESS_STRENGTH "$mat.shinpercent"
 #define AI_MATKEY_SHININESS_STRENGTH "$mat.shinpercent"
 
 
+// ---------------------------------------------------------------------------
 /** @def AI_MATKEY_COLOR_DIFFUSE
 /** @def AI_MATKEY_COLOR_DIFFUSE
-*  Defines the diffuse base color of the material
+ *  Defines the diffuse base color of the material
+ * <br>
+ * <b>Type:</b> color (aiColor4D or aiColor3D)<br>
+ * <b>Default value:</b> 0.0f|0.0f|0.0f|1.0f <br>
 */
 */
 #define AI_MATKEY_COLOR_DIFFUSE "$clr.diffuse"
 #define AI_MATKEY_COLOR_DIFFUSE "$clr.diffuse"
 
 
 /** @def AI_MATKEY_COLOR_AMBIENT
 /** @def AI_MATKEY_COLOR_AMBIENT
-*  Defines the ambient base color of the material
+ *  Defines the ambient base color of the material
+ * <br>
+ * <b>Type:</b> color (aiColor4D or aiColor3D)<br>
+ * <b>Default value:</b> 0.0f|0.0f|0.0f|1.0f <br>
 */
 */
 #define AI_MATKEY_COLOR_AMBIENT "$clr.ambient"
 #define AI_MATKEY_COLOR_AMBIENT "$clr.ambient"
 
 
 /** @def AI_MATKEY_COLOR_SPECULAR
 /** @def AI_MATKEY_COLOR_SPECULAR
-*  Defines the specular base color of the material
+ *  Defines the specular base color of the material
+ * <br>
+ * <b>Type:</b> color (aiColor4D or aiColor3D)<br>
+ * <b>Default value:</b> 0.0f|0.0f|0.0f|1.0f <br>
 */
 */
 #define AI_MATKEY_COLOR_SPECULAR "$clr.specular"
 #define AI_MATKEY_COLOR_SPECULAR "$clr.specular"
 
 
 /** @def AI_MATKEY_COLOR_EMISSIVE
 /** @def AI_MATKEY_COLOR_EMISSIVE
-*  Defines the emissive base color of the material
+ *  Defines the emissive base color of the material
+ * <br>
+ * <b>Type:</b> color (aiColor4D or aiColor3D)<br>
+ * <b>Default value:</b> 0.0f|0.0f|0.0f|1.0f <br>
 */
 */
 #define AI_MATKEY_COLOR_EMISSIVE "$clr.emissive"
 #define AI_MATKEY_COLOR_EMISSIVE "$clr.emissive"
 
 
+// ---------------------------------------------------------------------------
 /** @def AI_MATKEY_TEXTURE_DIFFUSE
 /** @def AI_MATKEY_TEXTURE_DIFFUSE
 *  Defines a specified diffuse texture channel of the material
 *  Defines a specified diffuse texture channel of the material
+ *  <br>
+ * <b>Type:</b> string (aiString)<br>
+ * <b>Default value:</b> none <br>
 */
 */
 #define AI_MATKEY_TEXTURE_DIFFUSE(N) "$tex.file.diffuse["#N"]"
 #define AI_MATKEY_TEXTURE_DIFFUSE(N) "$tex.file.diffuse["#N"]"
 #define AI_MATKEY_TEXTURE_DIFFUSE_  "$tex.file.diffuse"
 #define AI_MATKEY_TEXTURE_DIFFUSE_  "$tex.file.diffuse"
 
 
 /** @def AI_MATKEY_TEXTURE_AMBIENT
 /** @def AI_MATKEY_TEXTURE_AMBIENT
-*  Defines a specified ambient texture channel of the material
+ *  Defines a specified ambient texture channel of the material
+ *  <br>
+ * <b>Type:</b> string (aiString)<br>
+ * <b>Default value:</b> none <br>
 */
 */
 #define AI_MATKEY_TEXTURE_AMBIENT(N) "$tex.file.ambient["#N"]"
 #define AI_MATKEY_TEXTURE_AMBIENT(N) "$tex.file.ambient["#N"]"
 #define AI_MATKEY_TEXTURE_AMBIENT_   "$tex.file.ambient"
 #define AI_MATKEY_TEXTURE_AMBIENT_   "$tex.file.ambient"
 
 
 /** @def AI_MATKEY_TEXTURE_SPECULAR
 /** @def AI_MATKEY_TEXTURE_SPECULAR
-*  Defines a specified specular texture channel of the material
+ *  Defines a specified specular texture channel of the material
+ *  <br>
+ * <b>Type:</b> string (aiString)<br>
+ * <b>Default value:</b> none <br>
 */
 */
 #define AI_MATKEY_TEXTURE_SPECULAR(N) "$tex.file.specular["#N"]"
 #define AI_MATKEY_TEXTURE_SPECULAR(N) "$tex.file.specular["#N"]"
 #define AI_MATKEY_TEXTURE_SPECULAR_   "$tex.file.specular"
 #define AI_MATKEY_TEXTURE_SPECULAR_   "$tex.file.specular"
 
 
 /** @def AI_MATKEY_TEXTURE_EMISSIVE
 /** @def AI_MATKEY_TEXTURE_EMISSIVE
-*  Defines a specified emissive texture channel of the material
+ *  Defines a specified emissive texture channel of the material
+ *  <br>
+ * <b>Type:</b> string (aiString)<br>
+ * <b>Default value:</b> none <br>
 */
 */
 #define AI_MATKEY_TEXTURE_EMISSIVE(N) "$tex.file.emissive["#N"]"
 #define AI_MATKEY_TEXTURE_EMISSIVE(N) "$tex.file.emissive["#N"]"
 #define AI_MATKEY_TEXTURE_EMISSIVE_   "$tex.file.emissive"
 #define AI_MATKEY_TEXTURE_EMISSIVE_   "$tex.file.emissive"
 
 
 /** @def AI_MATKEY_TEXTURE_NORMALS
 /** @def AI_MATKEY_TEXTURE_NORMALS
-*  Defines a specified normal texture channel of the material
+ *  Defines a specified normal texture channel of the material
+ *  <br>
+ * <b>Type:</b> string (aiString)<br>
+ * <b>Default value:</b> none <br>
 */
 */
 #define AI_MATKEY_TEXTURE_NORMALS(N) "$tex.file.normals["#N"]"
 #define AI_MATKEY_TEXTURE_NORMALS(N) "$tex.file.normals["#N"]"
 #define AI_MATKEY_TEXTURE_NORMALS_   "$tex.file.normals"
 #define AI_MATKEY_TEXTURE_NORMALS_   "$tex.file.normals"
 
 
 /** @def AI_MATKEY_TEXTURE_HEIGHT
 /** @def AI_MATKEY_TEXTURE_HEIGHT
-* Defines a specified bumpmap texture (=heightmap) channel of the material
-* This is very similar to #AI_MATKEY_TEXTURE_NORMALS. It is provided
-* to allow applications to determine whether the input data for
-* normal mapping is already a normal map or needs to be converted from
-* a heightmap to a normal map.
+ * Defines a specified bumpmap texture (=heightmap) channel of the material
+ * This is very similar to #AI_MATKEY_TEXTURE_NORMALS. It is provided
+ * to allow applications to determine whether the input data for
+ * normal mapping is already a normal map or needs to be converted from
+ * a heightmap to a normal map.
+ * <br>
+ * <b>Type:</b> string (aiString)<br>
+ * <b>Default value:</b> none <br>
 */
 */
 #define AI_MATKEY_TEXTURE_HEIGHT(N) "$tex.file.bump["#N"]"
 #define AI_MATKEY_TEXTURE_HEIGHT(N) "$tex.file.bump["#N"]"
 #define AI_MATKEY_TEXTURE_HEIGHT_   "$tex.file.bump"
 #define AI_MATKEY_TEXTURE_HEIGHT_   "$tex.file.bump"
 
 
 /** @def AI_MATKEY_TEXTURE_SHININESS
 /** @def AI_MATKEY_TEXTURE_SHININESS
-*  Defines a specified shininess texture channel of the material
+ *  Defines a specified shininess texture channel of the material
+ *  <br>
+ * <b>Type:</b> string (aiString)<br>
+ * <b>Default value:</b> none <br>
 */
 */
 #define AI_MATKEY_TEXTURE_SHININESS(N) "$tex.file.shininess["#N"]"
 #define AI_MATKEY_TEXTURE_SHININESS(N) "$tex.file.shininess["#N"]"
 #define AI_MATKEY_TEXTURE_SHININESS_   "$tex.file.shininess"
 #define AI_MATKEY_TEXTURE_SHININESS_   "$tex.file.shininess"
 
 
 /** @def AI_MATKEY_TEXTURE_OPACITY
 /** @def AI_MATKEY_TEXTURE_OPACITY
-*  Defines a specified opacity texture channel of the material
+ *  Defines a specified opacity texture channel of the material
+ *  <br>
+ * <b>Type:</b> string (aiString)<br>
+ * <b>Default value:</b> none <br>
 */
 */
 #define AI_MATKEY_TEXTURE_OPACITY(N) "$tex.file.opacity["#N"]"
 #define AI_MATKEY_TEXTURE_OPACITY(N) "$tex.file.opacity["#N"]"
 #define AI_MATKEY_TEXTURE_OPACITY_   "$tex.file.opacity"
 #define AI_MATKEY_TEXTURE_OPACITY_   "$tex.file.opacity"
 
 
+// ---------------------------------------------------------------------------
+/** @def AI_MATKEY_TEXOP_DIFFUSE
+ * Specifies the blend operation too be used to combine the Nth
+ * diffuse texture with the (N-1)th diffuse texture (or the diffuse
+ * base color for the first diffuse texture)
+ * <br>
+ * <b>Type:</b> int (aiTextureOp)<br>
+ * <b>Default value:</b> 0<br>
+ * <b>Requires:</b> AI_MATKEY_TEXTURE_DIFFUSE(0)<br>
+ * @note Never use an non-numeric index (like a variable) for this.
+ * Remember, the key string is built by the preprocessor
+ */
+#define AI_MATKEY_TEXOP_DIFFUSE(N)	"$tex.op.diffuse["#N"]"
+/** @see AI_MATKEY_TEXOP_DIFFUSE */
+#define AI_MATKEY_TEXOP_AMBIENT(N)	"$tex.op.ambient["#N"]"
+/** @see AI_MATKEY_TEXOP_DIFFUSE */
+#define AI_MATKEY_TEXOP_SPECULAR(N)	"$tex.op.specular["#N"]"
+/** @see AI_MATKEY_TEXOP_DIFFUSE */
+#define AI_MATKEY_TEXOP_EMISSIVE(N)	"$tex.op.emissive["#N"]"
+/** @see AI_MATKEY_TEXOP_DIFFUSE */
+#define AI_MATKEY_TEXOP_NORMALS(N)	"$tex.op.normals["#N"]"
+/** @see AI_MATKEY_TEXOP_DIFFUSE */
+#define AI_MATKEY_TEXOP_HEIGHT(N)	"$tex.op.height["#N"]"
+/** @see AI_MATKEY_TEXOP_DIFFUSE */
+#define AI_MATKEY_TEXOP_SHININESS(N)"$tex.op.shininess["#N"]"
+/** @see AI_MATKEY_TEXOP_DIFFUSE */
+#define AI_MATKEY_TEXOP_OPACITY(N)	"$tex.op.opacity["#N"]"
+
+#define AI_MATKEY_TEXOP_DIFFUSE_	"$tex.op.diffuse"
+#define AI_MATKEY_TEXOP_AMBIENT_	"$tex.op.ambient"
+#define AI_MATKEY_TEXOP_SPECULAR_	"$tex.op.specular"
+#define AI_MATKEY_TEXOP_EMISSIVE_	"$tex.op.emissive"
+#define AI_MATKEY_TEXOP_NORMALS_	"$tex.op.normals"
+#define AI_MATKEY_TEXOP_HEIGHT_		"$tex.op.height"
+#define AI_MATKEY_TEXOP_SHININESS_	"$tex.op.shininess"
+#define AI_MATKEY_TEXOP_OPACITY_	"$tex.op.opacity"
 
 
-#define AI_MATKEY_TEXOP_DIFFUSE(N)		"$tex.op.diffuse["#N"]"
-#define AI_MATKEY_TEXOP_AMBIENT(N)		"$tex.op.ambient["#N"]"
-#define AI_MATKEY_TEXOP_SPECULAR(N)		"$tex.op.specular["#N"]"
-#define AI_MATKEY_TEXOP_EMISSIVE(N)		"$tex.op.emissive["#N"]"
-#define AI_MATKEY_TEXOP_NORMALS(N)		"$tex.op.normals["#N"]"
-#define AI_MATKEY_TEXOP_HEIGHT(N)			"$tex.op.bump["#N"]"
-#define AI_MATKEY_TEXOP_SHININESS(N)	"$tex.op.shininess["#N"]"
-#define AI_MATKEY_TEXOP_OPACITY(N)		"$tex.op.opacity["#N"]"
-
-#define AI_MATKEY_TEXOP_DIFFUSE_		"$tex.op.diffuse"
-#define AI_MATKEY_TEXOP_AMBIENT_		"$tex.op.ambient"
-#define AI_MATKEY_TEXOP_SPECULAR_		"$tex.op.specular"
-#define AI_MATKEY_TEXOP_EMISSIVE_		"$tex.op.emissive"
-#define AI_MATKEY_TEXOP_NORMALS_		"$tex.op.normals"
-#define AI_MATKEY_TEXOP_HEIGHT_			"$tex.op.bump"
-#define AI_MATKEY_TEXOP_SHININESS_		"$tex.op.shininess"
-#define AI_MATKEY_TEXOP_OPACITY_		"$tex.op.opacity"
-
+// ---------------------------------------------------------------------------
+/** @def AI_MATKEY_UVWSRC_DIFFUSE
+ * Specifies the UV channel to be used for the Nth diffuse texture
+ * <br>
+ * <b>Type:</b> int<br>
+ * <b>Default value:</b> 0<br>
+ * <b>Requires:</b> AI_MATKEY_TEXTURE_DIFFUSE(0)<br>
+ * @note Never use an non-numeric index (like a variable) for this.
+ * Remember, the key string is built by the preprocessor
+ */
 #define AI_MATKEY_UVWSRC_DIFFUSE(N)		"$tex.uvw.diffuse["#N"]"
 #define AI_MATKEY_UVWSRC_DIFFUSE(N)		"$tex.uvw.diffuse["#N"]"
+/** @see AI_MATKEY_UVWSRC_DIFFUSE */
 #define AI_MATKEY_UVWSRC_AMBIENT(N)		"$tex.uvw.ambient["#N"]"
 #define AI_MATKEY_UVWSRC_AMBIENT(N)		"$tex.uvw.ambient["#N"]"
+/** @see AI_MATKEY_UVWSRC_DIFFUSE */
 #define AI_MATKEY_UVWSRC_SPECULAR(N)	"$tex.uvw.specular["#N"]"
 #define AI_MATKEY_UVWSRC_SPECULAR(N)	"$tex.uvw.specular["#N"]"
+/** @see AI_MATKEY_UVWSRC_DIFFUSE */
 #define AI_MATKEY_UVWSRC_EMISSIVE(N)	"$tex.uvw.emissive["#N"]"
 #define AI_MATKEY_UVWSRC_EMISSIVE(N)	"$tex.uvw.emissive["#N"]"
+/** @see AI_MATKEY_UVWSRC_DIFFUSE */
 #define AI_MATKEY_UVWSRC_NORMALS(N)		"$tex.uvw.normals["#N"]"
 #define AI_MATKEY_UVWSRC_NORMALS(N)		"$tex.uvw.normals["#N"]"
-#define AI_MATKEY_UVWSRC_HEIGHT(N)		"$tex.uvw.bump["#N"]"
+/** @see AI_MATKEY_UVWSRC_DIFFUSE */
+#define AI_MATKEY_UVWSRC_HEIGHT(N)		"$tex.uvw.height["#N"]"
+/** @see AI_MATKEY_UVWSRC_DIFFUSE */
 #define AI_MATKEY_UVWSRC_SHININESS(N)	"$tex.uvw.shininess["#N"]"
 #define AI_MATKEY_UVWSRC_SHININESS(N)	"$tex.uvw.shininess["#N"]"
+/** @see AI_MATKEY_UVWSRC_DIFFUSE */
 #define AI_MATKEY_UVWSRC_OPACITY(N)		"$tex.uvw.opacity["#N"]"
 #define AI_MATKEY_UVWSRC_OPACITY(N)		"$tex.uvw.opacity["#N"]"
 
 
 #define AI_MATKEY_UVWSRC_DIFFUSE_		"$tex.uvw.diffuse"
 #define AI_MATKEY_UVWSRC_DIFFUSE_		"$tex.uvw.diffuse"
@@ -383,17 +509,34 @@ public:
 #define AI_MATKEY_UVWSRC_SPECULAR_		"$tex.uvw.specular"
 #define AI_MATKEY_UVWSRC_SPECULAR_		"$tex.uvw.specular"
 #define AI_MATKEY_UVWSRC_EMISSIVE_		"$tex.uvw.emissive"
 #define AI_MATKEY_UVWSRC_EMISSIVE_		"$tex.uvw.emissive"
 #define AI_MATKEY_UVWSRC_NORMALS_		"$tex.uvw.normals"
 #define AI_MATKEY_UVWSRC_NORMALS_		"$tex.uvw.normals"
-#define AI_MATKEY_UVWSRC_HEIGHT_			"$tex.uvw.bump"
+#define AI_MATKEY_UVWSRC_HEIGHT_		"$tex.uvw.height"
 #define AI_MATKEY_UVWSRC_SHININESS_		"$tex.uvw.shininess"
 #define AI_MATKEY_UVWSRC_SHININESS_		"$tex.uvw.shininess"
 #define AI_MATKEY_UVWSRC_OPACITY_		"$tex.uvw.opacity"
 #define AI_MATKEY_UVWSRC_OPACITY_		"$tex.uvw.opacity"
 
 
+// ---------------------------------------------------------------------------
+/** @def AI_MATKEY_TEXBLEND_DIFFUSE
+ * Specifies the blend factor to be used for the Nth diffuse texture.
+ * <br>
+ * <b>Type:</b> float<br>
+ * <b>Default value:</b> 1.0f<br>
+ * <b>Requires:</b> AI_MATKEY_TEXTURE_DIFFUSE(0)<br>
+ * @note Never use an non-numeric index (like a variable) for this.
+ * Remember, the key string is built by the preprocessor
+ */
 #define AI_MATKEY_TEXBLEND_DIFFUSE(N)	"$tex.blend.diffuse["#N"]"
 #define AI_MATKEY_TEXBLEND_DIFFUSE(N)	"$tex.blend.diffuse["#N"]"
+/** @see AI_MATKEY_TEXBLEND_DIFFUSE */
 #define AI_MATKEY_TEXBLEND_AMBIENT(N)	"$tex.blend.ambient["#N"]"
 #define AI_MATKEY_TEXBLEND_AMBIENT(N)	"$tex.blend.ambient["#N"]"
+/** @see AI_MATKEY_TEXBLEND_DIFFUSE */
 #define AI_MATKEY_TEXBLEND_SPECULAR(N)	"$tex.blend.specular["#N"]"
 #define AI_MATKEY_TEXBLEND_SPECULAR(N)	"$tex.blend.specular["#N"]"
+/** @see AI_MATKEY_TEXBLEND_DIFFUSE */
 #define AI_MATKEY_TEXBLEND_EMISSIVE(N)	"$tex.blend.emissive["#N"]"
 #define AI_MATKEY_TEXBLEND_EMISSIVE(N)	"$tex.blend.emissive["#N"]"
+/** @see AI_MATKEY_TEXBLEND_DIFFUSE */
 #define AI_MATKEY_TEXBLEND_NORMALS(N)	"$tex.blend.normals["#N"]"
 #define AI_MATKEY_TEXBLEND_NORMALS(N)	"$tex.blend.normals["#N"]"
-#define AI_MATKEY_TEXBLEND_HEIGHT(N)		"$tex.blend.bump["#N"]"
+/** @see AI_MATKEY_TEXBLEND_DIFFUSE */
+#define AI_MATKEY_TEXBLEND_HEIGHT(N)	"$tex.blend.height["#N"]"
+/** @see AI_MATKEY_TEXBLEND_DIFFUSE */
 #define AI_MATKEY_TEXBLEND_SHININESS(N)	"$tex.blend.shininess["#N"]"
 #define AI_MATKEY_TEXBLEND_SHININESS(N)	"$tex.blend.shininess["#N"]"
+/** @see AI_MATKEY_TEXBLEND_DIFFUSE */
 #define AI_MATKEY_TEXBLEND_OPACITY(N)	"$tex.blend.opacity["#N"]"
 #define AI_MATKEY_TEXBLEND_OPACITY(N)	"$tex.blend.opacity["#N"]"
 
 
 #define AI_MATKEY_TEXBLEND_DIFFUSE_		"$tex.blend.diffuse"
 #define AI_MATKEY_TEXBLEND_DIFFUSE_		"$tex.blend.diffuse"
@@ -401,17 +544,123 @@ public:
 #define AI_MATKEY_TEXBLEND_SPECULAR_	"$tex.blend.specular"
 #define AI_MATKEY_TEXBLEND_SPECULAR_	"$tex.blend.specular"
 #define AI_MATKEY_TEXBLEND_EMISSIVE_	"$tex.blend.emissive"
 #define AI_MATKEY_TEXBLEND_EMISSIVE_	"$tex.blend.emissive"
 #define AI_MATKEY_TEXBLEND_NORMALS_		"$tex.blend.normals"
 #define AI_MATKEY_TEXBLEND_NORMALS_		"$tex.blend.normals"
-#define AI_MATKEY_TEXBLEND_HEIGHT_		"$tex.blend.bump"
+#define AI_MATKEY_TEXBLEND_HEIGHT_		"$tex.blend.height"
 #define AI_MATKEY_TEXBLEND_SHININESS_	"$tex.blend.shininess"
 #define AI_MATKEY_TEXBLEND_SHININESS_	"$tex.blend.shininess"
 #define AI_MATKEY_TEXBLEND_OPACITY_		"$tex.blend.opacity"
 #define AI_MATKEY_TEXBLEND_OPACITY_		"$tex.blend.opacity"
 
 
+// ---------------------------------------------------------------------------
+/** @def AI_MATKEY_MAPPINGMODE_U_DIFFUSE
+ * Specifies the texture mapping mode for the Nth diffuse texture in
+ * the u (x) direction
+ * <br>
+ * <b>Type:</b> int (aiTextureMapMode)<br>
+ * <b>Default value:</b> aiTextureMapMode_Wrap<br>
+ * <b>Requires:</b> AI_MATKEY_TEXTURE_DIFFUSE(0)<br>
+ * @note Never use an non-numeric index (like a variable) for this.
+ * Remember, the key string is built by the preprocessor
+ */
+#define AI_MATKEY_MAPPINGMODE_U_DIFFUSE(N)	"$tex.mapmodeu.diffuse["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_U_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_U_AMBIENT(N)	"$tex.mapmodeu.ambient["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_U_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_U_SPECULAR(N)	"$tex.mapmodeu.specular["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_U_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_U_EMISSIVE(N)	"$tex.mapmodeu.emissive["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_U_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_U_NORMALS(N)	"$tex.mapmodeu.normals["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_U_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_U_HEIGHT(N)	"$tex.mapmodeu.height["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_U_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_U_SHININESS(N)"$tex.mapmodeu.shininess["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_U_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_U_OPACITY(N)	"$tex.mapmodeu.opacity["#N"]"
+
+#define AI_MATKEY_MAPPINGMODE_U_DIFFUSE_	"$tex.mapmodeu.diffuse"
+#define AI_MATKEY_MAPPINGMODE_U_AMBIENT_	"$tex.mapmodeu.ambient"
+#define AI_MATKEY_MAPPINGMODE_U_SPECULAR_	"$tex.mapmodeu.specular"
+#define AI_MATKEY_MAPPINGMODE_U_EMISSIVE_	"$tex.mapmodeu.emissive"
+#define AI_MATKEY_MAPPINGMODE_U_NORMALS_	"$tex.mapmodeu.normals"
+#define AI_MATKEY_MAPPINGMODE_U_HEIGHT_		"$tex.mapmodeu.height"
+#define AI_MATKEY_MAPPINGMODE_U_SHININESS_	"$tex.mapmodeu.shininess"
+#define AI_MATKEY_MAPPINGMODE_U_OPACITY_	"$tex.mapmodeu.opacity"
+
+// ---------------------------------------------------------------------------
+/** @def AI_MATKEY_MAPPINGMODE_V_DIFFUSE
+ * Specifies the texture mapping mode for the Nth diffuse texture in
+ * the v (y) direction
+ * <br>
+ * <b>Type:</b> int (aiTextureMapMode)<br>
+ * <b>Default value:</b> aiTextureMapMode_Wrap<br>
+ * <b>Requires:</b> AI_MATKEY_TEXTURE_DIFFUSE(0)<br>
+ * @note Never use an non-numeric index (like a variable) for this.
+ * Remember, the key string is built by the preprocessor
+ */
+#define AI_MATKEY_MAPPINGMODE_V_DIFFUSE(N)	"$tex.mapmodev.diffuse["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_V_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_V_AMBIENT(N)	"$tex.mapmodev.ambient["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_V_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_V_SPECULAR(N)	"$tex.mapmodev.specular["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_V_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_V_EMISSIVE(N)	"$tex.mapmodev.emissive["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_V_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_V_NORMALS(N)	"$tex.mapmodev.normals["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_V_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_V_HEIGHT(N)	"$tex.mapmodev.height["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_V_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_V_SHININESS(N)"$tex.mapmodev.shininess["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_V_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_V_OPACITY(N)	"$tex.mapmodev.opacity["#N"]"
+
+#define AI_MATKEY_MAPPINGMODE_V_DIFFUSE_	"$tex.mapmodev.diffuse"
+#define AI_MATKEY_MAPPINGMODE_V_AMBIENT_	"$tex.mapmodev.ambient"
+#define AI_MATKEY_MAPPINGMODE_V_SPECULAR_	"$tex.mapmodev.specular"
+#define AI_MATKEY_MAPPINGMODE_V_EMISSIVE_	"$tex.mapmodev.emissive"
+#define AI_MATKEY_MAPPINGMODE_V_NORMALS_	"$tex.mapmodev.normals"
+#define AI_MATKEY_MAPPINGMODE_V_HEIGHT_		"$tex.mapmodev.height"
+#define AI_MATKEY_MAPPINGMODE_V_SHININESS_	"$tex.mapmodev.shininess"
+#define AI_MATKEY_MAPPINGMODE_V_OPACITY_	"$tex.mapmodev.opacity"
+
+// ---------------------------------------------------------------------------
+/** @def AI_MATKEY_MAPPINGMODE_W_DIFFUSE
+ * Specifies the texture mapping mode for the Nth diffuse texture in
+ * the w (z) direction
+ * <br>
+ * <b>Type:</b> int (aiTextureMapMode)<br>
+ * <b>Default value:</b> aiTextureMapMode_Wrap<br>
+ * <b>Requires:</b> AI_MATKEY_TEXTURE_DIFFUSE(0)<br>
+ * @note Never use an non-numeric index (like a variable) for this.
+ * Remember, the key string is built by the preprocessor
+ */
+#define AI_MATKEY_MAPPINGMODE_W_DIFFUSE(N)	"$tex.mapmodew.diffuse["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_W_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_W_AMBIENT(N)	"$tex.mapmodew.ambient["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_W_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_W_SPECULAR(N)	"$tex.mapmodew.specular["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_W_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_W_EMISSIVE(N)	"$tex.mapmodew.emissive["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_W_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_W_NORMALS(N)	"$tex.mapmodew.normals["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_W_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_W_HEIGHT(N)	"$tex.mapmodew.bump["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_W_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_W_SHININESS(N)"$tex.mapmodew.shininess["#N"]"
+/** @see AI_MATKEY_MAPPINGMODE_W_DIFFUSE */
+#define AI_MATKEY_MAPPINGMODE_W_OPACITY(N)	"$tex.mapmodew.opacity["#N"]"
+
+#define AI_MATKEY_MAPPINGMODE_W_DIFFUSE_	"$tex.mapmodew.diffuse"
+#define AI_MATKEY_MAPPINGMODE_W_AMBIENT_	"$tex.mapmodew.ambient"
+#define AI_MATKEY_MAPPINGMODE_W_SPECULAR_	"$tex.mapmodew.specular"
+#define AI_MATKEY_MAPPINGMODE_W_EMISSIVE_	"$tex.mapmodew.emissive"
+#define AI_MATKEY_MAPPINGMODE_W_NORMALS_	"$tex.mapmodew.normals"
+#define AI_MATKEY_MAPPINGMODE_W_HEIGHT_		"$tex.mapmodew.height"
+#define AI_MATKEY_MAPPINGMODE_W_SHININESS_	"$tex.mapmodew.shininess"
+#define AI_MATKEY_MAPPINGMODE_W_OPACITY_	"$tex.mapmodew.opacity"
 
 
 #define AI_MATKEY_ORENNAYAR_ROUGHNESS	 "$shading.orennayar.roughness"
 #define AI_MATKEY_ORENNAYAR_ROUGHNESS	 "$shading.orennayar.roughness"
 #define AI_MATKEY_MINNAERT_DARKNESS		 "$shading.minnaert.darkness"
 #define AI_MATKEY_MINNAERT_DARKNESS		 "$shading.minnaert.darkness"
 #define AI_MATKEY_COOK_TORRANCE_REFRACTI "$shading.cookt.refracti"
 #define AI_MATKEY_COOK_TORRANCE_REFRACTI "$shading.cookt.refracti"
 #define AI_MATKEY_COOK_TORRANCE_PARAM	 "$shading.cookt.param"
 #define AI_MATKEY_COOK_TORRANCE_PARAM	 "$shading.cookt.param"
 
 
-
 /** @def AI_MATKEY_GLOBAL_BACKGROUND_IMAGE
 /** @def AI_MATKEY_GLOBAL_BACKGROUND_IMAGE
 *  Global property defined by some loaders. Contains the path to 
 *  Global property defined by some loaders. Contains the path to 
 *  the image file to be used as background image.
 *  the image file to be used as background image.
@@ -429,8 +678,8 @@ public:
 */
 */
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 aiReturn aiGetMaterialProperty(const C_STRUCT aiMaterial* pMat, 
 aiReturn aiGetMaterialProperty(const C_STRUCT aiMaterial* pMat, 
-	const char* pKey,
-	const C_STRUCT aiMaterialProperty** pPropOut);
+    const char* pKey,
+    const C_STRUCT aiMaterialProperty** pPropOut);
 
 
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -445,20 +694,20 @@ aiReturn aiGetMaterialProperty(const C_STRUCT aiMaterial* pMat,
 */
 */
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 aiReturn aiGetMaterialFloatArray(const C_STRUCT aiMaterial* pMat, 
 aiReturn aiGetMaterialFloatArray(const C_STRUCT aiMaterial* pMat, 
-	const char* pKey,
-	float* pOut,
-	unsigned int* pMax);
+    const char* pKey,
+    float* pOut,
+    unsigned int* pMax);
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 // inline it
 // inline it
 inline aiReturn aiGetMaterialFloat(const C_STRUCT aiMaterial* pMat, 
 inline aiReturn aiGetMaterialFloat(const C_STRUCT aiMaterial* pMat, 
-	 const char* pKey,
-	 float* pOut)
-	{return aiGetMaterialFloatArray(pMat,pKey,pOut,(unsigned int*)0x0);}
+     const char* pKey,
+     float* pOut)
+    {return aiGetMaterialFloatArray(pMat,pKey,pOut,(unsigned int*)0x0);}
 #else 
 #else 
 // use our friend, the C preprocessor
 // use our friend, the C preprocessor
 #define aiGetMaterialFloat (pMat, pKey, pOut) \
 #define aiGetMaterialFloat (pMat, pKey, pOut) \
-	aiGetMaterialFloatArray(pMat, pKey, pOut, NULL)
+    aiGetMaterialFloatArray(pMat, pKey, pOut, NULL)
 #endif //!__cplusplus
 #endif //!__cplusplus
 
 
 
 
@@ -474,20 +723,20 @@ inline aiReturn aiGetMaterialFloat(const C_STRUCT aiMaterial* pMat,
 */
 */
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 aiReturn aiGetMaterialIntegerArray(const C_STRUCT aiMaterial* pMat, 
 aiReturn aiGetMaterialIntegerArray(const C_STRUCT aiMaterial* pMat, 
-	const char* pKey,
-	int* pOut,
-	unsigned int* pMax);
+    const char* pKey,
+    int* pOut,
+    unsigned int* pMax);
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 // inline it
 // inline it
 inline aiReturn aiGetMaterialInteger(const C_STRUCT aiMaterial* pMat, 
 inline aiReturn aiGetMaterialInteger(const C_STRUCT aiMaterial* pMat, 
-	const char* pKey,
-	int* pOut)
-	{return aiGetMaterialIntegerArray(pMat,pKey,pOut,(unsigned int*)0x0);}
+    const char* pKey,
+    int* pOut)
+    {return aiGetMaterialIntegerArray(pMat,pKey,pOut,(unsigned int*)0x0);}
 #else 
 #else 
 // use our friend, the C preprocessor
 // use our friend, the C preprocessor
 #define aiGetMaterialInteger (pMat, pKey, pOut) \
 #define aiGetMaterialInteger (pMat, pKey, pOut) \
-	aiGetMaterialIntegerArray(pMat, pKey, pOut, NULL)
+    aiGetMaterialIntegerArray(pMat, pKey, pOut, NULL)
 #endif //!__cplusplus
 #endif //!__cplusplus
 
 
 
 
@@ -501,8 +750,8 @@ inline aiReturn aiGetMaterialInteger(const C_STRUCT aiMaterial* pMat,
 */
 */
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 aiReturn aiGetMaterialColor(const C_STRUCT aiMaterial* pMat, 
 aiReturn aiGetMaterialColor(const C_STRUCT aiMaterial* pMat, 
-	const char* pKey,
-	aiColor4D* pOut);
+    const char* pKey,
+    aiColor4D* pOut);
 
 
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -514,8 +763,8 @@ aiReturn aiGetMaterialColor(const C_STRUCT aiMaterial* pMat,
 */
 */
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 aiReturn aiGetMaterialString(const C_STRUCT aiMaterial* pMat, 
 aiReturn aiGetMaterialString(const C_STRUCT aiMaterial* pMat, 
-	const char* pKey,
-	aiString* pOut);
+    const char* pKey,
+    aiString* pOut);
 
 
 
 
 #define AI_TEXTYPE_OPACITY		0x0
 #define AI_TEXTYPE_OPACITY		0x0
@@ -533,31 +782,48 @@ aiReturn aiGetMaterialString(const C_STRUCT aiMaterial* pMat,
  *  This function is provided just for convinience. 
  *  This function is provided just for convinience. 
  *  @param pMat Pointer to the input material. May not be NULL
  *  @param pMat Pointer to the input material. May not be NULL
  *  @param iIndex Index of the texture to retrieve. If the index is too 
  *  @param iIndex Index of the texture to retrieve. If the index is too 
- *     large the function fails.
+ *		large the function fails.
  *  @param iTexType One of the AI_TEXTYPE constants. Specifies the type of
  *  @param iTexType One of the AI_TEXTYPE constants. Specifies the type of
- *     the texture to retrieve (e.g. diffuse, specular, height map ...)
+ *		the texture to retrieve (e.g. diffuse, specular, height map ...)
  *  @param szPath Receives the output path
  *  @param szPath Receives the output path
- *     NULL is no allowed as value
+ *		NULL is no allowed as value
  *  @param piUVIndex Receives the UV index of the texture. 
  *  @param piUVIndex Receives the UV index of the texture. 
- *     NULL is allowed as value.
+ *		NULL is allowed as value.
  *  @param pfBlendFactor Receives the blend factor for the texture
  *  @param pfBlendFactor Receives the blend factor for the texture
- *     NULL is allowed as value.
+ *		NULL is allowed as value.
  *  @param peTextureOp Receives the texture operation to perform between
  *  @param peTextureOp Receives the texture operation to perform between
- *     this texture and the previous texture.
- *     NULL is allowed as value.
+ *		this texture and the previous texture. NULL is allowed as value.
+ *  @param peMapMode Receives the mapping modes to be used for the texture.
+ *      The parameter may be NULL but if it is a valid pointer it MUST
+ *      point to an array of 3 aiTextureMapMode variables (one for each
+ *      axis: UVW order (=XYZ)). 
  */
  */
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
+#ifdef __cplusplus
 aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* pMat,
 aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* pMat,
-	unsigned int iIndex,
-	unsigned int iTexType,
-	C_STRUCT aiString* szPath,
-	unsigned int* piUVIndex,
-	float* pfBlendFactor,
-	aiTextureOp* peTextureOp); 
-
+    unsigned int iIndex,
+    unsigned int iTexType,
+    C_STRUCT aiString* szPath,
+    unsigned int* piUVIndex		= NULL,
+    float* pfBlendFactor		= NULL,
+    aiTextureOp* peTextureOp	= NULL,
+	aiTextureMapMode* peMapMode = NULL); 
+#else
+aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* pMat,
+    unsigned int iIndex,
+    unsigned int iTexType,
+    C_STRUCT aiString* szPath,
+    unsigned int* piUVIndex,
+    float* pfBlendFactor,
+    aiTextureOp* peTextureOp,
+	aiTextureMapMode* peMapMode); 
+#endif // !#ifdef __cplusplus
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
+
+#include "aiMaterial.inl"
+
 #endif //!__cplusplus
 #endif //!__cplusplus
 
 
 #endif //!!AI_MATERIAL_H_INC
 #endif //!!AI_MATERIAL_H_INC

+ 160 - 0
include/aiMaterial.inl

@@ -0,0 +1,160 @@
+/*
+---------------------------------------------------------------------------
+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 Defines the material system of the library
+ *
+ */
+
+#ifndef AI_MATERIAL_INL_INC
+#define AI_MATERIAL_INL_INC
+
+
+// ---------------------------------------------------------------------------
+/** @brief A class that provides easy access to the property list of a
+ *  material (aiMaterial) via template methods. You can cast an
+ *  aiMaterial* to aiMaterialCPP*
+ *  @note This extra class is necessary since template methods
+ *  are not allowed within C-linkage blocks (extern "C")
+ */
+class aiMaterialCPP : public aiMaterial
+{
+public:
+
+	// -------------------------------------------------------------------
+    /** Retrieve an array of Type values with a specific key 
+     *  from the material
+     *
+     * @param pKey Key to search for. One of the AI_MATKEY_XXX constants.
+     * @param pOut Pointer to a buffer to receive the result. 
+     * @param pMax Specifies the size of the given buffer, in Type's.
+     * Receives the number of values (not bytes!) read. 
+     * NULL is a valid value for this parameter.
+     */
+    template <typename Type>
+    inline aiReturn Get(const char* pKey,Type* pOut,
+        unsigned int* pMax);
+
+    // -------------------------------------------------------------------
+    /** Retrieve a Type value with a specific key 
+     *  from the material
+     *
+     * @param pKey Key to search for. One of the AI_MATKEY_XXX constants.
+     * @param pOut Reference to receive the output value
+     */
+    template <typename Type>
+	inline aiReturn Get(const char* pKey,Type& pOut);
+};
+
+// ---------------------------------------------------------------------------
+template <typename Type>
+inline aiReturn aiMaterialCPP::Get(const char* pKey,Type* pOut,
+	unsigned int* pMax)
+{
+	unsigned int iNum = pMax ? *pMax : 1;
+
+	aiMaterialProperty* prop;
+	aiReturn ret = aiGetMaterialProperty(this,pKey,&prop);
+	if ( AI_SUCCESS == ret )
+	{
+		if (prop->mDataLength < sizeof(Type)*iNum)return AI_FAILURE;
+		if (prop->mData != aiPTI_Buffer)return AI_FAILURE;
+
+		iNum = std::min(iNum,prop->mDataLength / sizeof(Type));
+		::memcpy(pOut,prop->mData,iNum * sizeof(Type));
+		if (pMax)*pMax = iNum;
+	}
+	return ret;
+}
+// ---------------------------------------------------------------------------
+template <typename Type>
+inline aiReturn aiMaterialCPP::Get(const char* pKey,Type& pOut)
+{
+	aiMaterialProperty* prop;
+	aiReturn ret = aiGetMaterialProperty(this,pKey,&prop);
+	if ( AI_SUCCESS == ret )
+	{
+		if (prop->mDataLength < sizeof(Type))return AI_FAILURE;
+		if (prop->mData != aiPTI_Buffer)return AI_FAILURE;
+
+		::memcpy(&pOut,prop->mData,sizeof(Type));
+	}
+	return ret;
+}
+// ---------------------------------------------------------------------------
+template <>
+inline aiReturn aiMaterialCPP::Get<float>(const char* pKey,float* pOut,
+	unsigned int* pMax)
+{
+	return aiGetMaterialFloatArray(this,pKey,pOut,pMax);
+}
+// ---------------------------------------------------------------------------
+template <>
+inline aiReturn aiMaterialCPP::Get<int>(const char* pKey,int* pOut,
+	unsigned int* pMax)
+{
+	return aiGetMaterialIntegerArray(this,pKey,pOut,pMax);
+}
+// ---------------------------------------------------------------------------
+template <>
+inline aiReturn aiMaterialCPP::Get<float>(const char* pKey,float& pOut)
+{
+	return aiGetMaterialFloat(this,pKey,&pOut);
+}
+// ---------------------------------------------------------------------------
+template <>
+inline aiReturn aiMaterialCPP::Get<int>(const char* pKey,int& pOut)
+{
+	return aiGetMaterialInteger(this,pKey,&pOut);
+}
+// ---------------------------------------------------------------------------
+template <>
+inline aiReturn aiMaterialCPP::Get<aiColor4D>(const char* pKey,aiColor4D& pOut)
+{
+	return aiGetMaterialColor(this,pKey,&pOut);
+}
+// ---------------------------------------------------------------------------
+template <>
+inline aiReturn aiMaterialCPP::Get<aiString>(const char* pKey,aiString& pOut)
+{
+	return aiGetMaterialString(this,pKey,&pOut);
+}
+
+#endif //! AI_MATERIAL_INL_INC

+ 14 - 0
include/aiMesh.h

@@ -185,6 +185,20 @@ struct aiBone
 		mNumWeights = 0; mWeights = NULL;
 		mNumWeights = 0; mWeights = NULL;
 	}
 	}
 
 
+	//! Copy constructor
+	aiBone(const aiBone& other)
+	{
+		mNumWeights = other.mNumWeights;
+		mOffsetMatrix = other.mOffsetMatrix;
+		mName = other.mName;
+
+		if (other.mWeights && other.mNumWeights)
+		{
+			mWeights = new aiVertexWeight[mNumWeights];
+			memcpy(mWeights,other.mWeights,mNumWeights * sizeof(aiVertexWeight));
+		}
+	}
+
 	//! Destructor to delete the array of vertex weights
 	//! Destructor to delete the array of vertex weights
 	~aiBone()
 	~aiBone()
 	{
 	{

二进制
tools/assimp_view/assimp_view.aps


+ 1 - 1
tools/assimp_view/assimp_view.rc

@@ -152,7 +152,7 @@ EXSTYLE WS_EX_TOPMOST | WS_EX_WINDOWEDGE
 CAPTION "AssimpView Log Output"
 CAPTION "AssimpView Log Output"
 FONT 8, "Courier New", 400, 0, 0x0
 FONT 8, "Courier New", 400, 0, 0x0
 BEGIN
 BEGIN
-    CONTROL         "",IDC_EDIT1,"RichEdit20A",ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER | WS_VSCROLL | WS_TABSTOP,3,4,358,174,WS_EX_STATICEDGE
+    CONTROL         "",IDC_EDIT1,"RichEdit20A",ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | ES_NUMBER | WS_VSCROLL | WS_TABSTOP,3,4,358,174,WS_EX_STATICEDGE
 END
 END
 
 
 
 

+ 110 - 106
workspaces/vc8/assimp.vcproj

@@ -79,11 +79,10 @@
 			/>
 			/>
 		</Configuration>
 		</Configuration>
 		<Configuration
 		<Configuration
-			Name="Release|Win32"
+			Name="Debug|x64"
 			OutputDirectory="./../../lib/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			OutputDirectory="./../../lib/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			ConfigurationType="4"
 			ConfigurationType="4"
-			WholeProgramOptimization="0"
 			>
 			>
 			<Tool
 			<Tool
 				Name="VCPreBuildEventTool"
 				Name="VCPreBuildEventTool"
@@ -99,18 +98,19 @@
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCMIDLTool"
 				Name="VCMIDLTool"
+				TargetEnvironment="3"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCCLCompilerTool"
 				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="2"
-				EnableIntrinsicFunctions="true"
-				FavorSizeOrSpeed="1"
+				Optimization="0"
 				AdditionalIncludeDirectories=""
 				AdditionalIncludeDirectories=""
-				PreprocessorDefinitions="NDEBUG, _SCL_SECURE_NO_WARNINGS, _CRT_SECURE_NO_WARNINGS,WIN32"
-				StringPooling="true"
-				BufferSecurityCheck="false"
-				EnableEnhancedInstructionSet="2"
+				PreprocessorDefinitions="DEBUG, _SCL_SECURE_NO_WARNINGS, _CRT_SECURE_NO_WARNINGS,WIN32"
+				BasicRuntimeChecks="3"
+				SmallerTypeCheck="true"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="true"
 				WarningLevel="3"
 				WarningLevel="3"
+				DebugInformationFormat="3"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCManagedResourceCompilerTool"
 				Name="VCManagedResourceCompilerTool"
@@ -141,10 +141,10 @@
 			/>
 			/>
 		</Configuration>
 		</Configuration>
 		<Configuration
 		<Configuration
-			Name="Release_DLL|Win32"
-			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			Name="Release|Win32"
+			OutputDirectory="./../../lib/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
-			ConfigurationType="2"
+			ConfigurationType="4"
 			WholeProgramOptimization="0"
 			WholeProgramOptimization="0"
 			>
 			>
 			<Tool
 			<Tool
@@ -184,15 +184,11 @@
 				Name="VCPreLinkEventTool"
 				Name="VCPreLinkEventTool"
 			/>
 			/>
 			<Tool
 			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)\assimp32.dll"
+				Name="VCLibrarianTool"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCALinkTool"
 				Name="VCALinkTool"
 			/>
 			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
 			<Tool
 			<Tool
 				Name="VCXDCMakeTool"
 				Name="VCXDCMakeTool"
 			/>
 			/>
@@ -202,21 +198,16 @@
 			<Tool
 			<Tool
 				Name="VCFxCopTool"
 				Name="VCFxCopTool"
 			/>
 			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
 			<Tool
 			<Tool
 				Name="VCPostBuildEventTool"
 				Name="VCPostBuildEventTool"
 			/>
 			/>
 		</Configuration>
 		</Configuration>
 		<Configuration
 		<Configuration
-			Name="Debug_DLL|Win32"
-			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			Name="Release|x64"
+			OutputDirectory="./../../lib/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
-			ConfigurationType="2"
+			ConfigurationType="4"
+			WholeProgramOptimization="0"
 			>
 			>
 			<Tool
 			<Tool
 				Name="VCPreBuildEventTool"
 				Name="VCPreBuildEventTool"
@@ -232,18 +223,19 @@
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCMIDLTool"
 				Name="VCMIDLTool"
+				TargetEnvironment="3"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCCLCompilerTool"
 				Name="VCCLCompilerTool"
-				Optimization="0"
+				InlineFunctionExpansion="2"
+				EnableIntrinsicFunctions="true"
+				FavorSizeOrSpeed="1"
 				AdditionalIncludeDirectories=""
 				AdditionalIncludeDirectories=""
-				PreprocessorDefinitions="DEBUG, _SCL_SECURE_NO_WARNINGS, _CRT_SECURE_NO_WARNINGS,WIN32"
-				BasicRuntimeChecks="3"
-				SmallerTypeCheck="true"
-				RuntimeLibrary="1"
-				EnableFunctionLevelLinking="true"
+				PreprocessorDefinitions="NDEBUG, _SCL_SECURE_NO_WARNINGS, _CRT_SECURE_NO_WARNINGS,WIN32"
+				StringPooling="true"
+				BufferSecurityCheck="false"
+				EnableEnhancedInstructionSet="2"
 				WarningLevel="3"
 				WarningLevel="3"
-				DebugInformationFormat="4"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCManagedResourceCompilerTool"
 				Name="VCManagedResourceCompilerTool"
@@ -255,15 +247,11 @@
 				Name="VCPreLinkEventTool"
 				Name="VCPreLinkEventTool"
 			/>
 			/>
 			<Tool
 			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)\assimp32d.dll"
+				Name="VCLibrarianTool"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCALinkTool"
 				Name="VCALinkTool"
 			/>
 			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
 			<Tool
 			<Tool
 				Name="VCXDCMakeTool"
 				Name="VCXDCMakeTool"
 			/>
 			/>
@@ -273,18 +261,12 @@
 			<Tool
 			<Tool
 				Name="VCFxCopTool"
 				Name="VCFxCopTool"
 			/>
 			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
 			<Tool
 			<Tool
 				Name="VCPostBuildEventTool"
 				Name="VCPostBuildEventTool"
 			/>
 			/>
 		</Configuration>
 		</Configuration>
 		<Configuration
 		<Configuration
-			Name="Release_DLL_Java|Win32"
+			Name="Release_DLL|Win32"
 			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			ConfigurationType="2"
 			ConfigurationType="2"
@@ -310,8 +292,8 @@
 				InlineFunctionExpansion="2"
 				InlineFunctionExpansion="2"
 				EnableIntrinsicFunctions="true"
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="1"
 				FavorSizeOrSpeed="1"
-				AdditionalIncludeDirectories="&quot;$(JAVA_HOME)\include&quot;;&quot;$(JAVA_HOME)\include\win32&quot;"
-				PreprocessorDefinitions="NDEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_JNI_EXPORT"
+				AdditionalIncludeDirectories=""
+				PreprocessorDefinitions="NDEBUG, _SCL_SECURE_NO_WARNINGS, _CRT_SECURE_NO_WARNINGS,WIN32"
 				StringPooling="true"
 				StringPooling="true"
 				BufferSecurityCheck="false"
 				BufferSecurityCheck="false"
 				EnableEnhancedInstructionSet="2"
 				EnableEnhancedInstructionSet="2"
@@ -322,14 +304,13 @@
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCResourceCompilerTool"
 				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="ASSIMP_JNI_EXPORT"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCPreLinkEventTool"
 				Name="VCPreLinkEventTool"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCLinkerTool"
 				Name="VCLinkerTool"
-				OutputFile="$(OutDir)\jAssimp32.dll"
+				OutputFile="$(OutDir)\assimp32.dll"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCALinkTool"
 				Name="VCALinkTool"
@@ -357,10 +338,11 @@
 			/>
 			/>
 		</Configuration>
 		</Configuration>
 		<Configuration
 		<Configuration
-			Name="Debug_DLL_Java|Win32"
+			Name="Release_DLL|x64"
 			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			ConfigurationType="2"
 			ConfigurationType="2"
+			WholeProgramOptimization="0"
 			>
 			>
 			<Tool
 			<Tool
 				Name="VCPreBuildEventTool"
 				Name="VCPreBuildEventTool"
@@ -376,32 +358,33 @@
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCMIDLTool"
 				Name="VCMIDLTool"
+				TargetEnvironment="3"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCCLCompilerTool"
 				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="&quot;$(JAVA_HOME)\include&quot;;&quot;$(JAVA_HOME)\include\win32&quot;"
-				PreprocessorDefinitions="DEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_JNI_EXPORT"
-				BasicRuntimeChecks="3"
-				SmallerTypeCheck="true"
-				RuntimeLibrary="1"
-				EnableFunctionLevelLinking="true"
+				InlineFunctionExpansion="2"
+				EnableIntrinsicFunctions="true"
+				FavorSizeOrSpeed="1"
+				AdditionalIncludeDirectories=""
+				PreprocessorDefinitions="NDEBUG, _SCL_SECURE_NO_WARNINGS, _CRT_SECURE_NO_WARNINGS,WIN32"
+				StringPooling="true"
+				BufferSecurityCheck="false"
+				EnableEnhancedInstructionSet="2"
 				WarningLevel="3"
 				WarningLevel="3"
-				DebugInformationFormat="4"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCManagedResourceCompilerTool"
 				Name="VCManagedResourceCompilerTool"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCResourceCompilerTool"
 				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="ASSIMP_JNI_EXPORT"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCPreLinkEventTool"
 				Name="VCPreLinkEventTool"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCLinkerTool"
 				Name="VCLinkerTool"
-				OutputFile="$(OutDir)\jAssimp32d.dll"
+				OutputFile="$(OutDir)\assimp64.dll"
+				TargetMachine="17"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCALinkTool"
 				Name="VCALinkTool"
@@ -429,10 +412,10 @@
 			/>
 			/>
 		</Configuration>
 		</Configuration>
 		<Configuration
 		<Configuration
-			Name="Debug|x64"
-			OutputDirectory="./../../lib/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			Name="Debug_DLL|Win32"
+			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
-			ConfigurationType="4"
+			ConfigurationType="2"
 			>
 			>
 			<Tool
 			<Tool
 				Name="VCPreBuildEventTool"
 				Name="VCPreBuildEventTool"
@@ -448,7 +431,6 @@
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCMIDLTool"
 				Name="VCMIDLTool"
-				TargetEnvironment="3"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCCLCompilerTool"
 				Name="VCCLCompilerTool"
@@ -460,7 +442,7 @@
 				RuntimeLibrary="1"
 				RuntimeLibrary="1"
 				EnableFunctionLevelLinking="true"
 				EnableFunctionLevelLinking="true"
 				WarningLevel="3"
 				WarningLevel="3"
-				DebugInformationFormat="3"
+				DebugInformationFormat="4"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCManagedResourceCompilerTool"
 				Name="VCManagedResourceCompilerTool"
@@ -472,11 +454,15 @@
 				Name="VCPreLinkEventTool"
 				Name="VCPreLinkEventTool"
 			/>
 			/>
 			<Tool
 			<Tool
-				Name="VCLibrarianTool"
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\assimp32d.dll"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCALinkTool"
 				Name="VCALinkTool"
 			/>
 			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
 			<Tool
 			<Tool
 				Name="VCXDCMakeTool"
 				Name="VCXDCMakeTool"
 			/>
 			/>
@@ -486,16 +472,21 @@
 			<Tool
 			<Tool
 				Name="VCFxCopTool"
 				Name="VCFxCopTool"
 			/>
 			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
 			<Tool
 			<Tool
 				Name="VCPostBuildEventTool"
 				Name="VCPostBuildEventTool"
 			/>
 			/>
 		</Configuration>
 		</Configuration>
 		<Configuration
 		<Configuration
-			Name="Release|x64"
-			OutputDirectory="./../../lib/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
+			Name="Debug_DLL|x64"
+			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
-			ConfigurationType="4"
-			WholeProgramOptimization="0"
+			ConfigurationType="2"
 			>
 			>
 			<Tool
 			<Tool
 				Name="VCPreBuildEventTool"
 				Name="VCPreBuildEventTool"
@@ -515,15 +506,15 @@
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCCLCompilerTool"
 				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="2"
-				EnableIntrinsicFunctions="true"
-				FavorSizeOrSpeed="1"
+				Optimization="0"
 				AdditionalIncludeDirectories=""
 				AdditionalIncludeDirectories=""
-				PreprocessorDefinitions="NDEBUG, _SCL_SECURE_NO_WARNINGS, _CRT_SECURE_NO_WARNINGS,WIN32"
-				StringPooling="true"
-				BufferSecurityCheck="false"
-				EnableEnhancedInstructionSet="2"
+				PreprocessorDefinitions="DEBUG, _SCL_SECURE_NO_WARNINGS, _CRT_SECURE_NO_WARNINGS,WIN32"
+				BasicRuntimeChecks="3"
+				SmallerTypeCheck="true"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="true"
 				WarningLevel="3"
 				WarningLevel="3"
+				DebugInformationFormat="3"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCManagedResourceCompilerTool"
 				Name="VCManagedResourceCompilerTool"
@@ -535,11 +526,16 @@
 				Name="VCPreLinkEventTool"
 				Name="VCPreLinkEventTool"
 			/>
 			/>
 			<Tool
 			<Tool
-				Name="VCLibrarianTool"
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)\assimp64d.dll"
+				TargetMachine="17"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCALinkTool"
 				Name="VCALinkTool"
 			/>
 			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
 			<Tool
 			<Tool
 				Name="VCXDCMakeTool"
 				Name="VCXDCMakeTool"
 			/>
 			/>
@@ -549,12 +545,18 @@
 			<Tool
 			<Tool
 				Name="VCFxCopTool"
 				Name="VCFxCopTool"
 			/>
 			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
 			<Tool
 			<Tool
 				Name="VCPostBuildEventTool"
 				Name="VCPostBuildEventTool"
 			/>
 			/>
 		</Configuration>
 		</Configuration>
 		<Configuration
 		<Configuration
-			Name="Release_DLL|x64"
+			Name="Release_DLL_Java|Win32"
 			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			ConfigurationType="2"
 			ConfigurationType="2"
@@ -574,15 +576,14 @@
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCMIDLTool"
 				Name="VCMIDLTool"
-				TargetEnvironment="3"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCCLCompilerTool"
 				Name="VCCLCompilerTool"
 				InlineFunctionExpansion="2"
 				InlineFunctionExpansion="2"
 				EnableIntrinsicFunctions="true"
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="1"
 				FavorSizeOrSpeed="1"
-				AdditionalIncludeDirectories=""
-				PreprocessorDefinitions="NDEBUG, _SCL_SECURE_NO_WARNINGS, _CRT_SECURE_NO_WARNINGS,WIN32"
+				AdditionalIncludeDirectories="&quot;$(JAVA_HOME)\include&quot;;&quot;$(JAVA_HOME)\include\win32&quot;"
+				PreprocessorDefinitions="NDEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_JNI_EXPORT"
 				StringPooling="true"
 				StringPooling="true"
 				BufferSecurityCheck="false"
 				BufferSecurityCheck="false"
 				EnableEnhancedInstructionSet="2"
 				EnableEnhancedInstructionSet="2"
@@ -593,14 +594,14 @@
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCResourceCompilerTool"
 				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="ASSIMP_JNI_EXPORT"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCPreLinkEventTool"
 				Name="VCPreLinkEventTool"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCLinkerTool"
 				Name="VCLinkerTool"
-				OutputFile="$(OutDir)\assimp64.dll"
-				TargetMachine="17"
+				OutputFile="$(OutDir)\jAssimp32.dll"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCALinkTool"
 				Name="VCALinkTool"
@@ -628,10 +629,11 @@
 			/>
 			/>
 		</Configuration>
 		</Configuration>
 		<Configuration
 		<Configuration
-			Name="Debug_DLL|x64"
+			Name="Release_DLL_Java|x64"
 			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			ConfigurationType="2"
 			ConfigurationType="2"
+			WholeProgramOptimization="0"
 			>
 			>
 			<Tool
 			<Tool
 				Name="VCPreBuildEventTool"
 				Name="VCPreBuildEventTool"
@@ -651,28 +653,29 @@
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCCLCompilerTool"
 				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories=""
-				PreprocessorDefinitions="DEBUG, _SCL_SECURE_NO_WARNINGS, _CRT_SECURE_NO_WARNINGS,WIN32"
-				BasicRuntimeChecks="3"
-				SmallerTypeCheck="true"
-				RuntimeLibrary="1"
-				EnableFunctionLevelLinking="true"
+				InlineFunctionExpansion="2"
+				EnableIntrinsicFunctions="true"
+				FavorSizeOrSpeed="1"
+				AdditionalIncludeDirectories="&quot;$(JAVA_HOME)\include&quot;;&quot;$(JAVA_HOME)\include\win32&quot;"
+				PreprocessorDefinitions="NDEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_JNI_EXPORT"
+				StringPooling="true"
+				BufferSecurityCheck="false"
+				EnableEnhancedInstructionSet="2"
 				WarningLevel="3"
 				WarningLevel="3"
-				DebugInformationFormat="3"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCManagedResourceCompilerTool"
 				Name="VCManagedResourceCompilerTool"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCResourceCompilerTool"
 				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="ASSIMP_JNI_EXPORT"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCPreLinkEventTool"
 				Name="VCPreLinkEventTool"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCLinkerTool"
 				Name="VCLinkerTool"
-				OutputFile="$(OutDir)\assimp64d.dll"
+				OutputFile="$(OutDir)\jAssimp64.dll"
 				TargetMachine="17"
 				TargetMachine="17"
 			/>
 			/>
 			<Tool
 			<Tool
@@ -701,11 +704,10 @@
 			/>
 			/>
 		</Configuration>
 		</Configuration>
 		<Configuration
 		<Configuration
-			Name="Release_DLL_Java|x64"
+			Name="Debug_DLL_Java|Win32"
 			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			OutputDirectory="./../../bin/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			IntermediateDirectory="./../../obj/$(ProjectName)_$(ConfigurationName)_$(PlatformName)"
 			ConfigurationType="2"
 			ConfigurationType="2"
-			WholeProgramOptimization="0"
 			>
 			>
 			<Tool
 			<Tool
 				Name="VCPreBuildEventTool"
 				Name="VCPreBuildEventTool"
@@ -721,19 +723,18 @@
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCMIDLTool"
 				Name="VCMIDLTool"
-				TargetEnvironment="3"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCCLCompilerTool"
 				Name="VCCLCompilerTool"
-				InlineFunctionExpansion="2"
-				EnableIntrinsicFunctions="true"
-				FavorSizeOrSpeed="1"
+				Optimization="0"
 				AdditionalIncludeDirectories="&quot;$(JAVA_HOME)\include&quot;;&quot;$(JAVA_HOME)\include\win32&quot;"
 				AdditionalIncludeDirectories="&quot;$(JAVA_HOME)\include&quot;;&quot;$(JAVA_HOME)\include\win32&quot;"
-				PreprocessorDefinitions="NDEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_JNI_EXPORT"
-				StringPooling="true"
-				BufferSecurityCheck="false"
-				EnableEnhancedInstructionSet="2"
+				PreprocessorDefinitions="DEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_JNI_EXPORT"
+				BasicRuntimeChecks="3"
+				SmallerTypeCheck="true"
+				RuntimeLibrary="1"
+				EnableFunctionLevelLinking="true"
 				WarningLevel="3"
 				WarningLevel="3"
+				DebugInformationFormat="4"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCManagedResourceCompilerTool"
 				Name="VCManagedResourceCompilerTool"
@@ -747,8 +748,7 @@
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCLinkerTool"
 				Name="VCLinkerTool"
-				OutputFile="$(OutDir)\jAssimp64.dll"
-				TargetMachine="17"
+				OutputFile="$(OutDir)\jAssimp32d.dll"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCALinkTool"
 				Name="VCALinkTool"
@@ -872,6 +872,10 @@
 				RelativePath="..\..\include\aiMaterial.h"
 				RelativePath="..\..\include\aiMaterial.h"
 				>
 				>
 			</File>
 			</File>
+			<File
+				RelativePath="..\..\include\aiMaterial.inl"
+				>
+			</File>
 			<File
 			<File
 				RelativePath="..\..\include\aiMatrix3x3.h"
 				RelativePath="..\..\include\aiMatrix3x3.h"
 				>
 				>