I was working on some unrelated code when I ran into some performance issues related to bounding volumes, mainly that we create a ton of instances every frame and then throw them away. This is creating some pretty bad memory pressure issues right now (way worse than our old issues) and some primitives are eating up a ton of CPU time because of BoudingSphere.fromPoints. This itself is no big deal because it’s easily fixed, which I am now in the process of doing on a branch.
If that were it, I wouldn’t have written this post; however, while refactoring the code I ran into some readability issues that I would like to address as well. In a lot of cases, we use the variable boundingVolume and when reading the code you have no way of knowing whether the object is a BoundingSphere or a BoundingRectangle. In fact, update function seems to return the same object literal
This may be clear to developer very familiar with the specific primitive they are working with, but it makes things difficult otherwise. I would like to change this to return separate properties based on bounding volume type, only one of which need be defined. For example:
Then, in code that “knows” which one will be defined already, no changes are needed (it just uses the correct property); in other areas where we may not be sure, we simply do a typeof check for undefined. Also, even though it’s an object literal, is there a name for this thing being returned? It seems like we should make it a concrete type so that it’s easier for people implementing their own primitives, though I understand this object may be temporary until further DDR work; if so ignore my last comment.
We will not keep the object literal for long. The data structure will be significantly more complicated, and will have an explicit type (well, as close to creating a type as we can in JavaScript). We could have stayed on a branch for a few months with the DDR before bringing anything in, but we are all in agreement that incremental fine-grained pull requests are preferred. On an upcoming pull request, you will see that this object will be changed to an array, and then later to a tree.
As for adding bounding volume properties for different types to this object, it seems better to me to keep a generic, polymorphic boundingVolume property. We care about projecting the bounding volume onto the near plane, intersecting it with a frustum, etc. As long as it has functions to do so, the rendering engine doesn’t care if it is a sphere, axis-aligned bounding box, object-oriented bounding box, k-DOP, or even a tree of heterogeneous bounding volumes. In C++, BoundingSphere, etc. would inherit from a BoundingVolume abstract class.
As for the primitive implementation, perhaps it is better for it to have separate bounding volumes for 3D, Columbus View, and 2D, and I’ll consider that as I look at the Columbus View architecture (theoretically this week).
Good to know. Thankfully, it turns out that 99% of the issues were
resolved by just optimizing BoundingSphere.fromPoints (see https://github.com/AnalyticalGraphicsInc/cesium/pull/206 ) so I'm not
even going to worry about the other extra instances we create for now
since there is going to be a lot of work in that area of the code
anyway.
Several of the “Visualizer” classes, such as ModelVisualizer, already have a getBoundingSphere() function, and DataSourceDisplay has one as well that loops over the visualizer instances for an entity and computes the combined bounding sphere.
Anything with ‘Spec’ on the end is the unit test for that class.
A DataSourceDisplay is used to visualize the entities. viewer.dataSourceDisplay will return the DataSourceDisplay that contains anything you’ve added to viewer.entities.
viewer.dataSourceDisplay.getBoundingSphere is a private function that will compute the bounding sphere for the entity.
You can poll that function until it returns Cesium.BoundingSphereState.DONE. Some of the entity parts are computed asynchronously, so the bounding sphere may not be ready and the function will return Cesium.BoundingSphereState.PENDING. When it returns Cesium.BoundingSphereState.DONE, the result parameter should will be the bounding sphere for that entity.
While it is generally not recommended to use a private function in your application, I’m not quite sure of any other way to get the bounding sphere for an entity.
If this is unclear, let me know and I’ll throw together an example.
How about getting the BoundingSphere for a DataSource? For instance, KmlDataSource?
Maybe there’s another way to do what I need to do. Basically, I want to be able to make the camera flyTo an Entity or DataSource and make sure the entire entity is visible. I’ve seen the Camera.flyToBoundingSphere function, which is exactly what I want.
Oh! In that case, you can use Viewer.flyTo. This function can handle many different types for the target argument, including an Entity, EntityColection or DataSource.