Ray collision - getContactNormal always null

As topic.



You can still get at the normal by getting the triangle of the collision and get the normal of that, but the more direct method of getting the contact normal seems to always return null.



Crude sample test below:


package com.flah.playground;

import com.jme3.app.SimpleApplication;
import com.jme3.collision.CollisionResult;
import com.jme3.collision.CollisionResults;
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.shape.Box;

public class RayNormal extends SimpleApplication {

   private CollisionResult cr;
   private CollisionResults results;
   private Ray pewPew;
   
   @Override
   public void simpleInitApp() {
      Box b = new Box(Vector3f.ZERO, 1, 1, 1);
      Geometry g = new Geometry("OrangeBox", b);
      Material m = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");
      m.setColor("m_Color", ColorRGBA.Orange);
      g.setMaterial(m);
      rootNode.attachChild(g);
      
      pewPew = new Ray(new Vector3f(-5, 0, 0), Vector3f.UNIT_X);
      results = new CollisionResults();
      
      rootNode.updateGeometricState();
   }
   
   @Override
   public void simpleUpdate(float tpf) {
      super.simpleUpdate(tpf);
      
      results.clear();
      rootNode.collideWith(pewPew, results);
      
      cr = results.getClosestCollision();

      System.out.println("Number of Collisions(2):     " + results.size());
      System.out.println("Name of Object:              " + cr.getGeometry().getName());
      System.out.println("Normal of Closest Collision: " + cr.getContactNormal());
      System.out.println("Normal of Triangle:          " + cr.getTriangle(null).getNormal());
   }

   public static void main(String[] args) {
      RayNormal app = new RayNormal();
      app.start();
   }
}

Hi!



I am having this problem also.

I am trying to move a spotlight just above where the ray hits.



I found a fix but it only works with non mesh (at Box it works) geometries.

by using this I can get the normal:



Triangle tri = new Triangle();

col.getGeometry().getMesh().getTriangle(col.getTriangleIndex(),tri);

return tri.getNormal();





@tehflah

what code you use to find the normal when it hits a mesh geometry?

this fix I found only returns 0,0,0 normals…



EDIT: I found a fix, I have Mesh class extended for metaballs, so I override getTriangles and allowed it to work with IntBuffer, here it is (a quick fix I did, just to see it working…):

public void getTriangle(int index, Vector3f v1, Vector3f v2, Vector3f v3){

VertexBuffer pb = getBuffer(Type.Position);

VertexBuffer ib = getBuffer(Type.Index);



if (pb.getFormat() == Format.Float){

FloatBuffer fpb = (FloatBuffer) pb.getData();



if (ib.getFormat() == Format.UnsignedShort){

// accepted format for buffers

ShortBuffer sib = (ShortBuffer) ib.getData();



// aquire triangle’s vertex indices

int vertIndex = index * 3;

int vert1 = sib.get(vertIndex);

int vert2 = sib.get(vertIndex+1);

int vert3 = sib.get(vertIndex+2);



BufferUtils.populateFromBuffer(v1, fpb, vert1);

BufferUtils.populateFromBuffer(v2, fpb, vert2);

BufferUtils.populateFromBuffer(v3, fpb, vert3);

}

if (ib.getFormat() == Format.UnsignedInt){

// accepted format for buffers

IntBuffer sib = (IntBuffer) ib.getData();



// aquire triangle’s vertex indices

int vertIndex = index * 3;

int vert1 = sib.get(vertIndex);

int vert2 = sib.get(vertIndex+1);

int vert3 = sib.get(vertIndex+2);



BufferUtils.populateFromBuffer(v1, fpb, vert1);

BufferUtils.populateFromBuffer(v2, fpb, vert2);

BufferUtils.populateFromBuffer(v3, fpb, vert3);

}

}

}

1 Like

great fix for getTriangle()



tried it out and works superb :slight_smile: