Browse Source

- Fixed a bug in FindInvalidData causing some animation channels to be lost
- Added Q3D loader. Seems to work quite well with Quick 3D 4.0
- Updated makefile, fixed GCC compilation error cause of packed matrix fields

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

aramis_acg 17 years ago
parent
commit
daae32d62f

+ 8 - 1
code/3DSConverter.cpp

@@ -666,7 +666,14 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut)
 			pcNode->mName = mScene->mLights[i]->mName;
 		}
 	}
-	else AddNodeToGraph(pcOut,  pcOut->mRootNode, mRootNode);
+	else
+	{
+		// 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);
+	}
 
 	// We used the first vertex color set to store some
 	// temporary values, so we need to cleanup here

+ 4 - 4
code/FindInvalidDataProcess.cpp

@@ -273,14 +273,14 @@ int FindInvalidDataProcess::ProcessAnimation (aiAnimation* anim)
 int FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim)
 {
 	// TODO: (thom) For some reason, even proper channels are deleted as well. Therefore deactivated it for the moment.
-	return 0;
+	//return 0;
 
 	int i = 0;
 
 	// Check whether all values are identical or whether there is just one keyframe
-	if ((1 >= anim->mNumPositionKeys || AllIdentical(anim->mPositionKeys,anim->mNumPositionKeys)) &&
-		(1 >= anim->mNumScalingKeys  || AllIdentical(anim->mRotationKeys,anim->mNumRotationKeys)) &&
-		(1 >= anim->mNumRotationKeys || AllIdentical(anim->mScalingKeys,anim->mNumScalingKeys)))
+	if ((anim->mNumPositionKeys < 1 || AllIdentical(anim->mPositionKeys,anim->mNumPositionKeys)) &&
+		(anim->mNumScalingKeys  < 1  || AllIdentical(anim->mRotationKeys,anim->mNumRotationKeys)) &&
+		(anim->mNumRotationKeys < 1 || AllIdentical(anim->mScalingKeys,anim->mNumScalingKeys)))
 	{
 		DefaultLogger::get()->error("Deleting dummy position animation channel");
 		return 1;

+ 6 - 6
code/Importer.cpp

@@ -122,9 +122,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_BUILD_NO_IRR_IMPORTER
 #	include "IRRLoader.h"
 #endif
-//#ifndef AI_BUILD_NO_Q3D_IMPORTER
-//#	include "Q3DLoader.h"
-//#endif
+#ifndef AI_BUILD_NO_Q3D_IMPORTER
+#	include "Q3DLoader.h"
+#endif
 
 
 // PostProcess-Steps
@@ -278,9 +278,9 @@ Importer::Importer() :
 #if (!defined AI_BUILD_NO_IRR_IMPORTER)
 	mImporter.push_back( new IRRImporter());
 #endif
-//#if (!defined AI_BUILD_NO_Q3D_IMPORTER)
-//	mImporter.push_back( new Q3DImporter());
-//#endif
+#if (!defined AI_BUILD_NO_Q3D_IMPORTER)
+	mImporter.push_back( new Q3DImporter());
+#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 -

+ 2 - 2
code/MD2FileData.h

@@ -144,8 +144,8 @@ struct Frame
  */
 struct TexCoord
 {
-	int16_t s;
-	int16_t t;
+	uint16_t s;
+	uint16_t t;
 } PACK_STRUCT;
 
 // ---------------------------------------------------------------------------

+ 1 - 1
code/MD2Loader.cpp

@@ -414,7 +414,7 @@ void MD2Importer::InternReadFile( const std::string& pFile,
 				// the texture coordinates are absolute values but we
 				// need relative values between 0 and 1
 				pcOut.x = pcTexCoords[iIndex].s / fDivisorU;
-				pcOut.y = 1.f- pcTexCoords[iIndex].t / fDivisorV;
+				pcOut.y = 1.f - pcTexCoords[iIndex].t / fDivisorV;
 			}
 		}
 		// FIX: flip the face order for use with OpenGL

+ 577 - 0
code/Q3DLoader.cpp

@@ -0,0 +1,577 @@
+/*
+---------------------------------------------------------------------------
+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 Q3D importer class */
+
+#include "AssimpPCH.h"
+
+// internal headers
+#include "Q3DLoader.h"
+#include "StreamReader.h"
+#include "fast_atof.h"
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor to be privately used by Importer
+Q3DImporter::Q3DImporter()
+{
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor, private as well 
+Q3DImporter::~Q3DImporter()
+{
+}
+
+// ------------------------------------------------------------------------------------------------
+// Returns whether the class can handle the format of the given file. 
+bool Q3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
+{
+	// simple check of file extension is enough for the moment
+	std::string::size_type pos = pFile.find_last_of('.');
+	// no file extension - can't read
+	if( pos == std::string::npos)return false;
+
+	std::string extension = pFile.substr( pos);
+	for (std::string::iterator it = extension.begin();
+		it != extension.end(); ++it)
+		*it = ::tolower(*it);
+
+	return (extension == ".q3o" || extension == ".q3s"); 
+}
+
+// ------------------------------------------------------------------------------------------------
+// Imports the given file into the given scene structure. 
+void Q3DImporter::InternReadFile( const std::string& pFile, 
+	aiScene* pScene, IOSystem* pIOHandler)
+{
+	StreamReaderLE stream(pIOHandler->Open(pFile,"rb"));
+
+	// The header is 22 bytes large
+	if (stream.GetRemainingSize() < 22)
+		throw new ImportErrorException("File is either empty or corrupt: " + pFile);
+
+	// Check the file signature
+	if (ASSIMP_strincmp( (const char*)stream.GetPtr(), "quick3Do", 8 ) &&
+		ASSIMP_strincmp( (const char*)stream.GetPtr(), "quick3Ds", 8 ))
+	{
+		throw new ImportErrorException("No Quick3D file. Signature is: " + 
+			std::string((const char*)stream.GetPtr(),8));
+	}
+
+	// Print the file format version
+	DefaultLogger::get()->info("Quick3D File format version: " + 
+		std::string(&((const char*)stream.GetPtr())[8],2));
+
+	// ... an store it
+	unsigned int ff = strtol10(&((const char*)stream.GetPtr())[8]);
+
+	stream.IncPtr(10);
+	unsigned int numMeshes    = (unsigned int)stream.GetI4();
+	unsigned int numMats      = (unsigned int)stream.GetI4();
+	unsigned int numTextures  = (unsigned int)stream.GetI4();
+
+	std::vector<Material> materials;
+	materials.reserve(numMats);
+
+	std::vector<Mesh> meshes;
+	meshes.reserve(numMeshes);
+
+	// Allocate the scene root node
+	pScene->mRootNode = new aiNode();
+
+	aiColor3D fgColor (0.6f,0.6f,0.6f);
+
+	// Now read all file chunks
+	while (true)
+	{
+		if (stream.GetRemainingSize() < 1)break;
+		char c = stream.GetI1();
+		switch (c)
+		{
+			// Meshes chunk
+		case 'm':
+			{
+				for (unsigned int quak = 0; quak < numMeshes; ++quak)
+				{
+					meshes.push_back(Mesh());
+					Mesh& mesh = meshes.back();
+
+					// read all vertices
+					unsigned int numVerts = (unsigned int)stream.GetI4();
+					if (!numVerts)
+						throw new ImportErrorException("Quick3D: Found mesh with zero vertices");
+
+					std::vector<aiVector3D>& verts = mesh.verts;
+					verts.resize(numVerts);
+
+					for (unsigned int i = 0; i < numVerts;++i)
+					{
+						verts[i].x = stream.GetF4();
+						verts[i].y = stream.GetF4();
+						verts[i].z = stream.GetF4();
+					}
+
+					// read all faces
+					numVerts = (unsigned int)stream.GetI4();
+					if (!numVerts)
+						throw new ImportErrorException("Quick3D: Found mesh with zero faces");
+
+					std::vector<Face >& faces = mesh.faces;
+					faces.reserve(numVerts);
+
+					// number of indices
+					for (unsigned int i = 0; i < numVerts;++i)
+					{
+						faces.push_back(Face(stream.GetI2()) );
+						if (faces.back().indices.empty())
+							throw new ImportErrorException("Quick3D: Found face with zero indices");
+					}
+
+					// indices
+					for (unsigned int i = 0; i < numVerts;++i)
+					{
+						Face& vec = faces[i];
+						for (unsigned int a = 0; a < (unsigned int)vec.indices.size();++a)
+							vec.indices[a] = stream.GetI4();
+					}
+
+					// material indices
+					for (unsigned int i = 0; i < numVerts;++i)
+					{
+						faces[i].mat = (unsigned int)stream.GetI4();
+					}
+
+					// read all normals
+					numVerts = (unsigned int)stream.GetI4();
+					std::vector<aiVector3D>& normals = mesh.normals;
+					normals.resize(numVerts);
+
+					for (unsigned int i = 0; i < numVerts;++i)
+					{
+						normals[i].x = stream.GetF4();
+						normals[i].y = stream.GetF4();
+						normals[i].z = stream.GetF4();
+					}
+
+					if (numTextures)
+					{
+						// read all texture coordinates
+						numVerts = (unsigned int)stream.GetI4();
+						std::vector<aiVector3D>& uv = mesh.uv;
+						uv.resize(numVerts);
+
+						for (unsigned int i = 0; i < numVerts;++i)
+						{
+							uv[i].x = stream.GetF4();
+							uv[i].y = stream.GetF4();
+						}
+
+						// UV indices
+						for (unsigned int i = 0; i < (unsigned int)faces.size();++i)
+						{
+							Face& vec = faces[i];
+							for (unsigned int a = 0; a < (unsigned int)vec.indices.size();++a)
+							{
+								vec.indices[a] = stream.GetI4();
+								if (!i && !a)
+									mesh.prevUVIdx = vec.indices[a];
+								else if (vec.indices[a] != mesh.prevUVIdx)
+									mesh.prevUVIdx = 0xffffffff;
+							}
+						}
+					}
+
+					// we don't need the rest, but we need to get to the next chunk
+					stream.IncPtr(36 + ((ff > 30 ? 12 : 0 )));
+				}
+				stream.IncPtr(4 + (ff > 30 ?  24 : 0 )); // unknown value here
+			}
+			break;
+
+			// materials chunk 
+		case 'c':
+
+			for (unsigned int i = 0; i < numMats; ++i)
+			{
+				materials.push_back(Material());
+				Material& mat = materials.back();
+
+				// read the material name
+				while (( c = stream.GetI1()))
+					mat.name.data[mat.name.length++] = c;
+				
+				// add the terminal character
+				mat.name.data[mat.name.length] = '\0';
+
+				// read the ambient color
+				mat.ambient.r = stream.GetF4();
+				mat.ambient.g = stream.GetF4();
+				mat.ambient.b = stream.GetF4();
+
+				// read the diffuse color
+				mat.diffuse.r = stream.GetF4();
+				mat.diffuse.g = stream.GetF4();
+				mat.diffuse.b = stream.GetF4();
+
+				// read the ambient color
+				mat.specular.r = stream.GetF4();
+				mat.specular.g = stream.GetF4();
+				mat.specular.b = stream.GetF4();
+
+				// read the transparency
+				mat.transparency = stream.GetF4();
+
+				// unknown value here
+				stream.IncPtr(4);
+			}
+
+			break;
+
+			// texture chunk
+		case 't':
+
+			pScene->mNumTextures = numTextures;
+			if (!numTextures)break;
+			pScene->mTextures    = new aiTexture*[pScene->mNumTextures];
+			// to make sure we won't crash if we leave through an exception
+			::memset(pScene->mTextures,0,sizeof(void*)*pScene->mNumTextures);
+			for (unsigned int i = 0; i < pScene->mNumTextures; ++i)
+			{
+				aiTexture* tex = pScene->mTextures[i] = new aiTexture();
+
+				// skip the texture name
+				while (stream.GetI1());
+
+				// read texture width and height
+				tex->mWidth  = (unsigned int)stream.GetI4();
+				tex->mHeight = (unsigned int)stream.GetI4();
+
+				if (!tex->mWidth || !tex->mHeight)
+					throw new ImportErrorException("Quick3D: Invalid texture. Width or height is zero");
+
+				register unsigned int mul = tex->mWidth * tex->mHeight;
+				aiTexel* begin = tex->pcData = new aiTexel[mul];
+				aiTexel* const end = & begin [mul];
+
+				for (;begin != end; ++begin)
+				{
+					begin->r = stream.GetI1();
+					begin->g = stream.GetI1();
+					begin->b = stream.GetI1();
+					begin->a = 0xff;
+				}
+			}
+
+			break;
+
+			// scene chunk
+		case 's':
+			{
+				// skip position and rotation
+				stream.IncPtr(12);
+
+				for (unsigned int i = 0; i < 4;++i)
+					for (unsigned int a = 0; a < 4;++a)
+						pScene->mRootNode->mTransformation[i][a] = stream.GetF4();
+				
+				stream.IncPtr(16);
+
+				// now setup a single camera
+				pScene->mNumCameras = 1;
+				pScene->mCameras = new aiCamera*[1];
+				aiCamera* cam = pScene->mCameras[0] = new aiCamera();
+				cam->mPosition.x = stream.GetF4();
+				cam->mPosition.y = stream.GetF4();
+				cam->mPosition.z = stream.GetF4();
+				cam->mName.Set("Q3DCamera");
+
+				// skip eye rotation for the moment
+				stream.IncPtr(12);
+
+				// read the default material color
+				fgColor .r = stream.GetF4();
+				fgColor .g = stream.GetF4();
+				fgColor .b = stream.GetF4();
+
+				// skip some unimportant properties
+				stream.IncPtr(29);
+
+				// setup a single point light with no attenuation
+				pScene->mNumLights = 1;
+				pScene->mLights = new aiLight*[1];
+				aiLight* light = pScene->mLights[0] = new aiLight();
+				light->mName.Set("Q3DLight");
+				light->mType = aiLightSource_POINT;
+
+				light->mAttenuationConstant  = 1;
+				light->mAttenuationLinear    = 0;
+				light->mAttenuationQuadratic = 0;
+
+				light->mColorDiffuse.r = stream.GetF4();
+				light->mColorDiffuse.g = stream.GetF4();
+				light->mColorDiffuse.b = stream.GetF4();
+
+				light->mColorSpecular = light->mColorDiffuse;
+
+
+				// We don't need the rest, but we need to know where
+				// this fucking chunk ends.
+				unsigned int temp = (unsigned int)(stream.GetI4() * stream.GetI4());
+
+				// skip the background file name
+				while (stream.GetI1());
+
+				// skip background texture data + the remaining fields 
+				stream.IncPtr(temp*3 + 20); // 4 bytes of unknown data here
+
+				// TODO
+				goto outer;
+			}
+			break;
+
+		default:
+			throw new ImportErrorException("Quick3D: Unknown chunk");
+			break;
+		};
+	}
+outer:
+
+	// If we have no mesh loaded - break here
+	if (meshes.empty())
+		throw new ImportErrorException("Quick3D: No meshes loaded");
+
+	// If we have no materials loaded - generate a default mat
+	if (materials.empty())
+	{
+		DefaultLogger::get()->info("Quick3D: No material found, generating one");
+		materials.push_back(Material());
+		materials.back().diffuse  = fgColor ;
+	}
+
+	// find out which materials we'll need
+	typedef std::pair<unsigned int, unsigned int> FaceIdx;
+	typedef std::vector< FaceIdx > FaceIdxArray;
+	FaceIdxArray* fidx = new FaceIdxArray[materials.size()]; 
+
+	unsigned int p = 0;
+	for (std::vector<Mesh>::iterator it = meshes.begin(), end = meshes.end();
+		 it != end; ++it,++p)
+	{
+		unsigned int q = 0;
+		for (std::vector<Face>::iterator fit = (*it).faces.begin(), fend = (*it).faces.end();
+			 fit != fend; ++fit,++q)
+		{
+			if ((*fit).mat >= materials.size())
+			{
+				DefaultLogger::get()->warn("Quick3D: Material index overflow");
+				(*fit).mat = 0;
+			}
+			if (fidx[(*fit).mat].empty())++pScene->mNumMeshes;
+			fidx[(*fit).mat].push_back( FaceIdx(p,q) );
+		}
+	}
+	pScene->mNumMaterials = pScene->mNumMeshes;
+	pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+	pScene->mMeshes = new aiMesh*[pScene->mNumMaterials];
+
+	for (unsigned int i = 0, real = 0; i < (unsigned int)materials.size(); ++i)
+	{
+		if (fidx[i].empty())continue;
+
+		// Allocate a mesh and a material
+		aiMesh* mesh = pScene->mMeshes[real] = new aiMesh();
+		MaterialHelper* mat = new MaterialHelper();
+		pScene->mMaterials[real] = mat;
+
+		mesh->mMaterialIndex = real;
+
+		// Build the output material
+		Material& srcMat = materials[i];
+		mat->AddProperty(&srcMat.diffuse,  1,AI_MATKEY_COLOR_DIFFUSE);
+		mat->AddProperty(&srcMat.specular, 1,AI_MATKEY_COLOR_SPECULAR);
+		mat->AddProperty(&srcMat.ambient,  1,AI_MATKEY_COLOR_AMBIENT);
+		
+		//srcMat.transparency = 1.0f - srcMat.transparency;
+		mat->AddProperty(&srcMat.transparency, 1, AI_MATKEY_OPACITY);
+
+		// add shininess - Quick3D seems to use it ins its viewer
+		srcMat.transparency = 16.f;
+		mat->AddProperty(&srcMat.transparency, 1, AI_MATKEY_SHININESS);
+
+		int m = (int)aiShadingMode_Phong;
+		mat->AddProperty(&m, 1, AI_MATKEY_SHADING_MODEL);
+
+		if (srcMat.name.length)
+			mat->AddProperty(&srcMat.name,AI_MATKEY_NAME);
+
+		// Add a texture
+		if (real < pScene->mNumTextures)
+		{
+			srcMat.name.data[0] = '*';
+			srcMat.name.length  = itoa10(&srcMat.name.data[1],1000,real);
+			mat->AddProperty(&srcMat.name,AI_MATKEY_TEXTURE_DIFFUSE(0));
+		}
+
+		mesh->mNumFaces = (unsigned int)fidx[i].size();
+		aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
+
+		// Now build the output mesh. First find out how many
+		// vertices we'll need
+		for (FaceIdxArray::const_iterator it = fidx[i].begin(),end = fidx[i].end();
+			 it != end; ++it)
+		{
+			mesh->mNumVertices += (unsigned int)meshes[(*it).first].faces[
+				(*it).second].indices.size();
+		}
+
+		aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+		aiVector3D* norms = mesh->mNormals  = new aiVector3D[mesh->mNumVertices];
+		aiVector3D* uv;
+		if (real < pScene->mNumTextures)
+		{
+			uv = mesh->mTextureCoords[0] =  new aiVector3D[mesh->mNumVertices];
+			mesh->mNumUVComponents[0]    =  2;
+		}
+		else uv = NULL;
+
+		// Build the final array
+		unsigned int cnt = 0;
+		for (FaceIdxArray::const_iterator it = fidx[i].begin(),end = fidx[i].end();
+			 it != end; ++it, ++faces)
+		{
+			Mesh& m    = meshes[(*it).first];
+			Face& face = m.faces[(*it).second];
+			faces->mNumIndices = (unsigned int)face.indices.size();
+			faces->mIndices = new unsigned int [faces->mNumIndices]; 
+
+
+			aiVector3D faceNormal;
+			bool fnOK = false;
+
+			for (unsigned int n = 0; n < faces->mNumIndices;++n, ++cnt, ++norms, ++verts)
+			{
+				if (face.indices[n] >= m.verts.size())
+				{
+					DefaultLogger::get()->warn("Quick3D: Vertex index overflow");
+					face.indices[n] = 0;
+				}
+
+				// copy vertices
+				*verts =  m.verts[ face.indices[n] ];
+
+				if (face.indices[n] >= m.normals.size() && faces->mNumIndices >= 3)
+				{
+					// we have no normal here - assign the face normal
+					if (!fnOK)
+					{
+						const aiVector3D& pV1 =  m.verts[ face.indices[0] ];
+						const aiVector3D& pV2 =  m.verts[ face.indices[1] ];
+						const aiVector3D& pV3 =  m.verts[ face.indices.size() - 1 ];
+						faceNormal = (pV2 - pV1) ^ (pV3 - pV1).Normalize();
+						fnOK = true;
+					}
+					*norms = faceNormal;
+				}
+				else *norms =  m.normals[ face.indices[n] ];
+
+				// copy texture coordinates
+				if (uv)
+				{
+					if (m.prevUVIdx != 0xffffffff && m.uv.size() >= m.verts.size()) // workaround
+					{
+						*uv++ = m.uv[face.indices[n]];
+					}
+					else
+					{
+						if (face.uvindices[n] >= m.uv.size())
+						{
+							DefaultLogger::get()->warn("Quick3D: Texture coordinate index overflow");
+							face.uvindices[n] = 0;
+						}
+						*uv++ = m.uv[face.uvindices[n]];
+					}
+				}
+
+				// setup the new vertex index
+				faces->mIndices[n] = cnt;
+			}
+
+		}
+		++real;
+	}
+
+	// Delete our nice helper array
+	delete[] fidx;
+
+	// Now we need to attach the meshes to the root node of the scene
+	pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
+	pScene->mRootNode->mMeshes = new unsigned int [pScene->mNumMeshes];
+	for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+		pScene->mRootNode->mMeshes[i] = i;
+
+	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);
+
+	// Add cameras and light sources to the scene root node
+	pScene->mRootNode->mNumChildren = pScene->mNumLights+pScene->mNumCameras;
+	if (pScene->mRootNode->mNumChildren)
+	{
+		pScene->mRootNode->mChildren = new aiNode* [ pScene->mRootNode->mNumChildren ];
+
+		// the light source
+		aiNode* nd = pScene->mRootNode->mChildren[0] = new aiNode();
+		nd->mParent = pScene->mRootNode;
+		nd->mName.Set("Q3DLight");
+		nd->mTransformation = pScene->mRootNode->mTransformation;
+		nd->mTransformation.Inverse();
+
+		// camera
+		nd = pScene->mRootNode->mChildren[1] = new aiNode();
+		nd->mParent = pScene->mRootNode;
+		nd->mName.Set("Q3DCamera");
+		nd->mTransformation = pScene->mRootNode->mChildren[0]->mTransformation;
+	}
+}

+ 132 - 0
code/Q3DLoader.h

@@ -0,0 +1,132 @@
+/*
+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 Declaration of the Q3D importer class. */
+#ifndef AI_Q3DLOADER_H_INCLUDED
+#define AI_Q3DLOADER_H_INCLUDED
+
+#include "BaseImporter.h"
+#include "../include/aiTypes.h"
+#include <vector>
+
+namespace Assimp	{
+
+// ---------------------------------------------------------------------------
+/** Importer class for the Quick3D Object and Scene formats.
+*/
+class Q3DImporter : public BaseImporter
+{
+	friend class Importer;
+
+protected:
+	/** Constructor to be privately used by Importer */
+	Q3DImporter();
+
+	/** Destructor, private as well */
+	~Q3DImporter();
+
+public:
+
+	// -------------------------------------------------------------------
+	/** Returns whether the class can handle the format of the given file. 
+	* See BaseImporter::CanRead() for details.	*/
+	bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const;
+
+protected:
+
+	// -------------------------------------------------------------------
+	/** Called by Importer::GetExtensionList() for each loaded importer.
+	 * See BaseImporter::GetExtensionList() for details
+	 */
+	void GetExtensionList(std::string& append)
+	{
+		append.append("*.q3o;*.q3s");
+	}
+
+	// -------------------------------------------------------------------
+	/** Imports the given file into the given scene structure. 
+	* See BaseImporter::InternReadFile() for details
+	*/
+	void InternReadFile( const std::string& pFile, aiScene* pScene, 
+		IOSystem* pIOHandler);
+
+private:
+
+	struct Material
+	{
+		Material()
+			:	diffuse			(0.6f,0.6f,0.6f)
+			,	transparency	(0.f)
+		{}
+
+		aiString name;
+		aiColor3D ambient, diffuse, specular;
+		float transparency;
+	};
+
+	struct Face
+	{
+		Face(unsigned int s)
+			:	indices	  (s)
+			,	uvindices (s)
+			,	mat		  (0)
+		{
+		}
+
+		std::vector<unsigned int> indices;
+		std::vector<unsigned int> uvindices;
+		unsigned int mat;
+	};
+
+	struct Mesh
+	{
+
+		std::vector<aiVector3D> verts;
+		std::vector<aiVector3D> normals;
+		std::vector<aiVector3D> uv;
+		std::vector<Face>       faces;
+
+		uint32_t prevUVIdx;
+	};
+};
+
+} // end of namespace Assimp
+
+#endif // AI_Q3DIMPORTER_H_IN

+ 6 - 0
code/ValidateDataStructure.cpp

@@ -735,6 +735,12 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
 		};
 	}
 
+	if (AI_SUCCESS == aiGetMaterialFloat( pMaterial,AI_MATKEY_OPACITY,&fTemp))
+	{
+		if (!fTemp)
+			ReportWarning("Material is fully transparent ... are you sure you REALLY want this?");
+	}
+
 	// check whether there are invalid texture keys
 	SearchForInvalidTextures(pMaterial,"diffuse");
 	SearchForInvalidTextures(pMaterial,"specular");

+ 2 - 1
code/makefile

@@ -70,7 +70,8 @@ SOURCES = AssimpPCH.cpp \
 	XFileParser.cpp \
 	./irrXML/irrXML.cpp \
 	IRRMeshLoader.cpp \
-	IRRLoader.cpp
+	IRRLoader.cpp \
+	Q3DLoader.cpp
 
 OBJECTS = $(SOURCES:.cpp=.o)
 

+ 2 - 1
code/makefile.mingw

@@ -70,7 +70,8 @@ SOURCES = AssimpPCH.cpp \
 	BVHLoader.cpp \
 	./irrXML/irrXML.cpp \
 	IRRMeshLoader.cpp \
-	IRRLoader.cpp
+	IRRLoader.cpp \
+	Q3DLoader.cpp
 
 OBJECTS = $(SOURCES:.cpp=.o)
 

+ 4 - 3
include/aiMatrix3x3.inl

@@ -44,9 +44,10 @@ inline aiMatrix3x3 aiMatrix3x3::operator* (const aiMatrix3x3& m) const
 // ------------------------------------------------------------------------------------------------
 inline aiMatrix3x3& aiMatrix3x3::Transpose()
 {
-	std::swap( a2, b1);
-	std::swap( a3, c1);
-	std::swap( b3, c2);
+	// (float&) don't remove, GCC complains cause of packed fields
+	std::swap( (float&)a2, (float&)b1);
+	std::swap( (float&)a3, (float&)c1);
+	std::swap( (float&)b3, (float&)c2);
 	return *this;
 }
 

+ 7 - 6
include/aiMatrix4x4.inl

@@ -58,12 +58,13 @@ inline aiMatrix4x4 aiMatrix4x4::operator* (const aiMatrix4x4& m) const
 // ---------------------------------------------------------------------------
 inline aiMatrix4x4& aiMatrix4x4::Transpose()
 {
-	std::swap( b1, a2);
-	std::swap( c1, a3);
-	std::swap( c2, b3);
-	std::swap( d1, a4);
-	std::swap( d2, b4);
-	std::swap( d3, c4);
+	// (float&) don't remove, GCC complains cause of packed fields
+	std::swap( (float&)b1, (float&)a2);
+	std::swap( (float&)c1, (float&)a3);
+	std::swap( (float&)c2, (float&)b3);
+	std::swap( (float&)d1, (float&)a4);
+	std::swap( (float&)d2, (float&)b4);
+	std::swap( (float&)d3, (float&)c4);
 	return *this;
 }
 

+ 9 - 1
workspaces/vc8/assimp.vcproj

@@ -1385,6 +1385,14 @@
 				<Filter
 					Name="Q3D"
 					>
+					<File
+						RelativePath="..\..\code\Q3DLoader.cpp"
+						>
+					</File>
+					<File
+						RelativePath="..\..\code\Q3DLoader.h"
+						>
+					</File>
 				</Filter>
 			</Filter>
 			<Filter
@@ -1631,7 +1639,7 @@
 						<Tool
 							Name="VCCLCompilerTool"
 							BasicRuntimeChecks="0"
-							SmallerTypeCheck="false"
+							SmallerTypeCheck="true"
 							UsePrecompiledHeader="0"
 						/>
 					</FileConfiguration>