Merge branch 'master' into master
commit
ce8081bd0a
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2022, assimp team
|
Copyright (c) 2006-2022, assimp team
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
@ -87,11 +86,6 @@ AnimationCurve::AnimationCurve(uint64_t id, const Element &element, const std::s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
AnimationCurve::~AnimationCurve() {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element &element, const std::string &name,
|
AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element &element, const std::string &name,
|
||||||
const Document &doc, const char *const *target_prop_whitelist /*= nullptr*/,
|
const Document &doc, const char *const *target_prop_whitelist /*= nullptr*/,
|
||||||
|
@ -147,11 +141,6 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element &element, cons
|
||||||
props = GetPropertyTable(doc, "AnimationCurveNode.FbxAnimCurveNode", element, sc, false);
|
props = GetPropertyTable(doc, "AnimationCurveNode.FbxAnimCurveNode", element, sc, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
AnimationCurveNode::~AnimationCurveNode() {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const AnimationCurveMap &AnimationCurveNode::Curves() const {
|
const AnimationCurveMap &AnimationCurveNode::Curves() const {
|
||||||
if (curves.empty()) {
|
if (curves.empty()) {
|
||||||
|
@ -193,11 +182,6 @@ AnimationLayer::AnimationLayer(uint64_t id, const Element &element, const std::s
|
||||||
props = GetPropertyTable(doc, "AnimationLayer.FbxAnimLayer", element, sc, true);
|
props = GetPropertyTable(doc, "AnimationLayer.FbxAnimLayer", element, sc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
AnimationLayer::~AnimationLayer() {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
AnimationCurveNodeList AnimationLayer::Nodes(const char *const *target_prop_whitelist /*= nullptr*/,
|
AnimationCurveNodeList AnimationLayer::Nodes(const char *const *target_prop_whitelist /*= nullptr*/,
|
||||||
size_t whitelist_size /*= 0*/) const {
|
size_t whitelist_size /*= 0*/) const {
|
||||||
|
@ -279,11 +263,6 @@ AnimationStack::AnimationStack(uint64_t id, const Element &element, const std::s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
AnimationStack::~AnimationStack() {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace FBX
|
} // namespace FBX
|
||||||
} // namespace Assimp
|
} // namespace Assimp
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
namespace FBX {
|
namespace FBX {
|
||||||
|
|
||||||
const std::string NULL_RECORD = { // 25 null bytes in 64-bit and 13 null bytes in 32-bit
|
static constexpr size_t NumNullRecords = 25;
|
||||||
|
const char NULL_RECORD[NumNullRecords] = { // 25 null bytes in 64-bit and 13 null bytes in 32-bit
|
||||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
|
||||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
|
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
|
||||||
}; // who knows why, it looks like two integers 32/64 bit (compressed and uncompressed sizes?) + 1 byte (might be compression type?)
|
}; // who knows why, it looks like two integers 32/64 bit (compressed and uncompressed sizes?) + 1 byte (might be compression type?)
|
||||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2022, assimp team
|
Copyright (c) 2006-2022, assimp team
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
|
|
@ -65,12 +65,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <iostream>
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <tuple>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
namespace FBX {
|
namespace FBX {
|
||||||
|
@ -187,8 +184,7 @@ std::string FBXConverter::MakeUniqueNodeName(const Model *const model, const aiN
|
||||||
|
|
||||||
/// This struct manages nodes which may or may not end up in the node hierarchy.
|
/// This struct manages nodes which may or may not end up in the node hierarchy.
|
||||||
/// When a node becomes a child of another node, that node becomes its owner and mOwnership should be released.
|
/// When a node becomes a child of another node, that node becomes its owner and mOwnership should be released.
|
||||||
struct FBXConverter::PotentialNode
|
struct FBXConverter::PotentialNode {
|
||||||
{
|
|
||||||
PotentialNode() : mOwnership(new aiNode), mNode(mOwnership.get()) {}
|
PotentialNode() : mOwnership(new aiNode), mNode(mOwnership.get()) {}
|
||||||
PotentialNode(const std::string& name) : mOwnership(new aiNode(name)), mNode(mOwnership.get()) {}
|
PotentialNode(const std::string& name) : mOwnership(new aiNode(name)), mNode(mOwnership.get()) {}
|
||||||
aiNode* operator->() { return mNode; }
|
aiNode* operator->() { return mNode; }
|
||||||
|
@ -231,7 +227,7 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
|
||||||
if (nullptr != model) {
|
if (nullptr != model) {
|
||||||
nodes_chain.clear();
|
nodes_chain.clear();
|
||||||
post_nodes_chain.clear();
|
post_nodes_chain.clear();
|
||||||
|
aiMatrix4x4 new_abs_transform = parent->mTransformation;
|
||||||
std::string node_name = FixNodeName(model->Name());
|
std::string node_name = FixNodeName(model->Name());
|
||||||
// even though there is only a single input node, the design of
|
// even though there is only a single input node, the design of
|
||||||
// assimp (or rather: the complicated transformation chain that
|
// assimp (or rather: the complicated transformation chain that
|
||||||
|
@ -268,7 +264,7 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
|
||||||
}
|
}
|
||||||
|
|
||||||
// attach geometry
|
// attach geometry
|
||||||
ConvertModel(*model, nodes_chain.back().mNode, root_node);
|
ConvertModel(*model, nodes_chain.back().mNode, root_node, new_abs_transform);
|
||||||
|
|
||||||
// check if there will be any child nodes
|
// check if there will be any child nodes
|
||||||
const std::vector<const Connection *> &child_conns = doc.GetConnectionsByDestinationSequenced(model->ID(), "Model");
|
const std::vector<const Connection *> &child_conns = doc.GetConnectionsByDestinationSequenced(model->ID(), "Model");
|
||||||
|
@ -447,7 +443,7 @@ void FBXConverter::GetUniqueName(const std::string &name, std::string &uniqueNam
|
||||||
auto it_pair = mNodeNames.insert({ name, 0 }); // duplicate node name instance count
|
auto it_pair = mNodeNames.insert({ name, 0 }); // duplicate node name instance count
|
||||||
unsigned int &i = it_pair.first->second;
|
unsigned int &i = it_pair.first->second;
|
||||||
while (!it_pair.second) {
|
while (!it_pair.second) {
|
||||||
i++;
|
++i;
|
||||||
std::ostringstream ext;
|
std::ostringstream ext;
|
||||||
ext << name << std::setfill('0') << std::setw(3) << i;
|
ext << name << std::setfill('0') << std::setw(3) << i;
|
||||||
uniqueName = ext.str();
|
uniqueName = ext.str();
|
||||||
|
@ -646,9 +642,8 @@ void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D &rot
|
||||||
|
|
||||||
bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
|
bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
|
||||||
const PropertyTable &props = model.Props();
|
const PropertyTable &props = model.Props();
|
||||||
bool ok;
|
|
||||||
|
|
||||||
const float zero_epsilon = ai_epsilon;
|
const auto zero_epsilon = ai_epsilon;
|
||||||
const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
|
const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
|
||||||
for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
|
for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
|
||||||
const TransformationComp comp = static_cast<TransformationComp>(i);
|
const TransformationComp comp = static_cast<TransformationComp>(i);
|
||||||
|
@ -660,6 +655,7 @@ bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
|
||||||
|
|
||||||
bool scale_compare = (comp == TransformationComp_GeometricScaling || comp == TransformationComp_Scaling);
|
bool scale_compare = (comp == TransformationComp_GeometricScaling || comp == TransformationComp_Scaling);
|
||||||
|
|
||||||
|
bool ok = true;
|
||||||
const aiVector3D &v = PropertyGet<aiVector3D>(props, NameTransformationCompProperty(comp), ok);
|
const aiVector3D &v = PropertyGet<aiVector3D>(props, NameTransformationCompProperty(comp), ok);
|
||||||
if (ok && scale_compare) {
|
if (ok && scale_compare) {
|
||||||
if ((v - all_ones).SquareLength() > zero_epsilon) {
|
if ((v - all_ones).SquareLength() > zero_epsilon) {
|
||||||
|
@ -894,18 +890,17 @@ void FBXConverter::SetupNodeMetadata(const Model &model, aiNode &nd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root_node) {
|
void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform) {
|
||||||
const std::vector<const Geometry *> &geos = model.GetGeometry();
|
const std::vector<const Geometry *> &geos = model.GetGeometry();
|
||||||
|
|
||||||
std::vector<unsigned int> meshes;
|
std::vector<unsigned int> meshes;
|
||||||
meshes.reserve(geos.size());
|
meshes.reserve(geos.size());
|
||||||
|
|
||||||
for (const Geometry *geo : geos) {
|
for (const Geometry *geo : geos) {
|
||||||
|
|
||||||
const MeshGeometry *const mesh = dynamic_cast<const MeshGeometry *>(geo);
|
const MeshGeometry *const mesh = dynamic_cast<const MeshGeometry *>(geo);
|
||||||
const LineGeometry *const line = dynamic_cast<const LineGeometry *>(geo);
|
const LineGeometry *const line = dynamic_cast<const LineGeometry *>(geo);
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
const std::vector<unsigned int> &indices = ConvertMesh(*mesh, model, parent, root_node);
|
const std::vector<unsigned int> &indices = ConvertMesh(*mesh, model, parent, root_node, absolute_transform);
|
||||||
std::copy(indices.begin(), indices.end(), std::back_inserter(meshes));
|
std::copy(indices.begin(), indices.end(), std::back_inserter(meshes));
|
||||||
} else if (line) {
|
} else if (line) {
|
||||||
const std::vector<unsigned int> &indices = ConvertLine(*line, root_node);
|
const std::vector<unsigned int> &indices = ConvertLine(*line, root_node);
|
||||||
|
@ -926,7 +921,7 @@ void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned int>
|
std::vector<unsigned int>
|
||||||
FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node) {
|
FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform) {
|
||||||
std::vector<unsigned int> temp;
|
std::vector<unsigned int> temp;
|
||||||
|
|
||||||
MeshMap::const_iterator it = meshes_converted.find(&mesh);
|
MeshMap::const_iterator it = meshes_converted.find(&mesh);
|
||||||
|
@ -949,13 +944,13 @@ FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *
|
||||||
const MatIndexArray::value_type base = mindices[0];
|
const MatIndexArray::value_type base = mindices[0];
|
||||||
for (MatIndexArray::value_type index : mindices) {
|
for (MatIndexArray::value_type index : mindices) {
|
||||||
if (index != base) {
|
if (index != base) {
|
||||||
return ConvertMeshMultiMaterial(mesh, model, parent, root_node);
|
return ConvertMeshMultiMaterial(mesh, model, absolute_transform, parent, root_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// faster code-path, just copy the data
|
// faster code-path, just copy the data
|
||||||
temp.push_back(ConvertMeshSingleMaterial(mesh, model, parent, root_node));
|
temp.push_back(ConvertMeshSingleMaterial(mesh, model, absolute_transform, parent, root_node));
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1023,7 +1018,35 @@ aiMesh *FBXConverter::SetupEmptyMesh(const Geometry &mesh, aiNode *parent) {
|
||||||
return out_mesh;
|
return out_mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model,
|
static aiSkeleton *createAiSkeleton(SkeletonBoneContainer &sbc) {
|
||||||
|
if (sbc.MeshArray.empty() || sbc.SkeletonBoneToMeshLookup.empty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
aiSkeleton *skeleton = new aiSkeleton;
|
||||||
|
for (auto *mesh : sbc.MeshArray) {
|
||||||
|
auto it = sbc.SkeletonBoneToMeshLookup.find(mesh);
|
||||||
|
if (it == sbc.SkeletonBoneToMeshLookup.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SkeletonBoneArray *ba = it->second;
|
||||||
|
if (ba == nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
skeleton->mNumBones = static_cast<unsigned int>(ba->size());
|
||||||
|
skeleton->mBones = new aiSkeletonBone*[skeleton->mNumBones];
|
||||||
|
size_t index = 0;
|
||||||
|
for (auto bone : (* ba)) {
|
||||||
|
skeleton->mBones[index] = bone;
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return skeleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform,
|
||||||
aiNode *parent, aiNode *) {
|
aiNode *parent, aiNode *) {
|
||||||
const MatIndexArray &mindices = mesh.GetMaterialIndices();
|
const MatIndexArray &mindices = mesh.GetMaterialIndices();
|
||||||
aiMesh *const out_mesh = SetupEmptyMesh(mesh, parent);
|
aiMesh *const out_mesh = SetupEmptyMesh(mesh, parent);
|
||||||
|
@ -1142,8 +1165,15 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c
|
||||||
ConvertMaterialForMesh(out_mesh, model, mesh, mindices[0]);
|
ConvertMaterialForMesh(out_mesh, model, mesh, mindices[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr) {
|
if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr && !doc.Settings().useSkeleton) {
|
||||||
ConvertWeights(out_mesh, mesh, parent, NO_MATERIAL_SEPARATION, nullptr);
|
ConvertWeights(out_mesh, mesh, absolute_transform, parent, NO_MATERIAL_SEPARATION, nullptr);
|
||||||
|
} else if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr && doc.Settings().useSkeleton) {
|
||||||
|
SkeletonBoneContainer sbc;
|
||||||
|
ConvertWeightsToSkeleton(out_mesh, mesh, absolute_transform, parent, NO_MATERIAL_SEPARATION, nullptr, sbc);
|
||||||
|
aiSkeleton *skeleton = createAiSkeleton(sbc);
|
||||||
|
if (skeleton != nullptr) {
|
||||||
|
mSkeletons.emplace_back(skeleton);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<aiAnimMesh *> animMeshes;
|
std::vector<aiAnimMesh *> animMeshes;
|
||||||
|
@ -1190,7 +1220,7 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned int>
|
std::vector<unsigned int>
|
||||||
FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, aiNode *parent,
|
FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform, aiNode *parent,
|
||||||
aiNode *root_node) {
|
aiNode *root_node) {
|
||||||
const MatIndexArray &mindices = mesh.GetMaterialIndices();
|
const MatIndexArray &mindices = mesh.GetMaterialIndices();
|
||||||
ai_assert(mindices.size());
|
ai_assert(mindices.size());
|
||||||
|
@ -1201,7 +1231,7 @@ FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &mo
|
||||||
for (MatIndexArray::value_type index : mindices) {
|
for (MatIndexArray::value_type index : mindices) {
|
||||||
if (had.find(index) == had.end()) {
|
if (had.find(index) == had.end()) {
|
||||||
|
|
||||||
indices.push_back(ConvertMeshMultiMaterial(mesh, model, index, parent, root_node));
|
indices.push_back(ConvertMeshMultiMaterial(mesh, model, absolute_transform, index, parent, root_node));
|
||||||
had.insert(index);
|
had.insert(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1209,9 +1239,8 @@ FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &mo
|
||||||
return indices;
|
return indices;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model,
|
unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform,
|
||||||
MatIndexArray::value_type index,
|
MatIndexArray::value_type index, aiNode *parent, aiNode *) {
|
||||||
aiNode *parent, aiNode *) {
|
|
||||||
aiMesh *const out_mesh = SetupEmptyMesh(mesh, parent);
|
aiMesh *const out_mesh = SetupEmptyMesh(mesh, parent);
|
||||||
|
|
||||||
const MatIndexArray &mindices = mesh.GetMaterialIndices();
|
const MatIndexArray &mindices = mesh.GetMaterialIndices();
|
||||||
|
@ -1374,7 +1403,7 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
|
||||||
ConvertMaterialForMesh(out_mesh, model, mesh, index);
|
ConvertMaterialForMesh(out_mesh, model, mesh, index);
|
||||||
|
|
||||||
if (process_weights) {
|
if (process_weights) {
|
||||||
ConvertWeights(out_mesh, mesh, parent, index, &reverseMapping);
|
ConvertWeights(out_mesh, mesh, absolute_transform, parent, index, &reverseMapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<aiAnimMesh *> animMeshes;
|
std::vector<aiAnimMesh *> animMeshes;
|
||||||
|
@ -1424,19 +1453,47 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
|
||||||
return static_cast<unsigned int>(mMeshes.size() - 1);
|
return static_cast<unsigned int>(mMeshes.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo,
|
static void copyBoneToSkeletonBone(aiMesh *mesh, aiBone *bone, aiSkeletonBone *skeletonBone ) {
|
||||||
|
skeletonBone->mNumnWeights = bone->mNumWeights;
|
||||||
|
skeletonBone->mWeights = bone->mWeights;
|
||||||
|
skeletonBone->mOffsetMatrix = bone->mOffsetMatrix;
|
||||||
|
skeletonBone->mMeshId = mesh;
|
||||||
|
skeletonBone->mNode = bone->mNode;
|
||||||
|
skeletonBone->mParent = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBXConverter::ConvertWeightsToSkeleton(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform, aiNode *parent, unsigned int materialIndex,
|
||||||
|
std::vector<unsigned int> *outputVertStartIndices, SkeletonBoneContainer &skeletonContainer) {
|
||||||
|
|
||||||
|
if (skeletonContainer.SkeletonBoneToMeshLookup.find(out) != skeletonContainer.SkeletonBoneToMeshLookup.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConvertWeights(out, geo, absolute_transform, parent, materialIndex, outputVertStartIndices);
|
||||||
|
skeletonContainer.MeshArray.emplace_back(out);
|
||||||
|
SkeletonBoneArray *ba = new SkeletonBoneArray;
|
||||||
|
for (size_t i = 0; i < out->mNumBones; ++i) {
|
||||||
|
aiBone *bone = out->mBones[i];
|
||||||
|
if (bone == nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
aiSkeletonBone *skeletonBone = new aiSkeletonBone;
|
||||||
|
copyBoneToSkeletonBone(out, bone, skeletonBone);
|
||||||
|
ba->emplace_back(skeletonBone);
|
||||||
|
}
|
||||||
|
skeletonContainer.SkeletonBoneToMeshLookup[out] = ba;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
|
||||||
aiNode *parent, unsigned int materialIndex,
|
aiNode *parent, unsigned int materialIndex,
|
||||||
std::vector<unsigned int> *outputVertStartIndices) {
|
std::vector<unsigned int> *outputVertStartIndices) {
|
||||||
ai_assert(geo.DeformerSkin());
|
ai_assert(geo.DeformerSkin());
|
||||||
|
|
||||||
std::vector<size_t> out_indices;
|
std::vector<size_t> out_indices, index_out_indices, count_out_indices;
|
||||||
std::vector<size_t> index_out_indices;
|
|
||||||
std::vector<size_t> count_out_indices;
|
|
||||||
|
|
||||||
const Skin &sk = *geo.DeformerSkin();
|
const Skin &sk = *geo.DeformerSkin();
|
||||||
|
|
||||||
std::vector<aiBone *> bones;
|
std::vector<aiBone*> bones;
|
||||||
|
|
||||||
const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION;
|
const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION;
|
||||||
ai_assert(no_mat_check || outputVertStartIndices);
|
ai_assert(no_mat_check || outputVertStartIndices);
|
||||||
|
|
||||||
|
@ -1496,7 +1553,7 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo,
|
||||||
// XXX this could be heavily simplified by collecting the bone
|
// XXX this could be heavily simplified by collecting the bone
|
||||||
// data in a single step.
|
// data in a single step.
|
||||||
ConvertCluster(bones, cluster, out_indices, index_out_indices,
|
ConvertCluster(bones, cluster, out_indices, index_out_indices,
|
||||||
count_out_indices, parent);
|
count_out_indices, absolute_transform, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
bone_map.clear();
|
bone_map.clear();
|
||||||
|
@ -1509,25 +1566,20 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo,
|
||||||
out->mBones = nullptr;
|
out->mBones = nullptr;
|
||||||
out->mNumBones = 0;
|
out->mNumBones = 0;
|
||||||
return;
|
return;
|
||||||
} else {
|
|
||||||
out->mBones = new aiBone *[bones.size()]();
|
|
||||||
out->mNumBones = static_cast<unsigned int>(bones.size());
|
|
||||||
|
|
||||||
std::swap_ranges(bones.begin(), bones.end(), out->mBones);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out->mBones = new aiBone *[bones.size()]();
|
||||||
|
out->mNumBones = static_cast<unsigned int>(bones.size());
|
||||||
|
std::swap_ranges(bones.begin(), bones.end(), out->mBones);
|
||||||
}
|
}
|
||||||
|
|
||||||
const aiNode *GetNodeByName(aiNode *current_node) {
|
void FBXConverter::ConvertCluster(std::vector<aiBone*> &local_mesh_bones, const Cluster *cluster,
|
||||||
aiNode *iter = current_node;
|
|
||||||
//printf("Child count: %d", iter->mNumChildren);
|
|
||||||
return iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,
|
|
||||||
std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices,
|
std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices,
|
||||||
std::vector<size_t> &count_out_indices, aiNode *) {
|
std::vector<size_t> &count_out_indices, const aiMatrix4x4 & /* absolute_transform*/,
|
||||||
ai_assert(cl); // make sure cluster valid
|
aiNode *) {
|
||||||
std::string deformer_name = cl->TargetNode()->Name();
|
ai_assert(cluster != nullptr); // make sure cluster valid
|
||||||
|
|
||||||
|
std::string deformer_name = cluster->TargetNode()->Name();
|
||||||
aiString bone_name = aiString(FixNodeName(deformer_name));
|
aiString bone_name = aiString(FixNodeName(deformer_name));
|
||||||
|
|
||||||
aiBone *bone = nullptr;
|
aiBone *bone = nullptr;
|
||||||
|
@ -1540,10 +1592,10 @@ void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const
|
||||||
bone = new aiBone();
|
bone = new aiBone();
|
||||||
bone->mName = bone_name;
|
bone->mName = bone_name;
|
||||||
|
|
||||||
bone->mOffsetMatrix = cl->Transform();
|
bone->mOffsetMatrix = cluster->Transform();
|
||||||
// store local transform link for post processing
|
// store local transform link for post processing
|
||||||
/*
|
/*
|
||||||
bone->mOffsetMatrix = cl->TransformLink();
|
bone->mOffsetMatrix = cluster->TransformLink();
|
||||||
bone->mOffsetMatrix.Inverse();
|
bone->mOffsetMatrix.Inverse();
|
||||||
|
|
||||||
aiMatrix4x4 matrix = (aiMatrix4x4)absolute_transform;
|
aiMatrix4x4 matrix = (aiMatrix4x4)absolute_transform;
|
||||||
|
@ -1560,7 +1612,7 @@ void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const
|
||||||
cursor = bone->mWeights = new aiVertexWeight[out_indices.size()];
|
cursor = bone->mWeights = new aiVertexWeight[out_indices.size()];
|
||||||
|
|
||||||
const size_t no_index_sentinel = std::numeric_limits<size_t>::max();
|
const size_t no_index_sentinel = std::numeric_limits<size_t>::max();
|
||||||
const WeightArray &weights = cl->GetWeights();
|
const WeightArray &weights = cluster->GetWeights();
|
||||||
|
|
||||||
const size_t c = index_out_indices.size();
|
const size_t c = index_out_indices.size();
|
||||||
for (size_t i = 0; i < c; ++i) {
|
for (size_t i = 0; i < c; ++i) {
|
||||||
|
@ -2605,7 +2657,7 @@ void FBXConverter::ConvertAnimationStack(const AnimationStack &st) {
|
||||||
meshMorphAnim->mNumKeys = numKeys;
|
meshMorphAnim->mNumKeys = numKeys;
|
||||||
meshMorphAnim->mKeys = new aiMeshMorphKey[numKeys];
|
meshMorphAnim->mKeys = new aiMeshMorphKey[numKeys];
|
||||||
unsigned int j = 0;
|
unsigned int j = 0;
|
||||||
for (auto animIt : *animData) {
|
for (auto &animIt : *animData) {
|
||||||
morphKeyData *keyData = animIt.second;
|
morphKeyData *keyData = animIt.second;
|
||||||
unsigned int numValuesAndWeights = static_cast<unsigned int>(keyData->values.size());
|
unsigned int numValuesAndWeights = static_cast<unsigned int>(keyData->values.size());
|
||||||
meshMorphAnim->mKeys[j].mNumValuesAndWeights = numValuesAndWeights;
|
meshMorphAnim->mKeys[j].mNumValuesAndWeights = numValuesAndWeights;
|
||||||
|
@ -3180,7 +3232,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
|
|
||||||
const float zero_epsilon = ai_epsilon;
|
const auto zero_epsilon = ai_epsilon;
|
||||||
|
|
||||||
const aiVector3D& preRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
|
const aiVector3D& preRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
|
||||||
if (ok && preRotation.SquareLength() > zero_epsilon) {
|
if (ok && preRotation.SquareLength() > zero_epsilon) {
|
||||||
|
@ -3625,6 +3677,12 @@ void FBXConverter::TransferDataToScene() {
|
||||||
|
|
||||||
std::swap_ranges(textures.begin(), textures.end(), mSceneOut->mTextures);
|
std::swap_ranges(textures.begin(), textures.end(), mSceneOut->mTextures);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mSkeletons.empty()) {
|
||||||
|
mSceneOut->mSkeletons = new aiSkeleton *[mSkeletons.size()];
|
||||||
|
mSceneOut->mNumSkeletons = static_cast<unsigned int>(mSkeletons.size());
|
||||||
|
std::swap_ranges(mSkeletons.begin(), mSkeletons.end(), mSceneOut->mSkeletons);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBXConverter::ConvertOrphanedEmbeddedTextures() {
|
void FBXConverter::ConvertOrphanedEmbeddedTextures() {
|
||||||
|
|
|
@ -75,7 +75,18 @@ typedef std::map<int64_t, morphKeyData*> morphAnimData;
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
namespace FBX {
|
namespace FBX {
|
||||||
|
|
||||||
|
class MeshGeometry;
|
||||||
|
|
||||||
|
using SkeletonBoneArray = std::vector<aiSkeletonBone *>;
|
||||||
|
using SkeletonBoneToMesh = std::map<aiMesh*, SkeletonBoneArray*>;
|
||||||
|
|
||||||
|
struct SkeletonBoneContainer {
|
||||||
|
std::vector<aiMesh *> MeshArray;
|
||||||
|
SkeletonBoneToMesh SkeletonBoneToMeshLookup;
|
||||||
|
};
|
||||||
|
|
||||||
class Document;
|
class Document;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a FBX #Document to #aiScene
|
* Convert a FBX #Document to #aiScene
|
||||||
* @param out Empty scene to be populated
|
* @param out Empty scene to be populated
|
||||||
|
@ -180,12 +191,12 @@ private:
|
||||||
void SetupNodeMetadata(const Model& model, aiNode& nd);
|
void SetupNodeMetadata(const Model& model, aiNode& nd);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertModel(const Model &model, aiNode *parent, aiNode *root_node);
|
void ConvertModel(const Model &model, aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
|
// MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
|
||||||
std::vector<unsigned int>
|
std::vector<unsigned int>
|
||||||
ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node);
|
ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
std::vector<unsigned int> ConvertLine(const LineGeometry& line, aiNode *root_node);
|
std::vector<unsigned int> ConvertLine(const LineGeometry& line, aiNode *root_node);
|
||||||
|
@ -194,15 +205,15 @@ private:
|
||||||
aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode *parent);
|
aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode *parent);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
unsigned int ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model,
|
unsigned int ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform,
|
||||||
aiNode *parent, aiNode *root_node);
|
aiNode *parent, aiNode *root_node);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
std::vector<unsigned int>
|
std::vector<unsigned int>
|
||||||
ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node);
|
ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform, aiNode *parent, aiNode *root_node);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
unsigned int ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, MatIndexArray::value_type index,
|
unsigned int ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform, MatIndexArray::value_type index,
|
||||||
aiNode *parent, aiNode *root_node);
|
aiNode *parent, aiNode *root_node);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -216,14 +227,19 @@ private:
|
||||||
* - outputVertStartIndices is only used when a material index is specified, it gives for
|
* - outputVertStartIndices is only used when a material index is specified, it gives for
|
||||||
* each output vertex the DOM index it maps to.
|
* each output vertex the DOM index it maps to.
|
||||||
*/
|
*/
|
||||||
void ConvertWeights(aiMesh *out, const MeshGeometry &geo, aiNode *parent = nullptr,
|
void ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform, aiNode *parent = nullptr,
|
||||||
unsigned int materialIndex = NO_MATERIAL_SEPARATION,
|
unsigned int materialIndex = NO_MATERIAL_SEPARATION,
|
||||||
std::vector<unsigned int> *outputVertStartIndices = nullptr);
|
std::vector<unsigned int> *outputVertStartIndices = nullptr);
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void ConvertWeightsToSkeleton(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
|
||||||
|
aiNode *parent, unsigned int materialIndex, std::vector<unsigned int> *outputVertStartIndices,
|
||||||
|
SkeletonBoneContainer &skeletonContainer);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,
|
void ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,
|
||||||
std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices,
|
std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices,
|
||||||
std::vector<size_t> &count_out_indices, aiNode *parent );
|
std::vector<size_t> &count_out_indices, const aiMatrix4x4 &absolute_transform, aiNode *parent);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo,
|
void ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo,
|
||||||
|
@ -296,7 +312,8 @@ private:
|
||||||
void ConvertAnimationStack(const AnimationStack& st);
|
void ConvertAnimationStack(const AnimationStack& st);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ProcessMorphAnimDatas(std::map<std::string, morphAnimData*>* morphAnimDatas, const BlendShapeChannel* bsc, const AnimationCurveNode* node);
|
void ProcessMorphAnimDatas(std::map<std::string, morphAnimData*>* morphAnimDatas,
|
||||||
|
const BlendShapeChannel* bsc, const AnimationCurveNode* node);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void GenerateNodeAnimations(std::vector<aiNodeAnim*>& node_anims,
|
void GenerateNodeAnimations(std::vector<aiNodeAnim*>& node_anims,
|
||||||
|
@ -445,6 +462,7 @@ private:
|
||||||
|
|
||||||
double anim_fps;
|
double anim_fps;
|
||||||
|
|
||||||
|
std::vector<aiSkeleton *> mSkeletons;
|
||||||
aiScene* const mSceneOut;
|
aiScene* const mSceneOut;
|
||||||
const FBX::Document& doc;
|
const FBX::Document& doc;
|
||||||
bool mRemoveEmptyBones;
|
bool mRemoveEmptyBones;
|
||||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2022, assimp team
|
Copyright (c) 2006-2022, assimp team
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
@ -58,16 +57,14 @@ namespace FBX {
|
||||||
using namespace Util;
|
using namespace Util;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Deformer::Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
Deformer::Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
|
||||||
: Object(id,element,name)
|
Object(id,element,name) {
|
||||||
{
|
|
||||||
const Scope& sc = GetRequiredScope(element);
|
const Scope& sc = GetRequiredScope(element);
|
||||||
|
|
||||||
const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
|
const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
|
||||||
props = GetPropertyTable(doc,"Deformer.Fbx" + classname,element,sc,true);
|
props = GetPropertyTable(doc,"Deformer.Fbx" + classname,element,sc,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Deformer::~Deformer()
|
Deformer::~Deformer()
|
||||||
{
|
{
|
||||||
|
|
|
@ -544,7 +544,7 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
|
||||||
ai_assert( count != 0 );
|
ai_assert( count != 0 );
|
||||||
ai_assert( count <= MAX_CLASSNAMES);
|
ai_assert( count <= MAX_CLASSNAMES);
|
||||||
|
|
||||||
size_t lengths[MAX_CLASSNAMES];
|
size_t lengths[MAX_CLASSNAMES] = {};
|
||||||
|
|
||||||
const size_t c = count;
|
const size_t c = count;
|
||||||
for (size_t i = 0; i < c; ++i) {
|
for (size_t i = 0; i < c; ++i) {
|
||||||
|
|
|
@ -164,7 +164,7 @@ class NodeAttribute : public Object {
|
||||||
public:
|
public:
|
||||||
NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
||||||
|
|
||||||
virtual ~NodeAttribute();
|
virtual ~NodeAttribute() = default;
|
||||||
|
|
||||||
const PropertyTable& Props() const {
|
const PropertyTable& Props() const {
|
||||||
ai_assert(props.get());
|
ai_assert(props.get());
|
||||||
|
@ -180,7 +180,7 @@ class CameraSwitcher : public NodeAttribute {
|
||||||
public:
|
public:
|
||||||
CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
||||||
|
|
||||||
virtual ~CameraSwitcher();
|
virtual ~CameraSwitcher() = default;
|
||||||
|
|
||||||
int CameraID() const {
|
int CameraID() const {
|
||||||
return cameraId;
|
return cameraId;
|
||||||
|
@ -225,7 +225,7 @@ class Camera : public NodeAttribute {
|
||||||
public:
|
public:
|
||||||
Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
||||||
|
|
||||||
virtual ~Camera();
|
virtual ~Camera() = default;
|
||||||
|
|
||||||
fbx_simple_property(Position, aiVector3D, aiVector3D(0,0,0))
|
fbx_simple_property(Position, aiVector3D, aiVector3D(0,0,0))
|
||||||
fbx_simple_property(UpVector, aiVector3D, aiVector3D(0,1,0))
|
fbx_simple_property(UpVector, aiVector3D, aiVector3D(0,1,0))
|
||||||
|
@ -250,21 +250,21 @@ public:
|
||||||
class Null : public NodeAttribute {
|
class Null : public NodeAttribute {
|
||||||
public:
|
public:
|
||||||
Null(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
Null(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
||||||
virtual ~Null();
|
virtual ~Null() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** DOM base class for FBX limb node markers attached to a node */
|
/** DOM base class for FBX limb node markers attached to a node */
|
||||||
class LimbNode : public NodeAttribute {
|
class LimbNode : public NodeAttribute {
|
||||||
public:
|
public:
|
||||||
LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
||||||
virtual ~LimbNode();
|
virtual ~LimbNode() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** DOM base class for FBX lights attached to a node */
|
/** DOM base class for FBX lights attached to a node */
|
||||||
class Light : public NodeAttribute {
|
class Light : public NodeAttribute {
|
||||||
public:
|
public:
|
||||||
Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
||||||
virtual ~Light();
|
virtual ~Light() = default;
|
||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
Type_Point,
|
Type_Point,
|
||||||
|
@ -690,7 +690,7 @@ using KeyValueList = std::vector<float>;
|
||||||
class AnimationCurve : public Object {
|
class AnimationCurve : public Object {
|
||||||
public:
|
public:
|
||||||
AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc);
|
AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc);
|
||||||
virtual ~AnimationCurve();
|
virtual ~AnimationCurve() = default;
|
||||||
|
|
||||||
/** get list of keyframe positions (time).
|
/** get list of keyframe positions (time).
|
||||||
* Invariant: |GetKeys()| > 0 */
|
* Invariant: |GetKeys()| > 0 */
|
||||||
|
@ -731,7 +731,7 @@ public:
|
||||||
AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
|
AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
|
||||||
const char *const *target_prop_whitelist = nullptr, size_t whitelist_size = 0);
|
const char *const *target_prop_whitelist = nullptr, size_t whitelist_size = 0);
|
||||||
|
|
||||||
virtual ~AnimationCurveNode();
|
virtual ~AnimationCurveNode() = default;
|
||||||
|
|
||||||
const PropertyTable& Props() const {
|
const PropertyTable& Props() const {
|
||||||
ai_assert(props.get());
|
ai_assert(props.get());
|
||||||
|
@ -776,7 +776,7 @@ using AnimationCurveNodeList = std::vector<const AnimationCurveNode*>;
|
||||||
class AnimationLayer : public Object {
|
class AnimationLayer : public Object {
|
||||||
public:
|
public:
|
||||||
AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc);
|
AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc);
|
||||||
virtual ~AnimationLayer();
|
virtual ~AnimationLayer() = default;
|
||||||
|
|
||||||
const PropertyTable& Props() const {
|
const PropertyTable& Props() const {
|
||||||
ai_assert(props.get());
|
ai_assert(props.get());
|
||||||
|
@ -799,7 +799,7 @@ using AnimationLayerList = std::vector<const AnimationLayer*>;
|
||||||
class AnimationStack : public Object {
|
class AnimationStack : public Object {
|
||||||
public:
|
public:
|
||||||
AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc);
|
AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc);
|
||||||
virtual ~AnimationStack();
|
virtual ~AnimationStack() = default;
|
||||||
|
|
||||||
fbx_simple_property(LocalStart, int64_t, 0L)
|
fbx_simple_property(LocalStart, int64_t, 0L)
|
||||||
fbx_simple_property(LocalStop, int64_t, 0L)
|
fbx_simple_property(LocalStop, int64_t, 0L)
|
||||||
|
|
|
@ -59,14 +59,12 @@ namespace Util {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// signal DOM construction error, this is always unrecoverable. Throws DeadlyImportError.
|
// signal DOM construction error, this is always unrecoverable. Throws DeadlyImportError.
|
||||||
void DOMError(const std::string& message, const Token& token)
|
void DOMError(const std::string& message, const Token& token) {
|
||||||
{
|
|
||||||
throw DeadlyImportError("FBX-DOM", Util::GetTokenText(&token), message);
|
throw DeadlyImportError("FBX-DOM", Util::GetTokenText(&token), message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void DOMError(const std::string& message, const Element* element /*= nullptr*/)
|
void DOMError(const std::string& message, const Element* element /*= nullptr*/) {
|
||||||
{
|
|
||||||
if(element) {
|
if(element) {
|
||||||
DOMError(message,element->KeyToken());
|
DOMError(message,element->KeyToken());
|
||||||
}
|
}
|
||||||
|
@ -76,8 +74,7 @@ void DOMError(const std::string& message, const Element* element /*= nullptr*/)
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// print warning, do return
|
// print warning, do return
|
||||||
void DOMWarning(const std::string& message, const Token& token)
|
void DOMWarning(const std::string& message, const Token& token) {
|
||||||
{
|
|
||||||
if(DefaultLogger::get()) {
|
if(DefaultLogger::get()) {
|
||||||
ASSIMP_LOG_WARN("FBX-DOM", Util::GetTokenText(&token), message);
|
ASSIMP_LOG_WARN("FBX-DOM", Util::GetTokenText(&token), message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,13 +74,11 @@ std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline
|
inline const T* ProcessSimpleConnection(const Connection& con,
|
||||||
const T* ProcessSimpleConnection(const Connection& con,
|
bool is_object_property_conn,
|
||||||
bool is_object_property_conn,
|
const char* name,
|
||||||
const char* name,
|
const Element& element,
|
||||||
const Element& element,
|
const char** propNameOut = nullptr) {
|
||||||
const char** propNameOut = nullptr)
|
|
||||||
{
|
|
||||||
if (is_object_property_conn && !con.PropertyName().length()) {
|
if (is_object_property_conn && !con.PropertyName().length()) {
|
||||||
DOMWarning("expected incoming " + std::string(name) +
|
DOMWarning("expected incoming " + std::string(name) +
|
||||||
" link to be an object-object connection, ignoring",
|
" link to be an object-object connection, ignoring",
|
||||||
|
|
|
@ -255,7 +255,7 @@ void FBXExporter::WriteBinaryHeader()
|
||||||
|
|
||||||
void FBXExporter::WriteBinaryFooter()
|
void FBXExporter::WriteBinaryFooter()
|
||||||
{
|
{
|
||||||
outfile->Write(NULL_RECORD.c_str(), NULL_RECORD.size(), 1);
|
outfile->Write(NULL_RECORD, NumNullRecords, 1);
|
||||||
|
|
||||||
outfile->Write(GENERIC_FOOTID.c_str(), GENERIC_FOOTID.size(), 1);
|
outfile->Write(GENERIC_FOOTID.c_str(), GENERIC_FOOTID.size(), 1);
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ struct ImportSettings {
|
||||||
readLights(true),
|
readLights(true),
|
||||||
readAnimations(true),
|
readAnimations(true),
|
||||||
readWeights(true),
|
readWeights(true),
|
||||||
|
useSkeleton(false),
|
||||||
preservePivots(true),
|
preservePivots(true),
|
||||||
optimizeEmptyAnimationCurves(true),
|
optimizeEmptyAnimationCurves(true),
|
||||||
useLegacyEmbeddedTextureNaming(false),
|
useLegacyEmbeddedTextureNaming(false),
|
||||||
|
@ -112,6 +113,11 @@ struct ImportSettings {
|
||||||
* Default value is true. */
|
* Default value is true. */
|
||||||
bool readWeights;
|
bool readWeights;
|
||||||
|
|
||||||
|
/** will convert all animation data into a skeleton (experimental)
|
||||||
|
* Default value is false.
|
||||||
|
*/
|
||||||
|
bool useSkeleton;
|
||||||
|
|
||||||
/** preserve transformation pivots and offsets. Since these can
|
/** preserve transformation pivots and offsets. Since these can
|
||||||
* not directly be represented in assimp, additional dummy
|
* not directly be represented in assimp, additional dummy
|
||||||
* nodes will be generated. Note that settings this to false
|
* nodes will be generated. Note that settings this to false
|
||||||
|
|
|
@ -90,12 +90,9 @@ static const aiImporterDesc desc = {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Constructor to be privately used by #Importer
|
// Constructor to be privately used by #Importer
|
||||||
FBXImporter::FBXImporter() {
|
FBXImporter::FBXImporter() :
|
||||||
}
|
mSettings() {
|
||||||
|
// empty
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// Destructor, private as well
|
|
||||||
FBXImporter::~FBXImporter() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -115,20 +112,21 @@ const aiImporterDesc *FBXImporter::GetInfo() const {
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Setup configuration properties for the loader
|
// Setup configuration properties for the loader
|
||||||
void FBXImporter::SetupProperties(const Importer *pImp) {
|
void FBXImporter::SetupProperties(const Importer *pImp) {
|
||||||
settings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
|
mSettings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
|
||||||
settings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
|
mSettings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
|
||||||
settings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
|
mSettings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
|
||||||
settings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true);
|
mSettings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true);
|
||||||
settings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
|
mSettings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
|
||||||
settings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
|
mSettings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
|
||||||
settings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
|
mSettings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
|
||||||
settings.readWeights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_WEIGHTS, true);
|
mSettings.readWeights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_WEIGHTS, true);
|
||||||
settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
|
mSettings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
|
||||||
settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
|
mSettings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
|
||||||
settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
|
mSettings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
|
||||||
settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
|
mSettings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
|
||||||
settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
|
mSettings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
|
||||||
settings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
|
mSettings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
|
||||||
|
mSettings.useSkeleton = pImp->GetPropertyBool(AI_CONFIG_FBX_USE_SKELETON_BONE_CONTAINER, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -155,7 +153,7 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||||
contents[contents.size() - 1] = 0;
|
contents[contents.size() - 1] = 0;
|
||||||
const char *const begin = &*contents.begin();
|
const char *const begin = &*contents.begin();
|
||||||
|
|
||||||
// broadphase tokenizing pass in which we identify the core
|
// broad-phase tokenized pass in which we identify the core
|
||||||
// syntax elements of FBX (brackets, commas, key:value mappings)
|
// syntax elements of FBX (brackets, commas, key:value mappings)
|
||||||
TokenList tokens;
|
TokenList tokens;
|
||||||
try {
|
try {
|
||||||
|
@ -173,15 +171,14 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||||
Parser parser(tokens, is_binary);
|
Parser parser(tokens, is_binary);
|
||||||
|
|
||||||
// take the raw parse-tree and convert it to a FBX DOM
|
// take the raw parse-tree and convert it to a FBX DOM
|
||||||
Document doc(parser, settings);
|
Document doc(parser, mSettings);
|
||||||
|
|
||||||
// convert the FBX DOM to aiScene
|
// convert the FBX DOM to aiScene
|
||||||
ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones);
|
ConvertToAssimpScene(pScene, doc, mSettings.removeEmptyBones);
|
||||||
|
|
||||||
// size relative to cm
|
// size relative to cm
|
||||||
float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor();
|
float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor();
|
||||||
if (size_relative_to_cm == 0.0)
|
if (size_relative_to_cm == 0.0) {
|
||||||
{
|
|
||||||
// BaseImporter later asserts that fileScale is non-zero.
|
// BaseImporter later asserts that fileScale is non-zero.
|
||||||
ThrowException("The UnitScaleFactor must be non-zero");
|
ThrowException("The UnitScaleFactor must be non-zero");
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,13 +69,14 @@ typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>
|
||||||
// -------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------
|
||||||
class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> {
|
class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> {
|
||||||
public:
|
public:
|
||||||
|
/// @brief The class constructor.
|
||||||
FBXImporter();
|
FBXImporter();
|
||||||
~FBXImporter() override;
|
|
||||||
|
|
||||||
// --------------------
|
/// @brief The class destructor, default implementation.
|
||||||
bool CanRead(const std::string &pFile,
|
~FBXImporter() override = default;
|
||||||
IOSystem *pIOHandler,
|
|
||||||
bool checkSig) const override;
|
/// @brief Will check the file for readability.
|
||||||
|
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// --------------------
|
// --------------------
|
||||||
|
@ -90,7 +91,7 @@ protected:
|
||||||
IOSystem *pIOHandler) override;
|
IOSystem *pIOHandler) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FBX::ImportSettings settings;
|
FBX::ImportSettings mSettings;
|
||||||
}; // !class FBXImporter
|
}; // !class FBXImporter
|
||||||
|
|
||||||
} // end of namespace Assimp
|
} // end of namespace Assimp
|
||||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2022, assimp team
|
Copyright (c) 2006-2022, assimp team
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
@ -54,18 +53,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "FBXImportSettings.h"
|
#include "FBXImportSettings.h"
|
||||||
#include "FBXDocumentUtil.h"
|
#include "FBXDocumentUtil.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
namespace FBX {
|
namespace FBX {
|
||||||
|
|
||||||
using namespace Util;
|
using namespace Util;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
|
Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc) :
|
||||||
: Object(id, element, name)
|
Object(id, element, name), skin() {
|
||||||
, skin()
|
const std::vector<const Connection*> &conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer");
|
||||||
{
|
|
||||||
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer");
|
|
||||||
for(const Connection* con : conns) {
|
for(const Connection* con : conns) {
|
||||||
const Skin* const sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element);
|
const Skin* const sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element);
|
||||||
if(sk) {
|
if(sk) {
|
||||||
|
@ -78,12 +74,6 @@ Geometry::Geometry(uint64_t id, const Element& element, const std::string& name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
Geometry::~Geometry()
|
|
||||||
{
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const std::vector<const BlendShape*>& Geometry::GetBlendShapes() const {
|
const std::vector<const BlendShape*>& Geometry::GetBlendShapes() const {
|
||||||
return blendShapes;
|
return blendShapes;
|
||||||
|
@ -183,18 +173,12 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
|
||||||
if(doc.Settings().readAllLayers || index == 0) {
|
if(doc.Settings().readAllLayers || index == 0) {
|
||||||
const Scope& layer = GetRequiredScope(*(*it).second);
|
const Scope& layer = GetRequiredScope(*(*it).second);
|
||||||
ReadLayer(layer);
|
ReadLayer(layer);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
FBXImporter::LogWarn("ignoring additional geometry layers");
|
FBXImporter::LogWarn("ignoring additional geometry layers");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
MeshGeometry::~MeshGeometry() {
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const std::vector<aiVector3D>& MeshGeometry::GetVertices() const {
|
const std::vector<aiVector3D>& MeshGeometry::GetVertices() const {
|
||||||
return m_vertices;
|
return m_vertices;
|
||||||
|
|
|
@ -55,22 +55,25 @@ namespace FBX {
|
||||||
/**
|
/**
|
||||||
* DOM base class for all kinds of FBX geometry
|
* DOM base class for all kinds of FBX geometry
|
||||||
*/
|
*/
|
||||||
class Geometry : public Object
|
class Geometry : public Object {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
|
/// @brief The class constructor with all parameters.
|
||||||
|
/// @param id The id.
|
||||||
|
/// @param element
|
||||||
|
/// @param name
|
||||||
|
/// @param doc
|
||||||
Geometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
|
Geometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
|
||||||
virtual ~Geometry();
|
virtual ~Geometry() = default;
|
||||||
|
|
||||||
/** Get the Skin attached to this geometry or nullptr */
|
/// Get the Skin attached to this geometry or nullptr
|
||||||
const Skin* DeformerSkin() const;
|
const Skin* DeformerSkin() const;
|
||||||
|
|
||||||
/** Get the BlendShape attached to this geometry or nullptr */
|
/// Get the BlendShape attached to this geometry or nullptr
|
||||||
const std::vector<const BlendShape*>& GetBlendShapes() const;
|
const std::vector<const BlendShape*>& GetBlendShapes() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Skin* skin;
|
const Skin* skin;
|
||||||
std::vector<const BlendShape*> blendShapes;
|
std::vector<const BlendShape*> blendShapes;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<int> MatIndexArray;
|
typedef std::vector<int> MatIndexArray;
|
||||||
|
@ -79,14 +82,13 @@ typedef std::vector<int> MatIndexArray;
|
||||||
/**
|
/**
|
||||||
* DOM class for FBX geometry of type "Mesh"
|
* DOM class for FBX geometry of type "Mesh"
|
||||||
*/
|
*/
|
||||||
class MeshGeometry : public Geometry
|
class MeshGeometry : public Geometry {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
/** The class constructor */
|
/** The class constructor */
|
||||||
MeshGeometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
|
MeshGeometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
|
||||||
|
|
||||||
/** The class destructor */
|
/** The class destructor */
|
||||||
virtual ~MeshGeometry();
|
virtual ~MeshGeometry() = default;
|
||||||
|
|
||||||
/** Get a list of all vertex points, non-unique*/
|
/** Get a list of all vertex points, non-unique*/
|
||||||
const std::vector<aiVector3D>& GetVertices() const;
|
const std::vector<aiVector3D>& GetVertices() const;
|
||||||
|
@ -130,6 +132,7 @@ public:
|
||||||
/** Determine the face to which a particular output vertex index belongs.
|
/** Determine the face to which a particular output vertex index belongs.
|
||||||
* This mapping is always unique. */
|
* This mapping is always unique. */
|
||||||
unsigned int FaceForVertexIndex( unsigned int in_index ) const;
|
unsigned int FaceForVertexIndex( unsigned int in_index ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ReadLayer( const Scope& layer );
|
void ReadLayer( const Scope& layer );
|
||||||
void ReadLayerElement( const Scope& layerElement );
|
void ReadLayerElement( const Scope& layerElement );
|
||||||
|
|
|
@ -57,114 +57,65 @@ namespace FBX {
|
||||||
using namespace Util;
|
using namespace Util;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
NodeAttribute::NodeAttribute(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
|
||||||
: Object(id,element,name)
|
Object(id, element, name), props() {
|
||||||
, props()
|
const Scope &sc = GetRequiredScope(element);
|
||||||
{
|
|
||||||
const Scope& sc = GetRequiredScope(element);
|
|
||||||
|
|
||||||
const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
|
const std::string &classname = ParseTokenAsString(GetRequiredToken(element, 2));
|
||||||
|
|
||||||
// hack on the deriving type but Null/LimbNode attributes are the only case in which
|
// hack on the deriving type but Null/LimbNode attributes are the only case in which
|
||||||
// the property table is by design absent and no warning should be generated
|
// the property table is by design absent and no warning should be generated
|
||||||
// for it.
|
// for it.
|
||||||
const bool is_null_or_limb = !strcmp(classname.c_str(), "Null") || !strcmp(classname.c_str(), "LimbNode");
|
const bool is_null_or_limb = !strcmp(classname.c_str(), "Null") || !strcmp(classname.c_str(), "LimbNode");
|
||||||
props = GetPropertyTable(doc,"NodeAttribute.Fbx" + classname,element,sc, is_null_or_limb);
|
props = GetPropertyTable(doc, "NodeAttribute.Fbx" + classname, element, sc, is_null_or_limb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
NodeAttribute::~NodeAttribute()
|
CameraSwitcher::CameraSwitcher(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
|
||||||
{
|
NodeAttribute(id, element, doc, name) {
|
||||||
// empty
|
const Scope &sc = GetRequiredScope(element);
|
||||||
}
|
const Element *const CameraId = sc["CameraId"];
|
||||||
|
const Element *const CameraName = sc["CameraName"];
|
||||||
|
const Element *const CameraIndexName = sc["CameraIndexName"];
|
||||||
|
|
||||||
|
if (CameraId) {
|
||||||
// ------------------------------------------------------------------------------------------------
|
cameraId = ParseTokenAsInt(GetRequiredToken(*CameraId, 0));
|
||||||
CameraSwitcher::CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
|
||||||
: NodeAttribute(id,element,doc,name)
|
|
||||||
{
|
|
||||||
const Scope& sc = GetRequiredScope(element);
|
|
||||||
const Element* const CameraId = sc["CameraId"];
|
|
||||||
const Element* const CameraName = sc["CameraName"];
|
|
||||||
const Element* const CameraIndexName = sc["CameraIndexName"];
|
|
||||||
|
|
||||||
if(CameraId) {
|
|
||||||
cameraId = ParseTokenAsInt(GetRequiredToken(*CameraId,0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(CameraName) {
|
if (CameraName) {
|
||||||
cameraName = GetRequiredToken(*CameraName,0).StringContents();
|
cameraName = GetRequiredToken(*CameraName, 0).StringContents();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(CameraIndexName && CameraIndexName->Tokens().size()) {
|
if (CameraIndexName && CameraIndexName->Tokens().size()) {
|
||||||
cameraIndexName = GetRequiredToken(*CameraIndexName,0).StringContents();
|
cameraIndexName = GetRequiredToken(*CameraIndexName, 0).StringContents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
CameraSwitcher::~CameraSwitcher()
|
Camera::Camera(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
|
||||||
{
|
NodeAttribute(id, element, doc, name) {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Camera::Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
Light::Light(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
|
||||||
: NodeAttribute(id,element,doc,name)
|
NodeAttribute(id, element, doc, name) {
|
||||||
{
|
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Camera::~Camera()
|
Null::Null(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
|
||||||
{
|
NodeAttribute(id, element, doc, name) {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Light::Light(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
LimbNode::LimbNode(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
|
||||||
: NodeAttribute(id,element,doc,name)
|
NodeAttribute(id, element, doc, name) {
|
||||||
{
|
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace FBX
|
||||||
|
} // namespace Assimp
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
#endif // ASSIMP_BUILD_NO_FBX_IMPORTER
|
||||||
Light::~Light()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
Null::Null(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
|
||||||
: NodeAttribute(id,element,doc,name)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
Null::~Null()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
LimbNode::LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
|
||||||
: NodeAttribute(id,element,doc,name)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
LimbNode::~LimbNode()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -162,12 +162,6 @@ Element::Element(const Token& key_token, Parser& parser) : key_token(key_token)
|
||||||
while(n->Type() != TokenType_KEY && n->Type() != TokenType_CLOSE_BRACKET);
|
while(n->Type() != TokenType_KEY && n->Type() != TokenType_CLOSE_BRACKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
Element::~Element()
|
|
||||||
{
|
|
||||||
// no need to delete tokens, they are owned by the parser
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Scope::Scope(Parser& parser,bool topLevel)
|
Scope::Scope(Parser& parser,bool topLevel)
|
||||||
{
|
{
|
||||||
|
@ -226,12 +220,6 @@ Parser::Parser (const TokenList& tokens, bool is_binary)
|
||||||
root.reset(new Scope(*this,true));
|
root.reset(new Scope(*this,true));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
Parser::~Parser()
|
|
||||||
{
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
TokenPtr Parser::AdvanceToNextToken()
|
TokenPtr Parser::AdvanceToNextToken()
|
||||||
{
|
{
|
||||||
|
@ -961,8 +949,7 @@ void ParseVectorDataArray(std::vector<float>& out, const Element& el)
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// read an array of uints
|
// read an array of uints
|
||||||
void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el)
|
void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el) {
|
||||||
{
|
|
||||||
out.resize( 0 );
|
out.resize( 0 );
|
||||||
const TokenList& tok = el.Tokens();
|
const TokenList& tok = el.Tokens();
|
||||||
if(tok.empty()) {
|
if(tok.empty()) {
|
||||||
|
@ -1186,7 +1173,6 @@ aiMatrix4x4 ReadMatrix(const Element& element)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// wrapper around ParseTokenAsString() with ParseError handling
|
// wrapper around ParseTokenAsString() with ParseError handling
|
||||||
std::string ParseTokenAsString(const Token& t)
|
std::string ParseTokenAsString(const Token& t)
|
||||||
|
|
|
@ -87,7 +87,7 @@ class Element
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Element(const Token& key_token, Parser& parser);
|
Element(const Token& key_token, Parser& parser);
|
||||||
~Element();
|
~Element() = default;
|
||||||
|
|
||||||
const Scope* Compound() const {
|
const Scope* Compound() const {
|
||||||
return compound.get();
|
return compound.get();
|
||||||
|
@ -160,7 +160,7 @@ public:
|
||||||
/** Parse given a token list. Does not take ownership of the tokens -
|
/** Parse given a token list. Does not take ownership of the tokens -
|
||||||
* the objects must persist during the entire parser lifetime */
|
* the objects must persist during the entire parser lifetime */
|
||||||
Parser (const TokenList& tokens,bool is_binary);
|
Parser (const TokenList& tokens,bool is_binary);
|
||||||
~Parser();
|
~Parser() = default;
|
||||||
|
|
||||||
const Scope& GetRootScope() const {
|
const Scope& GetRootScope() const {
|
||||||
return *root.get();
|
return *root.get();
|
||||||
|
|
|
@ -908,7 +908,7 @@ Ref<Node> FindSkeletonRootJoint(Ref<Skin> &skinRef) {
|
||||||
do {
|
do {
|
||||||
startNodeRef = parentNodeRef;
|
startNodeRef = parentNodeRef;
|
||||||
parentNodeRef = startNodeRef->parent;
|
parentNodeRef = startNodeRef->parent;
|
||||||
} while (!parentNodeRef->jointName.empty());
|
} while (parentNodeRef && !parentNodeRef->jointName.empty());
|
||||||
|
|
||||||
return parentNodeRef;
|
return parentNodeRef;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2022, assimp team
|
Copyright (c) 2006-2022, assimp team
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
@ -97,13 +96,14 @@ void SkeletonMeshBuilder::CreateGeometry(const aiNode *pNode) {
|
||||||
const aiMatrix4x4 &childTransform = pNode->mChildren[a]->mTransformation;
|
const aiMatrix4x4 &childTransform = pNode->mChildren[a]->mTransformation;
|
||||||
aiVector3D childpos(childTransform.a4, childTransform.b4, childTransform.c4);
|
aiVector3D childpos(childTransform.a4, childTransform.b4, childTransform.c4);
|
||||||
ai_real distanceToChild = childpos.Length();
|
ai_real distanceToChild = childpos.Length();
|
||||||
if (distanceToChild < 0.0001)
|
if (distanceToChild < ai_epsilon) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
aiVector3D up = aiVector3D(childpos).Normalize();
|
aiVector3D up = aiVector3D(childpos).Normalize();
|
||||||
|
|
||||||
aiVector3D orth(1.0, 0.0, 0.0);
|
aiVector3D orth(1.0, 0.0, 0.0);
|
||||||
if (std::fabs(orth * up) > 0.99)
|
if (std::fabs(orth * up) > 0.99) {
|
||||||
orth.Set(0.0, 1.0, 0.0);
|
orth.Set(0.0, 1.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
aiVector3D front = (up ^ orth).Normalize();
|
aiVector3D front = (up ^ orth).Normalize();
|
||||||
aiVector3D side = (front ^ up).Normalize();
|
aiVector3D side = (front ^ up).Normalize();
|
||||||
|
@ -183,8 +183,9 @@ void SkeletonMeshBuilder::CreateGeometry(const aiNode *pNode) {
|
||||||
// add all the vertices to the bone's influences
|
// add all the vertices to the bone's influences
|
||||||
bone->mNumWeights = numVertices;
|
bone->mNumWeights = numVertices;
|
||||||
bone->mWeights = new aiVertexWeight[numVertices];
|
bone->mWeights = new aiVertexWeight[numVertices];
|
||||||
for (unsigned int a = 0; a < numVertices; a++)
|
for (unsigned int a = 0; a < numVertices; ++a) {
|
||||||
bone->mWeights[a] = aiVertexWeight(vertexStartIndex + a, 1.0);
|
bone->mWeights[a] = aiVertexWeight(vertexStartIndex + a, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
// HACK: (thom) transform all vertices to the bone's local space. Should be done before adding
|
// HACK: (thom) transform all vertices to the bone's local space. Should be done before adding
|
||||||
// them to the array, but I'm tired now and I'm annoyed.
|
// them to the array, but I'm tired now and I'm annoyed.
|
||||||
|
@ -194,8 +195,9 @@ void SkeletonMeshBuilder::CreateGeometry(const aiNode *pNode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// and finally recurse into the children list
|
// and finally recurse into the children list
|
||||||
for (unsigned int a = 0; a < pNode->mNumChildren; a++)
|
for (unsigned int a = 0; a < pNode->mNumChildren; ++a) {
|
||||||
CreateGeometry(pNode->mChildren[a]);
|
CreateGeometry(pNode->mChildren[a]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -135,6 +135,9 @@ ASSIMP_API aiScene::aiScene() :
|
||||||
mNumCameras(0),
|
mNumCameras(0),
|
||||||
mCameras(nullptr),
|
mCameras(nullptr),
|
||||||
mMetaData(nullptr),
|
mMetaData(nullptr),
|
||||||
|
mName(),
|
||||||
|
mNumSkeletons(0),
|
||||||
|
mSkeletons(nullptr),
|
||||||
mPrivate(new Assimp::ScenePrivateData()) {
|
mPrivate(new Assimp::ScenePrivateData()) {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
@ -180,7 +183,8 @@ ASSIMP_API aiScene::~aiScene() {
|
||||||
delete[] mCameras;
|
delete[] mCameras;
|
||||||
|
|
||||||
aiMetadata::Dealloc(mMetaData);
|
aiMetadata::Dealloc(mMetaData);
|
||||||
mMetaData = nullptr;
|
|
||||||
|
delete[] mSkeletons;
|
||||||
|
|
||||||
delete static_cast<Assimp::ScenePrivateData *>(mPrivate);
|
delete static_cast<Assimp::ScenePrivateData *>(mPrivate);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,10 +43,10 @@
|
||||||
|
|
||||||
#include "crypt.h"
|
#include "crypt.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _MSC_VER
|
||||||
# pragma warning(push)
|
# pragma warning(push)
|
||||||
# pragma warning(disable : 4244)
|
# pragma warning(disable : 4244)
|
||||||
#endif // _WIN32
|
#endif // _MSC_VER
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
|
@ -164,8 +164,8 @@ int crypthead(const char *passwd, uint8_t *buf, int buf_size, uint32_t *pkeys,
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _MSC_VER
|
||||||
# pragma warning(pop)
|
# pragma warning(pop)
|
||||||
#endif // _WIN32
|
#endif // _MSC_VER
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
|
@ -23,8 +23,10 @@
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# define snprintf _snprintf
|
# define snprintf _snprintf
|
||||||
|
#ifdef _MSC_VER
|
||||||
# pragma warning(push)
|
# pragma warning(push)
|
||||||
# pragma warning(disable : 4131 4100)
|
# pragma warning(disable : 4131 4100)
|
||||||
|
#endif
|
||||||
# ifdef __clang__
|
# ifdef __clang__
|
||||||
# pragma clang diagnostic push
|
# pragma clang diagnostic push
|
||||||
# pragma clang diagnostic ignored "-Wunused-parameter"
|
# pragma clang diagnostic ignored "-Wunused-parameter"
|
||||||
|
@ -357,9 +359,9 @@ void fill_fopen64_filefunc(zlib_filefunc64_def *pzlib_filefunc_def)
|
||||||
pzlib_filefunc_def->opaque = NULL;
|
pzlib_filefunc_def->opaque = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _MSC_VER
|
||||||
# pragma warning(pop)
|
# pragma warning(pop)
|
||||||
# ifdef __clang__
|
# ifdef __clang__
|
||||||
# pragma clang diagnostic pop
|
# pragma clang diagnostic pop
|
||||||
# endif
|
# endif
|
||||||
#endif // _WIN32
|
#endif // _MSC_VER
|
||||||
|
|
|
@ -73,10 +73,10 @@
|
||||||
# define TRYFREE(p) {if (p) free(p);}
|
# define TRYFREE(p) {if (p) free(p);}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _MSC_VER
|
||||||
# pragma warning(push)
|
# pragma warning(push)
|
||||||
# pragma warning(disable : 4131 4244 4189 4245)
|
# pragma warning(disable : 4131 4244 4189 4245)
|
||||||
#endif // _WIN32
|
#endif // _MSC_VER
|
||||||
|
|
||||||
const char unz_copyright[] =
|
const char unz_copyright[] =
|
||||||
" unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
|
" unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
|
||||||
|
@ -1995,6 +1995,6 @@ extern int ZEXPORT unzEndOfFile(unzFile file)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _MSC_VER
|
||||||
# pragma warning(pop)
|
# pragma warning(pop)
|
||||||
#endif // _WIN32
|
#endif // _MSC_VER
|
|
@ -691,6 +691,15 @@ enum aiComponent
|
||||||
#define AI_CONFIG_FBX_CONVERT_TO_M \
|
#define AI_CONFIG_FBX_CONVERT_TO_M \
|
||||||
"AI_CONFIG_FBX_CONVERT_TO_M"
|
"AI_CONFIG_FBX_CONVERT_TO_M"
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
/** @brief Will enable the skeleton structo to store bone data.
|
||||||
|
*
|
||||||
|
* This will decouple the bone coupling to the mesh. This feature is
|
||||||
|
* experimental.
|
||||||
|
*/
|
||||||
|
#define AI_CONFIG_FBX_USE_SKELETON_BONE_CONTAINER \
|
||||||
|
"AI_CONFIG_FBX_USE_SKELETON_BONE_CONTAINER"
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** @brief Set the vertex animation keyframe to be imported
|
/** @brief Set the vertex animation keyframe to be imported
|
||||||
*
|
*
|
||||||
|
|
|
@ -120,7 +120,7 @@ extern "C" {
|
||||||
* primitive are actually present in a mesh. The #aiProcess_SortByPType flag
|
* primitive are actually present in a mesh. The #aiProcess_SortByPType flag
|
||||||
* executes a special post-processing algorithm which splits meshes with
|
* executes a special post-processing algorithm which splits meshes with
|
||||||
* *different* primitive types mixed up (e.g. lines and triangles) in several
|
* *different* primitive types mixed up (e.g. lines and triangles) in several
|
||||||
* 'clean' submeshes. Furthermore there is a configuration option (
|
* 'clean' sub-meshes. Furthermore there is a configuration option (
|
||||||
* #AI_CONFIG_PP_SBP_REMOVE) to force #aiProcess_SortByPType to remove
|
* #AI_CONFIG_PP_SBP_REMOVE) to force #aiProcess_SortByPType to remove
|
||||||
* specific kinds of primitives from the imported scene, completely and forever.
|
* specific kinds of primitives from the imported scene, completely and forever.
|
||||||
* In many cases you'll probably want to set this setting to
|
* In many cases you'll probably want to set this setting to
|
||||||
|
@ -269,12 +269,12 @@ struct aiBone {
|
||||||
unsigned int mNumWeights;
|
unsigned int mNumWeights;
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
|
#ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
|
||||||
// The bone armature node - used for skeleton conversion
|
/// The bone armature node - used for skeleton conversion
|
||||||
// you must enable aiProcess_PopulateArmatureData to populate this
|
/// you must enable aiProcess_PopulateArmatureData to populate this
|
||||||
C_STRUCT aiNode *mArmature;
|
C_STRUCT aiNode *mArmature;
|
||||||
|
|
||||||
// The bone node in the scene - used for skeleton conversion
|
/// The bone node in the scene - used for skeleton conversion
|
||||||
// you must enable aiProcess_PopulateArmatureData to populate this
|
/// you must enable aiProcess_PopulateArmatureData to populate this
|
||||||
C_STRUCT aiNode *mNode;
|
C_STRUCT aiNode *mNode;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -296,7 +296,7 @@ struct aiBone {
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
//! Default constructor
|
/// @brief Default constructor
|
||||||
aiBone() AI_NO_EXCEPT
|
aiBone() AI_NO_EXCEPT
|
||||||
: mName(),
|
: mName(),
|
||||||
mNumWeights(0),
|
mNumWeights(0),
|
||||||
|
@ -309,7 +309,7 @@ struct aiBone {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Copy constructor
|
/// @brief Copy constructor
|
||||||
aiBone(const aiBone &other) :
|
aiBone(const aiBone &other) :
|
||||||
mName(other.mName),
|
mName(other.mName),
|
||||||
mNumWeights(other.mNumWeights),
|
mNumWeights(other.mNumWeights),
|
||||||
|
@ -319,14 +319,27 @@ struct aiBone {
|
||||||
#endif
|
#endif
|
||||||
mWeights(nullptr),
|
mWeights(nullptr),
|
||||||
mOffsetMatrix(other.mOffsetMatrix) {
|
mOffsetMatrix(other.mOffsetMatrix) {
|
||||||
if (other.mWeights && other.mNumWeights) {
|
copyVertexWeights(other);
|
||||||
mWeights = new aiVertexWeight[mNumWeights];
|
}
|
||||||
::memcpy(mWeights, other.mWeights, mNumWeights * sizeof(aiVertexWeight));
|
|
||||||
|
void copyVertexWeights( const aiBone &other ) {
|
||||||
|
if (other.mWeights == nullptr || other.mNumWeights == 0) {
|
||||||
|
mWeights = nullptr;
|
||||||
|
mNumWeights = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mNumWeights = other.mNumWeights;
|
||||||
|
if (mWeights) {
|
||||||
|
delete[] mWeights;
|
||||||
|
}
|
||||||
|
|
||||||
|
mWeights = new aiVertexWeight[mNumWeights];
|
||||||
|
::memcpy(mWeights, other.mWeights, mNumWeights * sizeof(aiVertexWeight));
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Assignment operator
|
//! Assignment operator
|
||||||
aiBone &operator=(const aiBone &other) {
|
aiBone &operator = (const aiBone &other) {
|
||||||
if (this == &other) {
|
if (this == &other) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -334,21 +347,13 @@ struct aiBone {
|
||||||
mName = other.mName;
|
mName = other.mName;
|
||||||
mNumWeights = other.mNumWeights;
|
mNumWeights = other.mNumWeights;
|
||||||
mOffsetMatrix = other.mOffsetMatrix;
|
mOffsetMatrix = other.mOffsetMatrix;
|
||||||
|
copyVertexWeights(other);
|
||||||
if (other.mWeights && other.mNumWeights) {
|
|
||||||
if (mWeights) {
|
|
||||||
delete[] mWeights;
|
|
||||||
}
|
|
||||||
|
|
||||||
mWeights = new aiVertexWeight[mNumWeights];
|
|
||||||
::memcpy(mWeights, other.mWeights, mNumWeights * sizeof(aiVertexWeight));
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const aiBone &rhs) const {
|
bool operator==(const aiBone &rhs) const {
|
||||||
if (mName != rhs.mName || mNumWeights != rhs.mNumWeights) {
|
if (mName != rhs.mName || mNumWeights != rhs.mNumWeights ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -937,6 +942,100 @@ struct aiMesh {
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct aiSkeletonBone {
|
||||||
|
/// The parent bone index, is -1 one if this bone represents the root bone.
|
||||||
|
int mParent;
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
|
||||||
|
/// The bone armature node - used for skeleton conversion
|
||||||
|
/// you must enable aiProcess_PopulateArmatureData to populate this
|
||||||
|
C_STRUCT aiNode *mArmature;
|
||||||
|
|
||||||
|
/// The bone node in the scene - used for skeleton conversion
|
||||||
|
/// you must enable aiProcess_PopulateArmatureData to populate this
|
||||||
|
C_STRUCT aiNode *mNode;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/// @brief The number of weights
|
||||||
|
unsigned int mNumnWeights;
|
||||||
|
|
||||||
|
/// The mesh index, which will get influenced by the weight.
|
||||||
|
C_STRUCT aiMesh *mMeshId;
|
||||||
|
|
||||||
|
/// The influence weights of this bone, by vertex index.
|
||||||
|
C_STRUCT aiVertexWeight *mWeights;
|
||||||
|
|
||||||
|
/** Matrix that transforms from bone space to mesh space in bind pose.
|
||||||
|
*
|
||||||
|
* This matrix describes the position of the mesh
|
||||||
|
* in the local space of this bone when the skeleton was bound.
|
||||||
|
* Thus it can be used directly to determine a desired vertex position,
|
||||||
|
* given the world-space transform of the bone when animated,
|
||||||
|
* and the position of the vertex in mesh space.
|
||||||
|
*
|
||||||
|
* It is sometimes called an inverse-bind matrix,
|
||||||
|
* or inverse bind pose matrix.
|
||||||
|
*/
|
||||||
|
C_STRUCT aiMatrix4x4 mOffsetMatrix;
|
||||||
|
|
||||||
|
/// Matrix that transforms the locale bone in bind pose.
|
||||||
|
C_STRUCT aiMatrix4x4 mLocalMatrix;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
aiSkeletonBone() :
|
||||||
|
mParent(-1),
|
||||||
|
mArmature(nullptr),
|
||||||
|
mNode(nullptr),
|
||||||
|
mNumnWeights(0),
|
||||||
|
mMeshId(nullptr),
|
||||||
|
mWeights(nullptr),
|
||||||
|
mOffsetMatrix(),
|
||||||
|
mLocalMatrix() {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
~aiSkeletonBone() {
|
||||||
|
delete[] mWeights;
|
||||||
|
mWeights = nullptr;
|
||||||
|
}
|
||||||
|
#endif // __cplusplus
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
struct aiSkeleton {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
C_STRUCT aiString mName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
unsigned int mNumBones;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
C_STRUCT aiSkeletonBone **mBones;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
aiSkeleton() AI_NO_EXCEPT : mName(), mNumBones(0), mBones(nullptr) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
~aiSkeleton() {
|
||||||
|
delete[] mBones;
|
||||||
|
}
|
||||||
|
#endif // __cplusplus
|
||||||
|
};
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif //! extern "C"
|
#endif //! extern "C"
|
||||||
|
|
|
@ -79,8 +79,7 @@ extern "C" {
|
||||||
* the imported scene does consist of only a single root node without children.
|
* the imported scene does consist of only a single root node without children.
|
||||||
*/
|
*/
|
||||||
// -------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------
|
||||||
struct ASSIMP_API aiNode
|
struct ASSIMP_API aiNode {
|
||||||
{
|
|
||||||
/** The name of the node.
|
/** The name of the node.
|
||||||
*
|
*
|
||||||
* The name might be empty (length of zero) but all nodes which
|
* The name might be empty (length of zero) but all nodes which
|
||||||
|
@ -343,6 +342,16 @@ struct aiScene
|
||||||
*/
|
*/
|
||||||
C_STRUCT aiString mName;
|
C_STRUCT aiString mName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
unsigned int mNumSkeletons;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
C_STRUCT aiSkeleton **mSkeletons;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
//! Default constructor - set everything to 0/nullptr
|
//! Default constructor - set everything to 0/nullptr
|
||||||
|
@ -383,6 +392,10 @@ struct aiScene
|
||||||
return mAnimations != nullptr && mNumAnimations > 0;
|
return mAnimations != nullptr && mNumAnimations > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasSkeletons() const {
|
||||||
|
return mSkeletons != nullptr && mNumSkeletons > 0;
|
||||||
|
}
|
||||||
|
|
||||||
//! Returns a short filename from a full path
|
//! Returns a short filename from a full path
|
||||||
static const char* GetShortFilename(const char* filename) {
|
static const char* GetShortFilename(const char* filename) {
|
||||||
const char* lastSlash = strrchr(filename, '/');
|
const char* lastSlash = strrchr(filename, '/');
|
||||||
|
|
Binary file not shown.
|
@ -423,3 +423,10 @@ TEST_F(utFBXImporterExporter, importMaxPbrMaterialsSpecularGloss) {
|
||||||
ASSERT_EQ(mat->Get("$raw.3dsMax|main|emit_color", aiTextureType_NONE, 0, emitColor), aiReturn_SUCCESS);
|
ASSERT_EQ(mat->Get("$raw.3dsMax|main|emit_color", aiTextureType_NONE, 0, emitColor), aiReturn_SUCCESS);
|
||||||
EXPECT_EQ(emitColor, aiColor4D(1, 0, 1, 1));
|
EXPECT_EQ(emitColor, aiColor4D(1, 0, 1, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(utFBXImporterExporter, importSkeletonTest) {
|
||||||
|
Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/animation_with_skeleton.fbx", aiProcess_ValidateDataStructure);
|
||||||
|
ASSERT_NE(nullptr, scene);
|
||||||
|
ASSERT_TRUE(scene->mRootNode);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue