#include "3d/CCAnimationCurve.h" 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]) { 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); AnimationCurve* curve = new (std::nothrow) AnimationCurve(); 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() { CC_SAFE_DELETE_ARRAY(_keytime); CC_SAFE_DELETE_ARRAY(_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