#include "3d/AnimationCurve.h" NS_AX_BEGIN template void AnimationCurve::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 void AnimationCurve::setEvaluateFun(std::function fun) { _evaluateFun = fun; } //create animation curve template AnimationCurve* AnimationCurve::create(float* keytime, float* value, int count) { int floatSize = sizeof(float); AnimationCurve* curve = new 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 float AnimationCurve::getStartTime() const { return _keytime[0]; } template float AnimationCurve::getEndTime() const { return _keytime[_count - 1]; } template AnimationCurve::AnimationCurve() : _value(nullptr) , _keytime(nullptr) , _count(0) , _componentSizeByte(0) , _evaluateFun(nullptr) { } template AnimationCurve::~AnimationCurve() { AX_SAFE_DELETE_ARRAY(_keytime); AX_SAFE_DELETE_ARRAY(_value); } template int AnimationCurve::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_AX_END