Selaa lähdekoodia

- fbx: read deformers (Skin and Cluster).

Alexander Gessler 13 vuotta sitten
vanhempi
commit
06acead438

+ 1 - 0
code/CMakeLists.txt

@@ -416,6 +416,7 @@ SET(FBX_SRCS
 	FBXModel.cpp
 	FBXAnimation.cpp
 	FBXNodeAttribute.cpp
+	FBXDeformer.cpp
 )
 SOURCE_GROUP( FBX FILES ${FBX_SRCS})
 

+ 156 - 0
code/FBXDeformer.cpp

@@ -0,0 +1,156 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp 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 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  FBXNoteAttribute.cpp
+ *  @brief Assimp::FBX::NodeAttribute (and subclasses) implementation
+ */
+#include "AssimpPCH.h"
+
+#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
+
+#include "FBXParser.h"
+#include "FBXDocument.h"
+#include "FBXImporter.h"
+#include "FBXImportSettings.h"
+#include "FBXDocumentUtil.h"
+#include "FBXProperties.h"
+
+namespace Assimp {
+namespace FBX {
+
+	using namespace Util;
+
+// ------------------------------------------------------------------------------------------------
+Deformer::Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+	: Object(id,element,name)
+{
+	const Scope& sc = GetRequiredScope(element);
+
+	const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
+	props = GetPropertyTable(doc,"Deformer.Fbx" + classname,element,sc);
+}
+
+
+// ------------------------------------------------------------------------------------------------
+Deformer::~Deformer()
+{
+
+}
+
+
+// ------------------------------------------------------------------------------------------------
+Cluster::Cluster(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+: Deformer(id,element,doc,name)
+{
+	const Scope& sc = GetRequiredScope(element);
+
+	const Element& Indexes = GetRequiredElement(sc,"Indexes",&element);
+	const Element& Weights = GetRequiredElement(sc,"Weights",&element);
+	const Element& Transform = GetRequiredElement(sc,"Transform",&element);
+	const Element& TransformLink = GetRequiredElement(sc,"TransformLink",&element);
+
+	transform = ReadMatrix(Transform);
+	transformLink = ReadMatrix(TransformLink);
+
+	ReadVectorDataArray(indices,Indexes);
+	ReadVectorDataArray(weights,Weights);
+}
+
+
+// ------------------------------------------------------------------------------------------------
+Cluster::~Cluster()
+{
+
+}
+
+
+// ------------------------------------------------------------------------------------------------
+Skin::Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name)
+: Deformer(id,element,doc,name)
+{
+	const Scope& sc = GetRequiredScope(element);
+
+	const Element* const Link_DeformAcuracy = sc["Link_DeformAcuracy"];
+	if(Link_DeformAcuracy) {
+		accuracy = ParseTokenAsFloat(GetRequiredToken(*Link_DeformAcuracy,0));
+	}
+
+	const char* const arr[] = {"Deformer"};
+
+	// resolve assigned clusters 
+	const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),arr, 1);
+
+	clusters.reserve(conns.size());
+	BOOST_FOREACH(const Connection* con, conns) {
+
+		// Cluster -> Skin links should be object-object connections
+		if (con->PropertyName().length()) {
+			continue;
+		}
+
+		const Object* const ob = con->SourceObject();
+		if(!ob) {
+			DOMWarning("failed to read source object for incoming Skin link, ignoring",&element);
+			continue;
+		}
+
+		const Cluster* const cluster = dynamic_cast<const Cluster*>(ob);
+		if(cluster) {
+			clusters.push_back(cluster);
+			continue;
+		}
+
+	}
+}
+
+
+// ------------------------------------------------------------------------------------------------
+Skin::~Skin()
+{
+
+}
+
+
+
+}
+}
+
+#endif
+

+ 45 - 0
code/FBXDocument.cpp

@@ -376,6 +376,43 @@ void ReadVectorDataArray(std::vector<uint64_t>& out, const Element& el)
 }
 
 
+// ------------------------------------------------------------------------------------------------
+aiMatrix4x4 ReadMatrix(const Element& element)
+{
+	std::vector<float> values;
+	ReadVectorDataArray(values,element);
+
+	if(values.size() != 16) {
+		DOMError("expected 16 matrix elements");
+	}
+
+	aiMatrix4x4 result;
+
+	// XXX transposed or not, this is the question :-)
+	result.a1 = values[0];
+	result.a2 = values[1];
+	result.a3 = values[2];
+	result.a4 = values[3];
+
+	result.b1 = values[4];
+	result.b2 = values[5];
+	result.b3 = values[6];
+	result.b4 = values[7];
+
+	result.c1 = values[8];
+	result.c2 = values[9];
+	result.c3 = values[10];
+	result.c4 = values[11];
+
+	result.d1 = values[12];
+	result.d2 = values[13];
+	result.d3 = values[14];
+	result.d4 = values[15];
+
+	return result;
+}
+
+
 // ------------------------------------------------------------------------------------------------
 // fetch a property table and the corresponding property template 
 boost::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc, 
@@ -472,6 +509,14 @@ const Object* LazyObject::Get(bool dieOnError)
 				object.reset(new CameraSwitcher(id,element,doc,name));
 			}
 		}
+		else if (!strncmp(obtype,"Deformer",length)) {
+			if (!strcmp(classtag.c_str(),"Cluster")) {
+				object.reset(new Cluster(id,element,doc,name));
+			}
+			else if (!strcmp(classtag.c_str(),"Skin")) {
+				object.reset(new Skin(id,element,doc,name));
+			}
+		}
 		else if (!strncmp(obtype,"Model",length)) {
 			object.reset(new Model(id,element,doc,name));
 		}

+ 90 - 0
code/FBXDocument.h

@@ -641,6 +641,96 @@ private:
 };
 
 
+/** DOM class for deformers */
+class Deformer : public Object
+{
+public:
+
+	Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+	~Deformer();
+
+public:
+
+	const PropertyTable& Props() const {
+		ai_assert(props.get());
+		return *props.get();
+	}
+
+private:
+
+	boost::shared_ptr<const PropertyTable> props;
+};
+
+typedef std::vector<float> WeightList;
+typedef std::vector<unsigned int> WeightIndexArray;
+
+
+/** DOM class for skin deformer clusters (aka subdeformers) */
+class Cluster : public Deformer
+{
+public:
+
+	Cluster(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+	~Cluster();
+
+public:
+
+	/** get the list of deformer weights associated with this cluster */
+	const WeightList& GetWeights() const {
+		return weights;
+	}
+
+	/** get indices into the vertex data of the geometry associated
+	 *  with this cluster.*/
+	const WeightIndexArray& GetIndices() const {
+		return indices;
+	}
+
+	/** */
+	const aiMatrix4x4& Transform() const {
+		return transform;
+	}
+
+	const aiMatrix4x4& TransformLink() const {
+		return transformLink;
+	}
+
+private:
+
+	WeightList weights;
+	WeightIndexArray indices;
+
+	aiMatrix4x4 transform;
+	aiMatrix4x4 transformLink;
+};
+
+
+
+/** DOM class for skin deformers */
+class Skin : public Deformer
+{
+public:
+
+	Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name);
+	~Skin();
+
+public:
+
+	float DeformAccuracy() const {
+		return accuracy;
+	}
+
+
+	const std::vector<const Cluster*>& Clusters() const {
+		return clusters;
+	}
+
+private:
+
+	float accuracy;
+	std::vector<const Cluster*> clusters;
+};
+
 
 
 /** Represents a link between two FBX objects. */

+ 3 - 0
code/FBXDocumentUtil.h

@@ -98,6 +98,9 @@ void ReadVectorDataArray(std::vector<unsigned int>& out, const Element& el);
 void ReadVectorDataArray(std::vector<uint64_t>& out, const Element& el);
 
 
+// read a 4x4 matrix from an array of 16 floats
+aiMatrix4x4 ReadMatrix(const Element& element);
+
 
 // fetch a property table and the corresponding property template 
 boost::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc, 

+ 3 - 2
code/FBXModel.cpp

@@ -96,6 +96,7 @@ void Model::ResolveLinks(const Element& element, const Document& doc)
 
 	materials.reserve(conns.size());
 	geometry.reserve(conns.size());
+	attributes.reserve(conns.size());
 	BOOST_FOREACH(const Connection* con, conns) {
 
 		// material and geometry links should be Object-Object connections
@@ -105,7 +106,7 @@ void Model::ResolveLinks(const Element& element, const Document& doc)
 
 		const Object* const ob = con->SourceObject();
 		if(!ob) {
-			DOMWarning("failed to read source object for incoming model link, ignoring",&element);
+			DOMWarning("failed to read source object for incoming Model link, ignoring",&element);
 			continue;
 		}
 
@@ -127,7 +128,7 @@ void Model::ResolveLinks(const Element& element, const Document& doc)
 			continue;
 		}
 
-		DOMWarning("source object for model link is neither Material or Geometry, ignoring",&element);
+		DOMWarning("source object for model link is neither Material, NodeAttribute nor Geometry, ignoring",&element);
 		continue;
 	}
 }

+ 4 - 0
workspaces/vc9/assimp.vcproj

@@ -2071,6 +2071,10 @@
 						RelativePath="..\..\code\FBXConverter.h"
 						>
 					</File>
+					<File
+						RelativePath="..\..\code\FBXDeformer.cpp"
+						>
+					</File>
 					<File
 						RelativePath="..\..\code\FBXDocument.cpp"
 						>