📄 animsand.cpp
字号:
{ if (t >= m_pdPacedTime[i] && t <= m_pdPacedTime[i + 1]) { break; } } if (i + 1 < m_pElement->m_ulNumValues) { // 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()");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -