GeometryBatchFactory picking problem

cyuczieekc said:
@normen:
====
I wonder what's @xp61 doing, I really am :) I'm kind of bidding my time waiting... (not to imply any obligations though)

i wouldn't hold your breath, might be a few days ;)
1 Like

okay i’ve narrowed down the problem (i’ve also updated all plugins/nightly build),

the geometry i had been using was a hexagonal shape imported from blender constructed like so,

http://www.geometryatlas.com/entries/187

when i merge duplicates of these into a single object, the collision problems happen.

i tried replacing the hexagonal shape with a simple quad for testing, and there doesn’t seem to be a problem.

so there’s something in the construction of my hexagon shapes, or something in blender, which is screwing with raycasting when all the shapes are merged into a single object. (but they work fine when not merged…)

well i reconstructed my own hexagon shape internally (not imported) - and the problem persists,



depending on how i scale/translate things before optimizing seems to be the problem,

so transformations seem to be screwing with collision detection on objects that have been optimised into a single mesh.



trying now to locate specific instance of the problem…

if you could isolate that into a simple testcase that we can also run, it may actually save you some time, just copy paste around some code and maybe make a testcase? up to you, but really I believe it may save time… with a testcase we’d be like 3 people trying to track down the problem, not to mention it’s simpler than what you have due to it being a testcase as opposed to your entire project :slight_smile:

Please consider taking the time to make one…

yeah i’ll see what i can do, thanks.

mmmmmm may have got to the source of the problem…



it seems if i do a complete 360 rotation of my geometry in all directions before applying any further transformations, the problems go away

like so



hex.rotate((FastMath.PI * 2),(FastMath.PI * 2),(FastMath.PI * 2));



will double check this further…

that is somewhat odd…

does it work if you replace that rotation with

[java]hex.getWorldTranslation(); [/java]

which calls checkDoTransformUpdate();

cyuczieekc said:
that is somewhat odd...
does it work if you replace that rotation with
[java]hex.getWorldTranslation(); [/java]
which calls checkDoTransformUpdate();


no... just tried it there..

i’m afraid i’m back to square one,



i noticed that as i moved away from the world origin vertically(y), the problem starts up again, although seems fine when i move around just horizontally (x,z).



i’ll put together a test case…

okay here’s my test case - it’s a full main.java file…



when you run it move the camera forward and look down to see the blue tiles,

then keep shooting with space/click to place the red marker,

you need to keep repeating this about 10 / 20 times , and on different blue tiles, before the raycasting misses one.





[java]

package mygame;



import com.jme3.app.SimpleApplication;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.renderer.RenderManager;

import com.jme3.scene.Geometry;

import com.jme3.scene.shape.Box;

import com.jme3.scene.shape.Sphere;



import com.jme3.scene.Node;

import com.jme3.scene.Mesh;



import com.jme3.math.Vector3f;

import com.jme3.math.Vector2f;



import com.jme3.util.BufferUtils;

import java.nio.FloatBuffer;

import com.jme3.scene.VertexBuffer;

import com.jme3.scene.VertexBuffer.Type;



import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.KeyTrigger;

import com.jme3.input.controls.MouseButtonTrigger;

import com.jme3.math.Ray;

import com.jme3.input.KeyInput;



import com.jme3.font.BitmapText;

import com.jme3.collision.CollisionResult;

import com.jme3.collision.CollisionResults;

import com.jme3.math.Quaternion;



import jme3tools.optimize.GeometryBatchFactory;



/**

  • test
  • @author normenhansen

    */

    public class Main extends SimpleApplication {



    Geometry mark;



    public static void main(String[] args) {

    Main app = new Main();

    app.start();

    }



    @Override

    public void simpleInitApp() {



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



    //custome hex cap

    Mesh m = new Mesh();



    Vector3f[] vertices = new Vector3f[7];

    vertices[0] = new Vector3f(0.965926f, 0.166667f, 0.258819f);

    vertices[1] = new Vector3f(0.707107f, 0.166667f, -0.707107f);

    vertices[2] = new Vector3f(0.000000f, 0.166667f, 0.000000f);

    vertices[3] = new Vector3f(0.258819f, 0.166667f, 0.965926f);

    vertices[4] = new Vector3f(-0.707106f, 0.166667f, 0.707107f);

    vertices[5] = new Vector3f(-0.965926f, 0.166667f, -0.258818f);

    vertices[6] = new Vector3f(-0.258820f, 0.166667f, -0.965926f);



    Vector2f[] texCoord = new Vector2f[7];

    texCoord[0] = new Vector2f(1.000000f, 0.566988f);

    texCoord[1] = new Vector2f(0.750000f, 0.133975f);

    texCoord[2] = new Vector2f(0.500000f, 0.566987f);

    texCoord[3] = new Vector2f(0.750000f, 1.000000f);

    texCoord[4] = new Vector2f(0.250000f, 1.000000f);

    texCoord[5] = new Vector2f(0.000000f, 0.566987f);

    texCoord[6] = new Vector2f(0.250000f, 0.133975f);



    int[] indexes = {

    0, 1, 2,

    2, 3, 0,

    2, 4, 3,

    2, 5, 4,

    2, 6, 5,

    2, 1, 6

    };





    m.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(vertices));

    m.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord));

    m.setBuffer(Type.Index, 1, BufferUtils.createIntBuffer(indexes));

    m.createCollisionData();

    m.updateBound();



    Geometry geom = new Geometry("OurMesh", m);

    Node nd = new Node();



    nd.attachChild(geom);

    nd.scale(.5f);



    Material bluemat = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");

    bluemat.setColor("Color", ColorRGBA.Blue);

    geom.setMaterial(bluemat);

    Node grid = new Node();

    for (int x = 0; x < 3; x++) {

    for (int y = 0; y < 3; y++) {

    nd.setLocalTranslation(x, 0, y);

    nd.rotate(0, 2, 0);

    grid.attachChild(nd.clone());

    }

    }



    grid.move(0, -5, 0);



    Node newgrid = (Node) GeometryBatchFactory.optimize(grid);

    rootNode.attachChild(newgrid);



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





    initKeys();



    flyCam.setMoveSpeed(6f);





    }



    @Override

    public void simpleUpdate(float tpf) {

    //TODO: add update code

    }



    @Override

    public void simpleRender(RenderManager rm) {

    //TODO: add render code

    }



    private void initKeys() {

    inputManager.addMapping("Shoot", // Declare…

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

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

    inputManager.addListener(actionListener, "Shoot"); // … and add.

    }

    private ActionListener actionListener = new ActionListener() {



    @Override

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

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

    Node marker = new Node();

    marker.attachChild(mark);

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

    rootNode.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();

Geometry g = results.getCollision(i).getGeometry();
Node n1 = g.getParent();

int trino = results.getCollision(i).getTriangleIndex();
System.out.println("* Collision #" + i);
System.out.println(" You shot " + hit + " at " + pt + ", " + dist + " wu away. ");
System.out.println("* tri no" + trino);


}
// 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.
System.out.println("* closest parent " + closest.getGeometry().getParent().getParent().getName());


marker.setLocalTranslation(closest.getContactPoint());
rootNode.attachChild(marker);

System.out.println(" marked " + closest.getContactPoint());

} else {
// No hits? Then remove the red mark.
rootNode.detachChild(marker);
// sceneNode.updateGeometricState();
}
}
}
};
}
[/java]

I tried this, I’m not sure, but I kinda tried like 80 times, every time hit… maybe I’m not doing it right?

can you give me your camera location (pressing key C) and camera rotation from where you shoot at them? or even better when it missed

I used jme3 r7301

there we go, I replaced action with analog and added cam pos&rotation where there is a miss

just keep the left mouse button pressed when you move to see blinking where misses occur, but basically if you can keep the mouse steady at the start of the program and just left click you see it misses!

code below

http://i.imgur.com/babcT.png

http://i.imgur.com/vuSKp.png

[java]package org.jme3.forum2;

import com.jme3.app.SimpleApplication;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.renderer.RenderManager;

import com.jme3.scene.Geometry;

import com.jme3.scene.shape.Box;

import com.jme3.scene.shape.Sphere;

import com.jme3.scene.Node;

import com.jme3.scene.Mesh;

import com.jme3.math.Vector3f;

import com.jme3.math.Vector2f;

import com.jme3.util.BufferUtils;

import java.nio.FloatBuffer;

import com.jme3.scene.VertexBuffer;

import com.jme3.scene.VertexBuffer.Type;

import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.AnalogListener;

import com.jme3.input.controls.KeyTrigger;

import com.jme3.input.controls.MouseButtonTrigger;

import com.jme3.math.Ray;

import com.jme3.input.KeyInput;

import com.jme3.font.BitmapText;

import com.jme3.collision.CollisionResult;

import com.jme3.collision.CollisionResults;

import com.jme3.math.Quaternion;

import jme3tools.optimize.GeometryBatchFactory;

/**

  • test

    *
  • @author normenhansen

    */

    public class Main extends SimpleApplication {

    Geometry mark;

    public static void main(String[] args) {

    Main app = new Main();

    app.start();

    }

    @Override

    public void simpleInitApp() {

    cam.setLocation(new Vector3f(0.020104392f, -7.2130537f, 2.8410192f));

    cam.setRotation(new Quaternion(0.06470209f, 0.9191101f, -0.34940267f,

    0.17019996f));

    cam.setRotation(new Quaternion(0.0646277f, 0.9205545f, -0.34430403f,

    0.17279278f));

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

    // custome hex cap

    Mesh m = new Mesh();

    Vector3f[] vertices = new Vector3f[7];

    vertices[0] = new Vector3f(0.965926f, 0.166667f, 0.258819f);

    vertices[1] = new Vector3f(0.707107f, 0.166667f, -0.707107f);

    vertices[2] = new Vector3f(0.000000f, 0.166667f, 0.000000f);

    vertices[3] = new Vector3f(0.258819f, 0.166667f, 0.965926f);

    vertices[4] = new Vector3f(-0.707106f, 0.166667f, 0.707107f);

    vertices[5] = new Vector3f(-0.965926f, 0.166667f, -0.258818f);

    vertices[6] = new Vector3f(-0.258820f, 0.166667f, -0.965926f);

    Vector2f[] texCoord = new Vector2f[7];

    texCoord[0] = new Vector2f(1.000000f, 0.566988f);

    texCoord[1] = new Vector2f(0.750000f, 0.133975f);

    texCoord[2] = new Vector2f(0.500000f, 0.566987f);

    texCoord[3] = new Vector2f(0.750000f, 1.000000f);

    texCoord[4] = new Vector2f(0.250000f, 1.000000f);

    texCoord[5] = new Vector2f(0.000000f, 0.566987f);

    texCoord[6] = new Vector2f(0.250000f, 0.133975f);

    int[] indexes = { 0, 1, 2, 2, 3, 0, 2, 4, 3, 2, 5, 4, 2, 6, 5, 2, 1, 6 };

    m.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(vertices));

    m.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord));

    m.setBuffer(Type.Index, 1, BufferUtils.createIntBuffer(indexes));

    m.createCollisionData();

    m.updateBound();

    Geometry geom = new Geometry("OurMesh", m);

    Node nd = new Node();

    nd.attachChild(geom);

    nd.scale(.5f);

    Material bluemat = new Material(assetManager,

    "Common/MatDefs/Misc/SolidColor.j3md");

    bluemat.setColor("Color", ColorRGBA.Blue);

    geom.setMaterial(bluemat);

    Node grid = new Node();

    for (int x = 0; x < 3; x++) {

    for (int y = 0; y < 3; y++) {

    nd.setLocalTranslation(x, 0, y);

    nd.rotate(0, 2, 0);

    grid.attachChild(nd.clone());

    }

    }

    grid.move(0, -5, 0);

    Node newgrid = GeometryBatchFactory.optimize(grid);

    rootNode.attachChild(newgrid);

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

    initKeys();

    flyCam.setMoveSpeed(6f);

    }

    @Override

    public void simpleUpdate(float tpf) {

    // TODO: add update code

    }

    @Override

    public void simpleRender(RenderManager rm) {

    // TODO: add render code

    }

    private void initKeys() {

    inputManager.addMapping("Shoot", // Declare…

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

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

    inputManager.addListener(analogListener, "Shoot"); // … and add.

    }

    private final AnalogListener analogListener = new AnalogListener() {

    @Override

    public void onAnalog(String name, float value, float tpf) {

    // TODO Auto-generated method stub

    if (name.equals("Shoot")) {

    Node marker = new Node();

    marker.attachChild(mark);

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

    rootNode.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();
Geometry g = results.getCollision(i).getGeometry();
Node n1 = g.getParent();
int trino = results.getCollision(i).getTriangleIndex();
System.out.println("* Collision #" + i);
System.out.println(" You shot " + hit + " at " + pt + ", "
+ dist + " wu away. ");
System.out.println("* tri no" + trino);
}
// 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.
System.out.println("* closest parent "
+ closest.getGeometry().getParent().getParent()
.getName());
marker.setLocalTranslation(closest.getContactPoint());
rootNode.attachChild(marker);
System.out.println(" marked " + closest.getContactPoint());
} else {
// No hits? Then remove the red mark.
rootNode.detachChild(marker);
// sceneNode.updateGeometricState();
}
}
}
};
}[/java]


EDIT: cool way to test it is to not move the mouse , while keeping LMB pressed and just move camera forward/backward (W/S) to see misses (blinking red sphere)

Hi-

Thanks very much for your efforts :slight_smile:

I’m confused though - the new code I tried and I’m still having the same problems,

here’s a screenshot of when it ‘missed’ with cam location,



http://www.butterfly.ie/hextests/picktest.png

sorry, i guess at this stage you’re just showing the problem much better by having continuous analog testing,

yes you can see the blinking and missing much better…



now what :slight_smile:

yeah…at this stage, just showing that you are right, I didn’t have time to test it more then, to get to the root of the problem, trying more now…

well like i was saying, if i do a 360 rotation on the objects - it seems to work fine - (below)

but in my project, if i moved vertically away from the world origin, the problem seems to return…





[java]

package mygame;

import com.jme3.app.SimpleApplication;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.renderer.RenderManager;

import com.jme3.scene.Geometry;

import com.jme3.scene.shape.Box;

import com.jme3.scene.shape.Sphere;

import com.jme3.scene.Node;

import com.jme3.scene.Mesh;

import com.jme3.math.Vector3f;

import com.jme3.math.Vector2f;

import com.jme3.util.BufferUtils;

import java.nio.FloatBuffer;

import com.jme3.scene.VertexBuffer;

import com.jme3.scene.VertexBuffer.Type;

import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.AnalogListener;

import com.jme3.input.controls.KeyTrigger;

import com.jme3.input.controls.MouseButtonTrigger;

import com.jme3.math.Ray;

import com.jme3.input.KeyInput;

import com.jme3.font.BitmapText;

import com.jme3.collision.CollisionResult;

import com.jme3.collision.CollisionResults;

import com.jme3.math.Quaternion;

import jme3tools.optimize.GeometryBatchFactory;

import com.jme3.math.FastMath;

/**

  • test

    *
  • @author normenhansen

    */

    public class Main extends SimpleApplication {

    Geometry mark;

    public static void main(String[] args) {

    Main app = new Main();

    app.start();

    }

    @Override

    public void simpleInitApp() {

    cam.setLocation(new Vector3f(0.020104392f, -2.2130537f, 2.8410192f));

    cam.setRotation(new Quaternion(0.06470209f, 0.9191101f, -0.34940267f,

    0.17019996f));

    cam.setRotation(new Quaternion(0.0646277f, 0.9205545f, -0.34430403f,

    0.17279278f));

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

    // custome hex cap

    Mesh m = new Mesh();

    Vector3f[] vertices = new Vector3f[7];

    vertices[0] = new Vector3f(0.965926f, 0.166667f, 0.258819f);

    vertices[1] = new Vector3f(0.707107f, 0.166667f, -0.707107f);

    vertices[2] = new Vector3f(0.000000f, 0.166667f, 0.000000f);

    vertices[3] = new Vector3f(0.258819f, 0.166667f, 0.965926f);

    vertices[4] = new Vector3f(-0.707106f, 0.166667f, 0.707107f);

    vertices[5] = new Vector3f(-0.965926f, 0.166667f, -0.258818f);

    vertices[6] = new Vector3f(-0.258820f, 0.166667f, -0.965926f);

    Vector2f[] texCoord = new Vector2f[7];

    texCoord[0] = new Vector2f(1.000000f, 0.566988f);

    texCoord[1] = new Vector2f(0.750000f, 0.133975f);

    texCoord[2] = new Vector2f(0.500000f, 0.566987f);

    texCoord[3] = new Vector2f(0.750000f, 1.000000f);

    texCoord[4] = new Vector2f(0.250000f, 1.000000f);

    texCoord[5] = new Vector2f(0.000000f, 0.566987f);

    texCoord[6] = new Vector2f(0.250000f, 0.133975f);

    int[] indexes = { 0, 1, 2, 2, 3, 0, 2, 4, 3, 2, 5, 4, 2, 6, 5, 2, 1, 6 };

    m.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(vertices));

    m.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord));

    m.setBuffer(Type.Index, 1, BufferUtils.createIntBuffer(indexes));

    m.createCollisionData();

    m.updateBound();

    Geometry geom = new Geometry("OurMesh", m);

    Node nd = new Node();

    nd.attachChild(geom);

    nd.scale(.5f);

    Material bluemat = new Material(assetManager,

    "Common/MatDefs/Misc/SolidColor.j3md");

    bluemat.setColor("Color", ColorRGBA.Blue);

    geom.setMaterial(bluemat);

    Node grid = new Node();

    for (int x = 0; x < 3; x++) {

    for (int y = 0; y < 3; y++) {

    nd.setLocalTranslation(x, 0, y);

    nd.rotate(0, 2, 0);

    nd.rotate((FastMath.PI * 2), (FastMath.PI * 2), (FastMath.PI * 2));

    grid.attachChild(nd.clone());

    }

    }

    grid.move(0, -5, 0);

    Node newgrid = grid;//GeometryBatchFactory.optimize(grid);

    // newgrid.attachChild(grid);

    rootNode.attachChild(newgrid);

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

    initKeys();

    flyCam.setMoveSpeed(6f);

    }

    @Override

    public void simpleUpdate(float tpf) {

    // TODO: add update code

    }

    @Override

    public void simpleRender(RenderManager rm) {

    // TODO: add render code

    }

    private void initKeys() {

    inputManager.addMapping("Shoot", // Declare…

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

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

    inputManager.addListener(analogListener, "Shoot"); // … and add.

    }

    private final AnalogListener analogListener = new AnalogListener() {

    @Override

    public void onAnalog(String name, float value, float tpf) {

    // TODO Auto-generated method stub

    if (name.equals("Shoot")) {

    Node marker = new Node();

    marker.attachChild(mark);

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

    rootNode.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();
Geometry g = results.getCollision(i).getGeometry();
Node n1 = g.getParent();
int trino = results.getCollision(i).getTriangleIndex();
System.out.println("* Collision #" + i);
System.out.println(" You shot " + hit + " at " + pt + ", "
+ dist + " wu away. ");
System.out.println("* tri no" + trino);
}
// 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.
System.out.println("* closest parent "
+ closest.getGeometry().getParent().getParent()
.getName());
marker.setLocalTranslation(closest.getContactPoint());
rootNode.attachChild(marker);
System.out.println(" marked " + closest.getContactPoint());
} else {
// No hits? Then remove the red mark.
rootNode.detachChild(marker);
// sceneNode.updateGeometricState();
}
}
}
};
}
[/java]

and the problem is nothing to do with geometrybatchfactory specifically as i originally thought…

it can sometimes reappear when i use it - sometimes not,

it’s a very random problem…

1 Like

so far, it seems to me the collision is not detected in com.jme3.bounding.BoundingBox.collideWithRay(Ray, CollisionResults)

that is, the collision of the ray with the boundingbox of each of the hexagonz

I tried your last code, if I just keep LMB pressed and move away with the camera (ie. key S only) then it does detect lack of collisions, seems like the rotations didn’t have any effect… well maybe from the same cam location&rotation while it initially doesn’t detect collision, after you do your rotations it does detect it, but the “bug” is still there really, just have to get a different ray angle I think

basically if I change line 746 in com.jme3.bounding.BoundingBox.collideWithRay(Ray, CollisionResults):

[java]

return 0;[/java]

to:

[java] System.out.println(“no collision”);

return 0;[/java]

I can see that when no collision happens there are 9 “no collision” lines instead of 8 when it does happen, meaning , that method is the one that doesn’t detect it



EDIT: well I mean it could be that the bound is off, I mean, it doesn’t mean this method is bugged :slight_smile:

interesting, thanks for that…



at a wild guess i’m wondering is it something to do with internal floating point precision problems don’t picking up the collisions depending on where you are in world space…



i’m out of my depth on this, just a guess…

1 Like

looks like the same thing happens for Quad`s that have a 0 or very close to 0 height

here’s a sample code (note that I only show the bounding box of the Quad, rest is well invisible?)

also cam pos&rot is already set to the point of no collision detected

also note that if I replace:

[java] Quad m = new Quad(1f, 0.0000000000001f);[/java]

with

[java]Quad m = new Quad(1f, 0.1f);[/java]

there are always collisions

but if I replace it with

[java]Quad m = new Quad(1f, 0.000001f);[/java]

I can easily get some missed collisions by simply aiming the camera at a quad (well it’s boundingbox really) and only moving camera backward with S (keeping LMB pressed) - the red sphere will blink [just in case someone didn’t read prev posts xD]

It might be a float precision issue? I wonder what @momoko_fan or @normen think :slight_smile:

[java]package org.jme3.forum2;

import com.jme3.app.SimpleApplication;

import com.jme3.bounding.BoundingBox;

import com.jme3.bounding.BoundingVolume;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.renderer.RenderManager;

import com.jme3.renderer.ViewPort;

import com.jme3.scene.Geometry;

import com.jme3.scene.shape.Box;

import com.jme3.scene.shape.Quad;

import com.jme3.scene.shape.Sphere;

import com.jme3.scene.Node;

import com.jme3.scene.Mesh;

import com.jme3.scene.Spatial;

import com.jme3.math.Vector3f;

import com.jme3.math.Vector2f;

import com.jme3.util.BufferUtils;

import java.io.IOException;

import java.nio.FloatBuffer;

import com.jme3.scene.VertexBuffer;

import com.jme3.scene.VertexBuffer.Type;

import com.jme3.scene.control.Control;

import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.AnalogListener;

import com.jme3.input.controls.KeyTrigger;

import com.jme3.input.controls.MouseButtonTrigger;

import com.jme3.math.Ray;

import com.jme3.input.KeyInput;

import com.jme3.export.JmeExporter;

import com.jme3.export.JmeImporter;

import com.jme3.font.BitmapText;

import com.jme3.collision.CollisionResult;

import com.jme3.collision.CollisionResults;

import com.jme3.math.Quaternion;

import jme3tools.optimize.GeometryBatchFactory;

/**

  • test

    *
  • @author normenhansen

    */

    public class Hexagonz extends SimpleApplication {

    Geometry mark;

    public static void main(String[] args) {

    Hexagonz app = new Hexagonz();

    app.start();

    }

    @Override

    public void simpleInitApp() {

    cam.setLocation(new Vector3f(-678.7995f, 2953.4587f, -793.7561f));

    cam.setRotation(new Quaternion(0.55556095f, 0.26722988f, -0.19459328f,

    0.76293755f));

    // cam.setRotation(new Quaternion(0.0646277f, 0.9205545f, -0.34430403f,

    // 0.17279278f));

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

    mark.setLocalScale(1000f);

    // custome hex cap

    Quad m = new Quad(1f, 0.0000000000001f);

    // Mesh m = new Mesh();

    // Vector3f[] vertices = new Vector3f[7];

    // vertices[0] = new Vector3f(0.965926f, 0.166667f, 0.258819f);

    // vertices[1] = new Vector3f(0.707107f, 0.166667f, -0.707107f);

    // vertices[2] = new Vector3f(0.000000f, 0.166667f, 0.000000f);

    // vertices[3] = new Vector3f(0.258819f, 0.166667f, 0.965926f);

    // vertices[4] = new Vector3f(-0.707106f, 0.166667f, 0.707107f);

    // vertices[5] = new Vector3f(-0.965926f, 0.166667f, -0.258818f);

    // vertices[6] = new Vector3f(-0.258820f, 0.166667f, -0.965926f);

    // Vector2f[] texCoord = new Vector2f[7];

    // texCoord[0] = new Vector2f(1.000000f, 0.566988f);

    // texCoord[1] = new Vector2f(0.750000f, 0.133975f);

    // texCoord[2] = new Vector2f(0.500000f, 0.566987f);

    // texCoord[3] = new Vector2f(0.750000f, 1.000000f);

    // texCoord[4] = new Vector2f(0.250000f, 1.000000f);

    // texCoord[5] = new Vector2f(0.000000f, 0.566987f);

    // texCoord[6] = new Vector2f(0.250000f, 0.133975f);

    // int[] indexes = { 0, 1, 2, 2, 3, 0, 2, 4, 3, 2, 5, 4, 2, 6, 5, 2, 1,

    // 6 };

    // m.setBuffer(Type.Position, 3,

    // BufferUtils.createFloatBuffer(vertices));

    // m.setBuffer(Type.TexCoord, 2,

    // BufferUtils.createFloatBuffer(texCoord));

    // m.setBuffer(Type.Index, 1, BufferUtils.createIntBuffer(indexes));

    // m.createCollisionData();

    // m.updateBound();

    Geometry geom = new Geometry("OurMesh", m);

    Node nd = new Node();

    nd.attachChild(geom);

    nd.scale(.5f);

    Material bluemat = new Material(assetManager,

    "Common/MatDefs/Misc/SolidColor.j3md");

    bluemat.setColor("Color", ColorRGBA.Blue);

    geom.setMaterial(bluemat);

    Node grid = new Node();

    for (int x = 0; x < 3; x++) {

    for (int y = 0; y < 3; y++) {

    nd.setLocalTranslation(x, 0, y);

    nd.rotate(0, 2, 0);

    showBound(nd, grid);

    grid.attachChild(nd.clone());

    }

    }

    grid.move(0, -5, 0);

    Node newgrid = GeometryBatchFactory.optimize(grid);

    newgrid.setLocalScale(1000f);

    rootNode.attachChild(newgrid);

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

    initKeys();

    flyCam.setMoveSpeed(6000f);

    cam.setFrustumFar(11111111111f);

    }

    @Override

    public void simpleUpdate(float tpf) {

    // TODO: add update code

    }

    @Override

    public void simpleRender(RenderManager rm) {

    // TODO: add render code

    }

    private void initKeys() {

    inputManager.addMapping("Shoot", // Declare…

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

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

    inputManager.addListener(analogListener, "Shoot"); // … and add.

    }

    private final AnalogListener analogListener = new AnalogListener() {

    @Override

    public void onAnalog(String name, float value, float tpf) {

    // TODO Auto-generated method stub

    if (name.equals("Shoot")) {

    Node marker = new Node();

    marker.attachChild(mark);

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

    rootNode.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();
Geometry g = results.getCollision(i).getGeometry();
Node n1 = g.getParent();
int trino = results.getCollision(i).getTriangleIndex();
System.out.println("* Collision #" + i);
System.out.println(" You shot " + hit + " at " + pt + ", "
+ dist + " wu away. ");
System.out.println("* tri no" + trino);
}
// 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.
System.out.println("* closest parent "
+ closest.getGeometry().getParent().getParent()
.getName());
marker.setLocalTranslation(closest.getContactPoint());
rootNode.attachChild(marker);
System.out.println(" marked " + closest.getContactPoint());
} else {
// No hits? Then remove the red mark.
rootNode.detachChild(marker);
// sceneNode.updateGeometricState();
}
}
}
};
private void showBound(Spatial ofSpatial, Node attachToThisParent) {
BoundingVolume bv = ofSpatial.getWorldBound();
if (bv.getType() == BoundingVolume.Type.AABB) {
BoundingBox boundingBox = (BoundingBox) bv;
Box boundingMesh = new Box(boundingBox.getCenter(),
boundingBox.getXExtent(), boundingBox.getYExtent(),
boundingBox.getZExtent());
final Geometry boundingGeo = new Geometry(ofSpatial.getName()
+ "'s bounding box AABB", boundingMesh);
Material boundingMat = new Material(assetManager,
"Common/MatDefs/Misc/WireColor.j3md");
boundingMat.setColor("Color", ColorRGBA.Red);
boundingGeo.setMaterial(boundingMat);
attachToThisParent.attachChild(boundingGeo);
boundingGeo.addControl(new Control() {
private Spatial s;
@Override
public void write(JmeExporter ex) throws IOException {
// TODO Auto-generated method stub
}
@Override
public void read(JmeImporter im) throws IOException {
// TODO Auto-generated method stub
}
@Override
public void update(float tpf) {
// TODO Auto-generated method stub
// boundingGeo.setLocalScale(s.getLocal)
boundingGeo.setLocalTransform(s.getLocalTransform());
}
@Override
public void setSpatial(Spatial spatial) {
s = spatial;
}
@Override
public void setEnabled(boolean enabled) {
// TODO Auto-generated method stub
}
@Override
public void render(RenderManager rm, ViewPort vp) {
// TODO Auto-generated method stub
}
@Override
public boolean isEnabled() {
// TODO Auto-generated method stub
return false;
}
@Override
public Control cloneForSpatial(Spatial spatial) {
// TODO Auto-generated method stub
return null;
}
});
}
}
}[/java]

EDIT: ignore the part with the Control where I mistakenly don't realize that `s == boundingGeo`