- fbx: read deformers (Skin and Cluster).
parent
8d1db6229c
commit
06acead438
|
@ -416,6 +416,7 @@ SET(FBX_SRCS
|
||||||
FBXModel.cpp
|
FBXModel.cpp
|
||||||
FBXAnimation.cpp
|
FBXAnimation.cpp
|
||||||
FBXNodeAttribute.cpp
|
FBXNodeAttribute.cpp
|
||||||
|
FBXDeformer.cpp
|
||||||
)
|
)
|
||||||
SOURCE_GROUP( FBX FILES ${FBX_SRCS})
|
SOURCE_GROUP( FBX FILES ${FBX_SRCS})
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
// fetch a property table and the corresponding property template
|
||||||
boost::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
|
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));
|
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)) {
|
else if (!strncmp(obtype,"Model",length)) {
|
||||||
object.reset(new Model(id,element,doc,name));
|
object.reset(new Model(id,element,doc,name));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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. */
|
/** Represents a link between two FBX objects. */
|
||||||
|
|
|
@ -98,6 +98,9 @@ void ReadVectorDataArray(std::vector<unsigned int>& out, const Element& el);
|
||||||
void ReadVectorDataArray(std::vector<uint64_t>& 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
|
// fetch a property table and the corresponding property template
|
||||||
boost::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
|
boost::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
|
||||||
|
|
|
@ -96,6 +96,7 @@ void Model::ResolveLinks(const Element& element, const Document& doc)
|
||||||
|
|
||||||
materials.reserve(conns.size());
|
materials.reserve(conns.size());
|
||||||
geometry.reserve(conns.size());
|
geometry.reserve(conns.size());
|
||||||
|
attributes.reserve(conns.size());
|
||||||
BOOST_FOREACH(const Connection* con, conns) {
|
BOOST_FOREACH(const Connection* con, conns) {
|
||||||
|
|
||||||
// material and geometry links should be Object-Object connections
|
// 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();
|
const Object* const ob = con->SourceObject();
|
||||||
if(!ob) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +128,7 @@ void Model::ResolveLinks(const Element& element, const Document& doc)
|
||||||
continue;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2071,6 +2071,10 @@
|
||||||
RelativePath="..\..\code\FBXConverter.h"
|
RelativePath="..\..\code\FBXConverter.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\code\FBXDeformer.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\code\FBXDocument.cpp"
|
RelativePath="..\..\code\FBXDocument.cpp"
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in New Issue