diff --git a/libraries/animation/src/AnimBlendLinear.cpp b/libraries/animation/src/AnimBlendLinear.cpp index 4e8c42dad3..c066dc92eb 100644 --- a/libraries/animation/src/AnimBlendLinear.cpp +++ b/libraries/animation/src/AnimBlendLinear.cpp @@ -37,6 +37,19 @@ const AnimPoseVec& AnimBlendLinear::evaluate(const AnimVariantMap& animVars, con } else if (_children.size() == 1) { _poses = _children[0]->evaluate(animVars, context, dt, triggersOut); context.setDebugAlpha(_children[0]->getID(), parentDebugAlpha, _children[0]->getType()); + } else if (_children.size() == 2 && _blendType != AnimBlendType_Normal) { + // special case for additive blending + float alpha = glm::clamp(_alpha, 0.0f, 1.0f); + const size_t prevPoseIndex = 0; + const size_t nextPoseIndex = 1; + evaluateAndBlendChildren(animVars, context, triggersOut, alpha, prevPoseIndex, nextPoseIndex, dt); + + // for animation stack debugging + float weight2 = alpha; + float weight1 = 1.0f - weight2; + context.setDebugAlpha(_children[prevPoseIndex]->getID(), weight1 * parentDebugAlpha, _children[prevPoseIndex]->getType()); + context.setDebugAlpha(_children[nextPoseIndex]->getID(), weight2 * parentDebugAlpha, _children[nextPoseIndex]->getType()); + } else { float clampedAlpha = glm::clamp(_alpha, 0.0f, (float)(_children.size() - 1)); size_t prevPoseIndex = glm::floor(clampedAlpha); diff --git a/libraries/animation/src/AnimUtil.cpp b/libraries/animation/src/AnimUtil.cpp index 621e714f97..e5f7cf4182 100644 --- a/libraries/animation/src/AnimUtil.cpp +++ b/libraries/animation/src/AnimUtil.cpp @@ -28,19 +28,22 @@ void blend(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, A // additive blend void blendAdd(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, AnimPose* result) { + + const glm::quat identity = glm::quat(); for (size_t i = 0; i < numPoses; i++) { const AnimPose& aPose = a[i]; const AnimPose& bPose = b[i]; result[i].scale() = lerp(aPose.scale(), bPose.scale(), alpha); - // adjust sign of bPose.rot() if necessary - glm::quat bTemp = bPose.rot(); - float dot = glm::dot(aPose.rot(), bTemp); - if (dot < 0.0f) { - bTemp = -bTemp; + // ensure that delta has the same "polarity" as the identity quat. + // we don't need to do a full dot product, just sign of w is sufficient. + glm::quat delta = bPose.rot(); + if (delta.w < 0.0f) { + delta = -delta; } - result[i].rot() = glm::normalize((alpha * bTemp) * aPose.rot()); + delta = glm::lerp(identity, delta, alpha); + result[i].rot() = glm::normalize(delta * aPose.rot()); result[i].trans() = aPose.trans() + (alpha * bPose.trans()); }