Isometric projection is a function that maps 3D point to a 2D point . This article discusses two approaches to derive this function.
def get_isometric_projection(x:int, y:int, z:int):
SQRT_2, SQRT_3, SQRT_6 = 2**0.5, 3**0.5, 6**0.5
x_out = (x-y) / SQRT_2
y_out = (x+y-2*z) / SQRT_6
return x_out, y_out
Isometric projection is one of the ways to map a 3D point on a 2D plane. It is a linear transformation, which means it can be represented by a 2-by-3 matrix. A common way to explain the projection and derive the matrix is via using a composition of rotations - a 3D vector is rotated twice so that its diagonal lines up perpendicular to the 2D plane, then its z-coordinate is ignored, giving a 2D point.
However there is another way to arrive at the projection matrix. This way is arguably simpler and completely circumvents the rotation matrices. Let's take a look at both the approaches and build the isometric projection matrix from the ground up.
For the purpose of illustration, we will map a cube whose eight vertices are located at the points . Note that each side of this cube has length 2. To distinguish between different sides, the top edges of this cube are drawn in , the bottom edges in and the vertical edges in .
Probably the simplest way to map a 3D vector to a 2D plane is to simply ignore its z-coordinate: . This projection is shown in the visual below. We only see the top edges located at .
To make all edges visible, we rotate the 3D vectors such that the vector becomes perpendicular to the XY-plane. This can be done in two rotations:
You can combine the two rotations by multiplying the two rotation matrices. Using , and plugging in the values in the matrices we get:
The columns of this product are exactly where the three basis vectors land after both rotations:
Finally, ignoring the z-coordinate (dropping the third row) gives us the matrix for isometric 3D to 2D projection:
Try it out for different values of alpha and theta.
There is another approach to arrive at this matrix directly without thinking in terms of rotations. It uses the same line of reasoning that we used to derive the rotation matrix. Let's assume the 2-by-3 matrix we want is
where the column is the image of the x-basis vector, the column is the image of the y-basis vector, and the column is the image of the z-basis vector. All we need to do is to find out where on the XY-plane the three 3D basis vectors are mapped:
But in the visual above, we can see where these basis vectors are mapped:
Here is the ratio by which each vector is scaled. We do not know its value at this point but will calculate it shortly. But knowing these values almost gives us the entire matrix:
All we need to do is find the value of . We can find it out by comparing the edge length of the cube after the first rotation (which does not change the lengths) and the second rotation (which changes the length of each side). From the visual below, it is easy to see that :
The neutral lines show the view after the first rotation (edge lengths remain the same) and the rose lines show the view after the second rotation (edge lengths foreshortened). The vectors are foreshortened by a ratio , computed as the cosine of the tilted angle over the cosine of the flattened angle:
Setting this value in the above matrix gives us the isometric projection matrix as:
This is the same matrix, column for column, that we arrive at using the approach of two rotations above.