EDIT: ok, I guess it is the low floating point precision, any fixes for this example though?
This is based on this thread/post.
use the following code to test
Note that I also edited this, to actually see more clearly:
[patch]Index: src/core/com/jme3/bounding/BoundingBox.java
===================================================================
— src/core/com/jme3/bounding/BoundingBox.java (revision 7353)
+++ src/core/com/jme3/bounding/BoundingBox.java (working copy)
@@ -707,6 +707,9 @@
-
@see com.jme.bounding.BoundingVolume#intersectsWhere(com.jme.math.Ray)
*/
private int collideWithRay(Ray ray, CollisionResults results) {
- System.out.println(ray);
- System.out.println("sizeX=" + this.getXExtent() + "sizeY="
-
+ this.getYExtent() + "sizeZ=" + this.getZExtent());<br />
TempVars vars = TempVars.get();
assert vars.lock();
Vector3f diff = vars.vect1.set(ray.origin).subtractLocal(center);
@@ -735,22 +738,27 @@
results.addCollision(result);
result = new CollisionResult(points[1], distances[1]);
results.addCollision(result);
-
System.out.println("2 collisions");<br />
return 2;
}
Vector3f point = new Vector3f(ray.direction).multLocal(t[0]).addLocal(ray.origin);
CollisionResult result = new CollisionResult(point, t[0]);
results.addCollision(result);
-
System.out.println("1 collisions");<br />
return 1;
}
-
System.out.println("no collision");<br />
return 0;
}
[/patch]
When you run code, there are no collisions, just press W or S to move camera forward/backward to trigger 2 collisions and if you get close enough you can see when the closest collision is actually on the backface of the box (though most of the time it’s on the front face) or just comment and uncomment the blocks that set the camera pos&rot, marked with “XXX:” in the code
backside collision:
====
no collisions:
http://i.imgur.com/beqwu.png
[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 centred 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);
if (results.size() > 0) {
CollisionResult closest = results.getClosestCollision();
Vector3f worldContact = closest.getContactPoint();
Vector3f normal = closest.getContactNormal();
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]
EDIT: why is this relevant? because BoundingBox is the bound of ie. a Quad and the intersection of it with Ray will fail quite a lot