Position Paths
A path is a data structure designed to make it easier to move an object along a complex trajectory. The path stores a series of keyframes - places that the object should visit along the path. Each keyframe has a time indicating when the object should arrive at that position. When a path is applied to an object, the object will move gradually from point to point along the path, linearly interpolating in between keyframes. Here is some sample code that constructs a path:
local path = Path.new() path:setPosition(0, vec(0,0,0)) path:setPosition(1, vec(1,1,0)) path:setPosition(2, vec(2,0,0))
An object that follows this path will start at position (0,0,0) at time zero, gradually move to position (1,1,0) by the time one second has elapsed, then it will move to position (2,0,0) by the time two seconds have elapsed. The easiest way to make an object follow this path is this way:
path:setTarget(object1) path:go()
The first command links the path to a particular object. The second inserts the path into the Path Manager. From that point forward, the path manager checks the path every frame, calculating where the object should be at that point in time, and updating the object's position.
Rotation and Scale Paths
You can also make rotation and scale paths. Here is a rotation path:
local path = Path.new()
path:setRotation(0, Rotation.newCompassDirection("N"))
path:setRotation(1, Rotation.newCompassDirection("E"))
path:setRotation(2, Rotation.newCompassDirection("N"))
path:setRotation(3, Rotation.newCompassDirection("W"))
path:setRotation(4, Rotation.newCompassDirection("N"))
If an object is made to follow this path, the object will start facing north, then rotate to face east, then north, then west, then north again. The position of the object will not be affected, only the orientation.
Multi-Track Paths
Paths actually contain separate position, rotation, and scale "tracks." You can insert position keyframes into a path without ever specifying rotation or scale, for instance. In that case, the path won't affect the object's rotation or scale. A path can contain just one track, two tracks, or all three tracks (position, rotation, and scale).
Keyframe Timing
Keyframes don't have to be spaced evenly: for instance, you could have a path with keyframes at times 0,1,37,and 111. If a path contains multiple tracks (ie, both position and rotation), the keyframes from the two tracks don't have to line up. For instance, a path could have position keyframes at times 0, 5, 10, and rotation keyframes at times 13,14,15,16,17.
The path automatically sorts keyframes by time, so the following two paths are exactly the same:
local path1 = Path.new() path1:setPosition(0, vec(0,0,0)) path1:setPosition(1, vec(1,1,1)) path1:setPosition(2, vec(2,2,2)) local path2 = Path.new() path2:setPosition(0, vec(0,0,0)) path2:setPosition(2, vec(2,2,2)) path2:setPosition(1, vec(1,1,1))
Querying a Path
You can ask a path where an object will be at a given point in time using the method Path:getPosition, Path:getRotation, or Path:getScale.
Paths can Conflict
An object can't be in two places at the same time. If you construct two different position-paths and ask an object to follow them both at the same time, the results will be undefined. Typically, the object will follow one and ignore the other.
However, the position, rotation, and scale fields of an object are separate. So are the position, rotation, and scale tracks of the path. If you construct and activate a position-path, and simultaneously construct and activate a rotation-path, then there is no conflict. The position path will continously update the object's position field, the rotation path will continuously update the object's rotation field. The effects will combine properly.
Sometimes, paths do not appear to be conflicting, when they actually are. For example, consider a path that moves an object in the X-direction, and another path that moves an object in the Y-direction. These seem to be independent axes. But paths don't have separate X, Y, and Z tracks: they have position tracks. If you construct a path that affects X, it also affects Y and Z.
What Paths Cannot Do
When you build a path, you build it all at once, setting up all the keyframes. From that point forward, the object follows the planned trajectory blindly, regardless of what's happening in the scene. This is a fundamental limitation of paths: they execute blindly. A path can be very complicated in the sense that it can wiggle and zig and zag all over the place. But what it cannot do is adjust itself dynamically in response to changing conditions.
For this reason, some types of movement simply can't be done with paths. A good alternative, in these situations, is to create a background job whose responsbility is to move the object a little bit every frame. This process will be explained in another section.
Splining and Smoothing
You can construct a path with nice smooth curves by first inserting some keyframes, and then calling the smooth method. This method will round out the corners of the path. It does so by inserting additional keyframes.
The smooth operator uses splines to calculate the positions of the new keyframes. It treats the keyframes that you inserted manually as control points for a spline calculation. All of the splining algorithms supported go through the control points. To put it differently, the keyframes you originally inserted are not altered - the path will indeed go through your manually-inserted keyframes.
Quick Path Operators
For every movement operator starting with the word set such as setPosition, setHPR, setUpright, setCompassDirection, and so forth, there is a corresponding function whose name starts with pathTo, including such functions as pathToPosition, pathToHPR, pathToUpright, or pathToCompassDirection. These functions do nothing to the object - instead, they return paths. The path has already been targeted at the object. If the path is put into the Path Manager using the Path:go method, the object will gradually move from its current location to the target location over a period of one second. For example:
local path = obj:pathToPosition(1,2,3) path:go()
The first command constructs a path which contains two keyframes: time T0 at obj's current location, and time T1 at cartesian coordinate (1,2,3). The path is already targeted at obj. Simply invoking the "go" method causes obj to start moving. It is usually convenient to invoke the "go" method on the same line as the "pathToPosition" method, like this:
obj:pathToPosition(1,2,3):go()
Sometimes, you want a path whose duration is other than one second. In that case, the method Path:duration can be used to rescale the path after it has been constructed, like this:
local path = obj:pathToPosition(1,2,3) path:duration(5) path:go()
Now path contains two keyframes, one at time T0 at obj's current position, and one at time T5 at cartesian coordinate (1,2,3). When you launch the path using the "go" method, the object will take 5 seconds to reach its destination.
The duration method returns the path itself. This makes it convenient to invoke all this in one line of code, like this:
obj:pathToPosition(1,2,3):duration(5):go()
Quick Path Rules
Quick Path methods have a set of standardized rules that they all follow:
- All movement operators begin with the word 'set'.
- Set-methods are instantaneous.
- PathTo-methods return a path, whose duration is 1 second.
- For every set-method, there is a corresponding pathTo-method.
Unfortunately, following these rules rigidly has led to some functions with somewhat strange names. For example, the function to snap an object into the upright position is "setUpright" - because all functions that snap an object must start with the word "set." As another example, the function "pathToScaleX" will adjust the X-scale over time. The name of the function doesn't sound quite right, but given the rule that any function that returns a path must must start with the word "pathTo," that's what the function name has to be.
The upshot is that when you see these function names, don't interpret them literally as English sentences. Instead, remember the function naming rules.
- Printer-friendly version
- Login or register to post comments
-



