Explicit updateModelBound()

Nope, I don’t ever set a bounding box. I rely on the auto-created ones. I tried to play around with the TestPicking class to reproduce, but I couldn’t. I could attempt to reproduce via a test case, but being Thanksgiving weekend in the states I’ll be hard pressed to find the time. Perhaps I can try to reproduce while I’m sitting at the in-laws…

Oh, not sure if this helps, but the Geometry that I’m using to attach to a Shape node is a simple Quad.

Ok, the problem is when using a Quad… I modified the HelloPicking code to reproduce. Note the Howdy-Geometry that is not pickable. Once you place upateModelBound() at the very end of simpleInitApp it all works.



[java]

package jme3test.helloworld;



import com.jme3.app.SimpleApplication;

import com.jme3.collision.CollisionResult;

import com.jme3.collision.CollisionResults;

import com.jme3.font.BitmapText;

import com.jme3.input.KeyInput;

import com.jme3.input.MouseInput;

import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.KeyTrigger;

import com.jme3.input.controls.MouseButtonTrigger;

import com.jme3.light.DirectionalLight;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Ray;

import com.jme3.math.Vector3f;

import com.jme3.scene.Geometry;

import com.jme3.scene.Node;

import com.jme3.scene.Spatial;

import com.jme3.scene.shape.Box;

import com.jme3.scene.shape.Quad;

import com.jme3.scene.shape.Sphere;



/** Sample 8 - how to let the user pick (select) objects in the scene

  • using the mouse or key presses. Can be used for shooting, opening doors, etc. /

    public class HelloPicking extends SimpleApplication {



    public static void main(String[] args) {

    HelloPicking app = new HelloPicking();

    app.start();

    }

    Node shootables;

    Geometry mark;



    @Override

    public void simpleInitApp() {

    initCrossHairs(); // a "+" in the middle of the screen to help aiming

    initKeys(); // load custom key mappings

    initMark(); // a red sphere to mark the hit



    /
    * 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));

    Node node = new Node("Howdy-Node");

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

    mat1.setColor("Color", ColorRGBA.randomColor());

    Geometry geo = new Geometry("Howdy-Geometry", new Quad(16, 16));

    geo.setMaterial(mat1);

    node.attachChild(geo);

    shootables.attachChild(node);

    shootables.attachChild(makeFloor());

    shootables.attachChild(makeCharacter());

    }



    /
    * Declaring the "Shoot" action and mapping to its triggers. /

    private void initKeys() {

    inputManager.addMapping("Shoot",

    new KeyTrigger(KeyInput.KEY_SPACE), // trigger 1: spacebar

    new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); // trigger 2: left-button click

    inputManager.addListener(actionListener, "Shoot");

    }

    /
    * Defining the "Shoot" action: Determine what was hit and how to respond. */

    private ActionListener actionListener = new ActionListener() {



    public void onAction(String name, boolean keyPressed, float tpf) {

    if (name.equals("Shoot") && !keyPressed) {

    // 1. Reset results list.

    CollisionResults results = new CollisionResults();

    // 2. Aim the ray from cam loc to cam direction.

    Ray ray = new Ray(cam.getLocation(), cam.getDirection());

    // 3. Collect intersections between Ray and Shootables in results list.

    shootables.collideWith(ray, results);

    // 4. Print the results

    System.out.println("

Collisions? " + results.size() + "
");
for (int i = 0; i < results.size(); i++) {
// For each hit, we know distance, impact point, name of geometry.
float dist = results.getCollision(i).getDistance();
Vector3f pt = results.getCollision(i).getContactPoint();
String hit = results.getCollision(i).getGeometry().getName();
System.out.println("* Collision #" + i);
System.out.println(" You shot " + hit + " at " + pt + ", " + dist + " wu away.");
}
// 5. Use the results (we mark the hit object)
if (results.size() > 0) {
// The closest collision point is what was truly hit:
CollisionResult closest = results.getClosestCollision();
// Let's interact - we mark the hit with a red dot.
mark.setLocalTranslation(closest.getContactPoint());
rootNode.attachChild(mark);
} else {
// No hits? Then remove the red mark.
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/Unshaded.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/Unshaded.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() {
Sphere sphere = new Sphere(30, 30, 0.2f);
mark = new Geometry("BOOM!", sphere);
Material mark_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mark_mat.setColor("Color", ColorRGBA.Red);
mark.setMaterial(mark_mat);
}

/** A centred plus sign to help the player aim. */
protected void initCrossHairs() {
guiNode.detachAllChildren();
guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
BitmapText ch = new BitmapText(guiFont, false);
ch.setSize(guiFont.getCharSet().getRenderedSize() * 2);
ch.setText("+"); // crosshairs
ch.setLocalTranslation( // center
settings.getWidth() / 2 - guiFont.getCharSet().getRenderedSize() / 3 * 2,
settings.getHeight() / 2 + ch.getLineHeight() / 2, 0);
guiNode.attachChild(ch);
}

protected Spatial makeCharacter() {
// load a character from jme3test-test-data
Spatial golem = assetManager.loadModel("Models/Oto/Oto.mesh.xml");
golem.scale(0.5f);
golem.setLocalTranslation(-1.0f, -1.5f, -0.6f);

// We must add a light to make the model visible
DirectionalLight sun = new DirectionalLight();
sun.setDirection(new Vector3f(-0.1f, -0.7f, -1.0f));
golem.addLight(sun);
return golem;
}
}
[/java]
1 Like

Something weird is definitely going on. I also invoke @Momoko_Fan. He might know instantly what the issue is. It will be weeks before I have time to drill into this one.



I do know that I pick quads all the time in the guiNode… so it’s weird.

I hope I am trying this test case correctly … You’re saying the big quad at the top right is not pickable? It works fine for me.



[java]


Collisions? 1
* Collision #0
You shot Howdy-Geometry at (4.9196467, 8.032974, 9.536743E-7), 14.475057 wu away.
Collisions? 1
* Collision #0
You shot Howdy-Geometry at (4.2045527, 7.0469847, 0.0), 14.012144 wu away.
Collisions? 1
* Collision #0
You shot Howdy-Geometry at (4.4958572, 6.5209355, 0.0), 14.099041 wu away.
Collisions? 1
* Collision #0
You shot Howdy-Geometry at (5.5708756, 6.083879, 0.0), 14.603153 wu away.
Collisions? 1
* Collision #0
You shot Howdy-Geometry at (7.233628, 5.5384693, 9.536743E-7), 15.521069 wu away.
Collisions? 1
* Collision #0
You shot Howdy-Geometry at (8.252203, 6.3881326, 0.0), 16.165834 wu away.[/java]

I didn't put any updateModelBound() statements, the test case is run as-is. This is using latest jME3 nightly

Odd, I tried again and you’re right Momoko, the test case does work. Taking a closer look at any differences between the test case and my code in the game client, I found this:



[java]

Vector3f origin = cam.getWorldCoordinates(inputManager.getCursorPosition(), 0.0f);

Vector3f direction = cam.getWorldCoordinates(inputManager.getCursorPosition(), .3f);

direction.subtractLocal(origin).normalizeLocal();



Ray ray = new Ray(origin, direction);

[/java]



I changed the direction line to:

[java]Vector3f direction = cam.getWorldCoordinates(inputManager.getCursorPosition(), 1f);[/java]



and it all works now. Odd that using .3f always worked for me until I updated, but I’m glad that changing that value to 1f fixed the issue for me.



Thanks!