diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 61e804b2e..15f7643ce 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -7,8 +7,7 @@ on: branches: [ master ] jobs: - build-ubuntu: - + linux: runs-on: ubuntu-latest steps: @@ -19,4 +18,29 @@ jobs: run: cmake --build . - name: test run: cd bin && ./unit - + + mac: + runs-on: macos-latest + + steps: + - uses: actions/checkout@v1 + - name: configure + run: cmake CMakeLists.txt + - name: build + run: cmake --build . + - name: test + run: cd bin && ./unit + + windows: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v1 + - name: configure + run: cmake CMakeLists.txt + - name: build + run: cmake --build . --config Release + - name: test + run: | + cd bin\Release + .\unit diff --git a/code/Common/Assimp.cpp b/code/Common/Assimp.cpp index 66588f0bc..7dae2633c 100644 --- a/code/Common/Assimp.cpp +++ b/code/Common/Assimp.cpp @@ -693,3 +693,598 @@ ASSIMP_API C_STRUCT const aiImporterDesc* aiGetImporterDesc( const char *extensi } // ------------------------------------------------------------------------------------------------ +ASSIMP_API int aiVector2AreEqual( + const C_STRUCT aiVector2D* a, + const C_STRUCT aiVector2D* b) { + ai_assert(NULL != a); + ai_assert(NULL != b); + return *a == *b; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API int aiVector2AreEqualEpsilon( + const C_STRUCT aiVector2D* a, + const C_STRUCT aiVector2D* b, + const float epsilon) { + ai_assert(NULL != a); + ai_assert(NULL != b); + return a->Equal(*b, epsilon); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector2Add( + C_STRUCT aiVector2D* dst, + const C_STRUCT aiVector2D* src) { + ai_assert(NULL != dst); + ai_assert(NULL != src); + *dst = *dst + *src; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector2Subtract( + C_STRUCT aiVector2D* dst, + const C_STRUCT aiVector2D* src) { + ai_assert(NULL != dst); + ai_assert(NULL != src); + *dst = *dst - *src; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector2Scale( + C_STRUCT aiVector2D* dst, + const float s) { + ai_assert(NULL != dst); + *dst *= s; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector2SymMul( + C_STRUCT aiVector2D* dst, + const C_STRUCT aiVector2D* other) { + ai_assert(NULL != dst); + ai_assert(NULL != other); + *dst = dst->SymMul(*other); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector2DivideByScalar( + C_STRUCT aiVector2D* dst, + const float s) { + ai_assert(NULL != dst); + *dst /= s; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector2DivideByVector( + C_STRUCT aiVector2D* dst, + C_STRUCT aiVector2D* v) { + ai_assert(NULL != dst); + ai_assert(NULL != v); + *dst = *dst / *v; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API float aiVector2Length( + const C_STRUCT aiVector2D* v) { + ai_assert(NULL != v); + return v->Length(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API float aiVector2SquareLength( + const C_STRUCT aiVector2D* v) { + ai_assert(NULL != v); + return v->SquareLength(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector2Negate( + C_STRUCT aiVector2D* dst) { + ai_assert(NULL != dst); + *dst = -(*dst); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API float aiVector2DotProduct( + const C_STRUCT aiVector2D* a, + const C_STRUCT aiVector2D* b) { + ai_assert(NULL != a); + ai_assert(NULL != b); + return (*a) * (*b); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector2Normalize( + C_STRUCT aiVector2D* v) { + ai_assert(NULL != v); + v->Normalize(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API int aiVector3AreEqual( + const C_STRUCT aiVector3D* a, + const C_STRUCT aiVector3D* b) { + ai_assert(NULL != a); + ai_assert(NULL != b); + return *a == *b; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API int aiVector3AreEqualEpsilon( + const C_STRUCT aiVector3D* a, + const C_STRUCT aiVector3D* b, + const float epsilon) { + ai_assert(NULL != a); + ai_assert(NULL != b); + return a->Equal(*b, epsilon); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API int aiVector3LessThan( + const C_STRUCT aiVector3D* a, + const C_STRUCT aiVector3D* b) { + ai_assert(NULL != a); + ai_assert(NULL != b); + return *a < *b; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector3Add( + C_STRUCT aiVector3D* dst, + const C_STRUCT aiVector3D* src) { + ai_assert(NULL != dst); + ai_assert(NULL != src); + *dst = *dst + *src; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector3Subtract( + C_STRUCT aiVector3D* dst, + const C_STRUCT aiVector3D* src) { + ai_assert(NULL != dst); + ai_assert(NULL != src); + *dst = *dst - *src; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector3Scale( + C_STRUCT aiVector3D* dst, + const float s) { + ai_assert(NULL != dst); + *dst *= s; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector3SymMul( + C_STRUCT aiVector3D* dst, + const C_STRUCT aiVector3D* other) { + ai_assert(NULL != dst); + ai_assert(NULL != other); + *dst = dst->SymMul(*other); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector3DivideByScalar( + C_STRUCT aiVector3D* dst, const float s) { + ai_assert(NULL != dst); + *dst /= s; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector3DivideByVector( + C_STRUCT aiVector3D* dst, + C_STRUCT aiVector3D* v) { + ai_assert(NULL != dst); + ai_assert(NULL != v); + *dst = *dst / *v; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API float aiVector3Length( + const C_STRUCT aiVector3D* v) { + ai_assert(NULL != v); + return v->Length(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API float aiVector3SquareLength( + const C_STRUCT aiVector3D* v) { + ai_assert(NULL != v); + return v->SquareLength(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector3Negate( + C_STRUCT aiVector3D* dst) { + ai_assert(NULL != dst); + *dst = -(*dst); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API float aiVector3DotProduct( + const C_STRUCT aiVector3D* a, + const C_STRUCT aiVector3D* b) { + ai_assert(NULL != a); + ai_assert(NULL != b); + return (*a) * (*b); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector3CrossProduct( + C_STRUCT aiVector3D* dst, + const C_STRUCT aiVector3D* a, + const C_STRUCT aiVector3D* b) { + ai_assert(NULL != dst); + ai_assert(NULL != a); + ai_assert(NULL != b); + *dst = *a ^ *b; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector3Normalize( + C_STRUCT aiVector3D* v) { + ai_assert(NULL != v); + v->Normalize(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector3NormalizeSafe( + C_STRUCT aiVector3D* v) { + ai_assert(NULL != v); + v->NormalizeSafe(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiVector3RotateByQuaternion( + C_STRUCT aiVector3D* v, + const C_STRUCT aiQuaternion* q) { + ai_assert(NULL != v); + ai_assert(NULL != q); + *v = q->Rotate(*v); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix3FromMatrix4( + C_STRUCT aiMatrix3x3* dst, + const C_STRUCT aiMatrix4x4* mat) { + ai_assert(NULL != dst); + ai_assert(NULL != mat); + *dst = aiMatrix3x3(*mat); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix3FromQuaternion( + C_STRUCT aiMatrix3x3* mat, + const C_STRUCT aiQuaternion* q) { + ai_assert(NULL != mat); + ai_assert(NULL != q); + *mat = q->GetMatrix(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API int aiMatrix3AreEqual( + const C_STRUCT aiMatrix3x3* a, + const C_STRUCT aiMatrix3x3* b) { + ai_assert(NULL != a); + ai_assert(NULL != b); + return *a == *b; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API int aiMatrix3AreEqualEpsilon( + const C_STRUCT aiMatrix3x3* a, + const C_STRUCT aiMatrix3x3* b, + const float epsilon) { + ai_assert(NULL != a); + ai_assert(NULL != b); + return a->Equal(*b, epsilon); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix3Inverse(C_STRUCT aiMatrix3x3* mat) { + ai_assert(NULL != mat); + mat->Inverse(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API float aiMatrix3Determinant(const C_STRUCT aiMatrix3x3* mat) { + ai_assert(NULL != mat); + return mat->Determinant(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix3RotationZ( + C_STRUCT aiMatrix3x3* mat, + const float angle) { + ai_assert(NULL != mat); + aiMatrix3x3::RotationZ(angle, *mat); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix3FromRotationAroundAxis( + C_STRUCT aiMatrix3x3* mat, + const C_STRUCT aiVector3D* axis, + const float angle) { + ai_assert(NULL != mat); + ai_assert(NULL != axis); + aiMatrix3x3::Rotation(angle, *axis, *mat); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix3Translation( + C_STRUCT aiMatrix3x3* mat, + const C_STRUCT aiVector2D* translation) { + ai_assert(NULL != mat); + ai_assert(NULL != translation); + aiMatrix3x3::Translation(*translation, *mat); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix3FromTo( + C_STRUCT aiMatrix3x3* mat, + const C_STRUCT aiVector3D* from, + const C_STRUCT aiVector3D* to) { + ai_assert(NULL != mat); + ai_assert(NULL != from); + ai_assert(NULL != to); + aiMatrix3x3::FromToMatrix(*from, *to, *mat); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix4FromMatrix3( + C_STRUCT aiMatrix4x4* dst, + const C_STRUCT aiMatrix3x3* mat) { + ai_assert(NULL != dst); + ai_assert(NULL != mat); + *dst = aiMatrix4x4(*mat); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix4FromScalingQuaternionPosition( + C_STRUCT aiMatrix4x4* mat, + const C_STRUCT aiVector3D* scaling, + const C_STRUCT aiQuaternion* rotation, + const C_STRUCT aiVector3D* position) { + ai_assert(NULL != mat); + ai_assert(NULL != scaling); + ai_assert(NULL != rotation); + ai_assert(NULL != position); + *mat = aiMatrix4x4(*scaling, *rotation, *position); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix4Add( + C_STRUCT aiMatrix4x4* dst, + const C_STRUCT aiMatrix4x4* src) { + ai_assert(NULL != dst); + ai_assert(NULL != src); + *dst = *dst + *src; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API int aiMatrix4AreEqual( + const C_STRUCT aiMatrix4x4* a, + const C_STRUCT aiMatrix4x4* b) { + ai_assert(NULL != a); + ai_assert(NULL != b); + return *a == *b; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API int aiMatrix4AreEqualEpsilon( + const C_STRUCT aiMatrix4x4* a, + const C_STRUCT aiMatrix4x4* b, + const float epsilon) { + ai_assert(NULL != a); + ai_assert(NULL != b); + return a->Equal(*b, epsilon); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix4Inverse(C_STRUCT aiMatrix4x4* mat) { + ai_assert(NULL != mat); + mat->Inverse(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API float aiMatrix4Determinant(const C_STRUCT aiMatrix4x4* mat) { + ai_assert(NULL != mat); + return mat->Determinant(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API int aiMatrix4IsIdentity(const C_STRUCT aiMatrix4x4* mat) { + ai_assert(NULL != mat); + return mat->IsIdentity(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix4DecomposeIntoScalingEulerAnglesPosition( + const C_STRUCT aiMatrix4x4* mat, + C_STRUCT aiVector3D* scaling, + C_STRUCT aiVector3D* rotation, + C_STRUCT aiVector3D* position) { + ai_assert(NULL != mat); + ai_assert(NULL != scaling); + ai_assert(NULL != rotation); + ai_assert(NULL != position); + mat->Decompose(*scaling, *rotation, *position); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix4DecomposeIntoScalingAxisAnglePosition( + const C_STRUCT aiMatrix4x4* mat, + C_STRUCT aiVector3D* scaling, + C_STRUCT aiVector3D* axis, + float* angle, + C_STRUCT aiVector3D* position) { + ai_assert(NULL != mat); + ai_assert(NULL != scaling); + ai_assert(NULL != axis); + ai_assert(NULL != angle); + ai_assert(NULL != position); + mat->Decompose(*scaling, *axis, *angle, *position); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix4DecomposeNoScaling( + const C_STRUCT aiMatrix4x4* mat, + C_STRUCT aiQuaternion* rotation, + C_STRUCT aiVector3D* position) { + ai_assert(NULL != mat); + ai_assert(NULL != rotation); + ai_assert(NULL != position); + mat->DecomposeNoScaling(*rotation, *position); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix4FromEulerAngles( + C_STRUCT aiMatrix4x4* mat, + float x, float y, float z) { + ai_assert(NULL != mat); + mat->FromEulerAnglesXYZ(x, y, z); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix4RotationX( + C_STRUCT aiMatrix4x4* mat, + const float angle) { + ai_assert(NULL != mat); + aiMatrix4x4::RotationX(angle, *mat); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix4RotationY( + C_STRUCT aiMatrix4x4* mat, + const float angle) { + ai_assert(NULL != mat); + aiMatrix4x4::RotationY(angle, *mat); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix4RotationZ( + C_STRUCT aiMatrix4x4* mat, + const float angle) { + ai_assert(NULL != mat); + aiMatrix4x4::RotationZ(angle, *mat); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix4FromRotationAroundAxis( + C_STRUCT aiMatrix4x4* mat, + const C_STRUCT aiVector3D* axis, + const float angle) { + ai_assert(NULL != mat); + ai_assert(NULL != axis); + aiMatrix4x4::Rotation(angle, *axis, *mat); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix4Translation( + C_STRUCT aiMatrix4x4* mat, + const C_STRUCT aiVector3D* translation) { + ai_assert(NULL != mat); + ai_assert(NULL != translation); + aiMatrix4x4::Translation(*translation, *mat); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix4Scaling( + C_STRUCT aiMatrix4x4* mat, + const C_STRUCT aiVector3D* scaling) { + ai_assert(NULL != mat); + ai_assert(NULL != scaling); + aiMatrix4x4::Scaling(*scaling, *mat); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiMatrix4FromTo( + C_STRUCT aiMatrix4x4* mat, + const C_STRUCT aiVector3D* from, + const C_STRUCT aiVector3D* to) { + ai_assert(NULL != mat); + ai_assert(NULL != from); + ai_assert(NULL != to); + aiMatrix4x4::FromToMatrix(*from, *to, *mat); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiQuaternionFromEulerAngles( + C_STRUCT aiQuaternion* q, + float x, float y, float z) { + ai_assert(NULL != q); + *q = aiQuaternion(x, y, z); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiQuaternionFromAxisAngle( + C_STRUCT aiQuaternion* q, + const C_STRUCT aiVector3D* axis, + const float angle) { + ai_assert(NULL != q); + ai_assert(NULL != axis); + *q = aiQuaternion(*axis, angle); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiQuaternionFromNormalizedQuaternion( + C_STRUCT aiQuaternion* q, + const C_STRUCT aiVector3D* normalized) { + ai_assert(NULL != q); + ai_assert(NULL != normalized); + *q = aiQuaternion(*normalized); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API int aiQuaternionAreEqual( + const C_STRUCT aiQuaternion* a, + const C_STRUCT aiQuaternion* b) { + ai_assert(NULL != a); + ai_assert(NULL != b); + return *a == *b; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API int aiQuaternionAreEqualEpsilon( + const C_STRUCT aiQuaternion* a, + const C_STRUCT aiQuaternion* b, + const float epsilon) { + ai_assert(NULL != a); + ai_assert(NULL != b); + return a->Equal(*b, epsilon); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiQuaternionNormalize( + C_STRUCT aiQuaternion* q) { + ai_assert(NULL != q); + q->Normalize(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiQuaternionConjugate( + C_STRUCT aiQuaternion* q) { + ai_assert(NULL != q); + q->Conjugate(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiQuaternionMultiply( + C_STRUCT aiQuaternion* dst, + const C_STRUCT aiQuaternion* q) { + ai_assert(NULL != dst); + ai_assert(NULL != q); + *dst = (*dst) * (*q); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiQuaternionInterpolate( + C_STRUCT aiQuaternion* dst, + const C_STRUCT aiQuaternion* start, + const C_STRUCT aiQuaternion* end, + const float factor) { + ai_assert(NULL != dst); + ai_assert(NULL != start); + ai_assert(NULL != end); + aiQuaternion::Interpolate(*dst, *start, *end, factor); +} diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index e7ef8fa61..880b5de76 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -655,7 +655,8 @@ bool FBXConverter::NeedsComplexTransformationChain(const Model &model) { for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) { const TransformationComp comp = static_cast(i); - if (comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation) { + if (comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation || + comp == TransformationComp_PreRotation || comp == TransformationComp_PostRotation) { continue; } @@ -2739,15 +2740,12 @@ void FBXConverter::GenerateNodeAnimations(std::vector &node_anims, // be invoked _later_ (animations come first). If this node has only rotation, // scaling and translation _and_ there are no animated other components either, // we can use a single node and also a single node animation channel. - if (!has_complex && !NeedsComplexTransformationChain(target)) { - - aiNodeAnim *const nd = GenerateSimpleNodeAnim(fixed_name, target, chain, + if( !has_complex && !NeedsComplexTransformationChain(target)) { + aiNodeAnim* const nd = GenerateSimpleNodeAnim(fixed_name, target, chain, node_property_map.end(), - layer_map, start, stop, max_time, - min_time, - true // input is TRS order, assimp is SRT + min_time ); ai_assert(nd); @@ -3021,133 +3019,121 @@ aiNodeAnim *FBXConverter::GenerateTranslationNodeAnim(const std::string &name, return na.release(); } -aiNodeAnim *FBXConverter::GenerateSimpleNodeAnim(const std::string &name, - const Model &target, +aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name, + const Model& target, NodeMap::const_iterator chain[TransformationComp_MAXIMUM], - NodeMap::const_iterator iter_end, - const LayerMap &layer_map, + NodeMap::const_iterator iterEnd, int64_t start, int64_t stop, - double &max_time, - double &min_time, - bool reverse_order) - + double& maxTime, + double& minTime) { std::unique_ptr na(new aiNodeAnim()); na->mNodeName.Set(name); const PropertyTable &props = target.Props(); - // need to convert from TRS order to SRT? - if (reverse_order) { + // collect unique times and keyframe lists + KeyFrameListList keyframeLists[TransformationComp_MAXIMUM]; + KeyTimeList keytimes; - aiVector3D def_scale = PropertyGet(props, "Lcl Scaling", aiVector3D(1.f, 1.f, 1.f)); - aiVector3D def_translate = PropertyGet(props, "Lcl Translation", aiVector3D(0.f, 0.f, 0.f)); - aiVector3D def_rot = PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f)); + for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) { + if (chain[i] == iterEnd) + continue; - KeyFrameListList scaling; - KeyFrameListList translation; - KeyFrameListList rotation; + keyframeLists[i] = GetKeyframeList((*chain[i]).second, start, stop); - if (chain[TransformationComp_Scaling] != iter_end) { - scaling = GetKeyframeList((*chain[TransformationComp_Scaling]).second, start, stop); + for (KeyFrameListList::const_iterator it = keyframeLists[i].begin(); it != keyframeLists[i].end(); ++it) { + const KeyTimeList& times = *std::get<0>(*it); + keytimes.insert(keytimes.end(), times.begin(), times.end()); } - if (chain[TransformationComp_Translation] != iter_end) { - translation = GetKeyframeList((*chain[TransformationComp_Translation]).second, start, stop); - } + // remove duplicates + std::sort(keytimes.begin(), keytimes.end()); - if (chain[TransformationComp_Rotation] != iter_end) { - rotation = GetKeyframeList((*chain[TransformationComp_Rotation]).second, start, stop); - } + auto last = std::unique(keytimes.begin(), keytimes.end()); + keytimes.erase(last, keytimes.end()); + } - KeyFrameListList joined; - joined.insert(joined.end(), scaling.begin(), scaling.end()); - joined.insert(joined.end(), translation.begin(), translation.end()); - joined.insert(joined.end(), rotation.begin(), rotation.end()); + const Model::RotOrder rotOrder = target.RotationOrder(); + const size_t keyCount = keytimes.size(); - const KeyTimeList × = GetKeyTimeList(joined); + aiVector3D defTranslate = PropertyGet(props, "Lcl Translation", aiVector3D(0.f, 0.f, 0.f)); + aiVector3D defRotation = PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f)); + aiVector3D defScale = PropertyGet(props, "Lcl Scaling", aiVector3D(1.f, 1.f, 1.f)); + aiQuaternion defQuat = EulerToQuaternion(defRotation, rotOrder); - aiQuatKey *out_quat = new aiQuatKey[times.size()]; - aiVectorKey *out_scale = new aiVectorKey[times.size()]; - aiVectorKey *out_translation = new aiVectorKey[times.size()]; + aiVectorKey* outTranslations = new aiVectorKey[keyCount]; + aiQuatKey* outRotations = new aiQuatKey[keyCount]; + aiVectorKey* outScales = new aiVectorKey[keyCount]; - if (times.size()) { - ConvertTransformOrder_TRStoSRT(out_quat, out_scale, out_translation, - scaling, - translation, - rotation, - times, - max_time, - min_time, - target.RotationOrder(), - def_scale, - def_translate, - def_rot); - } - - // XXX remove duplicates / redundant keys which this operation did - // likely produce if not all three channels were equally dense. - - na->mNumScalingKeys = static_cast(times.size()); - na->mNumRotationKeys = na->mNumScalingKeys; - na->mNumPositionKeys = na->mNumScalingKeys; - - na->mScalingKeys = out_scale; - na->mRotationKeys = out_quat; - na->mPositionKeys = out_translation; + if (keyframeLists[TransformationComp_Translation].size() > 0) { + InterpolateKeys(outTranslations, keytimes, keyframeLists[TransformationComp_Translation], defTranslate, maxTime, minTime); } else { - - // if a particular transformation is not given, grab it from - // the corresponding node to meet the semantics of aiNodeAnim, - // which requires all of rotation, scaling and translation - // to be set. - if (chain[TransformationComp_Scaling] != iter_end) { - ConvertScaleKeys(na.get(), (*chain[TransformationComp_Scaling]).second, - layer_map, - start, stop, - max_time, - min_time); - } else { - na->mScalingKeys = new aiVectorKey[1]; - na->mNumScalingKeys = 1; - - na->mScalingKeys[0].mTime = 0.; - na->mScalingKeys[0].mValue = PropertyGet(props, "Lcl Scaling", - aiVector3D(1.f, 1.f, 1.f)); - } - - if (chain[TransformationComp_Rotation] != iter_end) { - ConvertRotationKeys(na.get(), (*chain[TransformationComp_Rotation]).second, - layer_map, - start, stop, - max_time, - min_time, - target.RotationOrder()); - } else { - na->mRotationKeys = new aiQuatKey[1]; - na->mNumRotationKeys = 1; - - na->mRotationKeys[0].mTime = 0.; - na->mRotationKeys[0].mValue = EulerToQuaternion( - PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f)), - target.RotationOrder()); - } - - if (chain[TransformationComp_Translation] != iter_end) { - ConvertTranslationKeys(na.get(), (*chain[TransformationComp_Translation]).second, - layer_map, - start, stop, - max_time, - min_time); - } else { - na->mPositionKeys = new aiVectorKey[1]; - na->mNumPositionKeys = 1; - - na->mPositionKeys[0].mTime = 0.; - na->mPositionKeys[0].mValue = PropertyGet(props, "Lcl Translation", - aiVector3D(0.f, 0.f, 0.f)); + for (size_t i = 0; i < keyCount; ++i) { + outTranslations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps; + outTranslations[i].mValue = defTranslate; } } + + if (keyframeLists[TransformationComp_Rotation].size() > 0) { + InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], defRotation, maxTime, minTime, rotOrder); + } else { + for (size_t i = 0; i < keyCount; ++i) { + outRotations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps; + outRotations[i].mValue = defQuat; + } + } + + if (keyframeLists[TransformationComp_Scaling].size() > 0) { + InterpolateKeys(outScales, keytimes, keyframeLists[TransformationComp_Scaling], defScale, maxTime, minTime); + } else { + for (size_t i = 0; i < keyCount; ++i) { + outScales[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps; + outScales[i].mValue = defScale; + } + } + + bool ok = false; + const float zero_epsilon = 1e-6f; + + const aiVector3D& preRotation = PropertyGet(props, "PreRotation", ok); + if (ok && preRotation.SquareLength() > zero_epsilon) { + const aiQuaternion preQuat = EulerToQuaternion(preRotation, Model::RotOrder_EulerXYZ); + for (size_t i = 0; i < keyCount; ++i) { + outRotations[i].mValue = preQuat * outRotations[i].mValue; + } + } + + const aiVector3D& postRotation = PropertyGet(props, "PostRotation", ok); + if (ok && postRotation.SquareLength() > zero_epsilon) { + const aiQuaternion postQuat = EulerToQuaternion(postRotation, Model::RotOrder_EulerXYZ); + for (size_t i = 0; i < keyCount; ++i) { + outRotations[i].mValue = outRotations[i].mValue * postQuat; + } + } + + // convert TRS to SRT + for (size_t i = 0; i < keyCount; ++i) { + aiQuaternion& r = outRotations[i].mValue; + aiVector3D& s = outScales[i].mValue; + aiVector3D& t = outTranslations[i].mValue; + + aiMatrix4x4 mat, temp; + aiMatrix4x4::Translation(t, mat); + mat *= aiMatrix4x4(r.GetMatrix()); + mat *= aiMatrix4x4::Scaling(s, temp); + + mat.Decompose(s, r, t); + } + + na->mNumScalingKeys = static_cast(keyCount); + na->mNumRotationKeys = na->mNumScalingKeys; + na->mNumPositionKeys = na->mNumScalingKeys; + + na->mScalingKeys = outScales; + na->mRotationKeys = outRotations; + na->mPositionKeys = outTranslations; + return na.release(); } @@ -3328,10 +3314,7 @@ void FBXConverter::InterpolateKeys(aiQuatKey *valOut, const KeyTimeList &keys, c // take shortest path by checking the inner product // http://www.3dkingdoms.com/weekly/weekly.php?a=36 if (quat.x * lastq.x + quat.y * lastq.y + quat.z * lastq.z + quat.w * lastq.w < 0) { - quat.x = -quat.x; - quat.y = -quat.y; - quat.z = -quat.z; - quat.w = -quat.w; + quat.Conjugate(); } lastq = quat; @@ -3339,60 +3322,6 @@ void FBXConverter::InterpolateKeys(aiQuatKey *valOut, const KeyTimeList &keys, c } } -void FBXConverter::ConvertTransformOrder_TRStoSRT(aiQuatKey *out_quat, aiVectorKey *out_scale, - aiVectorKey *out_translation, - const KeyFrameListList &scaling, - const KeyFrameListList &translation, - const KeyFrameListList &rotation, - const KeyTimeList ×, - double &maxTime, - double &minTime, - Model::RotOrder order, - const aiVector3D &def_scale, - const aiVector3D &def_translate, - const aiVector3D &def_rotation) { - if (rotation.size()) { - InterpolateKeys(out_quat, times, rotation, def_rotation, maxTime, minTime, order); - } else { - for (size_t i = 0; i < times.size(); ++i) { - out_quat[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps; - out_quat[i].mValue = EulerToQuaternion(def_rotation, order); - } - } - - if (scaling.size()) { - InterpolateKeys(out_scale, times, scaling, def_scale, maxTime, minTime); - } else { - for (size_t i = 0; i < times.size(); ++i) { - out_scale[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps; - out_scale[i].mValue = def_scale; - } - } - - if (translation.size()) { - InterpolateKeys(out_translation, times, translation, def_translate, maxTime, minTime); - } else { - for (size_t i = 0; i < times.size(); ++i) { - out_translation[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps; - out_translation[i].mValue = def_translate; - } - } - - const size_t count = times.size(); - for (size_t i = 0; i < count; ++i) { - aiQuaternion &r = out_quat[i].mValue; - aiVector3D &s = out_scale[i].mValue; - aiVector3D &t = out_translation[i].mValue; - - aiMatrix4x4 mat, temp; - aiMatrix4x4::Translation(t, mat); - mat *= aiMatrix4x4(r.GetMatrix()); - mat *= aiMatrix4x4::Scaling(s, temp); - - mat.Decompose(s, r, t); - } -} - aiQuaternion FBXConverter::EulerToQuaternion(const aiVector3D &rot, Model::RotOrder order) { aiMatrix4x4 m; GetRotationMatrix(order, rot, m); diff --git a/code/FBX/FBXConverter.h b/code/FBX/FBXConverter.h index c3830b894..d4f75820f 100644 --- a/code/FBX/FBXConverter.h +++ b/code/FBX/FBXConverter.h @@ -349,12 +349,10 @@ private: aiNodeAnim* GenerateSimpleNodeAnim(const std::string& name, const Model& target, NodeMap::const_iterator chain[TransformationComp_MAXIMUM], - NodeMap::const_iterator iter_end, - const LayerMap& layer_map, + NodeMap::const_iterator iterEnd, int64_t start, int64_t stop, - double& max_time, - double& min_time, - bool reverse_order = false); + double& maxTime, + double& minTime); // key (time), value, mapto (component index) typedef std::tuple, std::shared_ptr, unsigned int > KeyFrameList; @@ -379,20 +377,6 @@ private: 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); diff --git a/include/assimp/cimport.h b/include/assimp/cimport.h index dab60584b..a6ab93051 100644 --- a/include/assimp/cimport.h +++ b/include/assimp/cimport.h @@ -562,6 +562,675 @@ ASSIMP_API size_t aiGetImportFormatCount(void); * @return A description of that specific import format. NULL if pIndex is out of range. */ ASSIMP_API const C_STRUCT aiImporterDesc* aiGetImportFormatDescription( size_t pIndex); + +// -------------------------------------------------------------------------------- +/** Check if 2D vectors are equal. + * @param a First vector to compare + * @param b Second vector to compare + * @return 1 if the vectors are equal + * @return 0 if the vectors are not equal + */ +ASSIMP_API int aiVector2AreEqual( + const C_STRUCT aiVector2D* a, + const C_STRUCT aiVector2D* b); + +// -------------------------------------------------------------------------------- +/** Check if 2D vectors are equal using epsilon. + * @param a First vector to compare + * @param b Second vector to compare + * @param epsilon Epsilon + * @return 1 if the vectors are equal + * @return 0 if the vectors are not equal + */ +ASSIMP_API int aiVector2AreEqualEpsilon( + const C_STRUCT aiVector2D* a, + const C_STRUCT aiVector2D* b, + const float epsilon); + +// -------------------------------------------------------------------------------- +/** Add 2D vectors. + * @param dst First addend, receives result. + * @param src Vector to be added to 'dst'. + */ +ASSIMP_API void aiVector2Add( + C_STRUCT aiVector2D* dst, + const C_STRUCT aiVector2D* src); + +// -------------------------------------------------------------------------------- +/** Subtract 2D vectors. + * @param dst Minuend, receives result. + * @param src Vector to be subtracted from 'dst'. + */ +ASSIMP_API void aiVector2Subtract( + C_STRUCT aiVector2D* dst, + const C_STRUCT aiVector2D* src); + +// -------------------------------------------------------------------------------- +/** Multiply a 2D vector by a scalar. + * @param dst Vector to be scaled by \p s + * @param s Scale factor + */ +ASSIMP_API void aiVector2Scale( + C_STRUCT aiVector2D* dst, + const float s); + +// -------------------------------------------------------------------------------- +/** Multiply each component of a 2D vector with + * the components of another vector. + * @param dst First vector, receives result + * @param other Second vector + */ +ASSIMP_API void aiVector2SymMul( + C_STRUCT aiVector2D* dst, + const C_STRUCT aiVector2D* other); + +// -------------------------------------------------------------------------------- +/** Divide a 2D vector by a scalar. + * @param dst Vector to be divided by \p s + * @param s Scalar divisor + */ +ASSIMP_API void aiVector2DivideByScalar( + C_STRUCT aiVector2D* dst, + const float s); + +// -------------------------------------------------------------------------------- +/** Divide each component of a 2D vector by + * the components of another vector. + * @param dst Vector as the dividend + * @param v Vector as the divisor + */ +ASSIMP_API void aiVector2DivideByVector( + C_STRUCT aiVector2D* dst, + C_STRUCT aiVector2D* v); + +// -------------------------------------------------------------------------------- +/** Get the length of a 2D vector. + * @return v Vector to evaluate + */ +ASSIMP_API float aiVector2Length( + const C_STRUCT aiVector2D* v); + +// -------------------------------------------------------------------------------- +/** Get the squared length of a 2D vector. + * @return v Vector to evaluate + */ +ASSIMP_API float aiVector2SquareLength( + const C_STRUCT aiVector2D* v); + +// -------------------------------------------------------------------------------- +/** Negate a 2D vector. + * @param dst Vector to be negated + */ +ASSIMP_API void aiVector2Negate( + C_STRUCT aiVector2D* dst); + +// -------------------------------------------------------------------------------- +/** Get the dot product of 2D vectors. + * @param a First vector + * @param b Second vector + * @return The dot product of vectors + */ +ASSIMP_API float aiVector2DotProduct( + const C_STRUCT aiVector2D* a, + const C_STRUCT aiVector2D* b); + +// -------------------------------------------------------------------------------- +/** Normalize a 2D vector. + * @param v Vector to normalize + */ +ASSIMP_API void aiVector2Normalize( + C_STRUCT aiVector2D* v); + +// -------------------------------------------------------------------------------- +/** Check if 3D vectors are equal. + * @param a First vector to compare + * @param b Second vector to compare + * @return 1 if the vectors are equal + * @return 0 if the vectors are not equal + */ +ASSIMP_API int aiVector3AreEqual( + const C_STRUCT aiVector3D* a, + const C_STRUCT aiVector3D* b); + +// -------------------------------------------------------------------------------- +/** Check if 3D vectors are equal using epsilon. + * @param a First vector to compare + * @param b Second vector to compare + * @param epsilon Epsilon + * @return 1 if the vectors are equal + * @return 0 if the vectors are not equal + */ +ASSIMP_API int aiVector3AreEqualEpsilon( + const C_STRUCT aiVector3D* a, + const C_STRUCT aiVector3D* b, + const float epsilon); + +// -------------------------------------------------------------------------------- +/** Check if vector \p a is less than vector \p b. + * @param a First vector to compare + * @param b Second vector to compare + * @param epsilon Epsilon + * @return 1 if \p a is less than \p b + * @return 0 if \p a is equal or greater than \p b + */ +ASSIMP_API int aiVector3LessThan( + const C_STRUCT aiVector3D* a, + const C_STRUCT aiVector3D* b); + +// -------------------------------------------------------------------------------- +/** Add 3D vectors. + * @param dst First addend, receives result. + * @param src Vector to be added to 'dst'. + */ +ASSIMP_API void aiVector3Add( + C_STRUCT aiVector3D* dst, + const C_STRUCT aiVector3D* src); + +// -------------------------------------------------------------------------------- +/** Subtract 3D vectors. + * @param dst Minuend, receives result. + * @param src Vector to be subtracted from 'dst'. + */ +ASSIMP_API void aiVector3Subtract( + C_STRUCT aiVector3D* dst, + const C_STRUCT aiVector3D* src); + +// -------------------------------------------------------------------------------- +/** Multiply a 3D vector by a scalar. + * @param dst Vector to be scaled by \p s + * @param s Scale factor + */ +ASSIMP_API void aiVector3Scale( + C_STRUCT aiVector3D* dst, + const float s); + +// -------------------------------------------------------------------------------- +/** Multiply each component of a 3D vector with + * the components of another vector. + * @param dst First vector, receives result + * @param other Second vector + */ +ASSIMP_API void aiVector3SymMul( + C_STRUCT aiVector3D* dst, + const C_STRUCT aiVector3D* other); + +// -------------------------------------------------------------------------------- +/** Divide a 3D vector by a scalar. + * @param dst Vector to be divided by \p s + * @param s Scalar divisor + */ +ASSIMP_API void aiVector3DivideByScalar( + C_STRUCT aiVector3D* dst, + const float s); + +// -------------------------------------------------------------------------------- +/** Divide each component of a 3D vector by + * the components of another vector. + * @param dst Vector as the dividend + * @param v Vector as the divisor + */ +ASSIMP_API void aiVector3DivideByVector( + C_STRUCT aiVector3D* dst, + C_STRUCT aiVector3D* v); + +// -------------------------------------------------------------------------------- +/** Get the length of a 3D vector. + * @return v Vector to evaluate + */ +ASSIMP_API float aiVector3Length( + const C_STRUCT aiVector3D* v); + +// -------------------------------------------------------------------------------- +/** Get the squared length of a 3D vector. + * @return v Vector to evaluate + */ +ASSIMP_API float aiVector3SquareLength( + const C_STRUCT aiVector3D* v); + +// -------------------------------------------------------------------------------- +/** Negate a 3D vector. + * @param dst Vector to be negated + */ +ASSIMP_API void aiVector3Negate( + C_STRUCT aiVector3D* dst); + +// -------------------------------------------------------------------------------- +/** Get the dot product of 3D vectors. + * @param a First vector + * @param b Second vector + * @return The dot product of vectors + */ +ASSIMP_API float aiVector3DotProduct( + const C_STRUCT aiVector3D* a, + const C_STRUCT aiVector3D* b); + +// -------------------------------------------------------------------------------- +/** Get cross product of 3D vectors. + * @param dst Vector to receive the result. + * @param a First vector + * @param b Second vector + * @return The dot product of vectors + */ +ASSIMP_API void aiVector3CrossProduct( + C_STRUCT aiVector3D* dst, + const C_STRUCT aiVector3D* a, + const C_STRUCT aiVector3D* b); + +// -------------------------------------------------------------------------------- +/** Normalize a 3D vector. + * @param v Vector to normalize + */ +ASSIMP_API void aiVector3Normalize( + C_STRUCT aiVector3D* v); + +// -------------------------------------------------------------------------------- +/** Check for division by zero and normalize a 3D vector. + * @param v Vector to normalize + */ +ASSIMP_API void aiVector3NormalizeSafe( + C_STRUCT aiVector3D* v); + +// -------------------------------------------------------------------------------- +/** Rotate a 3D vector by a quaternion. + * @param v The vector to rotate by \p q + * @param q Quaternion to use to rotate \p v + */ +ASSIMP_API void aiVector3RotateByQuaternion( + C_STRUCT aiVector3D* v, + const C_STRUCT aiQuaternion* q); + +// -------------------------------------------------------------------------------- +/** Construct a 3x3 matrix from a 4x4 matrix. + * @param dst Receives the output matrix + * @param mat The 4x4 matrix to use + */ +ASSIMP_API void aiMatrix3FromMatrix4( + C_STRUCT aiMatrix3x3* dst, + const C_STRUCT aiMatrix4x4* mat); + +// -------------------------------------------------------------------------------- +/** Construct a 3x3 matrix from a quaternion. + * @param mat Receives the output matrix + * @param q The quaternion matrix to use + */ +ASSIMP_API void aiMatrix3FromQuaternion( + C_STRUCT aiMatrix3x3* mat, + const C_STRUCT aiQuaternion* q); + +// -------------------------------------------------------------------------------- +/** Check if 3x3 matrices are equal. + * @param a First matrix to compare + * @param b Second matrix to compare + * @return 1 if the matrices are equal + * @return 0 if the matrices are not equal + */ +ASSIMP_API int aiMatrix3AreEqual( + const C_STRUCT aiMatrix3x3* a, + const C_STRUCT aiMatrix3x3* b); + +// -------------------------------------------------------------------------------- +/** Check if 3x3 matrices are equal. + * @param a First matrix to compare + * @param b Second matrix to compare + * @param epsilon Epsilon + * @return 1 if the matrices are equal + * @return 0 if the matrices are not equal + */ +ASSIMP_API int aiMatrix3AreEqualEpsilon( + const C_STRUCT aiMatrix3x3* a, + const C_STRUCT aiMatrix3x3* b, + const float epsilon); + +// -------------------------------------------------------------------------------- +/** Invert a 3x3 matrix. + * @param mat Matrix to invert + */ +ASSIMP_API void aiMatrix3Inverse( + C_STRUCT aiMatrix3x3* mat); + +// -------------------------------------------------------------------------------- +/** Get the determinant of a 3x3 matrix. + * @param mat Matrix to get the determinant from + */ +ASSIMP_API float aiMatrix3Determinant( + const C_STRUCT aiMatrix3x3* mat); + +// -------------------------------------------------------------------------------- +/** Get a 3x3 rotation matrix around the Z axis. + * @param mat Receives the output matrix + * @param angle Rotation angle, in radians + */ +ASSIMP_API void aiMatrix3RotationZ( + C_STRUCT aiMatrix3x3* mat, + const float angle); + +// -------------------------------------------------------------------------------- +/** Returns a 3x3 rotation matrix for a rotation around an arbitrary axis. + * @param mat Receives the output matrix + * @param axis Rotation axis, should be a normalized vector + * @param angle Rotation angle, in radians + */ +ASSIMP_API void aiMatrix3FromRotationAroundAxis( + C_STRUCT aiMatrix3x3* mat, + const C_STRUCT aiVector3D* axis, + const float angle); + +// -------------------------------------------------------------------------------- +/** Get a 3x3 translation matrix. + * @param mat Receives the output matrix + * @param translation The translation vector + */ +ASSIMP_API void aiMatrix3Translation( + C_STRUCT aiMatrix3x3* mat, + const C_STRUCT aiVector2D* translation); + +// -------------------------------------------------------------------------------- +/** Create a 3x3 matrix that rotates one vector to another vector. + * @param mat Receives the output matrix + * @param from Vector to rotate from + * @param to Vector to rotate to + */ +ASSIMP_API void aiMatrix3FromTo( + C_STRUCT aiMatrix3x3* mat, + const C_STRUCT aiVector3D* from, + const C_STRUCT aiVector3D* to); + +// -------------------------------------------------------------------------------- +/** Construct a 4x4 matrix from a 3x3 matrix. + * @param dst Receives the output matrix + * @param mat The 3x3 matrix to use + */ +ASSIMP_API void aiMatrix4FromMatrix3( + C_STRUCT aiMatrix4x4* dst, + const C_STRUCT aiMatrix3x3* mat); + +// -------------------------------------------------------------------------------- +/** Construct a 4x4 matrix from scaling, rotation and position. + * @param mat Receives the output matrix. + * @param scaling The scaling for the x,y,z axes + * @param rotation The rotation as a hamilton quaternion + * @param position The position for the x,y,z axes + */ +ASSIMP_API void aiMatrix4FromScalingQuaternionPosition( + C_STRUCT aiMatrix4x4* mat, + const C_STRUCT aiVector3D* scaling, + const C_STRUCT aiQuaternion* rotation, + const C_STRUCT aiVector3D* position); + +// -------------------------------------------------------------------------------- +/** Add 4x4 matrices. + * @param dst First addend, receives result. + * @param src Matrix to be added to 'dst'. + */ +ASSIMP_API void aiMatrix4Add( + C_STRUCT aiMatrix4x4* dst, + const C_STRUCT aiMatrix4x4* src); + +// -------------------------------------------------------------------------------- +/** Check if 4x4 matrices are equal. + * @param a First matrix to compare + * @param b Second matrix to compare + * @return 1 if the matrices are equal + * @return 0 if the matrices are not equal + */ +ASSIMP_API int aiMatrix4AreEqual( + const C_STRUCT aiMatrix4x4* a, + const C_STRUCT aiMatrix4x4* b); + +// -------------------------------------------------------------------------------- +/** Check if 4x4 matrices are equal. + * @param a First matrix to compare + * @param b Second matrix to compare + * @param epsilon Epsilon + * @return 1 if the matrices are equal + * @return 0 if the matrices are not equal + */ +ASSIMP_API int aiMatrix4AreEqualEpsilon( + const C_STRUCT aiMatrix4x4* a, + const C_STRUCT aiMatrix4x4* b, + const float epsilon); + +// -------------------------------------------------------------------------------- +/** Invert a 4x4 matrix. + * @param result Matrix to invert + */ +ASSIMP_API void aiMatrix4Inverse( + C_STRUCT aiMatrix4x4* mat); + +// -------------------------------------------------------------------------------- +/** Get the determinant of a 4x4 matrix. + * @param mat Matrix to get the determinant from + * @return The determinant of the matrix + */ +ASSIMP_API float aiMatrix4Determinant( + const C_STRUCT aiMatrix4x4* mat); + +// -------------------------------------------------------------------------------- +/** Returns true of the matrix is the identity matrix. + * @param mat Matrix to get the determinant from + * @return 1 if \p mat is an identity matrix. + * @return 0 if \p mat is not an identity matrix. + */ +ASSIMP_API int aiMatrix4IsIdentity( + const C_STRUCT aiMatrix4x4* mat); + +// -------------------------------------------------------------------------------- +/** Decompose a transformation matrix into its scaling, + * rotational as euler angles, and translational components. + * + * @param mat Matrix to decompose + * @param scaling Receives the output scaling for the x,y,z axes + * @param rotation Receives the output rotation as a Euler angles + * @param position Receives the output position for the x,y,z axes + */ +ASSIMP_API void aiMatrix4DecomposeIntoScalingEulerAnglesPosition( + const C_STRUCT aiMatrix4x4* mat, + C_STRUCT aiVector3D* scaling, + C_STRUCT aiVector3D* rotation, + C_STRUCT aiVector3D* position); + +// -------------------------------------------------------------------------------- +/** Decompose a transformation matrix into its scaling, + * rotational split into an axis and rotational angle, + * and it's translational components. + * + * @param mat Matrix to decompose + * @param rotation Receives the rotational component + * @param axis Receives the output rotation axis + * @param angle Receives the output rotation angle + * @param position Receives the output position for the x,y,z axes. + */ +ASSIMP_API void aiMatrix4DecomposeIntoScalingAxisAnglePosition( + const C_STRUCT aiMatrix4x4* mat, + C_STRUCT aiVector3D* scaling, + C_STRUCT aiVector3D* axis, + float* angle, + C_STRUCT aiVector3D* position); + +// -------------------------------------------------------------------------------- +/** Decompose a transformation matrix into its rotational and + * translational components. + * + * @param mat Matrix to decompose + * @param rotation Receives the rotational component + * @param position Receives the translational component. + */ +ASSIMP_API void aiMatrix4DecomposeNoScaling( + const C_STRUCT aiMatrix4x4* mat, + C_STRUCT aiQuaternion* rotation, + C_STRUCT aiVector3D* position); + +// -------------------------------------------------------------------------------- +/** Creates a 4x4 matrix from a set of euler angles. + * @param mat Receives the output matrix + * @param x Rotation angle for the x-axis, in radians + * @param y Rotation angle for the y-axis, in radians + * @param z Rotation angle for the z-axis, in radians + */ +ASSIMP_API void aiMatrix4FromEulerAngles( + C_STRUCT aiMatrix4x4* mat, + float x, float y, float z); + +// -------------------------------------------------------------------------------- +/** Get a 4x4 rotation matrix around the X axis. + * @param mat Receives the output matrix + * @param angle Rotation angle, in radians + */ +ASSIMP_API void aiMatrix4RotationX( + C_STRUCT aiMatrix4x4* mat, + const float angle); + +// -------------------------------------------------------------------------------- +/** Get a 4x4 rotation matrix around the Y axis. + * @param mat Receives the output matrix + * @param angle Rotation angle, in radians + */ +ASSIMP_API void aiMatrix4RotationY( + C_STRUCT aiMatrix4x4* mat, + const float angle); + +// -------------------------------------------------------------------------------- +/** Get a 4x4 rotation matrix around the Z axis. + * @param mat Receives the output matrix + * @param angle Rotation angle, in radians + */ +ASSIMP_API void aiMatrix4RotationZ( + C_STRUCT aiMatrix4x4* mat, + const float angle); + +// -------------------------------------------------------------------------------- +/** Returns a 4x4 rotation matrix for a rotation around an arbitrary axis. + * @param mat Receives the output matrix + * @param axis Rotation axis, should be a normalized vector + * @param angle Rotation angle, in radians + */ +ASSIMP_API void aiMatrix4FromRotationAroundAxis( + C_STRUCT aiMatrix4x4* mat, + const C_STRUCT aiVector3D* axis, + const float angle); + +// -------------------------------------------------------------------------------- +/** Get a 4x4 translation matrix. + * @param mat Receives the output matrix + * @param translation The translation vector + */ +ASSIMP_API void aiMatrix4Translation( + C_STRUCT aiMatrix4x4* mat, + const C_STRUCT aiVector3D* translation); + +// -------------------------------------------------------------------------------- +/** Get a 4x4 scaling matrix. + * @param mat Receives the output matrix + * @param scaling The scaling vector + */ +ASSIMP_API void aiMatrix4Scaling( + C_STRUCT aiMatrix4x4* mat, + const C_STRUCT aiVector3D* scaling); + +// -------------------------------------------------------------------------------- +/** Create a 4x4 matrix that rotates one vector to another vector. + * @param mat Receives the output matrix + * @param from Vector to rotate from + * @param to Vector to rotate to + */ +ASSIMP_API void aiMatrix4FromTo( + C_STRUCT aiMatrix4x4* mat, + const C_STRUCT aiVector3D* from, + const C_STRUCT aiVector3D* to); + +// -------------------------------------------------------------------------------- +/** Create a Quaternion from euler angles. + * @param q Receives the output quaternion + * @param x Rotation angle for the x-axis, in radians + * @param y Rotation angle for the y-axis, in radians + * @param z Rotation angle for the z-axis, in radians + */ +ASSIMP_API void aiQuaternionFromEulerAngles( + C_STRUCT aiQuaternion* q, + float x, float y, float z); + +// -------------------------------------------------------------------------------- +/** Create a Quaternion from an axis angle pair. + * @param q Receives the output quaternion + * @param axis The orientation axis + * @param angle The rotation angle, in radians + */ +ASSIMP_API void aiQuaternionFromAxisAngle( + C_STRUCT aiQuaternion* q, + const C_STRUCT aiVector3D* axis, + const float angle); + +// -------------------------------------------------------------------------------- +/** Create a Quaternion from a normalized quaternion stored + * in a 3D vector. + * @param q Receives the output quaternion + * @param normalized The vector that stores the quaternion + */ +ASSIMP_API void aiQuaternionFromNormalizedQuaternion( + C_STRUCT aiQuaternion* q, + const C_STRUCT aiVector3D* normalized); + +// -------------------------------------------------------------------------------- +/** Check if quaternions are equal. + * @param a First quaternion to compare + * @param b Second quaternion to compare + * @return 1 if the quaternions are equal + * @return 0 if the quaternions are not equal + */ +ASSIMP_API int aiQuaternionAreEqual( + const C_STRUCT aiQuaternion* a, + const C_STRUCT aiQuaternion* b); + +// -------------------------------------------------------------------------------- +/** Check if quaternions are equal using epsilon. + * @param a First quaternion to compare + * @param b Second quaternion to compare + * @param epsilon Epsilon + * @return 1 if the quaternions are equal + * @return 0 if the quaternions are not equal + */ +ASSIMP_API int aiQuaternionAreEqualEpsilon( + const C_STRUCT aiQuaternion* a, + const C_STRUCT aiQuaternion* b, + const float epsilon); + +// -------------------------------------------------------------------------------- +/** Normalize a quaternion. + * @param q Quaternion to normalize + */ +ASSIMP_API void aiQuaternionNormalize( + C_STRUCT aiQuaternion* q); + +// -------------------------------------------------------------------------------- +/** Compute quaternion conjugate. + * @param q Quaternion to compute conjugate, + * receives the output quaternion + */ +ASSIMP_API void aiQuaternionConjugate( + C_STRUCT aiQuaternion* q); + +// -------------------------------------------------------------------------------- +/** Multiply quaternions. + * @param dst First quaternion, receives the output quaternion + * @param q Second quaternion + */ +ASSIMP_API void aiQuaternionMultiply( + C_STRUCT aiQuaternion* dst, + const C_STRUCT aiQuaternion* q); + +// -------------------------------------------------------------------------------- +/** Performs a spherical interpolation between two quaternions. + * @param dst Receives the quaternion resulting from the interpolation. + * @param start Quaternion when factor == 0 + * @param end Quaternion when factor == 1 + * @param factor Interpolation factor between 0 and 1 + */ +ASSIMP_API void aiQuaternionInterpolate( + C_STRUCT aiQuaternion* dst, + const C_STRUCT aiQuaternion* start, + const C_STRUCT aiQuaternion* end, + const float factor); + #ifdef __cplusplus } #endif diff --git a/include/assimp/quaternion.h b/include/assimp/quaternion.h index fd9abfd21..9a14bd413 100644 --- a/include/assimp/quaternion.h +++ b/include/assimp/quaternion.h @@ -99,7 +99,7 @@ public: aiQuaterniont& Conjugate (); /** Rotate a point by this quaternion */ - aiVector3t Rotate (const aiVector3t& in); + aiVector3t Rotate (const aiVector3t& in) const; /** Multiply two quaternions */ aiQuaterniont operator* (const aiQuaterniont& two) const; diff --git a/include/assimp/quaternion.inl b/include/assimp/quaternion.inl index e8bdb9aeb..32549db3b 100644 --- a/include/assimp/quaternion.inl +++ b/include/assimp/quaternion.inl @@ -277,7 +277,7 @@ inline aiQuaterniont& aiQuaterniont::Conjugate () // --------------------------------------------------------------------------- template -inline aiVector3t aiQuaterniont::Rotate (const aiVector3t& v) +inline aiVector3t aiQuaterniont::Rotate (const aiVector3t& v) const { aiQuaterniont q2(0.f,v.x,v.y,v.z), q = *this, qinv = q; qinv.Conjugate();