Template abuse to clean up llkeyframemotion. Only functional change: std::map<F32, curve> to std::vector<std::pair<F32, curve>>. Sorry in advance Linux.

This commit is contained in:
Shyotl
2019-08-06 02:21:56 -05:00
parent da86dd08c4
commit 4091bf9da5
2 changed files with 113 additions and 361 deletions

View File

@@ -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);
}
}
}

View File

@@ -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<typename T>
struct lerp_op {
static T lerp(F32 t, const T& before, const T& after)
{
return ::lerp(before, after, t);
}
};
template<>
struct lerp_op<LLQuaternion> {
static LLQuaternion lerp(F32 t, const LLQuaternion& before, const LLQuaternion& after)
{
return ::nlerp(t, before, after);
}
};
//-------------------------------------------------------------------------
// RotationKey
//-------------------------------------------------------------------------
class RotationKey
template<typename T>
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<T>::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<F32, ScaleKey> key_map_t;
InterpolationType mInterpolationType = LLKeyframeMotion::IT_LINEAR;
S32 mNumKeys = 0;
typedef std::vector< std::pair<F32, Key> > 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<F32, RotationKey> 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<F32, PositionKey> key_map_t;
key_map_t mKeys;
PositionKey mLoopInKey;
PositionKey mLoopOutKey;
};
typedef Curve<LLVector3> ScaleCurve;
typedef ScaleCurve::Key ScaleKey;
typedef Curve<LLQuaternion> RotationCurve;
typedef RotationCurve::Key RotationKey;
typedef Curve<LLVector3> PositionCurve;
typedef PositionCurve::Key PositionKey;
//-------------------------------------------------------------------------
// JointMotion