diff --git a/code/AssetLib/FBX/FBXAnimation.cpp b/code/AssetLib/FBX/FBXAnimation.cpp index 2fa3b7b05..af92ebe51 100644 --- a/code/AssetLib/FBX/FBXAnimation.cpp +++ b/code/AssetLib/FBX/FBXAnimation.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - All rights reserved. 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, 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); } -// ------------------------------------------------------------------------------------------------ -AnimationCurveNode::~AnimationCurveNode() { - // empty -} - // ------------------------------------------------------------------------------------------------ const AnimationCurveMap &AnimationCurveNode::Curves() const { 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); } -// ------------------------------------------------------------------------------------------------ -AnimationLayer::~AnimationLayer() { - // empty -} - // ------------------------------------------------------------------------------------------------ AnimationCurveNodeList AnimationLayer::Nodes(const char *const *target_prop_whitelist /*= nullptr*/, 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 Assimp diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index e8cfe1dc0..34a97c889 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -907,7 +907,6 @@ void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root meshes.reserve(geos.size()); for (const Geometry *geo : geos) { - const MeshGeometry *const mesh = dynamic_cast(geo); const LineGeometry *const line = dynamic_cast(geo); if (mesh) { @@ -1151,8 +1150,10 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c 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, absolute_transform, parent, NO_MATERIAL_SEPARATION, nullptr); + } else if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr && doc.Settings().useSkeleton) { + ConvertWeightsToSkeleton(out_mesh, mesh, absolute_transform, parent, NO_MATERIAL_SEPARATION, nullptr); } std::vector animMeshes; @@ -1435,25 +1436,35 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co return static_cast(mMeshes.size() - 1); } -void ConvertWeightsToSkeleton(const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform, aiNode *parent, unsigned int materialIndex, - std::vector *outputVertStartIndices) { - ai_assert(geo.DeformerSkin() != nullptr); +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; +} - aiSkeleton *skeleton = new aiSkeleton; - const Skin &sk = *geo.DeformerSkin(); - try { - for (auto &cluster : sk.Clusters()) { - const WeightIndexArray &indices = cluster->GetIndices(); - const MatIndexArray &mats = geo.GetMaterialIndices(); +void FBXConverter::ConvertWeightsToSkeleton(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform, aiNode *parent, unsigned int materialIndex, + std::vector *outputVertStartIndices, SkeletonBoneContainer &skeletonContainer) { - aiMatrix4x4 transform = cluster->Transform(); - for (WeightIndexArray::value_type index : indices) { - unsigned int count = 0; - const unsigned int *out_idx = geo.ToOutputVertexIndex(index, count); - } - } - } catch (...) { + 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, @@ -1539,12 +1550,11 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, out->mBones = nullptr; out->mNumBones = 0; return; - } else { - out->mBones = new aiBone *[bones.size()](); - out->mNumBones = static_cast(bones.size()); + } - std::swap_ranges(bones.begin(), bones.end(), out->mBones); - } + out->mBones = new aiBone *[bones.size()](); + out->mNumBones = static_cast(bones.size()); + std::swap_ranges(bones.begin(), bones.end(), out->mBones); } void FBXConverter::ConvertCluster(std::vector &local_mesh_bones, const Cluster *cluster, diff --git a/code/AssetLib/FBX/FBXConverter.h b/code/AssetLib/FBX/FBXConverter.h index becfdb3e8..a393f9ba0 100644 --- a/code/AssetLib/FBX/FBXConverter.h +++ b/code/AssetLib/FBX/FBXConverter.h @@ -75,7 +75,18 @@ typedef std::map morphAnimData; namespace Assimp { namespace FBX { +class MeshGeometry; + +using SkeletonBoneArray = std::vector; +using SkeletonBoneToMesh = std::map; + +struct SkeletonBoneContainer { + std::vector MeshArray; + SkeletonBoneToMesh SkeletonBoneToMeshLookup; +}; + class Document; + /** * Convert a FBX #Document to #aiScene * @param out Empty scene to be populated @@ -224,6 +235,11 @@ private: aiNode *parent = nullptr, unsigned int materialIndex = NO_MATERIAL_SEPARATION, std::vector *outputVertStartIndices = nullptr); + // ------------------------------------------------------------------------------------------------ + void ConvertWeightsToSkeleton(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform, + aiNode *parent, unsigned int materialIndex, std::vector *outputVertStartIndices, + SkeletonBoneContainer &skeletonContainer); + // ------------------------------------------------------------------------------------------------ void ConvertCluster(std::vector &local_mesh_bones, const Cluster *cl, std::vector &out_indices, std::vector &index_out_indices, @@ -301,7 +317,8 @@ private: void ConvertAnimationStack(const AnimationStack& st); // ------------------------------------------------------------------------------------------------ - void ProcessMorphAnimDatas(std::map* morphAnimDatas, const BlendShapeChannel* bsc, const AnimationCurveNode* node); + void ProcessMorphAnimDatas(std::map* morphAnimDatas, + const BlendShapeChannel* bsc, const AnimationCurveNode* node); // ------------------------------------------------------------------------------------------------ void GenerateNodeAnimations(std::vector& node_anims, diff --git a/code/AssetLib/FBX/FBXDocument.cpp b/code/AssetLib/FBX/FBXDocument.cpp index f228b1749..5bbc5a09c 100644 --- a/code/AssetLib/FBX/FBXDocument.cpp +++ b/code/AssetLib/FBX/FBXDocument.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -68,23 +67,13 @@ namespace FBX { using namespace Util; // ------------------------------------------------------------------------------------------------ -LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc) -: doc(doc) -, element(element) -, id(id) -, flags() { +LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc) : + doc(doc), element(element), id(id), flags() { // empty } // ------------------------------------------------------------------------------------------------ -LazyObject::~LazyObject() -{ - // empty -} - -// ------------------------------------------------------------------------------------------------ -const Object* LazyObject::Get(bool dieOnError) -{ +const Object* LazyObject::Get(bool dieOnError) { if(IsBeingConstructed() || FailedToConstruct()) { return nullptr; } @@ -234,17 +223,8 @@ const Object* LazyObject::Get(bool dieOnError) } // ------------------------------------------------------------------------------------------------ -Object::Object(uint64_t id, const Element& element, const std::string& name) -: element(element) -, name(name) -, id(id) -{ - // empty -} - -// ------------------------------------------------------------------------------------------------ -Object::~Object() -{ +Object::Object(uint64_t id, const Element& element, const std::string& name) : + element(element), name(name), id(id) { // empty } @@ -254,12 +234,6 @@ FileGlobalSettings::FileGlobalSettings(const Document &doc, std::shared_ptr Document::GetConnectionsSequenced(uint64_t id, co // ------------------------------------------------------------------------------------------------ std::vector Document::GetConnectionsSequenced(uint64_t id, bool is_src, - const ConnectionMap& conns, - const char* const* classnames, - size_t count) const - -{ + const ConnectionMap& conns, + const char* const* classnames, + size_t count) const { ai_assert(classnames); ai_assert( count != 0 ); ai_assert( count <= MAX_CLASSNAMES); - size_t lengths[MAX_CLASSNAMES]; + size_t lengths[MAX_CLASSNAMES] = {}; const size_t c = count; for (size_t i = 0; i < c; ++i) { @@ -657,9 +629,7 @@ std::vector Document::GetConnectionsByDestinationSequenced(ui // ------------------------------------------------------------------------------------------------ std::vector Document::GetConnectionsByDestinationSequenced(uint64_t dest, - const char* const* classnames, size_t count) const - -{ + const char* const* classnames, size_t count) const { return GetConnectionsSequenced(dest, false, ConnectionsByDestination(),classnames, count); } diff --git a/code/AssetLib/FBX/FBXDocument.h b/code/AssetLib/FBX/FBXDocument.h index bac7e7769..245874b5c 100644 --- a/code/AssetLib/FBX/FBXDocument.h +++ b/code/AssetLib/FBX/FBXDocument.h @@ -89,7 +89,7 @@ class LazyObject { public: LazyObject(uint64_t id, const Element& element, const Document& doc); - ~LazyObject(); + ~LazyObject() = default; const Object* Get(bool dieOnError = false); @@ -139,7 +139,7 @@ class Object { public: Object(uint64_t id, const Element& element, const std::string& name); - virtual ~Object(); + virtual ~Object() = default; const Element& SourceElement() const { return element; @@ -165,7 +165,7 @@ class NodeAttribute : public Object { public: NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name); - virtual ~NodeAttribute(); + virtual ~NodeAttribute() = default; const PropertyTable& Props() const { ai_assert(props.get()); @@ -181,7 +181,7 @@ class CameraSwitcher : public NodeAttribute { public: CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name); - virtual ~CameraSwitcher(); + virtual ~CameraSwitcher() = default; int CameraID() const { return cameraId; @@ -226,7 +226,7 @@ class Camera : public NodeAttribute { public: 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(UpVector, aiVector3D, aiVector3D(0,1,0)) @@ -251,21 +251,21 @@ public: class Null : public NodeAttribute { public: 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 */ class LimbNode : public NodeAttribute { public: 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 */ class Light : public NodeAttribute { public: Light(uint64_t id, const Element& element, const Document& doc, const std::string& name); - virtual ~Light(); + virtual ~Light() = default; enum Type { @@ -697,7 +697,7 @@ typedef std::vector KeyValueList; class AnimationCurve : public Object { public: 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). * Invariant: |GetKeys()| > 0 */ @@ -738,7 +738,7 @@ public: 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); - virtual ~AnimationCurveNode(); + virtual ~AnimationCurveNode() = default; const PropertyTable& Props() const { ai_assert(props.get()); @@ -783,7 +783,7 @@ typedef std::vector AnimationCurveNodeList; class AnimationLayer : public Object { public: AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc); - virtual ~AnimationLayer(); + virtual ~AnimationLayer() = default; const PropertyTable& Props() const { ai_assert(props.get()); @@ -806,7 +806,7 @@ typedef std::vector AnimationLayerList; class AnimationStack : public Object { public: 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(LocalStop, int64_t, 0L) @@ -1022,7 +1022,7 @@ class FileGlobalSettings { public: FileGlobalSettings(const Document& doc, std::shared_ptr props); - ~FileGlobalSettings(); + ~FileGlobalSettings() = default; const PropertyTable& Props() const { ai_assert(props.get()); diff --git a/code/AssetLib/FBX/FBXMeshGeometry.h b/code/AssetLib/FBX/FBXMeshGeometry.h index 3eb279bed..ad24877e4 100644 --- a/code/AssetLib/FBX/FBXMeshGeometry.h +++ b/code/AssetLib/FBX/FBXMeshGeometry.h @@ -132,6 +132,7 @@ public: /** Determine the face to which a particular output vertex index belongs. * This mapping is always unique. */ unsigned int FaceForVertexIndex( unsigned int in_index ) const; + private: void ReadLayer( const Scope& layer ); void ReadLayerElement( const Scope& layerElement ); diff --git a/code/AssetLib/FBX/FBXNodeAttribute.cpp b/code/AssetLib/FBX/FBXNodeAttribute.cpp index a144f417a..34fcdcf77 100644 --- a/code/AssetLib/FBX/FBXNodeAttribute.cpp +++ b/code/AssetLib/FBX/FBXNodeAttribute.cpp @@ -57,114 +57,65 @@ namespace FBX { using namespace Util; // ------------------------------------------------------------------------------------------------ -NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name) -: Object(id,element,name) -, props() -{ - const Scope& sc = GetRequiredScope(element); +NodeAttribute::NodeAttribute(uint64_t id, const Element &element, const Document &doc, const std::string &name) : + Object(id, element, name), props() { + 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 // the property table is by design absent and no warning should be generated // for it. 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() -{ - // empty -} +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"]; - -// ------------------------------------------------------------------------------------------------ -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 (CameraId) { + cameraId = ParseTokenAsInt(GetRequiredToken(*CameraId, 0)); } - if(CameraName) { - cameraName = GetRequiredToken(*CameraName,0).StringContents(); + if (CameraName) { + cameraName = GetRequiredToken(*CameraName, 0).StringContents(); } - if(CameraIndexName && CameraIndexName->Tokens().size()) { - cameraIndexName = GetRequiredToken(*CameraIndexName,0).StringContents(); + if (CameraIndexName && CameraIndexName->Tokens().size()) { + 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 } // ------------------------------------------------------------------------------------------------ -Camera::Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name) -: NodeAttribute(id,element,doc,name) -{ +Light::Light(uint64_t id, const Element &element, const Document &doc, const std::string &name) : + NodeAttribute(id, element, doc, name) { // empty } // ------------------------------------------------------------------------------------------------ -Camera::~Camera() -{ +Null::Null(uint64_t id, const Element &element, const Document &doc, const std::string &name) : + NodeAttribute(id, element, doc, name) { // empty } // ------------------------------------------------------------------------------------------------ -Light::Light(uint64_t id, const Element& element, const Document& doc, const std::string& name) -: NodeAttribute(id,element,doc,name) -{ +LimbNode::LimbNode(uint64_t id, const Element &element, const Document &doc, const std::string &name) : + NodeAttribute(id, element, doc, name) { // empty } +} // namespace FBX +} // namespace Assimp -// ------------------------------------------------------------------------------------------------ -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 +#endif // ASSIMP_BUILD_NO_FBX_IMPORTER diff --git a/code/AssetLib/FBX/FBXParser.cpp b/code/AssetLib/FBX/FBXParser.cpp index 7cb7ae739..488e075dc 100644 --- a/code/AssetLib/FBX/FBXParser.cpp +++ b/code/AssetLib/FBX/FBXParser.cpp @@ -949,8 +949,7 @@ void ParseVectorDataArray(std::vector& out, const Element& el) // ------------------------------------------------------------------------------------------------ // read an array of uints -void ParseVectorDataArray(std::vector& out, const Element& el) -{ +void ParseVectorDataArray(std::vector& out, const Element& el) { out.resize( 0 ); const TokenList& tok = el.Tokens(); if(tok.empty()) { @@ -1174,7 +1173,6 @@ aiMatrix4x4 ReadMatrix(const Element& element) return result; } - // ------------------------------------------------------------------------------------------------ // wrapper around ParseTokenAsString() with ParseError handling std::string ParseTokenAsString(const Token& t) diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index cd334f786..23ee14a9d 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -946,6 +946,7 @@ 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 @@ -959,6 +960,9 @@ struct aiSkeletonBone { /// @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; @@ -984,6 +988,7 @@ struct aiSkeletonBone { mArmature(nullptr), mNode(nullptr), mNumnWeights(0), + mMeshId(nullptr), mWeights(nullptr), mOffsetMatrix(), mLocalMatrix() {