如何获得更好的鼠标移动FPS,如相机移动JavaFX 8?

时间:2014-02-23 21:48:50

标签: camera javafx-8

我正在努力创建一个3D世界,我正在寻找帮助平滑我的鼠标控件以更像“FPS相机”(即:看起来鼠标在屏幕上的位置)

由于某种原因,我无法找到我的代码不好的地方..对于我来说,如果有意义的话,相机似乎是绕着一个支点移动而不仅仅是在它的轴上..

这是我的代码:

public class World3D extends Application {

private boolean forward, backward, left, right, vertControl;
private double mouX, mouY, oldX, oldY , deltaX, deltaY;
private final PerspectiveCamera camera = new PerspectiveCamera();
final Xform cameraXform = new Xform();
final Xform cameraXform2 = new Xform();
final Xform cameraXform3 = new Xform();
final double cameraDistance = 450;
final Group root = new Group();
final Group world = new Group();

@Override
public void start(Stage primaryStage) {
    root.getChildren().add(world);

    world.getChildren().add(cameraXform);
    cameraXform.getChildren().add(cameraXform2);
    cameraXform2.getChildren().add(cameraXform3);
    cameraXform3.getChildren().add(camera);
    cameraXform3.setRotateZ(180.0);

    camera.setFarClip(100000.0D);
    camera.setNearClip(0.1D);
    cameraXform.ry.setAngle(320.0);
    cameraXform.rx.setAngle(40);
    cameraXform.setTranslateZ(-800.0D);
    // sample skybox images
    //http://www.zfight.com/misc/images/textures/envmaps/grimmnight_large.jpg
    //http://www.zfight.com/misc/images/textures/envmaps/stormydays_large.jpg
    //http://www.zfight.com/misc/images/textures/envmaps/miramar_large.jpg
    //http://www.zfight.com/misc/images/textures/envmaps/interstellar_large.jpg
    //http://www.zfight.com/misc/images/textures/envmaps/violentdays_large.jpg
    SkyBox skyBox = new SkyBox(new Image("http://www.zfight.com/misc/images/textures/envmaps/violentdays_large.jpg"));

    world.getChildren().add(skyBox);

    Scene scene = new Scene(root, 1024, 768, true);
    scene.setCamera(camera);

    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);
    primaryStage.setFullScreen(true);
    primaryStage.show();

    handleMouse(scene);
    handleKeyboard(scene);
    AnimationTimer timer = new AnimationTimer() {
        @Override
        public void handle(long l) {
            if(forward && !vertControl){
                cameraXform.setTranslateZ(cameraXform.getTranslateZ() + 2.0D);
            }if(backward && !vertControl){
                cameraXform.setTranslateZ(cameraXform.getTranslateZ() - 2.0D);                
            }if(left){
                cameraXform.setTranslateX(cameraXform.getTranslateX() - 2.0D);
            }if(right){
                cameraXform.setTranslateX(cameraXform.getTranslateX() + 2.0D);
            }
            if(vertControl && forward){
                cameraXform.setTranslateY(cameraXform.getTranslateY() - 2.0D);
            }
            if(vertControl && backward){
                cameraXform.setTranslateY(cameraXform.getTranslateY() + 2.0D);
            }
        }
    };
    timer.start();
    loadAPlanet();
}

/**
 * The main() method is ignored in correctly deployed JavaFX application.
 * main() serves only as fallback in case the application can not be
 * launched through deployment artifacts, e.g., in IDEs with limited FX
 * support. NetBeans ignores main().
 *
 * @param args the command line arguments
 */
public static void main(String[] args) {
    launch(args);
}

private void handleKeyboard(Scene scene){
    scene.setOnKeyPressed((KeyEvent t) -> {
        switch(t.getCode()){
            case W:// forward like fps
                forward = true;
                break;
            case S: // backward
                backward = true;
                break;
            case A: // left
                left = true;
                break;
            case D: // right
                right = true;
                break;
            case SPACE: // can go up and down
                vertControl = true;
                break;
        }
    });
    scene.setOnKeyReleased((KeyEvent t) -> {
        switch(t.getCode()){
            case W:// forward like fps
                forward = false;
                break;
            case S: // backward
                backward = false;
                break;
            case A: // left
                left = false;
                break;
            case D: // right
                right = false;
                break;
            case SPACE: // can go up and down
                vertControl = false;
                break;
        }
    });
}

private void handleMouse(Scene scene){
    scene.setOnMouseMoved((MouseEvent t) -> {
        oldX = mouX;
        oldY = mouY;
        mouX = t.getSceneX();
        mouY = t.getSceneY();
        deltaX = (mouX - oldX);
        deltaY = (mouY - oldY);

        double modifier = 3.0;
        double modifierFactor = 0.1;

        if (t.isControlDown()) {
            modifier = 0.1;                
        }
        if (t.isShiftDown()) {
            modifier = 10.0;
        }
        cameraXform.ry.setAngle(cameraXform.ry.getAngle() + deltaX * modifierFactor * modifier * 2.0);  // +
        cameraXform.rx.setAngle(cameraXform.rx.getAngle() + deltaY * modifierFactor * modifier * 2.0);
    });

}

private void loadAPlanet(){
    Sphere s = new Sphere();
    PhongMaterial mat = new PhongMaterial();
    //mat.setDiffuseMap(new Image("http://www.zfight.com/misc/images/textures/envmaps/interstellar_large.jpg"));
    s.setMaterial(mat);
    s.setDrawMode(DrawMode.LINE);
    s.setRadius(150);
    s.setTranslateX(camera.getTranslateX());
    s.setTranslateZ(camera.getTranslateZ() + 500);
    world.getChildren().add(s);
}

}

和我的SkyBox

public class SkyBox extends Group {

private final ObservableIntegerArray faces = FXCollections.observableIntegerArray();
private final ObservableFloatArray texCoords = FXCollections.observableFloatArray();
private final ObservableFloatArray points = FXCollections.observableFloatArray();

private final double WIDTH, HEIGHT, DEPTH;
private TriangleMesh cube;
private MeshView skyBox;
private float x0, x1, x2, x3, x4, y0, y1, y2, y3;
private Image texImg;

public SkyBox(Image diff){
    this(20000,20000,20000, diff);
}

private SkyBox(double w, double h, double d, Image diffMap) {
    this.WIDTH = w;
    this.HEIGHT = h;
    this.DEPTH = d;
    this.cube = new TriangleMesh();
    this.skyBox = new MeshView();
    this.texImg = diffMap;
    PhongMaterial mat = new PhongMaterial();
    mat.setSpecularColor(Color.TRANSPARENT);
    mat.setDiffuseMap(texImg);

    this.calculatePoints();
    this.calculateTexCoords();
    this.calculateFaces();

    this.skyBox.setMesh(cube);
    this.skyBox.setMaterial(mat);
    this.skyBox.setCullFace(CullFace.NONE);

    AmbientLight light = new AmbientLight();
    light.setTranslateX(skyBox.getTranslateX() + (WIDTH / 2));
    light.setTranslateY(skyBox.getTranslateY() + (HEIGHT / 2));
    light.setTranslateZ(skyBox.getTranslateZ() + (DEPTH / 2));

    this.getChildren().addAll(skyBox, light);
}

private void calculatePoints() {
    float hw = (float) WIDTH / 2f;
    float hh = (float) HEIGHT / 2f;
    float hd = (float) DEPTH / 2f;

    points.addAll(
            hw, hh, hd,
            hw, hh, -hd,
            hw, -hh, hd,
            hw, -hh, -hd,
            -hw, hh, hd,
            -hw, hh, -hd,
            -hw, -hh, hd,
            -hw, -hh, -hd
    );
    cube.getPoints().addAll(points);

}

private void calculateFaces() {
    faces.addAll(
        0, 10, 2, 5, 1, 9,
        2, 5, 3, 4, 1, 9,
        4, 7, 5, 8, 6, 2,
        6, 2, 5, 8, 7, 3,
        0, 13, 1, 9, 4, 12,
        4, 12, 1, 9, 5, 8,
        2, 1, 6, 0, 3, 4,
        3, 4, 6, 0, 7, 3,
        0, 10, 4, 11, 2, 5,
        2, 5, 4, 11, 6, 6,
        1, 9, 3, 4, 5, 8,
        5, 8, 3, 4, 7, 3
    );
    cube.getFaces().addAll(faces);
}

private void calculateTexCoords() {
    x0 = 0f; x1 = 1 / 4f; x2 = 2 / 4f; x3 =  3 / 4f; x4 = 1f;
    y0 = 0f; y1 = 1 /3f; y2 = 2 / 3f; y3 = 1f;
    //x4 = 0; x3 = iw * 0.25f; x2 = iw / 2.0f; x1 = iw * 0.75f; x0 = iw;
    //y3 = 0; y2 = ih * 0.33f; y1 = ih * 0.66f; y0 = ih;

    texCoords.addAll(
        (x1 + 0.001f), (y0 + 0.001f),
        (x2 - 0.001f), y0,
        (x0), (y1 + 0.001f),
        (x1 + 0.001f), (y1 + 0.001f),
        (x2 - 0.001f), (y1 + 0.001f),
        x3, (y1 + 0.001f),
        (x4), (y1 + 0.001f),
        (x0), (y2 - 0.001f),
        (x1 + 0.001f), (y2 - 0.001f),
        x2, (y2 - 0.001f),
        x3, (y2 - 0.001f),
        (x4), (y2 - 0.001f),
        (x1 + 0.001f), (y3 - 0.001f),
        x2, (y3 - 0.001f)
    );
    cube.getTexCoords().addAll(texCoords);
}

public double getWidth() {
    return WIDTH;
}

public double getHeight() {
    return HEIGHT;
}

public double getDepth() {
    return DEPTH;
}

}

和Xform

import javafx.scene.Group;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Scale;
import javafx.scene.transform.Translate;

public class Xform extends Group {

public enum RotateOrder {
    XYZ, XZY, YXZ, YZX, ZXY, ZYX
}

public Translate t  = new Translate(); 
public Translate p  = new Translate(); 
public Translate ip = new Translate(); 
public Rotate rx = new Rotate();
{ rx.setAxis(Rotate.X_AXIS); }
public Rotate ry = new Rotate();
{ ry.setAxis(Rotate.Y_AXIS); }
public Rotate rz = new Rotate();
{ rz.setAxis(Rotate.Z_AXIS); }
public Scale s = new Scale();

public Xform() { 
    super(); 
    getTransforms().addAll(t, rz, ry, rx, s); 
}

public Xform(RotateOrder rotateOrder) { 
    super(); 
    // choose the order of rotations based on the rotateOrder
    switch (rotateOrder) {
    case XYZ:
        getTransforms().addAll(t, p, rz, ry, rx, s, ip); 
        break;
    case XZY:
        getTransforms().addAll(t, p, ry, rz, rx, s, ip); 
        break;
    case YXZ:
        getTransforms().addAll(t, p, rz, rx, ry, s, ip); 
        break;
    case YZX:
        getTransforms().addAll(t, p, rx, rz, ry, s, ip);  // For Camera
        break;
    case ZXY:
        getTransforms().addAll(t, p, ry, rx, rz, s, ip); 
        break;
    case ZYX:
        getTransforms().addAll(t, p, rx, ry, rz, s, ip); 
        break;
    }
}

public void setTranslate(double x, double y, double z) {
    t.setX(x);
    t.setY(y);
    t.setZ(z);
}

public void setTranslate(double x, double y) {
    t.setX(x);
    t.setY(y);
}

// Cannot override these methods as they are final:
// public void setTranslateX(double x) { t.setX(x); }
// public void setTranslateY(double y) { t.setY(y); }
// public void setTranslateZ(double z) { t.setZ(z); }
// Use these methods instead:
public void setTx(double x) { t.setX(x); }
public void setTy(double y) { t.setY(y); }
public void setTz(double z) { t.setZ(z); }

public void setRotate(double x, double y, double z) {
    rx.setAngle(x);
    ry.setAngle(y);
    rz.setAngle(z);
}

public void setRotateX(double x) { rx.setAngle(x); }
public void setRotateY(double y) { ry.setAngle(y); }
public void setRotateZ(double z) { rz.setAngle(z); }
public void setRx(double x) { rx.setAngle(x); }
public void setRy(double y) { ry.setAngle(y); }
public void setRz(double z) { rz.setAngle(z); }

public void setScale(double scaleFactor) {
    s.setX(scaleFactor);
    s.setY(scaleFactor);
    s.setZ(scaleFactor);
}

public void setScale(double x, double y, double z) {
    s.setX(x);
    s.setY(y);
    s.setZ(z);
}

// Cannot override these methods as they are final:
// public void setScaleX(double x) { s.setX(x); }
// public void setScaleY(double y) { s.setY(y); }
// public void setScaleZ(double z) { s.setZ(z); }
// Use these methods instead:
public void setSx(double x) { s.setX(x); }
public void setSy(double y) { s.setY(y); }
public void setSz(double z) { s.setZ(z); }

public void setPivot(double x, double y, double z) {
    p.setX(x);
    p.setY(y);
    p.setZ(z);
    ip.setX(-x);
    ip.setY(-y);
    ip.setZ(-z);
}

public void reset() {
    t.setX(0.0);
    t.setY(0.0);
    t.setZ(0.0);
    rx.setAngle(0.0);
    ry.setAngle(0.0);
    rz.setAngle(0.0);
    s.setX(1.0);
    s.setY(1.0);
    s.setZ(1.0);
    p.setX(0.0);
    p.setY(0.0);
    p.setZ(0.0);
    ip.setX(0.0);
    ip.setY(0.0);
    ip.setZ(0.0);
}

public void resetTSP() {
    t.setX(0.0);
    t.setY(0.0);
    t.setZ(0.0);
    s.setX(1.0);
    s.setY(1.0);
    s.setZ(1.0);
    p.setX(0.0);
    p.setY(0.0);
    p.setZ(0.0);
    ip.setX(0.0);
    ip.setY(0.0);
    ip.setZ(0.0);
}

}

任何帮助将不胜感激 (球体在世界上仅用于相机位置参考)

0 个答案:

没有答案