|
@@ -2,7 +2,7 @@
|
|
Open Asset Import Library (assimp)
|
|
Open Asset Import Library (assimp)
|
|
----------------------------------------------------------------------
|
|
----------------------------------------------------------------------
|
|
|
|
|
|
-Copyright (c) 2006-2021, assimp team
|
|
|
|
|
|
+Copyright (c) 2006-2022, assimp team
|
|
|
|
|
|
All rights reserved.
|
|
All rights reserved.
|
|
|
|
|
|
@@ -79,7 +79,7 @@ using namespace Util;
|
|
|
|
|
|
#define MAGIC_NODE_TAG "_$AssimpFbx$"
|
|
#define MAGIC_NODE_TAG "_$AssimpFbx$"
|
|
|
|
|
|
-#define CONVERT_FBX_TIME(time) (static_cast<double>(time) * 1000.0 / 46186158000LL)
|
|
|
|
|
|
+#define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000LL
|
|
|
|
|
|
FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBones) :
|
|
FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBones) :
|
|
defaultMaterialIndex(),
|
|
defaultMaterialIndex(),
|
|
@@ -653,7 +653,7 @@ bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
|
|
const PropertyTable &props = model.Props();
|
|
const PropertyTable &props = model.Props();
|
|
bool ok;
|
|
bool ok;
|
|
|
|
|
|
- const float zero_epsilon = 1e-6f;
|
|
|
|
|
|
+ const float 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);
|
|
@@ -2070,6 +2070,7 @@ void FBXConverter::SetTextureProperties(aiMaterial *out_mat, const LayeredTextur
|
|
TrySetTextureProperties(out_mat, layeredTextures, "ShininessExponent", aiTextureType_SHININESS, mesh);
|
|
TrySetTextureProperties(out_mat, layeredTextures, "ShininessExponent", aiTextureType_SHININESS, mesh);
|
|
TrySetTextureProperties(out_mat, layeredTextures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh);
|
|
TrySetTextureProperties(out_mat, layeredTextures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh);
|
|
TrySetTextureProperties(out_mat, layeredTextures, "TransparencyFactor", aiTextureType_OPACITY, mesh);
|
|
TrySetTextureProperties(out_mat, layeredTextures, "TransparencyFactor", aiTextureType_OPACITY, mesh);
|
|
|
|
+ TrySetTextureProperties(out_mat, layeredTextures, "ReflectionFactor", aiTextureType_METALNESS, mesh);
|
|
}
|
|
}
|
|
|
|
|
|
aiColor3D FBXConverter::GetColorPropertyFactored(const PropertyTable &props, const std::string &colorName,
|
|
aiColor3D FBXConverter::GetColorPropertyFactored(const PropertyTable &props, const std::string &colorName,
|
|
@@ -2618,7 +2619,7 @@ void FBXConverter::ConvertAnimationStack(const AnimationStack &st) {
|
|
meshMorphAnim->mKeys[j].mNumValuesAndWeights = numValuesAndWeights;
|
|
meshMorphAnim->mKeys[j].mNumValuesAndWeights = numValuesAndWeights;
|
|
meshMorphAnim->mKeys[j].mValues = new unsigned int[numValuesAndWeights];
|
|
meshMorphAnim->mKeys[j].mValues = new unsigned int[numValuesAndWeights];
|
|
meshMorphAnim->mKeys[j].mWeights = new double[numValuesAndWeights];
|
|
meshMorphAnim->mKeys[j].mWeights = new double[numValuesAndWeights];
|
|
- meshMorphAnim->mKeys[j].mTime = CONVERT_FBX_TIME(animIt.first);
|
|
|
|
|
|
+ meshMorphAnim->mKeys[j].mTime = CONVERT_FBX_TIME(animIt.first) * anim_fps;
|
|
for (unsigned int k = 0; k < numValuesAndWeights; k++) {
|
|
for (unsigned int k = 0; k < numValuesAndWeights; k++) {
|
|
meshMorphAnim->mKeys[j].mValues[k] = keyData->values.at(k);
|
|
meshMorphAnim->mKeys[j].mValues[k] = keyData->values.at(k);
|
|
meshMorphAnim->mKeys[j].mWeights[k] = keyData->weights.at(k);
|
|
meshMorphAnim->mKeys[j].mWeights[k] = keyData->weights.at(k);
|
|
@@ -2636,8 +2637,8 @@ void FBXConverter::ConvertAnimationStack(const AnimationStack &st) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- double start_time_fps = has_local_startstop ? CONVERT_FBX_TIME(start_time) : min_time;
|
|
|
|
- double stop_time_fps = has_local_startstop ? CONVERT_FBX_TIME(stop_time) : max_time;
|
|
|
|
|
|
+ double start_time_fps = has_local_startstop ? (CONVERT_FBX_TIME(start_time) * anim_fps) : min_time;
|
|
|
|
+ double stop_time_fps = has_local_startstop ? (CONVERT_FBX_TIME(stop_time) * anim_fps) : max_time;
|
|
|
|
|
|
// adjust relative timing for animation
|
|
// adjust relative timing for animation
|
|
for (unsigned int c = 0; c < anim->mNumChannels; c++) {
|
|
for (unsigned int c = 0; c < anim->mNumChannels; c++) {
|
|
@@ -3127,7 +3128,12 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
|
|
if (chain[i] == iterEnd)
|
|
if (chain[i] == iterEnd)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- keyframeLists[i] = GetKeyframeList((*chain[i]).second, start, stop);
|
|
|
|
|
|
+ if (i == TransformationComp_Rotation || i == TransformationComp_PreRotation
|
|
|
|
+ || i == TransformationComp_PostRotation || i == TransformationComp_GeometricRotation) {
|
|
|
|
+ keyframeLists[i] = GetRotationKeyframeList((*chain[i]).second, start, stop);
|
|
|
|
+ } else {
|
|
|
|
+ keyframeLists[i] = GetKeyframeList((*chain[i]).second, start, stop);
|
|
|
|
+ }
|
|
|
|
|
|
for (KeyFrameListList::const_iterator it = keyframeLists[i].begin(); it != keyframeLists[i].end(); ++it) {
|
|
for (KeyFrameListList::const_iterator it = keyframeLists[i].begin(); it != keyframeLists[i].end(); ++it) {
|
|
const KeyTimeList& times = *std::get<0>(*it);
|
|
const KeyTimeList& times = *std::get<0>(*it);
|
|
@@ -3157,7 +3163,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
|
|
InterpolateKeys(outTranslations, keytimes, keyframeLists[TransformationComp_Translation], defTranslate, maxTime, minTime);
|
|
InterpolateKeys(outTranslations, keytimes, keyframeLists[TransformationComp_Translation], defTranslate, maxTime, minTime);
|
|
} else {
|
|
} else {
|
|
for (size_t i = 0; i < keyCount; ++i) {
|
|
for (size_t i = 0; i < keyCount; ++i) {
|
|
- outTranslations[i].mTime = CONVERT_FBX_TIME(keytimes[i]);
|
|
|
|
|
|
+ outTranslations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps;
|
|
outTranslations[i].mValue = defTranslate;
|
|
outTranslations[i].mValue = defTranslate;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -3166,7 +3172,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
|
|
InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], defRotation, maxTime, minTime, rotOrder);
|
|
InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], defRotation, maxTime, minTime, rotOrder);
|
|
} else {
|
|
} else {
|
|
for (size_t i = 0; i < keyCount; ++i) {
|
|
for (size_t i = 0; i < keyCount; ++i) {
|
|
- outRotations[i].mTime = CONVERT_FBX_TIME(keytimes[i]);
|
|
|
|
|
|
+ outRotations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps;
|
|
outRotations[i].mValue = defQuat;
|
|
outRotations[i].mValue = defQuat;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -3175,13 +3181,14 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
|
|
InterpolateKeys(outScales, keytimes, keyframeLists[TransformationComp_Scaling], defScale, maxTime, minTime);
|
|
InterpolateKeys(outScales, keytimes, keyframeLists[TransformationComp_Scaling], defScale, maxTime, minTime);
|
|
} else {
|
|
} else {
|
|
for (size_t i = 0; i < keyCount; ++i) {
|
|
for (size_t i = 0; i < keyCount; ++i) {
|
|
- outScales[i].mTime = CONVERT_FBX_TIME(keytimes[i]);
|
|
|
|
|
|
+ outScales[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps;
|
|
outScales[i].mValue = defScale;
|
|
outScales[i].mValue = defScale;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool ok = false;
|
|
bool ok = false;
|
|
- const float zero_epsilon = 1e-6f;
|
|
|
|
|
|
+
|
|
|
|
+ const float 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) {
|
|
@@ -3274,6 +3281,79 @@ FBXConverter::KeyFrameListList FBXConverter::GetKeyframeList(const std::vector<c
|
|
return inputs; // pray for NRVO :-)
|
|
return inputs; // pray for NRVO :-)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+FBXConverter::KeyFrameListList FBXConverter::GetRotationKeyframeList(const std::vector<const AnimationCurveNode *> &nodes,
|
|
|
|
+ int64_t start, int64_t stop) {
|
|
|
|
+ KeyFrameListList inputs;
|
|
|
|
+ inputs.reserve(nodes.size() * 3);
|
|
|
|
+
|
|
|
|
+ //give some breathing room for rounding errors
|
|
|
|
+ const int64_t adj_start = start - 10000;
|
|
|
|
+ const int64_t adj_stop = stop + 10000;
|
|
|
|
+
|
|
|
|
+ for (const AnimationCurveNode *node : nodes) {
|
|
|
|
+ ai_assert(node);
|
|
|
|
+
|
|
|
|
+ const AnimationCurveMap &curves = node->Curves();
|
|
|
|
+ for (const AnimationCurveMap::value_type &kv : curves) {
|
|
|
|
+
|
|
|
|
+ unsigned int mapto;
|
|
|
|
+ if (kv.first == "d|X") {
|
|
|
|
+ mapto = 0;
|
|
|
|
+ } else if (kv.first == "d|Y") {
|
|
|
|
+ mapto = 1;
|
|
|
|
+ } else if (kv.first == "d|Z") {
|
|
|
|
+ mapto = 2;
|
|
|
|
+ } else {
|
|
|
|
+ FBXImporter::LogWarn("ignoring scale animation curve, did not recognize target component");
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const AnimationCurve *const curve = kv.second;
|
|
|
|
+ ai_assert(curve->GetKeys().size() == curve->GetValues().size());
|
|
|
|
+ ai_assert(curve->GetKeys().size());
|
|
|
|
+
|
|
|
|
+ //get values within the start/stop time window
|
|
|
|
+ std::shared_ptr<KeyTimeList> Keys(new KeyTimeList());
|
|
|
|
+ std::shared_ptr<KeyValueList> Values(new KeyValueList());
|
|
|
|
+ const size_t count = curve->GetKeys().size();
|
|
|
|
+
|
|
|
|
+ int64_t tp = curve->GetKeys().at(0);
|
|
|
|
+ float vp = curve->GetValues().at(0);
|
|
|
|
+ Keys->push_back(tp);
|
|
|
|
+ Values->push_back(vp);
|
|
|
|
+ if (count > 1) {
|
|
|
|
+ int64_t tc = curve->GetKeys().at(1);
|
|
|
|
+ float vc = curve->GetValues().at(1);
|
|
|
|
+ for (size_t n = 1; n < count; n++) {
|
|
|
|
+ while (std::abs(vc - vp) >= 180.0f) {
|
|
|
|
+ float step = std::floor(float(tc - tp) / (vc - vp) * 179.0f);
|
|
|
|
+ int64_t tnew = tp + int64_t(step);
|
|
|
|
+ float vnew = vp + (vc - vp) * step / float(tc - tp);
|
|
|
|
+ if (tnew >= adj_start && tnew <= adj_stop) {
|
|
|
|
+ Keys->push_back(tnew);
|
|
|
|
+ Values->push_back(vnew);
|
|
|
|
+ }
|
|
|
|
+ tp = tnew;
|
|
|
|
+ vp = vnew;
|
|
|
|
+ }
|
|
|
|
+ if (tc >= adj_start && tc <= adj_stop) {
|
|
|
|
+ Keys->push_back(tc);
|
|
|
|
+ Values->push_back(vc);
|
|
|
|
+ }
|
|
|
|
+ if (n + 1 < count) {
|
|
|
|
+ tp = tc;
|
|
|
|
+ vp = vc;
|
|
|
|
+ tc = curve->GetKeys().at(n + 1);
|
|
|
|
+ vc = curve->GetValues().at(n + 1);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ inputs.push_back(std::make_tuple(Keys, Values, mapto));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return inputs;
|
|
|
|
+}
|
|
|
|
+
|
|
KeyTimeList FBXConverter::GetKeyTimeList(const KeyFrameListList &inputs) {
|
|
KeyTimeList FBXConverter::GetKeyTimeList(const KeyFrameListList &inputs) {
|
|
ai_assert(!inputs.empty());
|
|
ai_assert(!inputs.empty());
|
|
|
|
|
|
@@ -3364,7 +3444,7 @@ void FBXConverter::InterpolateKeys(aiVectorKey *valOut, const KeyTimeList &keys,
|
|
}
|
|
}
|
|
|
|
|
|
// magic value to convert fbx times to seconds
|
|
// magic value to convert fbx times to seconds
|
|
- valOut->mTime = CONVERT_FBX_TIME(time);
|
|
|
|
|
|
+ valOut->mTime = CONVERT_FBX_TIME(time) * anim_fps;
|
|
|
|
|
|
min_time = std::min(min_time, valOut->mTime);
|
|
min_time = std::min(min_time, valOut->mTime);
|
|
max_time = std::max(max_time, valOut->mTime);
|
|
max_time = std::max(max_time, valOut->mTime);
|
|
@@ -3464,7 +3544,7 @@ void FBXConverter::ConvertRotationKeys(aiNodeAnim *na, const std::vector<const A
|
|
ai_assert(nodes.size());
|
|
ai_assert(nodes.size());
|
|
|
|
|
|
// XXX see notes in ConvertScaleKeys()
|
|
// XXX see notes in ConvertScaleKeys()
|
|
- const std::vector<KeyFrameList> &inputs = GetKeyframeList(nodes, start, stop);
|
|
|
|
|
|
+ const std::vector<KeyFrameList> &inputs = GetRotationKeyframeList(nodes, start, stop);
|
|
const KeyTimeList &keys = GetKeyTimeList(inputs);
|
|
const KeyTimeList &keys = GetKeyTimeList(inputs);
|
|
|
|
|
|
na->mNumRotationKeys = static_cast<unsigned int>(keys.size());
|
|
na->mNumRotationKeys = static_cast<unsigned int>(keys.size());
|