Puchatek
Puchatek

Reputation: 1537

Avoid drawing outside the screen with OpenGL vertex arrays

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?

Upvotes: 4

Views: 2211

Answers (1)

SigTerm
SigTerm

Reputation: 26419

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.

Upvotes: 10

Related Questions