Project: 3D Craft -- Transform data structure.

The p3dc_XFRM data structure represents a 3-D transformation in the P3DC environment. The contents are a 4 x 4 matrix (data) and an identifier member called id. Normally, the identifier represents a unique number so that the transform's identity can be ascertained, however there are two special IDs. An identifier value of 0 indicates that the transform has no data in it at all, thus it requires initialization before use. Any use of a transform with a zero identifier can be trapped by the code and rejected using asserts. The second special identifier is the value one (1). This identifier indicates that the matrix has been initialized to be the identity matrix. The identity matrix is zero except for the matrix diagonal which is initialized to the value one (1).

Functions that are described in this document:


The following functions operate on transforms in the library, they are written in C prototype form for clarity.

p3dc_XFRM *p3dc_identity_xfrm( p3dc_XFRM *A )

This function either initializes the transform referenced by the pointer A to be the identity transform, or, if A is null, it allocates a new transform, initializes that and returns a pointer to it. In all cases the returned pointer points to the initialized transform and the transform's identity is set to 1. (If a pointer was passed it is simply returned.) If this function returns null then it could not allocate a new transform.

void p3dc_free_xfrm( p3dc_XFRM **A )

This function discards a transform structure that is no longer needed. The memory used is not actually given back to the operating system, rather the transform is placed on a list of available structures and will be re-allocated when a transform is needed again. See the description in "Project: 3D Craft -- Memory Management" for more details on how this is done.

p3dc_XFRM *p3dc_mult_xfrm( p3dc_XFRM *R, p3dc_XFRM *A, p3dc_XFRM *B )

This function multiplies two transforms and returns the result. In matrix notation it returns AB which it is important to note is different than BA. (Matrix multiplication isn't commutative). If the pointer R is null, a new transform is allocated to hold the result, otherwise the result is stored in R and any previous contents of R are lost. The function is written so that the pointer R can be the same as either A or B and still behave correctly (that is you can implement A = AB with one call.) This function will return null if the result pointer was null and the library was unable to allocate a new transform structure. The identifier in the result transform will be unique.

void p3dc_dump_xfrm( p3dc_XFRM *T, char *title, char *head, char *fmt, char *tail )

This function is a diagnostic function for dumping a transform's contents into the log file. (see p3dc_log for more details on logging.) The pointer T points to the transform to dump. Next there are four optional strings, if they are all NULL then the library defaults them to a generic set, otherwise they are used as follows:

An example of printing a matrix with using the defaults is:

P3DC matrix (XID = 1):
    1.0000    0.0000    0.0000    0.0000  
    0.0000    1.0000    0.0000    0.0000  
    0.0000    0.0000    1.0000    0.0000  
    0.0000    0.0000    0.0000    1.0000  

And with tile="*TITLE*TITLE*\n", head = "*HEAD* ", tail = "*TAIL*\n", and fmt = "%g", you get this print out in the log:

*TITLE*TITLE*
*HEAD*  1000  *TAIL*
*HEAD*  0100  *TAIL*
*HEAD*  0010  *TAIL*
*HEAD*  0001  *TAIL*

p3dc_XFRM *p3dc_locate_xfrm( p3dc_XFRM *A, p3dc_FLOAT x, y, z )

This function has two modes of operation. The simplest occurs when the passed in value for A is null. In that case, the function allocates a new identity transform and sets its last column to be the translation specified. The constructed transform is then returned. It will return null if a transform could not be allocated.

When A is not null, this function performs the matrix operation: A = ATxyz where the transform Txyz represents a translation transformation and A is the original transformation. The original transform A is changed by this operation.

This function is used when constructing more complicated compound transformations. For example, when computing a transform to rotate a model about its local origin, the required mathematical construction is, A - T-x-y-zRqTxyz which consists of a translation from the local origin at (x, y, z) to zero, followed by the application of a rotation transformation, followed by the application of another translation transformation to return the origin to (x, y, z).

p3dc_XFRM *p3dc_move_xfrm( p3dc_XFRM *A, p3dc_PNT3 *V, p3dc_FLOAT dt )

This function is similar to the locate function except that it takes as its parameters a vector V and a distance dt. Again if A is null a new transform is allocated, if A is not null then it is modifed by a translation in the direction of V for a distance of dt units. This is useful when you want to move an object along a path during animation.

p3dc_XFRM *p3dc_scaleXYZ_xfrm( p3dc_XFRM *A, p3dc_FLOAT x, y, z )

This function will apply a scaling factor (possibly non-uniform) to the three axes. The effect is the points transformed by the resulting transform will have their x, y, and z components re-sized by possibly different amounts. As with all of the transformation functions if A is null a new transform is allocated, otherwise the transformation is applied to A and A is returned updated.

WARNING: a transform has been scaled non-uniformly it is no longer affine. Objects transformed by this transform may have angles between their components changed and the relative lengths of the components will definitely be changed. Those types of changes will invalidate any precomputed plane normals.

p3dc_XFRM *p3dc_scale_xfrm( p3dc_XFRM *A, p3dc_FLOAT s )

This function applys a uniform scaling transformation to the passed transform. As with other functions if the pointer A is null a new transform is allocated, if that allocation fails then null is returned. Unlike p3dc_scaleXYZ_xfrm the resulting transform remains affine and so plane normals and and angles are not changed when transformed by the resulting transform.

p3dc_XFRM *p3dc_zrot_xfrm( p3dc_XFRM *A, p3dc_FLOAT angle )

This function computes a rotation transformation of angle degrees about the Z axis and then applys that rotation to the the transform A. If A is null then a new transform is allocated that holds the Z rotation. If the allocation fails, null is returned. Postive angles represent clockwise rotation when looking along the Z axis into positive infinity. (Left hand co-ordinate system)

Transform rotations are specified using degrees rather than radians. I chose degrees because, for me, they are a more "natural" unit. The #define macros D2R and R2D are provided in p3dc.h to convert from degrees to radians and from radians to degrees respectively.

p3dc_XFRM *p3dc_yrot_xfrm( p3dc_XFRM *A, p3dc_FLOAT degree )

This function computes a rotation transformation of angle degrees about the Y axis and then applys that rotation to the the transform A. If A is null then a new transform is allocated that holds the Y rotation. If the allocation fails, null is returned. Postive angles represent clockwise rotation when looking up the Y axis into positive infinity. (Left hand co-ordinate system)

Transform rotations are specified using degrees rather than radians. I chose degrees because, for me, they are a more "natural" unit. The #define macros D2R and R2D are provided in p3dc.h to convert from degrees to radians and from radians to degrees respectively.

p3dc_XFRM *p3dc_xrot_xfrm( p3dc_XFRM *A, p3dc_FLOAT degree )

This function computes a rotation transformation of angle degrees about the X axis and then applys that rotation to the the transform A. If A is null then a new transform is allocated that holds the X rotation. If the allocation fails, null is returned. Postive angles represent clockwise rotation when looking along the X axis into positive infinity. (Left hand co-ordinate system)

Transform rotations are specified using degrees rather than radians. I chose degrees because, for me, they are a more "natural" unit. The #define macros D2R and R2D are provided in p3dc.h to convert from degrees to radians and from radians to degrees respectively.

p3dc_XFRM *p3dc_orientation_xfrm( p3dc_XFRM *A, p3dc_PNT3 *dir, *origin, p3dc_FLOAT roll )

This is a pretty neat function, it creates a transform that will transform from a local co-ordinate system into another co-ordinate system at a given location and orientation. The inputs to this function are A a transform to re-use, if A is null a new transform is allocated. Note that this function differs from the others in that it does not apply the computed transformation to A instead it replaces the transformation in A with the one it computes. The vector dir is a unit vector pointing along the direction where the positive Z axis in local space should be headed in the transformation space. The point origin is represents the location in transformation space to which the local space origin should be translated. The value roll represents a rotation about the local space's Z axis that should be applied in order to position the local notion of up. In summary, this function computes a transformation given a vector and an angle to translate from one co-ordinate space into another.

This function is used to position models into world co-ordinates.

p3dc_XFRM *p3dc_camera_xfrm( p3dc_XFRM *V, p3dc_PNT3 *dir, *origin, p3dc_FLOAT roll )

This function is the inverse of the p3dc_orientation_xfrm function. When applied it transforms the world into the co-ordinate system of a camera sitting at the position in origin in world co-ordinates, looking in the direction of dir and tilted by roll degrees.

This function is used extensively by the camera code to provide the basic world to view transformation.