BoundingSphere of the rootNode

Hi,

I need to get the get the BoundingSphere of the rootNode without the cam. How do I do this?
Thanks in advance!

1 Like

you cant get sphere from box,

but you can do something like(if i remember correctly) (BoundingBox)rootNode.getWorldBound() get its values and do "your bounding sphere based on bounding box"

if im wrong, let someone fix me.

That’s right. The scene graph does not accumulate bounding spheres. While they are certainly optimal for easy rejection, they are not optimal for merging (there actually is not good ‘accurate’ algorithm as far as I know) and quite often bounding spheres end up being non-optimally sized more often than axis-oriented bounding boxes.

Axis-oriented bounding boxes are trivial to merge and will always be as accurate as the leaf-nodes they are made of.

Ok, but the camera is still included in the BoundingBox, how can I get rid of it? (or better: How can I create a Node, which includes all objects in the scene but the camera)

You are mistaken. The camera is not an object in the scene graph.

…unless you have a CameraNode… but then that’s part of the scene and not actually the camera at all. If you want the size of the scene without the CameraNode then remove the CameraNode.

Oh, you are right, my mistake…

If you include the Minie Library in your project:

import jme3utilities.MyMesh;
import jme3utilities.math.VectorSet;
...
VectorSet locations = MyMesh.listVertexLocations(rootNode, null);
float mbsRadius = locations.maxLength();

Here’s a link to Minie at the JMonkeyStore:
https://jmonkeystore.com/38308161-c3cf-4e23-8754-528ca8387c11

So that method collects all of the vertexes in the entire scene in world space and then tells you the maximum distance from the origin? Or?

I can’t see how that’s useful at all in this case.

That distance is the radius of the minimum bounding sphere centered on the world origin. What more do you need?

What if all of your objects are within 4000 to 5000 in x,y,z? Your approach will give you a huge sphere that has no real meaning.

If the OP wants the minimum bounding sphere with an arbitrary center, that can be obtained using BoundingSphere.computeFromPoints(). Something like this:

        VectorSet locations = MyMesh.listVertexLocations(rootNode, null);
        FloatBuffer points = locations.toBuffer();
        BoundingSphere mbs = new BoundingSphere();
        mbs.computeFromPoints(points);
        float mbsRadius = mbs.getRadius();
        Vector3f mbsCenter = mbs.getCenter();

Yeah… Welzl’s algorithm.

The thing is that a sphere may not even be optimal for what OP wants. I’m curious what this is needed for. (For example, a sphere is going to be really bad for positioning a camera so that everything is in view.)

Edit: and note that Welzl’s algorithm can be pretty awful for a large number of points as it’s iteratively just trying combinations until it finds the right sphere. If sphere-level accuracy is not required then it’s a lot of wasted work.

I need it exactly for this problem. My idea is to place the camera in the center of the BoundingSphere and move it back a-times. I would compute a the folloing way:

a = radius of the boundingSphere/sin(opening angle of the camera)

Can you explain why this would be a bad idea or show a more efficient way?

1 Like

It’s bad only because it’s trivial to come up with scenes where the camera will end up super far away from the scene.

Imagine a case where you are looking at a long skinny triangle from one end. The camera will “move back” very far just to fit the whole sphere in but the sphere is much larger than what is in view.

If you already know the direction you will be looking then it’s relatively trivial to calculate a distance that will fit all points in view if that’s really what you need. If an approximation is all that’s needed then the axis-aligned bounding box already calculated may be enough, too.

You are right. Is it possible to create a bounding box, which is aligned to the local camera space and not to world space?

Yes.

1 Like

Ok, how?

1 Like
  1. Collect the world coordinates of the vertices.
  2. Apply Camera.getScreenCoordinates() to convert to camera space.
  3. Compute the axis-aligned bounding box.

And now @pspeed will explain why you don’t really want to do that either.

2 Likes

Well, I mean you don’t really need the bounding box. Just the point farthest left, point farthest right, top, bottom… the min and max in screen space.

Personally, I’d use dot product. getScreenCoordinates() can be used but may give strange results in cases outside the frustum I guess.

For each point:
calculate camera-relative position.
do a dot product between that position and camera.getLeft()… that’s x.
do a dot product between that position and camera.getUp()… that’s y.

Use min/max X and min/max Y to decide how far away to be.

You might want also the dot product with camera.getDirection() to help you set the near and far planes of the camera’s frustum.