tags:

views:

411

answers:

1

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  A: 

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.

Ozan
I never got a chance to use this, but I think it's the right solution--and I don't want to leave this "unanswered" for other reasons.
Kimball Robinson