com.jme3.math.Ray Java Examples

The following examples show how to use com.jme3.math.Ray. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: TerrainCameraController.java    From MikuMikuStudio with BSD 2-Clause "Simplified" License 6 votes vote down vote up
/**
 * Find where on the terrain the mouse intersects.
 */
protected Vector3f getTerrainCollisionPoint() {

    if (editorController.getTerrain(null) == null) {
        return null;
    }

    CollisionResults results = new CollisionResults();
    Ray ray = new Ray();
    Vector3f pos = cam.getWorldCoordinates(new Vector2f(mouseX, mouseY), 0).clone();
    Vector3f dir = cam.getWorldCoordinates(new Vector2f(mouseX, mouseY), 0.3f).clone();
    dir.subtractLocal(pos).normalizeLocal();
    ray.setOrigin(pos);
    ray.setDirection(dir);
    editorController.getTerrain(null).collideWith(ray, results);
    if (results == null) {
        return null;
    }
    final CollisionResult result = results.getClosestCollision();
    if (result == null) {
        return null;
    }
    return result.getContactPoint();
}
 
Example #2
Source File: TerrainQuad.java    From MikuMikuStudio with BSD 2-Clause "Simplified" License 6 votes vote down vote up
private int collideWithRay(Ray ray, CollisionResults results) {
    if (picker == null)
        picker = new BresenhamTerrainPicker(this);

    Vector3f intersection = picker.getTerrainIntersection(ray, results);
    if (intersection != null) {
        if (ray.getLimit() < Float.POSITIVE_INFINITY) {
            if (results.getClosestCollision().getDistance() <= ray.getLimit())
                return 1; // in range
            else
                return 0; // out of range
        } else
            return 1;
    } else
        return 0;
}
 
Example #3
Source File: TestObjGroupsLoading.java    From jmonkeyengine with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
@Override
public void simpleUpdate(final float tpf) {
    
    // ray to the center of the screen from the camera
    Ray ray = new Ray(cam.getLocation(), cam.getDirection());
    
    // find object at the center of the screen

    final CollisionResults results = new CollisionResults();
    rootNode.collideWith(ray, results);
    
    CollisionResult result = results.getClosestCollision();
    if (result == null) {
        pointerDisplay.setText("");
    } else {
        // display pointed geometry and it's parents names
        StringBuilder sb = new StringBuilder();
        for (Spatial node = result.getGeometry(); node != null; node = node.getParent()) {
            if (sb.length() > 0) {
                sb.append(" < ");
            }
            sb.append(node.getName());
        }
        pointerDisplay.setText(sb);
    }
}
 
Example #4
Source File: TerrainQuad.java    From MikuMikuStudio with BSD 2-Clause "Simplified" License 6 votes vote down vote up
@Override
public int collideWith(Collidable other, CollisionResults results){
    int total = 0;

    if (other instanceof Ray)
        return collideWithRay((Ray)other, results);

    // if it didn't collide with this bbox, return
    if (other instanceof BoundingVolume)
        if (!this.getWorldBound().intersects((BoundingVolume)other))
            return total;

    for (Spatial child : children){
        total += child.collideWith(other, results);
    }
    return total;
}
 
Example #5
Source File: TerrainQuad.java    From MikuMikuStudio with BSD 2-Clause "Simplified" License 6 votes vote down vote up
/**
 * Gather the terrain patches that intersect the given ray (toTest).
 * This only tests the bounding boxes
 * @param toTest
 * @param results
 */
public void findPick(Ray toTest, List<TerrainPickData> results) {

    if (getWorldBound() != null) {
        if (getWorldBound().intersects(toTest)) {
            // further checking needed.
            for (int i = 0; i < getQuantity(); i++) {
                if (children.get(i) instanceof TerrainPatch) {
                    TerrainPatch tp = (TerrainPatch) children.get(i);
                    tp.ensurePositiveVolumeBBox();
                    if (tp.getWorldBound().intersects(toTest)) {
                        CollisionResults cr = new CollisionResults();
                        toTest.collideWith(tp.getWorldBound(), cr);
                        if (cr != null && cr.getClosestCollision() != null) {
                            cr.getClosestCollision().getDistance();
                            results.add(new TerrainPickData(tp, cr.getClosestCollision()));
                        }
                    }
                }
                else if (children.get(i) instanceof TerrainQuad) {
                    ((TerrainQuad) children.get(i)).findPick(toTest, results);
                }
            }
        }
    }
}
 
Example #6
Source File: Octnode.java    From MikuMikuStudio with BSD 2-Clause "Simplified" License 6 votes vote down vote up
public final void intersectWhere(Ray r, Geometry[] geoms, float sceneMin, float sceneMax,
                                        CollisionResults results){
    for (OCTTriangle t : tris){
        float d = r.intersects(t.get1(), t.get2(), t.get3());
        if (Float.isInfinite(d))
            continue;

        Vector3f contactPoint = new Vector3f(r.getDirection()).multLocal(d).addLocal(r.getOrigin());
        CollisionResult result = new CollisionResult(geoms[t.getGeometryIndex()],
                                                     contactPoint,
                                                     d,
                                                     t.getTriangleIndex());
        results.addCollision(result);
    }
    for (int i = 0; i < 8; i++){
        Octnode child = children[i];
        if (child == null)
            continue;

        if (child.bbox.intersects(r)){
            child.intersectWhere(r, geoms, sceneMin, sceneMax, results);
        }
    }
}
 
Example #7
Source File: BresenhamTerrainPicker.java    From MikuMikuStudio with BSD 2-Clause "Simplified" License 6 votes vote down vote up
protected boolean checkTriangles(float gridX, float gridY, Ray pick, Vector3f intersection, TerrainPatch patch, Triangle store) {
    if (!getTriangles(gridX, gridY, patch))
        return false;

    if (pick.intersectWhere(gridTriA, intersection)) {
        store.set(gridTriA.get1(), gridTriA.get2(), gridTriA.get3());
        return true;
    } else {
        if (pick.intersectWhere(gridTriB, intersection)) {
            store.set(gridTriB.get1(), gridTriB.get2(), gridTriB.get3());
            return true;
        }
    }

    return false;
}
 
Example #8
Source File: TestRayCollision.java    From jmonkeyengine with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
public static void main(String[] args){
    Ray r = new Ray(Vector3f.ZERO, Vector3f.UNIT_X);
    BoundingBox bbox = new BoundingBox(new Vector3f(5, 0, 0), 1, 1, 1);

    CollisionResults res = new CollisionResults();
    bbox.collideWith(r, res);

    System.out.println("Bounding:" +bbox);
    System.out.println("Ray: "+r);

    System.out.println("Num collisions: "+res.size());
    for (int i = 0; i < res.size(); i++){
        System.out.println("--- Collision #"+i+" ---");
        float dist = res.getCollision(i).getDistance();
        Vector3f pt = res.getCollision(i).getContactPoint();
        System.out.println("distance: "+dist);
        System.out.println("point: "+pt);
    }
}
 
Example #9
Source File: BIHTree.java    From jmonkeyengine with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
@Override
public int collideWith(Collidable other,
        Matrix4f worldMatrix,
        BoundingVolume worldBound,
        CollisionResults results) {

    if (other instanceof Ray) {
        Ray ray = (Ray) other;
        return collideWithRay(ray, worldMatrix, worldBound, results);
    } else if (other instanceof BoundingVolume) {
        BoundingVolume bv = (BoundingVolume) other;
        return collideWithBoundingVolume(bv, worldMatrix, results);
    } else {
        throw new UnsupportedCollisionException("Collidable:" + other);
    }
}
 
Example #10
Source File: TerrainQuad.java    From jmonkeyengine with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
/**
 * Gather the terrain patches that intersect the given ray (toTest).
 * This only tests the bounding boxes
 * @param toTest
 * @param results
 */
public void findPick(Ray toTest, List<TerrainPickData> results) {

    if (getWorldBound() != null) {
        if (getWorldBound().intersects(toTest)) {
            // further checking needed.
            for (int i = 0; i < getQuantity(); i++) {
                if (children.get(i) instanceof TerrainPatch) {
                    TerrainPatch tp = (TerrainPatch) children.get(i);
                    tp.ensurePositiveVolumeBBox();
                    if (tp.getWorldBound().intersects(toTest)) {
                        CollisionResults cr = new CollisionResults();
                        toTest.collideWith(tp.getWorldBound(), cr);
                        if (cr.getClosestCollision() != null) {
                            cr.getClosestCollision().getDistance();
                            results.add(new TerrainPickData(tp, cr.getClosestCollision()));
                        }
                    }
                }
                else if (children.get(i) instanceof TerrainQuad) {
                    ((TerrainQuad) children.get(i)).findPick(toTest, results);
                }
            }
        }
    }
}
 
Example #11
Source File: TerrainQuad.java    From jmonkeyengine with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
@Override
public int collideWith(Collidable other, CollisionResults results){
    int total = 0;

    if (other instanceof Ray)
        return collideWithRay((Ray)other, results);

    // if it didn't collide with this bbox, return
    if (other instanceof BoundingVolume)
        if (!this.getWorldBound().intersects((BoundingVolume)other))
            return total;

    for (Spatial child : children){
        total += child.collideWith(other, results);
    }
    return total;
}
 
Example #12
Source File: TestRayCollision.java    From MikuMikuStudio with BSD 2-Clause "Simplified" License 6 votes vote down vote up
public static void main(String[] args){
    Ray r = new Ray(Vector3f.ZERO, Vector3f.UNIT_X);
    BoundingBox bbox = new BoundingBox(new Vector3f(5, 0, 0), 1, 1, 1);

    CollisionResults res = new CollisionResults();
    bbox.collideWith(r, res);

    System.out.println("Bounding:" +bbox);
    System.out.println("Ray: "+r);

    System.out.println("Num collisions: "+res.size());
    for (int i = 0; i < res.size(); i++){
        System.out.println("--- Collision #"+i+" ---");
        float dist = res.getCollision(i).getDistance();
        Vector3f pt = res.getCollision(i).getContactPoint();
        System.out.println("distance: "+dist);
        System.out.println("point: "+pt);
    }
}
 
Example #13
Source File: CollideIgnoreTransformTest.java    From jmonkeyengine with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
@Test
public void testPhantomTriangles() {
    JmeSystem.setSystemDelegate(new MockJmeSystemDelegate());
    assetManager = new DesktopAssetManager();
    assetManager.registerLocator(null, ClasspathLocator.class);
    assetManager.registerLoader(J3MLoader.class, "j3m", "j3md");
    rootNode = new Node();

    createRedSquare();

    rootNode.updateLogicalState(0.01f);
    rootNode.updateGeometricState();
    /**
     * ray in the -Z direction, starting from (0.5, 0.6, 10)
     */
    Ray ray1 = new Ray(/* origin */new Vector3f(0.5f, 0.6f, 10f),
            /* direction */ new Vector3f(0f, 0f, -1f));
    castRay(ray1, 1);
    /**
     * ray in the -Z direction, starting from (0.5, 3, 10)
     */
    Ray ray0 = new Ray(/* origin */new Vector3f(0.5f, 3f, 10f),
            /* direction */ new Vector3f(0f, 0f, -1f));
    castRay(ray0, 0);
}
 
Example #14
Source File: BresenhamTerrainPicker.java    From jmonkeyengine with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
protected boolean checkTriangles(float gridX, float gridY, Ray pick, Vector3f intersection, TerrainPatch patch, Triangle store) {
    if (!getTriangles(gridX, gridY, patch))
        return false;

    if (pick.intersectWhere(gridTriA, intersection)) {
        store.set(gridTriA.get1(), gridTriA.get2(), gridTriA.get3());
        return true;
    } else {
        if (pick.intersectWhere(gridTriB, intersection)) {
            store.set(gridTriB.get1(), gridTriB.get2(), gridTriB.get3());
            return true;
        }
    }

    return false;
}
 
Example #15
Source File: SimplePlayerAttackBehavior.java    From MonkeyBrains with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
public void onAction(String name, boolean isPressed, float tpf) {
    operation = name;
    if (isPressed) {
        supportedOperations.get(operation).setEnabled(true);
        Vector2f click2d = MonkeyBrainsAppState.getInstance().getApp().getInputManager().getCursorPosition();
        Vector3f click3d = agent.getCamera().getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 0f).clone();
        Vector3f dir = agent.getCamera().getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 1f).subtractLocal(click3d).normalizeLocal();
        Ray ray = new Ray(click3d, dir);
        Plane ground = new Plane(Vector3f.UNIT_Y, 0);
        Vector3f groundpoint = new Vector3f();
        ray.intersectsWherePlane(ground, groundpoint);
        ((SimpleAttackBehavior) supportedOperations.get(operation)).setTarget(groundpoint);
    } else {
        operation = null;
    }
}
 
Example #16
Source File: SpatialSelector.java    From OpenRTS with MIT License 5 votes vote down vote up
public Geometry getGeometry(Node n) {
	Ray r;
	if (centered) {
		r = getCameraRay();
	} else {
		r = getMouseRay();
	}
	return PointUtil.getPointedGeometry(n, r);
}
 
Example #17
Source File: SpatialSelector.java    From OpenRTS with MIT License 5 votes vote down vote up
public Point2D getCoord(Node n) {
	Ray r;
	if (centered) {
		r = getCameraRay();
	} else {
		r = getMouseRay();
	}
	return PointUtil.getPointedCoord(n, r);
}
 
Example #18
Source File: SpatialSelector.java    From OpenRTS with MIT License 5 votes vote down vote up
public Point2D getCoord(Node n, Point2D screenCoord) {
	Vector3f origin = cam.getWorldCoordinates(TranslateUtil.toVector2f(screenCoord), 0f);
	Vector3f direction = cam.getWorldCoordinates(TranslateUtil.toVector2f(screenCoord), 1f);
	direction.subtractLocal(origin).normalizeLocal();
	Ray r = new Ray(origin, direction);
	return PointUtil.getPointedCoord(n, r);
}
 
Example #19
Source File: PointUtil.java    From OpenRTS with MIT License 5 votes vote down vote up
private static CollisionResult getCollision(Node n, Ray r) {
	CollisionResults results = new CollisionResults();
	n.collideWith(r, results);
	if (results.size() == 0) {
		return null;
	}
	return results.getClosestCollision();
}
 
Example #20
Source File: ShapeGeometryTest.java    From jmonkeyengine with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
@Test
public void testCylinders() {
    Random random = new Random();
    
    // Create a cylinder, cast a random ray, and ensure everything goes well.
    Node scene = new Node("Scene Node");

    for (int i = 0; i < NUMBER_OF_TRIES; i++) {
        scene.detachAllChildren();

        Cylinder cylinder = new Cylinder(2, 8, 1, 1, true);
        Geometry geometry = new Geometry("cylinder", cylinder);
        geometry.rotate(FastMath.HALF_PI, 0, 0);
        scene.attachChild(geometry);

        // Cast a random ray, and count successes and IndexOutOfBoundsExceptions.
        Vector3f randomPoint = new Vector3f(random.nextFloat(), random.nextFloat(), random.nextFloat());
        Vector3f randomDirection = new Vector3f(random.nextFloat(), random.nextFloat(), random.nextFloat());
        randomDirection.normalizeLocal();

        Ray ray = new Ray(randomPoint, randomDirection);
        CollisionResults collisionResults = new CollisionResults();

        // If the geometry is invalid, this should throw various exceptions.
        scene.collideWith(ray, collisionResults);
    }
}
 
Example #21
Source File: PointUtil.java    From OpenRTS with MIT License 5 votes vote down vote up
public static Point2D getPointedCoord(Node n, Ray r) {
	CollisionResult collision = getCollision(n, r);
	if (collision == null) {
		return null;
	}
	// return Translator.toPoint2D(collision.getContactPoint());
	Vector3f p = collision.getContactPoint();
	return new Point2D(p.x, p.y);
}
 
Example #22
Source File: Octree.java    From MikuMikuStudio with BSD 2-Clause "Simplified" License 5 votes vote down vote up
public void intersect(Ray r, float farPlane, Geometry[] geoms, CollisionResults results){
    boundResults.clear();
    bbox.collideWith(r, boundResults);
    if (boundResults.size() > 0){
        float tMin = boundResults.getClosestCollision().getDistance();
        float tMax = boundResults.getFarthestCollision().getDistance();

        tMin = Math.max(tMin, 0);
        tMax = Math.min(tMax, farPlane);

        root.intersectWhere(r, geoms, tMin, tMax, results);
    }
}
 
Example #23
Source File: TestMousePick.java    From MikuMikuStudio with BSD 2-Clause "Simplified" License 5 votes vote down vote up
@Override
    public void simpleUpdate(float tpf){
        Vector3f origin    = cam.getWorldCoordinates(inputManager.getCursorPosition(), 0.0f);
        Vector3f direction = cam.getWorldCoordinates(inputManager.getCursorPosition(), 0.3f);
        direction.subtractLocal(origin).normalizeLocal();

        Ray ray = new Ray(origin, direction);
        CollisionResults results = new CollisionResults();
        shootables.collideWith(ray, results);
//        System.out.println("----- Collisions? " + results.size() + "-----");
//        for (int i = 0; i < results.size(); i++) {
//            // For each hit, we know distance, impact point, name of geometry.
//            float dist = results.getCollision(i).getDistance();
//            Vector3f pt = results.getCollision(i).getWorldContactPoint();
//            String hit = results.getCollision(i).getGeometry().getName();
//            System.out.println("* Collision #" + i);
//            System.out.println("  You shot " + hit + " at " + pt + ", " + dist + " wu away.");
//        }
        if (results.size() > 0) {
            CollisionResult closest = results.getClosestCollision();
            mark.setLocalTranslation(closest.getContactPoint());

            Quaternion q = new Quaternion();
            q.lookAt(closest.getContactNormal(), Vector3f.UNIT_Y);
            mark.setLocalRotation(q);

            rootNode.attachChild(mark);
        } else {
            rootNode.detachChild(mark);
        }
    }
 
Example #24
Source File: RayTrace.java    From MikuMikuStudio with BSD 2-Clause "Simplified" License 5 votes vote down vote up
public void update(){
    int w = image.getWidth();
    int h = image.getHeight();

    float wr = (float) cam.getWidth()  / image.getWidth();
    float hr = (float) cam.getHeight() / image.getHeight();

    scene.updateGeometricState();

    for (int y = 0; y < h; y++){
        for (int x = 0; x < w; x++){
            Vector2f v = new Vector2f(x * wr,y * hr);
            Vector3f pos = cam.getWorldCoordinates(v, 0.0f);
            Vector3f dir = cam.getWorldCoordinates(v, 0.3f);
            dir.subtractLocal(pos).normalizeLocal();

            Ray r = new Ray(pos, dir);

            results.clear();
            scene.collideWith(r, results);
            if (results.size() > 0){
                image.setRGB(x, h - y - 1, 0xFFFFFFFF);
            }else{
                image.setRGB(x, h - y - 1, 0xFF000000);
            }
        }
    }

    label.repaint();
}
 
Example #25
Source File: TerrainTestModifyHeight.java    From MikuMikuStudio with BSD 2-Clause "Simplified" License 5 votes vote down vote up
private Vector3f getWorldIntersection() {
    Vector3f origin = cam.getWorldCoordinates(new Vector2f(settings.getWidth() / 2, settings.getHeight() / 2), 0.0f);
    Vector3f direction = cam.getWorldCoordinates(new Vector2f(settings.getWidth() / 2, settings.getHeight() / 2), 0.3f);
    direction.subtractLocal(origin).normalizeLocal();

    Ray ray = new Ray(origin, direction);
    CollisionResults results = new CollisionResults();
    int numCollisions = terrain.collideWith(ray, results);
    if (numCollisions > 0) {
        CollisionResult hit = results.getClosestCollision();
        return hit.getContactPoint();
    }
    return null;
}
 
Example #26
Source File: HelloPicking.java    From MikuMikuStudio with BSD 2-Clause "Simplified" License 5 votes vote down vote up
public void onAction(String name, boolean keyPressed, float tpf) {
  if (name.equals("Shoot") && !keyPressed) {
    // 1. Reset results list.
    CollisionResults results = new CollisionResults();
    // 2. Aim the ray from cam loc to cam direction.
    Ray ray = new Ray(cam.getLocation(), cam.getDirection());
    // 3. Collect intersections between Ray and Shootables in results list.
    shootables.collideWith(ray, results);
    // 4. Print the results
    System.out.println("----- Collisions? " + results.size() + "-----");
    for (int i = 0; i < results.size(); i++) {
      // For each hit, we know distance, impact point, name of geometry.
      float dist = results.getCollision(i).getDistance();
      Vector3f pt = results.getCollision(i).getContactPoint();
      String hit = results.getCollision(i).getGeometry().getName();
      System.out.println("* Collision #" + i);
      System.out.println("  You shot " + hit + " at " + pt + ", " + dist + " wu away.");
    }
    // 5. Use the results (we mark the hit object)
    if (results.size() > 0) {
      // The closest collision point is what was truly hit:
      CollisionResult closest = results.getClosestCollision();
      // Let's interact - we mark the hit with a red dot.
      mark.setLocalTranslation(closest.getContactPoint());
      rootNode.attachChild(mark);
    } else {
      // No hits? Then remove the red mark.
      rootNode.detachChild(mark);
    }
  }
}
 
Example #27
Source File: TestDepthOfField.java    From MikuMikuStudio with BSD 2-Clause "Simplified" License 5 votes vote down vote up
@Override
public void simpleUpdate(float tpf) {
    Vector3f origin = cam.getWorldCoordinates(new Vector2f(settings.getWidth() / 2, settings.getHeight() / 2), 0.0f);
    Vector3f direction = cam.getWorldCoordinates(new Vector2f(settings.getWidth() / 2, settings.getHeight() / 2), 0.3f);
    direction.subtractLocal(origin).normalizeLocal();
    Ray ray = new Ray(origin, direction);
    CollisionResults results = new CollisionResults();
    int numCollisions = terrain.collideWith(ray, results);
    if (numCollisions > 0) {
        CollisionResult hit = results.getClosestCollision();
        fpsText.setText(""+hit.getDistance());
        dofFilter.setFocusDistance(hit.getDistance()/10.0f);
    }
}
 
Example #28
Source File: BIHTree.java    From MikuMikuStudio with BSD 2-Clause "Simplified" License 5 votes vote down vote up
private int collideWithRay(Ray r,
            Matrix4f worldMatrix,
            BoundingVolume worldBound,
            CollisionResults results) {

        boundResults.clear();
        worldBound.collideWith(r, boundResults);
        if (boundResults.size() > 0) {
            float tMin = boundResults.getClosestCollision().getDistance();
            float tMax = boundResults.getFarthestCollision().getDistance();

            if (tMax <= 0) {
                tMax = Float.POSITIVE_INFINITY;
            } else if (tMin == tMax) {
                tMin = 0;
            }

            if (tMin <= 0) {
                tMin = 0;
            }

            if (r.getLimit() < Float.POSITIVE_INFINITY) {
                tMax = Math.min(tMax, r.getLimit());
            }

//            return root.intersectBrute(r, worldMatrix, this, tMin, tMax, results);
            return root.intersectWhere(r, worldMatrix, this, tMin, tMax, results);
        }
        return 0;
    }
 
Example #29
Source File: BIHTree.java    From MikuMikuStudio with BSD 2-Clause "Simplified" License 5 votes vote down vote up
public int collideWith(Collidable other,
        Matrix4f worldMatrix,
        BoundingVolume worldBound,
        CollisionResults results) {

    if (other instanceof Ray) {
        Ray ray = (Ray) other;
        return collideWithRay(ray, worldMatrix, worldBound, results);
    } else if (other instanceof BoundingVolume) {
        BoundingVolume bv = (BoundingVolume) other;
        return collideWithBoundingVolume(bv, worldMatrix, results);
    } else {
        throw new UnsupportedCollisionException();
    }
}
 
Example #30
Source File: SceneEditTool.java    From MikuMikuStudio with BSD 2-Clause "Simplified" License 5 votes vote down vote up
private CollisionResult pick(Camera cam, Vector2f mouseLoc, Node node) {
    CollisionResults results = new CollisionResults();
    Ray ray = new Ray();
    Vector3f pos = cam.getWorldCoordinates(mouseLoc, 0).clone();
    Vector3f dir = cam.getWorldCoordinates(mouseLoc, 0.1f).clone();
    dir.subtractLocal(pos).normalizeLocal();
    ray.setOrigin(pos);
    ray.setDirection(dir);
    node.collideWith(ray, results);
    CollisionResult result = results.getClosestCollision();
    return result;
}