📄 animsand.cpp
字号:
// Do the interpolation
cRet.Interp(m_pElement->m_ppValue[i], m_pdPacedTime[i],
m_pElement->m_ppValue[i + 1], m_pdPacedTime[i + 1],
(double) ulTime, pDepend);
}
}
}
// Now we can clear the first time flag
m_bFirstTime = FALSE;
}
}
}
return cRet;
}
CAttr CAnimationSandwichLayer::CumulativeAnimationFunction(UINT32 ulTime,
CAttr* pUnder,
CAttr* pDepend)
{
CAttr cRet;
if (pUnder)
{
// Initialize to the underlying value
cRet = *pUnder;
// Are we cumulative or not?
if (m_pElement->m_ucAccumulate == kAccumulateSum)
{
// We are a cumulative animation
//
// Modulo the time by the simple duration
UINT32 ulModTime = 0;
if (m_pElement->m_ulSimpleDuration)
{
ulModTime = ulTime % m_pElement->m_ulSimpleDuration;
}
// Evaluate the simple animation function at this time
CAttr cMod = SimpleAnimationFunction(ulModTime, pUnder, pDepend);
// Find the iteration
UINT32 ulIter = 0;
if (m_pElement->m_ulSimpleDuration)
{
ulIter = ulTime / m_pElement->m_ulSimpleDuration;
}
if (ulIter)
{
// Evaluate the animation at the simple duration
cRet = SimpleAnimationFunction(m_pElement->m_ulSimpleDuration,
pUnder, pDepend);
// Multiply by iteration value
cRet.Mult((double) ulIter);
// Add the simple animation result
cRet.Add(&cMod, pDepend);
}
else
{
// We're on the first iteration
cRet = cMod;
}
}
else
{
// We are a non-cumulative animation
//
// Modulo the time by the simple duration
UINT32 ulModTime = 0;
if (m_pElement->m_ulSimpleDuration)
{
ulModTime = ulTime % m_pElement->m_ulSimpleDuration;
}
// Evaluate the simple animation function at this time
cRet = SimpleAnimationFunction(ulModTime, pUnder, pDepend);
}
}
return cRet;
}
void CAnimationSandwichLayer::RecomputePace(CAttr* pDepend)
{
if (!m_pdPacedDist)
{
m_pdPacedDist = new double [m_pElement->m_ulNumValues];
if (m_pdPacedDist)
{
memset((void*) m_pdPacedDist, 0, sizeof(double) *
m_pElement->m_ulNumValues);
}
}
if (!m_pdPacedTime)
{
m_pdPacedTime = new double [m_pElement->m_ulNumValues];
if (m_pdPacedTime)
{
memset((void*) m_pdPacedTime, 0, sizeof(double) *
m_pElement->m_ulNumValues);
}
}
if (m_pdPacedDist && m_pdPacedTime)
{
UINT32 i = 0;
// Compute D()
m_pdPacedDist[0] = 0.0;
for (i = 1; i < m_pElement->m_ulNumValues; i++)
{
m_pdPacedDist[i] = m_pdPacedDist[i - 1] +
CAttr::Dist(m_pElement->m_ppValue[i - 1],
m_pElement->m_ppValue[i],
pDepend);
}
// Compute T()
double dTotal = m_pdPacedDist[m_pElement->m_ulNumValues - 1];
for (i = 0; i < m_pElement->m_ulNumValues; i++)
{
m_pdPacedTime[i] = m_pdPacedDist[i] * m_pElement->m_ulSimpleDuration / dTotal;
}
}
}
UINT32 CAnimationSandwichLayer::ComputeFilteredSimpleTime(UINT32 ulUnfilteredActiveTime)
{
UINT32 ulRet = ulUnfilteredActiveTime;
if (m_pElement &&
(m_pElement->m_bAutoReverse ||
m_pElement->m_dSpeed != 1.0 ||
m_pElement->m_dAccelerate != 0.0 ||
m_pElement->m_dDecelerate != 0.0))
{
// Compute the duration of the acceleration phase
double dacc = ((double) m_pElement->m_ulSimpleDuration) *
m_pElement->m_dAccelerate;
// Compute the duration of the deceleration phase
double ddec = ((double) m_pElement->m_ulSimpleDuration) *
m_pElement->m_dDecelerate;
// Compute the active filtered time (which takes
// into account the speed attribute)
double dActiveFilteredTime = 0.0;
if (m_pElement->m_dSpeed > 0.0)
{
dActiveFilteredTime = ((double) ulUnfilteredActiveTime) *
m_pElement->m_dSpeed;
}
else
{
dActiveFilteredTime = ((double) m_pElement->m_ulADNoSpeed) -
(((double) ulUnfilteredActiveTime) *
fabs(m_pElement->m_dSpeed));
}
// Compute the unfiltered simple time
double dUnfilteredSimpleTime = dActiveFilteredTime;
double dDur = (double) m_pElement->m_ulSimpleDuration;
double dDurPrime = dDur;
if (m_pElement->m_bAutoReverse)
{
dDurPrime *= 2.0;
}
// Is there any repeating behavior?
if (m_pElement->m_dRepeatCount == 1.0 &&
(m_pElement->m_ulRepeatDur == ((UINT32) -1) ||
m_pElement->m_bRepeatDurIsIndefinite))
{
// No repeating behavior here, so unfiltered simple
// time is equal to active filtered time
dUnfilteredSimpleTime = dActiveFilteredTime;
}
else
{
// This animation repeats, so calcuate the
// remainder
if (dDurPrime != 0.0)
{
dUnfilteredSimpleTime =
dActiveFilteredTime -
dDurPrime * floor(dActiveFilteredTime / dDurPrime);
}
}
// Account for autoReverse behavior
double dUnfilteredSimpleTimePrime = dUnfilteredSimpleTime;
if (m_pElement->m_bAutoReverse &&
dUnfilteredSimpleTime >= dDur)
{
dUnfilteredSimpleTimePrime = (2.0 * dDur) - dUnfilteredSimpleTime;
}
// Compute the decel begin time
double dDecelBegin = dDur - ddec;
// Compute the filtered simple time
double dFilteredSimpleTime = (double) dUnfilteredSimpleTimePrime;
double dRDenom = 1.0 -
(m_pElement->m_dAccelerate / 2.0) -
(m_pElement->m_dDecelerate / 2.0);
double dR = 1.0;
if (dRDenom != 0.0)
{
dR = 1.0 / dRDenom;
}
if (dUnfilteredSimpleTimePrime >= 0.0 &&
dUnfilteredSimpleTimePrime < dacc)
{
dFilteredSimpleTime = dUnfilteredSimpleTimePrime *
ComputeRunRate(dUnfilteredSimpleTimePrime,
m_pElement->m_dAccelerate,
m_pElement->m_dDecelerate,
dDur) / 2.0;
}
else if (dUnfilteredSimpleTimePrime >= dacc &&
dUnfilteredSimpleTimePrime <= dDecelBegin)
{
dFilteredSimpleTime = dR * (dUnfilteredSimpleTimePrime - (dacc / 2.0));
}
else if (dUnfilteredSimpleTimePrime > dDecelBegin &&
dUnfilteredSimpleTimePrime <= dDur)
{
double tdec = dUnfilteredSimpleTime - dDecelBegin;
double pd = 1.0;
if (ddec != 0.0)
{
pd = tdec / ddec;
}
dFilteredSimpleTime = dR * (dDur - (dacc / 2.0) - ddec +
(tdec * (2.0 - pd) / 2.0));
// Make sure we don't ever round up to dDur if
// our input is less than dDur
if (dUnfilteredSimpleTimePrime < dDur &&
dFilteredSimpleTime >= dDur - 0.5)
{
dFilteredSimpleTime = dDur - 0.50000000001;
}
}
// Now round to nearest integer
ulRet = (UINT32) floor(dFilteredSimpleTime + 0.5);
}
return ulRet;
}
double CAnimationSandwichLayer::ComputeRunRate(double dT, double dAccel,
double dDecel, double dDur)
{
double dRet = 1.0;
double dacc = dDur * dAccel;
double ddec = dDur * dDecel;
double dRDenom = 1.0 - (dAccel / 2.0) - (dDecel / 2.0);
if (dRDenom != 0.0)
{
double dR = 1.0 / dRDenom;
// Compute the decel begin time
double dDecBegin = dDur - ddec;
// Now compute the run rate
if (dT >= 0.0 && dT < dacc)
{
if (dacc != 0.0)
{
dRet = dR * dT / dacc;
}
}
else if (dT >= dacc && dT <= dDecBegin)
{
dRet = dR;
}
else if (dT > dDecBegin && dT <= dDur)
{
if (ddec != 0.0)
{
dRet = dR * (dDur - dT) / ddec;
}
}
}
return dRet;
}
#if defined(XXXMEH_SPLINE_ANIMATION)
double CAnimationSandwichLayer::ComputeSpline(double t, double t1, double t2,
double v1, double v2, double x1,
double y1, double x2, double y2)
{
double dRet = 0.0;
if (x1 >= 0.0 && x1 <= 1.0 &&
y1 >= 0.0 && y1 <= 1.0 &&
x2 >= 0.0 && x2 <= 1.0 &&
y2 >= 0.0 && y2 <= 1.0)
{
if (t2 >= t1)
{
if (t >= t1)
{
if (t <= t2)
{
if (t2 > t1)
{
// We compute the spline interpolation
// in the following steps:
// a) Scale the time down to unit time
// b) Get the output bezier time (still in unit time)
// c) Use this output time as the
// input time for linear interpolation.
//
// Scale the time to unit time
double dInUnitT = (t - t1) / (t2 - t1);
// Get the output bezier time
double dOutUnitT = ComputeBezierOutputTime(dUnitT, x1, y1, x2, y2);
// Do a sanity check on the output time
if (dOutUnitT < 0.0)
{
dOutUnitT = 0.0;
HX_ASSERT(FALSE && "Bad value returned from ComputeBezierOutputTime()");
}
else if (dOutUnitT > 1.0)
{
dOutUnitT = 1.0;
HX_ASSERT(FALSE && "Bad value returned from ComputeBezierOutputTime()");
}
// Use this time to linearly interpolate
dRet = v1 + (v2 - v1) * dOutUnitT;
}
else
{
// t1 is equal to t2. So this is a discontinuous
// interval, so by endpoint-exclusive logic [a,b),
// we choose v2 for the output value. This is not
// an input error, so we don't assert.
dRet = v2;
}
}
else
{
dRet = v2;
HX_ASSERT(FALSE && "ComputeSpline(): t is greater than t2 - v2 assigned");
}
}
else
{
dRet = v1;
HX_ASSERT(FALSE && "ComputeSpline(): t is less than t1 - v1 assigned");
}
}
else
{
HX_ASSERT(FALSE && "ComputeSpline(): t2 cannot be less than t1");
}
}
else
{
HX_ASSERT(FALSE && "Illegal bezier control parameters in ComputeSpline()");
}
return dRet;
}
double CAnimationSandwichLayer::ComputeBezierOutputTime(double t,
double x1, double y1,
double x2, double y2)
{
double dRet = 0.0;
if (t >= 0.0 && t <= 1.0 &&
x1 >= 0.0 && x1 <= 1.0 &&
y1 >= 0.0 && y1 <= 1.0 &&
x2 >= 0.0 && x2 <= 1.0 &&
y2 >= 0.0 && y2 <= 1.0)
{
// We get the output bezier-curve-warped time
// by doing the following:
//
// a) Find q where x(q) = t
// b) Compute y(q)
//
// Find the q where x(q) = t
double dQ = SolveForBezierT(t, x1, x2, BEZIER_TOLERANCE);
// Do a sanity check on this value
if (dQ < 0.0)
{
dQ = 0.0;
HX_ASSERT(FALSE && "Bad value returned from SolveForBezierT()");
}
else if (dQ > 1.0)
{
dQ = 1.0;
HX_ASSERT(FALSE && "Bad value returned from SolveForBezierT()");
}
// Compute y(q)
dRet = ComputeBezier(dQ, y1, y2);
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -