How to see the wireframe of the bounds ? (of the BoundingVolume) jme3 r7301

Hello, I’m looking around trying to find how to show the bounding as wireframe(currently is invisible), I believe in jme2 there was a key to show/hide that (key_T or O ?)

Looked here: https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:debugging

and on the forum…

I admit I was searching rather superficially … someone that knows just say how please :slight_smile:

I think theres WireBox.fromBoundingVolume or something similar… So you have to create the mesh and geometry yourself.

1 Like

good to know there is no builtin way…

If I understand correctly each Mesh has a BoundingVolume (either a BoundingBox or a BoundingSphere) though these do not represent Meshes, they are just numbers/math

So in order to show one, I’d have to create a WireBox as you said from a BoundingVolume, however since I do want to check for collisions, I’d have to avoid using a WireBox (since it has no surfaces, as I understand it, it’s just lines), therefore I’d use a Box or a Sphere…

that’s not so bad, I’ll see what I can do

PS: I did see the fromBoundingBox on WireBox,

brb, something is killing my programs without notice

Just attach the shapes you want to collide with to one node and the debug shapes to another node and do the collision check on the first node. I dont know if wireboxes collide tho, they are just lines and thus have no dimension that you could click…

1 Like

but if I then change the original shapes, how could I trigger that to change my debug shape also? Control? or is there some other way, I’d hate to have it run update every frame, I’d want it to do so only when original shape changes … is there such thing in jme3 ? very similar to Control I mean

EDIT: I also need this to make sure I’m applying my transforms to nodes which although children of other nodes I want to keep them at fixed positions in world space, regardless of parents’ transforms applying on them, doing this requires recalculations only when any of the parents change transform, I’d very much love to have a hook on that, that is, if already exists, but other than Control :)) as I said, don’t like having my update called on every frame, I only need it called when parent changed

EDIT2: actually the hook concept is called listener in java :slight_smile: Must get me a listener onTransformChange for a Spatial ?



the WireBox seems to collide only at edges (the wires which appear to be contained in small boxes? kinda guessing… due to how they collide near their wires)

I am using a Box, works fine, but I need a way to keep them connected other than making sure I only transform the parent node(which contains both the original and it’s bounding debug shape).

this is pretty much what I have (been playing with):

http://i.imgur.com/hoXXF.jpg

[java]package org.jme3.forum2;

/*

  • Copyright © 2009-2010 jMonkeyEngine
  • All rights reserved.

    *
  • Redistribution and use in source and binary forms, with or without
  • modification, are permitted provided that the following conditions are
  • met:

    *
    • Redistributions of source code must retain the above copyright
  • notice, this list of conditions and the following disclaimer.

    *
    • Redistributions in binary form must reproduce the above copyright
  • notice, this list of conditions and the following disclaimer in the
  • documentation and/or other materials provided with the distribution.

    *
    • Neither the name of ‘jMonkeyEngine’ nor the names of its contributors
  • may be used to endorse or promote products derived from this software
  • without specific prior written permission.

    *
  • THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  • "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  • TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  • PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  • CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  • EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  • PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  • PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  • LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  • NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  • SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    /

    import java.util.prefs.BackingStoreException;

    import com.jme3.app.SimpleApplication;

    import com.jme3.bounding.BoundingBox;

    import com.jme3.bounding.BoundingVolume;

    import com.jme3.collision.CollisionResult;

    import com.jme3.collision.CollisionResults;

    import com.jme3.light.DirectionalLight;

    import com.jme3.material.Material;

    import com.jme3.math.ColorRGBA;

    import com.jme3.math.FastMath;

    import com.jme3.math.Quaternion;

    import com.jme3.math.Ray;

    import com.jme3.math.Transform;

    import com.jme3.math.Vector3f;

    import com.jme3.scene.Geometry;

    import com.jme3.scene.Node;

    import com.jme3.scene.Spatial;

    import com.jme3.scene.debug.Arrow;

    import com.jme3.scene.shape.Box;

    import com.jme3.scene.shape.Line;

    import com.jme3.system.AppSettings;

    public class TestMousePickAgain2 extends SimpleApplication {

    public static void main(String[] args) throws BackingStoreException {

    TestMousePickAgain2 app = new TestMousePickAgain2();

    AppSettings aps = new AppSettings(true);

    aps.load(aps.getTitle());

    aps.setVSync(true);

    app.setShowSettings(false);

    app.setSettings(aps);

    app.start();

    }

    Node shootables;

    Geometry mark;

    private final Vector3f marksScale = new Vector3f(4, 4, 10f);

    @Override

    public void simpleInitApp() {

    flyCam.setDragToRotate(true);

    flyCam.setMoveSpeed(20f);

    initMark();

    /
    * create four colored boxes and a floor to shoot at: /

    shootables = new Node(“Shootables”);

    rootNode.attachChild(shootables);

    // shootables.attachChild(makeCube(“a Dragon”, -2f, 0f, 1f));

    // shootables.attachChild(makeCube(“a tin can”, 1f, -2f, 0f));

    // shootables.attachChild(makeCube(“the Sheriff”, 0f, 1f, -2f));

    // shootables.attachChild(makeCube(“the Deputy”, 1f, 0f, -4f));

    shootables.attachChild(makeFloor());

    shootables.attachChild(makeCharacter());

    rootNode.scale(3.5f, 4.2f, 4.7f);

    rootNode.rotate(FastMath.DEG_TO_RAD * 65f, FastMath.DEG_TO_RAD * 65f,

    FastMath.DEG_TO_RAD * 65f);

    rootNode.setLocalTranslation(0, 0, -29);

    cam.setLocation(new Vector3f(1.4989337f, 4.4191055f, 73.00994f));

    cam.setRotation(new Quaternion(-0.0011200219f, 0.9985451f,

    -0.022919897f, -0.048795838f));

    }

    @Override

    public void simpleUpdate(float tpf) {

    Vector3f origin = cam.getWorldCoordinates(

    inputManager.getCursorPosition(), 0.0f);

    Vector3f direction = cam.getWorldCoordinates(

    inputManager.getCursorPosition(), 0.3f);

    // System.out.println("origin: " + origin + " / dir: " + direction);

    direction.subtractLocal(origin).normalizeLocal();

    Ray ray = new Ray(origin, direction);

    CollisionResults results = new CollisionResults();

    shootables.collideWith(ray, results);

    if (results.size() > 0) {

    CollisionResult closest = results.getClosestCollision();

    Vector3f contact = closest.getContactPoint();

    Vector3f normal = closest.getContactNormal();

    contact = rootNode.worldToLocal(contact, null);

    rootNode.attachChild(mark);

    mark.setLocalTranslation(contact);

    Vector3f upVec = rootNode.worldToLocal(Vector3f.UNIT_Y, null);

    Quaternion q = new Quaternion();

    // makes Z axis be in the same direction as normal

    // (our mark arrow is on the Z axis)

    q.lookAt(normal, upVec.normalize());

    q = mark.getParent().getWorldRotation().inverse().mult(q);

    mark.setLocalRotation(q);

    // if I want to keep mark’s scale to 1, regardless of parents’

    // transforms:

    mark.setLocalScale(marksScale.divide(mark.getParent()

    .getWorldScale()));

    } else {

    rootNode.detachChild(mark);

    }

    }

    /
    * A cube object for target practice /

    protected Geometry makeCube(String name, float x, float y, float z) {

    Box box = new Box(new Vector3f(x, y, z), 1, 1, 1);

    Geometry cube = new Geometry(name, box);

    Material mat1 = new Material(assetManager,

    “Common/MatDefs/Misc/ShowNormals.j3md”);

    // mat1.setColor(“Color”, ColorRGBA.randomColor());

    cube.setMaterial(mat1);

    return cube;

    }

    /
    * A floor to show that the “shot” can go through several objects. /

    protected Geometry makeFloor() {

    Box box = new Box(new Vector3f(0, -4, -5), 15, .2f, 15);

    Geometry floor = new Geometry(“the Floor”, box);

    Material mat1 = new Material(assetManager,

    “Common/MatDefs/Misc/SolidColor.j3md”);

    mat1.setColor(“Color”, ColorRGBA.Gray);

    floor.setMaterial(mat1);

    return floor;

    }

    /
    * A red ball that marks the last spot that was “hit” by the “shot”. */

    protected void initMark() {

    Arrow arrow = new Arrow(Vector3f.UNIT_Z.mult(2f));

    arrow.setLineWidth(3);

    mark = new Geometry(“markGeo”, arrow);

    Material mark_mat = new Material(assetManager,

    “Common/MatDefs/Misc/SolidColor.j3md”);

    mark_mat.setColor(“Color”, ColorRGBA.Red);

    mark.setMaterial(mark_mat);

    }

    protected Spatial makeCharacter() {

    Node charNode = new Node();

    // load a character from jme3test-test-data

    Spatial golem = assetManager.loadModel(“Models/Oto/Oto.mesh.xml”);

    charNode.attachChild(golem);

    golem.setLocalScale(0.5f);

    golem.setLocalTranslation(-1.0f, -1.5f, -0.6f);

    BoundingVolume bv = golem.getWorldBound();

    if (bv.getType() == BoundingVolume.Type.AABB) {

    // WireBox boundingMesh =

    // new WireBox();

    // boundingMesh.fromBoundingBox( bbox );

    BoundingBox boundingBox = (BoundingBox) bv;

    Box boundingMesh = new Box(boundingBox.getCenter(),

    boundingBox.getXExtent(), boundingBox.getYExtent(),

    boundingBox.getZExtent());

    Geometry boundingGeo = new Geometry(“golem’s bounding volume”,

    boundingMesh);

    Material boundingMat = new Material(assetManager,

    “Common/MatDefs/Misc/WireColor.j3md”);

    boundingMat.setColor(“Color”, ColorRGBA.Red);

    boundingGeo.setMaterial(boundingMat);

    charNode.attachChild(boundingGeo);

    }

    // We must add a light to make the model visible

    DirectionalLight sun = new DirectionalLight();

    sun.setDirection(new Vector3f(-0.1f, -0.7f, -1.0f).normalizeLocal());

    golem.addLight(sun);

    // golem.setLocalScale(0.8f);//XXX: when this, bbox remains

    charNode.setLocalScale(3, 4, 5);// when this, they both scale

    return charNode;

    }

    }[/java]

hmm interesting… wireframe everything:

originally from here: http://hub.jmonkeyengine.org/groups/development-discussion-jme3/forum/topic/wireframe/#post-103425



http://i.imgur.com/7I7lJ.jpg

code now:

[java]package org.jme3.forum2;



/*

  • Copyright © 2009-2010 jMonkeyEngine
  • All rights reserved.

    *
  • Redistribution and use in source and binary forms, with or without
  • modification, are permitted provided that the following conditions are
  • met:

    *
    • Redistributions of source code must retain the above copyright
  • notice, this list of conditions and the following disclaimer.

    *
    • Redistributions in binary form must reproduce the above copyright
  • notice, this list of conditions and the following disclaimer in the
  • documentation and/or other materials provided with the distribution.

    *
    • Neither the name of ‘jMonkeyEngine’ nor the names of its contributors
  • may be used to endorse or promote products derived from this software
  • without specific prior written permission.

    *
  • THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  • "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  • TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  • PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  • CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  • EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  • PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  • PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  • LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  • NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  • SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    /

    import java.util.prefs.BackingStoreException;



    import com.jme3.app.SimpleApplication;

    import com.jme3.asset.AssetManager;

    import com.jme3.bounding.BoundingBox;

    import com.jme3.bounding.BoundingVolume;

    import com.jme3.collision.CollisionResult;

    import com.jme3.collision.CollisionResults;

    import com.jme3.light.DirectionalLight;

    import com.jme3.material.Material;

    import com.jme3.math.ColorRGBA;

    import com.jme3.math.FastMath;

    import com.jme3.math.Quaternion;

    import com.jme3.math.Ray;

    import com.jme3.math.Vector3f;

    import com.jme3.post.SceneProcessor;

    import com.jme3.renderer.RenderManager;

    import com.jme3.renderer.ViewPort;

    import com.jme3.renderer.queue.RenderQueue;

    import com.jme3.scene.Geometry;

    import com.jme3.scene.Node;

    import com.jme3.scene.Spatial;

    import com.jme3.scene.debug.Arrow;

    import com.jme3.scene.shape.Box;

    import com.jme3.system.AppSettings;

    import com.jme3.texture.FrameBuffer;



    public class TestMousePickAgain3 extends SimpleApplication {



    public class WireProcessor implements SceneProcessor {



    RenderManager renderManager;

    Material wireMaterial;



    public WireProcessor(AssetManager manager) {

    wireMaterial = new Material(manager,

    “/Common/MatDefs/Misc/WireColor.j3md”);

    wireMaterial.setColor(“m_Color”, ColorRGBA.Green);

    }



    @Override

    public void initialize(RenderManager rm, ViewPort vp) {

    renderManager = rm;

    }



    @Override

    public void reshape(ViewPort vp, int w, int h) {

    }



    @Override

    public boolean isInitialized() {

    return renderManager != null;

    }



    @Override

    public void preFrame(float tpf) {

    }



    @Override

    public void postQueue(RenderQueue rq) {

    renderManager.setForcedMaterial(wireMaterial);

    }



    @Override

    public void postFrame(FrameBuffer out) {

    renderManager.setForcedMaterial(null);

    }



    @Override

    public void cleanup() {

    renderManager.setForcedMaterial(null);

    }

    }



    public static void main(String[] args) throws BackingStoreException {

    TestMousePickAgain3 app = new TestMousePickAgain3();

    AppSettings aps = new AppSettings(true);

    aps.load(aps.getTitle());

    aps.setVSync(true);

    app.setShowSettings(false);

    app.setSettings(aps);



    app.start();

    // app.createCanvas();

    // app.startCanvas(true);

    // LwjglCanvas context = (LwjglCanvas) app.getContext();

    // Canvas c = context.getCanvas();

    // System.out.println©;

    // JFrame j = new JFrame();

    // j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // j.getContentPane().add©;

    // j.setVisible(true);

    // j.setBounds(0, 0, app.settings.getWidth(), app.settings.getHeight());

    }



    Node shootables;

    Geometry mark;

    private final Vector3f marksScale = new Vector3f(4, 4, 10f);



    @Override

    public void simpleInitApp() {

    viewPort.addProcessor(new WireProcessor(assetManager));

    flyCam.setDragToRotate(true);

    flyCam.setMoveSpeed(120f);

    initMark();

    /
    * create four colored boxes and a floor to shoot at: /

    shootables = new Node(“Shootables”);

    rootNode.attachChild(shootables);

    // shootables.attachChild(makeCube(“a Dragon”, -2f, 0f, 1f));

    // shootables.attachChild(makeCube(“a tin can”, 1f, -2f, 0f));

    // shootables.attachChild(makeCube(“the Sheriff”, 0f, 1f, -2f));

    // shootables.attachChild(makeCube(“the Deputy”, 1f, 0f, -4f));

    // shootables.attachChild(makeFloor());

    shootables.attachChild(makeCharacter());

    rootNode.scale(3.5f, 4.2f, 4.7f);

    rootNode.rotate(FastMath.DEG_TO_RAD * 65f, FastMath.DEG_TO_RAD * 65f,

    FastMath.DEG_TO_RAD * 65f);

    rootNode.setLocalTranslation(0, 0, -29);

    cam.setLocation(new Vector3f(1.4989337f, 4.4191055f, 73.00994f));

    cam.setRotation(new Quaternion(-0.0011200219f, 0.9985451f,

    -0.022919897f, -0.048795838f));

    }



    @Override

    public void simpleUpdate(



    float tpfOfOrigTimer) {

    Vector3f origin = cam.getWorldCoordinates(

    inputManager.getCursorPosition(), 0.0f);

    Vector3f direction = cam.getWorldCoordinates(

    inputManager.getCursorPosition(), 0.3f);

    // System.out.println("origin: " + origin + " / dir: " + direction);

    direction.subtractLocal(origin).normalizeLocal();

    Ray ray = new Ray(origin, direction);

    CollisionResults results = new CollisionResults();

    shootables.collideWith(ray, results);

    if (results.size() > 0) {

    CollisionResult closest = results.getClosestCollision();

    Vector3f contact = closest.getContactPoint();

    Vector3f normal = closest.getContactNormal();

    contact = rootNode.worldToLocal(contact, null);

    rootNode.attachChild(mark);

    mark.setLocalTranslation(contact);

    Vector3f upVec = rootNode.worldToLocal(Vector3f.UNIT_Y, null);

    Quaternion q = new Quaternion();

    // makes Z axis be in the same direction as normal

    // (our mark arrow is on the Z axis)

    q.lookAt(normal, upVec.normalize());

    q = mark.getParent().getWorldRotation().inverse().mult(q);

    mark.setLocalRotation(q);

    // if I want to keep mark’s scale to 1, regardless of parents’

    // transforms:

    mark.setLocalScale(marksScale.divide(mark.getParent()

    .getWorldScale()));

    } else {

    rootNode.detachChild(mark);

    }

    }



    /
    * A cube object for target practice /

    protected Geometry makeCube(String name, float x, float y, float z) {

    Box box = new Box(new Vector3f(x, y, z), 1, 1, 1);

    Geometry cube = new Geometry(name, box);

    Material mat1 = new Material(assetManager,

    “Common/MatDefs/Misc/ShowNormals.j3md”);

    // mat1.setColor(“Color”, ColorRGBA.randomColor());

    cube.setMaterial(mat1);

    return cube;

    }



    /
    * A floor to show that the “shot” can go through several objects. /

    protected Geometry makeFloor() {

    Box box = new Box(new Vector3f(0, -4, -5), 15, .2f, 15);

    Geometry floor = new Geometry(“the Floor”, box);

    Material mat1 = new Material(assetManager,

    “Common/MatDefs/Misc/SolidColor.j3md”);

    mat1.setColor(“Color”, ColorRGBA.Gray);

    floor.setMaterial(mat1);

    return floor;

    }



    /
    * A red ball that marks the last spot that was “hit” by the “shot”. */

    protected void initMark() {

    Arrow arrow = new Arrow(Vector3f.UNIT_Z.mult(2f));

    arrow.setLineWidth(3);

    mark = new Geometry(“markGeo”, arrow);

    Material mark_mat = new Material(assetManager,

    “Common/MatDefs/Misc/SolidColor.j3md”);

    mark_mat.setColor(“Color”, ColorRGBA.Red);

    mark.setMaterial(mark_mat);

    }



    protected Spatial makeCharacter() {

    Node charNode = new Node();

    // load a character from jme3test-test-data

    Spatial golem = assetManager.loadModel(“Models/Oto/Oto.mesh.xml”);

    charNode.attachChild(golem);

    golem.setLocalScale(0.5f);

    golem.setLocalTranslation(-1.0f, -1.5f, -0.6f);

    BoundingVolume bv = golem.getWorldBound();

    if (bv.getType() == BoundingVolume.Type.AABB) {

    // WireBox boundingMesh =

    // new WireBox();

    // boundingMesh.fromBoundingBox( bbox );

    BoundingBox boundingBox = (BoundingBox) bv;



    Box boundingMesh = new Box(boundingBox.getCenter(),

    boundingBox.getXExtent(), boundingBox.getYExtent(),

    boundingBox.getZExtent());

    // boundingMesh.setMode( Mesh.Mode.Points );

    // boundingMesh.setMode( Mesh.Mode.Lines );

    // boundingMesh.setMode( Mesh.Mode.TriangleFan );

    // boundingMesh.setPointSize( 10f );

    Geometry boundingGeo = new Geometry(“golem’s bounding volume”,

    boundingMesh);

    Material boundingMat = new Material(assetManager,

    “Common/MatDefs/Misc/WireColor.j3md”);

    boundingMat.setColor(“Color”, ColorRGBA.Red);

    boundingGeo.setMaterial(boundingMat);

    charNode.attachChild(boundingGeo);

    }

    // We must add a light to make the model visible

    DirectionalLight sun = new DirectionalLight();

    sun.setDirection(new Vector3f(-0.1f, -0.7f, -1.0f).normalizeLocal());

    golem.addLight(sun);

    // golem.setLocalScale(0.8f);//XXX: when this, bbox remains

    charNode.setLocalScale(3, 4, 5);// when this, they both scale



    return charNode;

    }

    }

    [/java]