diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index ed9167f74..1c842e6b8 100644 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -138,257 +138,6 @@ U32 LLKeyframeMotion::JointMotionList::dumpDiagInfo(bool silent) const return total_size; } -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// ****Curve classes -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// ScaleCurve::ScaleCurve() -//----------------------------------------------------------------------------- -LLKeyframeMotion::ScaleCurve::ScaleCurve() -{ - mInterpolationType = LLKeyframeMotion::IT_LINEAR; - mNumKeys = 0; -} - -//----------------------------------------------------------------------------- -// ScaleCurve::~ScaleCurve() -//----------------------------------------------------------------------------- -LLKeyframeMotion::ScaleCurve::~ScaleCurve() -{ - mKeys.clear(); - mNumKeys = 0; -} - -//----------------------------------------------------------------------------- -// getValue() -//----------------------------------------------------------------------------- -LLVector3 LLKeyframeMotion::ScaleCurve::getValue(F32 time, F32 duration) -{ - LLVector3 value; - - if (mKeys.empty()) - { - value.clearVec(); - return value; - } - - key_map_t::iterator right = mKeys.lower_bound(time); - if (right == mKeys.end()) - { - // Past last key - --right; - value = right->second.mScale; - } - else if (right == mKeys.begin() || right->first == time) - { - // Before first key or exactly on a key - value = right->second.mScale; - } - else - { - // Between two keys - key_map_t::iterator left = right; --left; - F32 index_before = left->first; - F32 index_after = right->first; - ScaleKey& scale_before = left->second; - ScaleKey& scale_after = right->second; - if (right == mKeys.end()) - { - scale_after = mLoopInKey; - index_after = duration; - } - - F32 u = (time - index_before) / (index_after - index_before); - value = interp(u, scale_before, scale_after); - } - return value; -} - -//----------------------------------------------------------------------------- -// interp() -//----------------------------------------------------------------------------- -LLVector3 LLKeyframeMotion::ScaleCurve::interp(F32 u, ScaleKey& before, ScaleKey& after) -{ - switch (mInterpolationType) - { - case IT_STEP: - return before.mScale; - - default: - case IT_LINEAR: - case IT_SPLINE: - return lerp(before.mScale, after.mScale, u); - } -} - -//----------------------------------------------------------------------------- -// RotationCurve::RotationCurve() -//----------------------------------------------------------------------------- -LLKeyframeMotion::RotationCurve::RotationCurve() -{ - mInterpolationType = LLKeyframeMotion::IT_LINEAR; - mNumKeys = 0; -} - -//----------------------------------------------------------------------------- -// RotationCurve::~RotationCurve() -//----------------------------------------------------------------------------- -LLKeyframeMotion::RotationCurve::~RotationCurve() -{ - mKeys.clear(); - mNumKeys = 0; -} - -//----------------------------------------------------------------------------- -// RotationCurve::getValue() -//----------------------------------------------------------------------------- -LLQuaternion LLKeyframeMotion::RotationCurve::getValue(F32 time, F32 duration) -{ - LLQuaternion value; - - if (mKeys.empty()) - { - value = LLQuaternion::DEFAULT; - return value; - } - - key_map_t::iterator right = mKeys.lower_bound(time); - if (right == mKeys.end()) - { - // Past last key - --right; - value = right->second.mRotation; - } - else if (right == mKeys.begin() || right->first == time) - { - // Before first key or exactly on a key - value = right->second.mRotation; - } - else - { - // Between two keys - key_map_t::iterator left = right; --left; - F32 index_before = left->first; - F32 index_after = right->first; - RotationKey& rot_before = left->second; - RotationKey& rot_after = right->second; - if (right == mKeys.end()) - { - rot_after = mLoopInKey; - index_after = duration; - } - - F32 u = (time - index_before) / (index_after - index_before); - value = interp(u, rot_before, rot_after); - } - return value; -} - -//----------------------------------------------------------------------------- -// interp() -//----------------------------------------------------------------------------- -LLQuaternion LLKeyframeMotion::RotationCurve::interp(F32 u, RotationKey& before, RotationKey& after) -{ - switch (mInterpolationType) - { - case IT_STEP: - return before.mRotation; - - default: - case IT_LINEAR: - case IT_SPLINE: - return nlerp(u, before.mRotation, after.mRotation); - } -} - - -//----------------------------------------------------------------------------- -// PositionCurve::PositionCurve() -//----------------------------------------------------------------------------- -LLKeyframeMotion::PositionCurve::PositionCurve() -{ - mInterpolationType = LLKeyframeMotion::IT_LINEAR; - mNumKeys = 0; -} - -//----------------------------------------------------------------------------- -// PositionCurve::~PositionCurve() -//----------------------------------------------------------------------------- -LLKeyframeMotion::PositionCurve::~PositionCurve() -{ - mKeys.clear(); - mNumKeys = 0; -} - -//----------------------------------------------------------------------------- -// PositionCurve::getValue() -//----------------------------------------------------------------------------- -LLVector3 LLKeyframeMotion::PositionCurve::getValue(F32 time, F32 duration) -{ - LLVector3 value; - - if (mKeys.empty()) - { - value.clearVec(); - return value; - } - - key_map_t::iterator right = mKeys.lower_bound(time); - if (right == mKeys.end()) - { - // Past last key - --right; - value = right->second.mPosition; - } - else if (right == mKeys.begin() || right->first == time) - { - // Before first key or exactly on a key - value = right->second.mPosition; - } - else - { - // Between two keys - key_map_t::iterator left = right; --left; - F32 index_before = left->first; - F32 index_after = right->first; - PositionKey& pos_before = left->second; - PositionKey& pos_after = right->second; - if (right == mKeys.end()) - { - pos_after = mLoopInKey; - index_after = duration; - } - - F32 u = (time - index_before) / (index_after - index_before); - value = interp(u, pos_before, pos_after); - } - - llassert(value.isFinite()); - - return value; -} - -//----------------------------------------------------------------------------- -// interp() -//----------------------------------------------------------------------------- -LLVector3 LLKeyframeMotion::PositionCurve::interp(F32 u, PositionKey& before, PositionKey& after) -{ - switch (mInterpolationType) - { - case IT_STEP: - return before.mPosition; - default: - case IT_LINEAR: - case IT_SPLINE: - return lerp(before.mPosition, after.mPosition, u); - } -} - - //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // JointMotion class @@ -1668,7 +1417,7 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id) success = dp.unpackVector3(rot_angles, "rot_angles") && rot_angles.isFinite(); LLQuaternion::Order ro = StringToOrder("ZYX"); - rot_key.mRotation = mayaQ(rot_angles.mV[VX], rot_angles.mV[VY], rot_angles.mV[VZ], ro); + rot_key.mValue = mayaQ(rot_angles.mV[VX], rot_angles.mV[VY], rot_angles.mV[VZ], ro); } else { @@ -1680,10 +1429,10 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id) rot_vec.mV[VX] = U16_to_F32(x, -1.f, 1.f); rot_vec.mV[VY] = U16_to_F32(y, -1.f, 1.f); rot_vec.mV[VZ] = U16_to_F32(z, -1.f, 1.f); - rot_key.mRotation.unpackFromVector3(rot_vec); + rot_key.mValue.unpackFromVector3(rot_vec); } - if( !(rot_key.mRotation.isFinite()) ) + if( !(rot_key.mValue.isFinite()) ) { LL_WARNS() << "non-finite angle in rotation key" << " for animation " << asset_id << LL_ENDL; @@ -1697,9 +1446,11 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id) return FALSE; } - rCurve->mKeys[time] = rot_key; + rCurve->mKeys.emplace_back(time, rot_key); } + std::sort(rCurve->mKeys.begin(), rCurve->mKeys.end(), [](const auto& a, const auto& b) { return a.first < b.first; }); + //--------------------------------------------------------------------- // scan position curve header //--------------------------------------------------------------------- @@ -1752,12 +1503,12 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id) if (old_version) { - success = dp.unpackVector3(pos_key.mPosition, "pos"); + success = dp.unpackVector3(pos_key.mValue, "pos"); //MAINT-6162 - pos_key.mPosition.mV[VX] = llclamp( pos_key.mPosition.mV[VX], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); - pos_key.mPosition.mV[VY] = llclamp( pos_key.mPosition.mV[VY], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); - pos_key.mPosition.mV[VZ] = llclamp( pos_key.mPosition.mV[VZ], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + pos_key.mValue.mV[VX] = llclamp( pos_key.mValue.mV[VX], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + pos_key.mValue.mV[VY] = llclamp( pos_key.mValue.mV[VY], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + pos_key.mValue.mV[VZ] = llclamp( pos_key.mValue.mV[VZ], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); } else @@ -1768,12 +1519,12 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id) success &= dp.unpackU16(y, "pos_y"); success &= dp.unpackU16(z, "pos_z"); - pos_key.mPosition.mV[VX] = U16_to_F32(x, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); - pos_key.mPosition.mV[VY] = U16_to_F32(y, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); - pos_key.mPosition.mV[VZ] = U16_to_F32(z, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + pos_key.mValue.mV[VX] = U16_to_F32(x, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + pos_key.mValue.mV[VY] = U16_to_F32(y, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + pos_key.mValue.mV[VZ] = U16_to_F32(z, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); } - if( !(pos_key.mPosition.isFinite()) ) + if( !(pos_key.mValue.isFinite()) ) { LL_WARNS() << "non-finite position in key" << " for animation " << asset_id << LL_ENDL; @@ -1787,14 +1538,17 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id) return FALSE; } - pCurve->mKeys[pos_key.mTime] = pos_key; + pCurve->mKeys.emplace_back(pos_key.mTime, pos_key); if (is_pelvis) { - mJointMotionList->mPelvisBBox.addPoint(pos_key.mPosition); + mJointMotionList->mPelvisBBox.addPoint(pos_key.mValue); } + } + std::sort(pCurve->mKeys.begin(), pCurve->mKeys.end(), [](const auto& a, const auto& b) { return a.first < b.first; }); + joint_motion->mUsage = joint_state->getUsage(); } @@ -2087,7 +1841,7 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const U16 time_short = F32_to_U16(rot_key.mTime, 0.f, mJointMotionList->mDuration); success &= dp.packU16(time_short, "time"); - LLVector3 rot_angles = rot_key.mRotation.packToVector3(); + LLVector3 rot_angles = rot_key.mValue.packToVector3(); U16 x, y, z; rot_angles.quantize16(-1.f, 1.f, -1.f, 1.f); @@ -2110,15 +1864,15 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const success &= dp.packU16(time_short, "time"); U16 x, y, z; - pos_key.mPosition.quantize16(-LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); - x = F32_to_U16(pos_key.mPosition.mV[VX], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); - y = F32_to_U16(pos_key.mPosition.mV[VY], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); - z = F32_to_U16(pos_key.mPosition.mV[VZ], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + pos_key.mValue.quantize16(-LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + x = F32_to_U16(pos_key.mValue.mV[VX], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + y = F32_to_U16(pos_key.mValue.mV[VY], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + z = F32_to_U16(pos_key.mValue.mV[VZ], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); success &= dp.packU16(x, "pos_x"); success &= dp.packU16(y, "pos_y"); success &= dp.packU16(z, "pos_z"); - LL_DEBUGS("BVH") << " pos: t " << pos_key.mTime << " pos " << pos_key.mPosition.mV[VX] <<","<< pos_key.mPosition.mV[VY] <<","<< pos_key.mPosition.mV[VZ] << LL_ENDL; + LL_DEBUGS("BVH") << " pos: t " << pos_key.mTime << " pos " << pos_key.mValue.mV[VX] <<","<< pos_key.mValue.mV[VY] <<","<< pos_key.mValue.mV[VZ] << LL_ENDL; } } @@ -2296,9 +2050,9 @@ void LLKeyframeMotion::setLoopIn(F32 in_point) rot_curve->mLoopInKey.mTime = mJointMotionList->mLoopInPoint; scale_curve->mLoopInKey.mTime = mJointMotionList->mLoopInPoint; - pos_curve->mLoopInKey.mPosition = pos_curve->getValue(mJointMotionList->mLoopInPoint, mJointMotionList->mDuration); - rot_curve->mLoopInKey.mRotation = rot_curve->getValue(mJointMotionList->mLoopInPoint, mJointMotionList->mDuration); - scale_curve->mLoopInKey.mScale = scale_curve->getValue(mJointMotionList->mLoopInPoint, mJointMotionList->mDuration); + pos_curve->mLoopInKey.mValue = pos_curve->getValue(mJointMotionList->mLoopInPoint, mJointMotionList->mDuration); + rot_curve->mLoopInKey.mValue = rot_curve->getValue(mJointMotionList->mLoopInPoint, mJointMotionList->mDuration); + scale_curve->mLoopInKey.mValue = scale_curve->getValue(mJointMotionList->mLoopInPoint, mJointMotionList->mDuration); } } } @@ -2325,9 +2079,9 @@ void LLKeyframeMotion::setLoopOut(F32 out_point) rot_curve->mLoopOutKey.mTime = mJointMotionList->mLoopOutPoint; scale_curve->mLoopOutKey.mTime = mJointMotionList->mLoopOutPoint; - pos_curve->mLoopOutKey.mPosition = pos_curve->getValue(mJointMotionList->mLoopOutPoint, mJointMotionList->mDuration); - rot_curve->mLoopOutKey.mRotation = rot_curve->getValue(mJointMotionList->mLoopOutPoint, mJointMotionList->mDuration); - scale_curve->mLoopOutKey.mScale = scale_curve->getValue(mJointMotionList->mLoopOutPoint, mJointMotionList->mDuration); + pos_curve->mLoopOutKey.mValue = pos_curve->getValue(mJointMotionList->mLoopOutPoint, mJointMotionList->mDuration); + rot_curve->mLoopOutKey.mValue = rot_curve->getValue(mJointMotionList->mLoopOutPoint, mJointMotionList->mDuration); + scale_curve->mLoopOutKey.mValue = scale_curve->getValue(mJointMotionList->mLoopOutPoint, mJointMotionList->mDuration); } } } diff --git a/indra/llcharacter/llkeyframemotion.h b/indra/llcharacter/llkeyframemotion.h index c68243bd4..1db66a50d 100644 --- a/indra/llcharacter/llkeyframemotion.h +++ b/indra/llcharacter/llkeyframemotion.h @@ -387,101 +387,99 @@ public: enum InterpolationType { IT_STEP, IT_LINEAR, IT_SPLINE }; - //------------------------------------------------------------------------- - // ScaleKey - //------------------------------------------------------------------------- - class ScaleKey - { - public: - ScaleKey() { mTime = 0.0f; } - ScaleKey(F32 time, const LLVector3 &scale) { mTime = time; mScale = scale; } - - F32 mTime; - LLVector3 mScale; + template + struct lerp_op { + static T lerp(F32 t, const T& before, const T& after) + { + return ::lerp(before, after, t); + } + }; + template<> + struct lerp_op { + static LLQuaternion lerp(F32 t, const LLQuaternion& before, const LLQuaternion& after) + { + return ::nlerp(t, before, after); + } }; - //------------------------------------------------------------------------- - // RotationKey - //------------------------------------------------------------------------- - class RotationKey + template + struct Curve { - public: - RotationKey() { mTime = 0.0f; } - RotationKey(F32 time, const LLQuaternion &rotation) { mTime = time; mRotation = rotation; } + struct Key + { + Key() = default; + Key(F32 time, const T& value) { mTime = time; mValue = value; } + F32 mTime = 0; + T mValue; + }; - F32 mTime; - LLQuaternion mRotation; - }; + T interp(F32 u, Key& before, Key& after) + { + switch (mInterpolationType) + { + case IT_STEP: + return before.mValue; + default: + case IT_LINEAR: + case IT_SPLINE: + return lerp_op::lerp(u, before.mValue, after.mValue); + } + } - //------------------------------------------------------------------------- - // PositionKey - //------------------------------------------------------------------------- - class PositionKey - { - public: - PositionKey() { mTime = 0.0f; } - PositionKey(F32 time, const LLVector3 &position) { mTime = time; mPosition = position; } + T getValue(F32 time, F32 duration) + { + if (mKeys.empty()) + { + return T(); + } - F32 mTime; - LLVector3 mPosition; - }; + T value; + key_map_t::iterator right = std::lower_bound(mKeys.begin(), mKeys.end(), time, [](const auto& a, const auto& b) { return a.first < b; }); + if (right == mKeys.end()) + { + // Past last key + --right; + value = right->second.mValue; + } + else if (right == mKeys.begin() || right->first == time) + { + // Before first key or exactly on a key + value = right->second.mValue; + } + else + { + // Between two keys + key_map_t::iterator left = right; --left; + F32 index_before = left->first; + F32 index_after = right->first; + Key& pos_before = left->second; + Key& pos_after = right->second; + if (right == mKeys.end()) + { + pos_after = mLoopInKey; + index_after = duration; + } - //------------------------------------------------------------------------- - // ScaleCurve - //------------------------------------------------------------------------- - class ScaleCurve - { - public: - ScaleCurve(); - ~ScaleCurve(); - LLVector3 getValue(F32 time, F32 duration); - LLVector3 interp(F32 u, ScaleKey& before, ScaleKey& after); + F32 u = (time - index_before) / (index_after - index_before); + value = interp(u, pos_before, pos_after); + } + return value; + } - InterpolationType mInterpolationType; - S32 mNumKeys; - typedef std::map key_map_t; + InterpolationType mInterpolationType = LLKeyframeMotion::IT_LINEAR; + S32 mNumKeys = 0; + typedef std::vector< std::pair > key_map_t; key_map_t mKeys; - ScaleKey mLoopInKey; - ScaleKey mLoopOutKey; + Key mLoopInKey; + Key mLoopOutKey; }; - //------------------------------------------------------------------------- - // RotationCurve - //------------------------------------------------------------------------- - class RotationCurve - { - public: - RotationCurve(); - ~RotationCurve(); - LLQuaternion getValue(F32 time, F32 duration); - LLQuaternion interp(F32 u, RotationKey& before, RotationKey& after); - - InterpolationType mInterpolationType; - S32 mNumKeys; - typedef std::map key_map_t; - key_map_t mKeys; - RotationKey mLoopInKey; - RotationKey mLoopOutKey; - }; - - //------------------------------------------------------------------------- - // PositionCurve - //------------------------------------------------------------------------- - class PositionCurve - { - public: - PositionCurve(); - ~PositionCurve(); - LLVector3 getValue(F32 time, F32 duration); - LLVector3 interp(F32 u, PositionKey& before, PositionKey& after); - - InterpolationType mInterpolationType; - S32 mNumKeys; - typedef std::map key_map_t; - key_map_t mKeys; - PositionKey mLoopInKey; - PositionKey mLoopOutKey; - }; + typedef Curve ScaleCurve; + typedef ScaleCurve::Key ScaleKey; + typedef Curve RotationCurve; + typedef RotationCurve::Key RotationKey; + typedef Curve PositionCurve; + typedef PositionCurve::Key PositionKey; //------------------------------------------------------------------------- // JointMotion