ashen-aetna

Ashen Aetna

— Rustily stumbling around on an ash-covered volcano

(A tutorial on/in/about/with 3D graphics, Rust, Vulkan, ash)

Angles, orthogonality, rotations

Last chapter we have used some rotations to manipulate positions; this will not have been the last time for us to dig into coordinate changes and vector maths, so let us have a look at a few more 3D math basics. For some cases we will continue to use the functions provided by nalgebra; but that should not keep us from looking at the background.

If you are already familiar with the length of vectors, angles, sine and cosine, scalar product (dot product), orthogonality, projection (as in: projection of one vector onto another), orthogonalization (including Gram-Schmidt process and cross product) and rotation matrices, you can safely skip this chapter; we won’t change the code of our program.

Although we have extended the vectors to use for 3D graphics to vectors with four components, let us stick with those with three (or, occasionally, two) components. (For their relation with those four-component vectors see Chapter 15 and Chapter 16.)

Most of these concepts are needed for operations before we have to think about “how to get it on the screen”.

The length of a vector

Everyone has an idea what a length is, we only have to find a way to measure it.

For vectors like or , that is easy: The length is just the value of the non-zero component:

, .

eeeehm, okay, the absolute value (i.e. flipping signs whenever it would be negative) of the non-zero component: .

When a vector has two non-zero components, like , the situation looks like this:

and identifying a right triangle, we use Pythagoras’ theorem: the square of the length of the green line is the sum of the squared lengths of the blue lines: or .

How about an actually three-dimensional setting? Say, ?

That looks like this:

and there is, again, a right triangle. One of its sides is just the length we have computed previously. and

.

In the same way, we can decompose every vector in right triangles and, as general formula for the length of obtain

For any , we see that . The recipe for normalizing a vector (and thereby obtaining a “unit vector”) thus is simple: Instead of use . It still points in the same direction, but has length . This (not only this formula, but normalizing in general) does not work for .

Angles between vectors

Next, we consider the angle between two vectors. For any pair of vectors there is a plane containing both, so we can restrict all illustrations to 2D.

Angles — the “what lies between” of two vectors. How to measure the “how much”?

First observation: The following angles are the same:

We only have to think about angles between unit vectors.

Also, rotation (of both vectors by the same amount) does not change the angle, we can try to measure the angle between and the second vector: This is still the same angle as before:

Now, how large is it? As measure for an angle, we use the length of the curve from (the tip of) one to the other, along the circle. (Remember: we are talking about vectors with length one, so both tips lie on the circle with radius one, if we have the vectors start at the origin.)

The full circle therefore corresponds to an angle of 2π. (And if we define ° (“degree”) to be the number π/180, then you can call this full circle angle 360° if you prefer.)

What about an angle of 9/2 * π? Well:

No discernible difference to π/2.

What about negative angles? Well, okay, let’s say that is just “in the other direction”:

(this, for example, would be an angle of -π/4 from the x-axis to the other vector)

Introducing a sign, a direction means that we are not so much talking about an angle between, but rather about an angle fromto

How do we know which of the following two angles is +π/4 and which is -π/4?

That is a matter of convention. We decide: The angle from to is positive.

So, this angle is +π/4:

and this angle is +π/4

Aren’t they the same? No. Very important, but very subtle difference: Pay attention to the direction of the axes! (And, please, never draw an axis with an arrow head on each end. The arrow does not mean “there is more in this direction”, it means “the numbers increase in this direction”.)

For some of my drawings, the directions do not correspond to those of Vulkan’s coordinate system. I don’t care: That’s a matter of “from which direction are we looking at it”. But it becomes the more important to look at the directions indicated at the axes.

This angle is, indeed, -π/4 (as mentioned before, but now you can appreciate the direction of the axes…):

This is a nice definition, which works well for angles in the x-y-plane – but doesn’t really help outside of it, and we are hoping for 3D in the end. How do we distinguish positive and negative angles there?

Two ways of dealing with it (both will occur):

  1. We don’t. In some cases we really care about an angle between and not an angle from to, in that case the sign doesn’t matter, so we don’t bother defining it.
  2. We specify around which axis we are turning (think of the angle as rotating the first vector on top of the second) and define to which direction of turning positive rotations correspond. For our rotations “in the x-y-plane”, we will consider them “rotations around ”. In which direction? What does rotating around a vector mean? Take your right hand. Extend the thumb. This is the vector around which to rotate. In which direction? The remaining (non-extended) fingers with a little bit of imagination form an arc indicating a screw direction. (If your thumb points towards your nose, you will perceive this as counterclockwise.) That is the positive direction. Check that rotating around by +π/2 actually results in .

Finally, a symbol, in case I don’t want to write “angle between and ” in formulae: .

Sine and Cosine

The above was: Given two vectors, what is the angle. Now we look at the opposite: Given an angle (say, φ), can we find two vectors with that angle between them? Let’s, again, fix the first as .

Since we know the angle, that is: the arc length shown in the picture, the vector is easy to find graphically:

What are its coordinates? Let’s cheat. They are - apparently - uniquely defined by the above procedure (draw part of the unit circle, starting at (1,0), arc length equal to φ, and take the coordinates of the endpoint). We can just give names to these results “the x-coordinate of this point” (txcotp), “the y-coordinate of this point” (tycotp) and refer to txcotp(φ) and tycotp(φ) in all computations where we need them. If they are useful enough, many people will use them, and we will finally get functions in Rust and GLSL that immediately give us these values if we hand them the value of φ.

Well, the names that have traditionally been used are different, but the idea is not too far off: txcotp is called cos and tycotp is sin. The point at the tip of a unit vector starting from the origin that has an angle φ to the x-axis, therefore is

(And whether we write cos φ or cos(φ) is merely a question of taste and readability.)

By the way: As we have defined sine and cosine by means of a point on the unit circle, essentially by definition we have that . (Again a note on writing: This is often shortened to , although could be mistaken for — but the latter is so uncommon that that is no real concern.)

If we already know the cosine, but want to know the corresponding angle: The answer to that question is called arccos, so that — at least for angles φ between 0 and π. If we admit larger angles, there are different possibilities that result in the same cosine.

Similarly, arcsin is the answer to the question “which angle has the given value as its sine?”

And while we’re at introducing trigonometric functions: The tangent is the quotient of sine and cosine: .

Rotations in 2D

Now that we have names for the coordinates of a point on the x-axis after rotating it by a certain angle around , let’s try to describe the rotation of an arbitrary point (in the plane) by a given angle φ.

Rotations are linear (think about it; if necessary, have another look at the introduction of linearity in Chapter 14), thus can be represented by matrices.

Say, we want to rotate by an angle φ, and call this rotation . Then

How to find the values of “?”? The first column was the outcome of applying the rotation to . Well, that’s not too difficult, we have just given names to those components:

The second column is what happens to . And is rotated to .

If that was too fast or you prefer pictures:

The final matrix hence ends up being

What happens if we rotate first by an angle and then by an angle ? Well, in total, we rotate by . Can we see that for matrices? Yes: .

Oh, we have never before covered how to multiply two matrices. Then let’s have a look now. What is

We know how to multiply matrices with vectors. Let’s see:

so:

In position (1,2) (that is, first row, second column) of the result, we get the product of the first row of the first matrix and second column of the second. (And product of first row and second column is something we can interpret in terms of “matrix times vector”: .)

Okay, with that out of the way, back to our rotations:

We learn (by comparing components of the first and the last matrix in that short computation):

and

(These are very useful identities.)

Computing the angle between two vectors

If we are given one vector v and want to compute the angle between and this vector, that is not too difficult: We normalize v (all of the above was for unit vectors), and then take its first component: That is the cosine of the angle.

But what if the other vector is not , if we have two (unit) vectors and ?

Well, they are unit vectors, so let us write them as , . And an angle should not change when we rotate both vectors, so the angle between and is the same as the angle we want to find, for every rotation R. Let’s pick the rotation by , which turns to . Because then we are back in the previous setting.

So: . (If the changes of signs in the last step confuse you, try to follow them along the definition of sine and cosine and negative angles in the defining “picture”.)

What are and ? Let’s compute:

Okay, that’s what we wanted, because now we only need the angle between and the (rotated) second vector.

And the cosine of the angle is the first component:

(We can also obtain this term by computing , what a surprise.)

So, from two vectors , we ended up with . More general:

That’s — easy to compute. And useful in connection with angles. We should give it a name: Scalar product. Inner product. Dot product.

Formula to remember:

(I have included the lengths of the vectors in order to account for the fact that we were using unit vectors all the time.)

The nice thing: This formula still works in 3D. Here, (as you may have expected), and the “formula to remember” is the same.

Orthogonality

One of the most important sizes an angle can have is π/2; the right angle. The angle between two vectors is a right angle (read: “the vectors are orthogonal to each other”) if its cosine is 0, that is to say: If their scalar product is zero. Very good, because very simple to check.

Finding out whether does not even involve sine and cosine.

And also in 3D: and
are orthogonal iff .

Suppose we are given two vectors ( and ), and we want to decompose one of them (say, ) in two parts: One part with the same direction as the other given vector (let’s call this part ), and a second part orthogonal to that ( ).

If had a length of 1, then would have a length of cosφ. Also points in the same direction as .

Apparently,

And we can compute cosφ much more easily, as dot product (between normalized vectors e and v):

(If has length one, , much nicer and shorter.)

Finally, we can set .

Recipe: If you have two vectors (say, in 3D) and want to have two orthogonal vectors that lie in the same plane, take the first of your vectors (call it e), and take the orthogonal part of the second vector v. (Note that depends on the choice of , even though the notation does not announce this dependency.) Often, you’ll want to normalize them.

If we have two vectors and and want to find a third one orthogonal to both, we can first ensure that is orthogonal to (by replacing it by ); then we can choose a random vector (if it lies in the plane of and , we will have problems. But that’s improbable, and we could just start with a different vector), and compute with respect to . We then take and compute with respect to . The final is orthogonal to and .

But we can also use a shortcut and introduce a ready-made concept and formula yielding the vector that is orthogonal to two given vectors: The cross-product.

Actually, in this sentence the “the” in “the vector that is orthogonal” is overly optimistic: There are many such vectors; at least they all belong to one line. If we decide on length and direction (out of the two possible directions on this line) of the vector, we have determined it uniquely. Given two vectors and , we will then call this new orthogonal vector the “cross-product”

Perhaps we revisit it in the future, but for now let me just write the definition:

(From one line to the next, each index is increased by one, where we start again from 1 instead of using 4.)

This vector is, indeed, orthogonal to :

It is also orthogonal to (you do the computation).

Moreover, (in this order) form a right-handed coordinate system.

You can either check with the definition or use this last property to see that .

Rotation matrices (3D)

How can we recognize a rotation?

Tying back to the above ideas about angles: If we have some vectors and apply the same rotation to them, the angles between them do not change. Also their lengths remain the same.

If we want to put these two ideas into one condition, we can say that the scalar products are unchanged: For every rotation R and every vectors u and v, we have . (What does this have to do with lengths? Well, .)

We know that the columns of the matrix representing R are given by , and . And we know that , and have length one and are orthogonal to each other.

If we know three vectors , , that have length one and are orthogonal to each other, we can form a rotation matrix by setting

(Okay, to be more precise, that’s not completely true: We not only get rotations but could also obtain a reflection. But close enough.)

This is the rotation turning , and into , and , respectively.

How do we find a rotation (say, ) turning , and into , and ?

Let us give the components of some names:

This seems strange — until now it was mostly the columns, not the rows of a matrix that we used, because they had some meaning. Why do something else now? Because in the end it will turn out that this way of giving names is more useful than having columns a, b, c. (You’ll see.)

And, by the way, another random bit of notation (I should introduce it somewhere): If , then is called the transpose of and denoted by . So, if you wish: .

Back to our question: What are , , if we want to rotate onto etc.?

Well:

That is:

or, separately: , , . If you prefer scalar products, that is the same as , , . (Check it with the definitions.)

Treating and in the same manner, we also find , , and , and .

Let me repeat what we know about : It should be a vector of length one (because it’s a column in a rotation matrix), and , , , that is is orthogonal to and and (due to and both and being unit vectors) has an angle with whose cosine equals 1. But then … is .

Similarly, and .

Hence the matrix rotating , , onto , and is

Obviously, this rotation reverts the effects of (first rotating , , onto , , and then rotating those back to ,

and means everything is back to where it started).

is the so-called “inverse” of : .

So, to recap: For a rotation :

(For general matrices , the inverse is usually more difficult to compute, and for many matrices, it does not even exist.)

There’d be more to say about matrices and inverse; and even about rotations (for example, we have not talked about the matrix describing the rotation around a given axis). But I think that’s enough “math lecture” for now (and for that example of rotating around a given axis, we can use a specific nalgebra function to help us out).

Continue