Thread: Clipping in Direct3D

  1. #1
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607

    Clipping in Direct3D

    Having problems with clipping in Direct3D.

    I know how to assemble the clip matrix and could transform all of my vertices by this matrix, test against w, and accomplish clipping.

    However I want to work with the hardware and not against it. I've read the DirectX docs but it does not look like I can retrieve a clip matrix at any point in the pipeline. Since clipping is probably done on the hardware does this mean to pre-clip my vertices I will have to re-transform my vertices by my own clip matrix??

    Essentially if the object is off screen or not in the view frustrum I don't want it rendered.

  2. #2
    Registered User
    Join Date
    Mar 2003
    Posts
    580
    I assume you are talking about culling (not sending an object down the rendering pipeline as it's totally offscreen). You need to build the six planes of the frustum, and write code to frustum cull primitive shapes, i.e spheres and boxes. You don't want to spend anytime doing any transformations on each object, rather you leave the positions of the objects alone but bring the frustum planes into worldspace.

    edit:
    wait, I'm confused, if you've already got a frustum what more do you need?
    Last edited by Darkness; 11-24-2004 at 12:52 AM.

  3. #3
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Okay then once I do that just transform those into world space using the camera's Position as the translation amount?

    Is there any way to derive the six planes from the world matrix? In other word if I take the inverse of the view matrix can I find the six clip planes w/o manually creating them?

    I have a frustrum but in Direct3D you define it by simply stating a max distance, and an HFOV. It computes the rest. I have the formulas to compute the extents using those values. Is that what I use to create my planes?

  4. #4
    Registered User
    Join Date
    Apr 2002
    Posts
    1,571
    I'll give you some code from one of my old engines to extract that planes you need for frustum culling. I think my code is pretty self-explanatory. You start with the unit cube, and transform it by the inverse clip matrix and then extract the planes from the new points. Enjoy.

    Code:
    void Frustum::Calculate( D3DXMATRIX *lpMatView, D3DXMATRIX *lpMatProj )
    {
      D3DXMATRIX matClip;
    
      D3DXMatrixMultiply( &matClip, lpMatView, lpMatProj);
      D3DXMatrixInverse( &matClip, NULL, &matClip );  
    
      // Use unit extents at first
      vertices[0] = D3DXVECTOR3(-1.0f, -1.0f,  0.0f); 
      vertices[1] = D3DXVECTOR3( 1.0f, -1.0f,  0.0f); 
      vertices[2] = D3DXVECTOR3(-1.0f,  1.0f,  0.0f); 
      vertices[3] = D3DXVECTOR3( 1.0f,  1.0f,  0.0f); 
      vertices[4] = D3DXVECTOR3(-1.0f, -1.0f,  1.0f); 
      vertices[5] = D3DXVECTOR3( 1.0f, -1.0f,  1.0f); 
      vertices[6] = D3DXVECTOR3(-1.0f,  1.0f,  1.0f); 
      vertices[7] = D3DXVECTOR3( 1.0f,  1.0f,  1.0f); 
    
      // Transform unit extents by inverse clip matrix
      for( int i = 0; i < 8; ++i )
        D3DXVec3TransformCoord( &vertices[i], &vertices[i], &matClip );
      
      // Calculate the planes of the frustum from the given extents
      D3DXPlaneFromPoints( &planes[0], &vertices[0], &vertices[1], &vertices[2] );
      D3DXPlaneFromPoints( &planes[1], &vertices[6], &vertices[7], &vertices[5] );
      D3DXPlaneFromPoints( &planes[2], &vertices[2], &vertices[6], &vertices[4] );
      D3DXPlaneFromPoints( &planes[3], &vertices[7], &vertices[3], &vertices[5] );
      D3DXPlaneFromPoints( &planes[4], &vertices[2], &vertices[3], &vertices[6] );
      D3DXPlaneFromPoints( &planes[5], &vertices[1], &vertices[0], &vertices[4] );
    }
    "...the results are undefined, and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces." --Scott Meyers

  5. #5
    Registered User
    Join Date
    Mar 2003
    Posts
    580
    Okay, I've implemented this a few different ways. The 'official' way: multiply your projection matrix by your worldspace matrix (aka modelview matrix in OpenGL). I don't exactly remember how to extract the vectors like this, because to be honest what I did was just used code to extract the right and up vectors, then I mirrored them (reflected) them about the normalized view vector to obtain the left and down plane vectors (then, the near and far plane vectors are aligned with your view vector anyway).

    edit:
    You start with the unit cube, and transform it by the inverse clip matrix and then extract the planes from the new points. Enjoy.
    Right, we're on the same wavelength. I think that what I mentioned above is similar, except it starts one step ahead: instead of starting with the unit cube, it starts out with that cube transformed such that it represents your field of view (the projection matrix in OpenGL I believe), then multiplying it by the modelview/worldview matrix brings it into worldspace.

    edit1:holy crap i just realized that was someone else who posted that code, not bubba.

    i should really try sleeping...
    Last edited by Darkness; 11-24-2004 at 01:17 AM.

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Aha.....so the clip matrix is formed in D3D by multiplying the view matrix by the projection matrix. I dunno why I couldn't figure that out.

    Thanks a million Mr. Wizard.

  7. #7
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I probably will not worry about objects that are half in and half out of the frustrum. I really think splitting the thing and culling it would really take more time than simply letting the hardware do it. But for objects that lie completely out of the frustrum...I don't even want to mess with them.

    Another question I have:

    In my current setup each world matrix is computed inside of the render function. I set the projection matrix at the start of the render loop and then inside each object I have a world matrix that I transform it by. Is there a way to transform all objects by the same matrices? I know this might not be possible because rotations and such are not identical for all objects.

    I found a way around the translation matrix so I rarely use it anymore. Translation amounts will always reside at matrix._41, matrix._42 and matrix._43. So I just put my translation amounts into the final matrix be it the rotation, world, invview, or whatever is needed for that object and then set the world transform to that matrix.

    But Direct3D states that setting the transform messes with a lot of internal data structures and should be kept to a minimum. How do you transform each object correctly w/o constanty computing its own world matrix? A global world matrix would be nice....but again I'm not sure this is possible.

  8. #8
    Registered User
    Join Date
    Mar 2003
    Posts
    580
    enclose each object with a simpler volume, such as a sphere or axially aligned bounding box. just as long as you know the position of the object in worldspace, the dimensions of the bounding volume, and the frustum planes in worldspace, you're good to go.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Why use Direct3D?
    By m3rk in forum Tech Board
    Replies: 42
    Last Post: 05-22-2009, 09:08 AM
  2. Need help with getting DirectX 9.0 initilization
    By DarkMortar in forum Windows Programming
    Replies: 7
    Last Post: 05-09-2006, 08:58 PM
  3. How to Antialias Direct3D?
    By Deo in forum Game Programming
    Replies: 6
    Last Post: 06-02-2005, 12:14 PM
  4. Problem with Direct3D
    By frenchfry164 in forum Tech Board
    Replies: 1
    Last Post: 11-27-2003, 04:28 PM
  5. Direct3D vs. OpenGL
    By PorkyChop in forum Game Programming
    Replies: 22
    Last Post: 12-08-2002, 12:41 AM