Transition Macros
As part of my animation work I have a set of macros which simplify moving objects from one location to another, or in some other way allow me to transition an object from one state to another.
Linear Changes
There are going to be times when you want to fade a scene to black or from black, or fade between two scenes. You will want things to be at a starting state up until the motion or change begins, and for it to be at a certain place when the motion ends, and for it to stay there, and for the movement in between those times to occur at a steady rate. When that is the case, a macro like the following will come in handy:
#macro Transition(tNow, tStart, pStart, tEnd, pEnd) #if (tNow <= tStart) (pStart) #elseif(tNow >= tEnd) (pEnd) #else (pStart + (pEnd - pStart) * (tNow - tStart) / (tEnd - tStart)) #end #end
Call this macro with the parameters set to the following values:
pStart
and pEnd
can be any value type that can be added, subtracted, etc. I've used this for scalar values, vector values, and color values.Non-linear motion
While the macro above works well for camera fades and other transitions that aren't physical in nature, it has an issue that makes it less useful for moving physical objects, and to explain why this is the case I will introduce a concept called continuity
Degrees of continuity
Continuity is when a particular value or quality does not make any sudden instant changes, but instead changes gradually over time. It is a very important concept in computer graphics, both in modeling as well as in animation. A model will have C0 continuity when the edges of its pieces meet, C1 continuity when they meet in a smooth edge, C2 continuity when the curvature on both sides of the edge is the same, and so on. In the same way, the location of an object over time has its own set of continuities, and the first seven of these have special names for them:
As you go down this list, lapses in continuity start out garishly obvious, but become less noticeable the further down the list you go.
Macro for C1 Motion
If you only need a smooth start and stop, and sudden changes in acceleration aren't a problem, then you only need C1 continuity. I've found that non-linear transitions often do not follow a straight line from the start to the end, but also have a lateral component to the motion, so this macro has an extra parameter which I'll explain after the code:
#macro Transition1(tNow, tStart, pStart, tEnd, pEnd, vSwerve) #if (tNow <= tStart) (pStart) #elseif(tNow >= tEnd) (pEnd) #else #local tHack = (tNow - tStart) / (tEnd - tStart); #local uIndex = ((3 - 2 * tHack) * tHack * tHack); #local vIndex = tHack * tHack * (1 - tHack) * (1 - tHack) * 16; (pStart + (pEnd - pStart) * uIndex + vSwerve * vIndex) #end #end
The parameters have the same meaning as in the
Transition
macro above. The parameter vSwerve
supports the extra lateral motion, and should be set to the maximum extent that the lateral component will have. The lateral displacement will be applied gradually until its maximum value at the halfway point between tStart
and tEnd
, and then go down and taper off gradually at the end of the motion. If you don't want the lateral motion, set the parameter to <0, 0, 0>
.Macro for C2 Motion
If you need a smoother motion, so that acceleration is zero at the start and end of the animation, then you need C2 continuity. This macro has the same parameters as
Transition1
, but uses a more sophisticated calculation to ensure C2 continuity:#macro Transition2(tNow, tStart, pStart, tEnd, pEnd, vSwerve) #if (tNow <= tStart) (pStart) #elseif(tNow >= tEnd) (pEnd) #else #local tHack = (tNow - tStart) / (tEnd - tStart); #local uIndex = (((6 * tHack - 15) * tHack + 10) * tHack * tHack * tHack); #local vIndex = tHack * tHack * tHack * (1 - tHack) * (1 - tHack) * (1 - tHack) * 64; (pStart + (pEnd - pStart) * uIndex + vSwerve * vIndex) #end #end
Macro for C3 Motion
If you need even smoother motion, so that jerk is zero at the start and end of the animation, then you need C3 continuity, and this macro will provide it:
#macro Transition3(tNow, tStart, pStart, tEnd, pEnd, vSwerve) #if (tNow <= tStart) (pStart) #elseif(tNow >= tEnd) (pEnd) #else #local tHack = (tNow - tStart) / (tEnd - tStart); #local uIndex = ((((70 - 20 * tHack) * tHack - 84) * tHack + 35) * tHack * tHack * tHack * tHack); #local vIndex = tHack * tHack * tHack * tHack * (1 - tHack) * (1 - tHack) * (1 - tHack) * (1 - tHack) * 256; (pStart + (pEnd - pStart) * uIndex + vSwerve * vIndex) #end #end
The parameters have the same meaning as in the
Transition1
macro above.As for which of the macros to use for motion, the best way to decide is to test all three of them, and decide which one looks more natural to you.
For the Math-Heads
The equations for the non-linear macros were derived using some basic calculus. For all three macros, I took the polynomial
x - x2
and raised it to the power of the desired continuity level, giving x - x2
for Transition1
, x2 - 2x3 + x4
for Transition2
, and x3 - 3x4 + 3x5 - x6
for Transition3
.I then took the antiderivative of each polynomial and multiplied each one by the inverse of its value when evaluated at
x=1
. In each case, this resulted in a polynomial with a value of zero at x=0
and a value of one at x=1
, and is used to calculate the amount of motion along the vector from the start of motion to the end point.The formula for the coefficient of lateral motion was derived by taking the polynomial
x - x2
, raising it to the second, third, or fourth power respectively, and then scaling it by the inverse of the value of each polynomial when evaluated at a value of one-half. This results in a polynomial whose value is zero at x=0
and x=1
and a value of one at x=½
.Preview of Coming Attractions
The next item of most interest to some readers will be a way to create a motion path, again with arbitrary degrees of continuity. I'll have the math all done and some useful code to use. Watch this space.
Comments
Post a Comment