jme3 ray collision

Hey, everyone!

Ive got a problem with jme3 collision maybe someone can help me? :slight_smile:

The problem is that when you move geometry, the modelbound position is not updated.

This relates to the problem that you can only collide with the geometry when its location is inside the initial bounding box.

As you can see I took the HelloPicking tutorial and simply moved the orange box by (0, 1, 0).

The blue wireframe boxes show the modelbounds of the collosion objects.

It is only possible to collide with the object within the green marked area.

Setting a custom boundingbox, or moving the modelbound manually didnt work either.

Is this a known issue? I know jme3 is still alpha

I've noticed this too. Would appreciate a work-around if people know of one.

Paticleemitters are behaving strange too when you translate them. Then they are only visible from the right direction (they are sometimes invisible when you move around them.

jME3 collision system is currently not functional, sorry about that. It is definitely going to be fixed in the alpha2 release.

About the particle issue; can you please make a test-case demonstrating the issue?

Sure, here it is.

The red flame is not moved, both yellow flames are moved and bugged

import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;

public class ParticleEmitterBugTestCase extends SimpleApplication

   public static void main(String[] args)
      ParticleEmitterBugTestCase app = new ParticleEmitterBugTestCase();

   public void simpleInitApp()
      createfire(0, 0, 0, new ColorRGBA(1f, 0f, 0f, 1f));

      createfire(3, 0, 0, new ColorRGBA(1f, 1f, 0f, 0.5f));

      createfire(-3, 0, 0, new ColorRGBA(1f, 1f, 0f, 0.5f));

      // floor
      Box box = new Box(new Vector3f(0, -1, -5), 15, .2f, 15);
      Geometry floor = new Geometry("Floor", box);
      Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");
      mat1.setColor("m_Color", ColorRGBA.Gray);

   private void createfire(float x, float y, float z, ColorRGBA color)
      ParticleEmitter fire = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 20);
      Material mat_red = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
      mat_red.setTexture("m_Texture", assetManager.loadTexture("Effects/Explosion/flame.png"));
      fire.setImagesY(2); // 2x2 texture animation
      fire.setEndColor(color); // red
      fire.setStartColor(color); // yellow
      fire.setStartVel(new Vector3f(0, 1, 0));
      fire.move(x, y, z);

Just fly around a bit and you will see :)

The collision ray picking bug has been fixed in the latest SVN. Hopefully that will make some people happy :wink:

Also, about the particle bug:

I confirmed it.

It's due to particles emitting in world space by default, right now you can fix it easily by calling ParticleEmitter.setInWorldSpace(false), but your particles won't be in world space anymore.

It happens because the transformation of the particles is being applied twice to the bounding, once due to the individual particles translation, and again due to the transform. The incorrect bounding causes the frustum culling to flag the particle as being out of view.

It can probably be fixed by shifting the local bounding by the inverse of the transform.

Yay for ray fix, finally I can work on the swing3d input a bit more.

Thank you very much!

Now both works :slight_smile: Great job!

I apologize in advance for the slight necropost, but it is related.

This bug on the ray picking on a moving object, did the fix also include rotating objects?

I have a door object in my scene that has a controller applied to it once the door is clicked on with the mouse. However, as soon as I click on it to open the door, the door object (a simple box) is not selectable and the ray collision is reporting zero collisions. I changed it so that it spins 360 degrees and the box is selectable again only once it returns to it's original orientation. I changed it again to just move the object 1 unit and it DOES remain selectable while it moves. Then I changed it to move up 1 unit and rotate at the same time upon click - and I observe the same problem as only rotating, where the object is selectable at first, not selectable during the rotation, and selectable again once the object returns to it's original position/orientation.

I am using the Spatial.rotate(yaw,roll,pitch) method. (oooh, and I just noticed rotateUpTo… Gotta mess with that later)


Can you post a reproducible test case?

Certainly. Took me a bit to rip the guts out of my program, but the attached code does do the same thing. Sorry it's sorta long. I have a lot of this stuff spread around in different classes so it was a bit hacky to throw together.

I commented the move out on the controller as it really makes no difference if it's being translated while rotating. You can even click both of them and they won't be selectable for the duration of the spin.

Soooo, on to the code. What it should produce is two boxes, that in my situation were to resemble doors once I was through with them. They both start as the default color of blue and when the mouse hovers one of them, it should turn to yellow and back to blue if the cursor leaves the object. When clicked on, the box will have a controller added to it that spins it 360 degrees (in a very hacky manner, but meh, it works), and if you move your mouse while the object is spinning, the box is not selectable. - IE, the hover code suddenly does not work. However, if you wiggle the cursor around on the box you clicked while it spins, you should observe that the box will flicker yellow at the 180 degree point, and remain selectable again once the box has completed it's spin.

Thanks for taking a look!

package com.flah.playground;

import org.lwjgl.input.Mouse;

import com.jme3.collision.CollisionResult;
import com.jme3.collision.CollisionResults;
import com.jme3.input.MouseInput;
import com.jme3.input.RawInputListener;
import com.jme3.input.event.JoyAxisEvent;
import com.jme3.input.event.JoyButtonEvent;
import com.jme3.input.event.KeyInputEvent;
import com.jme3.input.event.MouseButtonEvent;
import com.jme3.input.event.MouseMotionEvent;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Ray;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.control.Control;
import com.jme3.scene.shape.Box;

public class RotationTestCase extends SimpleApplication {

   // Mouse Input Variables
   private Ray mouseRay;
   private CollisionResults rayResults;
   private CollisionResult closest;
   private Node interactiveRoot;
   // Temp Values for the Interactive Object
   private ColorRGBA defaultColor = ColorRGBA.Blue;
   public void simpleInitApp() {
      interactiveRoot = new Node("Interactive Node");
      Box abox = new Box(new Vector3f(0,0,0), 0.2f, 1, 1);
      Geometry geombox = new Geometry("door", abox);
      Material mat = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");
      mat.setColor("m_Color", defaultColor);
      geombox.getLocalTranslation().set(new Vector3f(2,-2,0));
      Box abox2 = new Box(new Vector3f(0,0,0), 0.2f, 1, 1);
      Geometry geombox2 = new Geometry("door", abox2);
      Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");
      mat2.setColor("m_Color", defaultColor);
      geombox2.getLocalTranslation().set(new Vector3f(5,-2,0));
   private void initMouse(MouseInput mouseInput) {
      mouseInput.setInputListener(new RawInputListener() {
         public void onMouseMotionEvent(MouseMotionEvent arg0) {
            Geometry n;
            // Reset the marked object's diffuse color to un-highlight it
            if(closest != null) {
               closest.getGeometry().getMaterial().setColor("m_Color", defaultColor);
            closest = null;
            System.out.println(arg0.getX() + ", " + arg0.getY());
            Vector2f mouseCoords = new Vector2f(arg0.getX(), arg0.getY());
            mouseRay = new Ray(cam.getWorldCoordinates(mouseCoords, 0),
                        cam.getWorldCoordinates(mouseCoords, 1).subtractLocal(
                        cam.getWorldCoordinates(mouseCoords, 0)).normalizeLocal());
            System.out.println("Ray Parameters: Origin: " + mouseRay.getOrigin() + ", Dir: " + mouseRay.getDirection());
            rayResults = new CollisionResults();
            interactiveRoot.collideWith(mouseRay, rayResults);
            System.out.println("Collisions? : " + rayResults.size());
            if(rayResults.size() > 0) {
               closest = rayResults.getClosestCollision();
               // Set the Diffuse Color of the Object to the "Highlight Color"
               closest.getGeometry().getMaterial().setColor("m_Color", ColorRGBA.Yellow);
         public void onMouseButtonEvent(MouseButtonEvent arg0) {
            if(arg0.getButtonIndex() == 0 && arg0.isReleased()) {
               System.out.println("Mouse Click : Pos(X,Y) : " + Mouse.getX() + ", " + Mouse.getY());
               if(closest != null) {
//                  Interactive n = (Interactive) closest.getGeometry().getParent();
//                  n.performMotion();
                  closest.getGeometry().addControl(new AbstractControl() {
                     private float ghettoCounter = 0;
                     public Control cloneForSpatial(Spatial arg0) {
                        return null;
                     protected void controlUpdate(float arg0) {
                        spatial.rotate(0, 0.001f, 0);
//                        spatial.move(0, 0.001f, 0);
                        ghettoCounter += 0.001f;
                        if(ghettoCounter > FastMath.PI * 2) {
                     protected void controlRender(RenderManager arg0, ViewPort arg1) {
         public void onKeyEvent(KeyInputEvent arg0) {}
         public void onJoyButtonEvent(JoyButtonEvent arg0) {}         
         public void onJoyAxisEvent(JoyAxisEvent arg0) {}

   public static void main(String[] args) {
      RotationTestCase app = new RotationTestCase();

I have found the same problem too. If you call the setLocalTranslation(). the ray collision works well, but when you call the setLocalRotation() and rotate a certain angle, the geometry can not be detected unless it return to its original angle.

Bug fixed in latest SVN.

Momoko_Fan said:

Bug fixed in latest SVN.

thanks, i will try.

Hooray! Works in the little test case I wrote. - And just tested with my game code and it works great!

Thanks a million Momoko!  :smiley: