| |
|
|
||||
![]() |
||||||
| |
|
|||||
|
The FFD Operation For the purposes of this example, we’ll assume that an object is defined with only positive values for the (x, y, z) coordinates of its vertices. The bounding box of the object would then have its origin at (0, 0, 0) in object space and extend to (xmax, ymax, zmax). The resting state of the FFD block would match the bounding box of the object. All Bezier curves, surfaces, and volumes are themselves examples of coordinate spaces. For a Bezier volume, a position with the volume is specified in terms of three coordinates, termed u, v, and w, and all assumed to vary between zero and one. Once an FFD block is defined around the object, each vertex in the object must be converted from its current (x, y, z) coordinate in the object to a (u, v, w) before deformation begins. This parametric coordinate is known as the "lattice space" position of a vertex. Assuming the axes used for the FFD at rest are the X, Y, Z axes of the object’s local coordinate system, you can calculate this position by normalizing all coordinates in the object to line in the range 0-1:
After this, we deform the FFD block however we like. Update the values in the array of points P, and then plug the vertex’s lattice space coordinate into the Bezier volume equation. The returned vector will be the deformed position of the point. After resultant position for every point is calculated, the model is drawn as usual. You can animate deformations by changing the positions of the control points every frame. An example of this is interpolating between one set of control points and another. Extending the Control: Local Deformation One disadvantage of using a single FFD block to control animation of an object is that you are applying global deformations. A deformation will alter the values of every vertex in the object to a greater or lesser extent. This gives the visual impression that the whole object is one jelly-like mass. This is undesirable in many situations. For instance, we might be deforming a car as a result of a crash. If the car were to be hit at its front-right corner, we would want that corner of the car to crumple, but the rest of the car should remain unaffected. We can apply changes more accurately to a particular part of the object by increasing the degree, and hence the number of control points, of the FFD. However, the changes applied are still global, and will still affect every point in the object, although to an increasingly small degree. The computational cost of the deformation is also greatly increased – remember that with an FFD block of degree n the inner loop is iterated n3 times per vertex. The solution is to use more than one FFD block per object. In fact, there are no restrictions on the use of FFDs – they can even overlap within an object. We might define the car as being encased in four FFDs, one for each quarter of the car (as seen from above). Now during impact, if the first FFD block is modified, only the affected part of the car will change. When joining FFDs the same continuity constraints apply as when joining Bezier curves or patches – that is, at a minimum, points which meet should be in the same position in space, and preferably should have some level of derivative continuity. This ensures that the object doesn’t develop any jagged edges or discontinuities during the deformation. |
|
|