After following the JME3 Picking tutorial I was wondering if it is possible to check what side (face) of a Box geometry object was hit by the ray?
if the dot product of the ray direction and the triangle normal is greater than zero, then you hit the front side, if its less than zero, you hit the back side.
EDIT: Sorry I mean the opposite. If the dot product is negative then its the front side. Because the mouse ray faces the opposite direction of the face normal
in that example
to get the normal:
[java]Vector3f normal = closest.getContactNormal();[/java]
@momoko_fan
I seem to be getting the exact opposite results: hit front => dot product is negative (ie. less than zero)
hit back => dot product is positive
unless there is some kind of fixed definition for front side and back side?
also, I tested this on a Box instead of a triangle (is that not the same thing?)
…unless you mistakenly swapped the two(which would be understandable, unless you’re an alien xD), I must be missing something
ie. this code:
[java]package org.jme3.forum2;
import java.util.prefs.BackingStoreException;
import com.jme3.app.SimpleApplication;
import com.jme3.collision.CollisionResult;
import com.jme3.collision.CollisionResults;
import com.jme3.font.BitmapText;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Ray;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.debug.Arrow;
import com.jme3.scene.shape.Box;
import com.jme3.system.AppSettings;
/**
*
/
public class CollisionFail extends SimpleApplication {
public static void main(String[] args) throws BackingStoreException {
CollisionFail app = new CollisionFail();
AppSettings aps = new AppSettings(true);
aps.load(aps.getTitle());
aps.setVSync(true);
app.setShowSettings(false);
app.setSettings(aps);
app.start();
}
private Node shootables;
private Geometry mark;
/
- (non-Javadoc)
*
-
@see com.jme3.app.SimpleApplication#simpleInitApp()
/
@Override
public void simpleInitApp() {
Box boxMesh = new Box(0.5f, 0.9f, 0.000001f);
Geometry boxGeo = new Geometry("box", boxMesh);
Material boxMat = new Material(assetManager,
"Common/MatDefs/Misc/WireColor.j3md");
boxMat.setColor("Color", ColorRGBA.Green);
boxGeo.setMaterial(boxMat);
shootables = new Node();
shootables.attachChild(boxGeo);
rootNode.attachChild(shootables);
initCrossHairs();
initMark();
flyCam.setMoveSpeed(10f);
// XXX: closest collision is on the backside:
cam.setLocation(new Vector3f(-3.135194f, 0.008213693f, 11.205608f));
cam.setRotation(new Quaternion(4.205436E-4f, 0.9896395f,
-0.0028993362f, 0.14354452f));
// XXX: there are no collisions:
// cam.setLocation(new Vector3f(-36.74216f, 0.70129883f, 124.61681f));
// cam.setRotation(new Quaternion(4.205436E-4f, 0.9896395f,
// -0.0028993362f, 0.14354452f));
}
private final Vector3f marksScale = new Vector3f(0.5f, 0.5f, 1f);
protected void initMark() {
Arrow arrow = new Arrow(Vector3f.UNIT_Z.mult(2f));
arrow.setLineWidth(3);
mark = new Geometry("markGeo", arrow);
Material mark_mat = new Material(assetManager,
"Common/MatDefs/Misc/SolidColor.j3md");
mark_mat.setColor("Color", ColorRGBA.Red);
mark.setMaterial(mark_mat);
}
/* A centered 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);
}
/*
- (non-Javadoc)
*
-
@see com.jme3.app.SimpleApplication#simpleUpdate(float)
*/
@Override
public void simpleUpdate(float tpf) {
CollisionResults results = new CollisionResults();
Ray ray = new Ray(cam.getLocation(), cam.getDirection());
// 3. Collect intersections between Ray and Shootables in
// results list.
shootables.collideWith(ray, results);
System.out.println(“Collisions:” + results.size());
if (results.size() > 0) {
CollisionResult closest = results.getClosestCollision();
Vector3f worldContact = closest.getContactPoint();
Vector3f normal = closest.getContactNormal();
System.out.println(“dot product:” + ray.getDirection().dot(normal));
worldContact = rootNode.worldToLocal(worldContact, null);
rootNode.attachChild(mark);
mark.setLocalTranslation(worldContact);
Vector3f upVec = rootNode.worldToLocal(Vector3f.UNIT_Y, null);
Quaternion q = new Quaternion();
// makes Z axis be in the same direction asnormal
// (ourmark
arrow is on the Z axis)
q.lookAt(normal, upVec.normalize());
q = mark.getParent().getWorldRotation().inverse().mult(q);
mark.setLocalRotation(q);
// if I want to keep mark’s scale to 1, regardless of parents’
// transforms:
mark.setLocalScale(marksScale.divide(mark.getParent()
.getWorldScale()));
} else {
rootNode.detachChild(mark);
}
}
}
[/java]
Yep, sorry I accidently swapped them. Fixed in original post now
sssWeet! I like it when my confusion is fixed much appreciated !