CollisionResult problem

Hello fellow coders,

I’ve tried to integrate the raycollision example in the hellocollision example (with the town.zip level) and everything seems to work fine, except for the returned ContactPoint of the (nearest) collision. This one is way of course, so I’m wondering if there’s a bug in place or that I’m making a newbmistake.



Any help is very much appreciated!



[java]package mygame;



import com.fluendo.utils.Debug;

import com.jme3.app.SimpleBulletApplication;

import com.jme3.asset.plugins.ZipLocator;

import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;

import com.jme3.bullet.collision.shapes.CompoundCollisionShape;

import com.jme3.bullet.nodes.PhysicsCharacterNode;

import com.jme3.bullet.nodes.PhysicsNode;

import com.jme3.bullet.util.CollisionShapeFactory;

import com.jme3.collision.CollisionResult;

import com.jme3.collision.CollisionResults;

import com.jme3.font.BitmapText;

import com.jme3.input.KeyInput;

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.renderer.ViewPort;

import com.jme3.renderer.queue.RenderQueue.ShadowMode;

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.Sphere;

import com.jme3.shadow.BasicShadowRenderer;



/**

  • Example 9 - How to make walls and floors solid.
  • This version uses Physics and a custom Action Listener.
  • @author normen, with edits by Zathras

    /

    public class Main

    extends SimpleBulletApplication

    implements ActionListener {



    Geometry mark;

    PhysicsNode levelNode;

    private Spatial gameScene;

    private PhysicsCharacterNode player;

    private Vector3f walkDirection = new Vector3f();

    private boolean left = false, right = false, up = false, down = false;



    public static void main(String[] args) {

    Main app = new Main();

    app.showSettings=false;

    app.start();

    }



    void addViewportAttributes(ViewPort view) {

    BasicShadowRenderer bsr = new BasicShadowRenderer(assetManager, 1024);

    bsr.setDirection(new Vector3f(-2.8f, -2.8f, -2.8f).normalize());

    view.addProcessor(bsr);

    }

    public void simpleInitApp() {

    renderer.setBackgroundColor(ColorRGBA.Cyan);

    // We re-use the flyby camera for rotation, while positioning is handled by physics

    flyCam.setMoveSpeed(100);

    setupKeys();

    addViewportAttributes(viewPort);



    // We add a light so we see the scene

    DirectionalLight dl = new DirectionalLight();

    dl.setColor(ColorRGBA.White.clone().multLocal(2));

    dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalize());

    rootNode.addLight(dl);



    // We load the scene from the zip file and adjust its size.

    assetManager.registerLocator(“town.zip”, ZipLocator.class.getName());

    gameScene = assetManager.loadModel(“main.scene”);

    gameScene.setLocalScale(2f);

    initMark();

    initCrossHairs();

    // We set up collision detection by creating a

    // compound collision shape and a physics node for the scene.

    CompoundCollisionShape sceneShape = CollisionShapeFactory.createMeshCompoundShape((Node) gameScene);

    levelNode = new PhysicsNode(gameScene, sceneShape, 0);

    levelNode.setShadowMode(ShadowMode.CastAndRecieve);

    // Here we set up collision detection for the player by creating

    // a capsule collision shape and a physics character node.

    // The physics character node offers extra settings for

    // size, stepheight, jumping, falling, and gravity.

    // We also put the player in its starting position.

    player = new PhysicsCharacterNode(new CapsuleCollisionShape(1.5f, 6f, 1), .05f);

    player.setJumpSpeed(20);

    player.setFallSpeed(30);

    player.setGravity(30);

    player.setLocalTranslation(new Vector3f(0, 10, 0));

    player.updateGeometricState();



    // We attach the scene and the player to the rootnode and the physics space,

    // to make them appear in the game world.

    rootNode.attachChild(levelNode);

    rootNode.attachChild(player);

    rootNode.updateGeometricState();

    getPhysicsSpace().add(levelNode);

    getPhysicsSpace().add(player);

    }



    /
    * We over-write some navigational key mappings here, so we can
  • add physics-controlled walking and jumping: /

    private void setupKeys() {

    inputManager.addMapping(“Lefts”, new KeyTrigger(KeyInput.KEY_A));

    inputManager.addMapping(“Rights”, new KeyTrigger(KeyInput.KEY_D));

    inputManager.addMapping(“Ups”, new KeyTrigger(KeyInput.KEY_W));

    inputManager.addMapping(“Downs”, new KeyTrigger(KeyInput.KEY_S));

    inputManager.addMapping(“Jumps”, new KeyTrigger(KeyInput.KEY_SPACE));

    inputManager.addListener(this, “Lefts”);

    inputManager.addListener(this, “Rights”);

    inputManager.addListener(this, “Ups”);

    inputManager.addListener(this, “Downs”);

    inputManager.addListener(this, “Jumps”);

    inputManager.addMapping(“Shoot”,

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

    new MouseButtonTrigger(0)); // trigger 2: left-button click

    inputManager.addListener(this, “Shoot”);

    }





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

    protected void initMark() {

    Sphere sphere = new Sphere(30, 30, 2f);

    mark = new Geometry(“BOOM!”, sphere);

    Material mark_mat = new Material(assetManager, “Common/MatDefs/Misc/SolidColor.j3md”);

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

    mark.setMaterial(mark_mat);

    }

    /
    * These are our custom actions triggered by key presses.
  • We do not walk yet, we just keep track of the direction the user pressed. */

    public void onAction(String binding, boolean value, float tpf) {

    if (binding.equals(“Lefts”)) {

    if (value) { left = true; } else { left = false; }

    } else if (binding.equals(“Rights”)) {

    if (value) { right = true; } else { right = false; }

    } else if (binding.equals(“Ups”)) {

    if (value) { up = true; } else { up = false; }

    } else if (binding.equals(“Downs”)) {

    if (value) { down = true; } else { down = false; }

    } else if (binding.equals(“Jumps”)) {

    player.jump();

    }else if (binding.equals(“Shoot”) && !value) {

    // 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.

    levelNode.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 + " at " + pt.toString());
//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());
Debug.warn(closest.getContactPoint().toString());
rootNode.attachChild(mark);
} else {
// No hits? Then remove the red mark.
rootNode.detachChild(mark);
}
}
}

/**
* This is the main event loop--walking happens here.
* We check in which direction the player is walking by interpreting
* the camera direction forward (camDir) and to the side (camLeft).
* The setWalkDirection() command is what lets a physics-controlled player walk.
* We also make sure here that the camera moves with player.
*/
@Override
public void simpleUpdate(float tpf) {
Vector3f camDir = cam.getDirection().clone().multLocal(0.6f);
Vector3f camLeft = cam.getLeft().clone().multLocal(0.4f);
walkDirection.set(0, 0, 0);
if (left) { walkDirection.addLocal(camLeft); }
if (right) { walkDirection.addLocal(camLeft.negate()); }
if (up) { walkDirection.addLocal(camDir); }
if (down) { walkDirection.addLocal(camDir.negate()); }
player.setWalkDirection(walkDirection);
cam.setLocation(player.getLocalTranslation());
}
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.setColor(ColorRGBA.White);
ch.setLocalTranslation( // center
settings.getWidth()/2 - guiFont.getCharSet().getRenderedSize()/3*2,
settings.getHeight()/2 + ch.getLineHeight()/2, 0);
guiNode.attachChild(ch);
}
}
[/java]

It should be ok, do you use the latest nightly or svn version or alpha-2? Some bugs in the collision system have been fixed lately. When using jMP, you can update to the latest nightly version easily via Tools->Plugins->Settings (see jMP help).

Cheers,

Normen

Thanks for your quick reply. I’ve tried to update as much as possible:

Installed version:0.6.0.5767 Available version:0.6.0.5920

Although the latest update for some reason won’t properly update (it keeps asking me to update even after update took place).

However, I’m still having the same problem. Any ideas?

try this one. I’ve already do some editing and it’s work now.



[java]package main;



import com.fluendo.utils.Debug;

import com.jme3.app.SimpleBulletApplication;

import com.jme3.asset.plugins.ZipLocator;

import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;

import com.jme3.bullet.collision.shapes.CompoundCollisionShape;

import com.jme3.bullet.nodes.PhysicsCharacterNode;

import com.jme3.bullet.nodes.PhysicsNode;

import com.jme3.bullet.util.CollisionShapeFactory;

import com.jme3.collision.CollisionResult;

import com.jme3.collision.CollisionResults;

import com.jme3.font.BitmapText;

import com.jme3.input.KeyInput;

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.renderer.ViewPort;

import com.jme3.renderer.queue.RenderQueue.ShadowMode;

import com.jme3.scene.Geometry;

import com.jme3.scene.Node;

import com.jme3.scene.Spatial;

import com.jme3.scene.shape.Sphere;

import com.jme3.shadow.BasicShadowRenderer;



/**

  • Example 9 - How to make walls and floors solid.
  • This version uses Physics and a custom Action Listener.
  • @author normen, with edits by Zathras

    /

    public class test3

    extends SimpleBulletApplication

    implements ActionListener {



    Geometry mark;

    PhysicsNode levelNode;

    private Spatial gameScene;

    private PhysicsCharacterNode player;

    private Vector3f walkDirection = new Vector3f();

    private boolean left = false, right = false, up = false, down = false;



    public static void main(String[] args) {

    test3 app = new test3();

    app.showSettings=false;

    app.start();

    }



    void addViewportAttributes(ViewPort view) {

    BasicShadowRenderer bsr = new BasicShadowRenderer(assetManager, 1024);

    bsr.setDirection(new Vector3f(-2.8f, -2.8f, -2.8f).normalize());

    view.addProcessor(bsr);

    }

    public void simpleInitApp() {

    renderer.setBackgroundColor(ColorRGBA.Cyan);

    // We re-use the flyby camera for rotation, while positioning is handled by physics

    flyCam.setMoveSpeed(100);

    setupKeys();

    addViewportAttributes(viewPort);



    // We add a light so we see the scene

    DirectionalLight dl = new DirectionalLight();

    dl.setColor(ColorRGBA.White.clone().multLocal(2));

    dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalize());

    rootNode.addLight(dl);



    // We load the scene from the zip file and adjust its size.

    assetManager.registerLocator(“town.zip”, ZipLocator.class.getName());

    gameScene = assetManager.loadModel(“main.scene”);

    gameScene.setLocalScale(2f);

    initMark();

    initCrossHairs();

    // We set up collision detection by creating a

    // compound collision shape and a physics node for the scene.

    CompoundCollisionShape sceneShape = CollisionShapeFactory.createMeshCompoundShape((Node) gameScene);

    levelNode = new PhysicsNode(gameScene, sceneShape, 0);

    levelNode.setShadowMode(ShadowMode.CastAndReceive);

    // Here we set up collision detection for the player by creating

    // a capsule collision shape and a physics character node.

    // The physics character node offers extra settings for

    // size, stepheight, jumping, falling, and gravity.

    // We also put the player in its starting position.

    player = new PhysicsCharacterNode(new CapsuleCollisionShape(1.5f, 6f, 1), .05f);

    player.setJumpSpeed(20);

    player.setFallSpeed(30);

    player.setGravity(30);

    player.setLocalTranslation(new Vector3f(0, 10, 0));

    player.updateGeometricState();



    // We attach the scene and the player to the rootnode and the physics space,

    // to make them appear in the game world.

    rootNode.attachChild(levelNode);

    rootNode.attachChild(player);

    rootNode.updateGeometricState();

    getPhysicsSpace().add(levelNode);

    getPhysicsSpace().add(player);

    }



    /
    * We over-write some navigational key mappings here, so we can
  • add physics-controlled walking and jumping: /

    private void setupKeys() {

    inputManager.addMapping(“Lefts”, new KeyTrigger(KeyInput.KEY_A));

    inputManager.addMapping(“Rights”, new KeyTrigger(KeyInput.KEY_D));

    inputManager.addMapping(“Ups”, new KeyTrigger(KeyInput.KEY_W));

    inputManager.addMapping(“Downs”, new KeyTrigger(KeyInput.KEY_S));

    inputManager.addMapping(“Jumps”, new KeyTrigger(KeyInput.KEY_SPACE));

    inputManager.addListener(this, “Lefts”);

    inputManager.addListener(this, “Rights”);

    inputManager.addListener(this, “Ups”);

    inputManager.addListener(this, “Downs”);

    inputManager.addListener(this, “Jumps”);

    inputManager.addMapping(“Shoot”,

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

    new MouseButtonTrigger(0)); // trigger 2: left-button click

    inputManager.addListener(this, “Shoot”);

    }



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

    protected void initMark() {

    Sphere sphere = new Sphere(30, 30, 2f);

    mark = new Geometry(“BOOM!”, sphere);

    Material mark_mat = new Material(assetManager, “Common/MatDefs/Misc/SolidColor.j3md”);

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

    mark.setMaterial(mark_mat);

    }

    /
    * These are our custom actions triggered by key presses.
  • We do not walk yet, we just keep track of the direction the user pressed. */

    public void onAction(String binding, boolean value, float tpf) {

    if (binding.equals(“Lefts”)) {

    if (value) { left = true; } else { left = false; }

    } else if (binding.equals(“Rights”)) {

    if (value) { right = true; } else { right = false; }

    } else if (binding.equals(“Ups”)) {

    if (value) { up = true; } else { up = false; }

    } else if (binding.equals(“Downs”)) {

    if (value) { down = true; } else { down = false; }

    } else if (binding.equals(“Jumps”)) {

    player.jump();

    } else if (binding.equals(“Shoot”) && !value) {

    // 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.

    levelNode.collideWith(ray, results);

    // 4. Print the results

    System.out.println("

Collisions? " + results.size() + "
");
for (int i = 0; i < results.size(); i++) {
// 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());
Debug.warn(closest.getContactPoint().toString());
rootNode.attachChild(mark);
}

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

/**
* This is the main event loop--walking happens here.
* We check in which direction the player is walking by interpreting
* the camera direction forward (camDir) and to the side (camLeft).
* The setWalkDirection() command is what lets a physics-controlled player walk.
* We also make sure here that the camera moves with player.
*/

@Override
public void simpleUpdate(float tpf) {
Vector3f camDir = cam.getDirection().clone().multLocal(0.6f);
Vector3f camLeft = cam.getLeft().clone().multLocal(0.4f);
walkDirection.set(0, 0, 0);
if (left) { walkDirection.addLocal(camLeft); }
if (right) { walkDirection.addLocal(camLeft.negate()); }
if (up) { walkDirection.addLocal(camDir); }
if (down) { walkDirection.addLocal(camDir.negate()); }
player.setWalkDirection(walkDirection);
cam.setLocation(player.getLocalTranslation());
}
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.setColor(ColorRGBA.White);
ch.setLocalTranslation( // center
settings.getWidth()/2 - guiFont.getCharSet().getRenderedSize()/3*2,
settings.getHeight()/2 + ch.getLineHeight()/2, 0);
guiNode.attachChild(ch);
}
}[/java]

There’s a part of your code missing, I guess it’s the essential part since I don’t see changes elsewhere:

[java] for (int i = 0; i 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);

}[/java]

Thanks for the quick reply though!

Topic can be closed :slight_smile: I finally fixed the issue by getting the latest nightly build installed, which was giving me trouble at first but now seems fine.

Thanks for the headsup.