5

I need a simple and fast way to find out how big a 3D bounding box appears on screen (for LOD calculation) by using OpenGL Modelview and Projection matrices and the OpenGL Viewport dimensions.

My first intention is to project all 8 box corners on screen by using gluProject() and calculate the area of the convex hull afterwards. This solution works only with bounding boxes that are fully within the view frustum.

But how can a get the covered area on screen for boxes that are not fully within the viewing volume? Imaging a box where 7 corners are behind the near plane and only one corner is in front of the near plane and thus within the view frustum.

I have found another very similar question Screen Projection and Culling united but it does not cover my problem.

Community
  • 1
  • 1
denim
  • 1,329
  • 1
  • 15
  • 24

2 Answers2

2

what about using queries and get samples that passes rendering?

http://www.opengl.org/wiki/Query_Object and see GL_SAMPLES_PASSED,

that way you could measure how many fragments are rendered and compare it for proper LOD selection.

fen
  • 9,835
  • 5
  • 34
  • 57
  • +1 Or you could even use the sample count of the object itself (not its box) from the previous frame (maybe you already meant it this way, might be worth to provide some clarification). – Christian Rau Feb 04 '13 at 13:39
  • Thank you for the quick answer. Actually this is what I am doing now. But for me this is a very time consuming way, because huge boxes update a lot of fragments (usually the whole screen) which really drops frame rate. I just wanted to ask if there is a very cheap way to achieve this, because this is a very common task I think. – denim Feb 04 '13 at 13:53
  • @denim Like said in my comment. Don't use any boxes at all. Just draw the objects (using the current LOD) and issue a query for each of it (but don't wait for it). Then in the next frame, use the query results of the previous frame to deterimine the new LOD. This way you probably don't have to wait for the query results (since the previous frame should already have finished) and neither do you have to draw huge boxes, only the objects that you need to draw anyway. Likewise are the results also more accurate than an approximating box. The one-frame delay shouldn't be noticed. – Christian Rau Feb 04 '13 at 19:54
  • Yes, I agree, this really sounds like the most accurate way. Thanks – denim Feb 04 '13 at 22:42
1

Why not just manually multiply the world-view-projection with the vertex positions? This will give you the vertices in "normalized device coordinates" where -1 is the bottom left of the screen and +1 is the top-right of the screen?

The only thing is if the projection is perspective, you have to divide your vertices by their 4th component, ie if the final vertex is (x,y,z,w) you would divide by w.

Take for example a position vector

v = {x, 0, -z, 1}

Given a vertical viewing angle view 'a' and an aspect ration 'r', the position of x' in normalized device coordinates (range 0 - 1) is this (this formula taken directly out of a graphics programming book):

x' = x *  cot(a/2) / ( r * z )

So a perspective projection for given parameters these will be as follows (shown in row major format):

cot(a/2) / r     0      0    0
     0        cot(a/2)  0    0
     0           0      z1  -1
     0           0      z2   0

When you multiply your vector by the projection matrix (assuming the world, view matrices are identity in this example) you get the following (i'm only computing the new "x" and "w" values cause only they matter in this example).

v' = { x * cot(a/2) / r, newY, newZ, z }

So finally when we divide the new vector by its fourth component we get

v' = { x * cot(a/2) / (r*z), newY/z, newZ/z, 1 }

So v'.x is now the screen space coordinate v.x. This is exactly what the graphics pipeline does to figure out where your vertex is on screen.

I've used this basic method before to figure out the size of geometry on screen. The nice part about it is that the math works regardless of whether or not the projection is perspective or orthographic, as long you divide by the 4th component of the vector (for orthographic projections, the 4th component will be 1).

default
  • 2,637
  • 21
  • 44
  • Thanks for your suggestion, but like mentioned before this approach is not right for boxes that have corners beyond the near clipping plane, because then the perspective projection doesn't give right results. – denim Feb 04 '13 at 22:44
  • Ok sounds like you got what you need. But perspective projection will give the right result as long as you divide by the 4th component of the vector. See "Homogeneous Divide" description [here](http://en.wikipedia.org/wiki/Transformation_matrix#Perspective_projection) – default Feb 14 '13 at 21:41
  • Thank you for your answer, I'd really like to know if there is a way to calculate the screen size instead of counting the pixels. I had a look at the specified link, but i still do not agree, Of course you "can" project points behind the near plane, but the projection will be wrong! You can easily see this be drawing a 2D sketch of a perspective projection and drawing projection lines throug the center of projection for a 2D line. The projection will be wrong. Hope the description is enough because i am not allowed to post images ;) – denim Feb 16 '13 at 23:36
  • see updated answer. I know this works, as I've used it before. So maybe I am answering a different question than what you are actually asking? – default Feb 19 '13 at 23:49
  • I agree with you everything you explained is done exactly the same way in gluProject() but you must not project vertices, that are behind the near clipping plane in an perspective viewing projection because the result is wrong. The projection is only valid for vertices in front of the near clipping plane. – denim Feb 20 '13 at 14:50
  • Ah I finally get it. Of course you can test if your vertices are inside the near/far planes by seeing if their final z-values are between -1 and 1, but you might have a case where one vertex is outside the frustum and another vertex is inside the frustum and so you want to know where the interpolated position intersects the frustum. That is a little bit harder of a problem. I'm sure its doable with the right math but I don't know off the top of my head. – default Feb 20 '13 at 16:13
  • Yeah you totally got the point now. Thank you for the excellent short description. Thats exactly what I wanted to know in the first time. But I guess that this is not so easy to achieve. In fact what I want to do is exactly done by each OpenGL implementation so there surely are a few people who know how to do this ;) – denim Feb 21 '13 at 07:48