Sign in to follow this  
_goat

APIs and Matrix Order (Row / Column)

Recommended Posts

_goat    804
At the moment, the mathematics of my engine are in the preliminary stages. Since my engine is designed to be API independant, I need a way of sending DirectX Row-Major matrices, and OpenGL Column-Major matrices. Thus I'd need two versions of "createPerspectiveMatrixLH", and two for the Right Handed equivalent. Clearly this is a sub-optimal solution. I wracked my brain for a pattern to solve this, but I came up with nothing. Does anybody have a suggestion for this? My gut tells me to shy away from specifying that I will be passing in [sic] Row-Major matrices, and expect the implementations of the APIs (who requrie Column-Major matrices) to transpose them for every function call. Any help would be greatly appreciated.

Share this post


Link to post
Share on other sites
ZQJ    496
Left and right handedness is not related to whether the matrices are stored in row-major or column-major order. To switch between row- and column-major order you just have to do a transpose along the lines of:


std::swap(matrix[1], matrix[4]);
std::swap(matrix[2], matrix[8]);
std::swap(matrix[3], matrix[12]);
std::swap(matrix[6], matrix[9]);
std::swap(matrix[7], matrix[13]);
std::swap(matrix[11], matrix[14]);



(I think I've got that right) Anyway, whether you use a left- or right-handed coordinate system is completely up to YOU and doesn't depend on the API, you just need to supply different projection matrices, so there's no reason to use a different system in each API.

Share this post


Link to post
Share on other sites
haegarr    7372
ZQJ is right with his answer. However, OGL has an extension allowing to use row-major order matrices as well: GL_ARB_transpose_matrix

See at
http://oss.sgi.com/projects/ogl-sample/registry/ARB/transpose_matrix.txt

I've never used it yet, but it seems to be available ... In my Mesa implementation it is also available w/ no ARB suffix, so I assume it is already part of the core implemention of todays OpenGL.

Share this post


Link to post
Share on other sites
JohnBolton    1372
Check out this thread. The topic is the same as yours.

Briefly, both D3D and OpenGL matrices are stored in memory in the same order. There is no need to transpose. However, there are other differences in the two that you will have to accomodate: LH vs RH, untransformed orientation (facing Z vs. facing -Z), and the different clip space clip volumes.

Share this post


Link to post
Share on other sites
ZQJ    496
Quote:
Original post by JohnBolton
However, there are other differences in the two that you will have to accomodate: LH vs RH, untransformed orientation (facing Z vs. facing -Z), and the different clip space clip volumes.


Once again - it is perfectly possible to set up an identical coordinate system in both APIs. As far as I know they're more similar then they appear (I'm not sure about the clip volume thing) - both use the same less comparison on Z coordinates by default (when Z buffering), and the main difference is that the conventional perspective matrices are different.

Share this post


Link to post
Share on other sites
_goat    804
Quote:
Briefly, both D3D and OpenGL matrices are stored in memory in the same order. There is no need to transpose. However, there are other differences in the two that you will have to accomodate: LH vs RH, untransformed orientation (facing Z vs. facing -Z), and the different clip space clip volumes.
Okay, since that is what will need to change for those two APIs, and might change even again for another API (hell, might as well make it totally flexible), what would you suggest for dealing with the differences? I mean, the perspective projection matrices for OpenGL and DirectX are:


DirectX (from SDK, same as Real Time Rendering, 2nd Ed.):
2*zn/(r-l) 0 0 0
0 2*zn*(t-b) 0 0
(l+r)/(l-r) (t+b)/(b-t) zf/(zf-zn) 1
0 0 zn*zf/(zn-zf) 0

OpenGL (from Real Time Rendering, 2nd Ed.):
2*zn/(r-l) 0 (l+r)/(l-r) 0
0 zn*(t-b) (t+b)/(b-t) 0
0 0 zf/(zf-zn) zn*zf/(zn-zf)
0 0 -1 0
Clearly, they are the transposition of each other (and modified for handedness and mapping). So, I clearly need a way of creating a perspective projection matrix, and sending it to the API (which could be anything), and making sure that the API understands it. Using my basic SMatrix4 class, there's no meta-data describing what it's got in it, and I don't like the idea of having to make an API transpose a matrix every function call, just because I've stated my engine will use a certain format.

Any help?

Share this post


Link to post
Share on other sites
haegarr    7372
I don't know whether it would be an acceptible solution for you, but why not making an abstraction layer as is (more or less) usual in such cases?

The projection (or anything similar w.r.t. the API) isn't described by a matrix but in general terms (e.g. the clipping plane distances, fov, ... as part of a camera). You could load the abstraction layer as a plug-in to avoid the entire app to fail due to binding problems to externals libs, but other solutions may be suitable for you, too. Then the layer provides the way to compute the matrix of interest in the way it is needed.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this