2
votes

In OpenGL in Delphi, I am attempting to calculate how much of a scene is viewable by finding the left, right, top and bottom extents of the viewing area in an orthographic projection. This will make some mouse interactions seem to be 1-to-1. I don't have much access to the code that sets up the orthographic projection matrix, but I know it calls glOrtho(...) to set up the projection matrix.

I need to be able to take a cartesian plane (not a rendered polygonal plane), then calculate the left, right, top and bottom edges of the viewing frustum from whatever information opengl can provide (I don't care about the front and back clipping planes). I don't have access to the code which sets up the viewing volume (using glScene library for Delphi), so the only information I can use to find this information (as far as I know) is

glGet(GL_PROJECTION_MATRIX, @projectionMatrix);

Based on the documentation in http://www.talisman.org/opengl-1.1/Reference/glOrtho.html, I decided I can do some math to calculate what the left, right, top and bottom extents were for the near plane (which in ortho mode is enough) (see my code below). However, when I actually look at the values I retrieve from glGet, I see a matrix with values that don't fit the description in the documentation link I gave above (see matrix data below). With such disappointing numbers, I have doubts about whether I am using glGet properly, and whether I can actually rely on those numbers to give me the left/right/top/bottom extents of the visible volume. I suppose I could also be making a mistake in Delphi, but I don't know what it would be.

In this particular instance, the plane is oriented to face the camera directly, and the camera has an orthogonal projection. I am not in complete control of how the projection matrix is set up, so I had hoped I could calculate the left edge as

 left = 2 / (A * (tx - 1)/(tx+1) - 1)

Where A and tx are retrieved from the projection matrix, as shown at http://www.talisman.org/opengl-1.1/Reference/glOrtho.html (I am not showing how I derived the formula above, so it could be incorrect--right now it gives an answer of -INF). The code I was using to retrieve the projection matrix values is as follows:

var
  projectionMatrix: TMatrix;
  Left, Right, Top, Bottom: Single;
  A, B, C, tx, ty, tz: Single;
begin
  A := projectionMatrix[0][0];
  B := projectionMatrix[1][1];
  C := projectionMatrix[2][2];
  tx := projectionMatrix[0][3];
  ty := projectionMatrix[1][3];
  tz := projectionMatrix[2][3];

  Left := 2 / (A * ((tx - 1) / (tx + 1) - 1));
  ShowMessage(FloatToStr(A));
  //etc...

The matrix values I see are about like this:

[0] (0, 1.7436188636e-39, 6.4310754487e+37, 1.3822464104e-39)
[1] (3.8535707769e-43, 1.4012984643e-45, 0, 2.8086960027e+32)
[2] (-4.20345941e+17, 0, 1.7437029415e-39, 2.8086960027e+32)
[3] (1.7437645986e-39, 6.4311900443e+37, +NAN, 1.7437645986e-39)

[Edit] glScene has the following declarations:

TMatrix = THomogeneousFltMatrix; 
THomogeneousFltMatrix = TMatrix4f; 
TMatrix4f = array[0..3] of TVector4f; 
TVector4f = array[0..3] of single; 

[Edit] If I change the projection matrix to a 16-value array, here is what happens:

var      
  projectionMatrix, modelviewMatrix: array[0..16] of single;
begin
  ...
  glGetFloatv(GL_PROJECTION_MATRIX, @projectionMatrix);
  ...

the resulting array is elements 0 through 16, which still doesn't look right.

projectionMatrix (5.9208279286e-39, -1536643072, 1.2429653406, -1.2128044229e-11, 2.8763115406, 0, 4.728515625, 1.7430022923e-39, 6.5138089186e+37, -3.7955583126e+30, -2.4000201225, -3.7955583126e+30, 2.4000201225, -1.2128044229e-11, 2.6263115406, -1.2128044229e-11, -2.6263115406)

1
Can you please show the declaration of TMatrix? Can you please show the exact code for your call to glGet()?Alistair Ward
as Alistar already said, check your TMatrix declaration. Essentially it hjas to be 16 consecutive single precision floats in memory, not 4 pointers to 4 floats.heeen
These are all from the glScene library: TMatrix = THomogeneousFltMatrix; THomogeneousFltMatrix = TMatrix4f; TMatrix4f = array[0..3] of TVector4f; TVector4f = array[0..3] of single; It seems Heeen is on the right track.Kimball Robinson
Alistair and Heeen, I edited the question per your suggestions and tried something new. See the question text.Kimball Robinson
Are you sure the matrix is supposed to be intact when your code is being called? Maybe the drawing code resets the projection matrix or somesuch and calls your code afterwards. Also, just for fun, can you load an identity matrix and check you are actually getting an identity matrix with glGet?heeen

1 Answers

1
votes

You seem to use glScene. Why not use TGLSceneBuffer.ScreenVectorIntersectWithPlane()?

You get 4 world vectors fom the 4 screen coordinates and have a rectangle whose area you can easily calculate.