3
votes

I have a large 3D scene for which all objects are stored in OpenGL vertex arrays and each frame is drawn with:

for(int i = 0 ; i < noLists ; ++i)
{
    glVertexPointer(3, GL_FLOAT, 0, vertexArraysList[i] ) ;
    glColorPointer(4, GL_FLOAT, 0, colorArraysList[i] ) ;
    glDrawArrays(GL_QUAD_STRIP, 0, verticesNumber) ;
}

Typically the user starts first looking at the entire scene, but soon identifies portion of interest and zooms in on a given region, so that large parts of entire scene fall outside the screen. But I find that FPS rate when zoomed is the same as when viewing entire screen, so it seems OpenGL draws all those vertices that fall outside the screen nonetheless (or at least progresses far enough with them in the pipeline as to make no difference from drawing them in terms of time cost).

Is there any way to test whether the content of a particular vertex array falls outside the screen, so I could avoid drawing it then?

1
Are you asking how to do that yourself, or some switch you can turn on to cause OpenGL to do that?Nicol Bolas
Either way. A magical switch would sure be great if there happens to be one.Puchatek
I don't really see how can I query whether a particular OpenGL coordinate, after all the transformations, falls within or outside of viewport, which is I guess what avoiding drawing "manually" would boil down to.Puchatek
@Puchatek: You actually can do that by applying matrix transforamtion to coordinate yourself. gluProject. However, that's not an efficient way for clipping objects.SigTerm
You're drawing quad strips. Are you doing some kind of 2D rendering, or is this a 3D scene?Nicol Bolas

1 Answers

9
votes

Calculate bounding box (axis-aligned (AABB) or oriented (OBB)) And check if it is visible. If it is not visible, don't draw the object.

Required knowledge:

  1. Plane equation (ax + by + cz + d = 0)
  2. Point to plane distance calculation.
  3. Construct plane (equation) using point and normal or using 3 points.
  4. Applying matrix transformation to a point/vector.
  5. Vector cross-product.

That's basic 3D stuff that can be found in plenty of tutorials on the web. Google "matrix faq", for example, gamasutra also had aabb/obb tutorials 7 years ago.

--edit--

Figuring out if a coordinate in 3D space is visible is the part chat escapes me. Well, back to notepad and a few tutorials

Plane can be defined by point (p) and normal (n). p is a point on the plane, n is a vector that is perpendicular to the plane.

Given point p1, you can figure out whether this point lies above the plane, on the plane, or below it, by performing simple calculation.

dist = dot((p1 - p), n), where dot is dot-product (dot(a, b) = a.x*b.x + a.y+b.y + a.z*b.z) If n is unit-length (dot(n, n) == 1) dist will store distance from point to plane. Otherwise it's sign will indicate where p1 is located. If dist > 0 p1 is above the plane, if dist < 0, it is below the plane, and if dist == 0 it is on the plane.

Frustrum is a "visible volume" which is defined by 4 planes that intersect at camera origin. Ever saw "camera cone" in 3d editor? That's what frustrum looks like if visualized.

Now, let's assume that for all those "frustrum" planes normals (plane normals, n, remember?) point outside the frustrum.

Now, you have an object you want to test. If ALL points of this objects's bounding box are "above" (or "outside") even for one frustrum plane, object is invisible, because it does not itnersect the frustrum. That's based on separating axis theorem. This will also work even if you use object's points instead of bounding box.

That should be enough to get you started. You can google the rest. Google for tutorials and 3d related stuff - those topics were discussed to death in last 10 years (mostly by wannabe game developers and beginners), there should be sea of info on the subject.