axmol/cocos/3d/CCAnimationCurve.inl

144 lines
3.7 KiB
Plaintext
Raw Normal View History

2014-06-17 10:49:52 +08:00
#include "3d/CCAnimationCurve.h"
2014-06-04 18:17:09 +08:00
NS_CC_BEGIN
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])
{
2014-06-16 18:22:32 +08:00
memcpy(dst, &_value[(_count - 1) * componentSize], _componentSizeByte);
2014-06-04 18:17:09 +08:00
return;
}
unsigned int index = determineIndex(time);
float scale = (_keytime[index + 1] - _keytime[index]);
float t = (time - _keytime[index]) / scale;
2014-06-10 19:53:06 +08:00
float* fromValue = &_value[index * componentSize];
2014-06-04 18:17:09 +08:00
float* toValue = fromValue + componentSize;
switch (type) {
2014-06-18 14:01:57 +08:00
case EvaluateType::INT_LINEAR:
2014-06-04 18:17:09 +08:00
{
for (auto i = 0; i < componentSize; i++) {
dst[i] = fromValue[i] + (toValue[i] - fromValue[i]) * t;
}
}
break;
2014-06-18 14:01:57 +08:00
case EvaluateType::INT_NEAR:
2014-06-04 18:17:09 +08:00
{
2015-04-07 16:37:51 +08:00
float* src = fabs(t) > 0.5f ? toValue : fromValue;
2014-06-04 18:17:09 +08:00
memcpy(dst, src, _componentSizeByte);
}
break;
2014-06-18 14:01:57 +08:00
case EvaluateType::INT_QUAT_SLERP:
2014-06-04 18:17:09 +08:00
{
// 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;
2014-06-18 14:01:57 +08:00
case EvaluateType::INT_USER_FUNCTION:
2014-06-04 18:17:09 +08:00
{
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);
AnimationCurve* curve = new (std::nothrow) AnimationCurve();
2014-06-04 18:17:09 +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)
2014-06-04 18:17:09 +08:00
, _count(0)
, _componentSizeByte(0)
, _evaluateFun(nullptr)
{
}
template <int componentSize>
AnimationCurve<componentSize>::~AnimationCurve()
{
CC_SAFE_DELETE(_keytime);
CC_SAFE_DELETE(_value);
}
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;
}
NS_CC_END