diff --git a/include/COLLADA2GLTFWriter.h b/include/COLLADA2GLTFWriter.h index 87ce7b710..c74d22c93 100644 --- a/include/COLLADA2GLTFWriter.h +++ b/include/COLLADA2GLTFWriter.h @@ -25,6 +25,7 @@ namespace COLLADA2GLTF { std::map>> _meshPositionMapping; std::map _skinInstances; std::map _animatedNodes; + std::map _originalRotationAngles; std::map*> _unboundSkeletonNodes; std::map _nodes; std::map> _skinJointNodes; diff --git a/src/COLLADA2GLTFWriter.cpp b/src/COLLADA2GLTFWriter.cpp index e8a44a4d4..90adeb9ef 100644 --- a/src/COLLADA2GLTFWriter.cpp +++ b/src/COLLADA2GLTFWriter.cpp @@ -184,6 +184,10 @@ bool COLLADA2GLTF::Writer::writeNodeToGroup(std::vector* group, con node->transform = transform; _animatedNodes[animationListId] = node; + if (transformation->getTransformationType() == COLLADAFW::Transformation::ROTATE) { + COLLADAFW::Rotate* rotate = (COLLADAFW::Rotate*)transformation; + _originalRotationAngles[animationListId] = rotate->getRotationAngle(); + } isAnimated = true; } else { @@ -1029,7 +1033,14 @@ void interpolateTranslation(float* base, std::vector input, std::vectorgetAnimationBindings(); + COLLADAFW::UniqueId animationListId = animationList->getUniqueId(); GLTF::Node* node = _animatedNodes[animationList->getUniqueId()]; + float originalRotationAngle = NAN; + std::map::iterator iter = _originalRotationAngles.find(animationListId); + if (iter != _originalRotationAngles.end()) { + originalRotationAngle = iter->second; + } + GLTF::Node::Transform* nodeTransform = node->transform; GLTF::Node::TransformTRS* nodeTransformTRS = NULL; std::set timeSet = std::set(); @@ -1217,6 +1228,12 @@ bool COLLADA2GLTF::Writer::writeAnimationList(const COLLADAFW::AnimationList* an COLLADABU::Math::Vector3 axis; COLLADABU::Math::Quaternion quaternion = COLLADABU::Math::Quaternion(nodeRotation[3], nodeRotation[0], nodeRotation[1], nodeRotation[2]); quaternion.toAngleAxis(angle, axis); + if (originalRotationAngle != NAN && fabs(COLLADABU::Math::Utils::degToRad(originalRotationAngle) - angle) > 1e-3) { + // Quaternion -> axis angle can flip chirality; check it against the original rotation angle and correct the axis direction + axis.x = -axis.x; + axis.y = -axis.y; + axis.z = -axis.z; + } angle = COLLADABU::Math::Utils::degToRad(output[index]); quaternion.fromAngleAxis(angle, axis); rotation[j * 4] = (float)quaternion.x;