Last modified 26 August 2003 by jdavis@math.wisc.edu
Inherits from NSObject
Conforms to NSCoding, NSCopying
SMKTransformation is a semi-abstract class that describes a rigid-body transformation of three-dimensional space. Any such transformation can be decomposed into a rotation followed by a translation, and SMKTransformation assumes that its transformation is of this form. In other words, the total transformation takes any vector v to the vector TRv, where T is a translation and R a rotation. Similarly, if we have two transformations F0 = T0R0 and F1 = T1R1, then their composition F0F1 takes v to F0F1v = T0R0T1R1v. Notice also that the inverse of TR is R-1T-1, not T-1R-1.
Translation is quite simple, and it is implemented concretely here.
- (id)setTranslation:(double *)vector;Sets the translation to match the vector.
- (id)getTranslation:(double *)vector;
Returns the translation in the indicated vector.
- (id)setTranslation:(unsigned int)index toValue:(double)value;
Sets indicated component (0, 1, or 2) to the passed value.
- (double)translation:(unsigned int)index;
Returns the indicated component (0, 1, or 2) of the translation.
Sometimes we just want to know how big the translation is.
- (double)lengthOfTranslation;Returns the length of the translation vector.
There are several convenient methods for applying the translation or its inverse to a scene or a vector.
- (id)translateScene;Applies the translation to the current OpenGL matrix.
- (id)inverselyTranslateScene;
Applies the inverse translation to the current OpenGL matrix.
- (id)translateVector:(double *)vector withResult:(double *)result;
Translates the indicated vector, by adding the translation to it. The output may alias the input.
- (id)inverselyTranslateVector:(double *)vector withResult:(double *)result;
Inversely translates the indicated vector, by subtracting the translation from it. The output may alias the input.
There are many ways to describe rotations, and which description is best depends on which problem you need to solve. SMKTransformation declares a variety of rotation methods, but leaves the implementations (of the primitive ones) to a subclass, so that you are free to describe rotation using quaternions, matrices, or any system of angles you like. Subclasses of SMKTransformation are not obligated to be able to model all rotations; a subclass might describe rotations in certain directions or with certain constraints. SMKTransformation's implementations always respond as if the rotation were the identity.
The first four methods let us apply the rotation in various ways. Override all of them without calling SMKTransformation's versions.
- (id)rotateScene;Applies the rotation to the current OpenGL matrix, and returns the receiver.
Applies the inverse rotation to the current OpenGL matrix, and returns the receiver.
- (id)rotateVector:(double *)vector withResult:(double *)result;
Rotates the indicated vector, and returns the receiver. The output may alias the input.
- (id)inverselyRotateVector:(double *)vector withResult:(double *)result;
Inversely rotates the indicated vector, and returns the receiver. The output may alias the input.
A rotation of three-dimensional space is uniquely determined by its effect on an orthonormal pair of vectors. The next method to be overridden specifies the rotation in this way.
- (BOOL)makeVector:(double *)vector1 andVector:(double *)vector2 rotateToTarget:(double *)target1 andTarget:(double *)target2;Configures the receiver so that it rotates vector1 to target1 and vector2 to target2 , returning YES if and only if successful. All vectors are assumed to have length 1. It is also assumed that vector1 and vector2 are perpendicular and that target1 and target2 are perpendicular. Override without calling this version.
As a reward for implementing this method, we get methods to compose transformations. You do not need to override these four.
- (BOOL)composeRotation:(SMKTransformation *)t0 andRotation:(SMKTransformation *)t1;
- (BOOL)composeRotations:(NSArray *)array;Sets the receiver's rotation to the composition of the given rotations. The receiver's translation is unaffected. In the process, makeVector:andVector:rotateToTarget:andTarget: is invoked on the receiver; this method returns YES if and only if that method does. The receiver may be one of the inputs.
- (BOOL)composeTransformation:(SMKTransformation *)t0 andTransformation:(SMKTransformation *)t1;
- (BOOL)composeTransformations:(NSArray *)array;Sets the receiver to the composition of the given transformations. In the process, makeVector:andVector:rotateToTarget:andTarget: is invoked on the receiver; this method returns YES if and only if that method does. The receiver may be one of the inputs.
A similar method configures the rotation based on a single vector and target. The receiver might be able to perform the rotation in many different ways; it may choose whichever one it prefers. On the other hand, it is not even obligated to succeed; for example, it might have constraints that don't allow it to.
- (BOOL)makeVector:(double *)vector rotateToTarget:(double *)target;Configures the receiver so that it rotates the indicated vector toward the target vector, returning YES if and only if successful. Both vectors are assumed to have length 1. Override without calling this version.
These last two methods are used by SMKSceneTree's inverse kinematics algorithms.
- (id)makeVector:(double *)vector rotateToTarget:(double *)target withResult:(double *)result;Like makeVector:rotateToTarget:, configures the receiver so that it rotates the vector toward the target. The inputs are assumed to have nonzero length, but not necessarily length 1. The actual location to which the vector is rotated is returned in result. The output may alias the input. This method is already implemented in terms of makeVector:rotateToTarget:; you do not need to override it.
- (id)setPlanarAngle:(double)angle;
Informs the receiver that there should be a bend of angle between the two scene elements that it connects. The angle is given in radians, and it is always between 0 and SMKPi. The receiver might find it appropriate to record SMKPi - angle, -(SMKPi - angle), or -angle instead of angle itself. Override without calling this version.