Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 8 of 8

Thread: draw frustum outlines

  1. #1
    Member Regular Contributor remdul's Avatar
    Join Date
    Mar 2004
    Location
    The Netherlands
    Posts
    335

    draw frustum outlines

    Hi,

    I have a world in which I have a bunch of cameras. I want to draw each camera view frustum as lines. In order to do that I need to know the (world-space) coordinates of the 8 vertices that make up the near- and far-plane polygons. How can I calculate these? I have the position, rotation/viewing direction vector/up vector, aspect ratio, farplane/nearplane distance etc.

    Thanks in advance.

  2. #2
    Advanced Member Frequent Contributor
    Join Date
    Apr 2004
    Posts
    990

    Re: draw frustum outlines

    As you, know the viewing frustum projects the viewvolume to the range [-1,1]x[-1,1]

    Just try defining 4 vertices:

    (-1,-1,scale,1.0);
    (-1,1,scale,1.0);
    (1,1,scale,1.0);
    (1,-1,scale,1.0);

    and multiply them them with the inverse of the projection matrix, that should do the trick.

    N.

  3. #3
    Advanced Member Frequent Contributor plasmonster's Avatar
    Join Date
    Mar 2004
    Posts
    739

    Re: draw frustum outlines

    Code :
    The transformed clip space position c of a
    world space vertex v is obtained by transforming 
    v with the product of the projection matrix P 
    and the modelview matrix MV
     
    c = P MV v
     
    So, if we could solve for v, then we could 
    genrerate vertex positions by plugging in clip 
    space positions. For your frustum, one line 
    would be between the clip space positions 
     
    (-1,-1,near) and (-1,-1,far), 
     
    the lower left edge of the frustum, for example.
     
    NB: If you would like to mix normalized device 
    coords (x,y) and eye space coords (near,far), 
    you need an additional step here. Modify your 
    clip position as follows
     
    c' = (c.x * c.z, c.y * c.z, c.z, c.z)
     
    otherwise you would need to supply both the z 
    and w for c, which might be inconvenient. Simply 
    use c' instead of c below.
     
     
    To solve for v, multiply both sides of the equation above with 
     
          -1       
    (P MV) 
     
    This gives
     
          -1      
    (P MV)   c = v
     
    This is equivalent to
     
      -1  -1      
    MV   P   c = v
     
     -1
    P   is given by
     
    |(r-l)/(2n)     0         0      (r+l)/(2n) |
    |     0    (t-b)/(2n)     0      (t+b)/(2n) |
    |     0         0         0         -1      |
    |     0         0   -(f-n)/(2fn) (f+n)/(2fn)|
     
    where l, r, t, b, n, and f are the parameters in the glFrustum() call.
     
    If you don't want to fool with inverting the 
    model matrix, the info you already have can be 
    used instead: the forward, right, and up 
    vectors, in addition to the eye position.
     
    First, go from clip space to eye space
     
         -1   
    e = P   c
     
    Next go from eye space to world space
     
    v = eyePos - forward*e.z + right*e.x + up*e.y
     
    assuming x = right, y = up, and -z = forward.
    edit:

    -tried to reformat
    -added a note

  4. #4
    Advanced Member Frequent Contributor yooyo's Avatar
    Join Date
    Apr 2003
    Location
    Belgrade, Serbia
    Posts
    872

    Re: draw frustum outlines

    Try something like this:
    Code :
    Assume proj contains projection matrix and mv contains modelview matrix...
    Matrix4 proj, mv, temp, inv;
    temp = proj * mv;
    inv = inverse(temp); // compute inverse of matrix
     
    VECTOR4 fr[8]=
    {
    // near
    {-1, -1, -1, 1}, { 1, -1, -1, 1}, { 1,  1, -1, 1},  {-1,  1, -1, 1},
    // far
    {-1, -1, 1, 1},	{ 1, -1, 1, 1},	{ 1,  1, 1, 1},  {-1,  1, 1, 1}
    };
    // Transform all vertices:
    // multiply vertex array (fr) by matrix. result is transformed vertex array (tfr)
    VECTOR4 tfr[8];
    transform_points(fr, 8, inv, tfr); 
     
    int i;
    for (i=0; i<8; i++)
    {
     tfr[i].x /= tfr[i].w;
     tfr[i].y /= tfr[i].w;
     tfr[i].z /= tfr[i].w;
     tfr[i].w = 1.0f;
    }
     
    glBegin(GL_LINES);
    connect tfr points as follow:
    0-1, 1-2, 2-3, 3-0, 
    4-5, 5-6, 6-7, 7-4,
    0-4, 1-5, 2-6, 3-7
    glEnd();
    This is a pseudo code. I suppose that you already have your math library with matrix and vector functions (inverse, transform_points and matrix_mult (*).

    yooyo

  5. #5
    Advanced Member Frequent Contributor plasmonster's Avatar
    Join Date
    Mar 2004
    Posts
    739

    Re: draw frustum outlines

    Here's a little code to demonstrate the idea
    above:

    Code :
    Vector xyzToWorld( Vector xyz, Vector eye,  Vector forward, Vector right, Vector up ) {
     
    // xyz is normalized device (x,y) and eye space z
    // eye, forward, right, and up constitute the
    // eye origin and basis vectors, respectively.
     
    // frustum info
    float nearZ   = 4;
    float farZ    = 10000;
    float fovX    = 90;
     
    // frutum setup  
    float projZ   = nearZ * tan( fovX * PI / 360 );
    float aspect  = screenHeight / screenWidth;
    float l       = -projZ;
    float r       = +projZ;
    float b       = -projZ * aspect;
    float t       = +projZ * aspect;
    float n       = nearZ;
    float f       = farZ;
     
    // inverse of projection matrix
    // based on the parameters above - the same 
    // values use in the glFrustum() call.
     
    float P[16] = {
    (r-l)/(2*n),      0,	     0,        (r+l)/(2*n),
         0,      (t-b)/(2*n),    0,        (t+b)/(2*n),
         0,           0,         0,             -1,      
         0,           0,   -(f-n)/(2*f*n), (f+n)/(2*f*n)
    };
     
    // undo divide with w (eye space z)
    float px = xyz.x * xyz.z;
    float py = xyz.y * xyz.z;
    float pw = xyz.z;
     
    // move into eye space
    float ex = P[0] * px  + P[1] * py  + P[3] * pw; 
    float ey = P[4] * px  + P[5] * py  + P[7] * pw;
    float ez = P[8] * px  + P[9] * py  + P[11]* pw;
     
    // move into world space
    return eye - forward*ez + right*ex + up*ey;
    }
    So, for your frustum problem, you could supply these values for xyx:
    (-1,-1,nearZ) (-1,-1,farZ)
    (-1,+1,nearZ) (-1,+1,farZ)
    (+1,+1,nearZ) (+1,+1,farZ)
    (+1,-1,nearZ) (+1,-1,farZ)

  6. #6
    Intern Contributor
    Join Date
    Jan 2004
    Posts
    69

    Re: draw frustum outlines

    with all the methods posted ill just add one more variation.

    fovy, near, far are given

    hheight = tan(fovy/2); //half the height of the frustum at z=1;
    hwidth = hheight * aspect; //same for width

    so assuming you know your cameras forward/up/right vectors (ie, using a "matrix camera" or simply invert the view matrix).

    right=hwidth*far*cam_right;
    top=hheight*far*cam_up;
    center=cam_pos + far*cam_forward;

    nice to have (vectors from the center of the far plane to the sides/corners)

    ftl = center - right + top; //far top left
    fbr = center + right - top; //far bottom right

    and so on.
    no need to touch any opengl matrices if you dont do anything fancy, know your fov and the cameras vectors (ok, that IS a matrix, but you usually manage that one yourself).

  7. #7
    Member Regular Contributor remdul's Avatar
    Join Date
    Mar 2004
    Location
    The Netherlands
    Posts
    335

    Re: draw frustum outlines

    Now that's exactly what I was looking for!

    Thanks to you all!

  8. #8
    Junior Member Newbie
    Join Date
    May 2004
    Posts
    2

    Re: draw frustum outlines

    One thing always puzzled me - why do people use the vertical field of view to define a perspective matrix?
    The more intuitive axis would be the horizontal field of view....for me at least.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •