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:

- p3dc_identity_xfrm
- p3dc_free_xfrm
- p3dc_mult_xfrm
- p3dc_dump_xfrm
- p3dc_locate_xfrm
- p3dc_move_xfrm
- p3dc_scaleXYZ_xfrm
- p3dc_scale_xfrm
- p3dc_xrot_xfrm
- p3dc_yrot_xfrm
- p3dc_zrot_xfrm
- p3dc_orientation_xfrm
- p3dc_camera_xfrm

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

Ato be the identity transform, or, ifAis 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

ABwhich it is important to note is different thanBA. (Matrix multiplication isn't commutative). If the pointerRis null, a new transform is allocated to hold the result, otherwise the result is stored inRand any previous contents ofRare lost. The function is written so that the pointerRcan be the same as eitherAorBand still behave correctly (that is you can implementA = ABwith 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_logfor more details on logging.) The pointerTpoints 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:

title- This string is printed before the transform is printed. the default is to print the string "P3DC matrix (XID =nnn):" wherennnis the identifier in the transform.head- This string is printed before each row of the matrix, if null it defaults to " " but you can set it to "| " to get vertical bars on your matrix.tail- This string is printed after each row of the matrix and should include a new line \n character.fmt- This string is used to format each element of the matrix, it defaults to "%#8.4f ".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.0000And 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

Ais 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

Ais not null, this function performs the matrix operation:A=AT_{xyz}where the transformT_{xyz}represents a translation transformation andAis the original transformation. The original transformAis 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-z}R_{q}T_{xyz}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

Vand a distancedt. Again ifAis null a new transform is allocated, ifAis not null then it is modifed by a translation in the direction ofVfor a distance ofdtunits. 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

Ais null a new transform is allocated, otherwise the transformation is applied toAandAis 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

Ais null a new transform is allocated, if that allocation fails then null is returned. Unlikep3dc_scaleXYZ_xfrmthe 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

angledegrees about the Z axis and then applys that rotation to the the transformA. IfAis 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

angledegrees about the Y axis and then applys that rotation to the the transformA. IfAis 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

angledegrees about the X axis and then applys that rotation to the the transformA. IfAis 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

Aa transform to re-use, ifAis null a new transform is allocated. Note that this function differs from the others in that it does not apply the computed transformation toAinstead itthe transformation inreplacesAwith the one it computes. The vectordiris a unit vector pointing along the direction where the positive Z axis in local space should be headed in the transformation space. The pointoriginis represents the location in transformation space to which the local space origin should be translated. The valuerollrepresents 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_xfrmfunction. When applied it transforms the world into the co-ordinate system of a camera sitting at the position inoriginin world co-ordinates, looking in the direction ofdirand tilted byrolldegrees.This function is used extensively by the camera code to provide the basic world to view transformation.