- fbx: read deformers (Skin and Cluster).
parent
8d1db6229c
commit
06acead438
|
@ -416,6 +416,7 @@ SET(FBX_SRCS
|
|||
FBXModel.cpp
|
||||
FBXAnimation.cpp
|
||||
FBXNodeAttribute.cpp
|
||||
FBXDeformer.cpp
|
||||
)
|
||||
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
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2071,6 +2071,10 @@
|
|||
RelativePath="..\..\code\FBXConverter.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\FBXDeformer.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\FBXDocument.cpp"
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue