I have done something like that in a RobotWar example that is floating arround here somehwere and in example repository.
Here is the actionlistener if this helps you get some ideas:
[java]
public void onAction(String name, boolean isPressed, float tpf) {
if (gameFinished) {
return;
}
if (name.equals(“Shoot”) && isPressed) {
if (playerLaserBeam == null) {
Vector2f click2d = inputManager.getCursorPosition();
Vector3f click3d = cam.getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 0f).clone();
Vector3f dir = cam.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);
if (addDebugObjects) {
Sphere help = new Sphere(8, 8, 0.2f);
helper = new Geometry("helper", help);
Material mathelper = mat.clone();
mathelper.setColor("Color", ColorRGBA.Red);
mathelper.setColor("GlowColor", ColorRGBA.Magenta);
helper.setMaterial(mathelper);
helper.center().move(groundpoint);
rootNode.attachChild(helper);
System.out.println("Clicked: x=" + groundpoint.x + "; y=" + groundpoint.z);
}
float laserlength = attackRange;
CollisionResults collsions = new CollisionResults();
click3d = new Vector3f(player.getLocalTranslation());
dir = groundpoint.subtract(click3d).normalizeLocal();
click3d.y = 3;
ray = new Ray(click3d, dir);
ray.setLimit(attackRange);
enemy.collideWith(ray, collsions);
if (collsions.size() > 0) {
float enemyhealth = (Float) enemy.getUserData("health");
enemy.setUserData("health", enemyhealth - laserdamage);
laserlength = player.getLocalTranslation().distance(enemy.getLocalTranslation());
}
Cylinder laser = new Cylinder(4, 8, 0.02f, laserlength);
playerLaserBeam = new Geometry("laserbeam", laser);
Material matlaser = mat.clone();
matlaser.setColor("Color", ColorRGBA.Orange);
matlaser.setColor("GlowColor", ColorRGBA.Red);
playerLaserBeam.setMaterial(matlaser);
// attach laserbeam to player so it moves with player
player.attachChild(playerLaserBeam);
// center laserbeam on players origin
playerLaserBeam.center();
// make the laserbeam point towards clicked spot
playerLaserBeam.lookAt(groundpoint, Vector3f.UNIT_Z);
// move laserbeam up so it does not shoot on ground level, but from player model
playerLaserBeam.move(new Vector3f(0, 3, 0));
// move laserbeam forward because cylinder is created with center at player origin
playerLaserBeam.move(playerLaserBeam.getLocalRotation().mult(new Vector3f(0, 0, laserlength / 2)));
playerLaserLifetime = lasermaxlifetime;
}
}
}
[/java]
Baiscaly you have to decide from where you want to shoot the ray, for that you could attach a node without any geometry to your model with a specific name, then you can get it by its name and use its position.
For the direction, well that depends where you want to shoot the ray at. If just in the same direction as the model than you can use its rotation, if its where you clicked you have to get the direction from the clicked point and the position of the node like in the example above.
Edit: Full code.