Okay, I've been playing with this idea for a while now, time to dedicate its own thread to it, which I suppose implies something of a commitment to the project aswell. And hopefully some direction.

To those who don't know what Croissant 9 is... It is a software-rendered Java demo that I released in 2003: http://pouet.net/prod.php?which=10808
For a long time I've had the idea to create a hardware-accelerated version of it. I think it would be a good project for bringing some maturity to the D3D/OpenGL frameworks that I have made. I will need to implement all aspects of the Java demo system in the D3D/OpenGL framework in order to get a proper demo out.

I have pretty much decided that I'm going to do this with OpenGL, and have it work on Windows, linux, FreeBSD and possibly other OSes. That would be true to the spirit of the original Java demo, which ran 'everywhere' (even without a 3D card).
However, since my OpenGL framework is based pretty closely on the D3D framework, I'm playing with the idea to integrate the two into a single codebase. That would be much like the Unigine engine, which also supports DX9/10/11/OpenGL.
Currently there is a collection of code in the D3D codebase, which was written during the development of Croissant 9, and implements part of the same functionality as the Java engine. So I started working off that.

So far, I can read the geometry and animation paths from the Croissant 9 dataset in D3D. I think I will do the .ogg music replayer next.
Posted on 2010-07-29 09:54:03 by Scali
I've decided to try and get things working in OpenGL first... as that would be my end-goal, rather than D3D.
In the process I've also merged some of the interfaces between OpenGL and D3D, so that they are closer together.

The geometry is parsed correctly in OpenGL... however, there still appears to be a problem with the animation keys. It looks like the rotation keys aren't handled properly. I will have to look into that. They are stored slightly differently from the BHM file format, and require some quaternion operations that I had not yet tested. It could be that their implementation is slightly off.
I could cheat a bit, and use the D3DX library. The D3D version uses that, and that works. I'll have to compare it against what happens in OpenGL.
The geometry itself, the regular object matrices and position animation seems to work okay though.
Posted on 2010-08-02 06:12:10 by Scali
Yay, with the help of the D3DX library, I managed to track down the bug in my own code. Very subtle... the D3DX functions allow you to use the same parameters as input and output, which my parser did. My own implementation performed the correct math, but it overwrote one of the input parameters if it was the same as the output. Now that is fixed, and in OpenGL the content can be parsed and displayed correctly.

Here is the autobot cube from one of the first scenes:
Posted on 2010-08-02 14:07:09 by Scali
Scali, is the functionality of your project similar to http://www.libsdl.org in terms of D3D and OpenGL? Is it simpler or more complex? I've used libsdl before ( not extensively though) for some quick and dirty graphics programming in C and was curious as to your viewpoint on the comparison.
Posted on 2010-08-02 17:03:33 by p1ranha
Scali, could you please post here the World/Model, View, and Projection matrices captured from any valid frame (it may be from the frame visible in the image you attached). I'm somehow getting strange perspective artifacts in OpenGL so I'd like to see a working set of matrices to compare them with my own ones. I copy-pasted my transformation functions directly from one of my D3D9 projects and that's the root of the problem, I think. Specifically I suspect row-major vs column-major order and -1.0 - +1.0 device-normalized space in OGL vs 0.0 - +1.0 in D3D9. What do you think? The other suspects are badly set up vertex arrays / VBOs, but I'd like to confirm the matrices first.

Please post the matrices in the order returned by glGetFloatv() or in the order you pass them to glLoadMatirix / glLoadTransposeMatrix / etc.
Posted on 2010-08-02 17:10:11 by ti_mo_n

Scali, is the functionality of your project similar to http://www.libsdl.org in terms of D3D and OpenGL? Is it simpler or more complex? I've used libsdl before ( not extensively though) for some quick and dirty graphics programming in C and was curious as to your viewpoint on the comparison.



Check out SFML if you don't want to deal with something as overly complex as SDL or the L/GPL.
Posted on 2010-08-02 17:50:32 by SpooK

Scali, is the functionality of your project similar to http://www.libsdl.org in terms of D3D and OpenGL? Is it simpler or more complex? I've used libsdl before ( not extensively though) for some quick and dirty graphics programming in C and was curious as to your viewpoint on the comparison.


I think my goal is slightly different from SDL.
SDL tries to be a sort of DirectX (audio, video, input etc) API, where I work a level higher. What I do is closer to a 3D engine project such as Ogre.
I have wrapped the API-specific functionality into a few classes, so you don't have to deal with the D3D or OpenGL API directly, in many cases.

So yes, with this framework it's simple to get things on screen, but if you want to extend the functionality, you still need to get down-and-dirty with the API directly. I don't try to abstract the API itself, I try to abstract it one level higher.
Posted on 2010-08-03 03:23:52 by Scali

Scali, could you please post here the World/Model, View, and Projection matrices captured from any valid frame (it may be from the frame visible in the image you attached). I'm somehow getting strange perspective artifacts in OpenGL so I'd like to see a working set of matrices to compare them with my own ones. I copy-pasted my transformation functions directly from one of my D3D9 projects and that's the root of the problem, I think. Specifically I suspect row-major vs column-major order and -1.0 - +1.0 device-normalized space in OGL vs 0.0 - +1.0 in D3D9. What do you think? The other suspects are badly set up vertex arrays / VBOs, but I'd like to confirm the matrices first.

Please post the matrices in the order returned by glGetFloatv() or in the order you pass them to glLoadMatirix / glLoadTransposeMatrix / etc.


The row-major/column-major thing doesn't affect you in practice. It is cancelled out because OpenGL uses column vectors (M*v) where D3D uses row vectors (v*M).
This means that the matrices appear exactly the same in memory (they are implicitly transposed because of the storage difference).
The order in which you multiply matrices is reversed between OpenGL and D3D though. So if you do A*B in D3D, you need to do B*A in OpenGL and vice versa.

I'm at work now, so I can't access my code and put some dumps in.
However, it's open source, so you could do it yourself.
You can grab the source from SVN from this project: http://sourceforge.net/projects/bhmfileformat/
Then you can just add your matrix dump code yourself.

I know one problem I ran into is that the gluPerspective function takes degrees where D3DX's perspective matrix generation function takes radians. So when I plugged the D3D values in, things looked weird :)
Posted on 2010-08-03 03:31:25 by Scali
Think I better disagree here,  they are not the same memory layout, otherwise the order of multiplication would not matter.
You are right that you CAN use the same memory layout - but it is actually incorrect to do so.

Row and Column Major are ARRAY ORDERING SYSTEMS, ie, they dictate the naming convention of the array cells.
The difference between left and right handed coordinate systems is simply that one is the Transpose of the other.
If you adjust your memory layout correctly, you won't need to reverse the order of the elements in multiplications.


Affine 4x4 Transformation Matrix Layouts:

DirectX                     OpenGL
m00 m01 m02 m03    m00  m10 m20 m30
m10 m11 m12 m13    m01  m11 m21 m31
m20 m21 m22 m23    m02  m12 m22 m32
m30 m31 m32 m33    m03  m13 m23 m33

Xx   Xy   Xz   0           Xx   Yx     Zx    Px
Yx   Yy   Yz    0           Xy   Yy     Zy    Py
Zx   Zy   Zz   0           Xz    Yz    Zz     Pz
Px   Py   Pz   1            0     0      0        1

Please feel free to disagree, if you choose, but if you take my word for this, and simply rename the fields in your structure, and your matrix functions address fields by name (as mine do), then your functions will work with no changes.
By renaming the fields / changing the memory layout, you are effectively pre-transposing the matrix.

My matrix math function includefile has a simple switch I use to choose one matrix layout or the other, the functions will work in both systems :)

Posted on 2010-08-03 07:26:20 by Homer
They ARE the same memory layout. If you look at the BHM parser, you can clearly see that.
The BHM format was aimed at D3D, and exports matrices as a blob of 16 floats in a D3DXMATRIX layout.
These are used as-is in the OpenGL code. They are not transposed, because there is no need to.

Since OpenGL uses column vectors, technically you'd need the transpose of the matrix used in D3D, which uses row vectors... as I said, M*v vs v*M.
Or more accurately: M*v and (v^T)*(M^T).
This is why the matrix multiplication order is different.
Namely (A*B)^T == (B^T)*(A^T).

However, since OpenGL *also* uses column major storage (Fortran-style), it stores the elements in the array the other way around, compared to D3D (C/C++ style).
So, yes... From a mathematical point-of view, it looks like this:
DirectX                    OpenGL
m00 m01 m02 m03    m00  m10 m20 m30
m10 m11 m12 m13    m01  m11 m21 m31
m20 m21 m22 m23    m02  m12 m22 m32
m30 m31 m32 m33    m03  m13 m23 m33

But when it is written to memory, they both write it out as a linear sequence, in both cases resulting in:
m00 m01 m02 m03 m10 m11 m12 m13 m20 m21 m22 m23 m30 m31 m32 m33.

In other words, your array indices are the same in D3D and OpenGL, whether you use matrix(i) or matrix(x)(y). The memory layout is the same.

The difference is the MEANING of x and y. In OpenGL, x are the columns, y are the rows. In D3D, x are the rows, and y are the columns.
As I say, transposition is implicit.

Look at my GLUX library, which has nearly identical functionality to the D3DX library. You can see how it uses the matrices and vectors.
I actually have an important note in my GLMatrix definition in GLTypes.h:
/**
* Column-major matrix, compatible with OpenGL single precision GLfloat matrices.
* Note that C++ is row-major oriented, so indexing is like this:
* m;
*/
struct GLMatrix
{
        GLfloat m[4][4];
        operator GLfloat*() { return (GLfloat*)this; }
};

Posted on 2010-08-03 07:41:55 by Scali
Yeah ok, I'll agree with that, the cells are indeed written out to memory in sequential order according to their names, meaning we can't simply treat them as 4 x Vec4 - theres something else too.

I said that the only difference b/w left and right coordinate systems is that one is transpose of the other.
Almost true.

Some of the 3x3 orientation part of the matrix gets its sign flipped.
Posted on 2010-08-03 07:48:08 by Homer

I said that the only difference b/w left and right coordinate systems is that one is transpose of the other.


But left-handed vs right-handed coordinate systems are another issue altogether. Both APIs support either way, depending on what projection matrix you use.
Posted on 2010-08-03 07:51:39 by Scali
Your argument was actually helpful. Thanks guys ^^ You should argue more aften ;p

Anyway, I managed to make things work correctly. Turned out to be a badly set up view matrix (the middle one between world/model and projection). I was loading it via LoadTransposeMatrix so its effect was exactly the opposite of what I wanted. I really don't know what was LoadTransposeMatrix doing there ^^'

Now I have another problem which is quite puzzling. I set up the projection matrix with D3DXMatrixPerspectiveFovLH. One of its parameters is aspect ratio. I put width divided by height there (both values converted to floats before the division). It works correctly when I increase the width (thus increasing the ratio), but seems to be broken when I increase the height (thus decreasing the ratio). Please try it yourself (attachment) and tell me what you think. Basically, I want the cube's size to remain unchanged when only one of the coordinates changes, just like it is now with width.

The relevant parts of the code are:

// APPDATA (ad) is a superstructure which holds pretty much everything.

// The following is called every time the window's size changes:
if (ad->newW || ad->newH) { // if there is new width or height
 glViewport(0, 0, ad->newW, ad->newH);
 ad->oldW = ad->newW;
 ad->oldH = ad->newH;
 ad->newW = ad->newH = 0;
 setupPerspective(ad);
}

VOID setupPerspective(APPDATA *ad) {
 D3DXMATRIX tmpmat;

 ad->aspect = (FLOAT)(((FLOAT)(ad->oldW)) / ((FLOAT)(ad->oldH)));
 ad->d3dxf.D3DXMatrixPerspectiveFovLH(&(ad->proj), (FLOAT)ToRad(40.0), ad->aspect, 0.1f, 10.0f);
 glMatrixMode(GL_PROJECTION);
 glLoadMatrixf((ad->proj.m[0]));
}


I also noticed that glFinish performs a busy-wait (consuming a CPU core). I think it's related to this bug. Is there any known workaround except not using glFinish? Not that I need glFinish for anything. I'm just curious if there is any way to make it sleep instead of wasting CPU cycles.
Posted on 2010-08-04 13:52:22 by ti_mo_n
Your sourcecode for the setupPerspective function has variables called "oldW" and "oldH" - are these the OLD width and height??
You should use the CURRENT values in your call to set the perspective.
But the size of the cube on the screen, in pixels, is based on more than just the aspect ratio.
It also depends on the viewing distance, of course, with respect to the dimensions of the render device.
Posted on 2010-08-08 05:01:47 by Homer
Hi! Thank you for answering :) OldW and oldH are being set with the values from newW and newH before calling setupPespective. The cube becomes bigger ONLY with aspect ratios lower than 1.3333. For aspect ratios 1.3333 and above, its size remains unchanged (it only centers itself). Pretty strange. I never hand such problem in Direct3D.
Posted on 2010-08-08 08:07:58 by ti_mo_n
Have you found your problem yet?
I think the projection matrix is pretty much the only matrix that is not the same in D3D and OpenGL, because of the different 'device space' coordinate systems.
I'd have to look into what the differences were exactly, because I don't remember them off the top of my head, but I recall that using a custom projection matrix for z=infinity required custom code for both APIs.

But have you tried just using gluPerspective instead of D3DXMatrixPerspectiveFovRH?
That's what I do in my code currently. You can feed them pretty much the same parameters. You could compare the different matrices that they generate from the same parameters.

OpenGL generates it like such:
http://www.opengl.org/sdk/docs/man/xhtml/gluPerspective.xml

f=cotangent (fovy/2)

f/aspect  0  0                        0
0          f  0                        0
0          0  zFar+zNear / zNear−zFar  2×zFar×zNear / zNear−zFar
0          0  -1                        0


And Direct3D generates it like such:
http://msdn.microsoft.com/en-us/library/bb205351(v=VS.85).aspx

xScale  0            0              0
0        yScale      0              0
0        0        zf/(zn-zf)        -1
0        0        zn*zf/(zn-zf)      0
where:
yScale = cot(fovY/2)
   
xScale = yScale / aspect ratio


Rewriting OpenGL to D3D's syntax would yield:

xScale  0        0              0
0        yScale  0              0
0        0        zf+zn/(zn−zf)  2*zn*zf/(zn−zf)
0        0        -1              0


So apart from the transpose notation, the only difference is these two entries:
zf/(zn-zf) -> zf+zn/(zn−zf) (translated by a factor zn)
zn*zf/(zn-zf) -> 2*zn*zf/(zn−zf) (scaled by a factor 2)
(These differences basically encode the different 0..1 and -1..1 depth-ranges between the two APIs).

So gluPerspective is right-handed.
If you compare D3DMatrixPerspectiveFovLH vs RH, you'll see that basically only the sign of the third row is flipped (which would be the third column in OpenGL). In other words, the direction of the z-axis is inverted. The element at m32 is also rewritten to re-use the (zf-zn) term, but essentially does not change. So it's easy to construct a left-handed projection matrix for OpenGL as well:

xScale  0        0              0
0        yScale  0              0
0        0        zf+zn/(zf−zn)  -2*zn*zf/(zf−zn)
0        0        1              0
Posted on 2010-08-18 04:27:54 by Scali
That's a great post, Scali :)
At some point, I know I'm going to search here for that info (my brain is more like a sieve each year), and I certainly haven't ever posted that before, I figure this will be the top result :)
Posted on 2010-08-18 07:42:47 by Homer
I simply use D3DXMatrixPerspectiveFovLH in OpenGL. I recently had a problem with it resizing my geometry but I've already solved it. The resize was because of X scale being calculated based on Y scale. That's why the geometry resized only when the height of the window changed.

Anyway, Is there any reason not to use D3DXMatrixPerspectiveFovLH ? I know it's a simple matrix math function and can be easily hand-written. I'm just curious if I should be aware of any problems one might encounter in the future.
Posted on 2010-08-18 09:36:28 by ti_mo_n
Portability - it can only work on Windows operating systems.
And it's not a big deal to write your own, which I suggest will be better, having seen the kind of crud behind some DX matrix functions.
Posted on 2010-08-18 10:03:32 by Homer
Well, I suppose using the D3D projection matrix will mean that you're only using half your zbuffer's resolution.
Posted on 2010-08-18 11:34:07 by Scali