PDA

View Full Version : Trying to render a frusum "shape" from a given orthographic projection matrix.



Alberto García
01-01-2018, 12:18 PM
Hi guys, in order to test my application, I want to render a shape which represents the volume of an orthographic projection.

I have found this code (http://jotschi.de/2009/12/13/drawing-the-perspective-view-frustum-with-opengl/), and when I pass a perspective projection matrix, it creates the frustum shape perfectly, but when I pass a matrix of a orthographic projection, all components ( x, y and z ) of the each generate vert are set with 0.0f.

So two questions:

1º) Why the frustum shape with a perspective matrix is built correctly, but not with an orthographic matrix?
2º) How can I create a frustum shape from an orthograpic projection matrix?

PD: The orthographic projection that I'm trying to render with that code, works well in my program.

Thanks in advances,
Alberto.

Alfonse Reinheart
01-01-2018, 01:19 PM
The word "fustrum" describes a specific shape: it's a pyramid with the top chopped off (https://en.wikipedia.org/wiki/Frustum). The volume of an orthographic projection is not a frustum. Therefore, you cannot render a frustum that represents a non-frustrum shape.

The volume of an orthographic projection is a cuboid/rectangular prism (https://en.wikipedia.org/wiki/Cuboid).

Alberto García
01-02-2018, 04:03 AM
Thanks for the clarification, Alfonse.

Then the question is:

How can I produce a shape in order to see the "view volume" of an orthographic projection, using my projection matrix?

Dark Photon
01-02-2018, 07:02 AM
That code just doesn't know how to back-infer the frustum generation parameters correctly for an orthographic frustum. It only supports a perspective frustum.

That said, updating it to detect an orthographic projection and allowing it to back-infer the frustum-generation parameters (l,r,b,t,n,f) from the orthographic projection matrix shouldn't be that hard. See the ortho and perspective projection matrices at the bottom of this page (http://www.glprogramming.com/red/appendixf.html). To determine which type of transform you have, just look at the bottom row. And combinations of matrix elements will give you (l,r,b,t,n,f), similar to the logic already there for a perspective projection matrix.

By the way, regardless of whether we're talking about an orthographic projection or a perspective projection, both are defined by a frustum (which is a region of a solid which lies between 2 parallel planes -- near and far in this case). A rectangular prism is just as much a frustum as a pyramid chopped by parallel planes. Both are easily defined by 6 planes, at least 2 of which are parallel.

The only confusion is that legacy OpenGL provided separate APIs to specify an orthographic projection matrix (glOrtho) and perspective projection matrix (glFrustum), falsely implying that only the perspective projection is defined by a frustum.

GClements
01-02-2018, 08:00 AM
How can I produce a shape in order to see the "view volume" of an orthographic projection, using my projection matrix?
Transform the vertices of the signed unit cube by the inverse of the projection matrix.

If the projection matrix has a known structure, it's possible to simplify the inverse (which is what that blog post tries to do, although I'm fairly sure it's wrong). But a generalised inverse isn't that difficult, and is something you should have available anyhow.

Alberto García
05-13-2018, 01:38 PM
Hi again, I come back with this issue,

according the post of GClements I have multiplied a unit cube by the inverse of my projection matrix ( orthographic ), but the shape produced by this operations doesn't match what I expect.

Here the source code:



void SetOrtho( Mat4 proj )
{
Mat4 inv = proj.Inverse();

// NEAR corners
Vec3 bln = inv * Vec4( Vec3( -1.0f, -1.0f, -1.0f ), 1.0f );
Vec3 brn = inv * Vec4( Vec3( 1.0f, -1.0f, -1.0f ), 1.0f );
Vec3 tln = inv * Vec4( Vec3( -1.0f, 1.0f, -1.0f ), 1.0f );
Vec3 trn = inv * Vec4( Vec3( 1.0f, 1.0f, -1.0f ), 1.0f );
// FAR corners
Vec3 blf = inv * Vec4( Vec3( -1.0f, -1.0f, 1.0f ), 1.0f );
Vec3 brf = inv * Vec4( Vec3( 1.0f, -1.0f, 1.0f ), 1.0f );
Vec3 tlf = inv * Vec4( Vec3( -1.0f, 1.0f, 1.0f ), 1.0f );
Vec3 trf = inv * Vec4( Vec3( 1.0f, 1.0f, 1.0f ), 1.0f );

Vec3 verts[] =
{
Vec3( tln ),
Vec3( trn ),
Vec3( brn ),
Vec3( bln ),
Vec3( tlf ),
Vec3( trf ),
Vec3( brf ),
Vec3( blf )
};

GLuint indexes[] =
{
// front
0, 1,
1, 2,
2, 3,
3, 0,
// back
4, 5,
5, 6,
6, 7,
7, 4,
// union
0, 4,
1, 5,
2, 6,
3, 7
};

Prana::SurfaceData *data = this->GetData();

data->mIndices.SaveData( indexes, 24 );
data->GetVBO( Prana::VBO_ID::INDEXES ).SetUpdated( false );
data->mVerts.SaveData( verts, 8 );
data->GetVBO( Prana::VBO_ID::VERTS ).SetUpdated( false );

data->CreateGL_VAO();
}


Is it right?

Thanks in advance,
Alberto

Alberto García
05-13-2018, 02:00 PM
I'm sorry I have noticed that there was an error in the multiplication order, now it runs has expected.