Picking and highlighting the side of a cube


I’m currently working on my ship builder. The main building blocks are cubes. To these cubes you can link other cubes, or other basic elements like spheres, cones, etc.
In order to make this possible, I need to be able to determine the side of the cube that has been selected. I can do the whole ray casting thing to detect the selected cube. What I can’t seem to figure out, or find on the wiki anywhere, is how to determine the side of the cube that has been selected. If I can do that, I then also need to figure out how to highlight that side of the cube, and to determine the center of it.

First things first though, how do I detect which side of the cube has been selected?


The contact normal?

I think I managed to fix it, although it might be that there’s a better way.

public void onAnalog(String name, float value, float tpf) {
if (name.equals(MAPPING_ROTATE)) {
CollisionResults results = new CollisionResults();
Vector2f mouseLocation2D = inputManager.getCursorPosition();
Vector3f mouseLocation3D = cam.getWorldCoordinates(mouseLocation2D, 0.0f);
Vector3f direction = cam.getWorldCoordinates(mouseLocation2D, 1.0f).subtractLocal(mouseLocation3D);
Ray ray = new Ray(mouseLocation3D, direction);
rootNode.collideWith(ray, results);
if (results.size() > 0) {
CollisionResult result = results.getClosestCollision();
Triangle triangle = new Triangle();
triangle = result.getTriangle(triangle);
float dist12 = Math.abs(triangle.get1().distance(triangle.get2()));
float dist23 = Math.abs(triangle.get2().distance(triangle.get3()));
float dist31 = Math.abs(triangle.get3().distance(triangle.get1()));
Vector3f box1 = null;
Vector3f box2 = null;
if (dist12 == dist23) { //dist31 is biggest
box1 = triangle.get3();
box2 = triangle.get1();
} else if (dist23 == dist31) { //dist12 is biggest
box1 = triangle.get1();
box2 = triangle.get2();
} else if (dist31 == dist12) { //dist23 is biggest
box1 = triangle.get2();
box2 = triangle.get3();
Box highlightBox = new Box(box1, box2);
Geometry highlightGeom = new Geometry(“highlightBox”, highlightBox);
Material mat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);
mat.setColor(“Color”, ColorRGBA.Red);
Node boxNode = result.getGeometry().getParent();

What I’m doing here is:
1: determine the targetted geometry. Currently I only have boxes, so that makes it a bit easier.
2: determine the targetted triangle on the geometry.
3: determine the longest side of the triangle, the two points making up the longest side are oposite each other.
4: use these oposite points to create a new 0 height box located on the selected side and give this box a different color.
5: add the new box to the same boxNode

For some reason, this already fixes it so the highlighting is removed when the mouse button is released. I’m not quite sure how that’s possible.

I guess I don’t really understand why the contact normal doesn’t tell you exactly what you need to know. It points in the exact direction of the face after all.

I get that, I just couldn’t figure out how to translate that into code which would let me highlight it. This seems to do both at the same time.

Vector3f cn = contact normal
Vector3f centerOfClickedSide = box.getCenter().clone();
centerOfClickedSize.addLocal( cn.mult(box.getXExtent()) );
centerOfClickedSize.addLocal( cn.mult(box.getYExtent()) );
centerOfClickedSize.addLocal( cn.mult(box.getZExtent()) );

…in theory.