Ver Fonte

Small fix to the ASE loader - workaround for bitmaps with filename "None".
Further work on the IRR loader. Still work in progress.
Fixed a minor issue in StandardShapes.
Fixed a bug in the Q3D loader causing models without textures to load incorrectly.

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

aramis_acg há 17 anos atrás
pai
commit
240dbfd864

+ 12 - 0
code/ASEParser.cpp

@@ -587,7 +587,10 @@ void Parser::ParseLV3MapBlock(Texture& map)
 				if(!ParseString(temp,"*MAP_CLASS"))
 					SkipToNextToken();
 				if (temp != "Bitmap")
+				{
+					DefaultLogger::get()->warn("ASE: Skipping unknown map type: " + temp);
 					parsePath = false; 
+				}
 				continue;
 			}
 			// path to the texture
@@ -595,6 +598,15 @@ void Parser::ParseLV3MapBlock(Texture& map)
 			{
 				if(!ParseString(map.mMapName,"*BITMAP"))
 					SkipToNextToken();
+
+				if (map.mMapName == "None")
+				{
+					// Files with 'None' as map name are produced by
+					// an Maja to ASE exporter which name I forgot ..
+					DefaultLogger::get()->warn("ASE: Skipping invalid map entry");
+					map.mMapName = "";
+				}
+
 				continue;
 			}
 			// offset on the u axis

+ 1 - 1
code/FindInvalidDataProcess.cpp

@@ -208,7 +208,7 @@ inline bool ProcessArray(T*& in, unsigned int num,const char* name,
 template <typename T>
 inline bool AllIdentical(T* in, unsigned int num)
 {
-	if (!num)return true;
+	if (num <= 1)return true;
 	for (unsigned int i = 0; i < num-1;++i)
 	{
 		if (in[i] != in[i+1])return false;

+ 175 - 10
code/IRRLoader.cpp

@@ -102,6 +102,129 @@ bool IRRImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
 	return false;
 }
 
+// ------------------------------------------------------------------------------------------------
+void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
+	BatchLoader& batch,
+	std::vector<aiMesh*>&        meshes,
+	std::vector<aiNodeAnim*>&    anims,
+	std::vector<AttachmentInfo>& attach)
+{
+	// Setup the name of this node
+	rootOut->mName.Set(root->name);
+
+	unsigned int oldMeshSize = (unsigned int)meshes.size();
+
+	// Now determine the type of the node 
+	switch (root->type)
+	{
+	case Node::ANIMMESH:
+	case Node::MESH:
+		{
+			// get the loaded mesh from the scene and add it to
+			// the list of all scenes to be attached to the 
+			// graph we're currently building
+			aiScene* scene = batch.GetImport(root->meshPath);
+			if (!scene)
+			{
+				DefaultLogger::get()->error("IRR: Unable to load external file: " + root->meshPath);
+				break;
+			}
+			attach.push_back(AttachmentInfo(scene,rootOut));
+		}
+		break;
+	
+	case Node::LIGHT:
+	case Node::CAMERA:
+
+		// We're already finished with lights and cameras
+		break;
+
+
+	case Node::SPHERE:
+		{
+			// generate the sphere model. Our input parameter to
+			// the sphere generation algorithm is the number of
+			// subdivisions of each triangle - but here we have
+			// the number of poylgons on a specific axis. Just
+			// use some limits ...
+			unsigned int mul = root->spherePolyCountX*root->spherePolyCountY;
+			if      (mul < 100)mul = 2;
+			else if (mul < 300)mul = 3;
+			else               mul = 4;
+
+			meshes.push_back(StandardShapes::MakeMesh(mul,&StandardShapes::MakeSphere));
+
+			// Adjust scaling
+			root->scaling *= root->sphereRadius;
+		}
+		break;
+
+	case Node::CUBE:
+	case Node::SKYBOX:
+		{
+			// Skyboxes and normal cubes - generate the cube first
+			meshes.push_back(StandardShapes::MakeMesh(&StandardShapes::MakeHexahedron));
+
+			// Adjust scaling
+			root->scaling *= root->sphereRadius;
+		}
+		break;
+
+	case Node::TERRAIN:
+		{
+		}
+		break;
+	};
+
+	// Check whether we added a mesh. In this case we'll also
+	// need to attach it to the node
+	if (oldMeshSize != (unsigned int) meshes.size())
+	{
+		rootOut->mNumMeshes = 1;
+		rootOut->mMeshes    = new unsigned int[1];
+		rootOut->mMeshes[0] = oldMeshSize;
+	}
+
+	// Now compute the final local transformation matrix of the
+	// node from the given translation, rotation and scaling values.
+	// (the rotation is given in Euler angles, XYZ order)
+	aiMatrix4x4 m;
+	rootOut->mTransformation = aiMatrix4x4::RotationX(AI_DEG_TO_RAD(root->rotation.x),m)
+		* aiMatrix4x4::RotationY(AI_DEG_TO_RAD(root->rotation.y),m)
+		* aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(root->rotation.z),m);
+
+	// apply scaling
+	aiMatrix4x4& mat = rootOut->mTransformation;
+	mat.a1 *= root->scaling.x;
+	mat.b1 *= root->scaling.x; 
+	mat.c1 *= root->scaling.x;
+	mat.a2 *= root->scaling.y; 
+	mat.b2 *= root->scaling.y; 
+	mat.c2 *= root->scaling.y;
+	mat.a3 *= root->scaling.z;
+	mat.b3 *= root->scaling.z; 
+	mat.c3 *= root->scaling.z;
+
+	// apply translation
+	mat.a4 = root->position.x; 
+	mat.b4 = root->position.y; 
+	mat.c4 = root->position.z;
+
+	// Add all children recursively. First allocate enough storage
+	// for them, then call us again
+	rootOut->mNumChildren = (unsigned int)root->children.size();
+	if (rootOut->mNumChildren)
+	{
+		rootOut->mChildren = new aiNode*[rootOut->mNumChildren];
+		for (unsigned int i = 0; i < rootOut->mNumChildren;++i)
+		{
+			aiNode* node = rootOut->mChildren[i] =  new aiNode();
+			node->mParent = rootOut;
+			GenerateGraph(root->children[i],node,scene,batch,meshes,anims,attach);
+		}
+	}
+}
+
 // ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure. 
 void IRRImporter::InternReadFile( const std::string& pFile, 
@@ -133,7 +256,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
 	// List of output lights
 	std::vector<aiLight*> lights;
 
-
+	// Batch loader used to load external models
 	BatchLoader batch(pIOHandler);
 	
 	cameras.reserve(5);
@@ -391,6 +514,10 @@ void IRRImporter::InternReadFile( const std::string& pFile,
 								{
 									curAnim->circleRadius = prop.value;
 								}
+								else if (curAnim->type == Animator::FOLLOW_SPLINE && prop.name == "Tightness")
+								{
+									curAnim->tightness = prop.value;
+								}
 							}
 							else
 							{
@@ -439,13 +566,12 @@ void IRRImporter::InternReadFile( const std::string& pFile,
 										lights.back()->mAngleInnerCone =  AI_DEG_TO_RAD( prop.value );
 									}
 								}
-								// radius of the sphere to be generated
-								else if (Node::SPHERE == curNode->type)
+								// radius of the sphere to be generated -
+								// or alternatively, size of the cube
+								else if (Node::SPHERE == curNode->type && prop.name == "Radius" ||
+										 Node::CUBE == curNode->type   && prop.name == "Size" )
 								{
-									if (prop.name == "Radius")
-									{
-										curNode->sphereRadius = prop.value;
-									}
+									curNode->sphereRadius = prop.value;
 								}
 							}
 						}
@@ -524,6 +650,34 @@ void IRRImporter::InternReadFile( const std::string& pFile,
 									}
 
 									batch.AddLoadRequest(prop.value,pp,&map);
+									curNode->meshPath = prop.value;
+								}
+								else if (inAnimator && prop.name == "Type")
+								{
+									// type of the animator
+									if (prop.value == "rotation")
+									{
+										curAnim->type = Animator::ROTATION;
+									}
+									else if (prop.value == "flyCircle")
+									{
+										curAnim->type = Animator::FLY_CIRCLE;
+									}
+									else if (prop.value == "flyStraight")
+									{
+										curAnim->type = Animator::FLY_CIRCLE;
+									}
+									else if (prop.value == "followSpline")
+									{
+										curAnim->type = Animator::FOLLOW_SPLINE;
+									}
+									else
+									{
+										DefaultLogger::get()->warn("IRR: Ignoring unknown animator: "
+											+ prop.value);
+
+										curAnim->type = Animator::UNKNOWN;
+									}
 								}
 							}
 						}
@@ -603,7 +757,6 @@ void IRRImporter::InternReadFile( const std::string& pFile,
 	tempScene->mLights = new aiLight*[tempScene->mNumLights];
 	::memcpy(tempScene->mLights,&lights[0],sizeof(void*)*tempScene->mNumLights);
 
-
 	// temporary data
 	std::vector< aiNodeAnim*> anims;
 	std::vector< AttachmentInfo > attach;
@@ -615,8 +768,8 @@ void IRRImporter::InternReadFile( const std::string& pFile,
 	/* Now process our scenegraph recursively: generate final
 	 * meshes and generate animation channels for all nodes.
 	 */
-//	GenerateGraph(root,tempScene->mRootNode, tempScene,
-//		batch, meshes, anims, attach);
+	GenerateGraph(root,tempScene->mRootNode, tempScene,
+		batch, meshes, anims, attach);
 
 	if (!anims.empty())
 	{
@@ -644,9 +797,21 @@ void IRRImporter::InternReadFile( const std::string& pFile,
 		pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
 		DefaultLogger::get()->info("IRR: No Meshes loaded, setting AI_SCENE_FLAGS_INCOMPLETE flag");
 	}
+	else
+	{
+		// copy all meshes to the temporary scene
+		tempScene->mNumMeshes = (unsigned int)meshes.size();
+		tempScene->mMeshes = new aiMesh*[tempScene->mNumMeshes];
+		::memcpy(tempScene->mMeshes,&meshes[0],tempScene->mNumMeshes);
+	}
 
 	/*  Now merge all sub scenes and attach them to the correct
 	 *  attachment points in the scenegraph.
 	 */
 	SceneCombiner::MergeScenes(pScene,tempScene,attach);
+
+
+	/* Finished ... everything destructs automatically and all 
+	 * temporary scenes have already been deleted by MergeScenes()
+	 */
 }

+ 14 - 0
code/IRRLoader.h

@@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_IRRLOADER_H_INCLUDED
 
 #include "IRRMeshLoader.h"
+#include "SceneCombiner.h"
 
 namespace Assimp	{
 
@@ -208,6 +209,9 @@ private:
 		// 0.f if not specified
 		float framesPerSecond;
 
+		// Meshes: path to the mesh to be loaded
+		std::string meshPath;
+
 		// Meshes: List of materials to be assigned
 		// along with their corresponding material flags
 		std::vector< std::pair<aiMaterial*, unsigned int> > materials;
@@ -221,6 +225,16 @@ private:
 		// List of all animators assigned to the node
 		std::list<Animator> animators;
 	};
+
+
+	/** Fill the scenegraph recursively
+	 */
+	void GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
+		BatchLoader& batch,
+		std::vector<aiMesh*>& meshes,
+		std::vector<aiNodeAnim*>& anims,
+		std::vector<AttachmentInfo>& attach);
+
 };
 
 } // end of namespace Assimp

+ 8 - 4
code/Q3DLoader.cpp

@@ -194,10 +194,10 @@ void Q3DImporter::InternReadFile( const std::string& pFile,
 						normals[i].z = stream.GetF4();
 					}
 
-					if (numTextures)
+					numVerts = (unsigned int)stream.GetI4();
+					if (numTextures && numVerts)
 					{
 						// read all texture coordinates
-						numVerts = (unsigned int)stream.GetI4();
 						std::vector<aiVector3D>& uv = mesh.uv;
 						uv.resize(numVerts);
 
@@ -435,10 +435,14 @@ outer:
 		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);
-		
+	
+		// NOTE: Ignore transparency for the moment - it seems
+		// unclear how to interpret the data
+#if 0
 		if (!(minor > '0' && major == '3'))
 			srcMat.transparency = 1.0f - srcMat.transparency;
 		mat->AddProperty(&srcMat.transparency, 1, AI_MATKEY_OPACITY);
+#endif
 
 		// add shininess - Quick3D seems to use it ins its viewer
 		srcMat.transparency = 16.f;
@@ -522,7 +526,7 @@ outer:
 				else *norms =  m.normals[ face.indices[n] ];
 
 				// copy texture coordinates
-				if (uv)
+				if (uv && m.uv.size())
 				{
 					if (m.prevUVIdx != 0xffffffff && m.uv.size() >= m.verts.size()) // workaround
 					{

+ 3 - 3
code/StandardShapes.cpp

@@ -166,12 +166,12 @@ aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)(
 }
 
 // ------------------------------------------------------------------------------------------------
-aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)(
+aiMesh* StandardShapes::MakeMesh (unsigned int num,  void (*GenerateFunc)(
 	unsigned int,std::vector<aiVector3D>&))
 {
 	std::vector<aiVector3D> temp;
-	unsigned num = (*GenerateFunc)(4,temp);
-	return MakeMesh(temp,num);
+	(*GenerateFunc)(num,temp);
+	return MakeMesh(temp,3);
 }
 
 // ------------------------------------------------------------------------------------------------

+ 1 - 1
code/StandardShapes.h

@@ -78,7 +78,7 @@ public:
 	static aiMesh* MakeMesh ( unsigned int (*GenerateFunc)
 		(std::vector<aiVector3D>&, bool));
 
-	static aiMesh* MakeMesh ( unsigned int (*GenerateFunc)
+	static aiMesh* MakeMesh ( unsigned int n,  void (*GenerateFunc)
 		(unsigned int,std::vector<aiVector3D>&));
 
 	// ----------------------------------------------------------------

+ 35 - 35
include/aiQuaternion.h

@@ -211,41 +211,41 @@ inline aiQuaternion::aiQuaternion( aiVector3D normalized)
 // Congrats, gmtl!
 inline void aiQuaternion::Interpolate( aiQuaternion& pOut, const aiQuaternion& pStart, const aiQuaternion& pEnd, float pFactor)
 {
-  // calc cosine theta
-  float cosom = pStart.x * pEnd.x + pStart.y * pEnd.y + pStart.z * pEnd.z + pStart.w * pEnd.w;
-
-  // adjust signs (if necessary)
-  aiQuaternion end = pEnd;
-  if( cosom < 0.0f)
-  {
-    cosom = -cosom;
-    end.x = -end.x;   // Reverse all signs
-    end.y = -end.y;
-    end.z = -end.z;
-    end.w = -end.w;
-  } 
-
-  // Calculate coefficients
-  float sclp, sclq;
-  if( (1.0f - cosom) > 0.0001f) // 0.0001 -> some epsillon
-  {
-    // Standard case (slerp)
-    float omega, sinom;
-    omega = acos( cosom); // extract theta from dot product's cos theta
-    sinom = sin( omega);
-    sclp  = sin( (1.0f - pFactor) * omega) / sinom;
-    sclq  = sin( pFactor * omega) / sinom;
-  } else
-  {
-    // Very close, do linear interp (because it's faster)
-    sclp = 1.0f - pFactor;
-    sclq = pFactor;
-  }
-
-  pOut.x = sclp * pStart.x + sclq * end.x;
-  pOut.y = sclp * pStart.y + sclq * end.y;
-  pOut.z = sclp * pStart.z + sclq * end.z;
-  pOut.w = sclp * pStart.w + sclq * end.w;
+  // calc cosine theta
+  float cosom = pStart.x * pEnd.x + pStart.y * pEnd.y + pStart.z * pEnd.z + pStart.w * pEnd.w;
+
+  // adjust signs (if necessary)
+  aiQuaternion end = pEnd;
+  if( cosom < 0.0f)
+  {
+    cosom = -cosom;
+    end.x = -end.x;   // Reverse all signs
+    end.y = -end.y;
+    end.z = -end.z;
+    end.w = -end.w;
+  } 
+
+  // Calculate coefficients
+  float sclp, sclq;
+  if( (1.0f - cosom) > 0.0001f) // 0.0001 -> some epsillon
+  {
+    // Standard case (slerp)
+    float omega, sinom;
+    omega = acos( cosom); // extract theta from dot product's cos theta
+    sinom = sin( omega);
+    sclp  = sin( (1.0f - pFactor) * omega) / sinom;
+    sclq  = sin( pFactor * omega) / sinom;
+  } else
+  {
+    // Very close, do linear interp (because it's faster)
+    sclp = 1.0f - pFactor;
+    sclq = pFactor;
+  }
+
+  pOut.x = sclp * pStart.x + sclq * end.x;
+  pOut.y = sclp * pStart.y + sclq * end.y;
+  pOut.z = sclp * pStart.z + sclq * end.z;
+  pOut.w = sclp * pStart.w + sclq * end.w;
 }
 
 } // end extern "C"