|
@@ -2,7 +2,8 @@
|
|
|
Open Asset Import Library (assimp)
|
|
|
----------------------------------------------------------------------
|
|
|
|
|
|
-Copyright (c) 2006-2017, assimp team
|
|
|
+Copyright (c) 2006-2018, assimp team
|
|
|
+
|
|
|
|
|
|
All rights reserved.
|
|
|
|
|
@@ -45,7 +46,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
#ifndef INCLUDED_AI_FBX_CONVERTER_H
|
|
|
#define INCLUDED_AI_FBX_CONVERTER_H
|
|
|
|
|
|
+#include "FBXParser.h"
|
|
|
+#include "FBXMeshGeometry.h"
|
|
|
+#include "FBXDocument.h"
|
|
|
+#include "FBXUtil.h"
|
|
|
+#include "FBXProperties.h"
|
|
|
+#include "FBXImporter.h"
|
|
|
+#include <assimp/anim.h>
|
|
|
+#include <assimp/material.h>
|
|
|
+#include <assimp/light.h>
|
|
|
+#include <assimp/texture.h>
|
|
|
+#include <assimp/camera.h>
|
|
|
+#include <assimp/StringComparison.h>
|
|
|
+
|
|
|
struct aiScene;
|
|
|
+struct aiNode;
|
|
|
+struct aiMaterial;
|
|
|
|
|
|
namespace Assimp {
|
|
|
namespace FBX {
|
|
@@ -59,6 +75,373 @@ class Document;
|
|
|
*/
|
|
|
void ConvertToAssimpScene(aiScene* out, const Document& doc);
|
|
|
|
|
|
+/** Dummy class to encapsulate the conversion process */
|
|
|
+class Converter {
|
|
|
+public:
|
|
|
+ /**
|
|
|
+ * The different parts that make up the final local transformation of a fbx-node
|
|
|
+ */
|
|
|
+ enum TransformationComp {
|
|
|
+ TransformationComp_Translation = 0,
|
|
|
+ TransformationComp_RotationOffset,
|
|
|
+ TransformationComp_RotationPivot,
|
|
|
+ TransformationComp_PreRotation,
|
|
|
+ TransformationComp_Rotation,
|
|
|
+ TransformationComp_PostRotation,
|
|
|
+ TransformationComp_RotationPivotInverse,
|
|
|
+ TransformationComp_ScalingOffset,
|
|
|
+ TransformationComp_ScalingPivot,
|
|
|
+ TransformationComp_Scaling,
|
|
|
+ TransformationComp_ScalingPivotInverse,
|
|
|
+ TransformationComp_GeometricTranslation,
|
|
|
+ TransformationComp_GeometricRotation,
|
|
|
+ TransformationComp_GeometricScaling,
|
|
|
+
|
|
|
+ TransformationComp_MAXIMUM
|
|
|
+ };
|
|
|
+
|
|
|
+public:
|
|
|
+ Converter(aiScene* out, const Document& doc);
|
|
|
+ ~Converter();
|
|
|
+
|
|
|
+private:
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ // find scene root and trigger recursive scene conversion
|
|
|
+ void ConvertRootNode();
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ // collect and assign child nodes
|
|
|
+ void ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform = aiMatrix4x4());
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void ConvertLights(const Model& model);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void ConvertCameras(const Model& model);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void ConvertLight(const Model& model, const Light& light);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void ConvertCamera(const Model& model, const Camera& cam);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ // this returns unified names usable within assimp identifiers (i.e. no space characters -
|
|
|
+ // while these would be allowed, they are a potential trouble spot so better not use them).
|
|
|
+ const char* NameTransformationComp(TransformationComp comp);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ // note: this returns the REAL fbx property names
|
|
|
+ const char* NameTransformationCompProperty(TransformationComp comp);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ aiVector3D TransformationCompDefaultValue(TransformationComp comp);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void GetRotationMatrix(Model::RotOrder mode, const aiVector3D& rotation, aiMatrix4x4& out);
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ /**
|
|
|
+ * checks if a node has more than just scaling, rotation and translation components
|
|
|
+ */
|
|
|
+ bool NeedsComplexTransformationChain(const Model& model);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ // note: name must be a FixNodeName() result
|
|
|
+ std::string NameTransformationChainNode(const std::string& name, TransformationComp comp);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ /**
|
|
|
+ * note: memory for output_nodes will be managed by the caller
|
|
|
+ */
|
|
|
+ void GenerateTransformationNodeChain(const Model& model, std::vector<aiNode*>& output_nodes);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void SetupNodeMetadata(const Model& model, aiNode& nd);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void ConvertModel(const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
|
|
|
+ std::vector<unsigned int> ConvertMesh(const MeshGeometry& mesh, const Model& model,
|
|
|
+ const aiMatrix4x4& node_global_transform);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ aiMesh* SetupEmptyMesh(const MeshGeometry& mesh);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model,
|
|
|
+ const aiMatrix4x4& node_global_transform);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ std::vector<unsigned int> ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
|
|
|
+ const aiMatrix4x4& node_global_transform);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ unsigned int ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
|
|
|
+ MatIndexArray::value_type index,
|
|
|
+ const aiMatrix4x4& node_global_transform);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits<unsigned int>::max() */
|
|
|
+ static_cast<unsigned int>(-1);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ /**
|
|
|
+ * - if materialIndex == NO_MATERIAL_SEPARATION, materials are not taken into
|
|
|
+ * account when determining which weights to include.
|
|
|
+ * - outputVertStartIndices is only used when a material index is specified, it gives for
|
|
|
+ * each output vertex the DOM index it maps to.
|
|
|
+ */
|
|
|
+ void ConvertWeights(aiMesh* out, const Model& model, const MeshGeometry& geo,
|
|
|
+ const aiMatrix4x4& node_global_transform = aiMatrix4x4(),
|
|
|
+ unsigned int materialIndex = NO_MATERIAL_SEPARATION,
|
|
|
+ std::vector<unsigned int>* outputVertStartIndices = NULL);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void ConvertCluster(std::vector<aiBone*>& bones, const Model& /*model*/, const Cluster& cl,
|
|
|
+ std::vector<size_t>& out_indices,
|
|
|
+ std::vector<size_t>& index_out_indices,
|
|
|
+ std::vector<size_t>& count_out_indices,
|
|
|
+ const aiMatrix4x4& node_global_transform);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo,
|
|
|
+ MatIndexArray::value_type materialIndex);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ unsigned int GetDefaultMaterial();
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ // Material -> aiMaterial
|
|
|
+ unsigned int ConvertMaterial(const Material& material, const MeshGeometry* const mesh);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ // Video -> aiTexture
|
|
|
+ unsigned int ConvertVideo(const Video& video);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures,
|
|
|
+ const std::string& propName,
|
|
|
+ aiTextureType target, const MeshGeometry* const mesh);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void TrySetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures,
|
|
|
+ const std::string& propName,
|
|
|
+ aiTextureType target, const MeshGeometry* const mesh);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void SetTextureProperties(aiMaterial* out_mat, const TextureMap& textures, const MeshGeometry* const mesh);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ aiColor3D GetColorPropertyFromMaterial(const PropertyTable& props, const std::string& baseName,
|
|
|
+ bool& result);
|
|
|
+ aiColor3D GetColorPropertyFactored(const PropertyTable& props, const std::string& colorName,
|
|
|
+ const std::string& factorName, bool& result, bool useTemplate = true);
|
|
|
+ aiColor3D GetColorProperty(const PropertyTable& props, const std::string& colorName,
|
|
|
+ bool& result, bool useTemplate = true);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void SetShadingPropertiesCommon(aiMaterial* out_mat, const PropertyTable& props);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ // get the number of fps for a FrameRate enumerated value
|
|
|
+ static double FrameRateToDouble(FileGlobalSettings::FrameRate fp, double customFPSVal = -1.0);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ // convert animation data to aiAnimation et al
|
|
|
+ void ConvertAnimations();
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ // rename a node already partially converted. fixed_name is a string previously returned by
|
|
|
+ // FixNodeName, new_name specifies the string FixNodeName should return on all further invocations
|
|
|
+ // which would previously have returned the old value.
|
|
|
+ //
|
|
|
+ // this also updates names in node animations, cameras and light sources and is thus slow.
|
|
|
+ //
|
|
|
+ // NOTE: the caller is responsible for ensuring that the new name is unique and does
|
|
|
+ // not collide with any other identifiers. The best way to ensure this is to only
|
|
|
+ // append to the old name, which is guaranteed to match these requirements.
|
|
|
+ void RenameNode(const std::string& fixed_name, const std::string& new_name);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ // takes a fbx node name and returns the identifier to be used in the assimp output scene.
|
|
|
+ // the function is guaranteed to provide consistent results over multiple invocations
|
|
|
+ // UNLESS RenameNode() is called for a particular node name.
|
|
|
+ std::string FixNodeName(const std::string& name);
|
|
|
+
|
|
|
+ typedef std::map<const AnimationCurveNode*, const AnimationLayer*> LayerMap;
|
|
|
+
|
|
|
+ // XXX: better use multi_map ..
|
|
|
+ typedef std::map<std::string, std::vector<const AnimationCurveNode*> > NodeMap;
|
|
|
+
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void ConvertAnimationStack(const AnimationStack& st);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void GenerateNodeAnimations(std::vector<aiNodeAnim*>& node_anims,
|
|
|
+ const std::string& fixed_name,
|
|
|
+ const std::vector<const AnimationCurveNode*>& curves,
|
|
|
+ const LayerMap& layer_map,
|
|
|
+ int64_t start, int64_t stop,
|
|
|
+ double& max_time,
|
|
|
+ double& min_time);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ bool IsRedundantAnimationData(const Model& target,
|
|
|
+ TransformationComp comp,
|
|
|
+ const std::vector<const AnimationCurveNode*>& curves);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ aiNodeAnim* GenerateRotationNodeAnim(const std::string& name,
|
|
|
+ const Model& target,
|
|
|
+ const std::vector<const AnimationCurveNode*>& curves,
|
|
|
+ const LayerMap& layer_map,
|
|
|
+ int64_t start, int64_t stop,
|
|
|
+ double& max_time,
|
|
|
+ double& min_time);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ aiNodeAnim* GenerateScalingNodeAnim(const std::string& name,
|
|
|
+ const Model& /*target*/,
|
|
|
+ const std::vector<const AnimationCurveNode*>& curves,
|
|
|
+ const LayerMap& layer_map,
|
|
|
+ int64_t start, int64_t stop,
|
|
|
+ double& max_time,
|
|
|
+ double& min_time);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ aiNodeAnim* GenerateTranslationNodeAnim(const std::string& name,
|
|
|
+ const Model& /*target*/,
|
|
|
+ const std::vector<const AnimationCurveNode*>& curves,
|
|
|
+ const LayerMap& layer_map,
|
|
|
+ int64_t start, int64_t stop,
|
|
|
+ double& max_time,
|
|
|
+ double& min_time,
|
|
|
+ bool inverse = false);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ // generate node anim, extracting only Rotation, Scaling and Translation from the given chain
|
|
|
+ aiNodeAnim* GenerateSimpleNodeAnim(const std::string& name,
|
|
|
+ const Model& target,
|
|
|
+ NodeMap::const_iterator chain[TransformationComp_MAXIMUM],
|
|
|
+ NodeMap::const_iterator iter_end,
|
|
|
+ const LayerMap& layer_map,
|
|
|
+ int64_t start, int64_t stop,
|
|
|
+ double& max_time,
|
|
|
+ double& min_time,
|
|
|
+ bool reverse_order = false);
|
|
|
+
|
|
|
+ // key (time), value, mapto (component index)
|
|
|
+ typedef std::tuple<std::shared_ptr<KeyTimeList>, std::shared_ptr<KeyValueList>, unsigned int > KeyFrameList;
|
|
|
+ typedef std::vector<KeyFrameList> KeyFrameListList;
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ KeyFrameListList GetKeyframeList(const std::vector<const AnimationCurveNode*>& nodes, int64_t start, int64_t stop);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ KeyTimeList GetKeyTimeList(const KeyFrameListList& inputs);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void InterpolateKeys(aiVectorKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
|
|
|
+ const aiVector3D& def_value,
|
|
|
+ double& max_time,
|
|
|
+ double& min_time);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void InterpolateKeys(aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
|
|
|
+ const aiVector3D& def_value,
|
|
|
+ double& maxTime,
|
|
|
+ double& minTime,
|
|
|
+ Model::RotOrder order);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void ConvertTransformOrder_TRStoSRT(aiQuatKey* out_quat, aiVectorKey* out_scale,
|
|
|
+ aiVectorKey* out_translation,
|
|
|
+ const KeyFrameListList& scaling,
|
|
|
+ const KeyFrameListList& translation,
|
|
|
+ const KeyFrameListList& rotation,
|
|
|
+ const KeyTimeList& times,
|
|
|
+ double& maxTime,
|
|
|
+ double& minTime,
|
|
|
+ Model::RotOrder order,
|
|
|
+ const aiVector3D& def_scale,
|
|
|
+ const aiVector3D& def_translate,
|
|
|
+ const aiVector3D& def_rotation);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ // euler xyz -> quat
|
|
|
+ aiQuaternion EulerToQuaternion(const aiVector3D& rot, Model::RotOrder order);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/,
|
|
|
+ int64_t start, int64_t stop,
|
|
|
+ double& maxTime,
|
|
|
+ double& minTime);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
|
|
|
+ const LayerMap& /*layers*/,
|
|
|
+ int64_t start, int64_t stop,
|
|
|
+ double& maxTime,
|
|
|
+ double& minTime);
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
|
|
|
+ const LayerMap& /*layers*/,
|
|
|
+ int64_t start, int64_t stop,
|
|
|
+ double& maxTime,
|
|
|
+ double& minTime,
|
|
|
+ Model::RotOrder order);
|
|
|
+
|
|
|
+ void ConvertGlobalSettings();
|
|
|
+
|
|
|
+ // ------------------------------------------------------------------------------------------------
|
|
|
+ // copy generated meshes, animations, lights, cameras and textures to the output scene
|
|
|
+ void TransferDataToScene();
|
|
|
+
|
|
|
+private:
|
|
|
+
|
|
|
+ // 0: not assigned yet, others: index is value - 1
|
|
|
+ unsigned int defaultMaterialIndex;
|
|
|
+
|
|
|
+ std::vector<aiMesh*> meshes;
|
|
|
+ std::vector<aiMaterial*> materials;
|
|
|
+ std::vector<aiAnimation*> animations;
|
|
|
+ std::vector<aiLight*> lights;
|
|
|
+ std::vector<aiCamera*> cameras;
|
|
|
+ std::vector<aiTexture*> textures;
|
|
|
+
|
|
|
+ typedef std::map<const Material*, unsigned int> MaterialMap;
|
|
|
+ MaterialMap materials_converted;
|
|
|
+
|
|
|
+ typedef std::map<const Video*, unsigned int> VideoMap;
|
|
|
+ VideoMap textures_converted;
|
|
|
+
|
|
|
+ typedef std::map<const Geometry*, std::vector<unsigned int> > MeshMap;
|
|
|
+ MeshMap meshes_converted;
|
|
|
+
|
|
|
+ // fixed node name -> which trafo chain components have animations?
|
|
|
+ typedef std::map<std::string, unsigned int> NodeAnimBitMap;
|
|
|
+ NodeAnimBitMap node_anim_chain_bits;
|
|
|
+
|
|
|
+ // name -> has had its prefix_stripped?
|
|
|
+ typedef std::map<std::string, bool> NodeNameMap;
|
|
|
+ NodeNameMap node_names;
|
|
|
+
|
|
|
+ typedef std::map<std::string, std::string> NameNameMap;
|
|
|
+ NameNameMap renamed_nodes;
|
|
|
+
|
|
|
+ double anim_fps;
|
|
|
+
|
|
|
+ aiScene* const out;
|
|
|
+ const FBX::Document& doc;
|
|
|
+};
|
|
|
+
|
|
|
}
|
|
|
}
|
|
|
|