diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 61b592bd8..d7600080c 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -416,6 +416,7 @@ SET(FBX_SRCS FBXModel.cpp FBXAnimation.cpp FBXNodeAttribute.cpp + FBXDeformer.cpp ) SOURCE_GROUP( FBX FILES ${FBX_SRCS}) diff --git a/code/FBXDeformer.cpp b/code/FBXDeformer.cpp new file mode 100644 index 000000000..0cfcde65a --- /dev/null +++ b/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& 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(ob); + if(cluster) { + clusters.push_back(cluster); + continue; + } + + } +} + + +// ------------------------------------------------------------------------------------------------ +Skin::~Skin() +{ + +} + + + +} +} + +#endif + diff --git a/code/FBXDocument.cpp b/code/FBXDocument.cpp index 0f3390157..a682d09c9 100644 --- a/code/FBXDocument.cpp +++ b/code/FBXDocument.cpp @@ -376,6 +376,43 @@ void ReadVectorDataArray(std::vector& out, const Element& el) } +// ------------------------------------------------------------------------------------------------ +aiMatrix4x4 ReadMatrix(const Element& element) +{ + std::vector 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 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)); } diff --git a/code/FBXDocument.h b/code/FBXDocument.h index 75efe71c1..bce541694 100644 --- a/code/FBXDocument.h +++ b/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 props; +}; + +typedef std::vector WeightList; +typedef std::vector 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& Clusters() const { + return clusters; + } + +private: + + float accuracy; + std::vector clusters; +}; + /** Represents a link between two FBX objects. */ diff --git a/code/FBXDocumentUtil.h b/code/FBXDocumentUtil.h index 0e25e5629..35dbf7d22 100644 --- a/code/FBXDocumentUtil.h +++ b/code/FBXDocumentUtil.h @@ -98,6 +98,9 @@ void ReadVectorDataArray(std::vector& out, const Element& el); void ReadVectorDataArray(std::vector& 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 GetPropertyTable(const Document& doc, diff --git a/code/FBXModel.cpp b/code/FBXModel.cpp index 69e2ee48c..196e44a53 100644 --- a/code/FBXModel.cpp +++ b/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; } } diff --git a/workspaces/vc9/assimp.vcproj b/workspaces/vc9/assimp.vcproj index 763c51df0..3cf24174b 100644 --- a/workspaces/vc9/assimp.vcproj +++ b/workspaces/vc9/assimp.vcproj @@ -2071,6 +2071,10 @@ RelativePath="..\..\code\FBXConverter.h" > + +