4D-Vectors and 3*3 Matrices

As I’m currently redeveloping my 3D-Engine in C++ I’m curious how to implement the linear algebra most effective.
I saw in many implementations that the programmers implemented classes for 3D- and for 4D Vectors and 33 and 44 Matrices. Now I wonder what 33 matrices and 4D-Vectors are good for if their usage is always up to the coder, since there is no general usage for them. The coders say that a 4D-Vector would represent a point whenever the 4th Component (w) is 1. Now, what is that information good for? Shouldnt the coder know if the certain vector represents a translation or a point?
How for example is a crossproduct for 4D-Vectors defined? Or a Dot-Product? What do they mean if they’re defined?
Now one can argue that the multiplication of a 3D-Vector with a 4
4 Matrix is not defined, but you can handle a 3D-Vector appropriately to do it. If one had to use the crossproduct on a 3D-Vector, convert it to a 4D-Vector to multiply it with a matrix, then what is the sense of it?

A rather implementation related question: Is it faster to use 3 concrete variables as the components of a 3D-Vector or an array of three elements?

Thank you for every insight that can halp me!
Michael

Hi !

As you say, at first sight, one could ask : why don’t we simply use 3d vectors and 3x3 matrices ?
Answer : because by doing this we could never make translations. A translation T is not a linear operator, ie, you don’t have T(ax+by)=aT(x)+bT(y) (that’s obvious).
Now i’m going to explain you how we solve the problem using 4d vectors.
We identify the 3d vector (x y z) with the 4d vector (x y z 1).
Now look at the following matrix:
(1 0 0 a)
(0 1 0 b)
(0 0 1 c)
(0 0 0 1)
What happens if you multiply (x y z 1) by this matrix ? You get
(1 0 0 a) (x) = (x+a)
(0 1 0 b) (y) = (y+b)
(0 0 1 c) (z) = (z+c)
(0 0 0 1) (1) = (1)
You get the 4d vector (x+a y+b z+c 1) So this matrix is the translation by the vector (a b c) !
More generally we identify the 4d vector (x y z w) with the 3d vector (x/w y/w z/w).
So, the smaller the w-component of the 4d-vector, the bigger the components of the 3d-vector.
But, you might object, that’s possible only if w is nonzero. if w=0, we’re doing a division by 0 ! We solve this problem by saying that (x y w 0) is a so-called “point at infinity” or “direction at infinity” (that’s the same). So our 4d-vectors (x y z w) give 2 types of equivalence classes :
if w is nonzero, (x y z w) is identified with the ordinary point (x/w y/w z/w).
if w is zero, (x y z w) is a direction at infinity, pointed to by the vector (x y z).

Now, Michael, I know you’re an advanced opengl coder. So you’ve certainly already used a directional light (eg, for the sun…). You know that, to do this, you pass a GL_POSITION which is a 4d-vector with 0 as its w-component. That matches perfectly what I’ve said above. In fact, by using those 4d-vectors, we don’t make any distinction between ordinary points and directions at infinity. That’s called “projective geometry”.

Now, to understant your other questions :
you don’t compute a cross product of 4d-vectors. The cross-product is an object that lives only in dimension 3. So you convert your vectors into 3d-vectors like above, you compute the cross-product and you add a 1 as the 4th component to convert it back to a 4d-vector.
In this case, of course, using 4d vectors leads to a complication. But on the other hand you have so big advantages from using 4d-vectors…
For the dot-product, there’s no problem:
xx’ + yy’ + zz’ + ww’.

And it’s faster to use an array of elements rather that individual components, because the corresponding opengl functions (with a ‘v’ ) are faster to call.

Hope this helps
Morglum

[This message has been edited by Morglum (edited 04-10-2002).]

Exactly, that’s what I mean! We dont necessarily need 4D-Vectors and 33 Matrices for any calculation inside our own code.
We dont need 3
3 matrices at all, and the functionality of 4D-Vectors can be VERY limited (such as an array with a constructor to convert a 3D-Vector to a 4D-Vector.)
Thus, 4D-Vectors in use dont deserve the “Vector”-calling.
And 4*4 matrices define a product with 3D-Vector in such a way that they assume the 4th component is not important or 1.

Or on the other hand, we can implement a 4D-Vector that acts in almost every operation like a 3D-Vector and wouldnt need 3D-Vectors. This could be better for memory alignment.

Thank you Morglum!

Oh, and while it is cool to have that w value to distinct between translations and directions, i dont see any usage for that information. I think its certainly unwanted that 4D-Vector gets converted to a 3D-Vector by dividing every of the first three components through w. If one would do it that way, the coder would always have to worry about the 4th component. If one wouldnt one could still scale the vector manually.

You’re right, in your application, you’ll always use w=0 or w=1. It’s useless to bother with any other value for w, and, as you say, it carries no other information.

>>>>>>>
I think its certainly unwanted that 4D-Vector gets
converted to a 3D-Vector by dividing every of the first three components through w
<<<<<<<

Yes ! in fact, one could perfectly use another correspondence. That would simply change the 4d-vectors sent at infinity (the set of such vertors is called the"hyperplane at infinity" - in the case of opengl, it consists of the vectors having w=0 ). The guys who designed OpenGL had to choose one, and they choosed the one that was most widely used.

>>>>>>>>>>>>
This could be better for memory alignment.
<<<<<<<<<<<<

Why ? I don’t understand why there could be memory alignment problems. Just take for the coords floats if you’re compiling in 32-bit and doubles if you’re compiling in 64-bit, and there shouldn’t be any problems, unless there’s something I’ve not understood.

Morglum

Well, if you have an array of vectors with four components, every vector would start at a 16-byte border. If they had 3 components (12 bytes) that wouldnt be the case.
Now 16 is a power of two, 12 isn’t. I thought that might make a difference, but im absolutely no guru. So i think it might make a difference.

Again, thank you very much for your insight, it’s highly appreciated!
Michael

So I’ll stick with 4-component vectors, where matrix operations only affect the 3 first components. The fourth component can be used for colors etc, where linear algebra is not needed.

I’m currently doing some stuff with an identity projection matrix and only a scale on the modelview matrix to get arbitrary w values down the pipe. This way I get direct control over texture LOD and perspective correction. I admit that this is not the common case but I’m glad that OpenGL just handles the stuff correctly.

Michael,

you’ve just teached me something. I thought that alignment was only every 4 bytes on 32-bit PCs. I thought it didn’t make any difference, whether data was aligned to 4 bytes or to 16 bytes. thanks !

Morglum

Hi !

The good thing with 16 byte alignment is that the CPU cache is designed to handle reading and writing in 16 byte chunks (or 32 byte chunks), so aligning on 16 bytes could improve performance a little bit sometimes.

But this kind of stuff changes all the time with new CPU’s so usualy it’s enough to keep stuff aligned with it’s own size (float on 4 bytes, double on 8 and so on).

But of course then we have MMX/SSE code, this also requires that you keep stuff aligned on 16 bytes.

Mikael