이 질문의 나의 독서 목적은 (카메라가 커서에 직면하지만, 어디 어디하지 촬영되지 않는 것입니다 화면 중앙에 있음)가 가리키고 있습니다.
이 작업은 cam.getWorldCoordinates(screenPosition, zDepth);
명령을 사용하여 수행 할 수 있습니다. 이는 화면의 screenPosition 지점에서 끝날 공간에서 3D 점을 반환합니다. 따라서 zDepth가 0이고 zDepth가 1 인 점을 바깥 쪽을 향하는 커서 위치에서 만들면 커서가 "끝났습니다"라는 것이 선택됩니다. screen 위치는 창 왼쪽 하단의 픽셀 단위입니다.
이 기술을 사용하는 예제 프로그램은 다음과 같습니다. hello picking의 두 번째 부분을 기반으로합니다.
내 예에서
이 커서가 키보드를 사용하여 이동은 (H는, J는, K, U)하지만 마우스 클릭도 사용될 수있다 (그러나 나는 주변을 두리번을 위해 마우스를 사용하고 있습니다)
import com.jme3.app.SimpleApplication;
import com.jme3.collision.CollisionResults;
import com.jme3.font.BitmapText;
import com.jme3.input.KeyInput;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Ray;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.shape.Box;
public class Main extends SimpleApplication {
public static KeyBindings keyBindings;
public Vector2f cursorPosition=new Vector2f(100,100);
public Node shootables=new Node();
public Node crossHairNode=new Node();
public static void main(String[] args) {
Main app = new Main();
app.start();
}
@Override
public void simpleInitApp() {
//bind keys to move cursor
keyBindings=new KeyBindings(inputManager); //for managing keystrokes
keyBindings.registerKeyBinding(KeyInput.KEY_SPACE, "fire");
keyBindings.registerKeyBinding(KeyInput.KEY_U, "up");
keyBindings.registerKeyBinding(KeyInput.KEY_J, "down");
keyBindings.registerKeyBinding(KeyInput.KEY_H, "left");
keyBindings.registerKeyBinding(KeyInput.KEY_K, "right");
initGui();
Box b = new Box(Vector3f.ZERO, 2, 2, 2);
Geometry geom = new Geometry("BigBox", b);
Box b2 = new Box(Vector3f.ZERO, 1, 1, 1);
Geometry geom2 = new Geometry("SmallBox", b2);
geom2.setLocalTranslation(3, 0, 3);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Blue);
geom.setMaterial(mat);
geom2.setMaterial(mat);
rootNode.attachChild(shootables);
shootables.attachChild(geom);
shootables.attachChild(geom2);
}
@Override
public void simpleUpdate(float tpf) {
updateCrossHairs();
if (keyBindings.getBinding("fire").hasBecomeTrueSinceLastAccess()){
CollisionResults results = new CollisionResults();
Vector3f cursor3dLocation = cam.getWorldCoordinates(
new Vector2f(cursorPosition.x, cursorPosition.y), 0f).clone();
Vector3f dir = cam.getWorldCoordinates(
new Vector2f(cursorPosition.x, cursorPosition.y), 1f).subtractLocal(cursor3dLocation).normalizeLocal();
Ray ray = new Ray(cursor3dLocation, dir);
shootables.collideWith(ray, results);
if (results.size()>0){
resultsText.setText("Hit: " + results.getClosestCollision().getGeometry().getName());
resultsText.setLocalTranslation(settings.getWidth()-resultsText.getLineWidth(),resultsText.getLineHeight(), 0);
}else{
resultsText.setText("Missed");
resultsText.setLocalTranslation(settings.getWidth()-resultsText.getLineWidth(),resultsText.getLineHeight(), 0);
}
}
}
private void updateCrossHairs(){
if (keyBindings.getBinding("up").getValue()==true){
cursorPosition.y+=1;
}
if (keyBindings.getBinding("down").getValue()==true){
cursorPosition.y+=-1;
}
if (keyBindings.getBinding("left").getValue()==true){
cursorPosition.x+=-1;
}
if (keyBindings.getBinding("right").getValue()==true){
cursorPosition.x+=+1;
}
crossHairNode.setLocalTranslation(cursorPosition.x - crossHair.getLineWidth()/2,cursorPosition.y + crossHair.getLineHeight()/2, 0);
}
BitmapText crossHair;
BitmapText instructions;
BitmapText resultsText;
private void initGui() {
setDisplayStatView(false);
guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
crossHair = new BitmapText(guiFont, false);
crossHair.setSize(guiFont.getCharSet().getRenderedSize() * 2);
crossHair.setText("+"); // crosshairs
crossHairNode.setLocalTranslation(cursorPosition.x - crossHair.getLineWidth()/2,cursorPosition.y + crossHair.getLineHeight()/2, 0);
guiNode.attachChild(crossHairNode);
crossHairNode.attachChild(crossHair);
instructions= new BitmapText(guiFont, false);
instructions.setSize(guiFont.getCharSet().getRenderedSize());
instructions.setText("Move cross hairs with U,H,J,K keys, fire with space \n (WSAD moves camera position and look with mouse)");
instructions.setLocalTranslation(0, settings.getHeight(), 0);
guiNode.attachChild(instructions);
resultsText= new BitmapText(guiFont, false);
resultsText.setSize(guiFont.getCharSet().getRenderedSize());
resultsText.setText("Press Space to fire");
resultsText.setLocalTranslation(settings.getWidth()-resultsText.getLineWidth(),resultsText.getLineHeight(), 0);
guiNode.attachChild(resultsText);
}
@Override
public void simpleRender(RenderManager rm) {
//TODO: add render code
}
}
키 바인딩은, 커서의 움직임을 제어하는 데에만 사용 :
import com.jme3.input.InputManager;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import java.util.ArrayList;
import java.util.Locale;
public class KeyBindings implements ActionListener{
private InputManager inputManager;
private ArrayList<String> bindingString=new ArrayList<String>(100);
private ArrayList<KeyBinding> binding=new ArrayList<KeyBinding>(100);
public KeyBindings(InputManager inputManager){
this.inputManager=inputManager;
}
public void registerKeyBinding(int key,String bindingName){
bindingName=preprocess(bindingName);
inputManager.addMapping(bindingName, new KeyTrigger(key));
inputManager.addListener(this, bindingName);
binding.add(new KeyBinding());
bindingString.add(bindingName);
}
public void registerMouseBinding(int button,String bindingName){
bindingName=preprocess(bindingName);
inputManager.addMapping(bindingName, new MouseButtonTrigger(button));
inputManager.addListener(this, bindingName);
binding.add(new KeyBinding());
bindingString.add(bindingName);
}
public KeyBinding getBinding(String bindingName){
//get which binding we're after
bindingName=preprocess(bindingName);
int index=bindingString.indexOf(bindingName);
if (index!=-1){
return binding.get(index);
}else{
return null;
}
}
public void onAction(String bindingName, boolean isPressed, float tpf) {
bindingName=preprocess(bindingName);
//get which binding we're after
int index=bindingString.indexOf(bindingName);
if (index!=-1){
binding.get(index).setValue(isPressed);
}
}
private String preprocess(String string){
return string.toUpperCase();
}
}
public class KeyBinding {
private boolean value;
private boolean changedSinceLastAccess; //to avoid multiclicks etc
private boolean valueTrueSinceLastAccess;
public void setValue(boolean value){
this.value=value;
changedSinceLastAccess=true;
if (value==true){
valueTrueSinceLastAccess=true;
}
}
public boolean hasChangedSinceLastAccess(){
return changedSinceLastAccess;
}
public boolean hasBecomeTrueSinceLastAccess(){
//this collects any trues since the last access, is good for things like mouse clicks,
//which are instantaneous and you want then recorded on the next tick
if (valueTrueSinceLastAccess==true){
valueTrueSinceLastAccess=false;
return true;
}else{
return false;
}
}
public boolean getValue(){
changedSinceLastAccess=false;
valueTrueSinceLastAccess=false;
return value;
}
public boolean getValue_withoutNotifying(){
return value;
}
}
와우 그게 멋진! –