Explorar o código

Fixed 3DS, ASE, MD3 and Q3D orientation after Schrompf' recent changes to the RH-LH conversion.
WIP version of animation support in the 3DS loader. Still hoping to find out why the pivots aren't handled correctly ...
Added first draft of a B3D loader provided by Mark Sibly.
Moved DeterminePType-Step to ScenePreprocessor.
Small LWO fix. Still texturing problems.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@231 67173fc5-114c-0410-ac8e-9d2fd5bffc1f

aramis_acg %!s(int64=17) %!d(string=hai) anos
pai
achega
7c50899481

+ 118 - 11
code/3DSConverter.cpp

@@ -519,11 +519,13 @@ void Discreet3DSImporter::ConvertMeshes(aiScene* pcOut)
 
 // ------------------------------------------------------------------------------------------------
 // Add a node to the scenegraph and setup its final transformation
-void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn)
+void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn,
+	aiMatrix4x4& absTrafo)
 {
 	std::vector<unsigned int> iArray;
 	iArray.reserve(3);
 
+	aiMatrix4x4 abs;
 	if (pcIn->mName == "$$$DUMMY")
 	{
 		// append the "real" name of the dummy to the string
@@ -542,11 +544,21 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod
 		}
 		if (!iArray.empty())
 		{
+			// The matrix should be identical for all meshes.
+			// It HAS to be identical for all meshes ........
 			aiMatrix4x4& mTrafo = ((D3DS::Mesh*)pcSOut->mMeshes[iArray[0]]->mColors[0])->mMat;
 			aiMatrix4x4 mInv = mTrafo;
 			if (!configSkipPivot)
 				mInv.Inverse();
 
+		/*	abs = mTrafo;
+			pcOut->mTransformation = absTrafo;
+			pcOut->mTransformation = pcOut->mTransformation.Inverse() * mTrafo;
+			const aiVector3D& pivot = pcIn->vPivot;
+			aiMatrix4x4 trans;
+		*/
+			const aiVector3D& pivot = pcIn->vPivot;
+
 			pcOut->mNumMeshes = (unsigned int)iArray.size();
 			pcOut->mMeshes = new unsigned int[iArray.size()];
 			for (unsigned int i = 0;i < iArray.size();++i)
@@ -555,7 +567,6 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod
 				aiMesh* const mesh = pcSOut->mMeshes[iIndex];
 
 				// http://www.zfx.info/DisplayThread.php?MID=235690#235690
-				const aiVector3D& pivot = pcIn->vPivot;
 				const aiVector3D* const pvEnd = mesh->mVertices+mesh->mNumVertices;
 				aiVector3D* pvCurrent = mesh->mVertices;
 
@@ -568,7 +579,6 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod
 						pvCurrent->y -= pivot.y;
 						pvCurrent->z -= pivot.z;
 						*pvCurrent = mTrafo * (*pvCurrent);
-						//std::swap( pvCurrent->y, pvCurrent->z );
 						++pvCurrent;
 					}
 				}
@@ -577,22 +587,81 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod
 				{
 					while (pvCurrent != pvEnd)
 					{
-						std::swap( pvCurrent->y, pvCurrent->z );
+						*pvCurrent = mInv * (*pvCurrent);
 						++pvCurrent;
 					}
 				}
 #endif
+
+				// Setup the mesh index
 				pcOut->mMeshes[i] = iIndex;
 			}
 		}
 	}
 
+	// Generate animation channels for the node
+	if (pcIn->aPositionKeys.size()  > 0  || pcIn->aRotationKeys.size()   > 0   ||
+		pcIn->aScalingKeys.size()   > 0  || pcIn->aCameraRollKeys.size() > 0 ||
+		pcIn->aTargetPositionKeys.size() > 0)
+	{
+		aiAnimation* anim = pcSOut->mAnimations[0];
+		ai_assert(NULL != anim);
+
+		// Allocate a new channel, increment the channel index
+		aiNodeAnim* channel = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
+
+		// POSITION keys
+		if (pcIn->aPositionKeys.size()  > 0)
+		{
+			// Sort all keys with ascending time values
+			std::sort(pcIn->aPositionKeys.begin(),pcIn->aPositionKeys.end());
+
+			channel->mNumPositionKeys = (unsigned int)pcIn->aPositionKeys.size();
+			channel->mPositionKeys = new aiVectorKey[channel->mNumPositionKeys];
+			::memcpy(channel->mPositionKeys,&pcIn->aPositionKeys[0],
+				sizeof(aiVectorKey)*channel->mNumPositionKeys);
+
+			// Get the maximum key
+			anim->mDuration = std::max(anim->mDuration,channel->
+				mPositionKeys[channel->mNumPositionKeys-1].mTime);
+		}
+
+		// ROTATION keys
+		if (pcIn->aRotationKeys.size()  > 0)
+		{
+			// Sort all keys with ascending time values
+			std::sort(pcIn->aRotationKeys.begin(),pcIn->aRotationKeys.end());
+
+			channel->mNumRotationKeys = (unsigned int)pcIn->aRotationKeys.size();
+			channel->mRotationKeys = new aiQuatKey[channel->mNumRotationKeys];
+			::memcpy(channel->mRotationKeys,&pcIn->aRotationKeys[0],
+				sizeof(aiQuatKey)*channel->mNumRotationKeys);
+
+			// Get the maximum key
+			anim->mDuration = std::max(anim->mDuration,channel->
+				mRotationKeys[channel->mNumRotationKeys-1].mTime);
+		}
+
+		// SCALING keys
+		if (pcIn->aScalingKeys.size()  > 0)
+		{
+			// Sort all keys with ascending time values
+			std::sort(pcIn->aScalingKeys.begin(),pcIn->aScalingKeys.end());
+
+			channel->mNumScalingKeys = (unsigned int)pcIn->aScalingKeys.size();
+			channel->mScalingKeys = new aiVectorKey[channel->mNumScalingKeys];
+			::memcpy(channel->mScalingKeys,&pcIn->aScalingKeys[0],
+				sizeof(aiVectorKey)*channel->mNumScalingKeys);
+
+			// Get the maximum key
+			anim->mDuration = std::max(anim->mDuration,channel->
+				mScalingKeys[channel->mNumScalingKeys-1].mTime);
+		}
+	}
+
 	// Setup the name of the node
 	pcOut->mName.Set(pcIn->mName);
 
-	// Setup the transformation matrix of the node
-	pcOut->mTransformation = aiMatrix4x4(); 
-
 	// Allocate storage for children
 	pcOut->mNumChildren = (unsigned int)pcIn->mChildren.size();
 	pcOut->mChildren = new aiNode*[pcIn->mChildren.size()];
@@ -602,11 +671,30 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Nod
 	{
 		pcOut->mChildren[i] = new aiNode();
 		pcOut->mChildren[i]->mParent = pcOut;
-		AddNodeToGraph(pcSOut,pcOut->mChildren[i],pcIn->mChildren[i]);
+		AddNodeToGraph(pcSOut,pcOut->mChildren[i],pcIn->mChildren[i],abs);
 	}
 	return;
 }
 
+// ------------------------------------------------------------------------------------------------
+// Find out how many node animation channels we'll have finally
+void CountTracks(D3DS::Node* node, unsigned int& cnt)
+{
+	// We will never generate more than one channel for a node, so
+	// this is rather easy here.
+
+	if (node->aPositionKeys.size()  > 0  || node->aRotationKeys.size()   > 0   ||
+		node->aScalingKeys.size()   > 0  || node->aCameraRollKeys.size() > 0 ||
+		node->aTargetPositionKeys.size()  > 0)
+	{
+		++cnt;
+	}
+
+	// Recursively process all children
+	for (unsigned int i = 0; i < node->mChildren.size();++i)
+		CountTracks(node->mChildren[i],cnt);
+}
+
 // ------------------------------------------------------------------------------------------------
 // Generate the output node graph
 void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut)
@@ -670,9 +758,26 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut)
 	{
 		// First of all: find out how many scaling, rotation and translation
 		// animation tracks we'll have afterwards
-		//unsigned int numRot = 0, numScale = 0, numTranslate = 0;
-		//CountTracks(mRootNode,numRot,numScale,numTranslate);
-		AddNodeToGraph(pcOut,  pcOut->mRootNode, mRootNode);
+		unsigned int numChannel = 0;
+		CountTracks(mRootNode,numChannel);
+
+		if (numChannel)
+		{
+			// Allocate a primary animation channel
+			pcOut->mNumAnimations = 1;
+			pcOut->mAnimations    = new aiAnimation*[1];
+			aiAnimation* anim     = pcOut->mAnimations[0] = new aiAnimation();
+
+			anim->mName.Set("3DSMasterAnim");
+
+			// Allocate enough storage for all node animation channels, 
+			// but don't set the mNumChannels member - we'll use it to
+			// index into the array
+			anim->mChannels = new aiNodeAnim*[numChannel];
+		}
+
+		aiMatrix4x4 m;
+		AddNodeToGraph(pcOut,  pcOut->mRootNode, mRootNode,m);
 	}
 
 	// We used the first vertex color set to store some
@@ -694,11 +799,13 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut)
 	if (pcOut->mRootNode->mName.data[0] == '$' && pcOut->mRootNode->mName.data[1] == '$')
 		pcOut->mRootNode->mName.Set("<root>");
 
+#if 0
 	// modify the transformation of the root node to change
 	// the coordinate system of the whole scene from Max' to OpenGL
 	pcOut->mRootNode->mTransformation.a3 *= -1.f;
 	pcOut->mRootNode->mTransformation.b3 *= -1.f;
 	pcOut->mRootNode->mTransformation.c3 *= -1.f;
+#endif
 }
 
 // ------------------------------------------------------------------------------------------------

+ 6 - 3
code/3DSLoader.cpp

@@ -566,11 +566,14 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
 		// (target animation channels are stored with a
 		//  separate object ID)
 		D3DS::Node* pcNode = FindNode(mRootNode,name);
-		if (!pcNode)
+		if (pcNode)
 		{
-			pcNode = new D3DS::Node();
-			pcNode->mName = name;
+			// Make this node the current node
+			mCurrentNode = pcNode;
+			break;	
 		}
+		pcNode = new D3DS::Node();
+		pcNode->mName = name;
 
 		// There are two unknown values which we can safely ignore
 		stream->IncPtr(4);

+ 2 - 1
code/3DSLoader.h

@@ -219,7 +219,8 @@ protected:
 	// -------------------------------------------------------------------
 	/** Add a node to the node graph
 	*/
-	void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn);
+	void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn,
+		aiMatrix4x4& absTrafo);
 
 	// -------------------------------------------------------------------
 	/** Search for a node in the graph.

+ 10 - 7
code/ASELoader.cpp

@@ -556,12 +556,15 @@ void ASEImporter::AddNodes (std::vector<BaseNode*>& nodes,
 
 	// allocate enough space for the child nodes
 	pcParent->mNumChildren = (unsigned int)apcNodes.size();
-	pcParent->mChildren = new aiNode*[apcNodes.size()];
-
-	// now build all nodes for our nice new children
-	for (unsigned int p = 0; p < apcNodes.size();++p)
+	if (pcParent->mNumChildren)
 	{
-		pcParent->mChildren[p] = apcNodes[p];
+		pcParent->mChildren = new aiNode*[apcNodes.size()];
+
+		// now build all nodes for our nice new children
+		for (unsigned int p = 0; p < apcNodes.size();++p)
+		{
+			pcParent->mChildren[p] = apcNodes[p];
+		}
 	}
 	return;
 }
@@ -578,7 +581,7 @@ void ASEImporter::BuildNodes()
 	pcScene->mRootNode->mName.Set("<root>");
 
 	// Setup the coordinate system transformation
-	pcScene->mRootNode->mTransformation.c3 *= -1.f;
+	//pcScene->mRootNode->mTransformation.c3 *= -1.f;
 	pcScene->mRootNode->mNumChildren = 1;
 	pcScene->mRootNode->mChildren = new aiNode*[1];
 	pcScene->mRootNode->mChildren[0] = new aiNode();
@@ -744,7 +747,7 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
 				if (!mesh.amTexCoords[c].empty())
 				{
 					amTexCoords[c][iCurrent] = mesh.amTexCoords[c][(*i).amUVIndices[c][n]];
-					amTexCoords[c][iCurrent].y = 1.0f - amTexCoords[c][iCurrent].y; // DX-to-OGL
+					// amTexCoords[c][iCurrent].y = 1.f- amTexCoords[c][iCurrent].y; // DX-to-OGL
 				}
 			}
 			// add vertex colors

+ 377 - 0
code/B3DImporter.cpp

@@ -0,0 +1,377 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Implementation of the b3d importer class */
+
+#include "AssimpPCH.h"
+
+// internal headers
+#include "B3DImporter.h"
+#include "TextureTransform.h"
+
+using namespace Assimp;
+using namespace std;
+
+bool B3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const{
+
+	int pos=pFile.find_last_of( '.' );
+	if( pos==string::npos ) return false;
+
+	string ext=pFile.substr( pos+1 );
+	if( ext.size()!=3 ) return false;
+
+	return (ext[0]=='b' || ext[0]=='B') && (ext[1]=='3') && (ext[2]=='d' || ext[2]=='D');
+}
+
+void B3DImporter::GetExtensionList( std::string& append ){
+	append.append("*.b3d");
+}
+
+void B3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler){
+
+	boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
+
+	// Check whether we can read from the file
+	if( file.get() == NULL)
+		throw new ImportErrorException( "Failed to open B3D file " + pFile + ".");
+
+	// check whether the .b3d file is large enough to contain
+	// at least one chunk.
+	size_t fileSize = file->FileSize();
+	if( fileSize < 8) throw new ImportErrorException( "B3D File is too small.");
+
+	_pos=0;
+	_buf.resize( fileSize );
+	file->Read( &_buf[0],1,fileSize );
+	_stack.clear();
+	_textures.clear();
+	_materials.size();
+	_vertices.clear();
+	_meshes.clear();
+
+	ReadBB3D();
+
+	//materials
+	aiMaterial **mats=new aiMaterial*[_materials.size()];
+	for( unsigned i=0;i<_materials.size();++i ){
+		mats[i]=_materials[i];
+	}
+	pScene->mNumMaterials=_materials.size();
+	pScene->mMaterials=mats;
+
+	//meshes
+	aiMesh **meshes=new aiMesh*[_meshes.size()];
+	for( unsigned i=0;i<_meshes.size();++i ){
+		meshes[i]=_meshes[i];
+	}
+	pScene->mNumMeshes=_meshes.size();
+	pScene->mMeshes=meshes;
+
+	//nodes - NOTE: Have to create mMeshes array here or crash 'n' burn.
+	aiNode *node=new aiNode( "root" );
+	node->mNumMeshes=_meshes.size();
+	node->mMeshes=new unsigned[_meshes.size()];
+	for( unsigned i=0;i<_meshes.size();++i ){
+		node->mMeshes[i]=i;
+	}
+	pScene->mRootNode=node;
+}
+
+int B3DImporter::ReadByte(){
+	if( _pos<_buf.size() ) return _buf[_pos++];
+	throw new ImportErrorException( "B3D EOF Error" );
+}
+
+int B3DImporter::ReadInt(){
+	if( _pos+4<=_buf.size() ){
+		int n=*(int*)&_buf[_pos];
+		_pos+=4;
+		return n;
+	}
+	throw new ImportErrorException( "B3D EOF Error" );
+}
+
+float B3DImporter::ReadFloat(){
+	if( _pos+4<=_buf.size() ){
+		float n=*(float*)&_buf[_pos];
+		_pos+=4;
+		return n;
+	}
+	throw new ImportErrorException( "B3D EOF Error" );
+}
+
+B3DImporter::Vec2 B3DImporter::ReadVec2(){
+	Vec2 t;
+	t.x=ReadFloat();
+	t.y=ReadFloat();
+	return t;
+}
+
+B3DImporter::Vec3 B3DImporter::ReadVec3(){
+	Vec3 t;
+	t.x=ReadFloat();
+	t.y=ReadFloat();
+	t.z=ReadFloat();
+	return t;
+}
+
+B3DImporter::Vec4 B3DImporter::ReadVec4(){
+	Vec4 t;
+	t.x=ReadFloat();
+	t.y=ReadFloat();
+	t.z=ReadFloat();
+	t.w=ReadFloat();
+	return t;
+}
+
+string B3DImporter::ReadString(){
+	string str;
+	while( _pos<_buf.size() ){
+		char c=(char)ReadByte();
+		if( !c ) return str;
+		str+=c;
+	}
+	throw new ImportErrorException( "B3D EOF Error" );
+}
+
+string B3DImporter::ReadChunk(){
+	string tag;
+	for( int i=0;i<4;++i ){
+		tag+=char( ReadByte() );
+	}
+//	cout<<"ReadChunk:"<<tag<<endl;
+	unsigned sz=(unsigned)ReadInt();
+	_stack.push_back( _pos+sz );
+	return tag;
+}
+
+void B3DImporter::ExitChunk(){
+	_pos=_stack.back();
+	_stack.pop_back();
+}
+
+unsigned B3DImporter::ChunkSize(){
+	return _stack.back()-_pos;
+}
+
+void B3DImporter::ReadTEXS(){
+	while( ChunkSize() ){
+		string name=ReadString();
+		int flags=ReadInt();
+		int blend=ReadInt();
+		Vec2 pos=ReadVec2();
+		Vec2 scale=ReadVec2();
+		float rot=ReadFloat();
+
+		Texture tex;
+		tex.name=name;
+		_textures.push_back( tex );
+	}
+}
+
+void B3DImporter::ReadBRUS(){
+	int n_texs=ReadInt();
+	while( ChunkSize() ){
+		string name=ReadString();
+		Vec4 color=ReadVec4();
+		float shiny=ReadFloat();
+		int blend=ReadInt();
+		int fx=ReadInt();
+
+		MaterialHelper *mat=new MaterialHelper;
+		_materials.push_back( mat );
+
+		for( int i=0;i<n_texs;++i ){
+			int texid=ReadInt();
+			if( !i ){
+				//just use tex 0 for now
+				const Texture &tex=_textures[texid];
+
+				aiString texstr;
+				texstr.Set( tex.name );
+				mat->AddProperty( &texstr,AI_MATKEY_TEXTURE_DIFFUSE(0) );
+			}
+		}
+	}
+}
+
+void B3DImporter::ReadVRTS(){
+	int vertFlags=ReadInt();
+	int tc_sets=ReadInt();
+	int tc_size=ReadInt();
+
+	if( tc_sets<0 || tc_sets>4 || tc_size<0 || tc_size>4 ) throw new ImportErrorException( "B3D Param Error" );
+
+	while( ChunkSize() ){
+		Vertex vert;
+
+		vert.position=ReadVec3();
+
+		if( vertFlags & 1 ){
+			vert.normal=ReadVec3();
+		}
+
+		if( vertFlags & 2 ){
+			Vec4 color=ReadVec4();
+		}
+
+		for( int i=0;i<tc_sets;++i ){
+			float texcoords[4]={0,0,0,0};
+			for( int j=0;j<tc_size;++j ){
+				texcoords[j]=ReadFloat();
+			}
+			if( !i ) memcpy( &vert.texcoords.x,texcoords,12 );
+		}
+		_vertices.push_back( vert );
+	}
+}
+
+void B3DImporter::ReadTRIS(){
+	int matid=ReadInt();
+
+	for( vector<Vertex>::iterator it=_vertices.begin();it!=_vertices.end();++it ){
+		it->index=-1;
+	}
+
+	vector<int> verts,tris;
+
+	while( ChunkSize() ){
+		int i=ReadInt();
+		Vertex &vert=_vertices[i];
+		if( vert.index==-1 ){
+			vert.index=verts.size();
+			verts.push_back( i );
+		}
+		tris.push_back( vert.index );
+	}
+
+	if( verts.empty() || tris.empty() ) return;
+
+	unsigned n_verts=verts.size();
+	unsigned n_tris=tris.size()/3;
+
+	//OK, we have a whole mesh...
+	aiVector3D *mv=new aiVector3D[n_verts];
+	aiVector3D *mn=new aiVector3D[n_verts];
+	aiVector3D *mc=new aiVector3D[n_verts];
+	for( unsigned i=0;i<n_verts;++i ){
+		Vertex &v=_vertices[verts[i]];
+		memcpy( &mv[i].x,&v.position.x,12 );
+		memcpy( &mn[i].x,&v.normal.x,12 );
+		memcpy( &mc[i].x,&v.texcoords.x,12 );
+	}
+
+	aiFace *faces=new aiFace[n_tris];
+	for( unsigned i=0;i<n_tris;++i ){
+		faces[i].mNumIndices=3;
+		unsigned *ip=faces[i].mIndices=new unsigned[3];
+		ip[0]=tris[i*3];
+		ip[1]=tris[i*3+1];
+		ip[2]=tris[i*3+2];
+	}
+
+	aiMesh *mesh=new aiMesh;
+
+	mesh->mMaterialIndex=matid;
+
+	mesh->mNumVertices=n_verts;
+	mesh->mVertices=mv;
+	mesh->mNormals=mn;
+	mesh->mTextureCoords[0]=mc;
+
+	mesh->mNumFaces=n_tris;
+	mesh->mFaces=faces;
+
+	_meshes.push_back( mesh );
+}
+
+void B3DImporter::ReadMESH(){
+	int matid=ReadInt();
+
+	_vertices.clear();
+
+	while( ChunkSize() ){
+		string t=ReadChunk();
+		if( t=="VRTS" ){
+			ReadVRTS();
+		}else if( t=="TRIS" ){
+			ReadTRIS();
+		}
+		ExitChunk();
+	}
+
+	_vertices.clear();
+}
+
+void B3DImporter::ReadNODE(){
+
+	string name=ReadString();
+	Vec3 trans=ReadVec3();
+	Vec3 scale=ReadVec3();
+	Vec4 rot=ReadVec4();
+
+	while( ChunkSize() ){
+		string t=ReadChunk();
+		if( t=="MESH" ){
+			ReadMESH();
+		}
+		ExitChunk();
+	}
+}
+
+void B3DImporter::ReadBB3D(){
+	string t=ReadChunk();
+	if( t=="BB3D" ){
+		int version=ReadInt();
+		while( ChunkSize() ){
+			string t=ReadChunk();
+			if( t=="TEXS" ){
+				ReadTEXS();
+			}else if( t=="BRUS" ){
+				ReadBRUS();
+			}else if( t=="NODE" ){
+				ReadNODE();
+			}
+			ExitChunk();
+		}
+	}
+	ExitChunk();
+}

+ 106 - 0
code/B3DImporter.h

@@ -0,0 +1,106 @@
+
+/*
+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 Definition of the .b3d importer class. */
+
+#ifndef AI_B3DIMPORTER_H_INC
+#define AI_B3DIMPORTER_H_INC
+
+#include "../include/aiTypes.h"
+#include "../include/aiMesh.h"
+#include "../include/aiMaterial.h"
+
+#include <string>
+#include <vector>
+
+namespace Assimp{
+
+class B3DImporter : public BaseImporter{
+public:
+
+	virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
+
+protected:
+
+	virtual void GetExtensionList(std::string& append);
+	virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+
+private:
+
+	struct Vec2{ float x,y; };
+	struct Vec3{ float x,y,z; };
+	struct Vec4{ float x,y,z,w; };
+	struct Texture{ std::string name; };
+	struct Vertex{ int index;Vec3 position,normal,texcoords; };
+
+	int ReadByte();
+	int ReadInt();
+	float ReadFloat();
+	Vec2 ReadVec2();
+	Vec3 ReadVec3();
+	Vec4 ReadVec4();
+	std::string ReadString();
+	std::string ReadChunk();
+	void ExitChunk();
+	unsigned ChunkSize();
+
+	void ReadTEXS();
+	void ReadBRUS();
+	void ReadVRTS();
+	void ReadTRIS();
+	void ReadMESH();
+	void ReadNODE();
+	void ReadBB3D();
+
+	unsigned _pos;
+	unsigned _size;
+	std::vector<unsigned char> _buf;
+	std::vector<unsigned> _stack;
+
+	std::vector<Texture> _textures;
+	std::vector<MaterialHelper*> _materials;
+	std::vector<Vertex> _vertices;
+	std::vector<aiMesh*> _meshes;
+};
+
+}
+
+#endif

+ 23 - 0
code/IRRLoader.cpp

@@ -130,6 +130,29 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
 				break;
 			}
 			attach.push_back(AttachmentInfo(scene,rootOut));
+
+			// now combine the material we've loaded for this mesh
+			// with the real meshes we got from the file. As we
+			// don't execute any pp-steps on the file, the numbers
+			// should be equal. If they are not, we can impossibly
+			// do this  ...
+			if (root->materials.size() != (unsigned int)scene->mNumMaterials)
+			{
+				DefaultLogger::get()->warn("IRR: Failed to match imported materials "
+					"with the materials found in the IRR scene file");
+
+				break;
+			}
+			for (unsigned int i = 0; i < scene->mNumMaterials;++i)
+			{
+				// delete the old material
+				delete scene->mMaterials[i];
+
+				std::pair<aiMaterial*, unsigned int>& src = root->materials[i];
+				scene->mMaterials[i] = src.first;
+
+				// Process material flags (e.g. lightmapping)
+			}
 		}
 		break;
 	

+ 20 - 2
code/IRRMeshLoader.cpp

@@ -455,6 +455,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
 	int textMeaning = 0;
 	int vertexFormat = 0; // 0 = normal; 1 = 2 tcoords, 2 = tangents
 	bool useColors = false;
+	bool needLightMap = false;
 
 	// Parse the XML file
 	while (reader->read())
@@ -752,7 +753,12 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
 					mat->AddProperty(&curColors[0].a,1,AI_MATKEY_OPACITY);
 				}
 
-				/* TODO: Add lightmapping support here */
+				// store the material flags for later use
+				curMesh->mNumUVComponents[3] = curMatFlags;
+				if ( curMatFlags & AI_IRRMESH_MAT_lightmap )
+				{
+					needLightMap = true;
+				}
 			}}
 			break;
 
@@ -783,10 +789,22 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
 	if (materials.empty())
 		throw new ImportErrorException("IRRMESH: Unable to read a mesh from this file");
 
+	if(needLightMap)
+	{
+		// Compute light map UV coordinates
+//		ComputeLightMapUVCoordinates(meshes,materials);
+	}
+
 	// now generate the output scene
 	pScene->mNumMeshes = (unsigned int)meshes.size();
 	pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
-	::memcpy(pScene->mMeshes,&meshes[0],sizeof(void*)*pScene->mNumMeshes);
+	for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+	{
+		pScene->mMeshes[i] = meshes[i];
+
+		// clean this value ...
+		pScene->mMeshes[i]->mNumUVComponents[3] = 0;
+	}
 
 	pScene->mNumMaterials = (unsigned int)materials.size();
 	pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];

+ 8 - 9
code/Importer.cpp

@@ -126,6 +126,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_BUILD_NO_Q3D_IMPORTER
 #	include "Q3DLoader.h"
 #endif
+#ifndef AI_BUILD_NO_B3D_IMPORTER
+#	include "B3DImporter.h"
+#endif
 
 
 // PostProcess-Steps
@@ -180,14 +183,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_BUILD_NO_FINDDEGENERATES_PROCESS
 #	include "FindDegenerates.h"
 #endif
-
-// NOTE: the preprocessor code has been moved to the header as
-// we've also declared the DeterminePType process in it, which
-// can't be removed.
-
-//#ifndef AI_BUILD_NO_SORTBYPTYPE_PROCESS
+#ifndef AI_BUILD_NO_SORTBYPTYPE_PROCESS
 #	include "SortByPTypeProcess.h"
-//#endif
+#endif
 
 using namespace Assimp;
 
@@ -282,6 +280,9 @@ Importer::Importer() :
 #if (!defined AI_BUILD_NO_Q3D_IMPORTER)
 	mImporter.push_back( new Q3DImporter());
 #endif
+#if (!defined AI_BUILD_NO_B3D_IMPORTER)
+	mImporter.push_back( new B3DImporter());
+#endif
 
 	// add an instance of each post processing step here in the order 
 	// of sequence it is executed. steps that are added here are not validated -
@@ -292,8 +293,6 @@ Importer::Importer() :
 	mPostProcessingSteps.push_back( new ValidateDSProcess()); 
 #endif
 
-	mPostProcessingSteps.push_back( new DeterminePTypeHelperProcess());
-
 
 #if (!defined AI_BUILD_NO_FINDDEGENERATES_PROCESS)
 	mPostProcessingSteps.push_back( new FindDegeneratesProcess());

+ 5 - 1
code/LWOLoader.cpp

@@ -143,6 +143,8 @@ void LWOImporter::InternReadFile( const std::string& pFile,
 	// old lightwave file format (prior to v6)
 	if (AI_LWO_FOURCC_LWOB == fileType)
 	{
+		DefaultLogger::get()->info("LWO file format: LWOB (<= LightWave 5.5)");
+
 		mIsLWO2 = false;
 		this->LoadLWOBFile();
 	}
@@ -150,6 +152,8 @@ void LWOImporter::InternReadFile( const std::string& pFile,
 	// new lightwave format
 	else if (AI_LWO_FOURCC_LWO2 == fileType)
 	{
+		DefaultLogger::get()->info("LWO file format: LWO2 (>= LightWave 6)");
+
 		mIsLWO2 = true;
 		this->LoadLWO2File();
 	}
@@ -307,7 +311,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
 							aiVector3D*& pp = pvUV[w];
 							const aiVector2D& src = ((aiVector2D*)&layer.mUVChannels[vUVChannelIndices[w]].rawData[0])[idx];
 							pp->x = src.x;
-							pp->y = 1.f-src.y; // DX to OGL
+							pp->y = src.y; // DX to OGL
 							pp++;
 						}
 

+ 2 - 2
code/MD3Loader.cpp

@@ -297,14 +297,14 @@ void MD3Importer::InternReadFile(
 			{
 				// read vertices
 				pcMesh->mVertices[iCurrent].x = pcVertices[ pcTriangles->INDEXES[c]].X*AI_MD3_XYZ_SCALE;
-				pcMesh->mVertices[iCurrent].y = pcVertices[ pcTriangles->INDEXES[c]].Y*-1.0f*AI_MD3_XYZ_SCALE;
+				pcMesh->mVertices[iCurrent].y = pcVertices[ pcTriangles->INDEXES[c]].Y*AI_MD3_XYZ_SCALE;
 				pcMesh->mVertices[iCurrent].z = pcVertices[ pcTriangles->INDEXES[c]].Z*AI_MD3_XYZ_SCALE;
 
 				// convert the normal vector to uncompressed float3 format
 				LatLngNormalToVec3(pcVertices[pcTriangles->INDEXES[c]].NORMAL,
 					(float*)&pcMesh->mNormals[iCurrent]);
 
-				pcMesh->mNormals[iCurrent].y *= -1.0f;
+				//pcMesh->mNormals[iCurrent].y *= -1.0f;
 
 				// read texture coordinates
 				pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[ pcTriangles->INDEXES[c]].U;

+ 2 - 2
code/Q3DLoader.cpp

@@ -562,11 +562,11 @@ outer:
 	for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
 		pScene->mRootNode->mMeshes[i] = i;
 
-	pScene->mRootNode->mTransformation *= aiMatrix4x4(
+	/*pScene->mRootNode->mTransformation *= aiMatrix4x4(
 		1.f, 0.f, 0.f, 0.f,
 	    0.f, -1.f,0.f, 0.f,
 		0.f, 0.f, 1.f, 0.f,
-		0.f, 0.f, 0.f, 1.f);
+		0.f, 0.f, 0.f, 1.f);*/
 
 	// Add cameras and light sources to the scene root node
 	pScene->mRootNode->mNumChildren = pScene->mNumLights+pScene->mNumCameras;

+ 35 - 1
code/ScenePreprocessor.cpp

@@ -48,7 +48,10 @@ void ScenePreprocessor::ProcessScene (aiScene* _scene)
 {
 	scene = _scene;
 
-	// - nothing to do for meshes for the moment
+	// Process all meshes
+	for (unsigned int i = 0; i < scene->mNumMeshes;++i)
+		ProcessMesh(scene->mMeshes[i]);
+
 	// - nothing to do for materials for the moment
 	// - nothing to do for nodes for the moment
 	// - nothing to do for textures for the moment
@@ -60,6 +63,37 @@ void ScenePreprocessor::ProcessScene (aiScene* _scene)
 		ProcessAnimation(scene->mAnimations[i]);
 }
 
+// ---------------------------------------------------------------------------
+void ScenePreprocessor::ProcessMesh (aiMesh* mesh)
+{
+	// If the information which primitive types are there in the
+	// mesh is currently not available, compute it.
+	if (!mesh->mPrimitiveTypes)
+	{
+		for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
+		{
+			aiFace& face = mesh->mFaces[a];
+			switch (face.mNumIndices)
+			{
+			case 3u:
+				mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+				break;
+
+			case 2u:
+				mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
+				break;
+
+			case 1u:
+				mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
+				break;
+
+			default:
+				mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+				break;
+			}
+		}
+	}
+}
 
 // ---------------------------------------------------------------------------
 void ScenePreprocessor::ProcessAnimation (aiAnimation* anim)

+ 1 - 0
code/ScenePreprocessor.h

@@ -64,6 +64,7 @@ public:
 protected:
 
 	void ProcessAnimation (aiAnimation* anim);
+	void ProcessMesh (aiMesh* mesh);
 
 protected:
 

+ 0 - 58
code/SortByPTypeProcess.cpp

@@ -51,64 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by Importer
-DeterminePTypeHelperProcess ::DeterminePTypeHelperProcess()
-{
-}
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-DeterminePTypeHelperProcess::~DeterminePTypeHelperProcess()
-{
-	// nothing to do here
-}
-
-// ------------------------------------------------------------------------------------------------
-// Returns whether the processing step is present in the given flag field.
-bool DeterminePTypeHelperProcess::IsActive( unsigned int pFlags) const
-{
-	// this step is always active
-	return	true;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Executes the post processing step on the given imported data.
-void DeterminePTypeHelperProcess::Execute( aiScene* pScene)
-{
-	DefaultLogger::get()->debug("DeterminePTypeHelper begin");
-	for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
-	{
-		aiMesh* mesh = pScene->mMeshes[i];
-		if (!mesh->mPrimitiveTypes)
-		{
-			for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
-			{
-				aiFace& face = mesh->mFaces[a];
-				switch (face.mNumIndices)
-				{
-				case 3u:
-					mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
-					break;
-
-				case 2u:
-					mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
-					break;
-
-				case 1u:
-					mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
-					break;
-
-				default:
-					mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
-					break;
-				}
-			}
-		}
-	}
-	DefaultLogger::get()->debug("DeterminePTypeHelper finished");
-}
-
 
 
 // ------------------------------------------------------------------------------------------------

+ 0 - 30
code/SortByPTypeProcess.h

@@ -50,35 +50,6 @@ class SortByPTypeProcessTest;
 namespace Assimp	{
 
 
-// ---------------------------------------------------------------------------
-/** DeterminePTypeHelperProcess: If aiMesh::mPrimitiveTypes is 0,
- *  this step determines the types of primitive a mesh consists of.
-*/
-class ASSIMP_API DeterminePTypeHelperProcess : public BaseProcess
-{
-	friend class Importer;
-	friend class ::SortByPTypeProcessTest; // grant the unit test full access to us
-
-protected:
-	/** Constructor to be privately used by Importer */
-	DeterminePTypeHelperProcess();
-
-	/** Destructor, private as well */
-	~DeterminePTypeHelperProcess();
-
-public:
-	// -------------------------------------------------------------------
-	bool IsActive( unsigned int pFlags) const;
-
-	// -------------------------------------------------------------------
-	void Execute( aiScene* pScene);
-
-private:
-
-};
-
-#if (!defined AI_BUILD_NO_SORTBYPTYPE_PROCESS)
-
 // ---------------------------------------------------------------------------
 /** SortByPTypeProcess: Sorts meshes by the types of primitives they contain.
  *  A mesh with 5 lines, 3 points and 145 triangles would be split in 3 
@@ -111,7 +82,6 @@ private:
 	int configRemoveMeshes;
 };
 
-#endif 
 
 } // end of namespace Assimp
 

+ 2 - 1
code/makefile

@@ -72,7 +72,8 @@ SOURCES = AssimpPCH.cpp \
 	IRRMeshLoader.cpp \
 	IRRLoader.cpp \
 	Q3DLoader.cpp \
-	ScenePreprocessor.cpp
+	ScenePreprocessor.cpp \
+	B3DImporter.cpp
 
 OBJECTS = $(SOURCES:.cpp=.o)
 

+ 3 - 1
code/makefile.mingw

@@ -72,7 +72,9 @@ SOURCES = AssimpPCH.cpp \
 	IRRMeshLoader.cpp \
 	IRRLoader.cpp \
 	Q3DLoader.cpp \
-	ScenePreprocessor.cpp
+	ScenePreprocessor.cpp \
+	B3DImporter.cpp
+	
 
 OBJECTS = $(SOURCES:.cpp=.o)
 

+ 12 - 0
workspaces/vc8/assimp.vcproj

@@ -1402,6 +1402,18 @@
 						>
 					</File>
 				</Filter>
+				<Filter
+					Name="B3D"
+					>
+					<File
+						RelativePath="..\..\code\B3DImporter.cpp"
+						>
+					</File>
+					<File
+						RelativePath="..\..\code\B3DImporter.h"
+						>
+					</File>
+				</Filter>
 			</Filter>
 			<Filter
 				Name="PostProcess"