FBX: store UnitScaleFactor for fbx-files.

This commit is contained in:
kim kulling
2018-01-23 15:13:23 +01:00
parent 8ac1de3287
commit 88a0bb1b6d
9 changed files with 479 additions and 446 deletions

View File

@@ -66,7 +66,6 @@ namespace FBX {
using namespace Util;
#define MAGIC_NODE_TAG "_$AssimpFbx$"
#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L
@@ -74,373 +73,6 @@ using namespace Util;
// XXX vc9's debugger won't step into anonymous namespaces
//namespace {
/** 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 );
// ------------------------------------------------------------------------------------------------
// 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;
};
Converter::Converter( aiScene* out, const Document& doc )
: defaultMaterialIndex()
@@ -472,6 +104,7 @@ Converter::Converter( aiScene* out, const Document& doc )
}
}
ConvertGlobalSettings();
TransferDataToScene();
// if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE
@@ -3341,8 +2974,20 @@ void Converter::ConvertRotationKeys( aiNodeAnim* na, const std::vector<const Ani
na->mNumRotationKeys = static_cast<unsigned int>( keys.size() );
na->mRotationKeys = new aiQuatKey[ keys.size() ];
if ( keys.size() > 0 )
InterpolateKeys( na->mRotationKeys, keys, inputs, aiVector3D( 0.0f, 0.0f, 0.0f ), maxTime, minTime, order );
if (!keys.empty()) {
InterpolateKeys(na->mRotationKeys, keys, inputs, aiVector3D(0.0f, 0.0f, 0.0f), maxTime, minTime, order);
}
}
void Converter::ConvertGlobalSettings() {
if (nullptr == out) {
return;
}
out->mMetaData = aiMetadata::Alloc(1);
unsigned int index(0);
const double unitScalFactor(doc.GlobalSettings().UnitScaleFactor());
out->mMetaData->Set(index, "UnitScaleFactor", unitScalFactor);
}
void Converter::TransferDataToScene()