266 lines
9.0 KiB
C++
266 lines
9.0 KiB
C++
/**
|
|
@file JCKeyframeNodeList.cpp
|
|
@brief
|
|
@author James
|
|
@version 1.0
|
|
@date 2018_7_12
|
|
*/
|
|
|
|
#include "JCKeyframeNodeList.h"
|
|
#include "../Log.h"
|
|
|
|
namespace laya
|
|
{
|
|
//------------------------------------------------------------------------------
|
|
JCKeyframeNodeList::JCKeyframeNodeList()
|
|
{
|
|
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
JCKeyframeNodeList::~JCKeyframeNodeList()
|
|
{
|
|
m_vNodes.clear();
|
|
}
|
|
|
|
void JCKeyframeNodeList::evaluateClipDatasRealTime(JCKeyframeNodeList* nodes, float playCurTime, short* realTimeCurrentFrameIndexs, int indexSize, bool addtive, bool frontPlay)
|
|
{
|
|
int nNodeCount = nodes->getCount();
|
|
if (nNodeCount != indexSize)
|
|
{
|
|
LOGE("evaluateClipDatasRealTime error");
|
|
return;
|
|
}
|
|
for (int i = 0; i < nNodeCount; i++) {
|
|
JCKeyframeNode* node = nodes->m_vNodes[i];
|
|
int type = node->m_nType;
|
|
short nextFrameIndex = 0;
|
|
std::vector<JCKeyFrame*> keyFrames = node->m_vKeyFrames;
|
|
int keyFramesCount = keyFrames.size();
|
|
short frameIndex = realTimeCurrentFrameIndexs[i];
|
|
|
|
if (true)
|
|
{
|
|
if (frameIndex != -1 && playCurTime < keyFrames[frameIndex]->m_nTime)
|
|
{
|
|
frameIndex = -1;
|
|
realTimeCurrentFrameIndexs[i] = frameIndex;
|
|
}
|
|
|
|
nextFrameIndex = frameIndex + 1;
|
|
while (nextFrameIndex < keyFramesCount) {
|
|
if (keyFrames[nextFrameIndex]->m_nTime > playCurTime)
|
|
break;
|
|
frameIndex++;
|
|
nextFrameIndex++;
|
|
realTimeCurrentFrameIndexs[i] = frameIndex;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nextFrameIndex = frameIndex + 1;
|
|
if ((nextFrameIndex != keyFramesCount) &&
|
|
(playCurTime > keyFrames[nextFrameIndex]->m_nTime))
|
|
{
|
|
frameIndex = keyFramesCount - 1;
|
|
realTimeCurrentFrameIndexs[i] = frameIndex;
|
|
}
|
|
|
|
nextFrameIndex = frameIndex + 1;
|
|
while (frameIndex > -1)
|
|
{
|
|
if (keyFrames[frameIndex]->m_nTime < playCurTime)
|
|
break;
|
|
frameIndex--;
|
|
nextFrameIndex--;
|
|
realTimeCurrentFrameIndexs[i] = frameIndex;
|
|
}
|
|
}
|
|
|
|
bool isEnd = (nextFrameIndex == keyFramesCount);
|
|
|
|
switch (type) {
|
|
case 0:
|
|
{
|
|
node->m_nDataType = 0;
|
|
JCFloatKeyframe* pKeyframe = (JCFloatKeyframe*)keyFrames[0];
|
|
if (frameIndex != -1)
|
|
{
|
|
JCFloatKeyframe* frame = (JCFloatKeyframe*)keyFrames[frameIndex];
|
|
if (isEnd) {//如果nextFrame为空,不修改数据,保持上一帧
|
|
node->m_pDataFloat = frame->m_nValue;
|
|
}
|
|
else {
|
|
JCFloatKeyframe* nextFarme = (JCFloatKeyframe*)keyFrames[nextFrameIndex];
|
|
float d = nextFarme->m_nTime - frame->m_nTime;
|
|
float t;
|
|
if (d != 0)
|
|
t = (playCurTime - frame->m_nTime) / d;
|
|
else
|
|
t = 0;
|
|
node->m_pDataFloat = _hermiteInterpolate(frame, nextFarme, t, d);
|
|
}
|
|
}
|
|
else {
|
|
node->m_pDataFloat = pKeyframe->m_nValue;
|
|
}
|
|
if (addtive) {
|
|
node->m_pDataFloat -= pKeyframe->m_nValue;
|
|
}
|
|
break;
|
|
}
|
|
case 1:
|
|
case 4:
|
|
{
|
|
node->m_nDataType = 1;
|
|
JCFloatArrayKeyframe::FloatArrayBuffer* clipData = &node->m_pDataFloatArray;
|
|
_evaluateFrameNodeArrayDatasRealTime(keyFrames, frameIndex, isEnd, playCurTime, 3, *clipData);
|
|
if (addtive) {
|
|
JCFloatArrayKeyframe* pKeyframe = (JCFloatArrayKeyframe*)keyFrames[0];
|
|
JCFloatArrayKeyframe::FloatArrayBuffer* firstFrameValue = &pKeyframe->m_pData;
|
|
float* clipVData = (float*)clipData->data;
|
|
float* firstValue = (float*)firstFrameValue->data;
|
|
clipVData[0] -= firstValue[6];
|
|
clipVData[1] -= firstValue[7];
|
|
clipVData[2] -= firstValue[8];
|
|
}
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
node->m_nDataType = 1;
|
|
JCFloatArrayKeyframe::FloatArrayBuffer* clipData = &node->m_pDataFloatArray;
|
|
_evaluateFrameNodeArrayDatasRealTime(keyFrames, frameIndex, isEnd, playCurTime, 4, *clipData);
|
|
if (addtive) {
|
|
float temp[4];
|
|
JCFloatArrayKeyframe* pKeyframe = (JCFloatArrayKeyframe*)keyFrames[0];
|
|
JCFloatArrayKeyframe::FloatArrayBuffer* firstFrameValue = &pKeyframe->m_pData;
|
|
quaternionConjugate((float*)firstFrameValue->data,8,temp);
|
|
quaternionMultiply(temp, (float*)clipData->data, (float*)clipData->data);
|
|
}
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
node->m_nDataType = 1;
|
|
JCFloatArrayKeyframe::FloatArrayBuffer* clipData = &node->m_pDataFloatArray;
|
|
_evaluateFrameNodeArrayDatasRealTime(keyFrames, frameIndex, isEnd, playCurTime, 3, *clipData);
|
|
if (addtive) {
|
|
JCFloatArrayKeyframe* pKeyframe = (JCFloatArrayKeyframe*)keyFrames[0];
|
|
JCFloatArrayKeyframe::FloatArrayBuffer* firstFrameValue = &pKeyframe->m_pData;
|
|
float* clipVData = (float*)clipData->data;
|
|
float* firstValue = (float*)firstFrameValue->data;
|
|
clipVData[0] /= firstValue[6];
|
|
clipVData[1] /= firstValue[7];
|
|
clipVData[2] /= firstValue[8];
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
throw "AnimationClip:unknown node type.";
|
|
}
|
|
}
|
|
}
|
|
|
|
float JCKeyframeNodeList::_hermiteInterpolate(JCFloatKeyframe* frame, JCFloatKeyframe* nextFrame, float t, float dur) {
|
|
float t0 = frame->m_nOutTangent, t1 = nextFrame->m_nInTangent;
|
|
float t2 = t * t;
|
|
float t3 = t2 * t;
|
|
float a = (float)(2.0 * t3 - 3.0 * t2 + 1.0);
|
|
float b = (float)(t3 - 2.0 * t2 + t);
|
|
float c = (float)(t3 - t2);
|
|
float d = (float)(-2.0 * t3 + 3.0 * t2);
|
|
return a * frame->m_nValue + b * t0 * dur + c * t1 * dur + d * nextFrame->m_nValue;
|
|
}
|
|
|
|
void JCKeyframeNodeList::_evaluateFrameNodeArrayDatasRealTime(std::vector<JCKeyFrame*>& keyFrames, int frameIndex, bool isEnd, float playCurTime, int width, JCFloatArrayKeyframe::FloatArrayBuffer& outDatas)
|
|
{
|
|
int dataOffset = width * 2;
|
|
float* outVData = (float*)outDatas.data;
|
|
if (frameIndex != -1)
|
|
{
|
|
JCFloatArrayKeyframe* frame = (JCFloatArrayKeyframe*)keyFrames[frameIndex];
|
|
if (isEnd)
|
|
{
|
|
float* frameData = (float*)frame->m_pData.data;
|
|
for (int j = 0; j < width; j++)
|
|
outVData[j] = frameData[dataOffset+j];//不能设为null,会造成跳过当前帧数据
|
|
}
|
|
else
|
|
{
|
|
JCFloatArrayKeyframe* nextKeyFrame = (JCFloatArrayKeyframe*)keyFrames[frameIndex + 1];
|
|
float t;
|
|
float startTime = frame->m_nTime;
|
|
float d = nextKeyFrame->m_nTime - startTime;
|
|
if (d != 0)
|
|
t = (playCurTime - startTime) / d;
|
|
else
|
|
t = 0;
|
|
|
|
_hermiteInterpolateArray(frame, nextKeyFrame, t, d, outDatas);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
JCFloatArrayKeyframe::FloatArrayBuffer* firstFrameDatas = &((JCFloatArrayKeyframe*)keyFrames[0])->m_pData;
|
|
float* frameData = (float*)firstFrameDatas->data;
|
|
for (int j = 0; j < width; j++)
|
|
outVData[j] = frameData[dataOffset+j];
|
|
}
|
|
}
|
|
|
|
void JCKeyframeNodeList::_hermiteInterpolateArray(JCFloatArrayKeyframe* frame, JCFloatArrayKeyframe* nextFrame, float t, float dur, JCFloatArrayKeyframe::FloatArrayBuffer& out) {
|
|
bool isComputeParams = false;
|
|
float a, b, c, d;
|
|
float* out_data = (float*)out.data;
|
|
float* p0_data = (float*)frame->m_pData.data;
|
|
float* p1_data = (float*)nextFrame->m_pData.data;
|
|
int nOutTanOffset = out.byteSize / sizeof(float);
|
|
int nOffset = nOutTanOffset * 2;
|
|
for (int i = 0; i < nOutTanOffset; i++) {
|
|
float t0 = p0_data[nOutTanOffset +i], t1 = p1_data[i];
|
|
if (!isComputeParams) {
|
|
float t2 = t * t;
|
|
float t3 = t2 * t;
|
|
a = (float)(2.0 * t3 - 3.0 * t2 + 1.0);
|
|
b = (float)(t3 - 2.0 * t2 + t);
|
|
c = (float)(t3 - t2);
|
|
d = (float)(-2.0 * t3 + 3.0 * t2);
|
|
isComputeParams = true;
|
|
}
|
|
out_data[i] = a * p0_data[nOffset+i] + b * t0 * dur + c * t1 * dur + d * p1_data[nOffset+i];
|
|
}
|
|
}
|
|
|
|
void JCKeyframeNodeList::quaternionConjugate(float* value,int nOffset, float* result) {
|
|
result[0] = -value[nOffset];
|
|
result[1] = -value[nOffset+1];
|
|
result[2] = -value[nOffset+2];
|
|
result[3] = value[nOffset+3];
|
|
}
|
|
|
|
void JCKeyframeNodeList::quaternionMultiply(float* le, float* re, float* oe) {
|
|
/*[DISABLE-ADD-VARIABLE-DEFAULT-VALUE]*/
|
|
float lx = le[0];
|
|
float ly = le[1];
|
|
float lz = le[2];
|
|
float lw = le[3];
|
|
float rx = re[0];
|
|
float ry = re[1];
|
|
float rz = re[2];
|
|
float rw = re[3];
|
|
|
|
float a = ly * rz - lz * ry;
|
|
float b = lz * rx - lx * rz;
|
|
float c = lx * ry - ly * rx;
|
|
float d = lx * rx + ly * ry + lz * rz;
|
|
oe[0] = lx * rw + rx * lw + a;
|
|
oe[1] = ly * rw + ry * lw + b;
|
|
oe[2] = lz * rw + rz * lw + c;
|
|
oe[3] = lw * rw - d;
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
//-----------------------------END FILE--------------------------------
|