Hello,

So I'm aware that OpenGL is Column major and DirectX is Row major, but how does that translate into a basic 1D array?

So given the below visual matrix, what would the first 3 in the array of each platform and which 3 would be the x,y and z translation of each platform?

``````  |AA BA CA DA|
|AB BB CB DB|
|AC BC CC DC|
``````

What I'm trying to find out is if I was given a matrix pulled from either platforms, would a formula for one work with the other (x,y,z translation index stay the same).

On a side note, is there a difference between directX and direct3D?

There are two different matters at play here. There is the mathematical concepts of column vectors versus row vectors. And there is the memory layout issue of storing matrices in column-major or row-major. These are two completely separate issues. In mathematics, we almost exclusively use column vectors. In mathematics, memory …

## All 4 Replies

When you have column-major ordering, that matrix would look like this in memory:

``````AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD
``````

When you have row-major ordering, that matrix would look like this in memory:

``````AA BA CA DA AB BB CB DB AC BC CC DC AD BD CD DD
``````

The translation part of a homogeneous transformation matrix, is in the last column (DA, DB, DC), in other words, you have orderings like this:

``````column-major:
AA AB AC  0 BA BB BC  0 CA CB CC  0  x  y  z  1

row-major:
AA BA CA  x AB BB CB  y AC BC CC  z  0  0  0  1
``````

What I'm trying to find out is if I was given a matrix pulled from either platforms, would a formula for one work with the other (x,y,z translation index stay the same).

No it will not. You should abstract away that detail. Most matrix or linear algebra packages can easily accomodate either ordering by simply hiding it away in the implementation details of a matrix class. For example, here is a very simple way to handle this:

``````class Matrix4x4 {
private:
double* data;
bool is_column_major;

public:
// ....

double operator()(int i, int j) const {
if(is_column_major)
return data[j * 4 + i];
else
return data[i * 4 + j];
};

double& operator()(int i, int j) {
if(is_column_major)
return data[j * 4 + i];
else
return data[i * 4 + j];
};

// ...
};
``````

It's that simple, this way everything else you can just write in terms of a matrix that you can address like `m(i,j)` to get the element of row `i` and column `j`, and you don't have to worry about ordering. There are, obviously, better ways to do this (with less overhead), but that's the basic idea.

On a side note, is there a difference between directX and direct3D?

Direct3D is just the part of DirectX that handles 3D graphics. DirectX is a wider library that also provides other things like audio and 2D graphics (DirectDraw) for example. OpenGL is more comparable to Direct3D because it, too, only does 3D graphics.

So I now have a better idea, but there's still one more thing that confuses me and it's because this explanation seems to controdict what you said about the tanslation part.

So your version (correct me if I'm wrong) is you took both arrays and put them on paper as a matrix they'd be identical(it's just how the array is ordered), but his has it such that:

``````Where T is the translation part of the matrix:
This is OpenGL
|X X X T|
|X X X T|
|X X X T|
|X X X X|

This is Direct3D
|X X X X|
|X X X X|
|X X X X|
|T T T X|
``````

Thanks for the help so far, mike_2000_17.

There are two different matters at play here. There is the mathematical concepts of column vectors versus row vectors. And there is the memory layout issue of storing matrices in column-major or row-major. These are two completely separate issues. In mathematics, we almost exclusively use column vectors. In mathematics, memory layouts do not exist, since mathematics is abstract, and memory layouts are an implementation detail / choice when you put the abstract math into real code.

So, to make things clear, in mathematics, we have this:

``````|X X X T|   |X|
|X X X T| x |Y|  =  M x V
|X X X T|   |Z|
|0 0 0 1|   |1|
``````

which performs the rotation and translation of the 3D vector (X,Y,Z). If you transpose the entire expression, you get an equivalent expression:

``````(M x V)^T = V^T x M^T = | X Y Z 1| x |X X X 0|
|X X X 0|
|X X X 0|
|T T T 1|
``````

(where all the X's are transposed too). The above is how the mathematical conventions of row-vectors and column-vectors relate to each other. In other words, using row-vectors just means that you transpose everything. But like I said, in mathematics, we use, almost exclusively, column-vectors. And I just noticed that Direct3D documentation uses row-vectors... (sigh).. (rolleyes)..

In OpenGL, the matrices are stored in column-major ordering, meaning that the memory index of each element of the matrix is as follows:

``````| 0  4  8 12|
| 1  5  9 13|
| 2  6 10 14|
| 3  7 11 15|
``````

But in Direct3D, they store them in row-major ordering, leading to these indices:

``````| 0  1  2  3|
| 4  5  6  7|
| 8  9 10 11|
|12 13 14 15|
``````

That's how it is. Now, because Direct3D "thinks" about transformation matrices in a transposed way (using row-vectors), this actually means that the actual numbers stored in both cases (OpenGL or Direct3D) will be the same. In other words, two wrongs make it right.

I hope this clears the confusion.

Here, you can work out both multiplications like this:

OpenGL:

``````| 0  4  8 12|   |X|   |0X + 4Y +  8Z + 12|
| 1  5  9 13| x |Y| = |1X + 5Y +  9Z + 13|
| 2  6 10 14|   |Z|   |2X + 6Y + 10Z + 14|
| 3  7 11 15|   |1|   |3X + 7Y + 11Z + 15|
``````

Direct3D:

``````|X Y Z 1| x | 0  1  2  3|
| 4  5  6  7|
| 8  9 10 11|
|12 13 14 15|
= | 0X + 4Y +  8Z + 12,
1X + 5Y +  9Z + 13,
2X + 6Y + 10Z + 14,
3X + 7Y + 11Z + 15 |
``````

As you see, the result is the same.

If you want to keep your sanity, I recommend that you stick to column-vectors whenever you try to work out anything mathematically. And don't read too much stuff that uses row-vectors, to avoid the confusion it causes. Everything that is authorative in this area will come from the field of mathematics, which will mostly use column-vectors.

The main problem when learning about all of this stuff about 3D transformations and related topics is about the confusion about various conventions being used. Just wait until you get a load of the various representations of 3D rotations, like axis-angle, quaternions, rotation matrices, the 12 different Euler angle conventions, and the body-fixed vs. global conventions, and the components vs. basis rotations... there is a lot of room for confusion, so make sure you keep your head from spinning too much, and you might come out of it alive (I barely made it, back when I learned this stuff).

Thanks mike_2000_17, that did the job for me. It clears up everything (and some other things I didn't consider).

Be a part of the DaniWeb community

We're a friendly, industry-focused community of 1.19 million developers, IT pros, digital marketers, and technology enthusiasts learning and sharing knowledge.