3D Transformations aren’t difficult to use, but there is not a whole lot of information about using them. Hopefully this tutorial will help.
Table of contents
- What are transformations?
- Theory: Basic knowledge
- Theory: Order of transformations
- set and add
What are transformations?
The verb to transform means to change, to shape. Transforming a model means you are manipulating the model in some way: rotating, moving and scaling are some (actually all) of the possibilities.
Theory: Basic knowledge
There are a couple of things you should know before starting with transformations. The most important thing is that a transformation always ‘transforms’ around point zero: (0, 0, 0). This can cause some problems. If you draw your model on (10, 10, 10), and rotate it 180 degrees around the z-axis, it will end up on (-10, -10, -10). But we’ll learn how to avoid this later on. Another thing is that transformations don’t reset after the model is drawn. If you don’t erase them, they will also be used for the next model.
Theory: Order of transformations
The order of transformations is important. Let’s say we first rotate a model 90 degrees around the z-axis, and then move it 100 pixels over the x-axis (the latter is called a ‘translation’, by the way). The model will end up on (100, 0, 0), rotated 90 degrees, as you would expect.
However, if we swap the two transformations, meaning we first move it 100 pixels over the x-axis, and then rotate it 90 degrees around the z-axis, we will end up with a model that is rotated 90 degrees, but positioned on (0, 100, 0). Think about it: all transformations are origined in point (0, 0, 0).
Because of this, you will first have to draw your model on (0, 0, 0), then transform it however you like (rotate or scale it, for example), and then move it to the desired (x, y, z) location using a transformation.
A transformation could look like this:
- Rotate around the z-axis;
- Translate to (x, y, z)
- Draw the model on (0, 0, 0)
The model is first drawn on (0, 0, 0). Notice how the actual transformations are located above it. This is okay, because they are saved and used when the model is drawn: first the model is rotated, and then it is moved to (x, y, z).
Don’t forget: first you do your transformations, then you do a translation to (x, y, z), then you draw the model on (0, 0, 0).
This is the ‘reset’ function. When used, all current transformations are erased. In other words: always start your transformation block with this, and it with this as well (after you’ve drawn the model, of course). Starting with this line is not necessary, because you should have erased all previous transformations when you drew the previous model, but it certainly makes for cleaner and safer code.
set and add
There is an alternative to the previous chapter, but you will have to understand the differences between functions containing _set_, and functions containing _add_.
Every transformation has both a set and add version. Think of it as
d3d_transform_set_translation. They both have the same effect, except for the fact that when you execute a _set_ function, all the previous transformations are erased, too.
When you use an _add_ function, the transformation is just added to the previous ones. Calling a _set_ function is the equivalent of using
d3d_transform_set_identity(), followed by the respective _add_ function. Placing multiple _set_ functions after each other is thus useless.
So, as an alternative to
d3d_transform_identity(), you can also use the _set_ version of the first transformation instead of the _add_ version. Personally, I don’t find this a good method, simply because you are combining two functions in to one, making your code less readable and organized. But it works, so use as you wish.
Time for some practical stuff. There are four rotations, that all have a set and add version. The first three are:
These are fairly obvious: with each of the three pairs you can rotate a model around respectively the x-, y- and z-axis. Angle is in degrees, naturally counter-clockwise (in the positive axis direction).
Then there’s this function:
d3d_transform_set_rotation_axis(xa, ya, za, angle)
d3d_transform_add_rotation_axis(xa, ya, za, angle)
This one probably needs some explanation. For this function there is no defined axis to rotate around: you will have to define this one yourself. The axis is the vector (xa, ya, za). Angle is, again, in degrees.
d3d_transform_set_rotation_x(angle) == d3d_transform_set_rotation_axis(1, 0, 0, angle)
d3d_transform_set_rotation_y(angle) == d3d_transform_set_rotation_axis(0, 1, 0, angle)
d3d_transform_set_rotation_z(angle) == d3d_transform_set_rotation_axis(0, 0, 1, angle)
Obviously it’s a better idea to use the functions on the left side, but this should clear up any questions you had about the function.
Only one function here, with both a set and add version:
d3d_transform_set_translation(xt, yt, zt) and
d3d_transform_add_translation(xt, yt, zt)
A translation is just a ‘movement’. d3d_transform_set_translation(50, 50, 50) will move the model 50 pixels over each axis.
You can use this function to move your model to its (x, y, z) position.
For scaling there is only one pair of functions as well:
d3d_transform_set_scaling(xs, ys, zs) and
d3d_transform_add_scaling(xs, ys, zs)
This one probably doesn’t need a whole lot of explanation: you can use this one to resize your model. xs, ys and zs are factors: 1 is the normal size, 2 is twice as big, 1/2 is twice as small.
Note: If you use lighting, you shouldn’t use this function. The transformation doesn’t just scale the model, it also scales the normals, meaning that they won’t have a length of 1 anymore. This means that scaled objects will be either unnaturally dark, or unnaturally bright. The only thing you can do about this, is making models of different sizes. But if you don’t use lighting, don’t worry.
So that’s all of the functions. But how can you use them? I’ll give a simple example. By now, you probably understand what each function does. Use this script as an example to build your own transformation. This scripts draws the model on position (x, y, z) , rotated at angle degrees.
d3d_transform_set_identity() //reset alle transformaties d3d_transform_add_rotation_z(direction) //we rotate around the z-axis d3d_transform_add_translation(x,y,z) //we move it to its position d3d_model_draw(model,0,0,0,-1) //lastly, we draw it (on (0,0,0)!!) d3d_transform_set_identity() //reset al transformations
That’s it! Feel free to leave a comment below if you have a question.