1
Vector3d nearC(0,0,0 -w);
Vector3d farC(0,0,0-x);
double width = y/2;
double height = z/2;
double angleOfHeight = atan(height/w);
double angleOfWidth = atan(width/w);
double adjustedHeight = tan(angleOfHeight) * x;
double adjustedWidth = tan(angleOfWidth) * x;

nearC[0] - width, nearC[1] - height, nearC[2]
nearC[0] - width, nearC[1] + height, nearC[2]
nearC[0] + width, nearC[1] + height, nearC[2]
nearC[0] + width, nearC[1] - height, nearC[2]
farC[0] - adjustedWidth, farC[1] - adjustedHeight, farC[2]
farC[0] - adjustedWidth, farC[1] + adjustedHeight, farC[2]
farC[0] + adjustedWidth, farC[1] + adjustedHeight, farC[2]
farC[0] + adjustedWidth, farC[1] - adjustedHeight, farC[2]

Above is my frustum in view coordinates. View Matrix is:

 0   0  -1   0
 0   1   0  -1
 1   0   0 -10
 0   0   0   1

All of it is right, we have a sheet.

I can't for the life of me figure how to get that frustum in canonical viewing volume. I've run through every perspective projection I could find. Current is this:

        s,        0,                      0,                     0,
        0,        s,                      0,                     0,
        0,        0,             -(f+ne)/(f-ne),            2*f*ne/(f-ne),
        0,        0,                      1,                     0;

double s = 1/tan(angleOfView * 0.5 * M_PI / 180);

I'm missing a step or something, right? Or a few steps?

Sorry to sound so hopeless now, been spinning wheels a while on this.

Any help appreciated.

Sean
  • 31
  • 4
  • 1
    its unclear what you want to achieve.... and where the problem is try to describe your problem a bit more – Spektre May 06 '20 at 07:34
  • I'm trying to achieve something like this: https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/projection-matrices-what-you-need-to-know-first Mapping a viewing frustum to that -1,1 canonical view. But I just can't manage it haha. – Sean May 06 '20 at 07:38
  • 1
    what exactly is known? your first code/table is a mess. – Spektre May 06 '20 at 07:45
  • I have the translation from world coordinates to viewing coordinates. That's from the first block, which gives the 8 corners of the frustum. The matrix beneath that is the translation from world coordinates to viewing coordinates. Now I'm trying to get those 8 corners of the frustum into a -1,1 box. w is the distance to the far pane. x is the distance to the near pane. Calculations beneath all that are trig to get the frustum. **Sorry x is far, w is near. – Sean May 06 '20 at 07:56
  • Basically I've managed the trig and the first translation from world coordinates to viewing coordinates but every other matrix has eluded me. Can't work the orthogonal, can't work the canonical viewing volume. – Sean May 06 '20 at 07:59
  • are you sure your 8 points form frustrum? I would start with projection and only then go for view matrix – Spektre May 06 '20 at 08:16

1 Answers1

2

Lest start with the perspective projection. The common way in old GL is to use gluPerspective.

for that we need znear,zfar,FOV and aspect ratio of view. For more info see:

  • Calculating the perspective projection matrix according to the view plane

    I am used to use FOVx (viewing angle in x axis). To compute that you need to look at your frustrum from above looking at xz plane (in camera space):

    frustrum XY plane

    so:

    tan(FOVx/2) = znear_width / 2*focal_length
    FOVx = 2*atan(znear_width / 2*focal_length)
    

    the focal length can be computed by computing the intersection of frustrum edge lines. Or by using triangle similarity. The second is easier to write:

    zfar_width/2*(|zfar-znear|+focal_length) = znear_width/2*(focal_length)
    zfar_width/(|zfar-znear|+focal_length) = znear_width/(focal_length)
    focal_length = (|zfar-znear|+focal_length)*znear_width/zfar_width
    focal_length - focal_length*znear_width/zfar_width = |zfar-znear|*znear_width/zfar_width 
    focal_length*(1-(znear_width/zfar_width)) = |zfar-znear|*znear_width/zfar_width 
    focal_length = (|zfar-znear|*znear_width/zfar_width) / (1-(znear_width/zfar_width))
    

    and that is all we need so:

    focal_length = (|zfar-znear|*znear_width/zfar_width) / (1-(znear_width/zfar_width))
    FOVx = 2*atan(znear_width / 2*focal_length)        
    FOVx*=180.0/M_PI; // convert to degrees
    aspect=znear_width/znear_height;
    gluPerspective(FOVx/aspect,aspect,znear,zfar);
    

    just be aware of that |zfar-znear| is perpendicular distance between the planes !!! So if you do not have axis aligned ones then you need to compute that using dot product and normal ...

Spektre
  • 49,595
  • 11
  • 110
  • 380
  • Thanks very much buddy. I'll try this out now. Btw you seem so cool haha. – Sean May 06 '20 at 17:05
  • Hello again, buddy, I got that out. Well, it was what I had already really, only I had it all done out myself. But now how do I get the canonical view volume? Dunno will you get this haha. – Sean May 14 '20 at 05:49
  • @Sean You just multiply the modelview and projection matrices together ... where modelview represents transformation from your rendered model space into view space.. From the stuff you got in your question it looks like your frustrum is axis aligned so its just matter of translating along z axis. Beware gluPerspective is looking in `-Z` direction so maybe even rotate by 180deg or flip/mirror .... – Spektre May 18 '20 at 05:48