Transformations

Game Maker 8

Transformations

Transformation allow you to change the place where things are drawn in the world. For example, the function to draw blocks can only draw axis-parallel blocks. By first setting a rotation transformation you can create rotated blocks. Also sprites are always drawn parallel to the xy-plane. By setting a transformation you can change this. There are two types of functions: functions that set the transformation and functions that add transformations.

d3d_transform_set_identity() Sets the transformation to the identity (no transformation).
d3d_transform_set_translation(xt,yt,zt) Sets the transformation to a translation over the indicated vector.
d3d_transform_set_scaling(xs,ys,zs) Sets the transformation to a scaling with the indicated amounts.
d3d_transform_set_rotation_x(angle) Sets the transformation to a rotation around the x-axis with the indicated amount.
d3d_transform_set_rotation_y(angle) Sets the transformation to a rotation around the y-axis with the indicated amount.
d3d_transform_set_rotation_z(angle) Sets the transformation to a rotation around the z-axis with the indicated amount.
d3d_transform_set_rotation_axis(xa,ya,za,angle) Sets the transformation to a rotation around the axis indicated by the vector with the indicated amount.
d3d_transform_add_translation(xt,yt,zt) Adds a translation over the indicated vector.
d3d_transform_add_scaling(xs,ys,zs) Adds a scaling with the indicated amounts.
d3d_transform_add_rotation_x(angle) Adds a rotation around the x-axis with the indicated amount.
d3d_transform_add_rotation_y(angle) Adds a rotation around the y-axis with the indicated amount.
d3d_transform_add_rotation_z(angle) Adds a rotation around the z-axis with the indicated amount.
d3d_transform_add_rotation_axis(xa,ya,za,angle) Adds a rotation around the axis indicated by the vector with the indicated amount.
Realize that rotation and scaling are with respect to the origin of the world, not with respect to the object that is to be drawn. If the object is not at the origin it will also move to a different place, which is not what we want. So to e.g. rotate an object over its own x-axis, we must first translate it to the origin, next rotate it, and finally translate it back to its position. This is what the functions to add transformations are for.

The following examples might explain this better. Assume we have a sprite spr that we want to draw at position (100,100,10). We can use the following code to do this

{
  d3d_transform_set_translation(100,100,10);
  draw_sprite(spr,0,0,0);
  d3d_transform_set_identity();
}

Note that because we use a translation we should now draw the sprite at position (0,0). (This assumes the current instance has a depth of 0! If you are not sure, first set the depth.) If we would use this in our first person shooter we would not see the sprite. The reason is that it is still parallel to the xy-plane. We want to rotate it over 90 degrees along the x-axis (or y-axis). So we need to add a rotation. Remember the order: we must first rotate the sprite and then translate it. So we can use the following code.

{
  d3d_transform_set_identity();
  d3d_transform_add_rotation_x(90);
  d3d_transform_add_translation(100,100,10);
  draw_sprite(spr,0,0,0);
  d3d_transform_set_identity();
}

Sometimes you temporarily want to save the current transformation, for example to add an additional transformation and then restore the old one (this often happens when drawing hierarchical models). To this end you can push the current transformation on a stack and later pop it from the stack to make it the current transformation again. The following functions exist for this:

d3d_transform_stack_clear() Clears the stack of transformations.
d3d_transform_stack_empty() Returns whether the transformation stack is empty.
d3d_transform_stack_push() Pushes the current transformation on the stack. Returns whether there was room on the stack to push it there (if you forget popping transformation you at some moment will run out of room on the stack).
d3d_transform_stack_pop() Pops the top transformation from the stack and makes it the current one. Returns whether there was a transformation on the stack.
d3d_transform_stack_top() Makes the top transformation the current one, but does not remove it from the stack. Returns whether there was a transformation on the stack.
d3d_transform_stack_discard() Removes the top transformation from the stack but does not make it the current one. Returns whether there was a transformation on the stack.

Using transformation is a powerful mechanism. But be careful and always set the transformation back to the identity once you are done.