How do BoundingVolumes work?

What is a boundingvolume? How is it different from a gbv? ie, how does one imagine a bv which is not a gbv?

Why does PandaNode have a bv and not a gbv?

How does one go about modifying a bv/gbv?


In a fit of overenthusiastic genericity in the early days of Panda’s development, I decided to abstract away the distinction of a “bounding volume” from that of a specific “bounding volume in space”. The idea was that maybe we might construct a specialized graph of PandaNodes that represents something other than renderable geometry, for instance, maybe a network communication graph or something. In that context, each node wouldn’t have a geometric bounding volume, but would instead have some other kind of abstract network-latency volume. The BoundingVolume interface is designed to be generic enough to support this abstract concept.

In practice, of course, none of that actually happened, and whenever you come across a PandaNode, it always contains a GeometricBoundingVolume–specifically, it almost certainly contains a BoundingSphere (although I also left room for the possibility of other shapes of bounding volumes when the situation demanded it).

All of these inherit from the base class, BoundingVolume. The proper way to query the properties one of these, then, is to verify that it is in fact a GeometricBoundingVolume via is_of_type(), and then use the DCAST macro to downcast it to a GeometricBoundingVolume pointer.


Ok, that makes sense.

Couple of follow-up questions:

  • what would be the issues with migrating PandaNode to use gbvs directly, to save that DCAST?
  • how does one go about setting the properties of that boundingsphere?


The DCAST is actually free. In a production build (i.e. OPTIMIZE=4), it compiles into a static cast, which is evaluated at compilation time.

The easiest way to fit a bounding sphere to geometry is to determine a list of vertices that define the geometry, and put all those points in an array. Then bounding_volume->around(points, points + num_points) is the STL-style method that automatically computes a sphere around the indicated points.


bounding_volume->around(points, points + num_points)

Ah… and that really does mean num_points, not num_points - 1. Yes, that works a lot better :slight_smile:

The DCAST is actually free.

Yes, its actually a readability and maintainability issue.

Readability: it’s a couple of extra lines of code, so its more code to understand, and it reduces concision.

Maintainability: ditto

Also, it’s extra text in the documentation, ie … ingVolumes

What do you think? Is this a big change? What happens if you use a DCAST macro to cast from a pointer to gbv to a pointer to gbv?


(Just to confirm, the bouding volume works perfectly now btw! Awesome :smiley: )


Well, the readability/maintainability issue is a good point. In point of fact, I’d been angling to rework the whole BoundingVolume thing anyway; I also don’t like the fact that set_bound() and get_bound() operate on a reference to a BoundingVolume instead of a pointer–the convention established throughout Panda is to use a pointer when something might represent polymorphism, and a reference otherwise. This violates that convention.

But it seems a fairly minor point, yet I think it might be a fairly sizeable effort to fix; and there are so many bigger things to rework in the meantime. (But I really do love reworking code to make it clearer and cleaner. :slight_smile: It’s just a question of time.)

In fact, we use the DCAST macro fairly heavily throughout Panda, so anyone who spends any time with the code will need to become familiar with it anyway, reducing the readability objection somewhat.

That being said, if you’d like to take a stab at changing this, I’d be happy to accept your changes. :slight_smile:

Oh, and to answer your question: you can DCAST a gbv to a gbv, and it works, but I think this sort of pointless operation would even further obfuscate the code.