How do draw a bounding volume?

Hello,

I’m implementing an 3D editor in which the user can add among others spheres or boxes. To create a box I user the following code:



[java]

Box b = new Box(5,5,5);

MyGeometry geom = new MyGeometry(“Box”, b);

Material mat = new Material(app.getAssetManager(), “Common/MatDefs/Light/Lighting.j3md”);

mat.setTexture(“DiffuseMap”, app.getAssetManager().loadTexture(“Textures/texture1.jpg”));

mat.setFloat(“Shininess”, 50f);

geom.setMaterial(mat);

geom.setLocalTranslation(new Vector3f());

geom.setModelBound(new BoundingBox());

geom.updateModelBound();

[/java]



Now I would like to draw a bounding volume around the geometry, if the geometry is selected. This should be simular to this picture:







Does anyone have any idea how can I achieve this?

Create a mesh and geometry based on the boundingvolume (if box then box etc) and attach it to the scenegraph, thats the way jMP does the “selection view”. However in jMP the location is still somehow messed up, if you come up with a clean and working solution tell me :wink:

1 Like

Thanks for your answer. But I’m not so familiar with the jme3 (I use it only for 6 weeks), so I don’t know how to create a mesh and geometry based on the bounding volumes. Can you tell me, how this works?

Creating geometry and meshes to make a box is described in the very first HelloWorld tutorial…

This is how its done in jMP:

http://code.google.com/p/jmonkeyengine/source/browse/branches/jme3-gde/jme3-core/src/com/jme3/gde/core/scene/controller/SceneToolController.java#183

You can create a WireBox and then use the fromBoundingBox() method

4 Likes

Oh cool :smiley:

Thank you! That works very fine.

Hello,

I have one more question related to the rotation and scale of geometries. I rotate and scale the geometries with g.setLocalRotate and g.setLocalScale. Although I call g.updateModelBound() after this changes, the boundingBox is not updated. How can I update the boundingBox?

You have to call fromBoundingBox() again

Oh, I forgot this. Thanks.



After the scale or rotate of the geometry I get a new problem: The boundingBox is larger than the geometry:







For this example I had scaled the sphere only in x-direction. Does any one know, why the BoundingBox is after scale or rotate larger than the geometry?

Hello, I have to concretize my problem. My default sphere has a radius of 3. In the following picture (The distance between the grid lines is 10) I scale the sphere by 2 in x direction:







The information about the sphere after the scaling is the following:



translation: (0.0, 0.0, 0.0)

scale: (2.0, 1.0, 1.0)

rotate: (0.0, 0.0, 0.0, 1.0)

bound: BoundingBox [Center: (0.0, 0.0, 0.0) xExtent: 5.992299 yExtent: 2.9961495 zExtent: 3.0]



I think this information is correct. the xExtent is nearly 6, because of the scale factor os 2. But the visualization in the picture don’t fit to this information. The xExtent in the picture looks like 12. Does anyone a idea, how I solve this problem?



EDIT: I had tested a little bit more:



scale factor: 2. xExtent: 6. visible xExtent of boundingBox in view: 12

scale factor: 3. xExtent: 9. visible xExtent of boundingBox in view: 27

scale factor: 4. xExtent: 12. visible xExtent of boundingBox in view: 48

scale factor: 5. xExtent: 15. visible xExtent of boundingBox in view: 75



So the xExtent of the boundingBox multiplied wit the scale factor once again.

I solved the problem: I use g.getModelBound() instead of g.getWorldBound() to get the BoundingVolume.

Hi guys. I tried to test the boundingBox too. I did you described it here, but the boundingBox does not move/rotate with the Geometry. Should I attach the BoundingBox to the Geometry?



Here is my code:





[java]

import com.jme3.app.SimpleApplication;

import com.jme3.bounding.BoundingBox;

import com.jme3.light.DirectionalLight;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.scene.Geometry;

import com.jme3.scene.Mesh;

import com.jme3.scene.debug.WireBox;

import com.jme3.scene.shape.Sphere;







public class DrawCollisionBox extends SimpleApplication {



public static void main(String[] args) {

DrawCollisionBox app = new DrawCollisionBox();

app.start();

}



Geometry geom;

Geometry bx;

WireBox wbx;





@Override

public void simpleInitApp() {

Mesh sphr = new Sphere(10, 10, 1f);

geom = new Geometry("Sphere", sphr);

geom.scale(2,1,1); //check if scale works with bx correctly







//geom.setModelBound(bb);

wbx = new WireBox();

wbx.fromBoundingBox((BoundingBox) geom.getWorldBound());



Geometry bx = new Geometry("TheMesh", wbx);

Material mat_box = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

mat_box.setColor("m_Color", ColorRGBA.Blue);

bx.setMaterial(mat_box);

bx.updateModelBound();





rootNode.attachChild(bx);





Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");

geom.setMaterial(mat);

rootNode.attachChild(geom);





DirectionalLight dl = new DirectionalLight();

dl.setDirection(new Vector3f(-0.8f, -0.6f, -0.08f).normalizeLocal());

dl.setColor(new ColorRGBA(1,1,1,1));

rootNode.addLight(dl);



viewPort.setBackgroundColor(ColorRGBA.Gray);

flyCam.setMoveSpeed(30);



}





@Override

public void simpleUpdate(float tpf)

{

//float angle =0;

float angle= tpf*2f;

// angle %= FastMath.TWO_PI;





geom.move(0, angle, 0);

geom.rotate(0, angle, 0);

System.out.println(geom.getLocalRotation().getY());



}



}[/java]

You’re applying transforms to the geometry but not applying them to the bounding box geometry so obviously you won’t see them.

The “fromBoundingBox” method just takes the current data of the bounding box so if anything changes after that you won’t see it

But when I make such an operation in the simpleUpdate():

[java]bx.rotate(0, angle, 0);[/java]

or

[java]bx.setLocalRotation(geom.getLocalRotation());

[/java]





I get such an exceptin:



INFO: Child (TheMesh) attached to this node (Root Node)

Sep 11, 2011 3:38:50 PM com.jme3.material.MaterialDef

INFO: Loaded material definition: Phong Lighting

Sep 11, 2011 3:38:50 PM com.jme3.scene.Node attachChild

INFO: Child (Sphere) attached to this node (Root Node)

Sep 11, 2011 3:38:50 PM com.jme3.app.Application handleError

SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]

java.lang.NullPointerException

at BasicExamples.DrawCollisionBox.simpleUpdate(DrawCollisionBox.java:76)

at com.jme3.app.SimpleApplication.update(SimpleApplication.java:255)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:144)

at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:218)

at java.lang.Thread.run(Thread.java:662)

That’s because you’re re-declaring “Geometry bx” in your simpleInitApp(). You’re not actually setting the “bx” variable in object itself. This is basic Java functionality and is expected …

Oh, I did not see it. THANK YOU VERY MUCH AND SORRY FOR YOUR SPENT TIME!

You also need to nest both the Geometry and the WireBox into a Node (pivotPoint). Creates a much more cleaner scene graph structure:

[patch]

rootNode

|

pivotPoint

|

+

+


+
+
| |
wirebox geom
[/patch]

Then animate the pivotPoint

something like this:
[java]import com.jme3.app.SimpleApplication;
import com.jme3.bounding.BoundingBox;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.debug.WireBox;
import com.jme3.scene.shape.Sphere;

public class DrawCollisionBox extends SimpleApplication {

public static void main(String[] args) {
DrawCollisionBox app = new DrawCollisionBox();
app.start();
}


Node pivotPoint;

@Override
public void simpleInitApp() {
Geometry geom;
Geometry bx;
WireBox wbx;
pivotPoint = new Node("Pivot Point");

Mesh sphr = new Sphere(10, 10, 1f);
geom = new Geometry("Sphere", sphr);
geom.scale(2, 1, 1); // check if scale works with bx correctly

// geom.setModelBound(bb);
wbx = new WireBox();
wbx.fromBoundingBox((BoundingBox) geom.getWorldBound());

bx = new Geometry("TheMesh", wbx);
Material mat_box = new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md");
mat_box.setColor("m_Color", ColorRGBA.Blue);
bx.setMaterial(mat_box);
bx.updateModelBound();

pivotPoint.attachChild(bx);


Material mat = new Material(assetManager,
"Common/MatDefs/Light/Lighting.j3md");
geom.setMaterial(mat);

pivotPoint.attachChild(geom);


DirectionalLight dl = new DirectionalLight();
dl.setDirection(new Vector3f(-0.8f, -0.6f, -0.08f).normalizeLocal());
dl.setColor(new ColorRGBA(1, 1, 1, 1));
rootNode.addLight(dl);

viewPort.setBackgroundColor(ColorRGBA.Gray);
flyCam.setMoveSpeed(30);

rootNode.attachChild(pivotPoint);

}

@Override
public void simpleUpdate(float tpf) {
// float angle =0;
float angle = tpf * 2f;
// angle %= FastMath.TWO_PI;

pivotPoint.move(0, angle, 0);
pivotPoint.rotate(0, angle, 0);
System.out.println(pivotPoint.getLocalRotation().getY());

}

}[/java]

Why don’t you place all of them in a Node and translate/rotate the the node as you want…

@simar.i3r said: Why don't you place all of them in a Node and translate/rotate the the node as you want..

…given that this thread is two years old, I suspect the OP has already moved on to other things. :slight_smile: