2023-06-11 13:08:08 +08:00
|
|
|
#include "3d/AnimationCurve.h"
|
2022-07-11 17:50:21 +08:00
|
|
|
NS_AX_BEGIN
|
2019-11-23 20:27:39 +08:00
|
|
|
|
|
|
|
template <int componentSize>
|
|
|
|
void AnimationCurve<componentSize>::evaluate(float time, float* dst, EvaluateType type) const
|
|
|
|
{
|
|
|
|
if (_count == 1 || time <= _keytime[0])
|
|
|
|
{
|
|
|
|
memcpy(dst, _value, _componentSizeByte);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (time >= _keytime[_count - 1])
|
|
|
|
{
|
|
|
|
memcpy(dst, &_value[(_count - 1) * componentSize], _componentSizeByte);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int index = determineIndex(time);
|
|
|
|
|
|
|
|
float scale = (_keytime[index + 1] - _keytime[index]);
|
|
|
|
float t = (time - _keytime[index]) / scale;
|
|
|
|
|
|
|
|
float* fromValue = &_value[index * componentSize];
|
|
|
|
float* toValue = fromValue + componentSize;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case EvaluateType::INT_LINEAR:
|
|
|
|
{
|
|
|
|
for (auto i = 0; i < componentSize; i++) {
|
|
|
|
dst[i] = fromValue[i] + (toValue[i] - fromValue[i]) * t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EvaluateType::INT_NEAR:
|
|
|
|
{
|
|
|
|
float* src = std::abs(t) > 0.5f ? toValue : fromValue;
|
|
|
|
memcpy(dst, src, _componentSizeByte);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EvaluateType::INT_QUAT_SLERP:
|
|
|
|
{
|
|
|
|
// Evaluate.
|
|
|
|
Quaternion quat;
|
|
|
|
if (t >= 0)
|
|
|
|
Quaternion::slerp(Quaternion(fromValue), Quaternion(toValue), t, &quat);
|
|
|
|
else
|
|
|
|
Quaternion::slerp(Quaternion(toValue), Quaternion(fromValue), t, &quat);
|
|
|
|
|
|
|
|
dst[0] = quat.x;
|
|
|
|
dst[1] = quat.y;
|
|
|
|
dst[2] = quat.z;
|
|
|
|
dst[3] = quat.w;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EvaluateType::INT_USER_FUNCTION:
|
|
|
|
{
|
|
|
|
if (_evaluateFun)
|
|
|
|
_evaluateFun(time, dst);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <int componentSize>
|
|
|
|
void AnimationCurve<componentSize>::setEvaluateFun(std::function<void(float time, float* dst)> fun)
|
|
|
|
{
|
|
|
|
_evaluateFun = fun;
|
|
|
|
}
|
|
|
|
|
|
|
|
//create animation curve
|
|
|
|
template <int componentSize>
|
|
|
|
AnimationCurve<componentSize>* AnimationCurve<componentSize>::create(float* keytime, float* value, int count)
|
|
|
|
{
|
|
|
|
int floatSize = sizeof(float);
|
2021-12-08 00:11:53 +08:00
|
|
|
AnimationCurve* curve = new AnimationCurve();
|
2019-11-23 20:27:39 +08:00
|
|
|
curve->_keytime = new float[count];
|
|
|
|
memcpy(curve->_keytime, keytime, count * floatSize);
|
|
|
|
|
|
|
|
int compoentSizeByte = componentSize * floatSize;
|
|
|
|
int totalByte = count * compoentSizeByte;
|
|
|
|
curve->_value = new float[totalByte / floatSize];
|
|
|
|
memcpy(curve->_value, value, totalByte);
|
|
|
|
|
|
|
|
curve->_count = count;
|
|
|
|
curve->_componentSizeByte = compoentSizeByte;
|
|
|
|
|
|
|
|
curve->autorelease();
|
|
|
|
return curve;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <int componentSize>
|
|
|
|
float AnimationCurve<componentSize>::getStartTime() const
|
|
|
|
{
|
|
|
|
return _keytime[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
template <int componentSize>
|
|
|
|
float AnimationCurve<componentSize>::getEndTime() const
|
|
|
|
{
|
|
|
|
return _keytime[_count - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <int componentSize>
|
|
|
|
AnimationCurve<componentSize>::AnimationCurve()
|
|
|
|
: _value(nullptr)
|
|
|
|
, _keytime(nullptr)
|
|
|
|
, _count(0)
|
|
|
|
, _componentSizeByte(0)
|
|
|
|
, _evaluateFun(nullptr)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
template <int componentSize>
|
|
|
|
AnimationCurve<componentSize>::~AnimationCurve()
|
|
|
|
{
|
2022-07-16 10:43:05 +08:00
|
|
|
AX_SAFE_DELETE_ARRAY(_keytime);
|
|
|
|
AX_SAFE_DELETE_ARRAY(_value);
|
2019-11-23 20:27:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <int componentSize>
|
|
|
|
int AnimationCurve<componentSize>::determineIndex(float time) const
|
|
|
|
{
|
|
|
|
unsigned int min = 0;
|
|
|
|
unsigned int max = _count - 1;
|
|
|
|
unsigned int mid = 0;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
mid = (min + max) >> 1;
|
|
|
|
|
|
|
|
if (time >= _keytime[mid] && time <= _keytime[mid + 1])
|
|
|
|
return mid;
|
|
|
|
else if (time < _keytime[mid])
|
|
|
|
max = mid - 1;
|
|
|
|
else
|
|
|
|
min = mid + 1;
|
|
|
|
} while (min <= max);
|
|
|
|
|
|
|
|
// We should never hit this!
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-07-11 17:50:21 +08:00
|
|
|
NS_AX_END
|