Cavalier oblique projection

Hi all!

This is my first post in this forum (and my first day in OpenGL), hope you can help me.

I’ve built up a cube, being centred in (0,0,0) with side length 2.

Now, if I use an orthographic projection such as


gl.glMatrixMode(GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrtho(-5, 5, -5, 5, 5, -5);
gl.glMatrixMode(GL_MODELVIEW);
gl.glLoadIdentity();
glu.gluLookAt(
0.0f, 0.0f, 5.0f, 
0.0f, 0.0f, 0.0f, 
0.0f, 1.0f, 0.0f);

then I just see the front side of my nice cube.

What I would like to achieve now, is a cavalier (or cabinet, should be similar) projection of my cube. See for a perfect example figures 11 and 12 of this website.

I’ve tried around for several hours now, but I don’t get it.

There is one post on this forum concerning this topic, but the proposed method does not work for me (if I just post-multiply the there given matrix to my glOrtho(…).

Thanks a lot in advance for your kind answers,

with best regards,
Oliver

Partial solution found!

Hi, i found a solution, how to produce this cavalier projection.

using this code:


gl.glMatrixMode(GL_PROJECTION);
gl.glLoadIdentity();
double[] cavalier = {
            1,0,Math.cos(Math.PI/4),0,
            0,1,Math.sin(Math.PI/4),0,
            0,0,1                  ,0,
            0,0,0                  ,1};
gl.glMultTransposeMatrixd(cavalier,0);
gl.glOrtho(-5, 5, -5, 5, -15, 15);

the desired oblique projection can be achieved.
The important thing was to first multiply the cavalier matrix and then, afterward let glOrtho do the actual projection (the glOrtho matrix has only zeros in the third row!).

But:
This code moves all my objects to the upper right!
Does anybody of you have an idea how to circumvent (or just how to calculate) that?

Thanks in advance!

With best regrads,
Oliver

Ehm,…check again?

is there any working solution or example how to use oblique projection in opengl?

Refer to the first link. This is just a standard parallel projection (glOrtho) where we’ve applied a skew to the X and Y based on Z depth first. This can be encoded in a 4x4 matrix. Just slap it on before applying the standard parallel projection transform.

thx for the response.
i tried that, but i can’t get it perfectly right: if i load the cavalier matrix first, and then multiply it with the ortho-matrix (glOrtho), the picture stretches if i resize the window. the cavalier perspective isn’t displayed correctly.


        gl.glViewport(0, 0, width, height);
        gl.glMatrixMode(GL.GL_PROJECTION);
        gl.glLoadIdentity();      

        double alpha = 45;
        double[] cavalier = {
                1, 0, -1 * Math.cos(Math.toRadians(alpha)), 0,
                0, 1, -1 * Math.sin(Math.toRadians(alpha)), 0,
                0, 0, 1                 			  , 0,
                0, 0, 0                 			  , 1};
        
        double ratio = (double) width / (double) height;
        int w = 10;

        gl.glLoadTransposeMatrixd(cavalier, 0);
        gl.glOrtho(-w * ratio, w * ratio, -w, w, -10, 100);

        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();

if i first load the ortho-matrix, and then multiply it by the cavalier matrix, the cavalier perspective is displayed corretly. unfortunately, there seems to be a strange translation of the picture, depending on the angle the matrix is using.


        gl.glViewport(0, 0, width, height);
        gl.glMatrixMode(GL.GL_PROJECTION);
        gl.glLoadIdentity();      

        double alpha = 45;
        double[] cavalier = {
                1, 0, -1 * Math.cos(Math.toRadians(alpha)), 0,
                0, 1, -1 * Math.sin(Math.toRadians(alpha)), 0,
                0, 0, 1                 			  , 0,
                0, 0, 0                 			  , 1};
        
        double ratio = (double) width / (double) height;
        int w = 10;

        gl.glOrtho(-w * ratio, w * ratio, -w, w, -10, 100);
        gl.glMultTransposeMatrixd(cavalier, 0);

        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();

any ideas why this is?

i’m using jogl by the way, that’s why theres a ‘gl.’ in front of every command…

Yeah this makes sense. This “skew” transform needs to be applied in eye space. Eye space by definition is “after” the MODELVIEW matrix is applied and “before” the PROJECTION matrix is applied.

This explains why your first approach is wrong. You were applying the cavelier transform in NDC space.

Now as to that shift with the second approach, I think I know what’s going on. Think about it for a second. What plane are you skewing with respect to? That is, on which plane are the XY values going to remain unmodified? Z=0, right? Further our from Z = 0 (the XY plane) yields more skew. So your whole object is being skewed sideways, not just the parts behind the front surface of your object in eye space.

It sounds like you want the latter. So you need to find the eye-space Z depth of the front of your object, and then skew w.r.t. that plane not Z=0 (i.e. Z subtract, cavelier skew, Z add).

Also, one thing you’ll probably bump into with this at some point. You probably want to apply this cavelier “eye-space tweak” transform at the bottom of your MODELVIEW stack as opposed to to the top of your PROJECTION stack. Reason is that after MODELVIEW but before projection, the hardware has to clip your model based on what’s still in the frustum. Your cavelier transform can shift faces that weren’t previously visible into the frustum and shift faces that were previously in the frustum out. So it needs to be in MODELVIEW.

thanks for the comprehensive reply. now that you notice the translation on the z-axis, i actually see what made my cube move around. i entirely forgot that there was a negative translation on the cube first. and what the cavalier projection does, is exatly what i saw: projecting points that go into the z-axis, making them appear more and more to the left or right, depending on the given angle. if i remove the translation on the cube, the front face remains at the same place, while all other sides get projected to the side, according to the cavalier projection.
i’m not quite sure whether this is mathematically incorrect, but i’m doing the whole multiplication thing as i showed it in the second code part i postet - this leads to the desired result.

For the archives, this is complete nonsense. Don’t know how I got that confused. Reasons to consider MODELVIEW vs. PROJECTION include: if you’re using eye-space for something such as application of user-defined clipping planes, computing fog coordinates, computing point size, eye-space texture coordinate generation, lighting, etc. but does not have anything to do with standard view-frustum clipping.

Of the above, if you’re lighting, decide whether you want the lighting to be correct in normal 3D space on in this sheared space. Probably the latter. And if so, put this transform in MODELVIEW.