My friend Sir Bob asked me yesterday if I knew anything about drawing something like a three-dimensional box on a flat screen, like in Java, and have it so that if you were to drag the mouse, you could rotate the box.
Simply put: yes. I very briefly outlined the concept of rasterisation, how it works in a context like OpenGL, and how you could do it manually. This post is a bit of an elaboration on the "how you could do it manually" part, with basic geometry.
These are simple ways of rendering 3D objects in a 2-dimension space (like a computer screen.) Libraries like OpenGL don't do this, OpenGL uses transformation matrices; but those matrices are derived from simple geometry like this.
Converting from object-space to screen-space. For example, you may have a line from {0, 1, 1} to {1, 2, 0}, and you want to convert it to a line on the 2-dimensional screen.
Ignore the z part.
{ x, y, z } → { x, y }
For example: {0, 1, 1} becomes {0, 1}, and {1, 2, 0} becomes {1, 2}
Shrink things that are further from the view-point.
{ x, y, z } → { x / (z + 1), y / (z + 1) }
For example: {0, 1, 1} becomes {0, ½}, and {1, 2, 0} becomes {1, 2}
Moving the object in its 3-dimensional space, by rotating it about the point {0, 0}.
Rotate the vector { x, z }
1. current angle = |
⎧ 90° |
.. if x = 0, z > 0 |
⎨ 270° | .. if x = 0, z < 0 | |
⎩ atan(z / x) | .. otherwise | |
2. distance = | sqrt(x2 + z2) | |
3. new angle = | current angle + rotation | |
4. new point = | { x = distance × cos(new angle), z = distance × sin(new angle) } |
Note: the y value doesn't change. I'm sure you can work out why not.
Rotate the vector { y, z }
(as above, using y in place of x)
Rotate the vector { x, y }
1. Easy solution: let the 2D render surface take care of that (eg. Java Graphics2D's .rotate()
— note: in the documentation for rotate you can see a two dimensional transformation matrix.)
2. Real solution: as above, using y in place of z
To rotate an object about a Y axis that isn't at {x=0, z=0}, you do the same maths as above, but translate the x and z terms so they are relative to the axis.
For example, to rotate the line above by 90° about the axis {x=-1, z=1}:
Then to draw the line in a perspective view, the screen points are: {-0.33, 0.33} and {1.5, 1}
Disclaimer: I worked most of this post out in my head, so if it's wrong, tough.
Also, there are additional factors you can introduce, such as a field of view, clipping box, etc. that give you a bit more control over what you draw.
My general rule when doing anything graphical is this: don't be afraid to hold your hands out and imagine what is happening to the objects. Visualising everything is key to understanding it, much more so than the maths.
... Matty /<