Advertisement
Giorgos_Xou

SimpleFPSCamera.java

Oct 30th, 2019
243
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 17.73 KB | None | 0 0
  1.  
  2. /**
  3.  * SimpleFPSCamera.java
  4.  *
  5.  * Copyright (c) 2013-2016, F(X)yz
  6.  * All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions are met:
  10.  *     * Redistributions of source code must retain the above copyright
  11.  * notice, this list of conditions and the following disclaimer.
  12.  *     * Redistributions in binary form must reproduce the above copyright
  13.  * notice, this list of conditions and the following disclaimer in the
  14.  * documentation and/or other materials provided with the distribution.
  15.  *     * Neither the name of F(X)yz, any associated website, nor the
  16.  * names of its contributors may be used to endorse or promote products
  17.  * derived from this software without specific prior written permission.
  18.  *
  19.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  20.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22.  * DISCLAIMED. IN NO EVENT SHALL F(X)yz BE LIABLE FOR ANY
  23.  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28.  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29.  */
  30.  
  31. package app;
  32.  
  33. import javafx.animation.AnimationTimer;
  34. import javafx.beans.property.ReadOnlyObjectProperty;
  35. import javafx.beans.property.ReadOnlyObjectWrapper;
  36. import javafx.beans.value.ObservableValue;
  37. import javafx.geometry.Point3D;
  38. import javafx.scene.Group;
  39. import javafx.scene.Parent;
  40. import javafx.scene.PerspectiveCamera;
  41. import javafx.scene.Scene;
  42. import javafx.scene.SubScene;
  43. import javafx.scene.input.KeyCode;
  44. import javafx.scene.input.KeyEvent;
  45. import javafx.scene.input.MouseEvent;
  46. import javafx.scene.input.ScrollEvent;
  47. import javafx.scene.transform.Affine;
  48. import javafx.scene.transform.Rotate;
  49. import javafx.scene.transform.Transform;
  50. import javafx.scene.transform.Translate;
  51. import javafx.util.Callback;
  52.  
  53. /**
  54.  * A self initializing First Person Shooter camera
  55.  *
  56.  * @author Jason Pollastrini aka jdub1581
  57.  */
  58. public class SimpleFPSCamera extends Parent {
  59.  
  60.     public SimpleFPSCamera() {
  61.         initialize();
  62.     }
  63.  
  64.     private void update() {
  65.         updateControls();
  66.     }
  67.  
  68.     private void updateControls() {
  69.         if (fwd && !back) {
  70.             moveForward();
  71.         }
  72.         if (strafeL) {
  73.             strafeLeft();
  74.         }
  75.         if (strafeR) {
  76.             strafeRight();
  77.         }
  78.         if (back && !fwd) {
  79.             moveBack();
  80.         }
  81.         if (up && !down) {
  82.             moveUp();
  83.         }
  84.         if (down && !up) {
  85.             moveDown();
  86.         }
  87.     }
  88.  
  89.     /*
  90.      * ==========================================================================
  91.      * Initialization
  92.      */
  93.     private final Group root = new Group();
  94.     private final Affine affine = new Affine();
  95.     private final Translate t = new Translate(0, 0, 0);
  96.     private final Rotate rotateX = new Rotate(0, Rotate.X_AXIS), rotateY = new Rotate(0, Rotate.Y_AXIS),
  97.             rotateZ = new Rotate(0, Rotate.Z_AXIS);
  98.  
  99.     private boolean fwd, strafeL, strafeR, back, up, down, shift;
  100.  
  101.     private double mouseSpeed = 1.0, mouseModifier = 0.1;
  102.     private double moveSpeed = 10.0;
  103.     private double mousePosX;
  104.     private double mousePosY;
  105.     private double mouseOldX;
  106.     private double mouseOldY;
  107.     private double mouseDeltaX;
  108.     private double mouseDeltaY;
  109.  
  110.     private void initialize() {
  111.         getChildren().add(root);
  112.         getTransforms().add(affine);
  113.         initializeCamera();
  114.         startUpdateThread();
  115.     }
  116.  
  117.     private void KEY_ACTION(boolean PRESSED, KeyCode key) {
  118.  
  119.         switch (key) {
  120.         case Q:
  121.             up = PRESSED;
  122.             break;
  123.         case E:
  124.             down = PRESSED;
  125.             break;
  126.         case W:
  127.             fwd = PRESSED;
  128.             break;
  129.         case S:
  130.             back = PRESSED;
  131.             break;
  132.         case A:
  133.             strafeL = PRESSED;
  134.             break;
  135.         case D:
  136.             strafeR = PRESSED;
  137.             break;
  138.         case SHIFT:
  139.             shift = PRESSED;
  140.             moveSpeed = 10 + (10 * (PRESSED ? 1 : 0));
  141.             break;
  142.         }
  143.     }
  144.  
  145.     KeyCode _key = KeyCode.Q; // ~ it is better to have Q than anything else in this case of KEY_ACTION
  146.                               // function because else it would have cheked all possibilities [...] ?
  147.                               // 29/9/2019
  148.  
  149.     public void loadControlsForSubScene(SubScene scene) {
  150.         // sceneProperty().addListener(l -> { // Comment That Part
  151.         if (scene != null) { // Change getScene() to scene.getScene()
  152.  
  153.             scene.addEventHandler(KeyEvent.ANY, key -> {
  154.  
  155.                 _key = key.getCode();
  156.  
  157.                 if (key.getEventType() == KeyEvent.KEY_PRESSED) {
  158.  
  159.                     KEY_ACTION(true, _key); // Pressed = true , KeyEvent
  160.  
  161.                 } else if (key.getEventType() == KeyEvent.KEY_RELEASED) {
  162.  
  163.                     KEY_ACTION(false, _key); // Released = false , KeyEvent
  164.  
  165.                 }
  166.  
  167.                 key.consume();
  168.  
  169.             });
  170.  
  171.         }
  172.         // });
  173.         scene.addEventHandler(MouseEvent.ANY, me -> {
  174.  
  175.             if (me.getEventType().equals(MouseEvent.MOUSE_PRESSED)) {
  176.                 scene.requestFocus();
  177.                 me.consume();
  178.  
  179.                 mousePosX = me.getSceneX();
  180.                 mousePosY = me.getSceneY();
  181.                 mouseOldX = me.getSceneX();
  182.                 mouseOldY = me.getSceneY();
  183.  
  184.             } else if (me.getEventType().equals(MouseEvent.MOUSE_DRAGGED)) {
  185.  
  186.                 mouseOldX = mousePosX;
  187.                 mouseOldY = mousePosY;
  188.                 mousePosX = me.getSceneX();
  189.                 mousePosY = me.getSceneY();
  190.                 mouseDeltaX = (mousePosX - mouseOldX);
  191.                 mouseDeltaY = (mousePosY - mouseOldY);
  192.  
  193.                 mouseSpeed = 1.0;
  194.                 mouseModifier = 0.1;
  195.  
  196.                 if (me.isPrimaryButtonDown()) {
  197.                     if (me.isControlDown()) {
  198.                         mouseSpeed = 0.1;
  199.                     }
  200.                     if (me.isShiftDown()) {
  201.                         mouseSpeed = 1.0;
  202.                     }
  203.                     t.setX(getPosition().getX());
  204.                     t.setY(getPosition().getY());
  205.                     t.setZ(getPosition().getZ());
  206.  
  207.                     affine.setToIdentity();
  208.  
  209.                     rotateY.setAngle(MathUtils.clamp(-360,
  210.                             ((rotateY.getAngle() + mouseDeltaX * (mouseSpeed * mouseModifier)) % 360 + 540) % 360 - 180,
  211.                             360)); // horizontal
  212.                     rotateX.setAngle(MathUtils.clamp(-45,
  213.                             ((rotateX.getAngle() - mouseDeltaY * (mouseSpeed * mouseModifier)) % 360 + 540) % 360 - 180,
  214.                             35)); // vertical
  215.                     affine.prepend(t.createConcatenation(rotateY.createConcatenation(rotateX)));
  216.  
  217.                 } else if (me.isSecondaryButtonDown()) {
  218.                     /*
  219.                      * init zoom?
  220.                      */
  221.                 } else if (me.isMiddleButtonDown()) {
  222.                     /*
  223.                      * init panning?
  224.                      */
  225.                 }
  226.  
  227.             } else if (me.getEventType().equals(MouseEvent.MOUSE_RELEASED)) {
  228.                 // if (!scene.isFocused()){ scene.requestFocus(); }
  229.                 // System.out.println(scene.getScene().getFocusOwner().getId() + " - HOW IS THIS
  230.                 // POSSIBLE .__. ??");
  231.             } else if (me.getEventType().equals(MouseEvent.MOUSE_ENTERED_TARGET)) {
  232.  
  233.                 // if (scene.isFocused()){ scene.requestFocus(); }
  234.  
  235.             } else if (me.getEventType().equals(MouseEvent.MOUSE_EXITED)) {
  236.  
  237.                 // if (scene.isFocused()){ scene.requestFocus(); }
  238.             }
  239.  
  240.         });
  241.  
  242.         scene.addEventHandler(ScrollEvent.ANY, se -> {
  243.  
  244.             if (se.getEventType().equals(ScrollEvent.SCROLL_STARTED)) {
  245.  
  246.             } else if (se.getEventType().equals(ScrollEvent.SCROLL)) {
  247.  
  248.             } else if (se.getEventType().equals(ScrollEvent.SCROLL_FINISHED)) {
  249.  
  250.             }
  251.         });
  252.  
  253.         scene.focusedProperty().addListener(
  254.                 (ObservableValue<? extends Boolean> observable, Boolean oldFocusValue, Boolean newFocusValue) -> {
  255.  
  256.                     // if (!newFocusValue) { KEY_ACTION(false , _key); }; // Released = false , KeyEvent
  257.                    
  258.                     fwd = false;
  259.                     strafeL = false;
  260.                     strafeR = false;
  261.                     back = false;
  262.                     up = false;
  263.                     down = false;
  264.                     shift = false;
  265.  
  266.                 });
  267.     }
  268.  
  269.     public void loadControlsForScene(Scene scene) {
  270.  
  271.         scene.addEventHandler(KeyEvent.ANY, ke -> {
  272.             if (ke.getEventType() == KeyEvent.KEY_PRESSED) {
  273.                 switch (ke.getCode()) {
  274.                 case Q:
  275.                     up = true;
  276.                     break;
  277.                 case E:
  278.                     down = true;
  279.                     break;
  280.                 case W:
  281.                     fwd = true;
  282.                     break;
  283.                 case S:
  284.                     back = true;
  285.                     break;
  286.                 case A:
  287.                     strafeL = true;
  288.                     break;
  289.                 case D:
  290.                     strafeR = true;
  291.                     break;
  292.                 case SHIFT:
  293.                     shift = true;
  294.                     moveSpeed = 20;
  295.                     break;
  296.                 }
  297.             } else if (ke.getEventType() == KeyEvent.KEY_RELEASED) {
  298.                 switch (ke.getCode()) {
  299.                 case Q:
  300.                     up = false;
  301.                     break;
  302.                 case E:
  303.                     down = false;
  304.                     break;
  305.                 case W:
  306.                     fwd = false;
  307.                     break;
  308.                 case S:
  309.                     back = false;
  310.                     break;
  311.                 case A:
  312.                     strafeL = false;
  313.                     break;
  314.                 case D:
  315.                     strafeR = false;
  316.                     break;
  317.                 case SHIFT:
  318.                     moveSpeed = 10;
  319.                     shift = false;
  320.                     break;
  321.                 }
  322.             }
  323.             ke.consume();
  324.         });
  325.         scene.addEventHandler(MouseEvent.ANY, me -> {
  326.  
  327.             if (me.getEventType().equals(MouseEvent.MOUSE_PRESSED)) {
  328.                 mousePosX = me.getSceneX();
  329.                 mousePosY = me.getSceneY();
  330.                 mouseOldX = me.getSceneX();
  331.                 mouseOldY = me.getSceneY();
  332.  
  333.             } else if (me.getEventType().equals(MouseEvent.MOUSE_DRAGGED)) {
  334.                 mouseOldX = mousePosX;
  335.                 mouseOldY = mousePosY;
  336.                 mousePosX = me.getSceneX();
  337.                 mousePosY = me.getSceneY();
  338.                 mouseDeltaX = (mousePosX - mouseOldX);
  339.                 mouseDeltaY = (mousePosY - mouseOldY);
  340.  
  341.                 mouseSpeed = 1.0;
  342.                 mouseModifier = 0.1;
  343.  
  344.                 if (me.isPrimaryButtonDown()) {
  345.                     if (me.isControlDown()) {
  346.                         mouseSpeed = 0.1;
  347.                     }
  348.                     if (me.isShiftDown()) {
  349.                         mouseSpeed = 1.0;
  350.                     }
  351.                     t.setX(getPosition().getX());
  352.                     t.setY(getPosition().getY());
  353.                     t.setZ(getPosition().getZ());
  354.  
  355.                     affine.setToIdentity();
  356.  
  357.                     rotateY.setAngle(MathUtils.clamp(-360,
  358.                             ((rotateY.getAngle() + mouseDeltaX * (mouseSpeed * mouseModifier)) % 360 + 540) % 360 - 180,
  359.                             360)); // horizontal
  360.                     rotateX.setAngle(MathUtils.clamp(-45,
  361.                             ((rotateX.getAngle() - mouseDeltaY * (mouseSpeed * mouseModifier)) % 360 + 540) % 360 - 180,
  362.                             35)); // vertical
  363.                     affine.prepend(t.createConcatenation(rotateY.createConcatenation(rotateX)));
  364.  
  365.                 } else if (me.isSecondaryButtonDown()) {
  366.                     /*
  367.                      * init zoom?
  368.                      */
  369.                 } else if (me.isMiddleButtonDown()) {
  370.                     /*
  371.                      * init panning?
  372.                      */
  373.                 }
  374.             }
  375.         });
  376.  
  377.         scene.addEventHandler(ScrollEvent.ANY, se -> {
  378.  
  379.             if (se.getEventType().equals(ScrollEvent.SCROLL_STARTED)) {
  380.  
  381.             } else if (se.getEventType().equals(ScrollEvent.SCROLL)) {
  382.  
  383.             } else if (se.getEventType().equals(ScrollEvent.SCROLL_FINISHED)) {
  384.  
  385.             }
  386.         });
  387.     }
  388.  
  389.     private void initializeCamera() {
  390.         getCamera().setNearClip(0.1);
  391.         getCamera().setFarClip(100000);
  392.         getCamera().setFieldOfView(42);
  393.         getCamera().setVerticalFieldOfView(true);
  394.         root.getChildren().add(getCamera());
  395.     }
  396.  
  397.     private void startUpdateThread() {
  398.         new AnimationTimer() {
  399.             @Override
  400.             public void handle(long now) {
  401.                 update();
  402.             }
  403.         }.start();
  404.     }
  405.     /*
  406.      * ==========================================================================
  407.      * Movement
  408.      */
  409.  
  410.     private void moveForward() {
  411.         affine.setTx(getPosition().getX() + moveSpeed * getN().getX());
  412.         affine.setTy(getPosition().getY() + moveSpeed * getN().getY());
  413.         affine.setTz(getPosition().getZ() + moveSpeed * getN().getZ());
  414.     }
  415.  
  416.     private void strafeLeft() {
  417.         affine.setTx(getPosition().getX() + moveSpeed * -getU().getX());
  418.         affine.setTy(getPosition().getY() + moveSpeed * -getU().getY());
  419.         affine.setTz(getPosition().getZ() + moveSpeed * -getU().getZ());
  420.     }
  421.  
  422.     private void strafeRight() {
  423.         affine.setTx(getPosition().getX() + moveSpeed * getU().getX());
  424.         affine.setTy(getPosition().getY() + moveSpeed * getU().getY());
  425.         affine.setTz(getPosition().getZ() + moveSpeed * getU().getZ());
  426.     }
  427.  
  428.     private void moveBack() {
  429.         affine.setTx(getPosition().getX() + moveSpeed * -getN().getX());
  430.         affine.setTy(getPosition().getY() + moveSpeed * -getN().getY());
  431.         affine.setTz(getPosition().getZ() + moveSpeed * -getN().getZ());
  432.     }
  433.  
  434.     private void moveUp() {
  435.         affine.setTx(getPosition().getX() + moveSpeed * -getV().getX());
  436.         affine.setTy(getPosition().getY() + moveSpeed * -getV().getY());
  437.         affine.setTz(getPosition().getZ() + moveSpeed * -getV().getZ());
  438.     }
  439.  
  440.     private void moveDown() {
  441.         affine.setTx(getPosition().getX() + moveSpeed * getV().getX());
  442.         affine.setTy(getPosition().getY() + moveSpeed * getV().getY());
  443.         affine.setTz(getPosition().getZ() + moveSpeed * getV().getZ());
  444.     }
  445.  
  446.     /*
  447.      * ==========================================================================
  448.      * Properties
  449.      */
  450.     private final ReadOnlyObjectWrapper<PerspectiveCamera> camera = new ReadOnlyObjectWrapper<>(this, "camera",
  451.             new PerspectiveCamera(true));
  452.  
  453.     public final PerspectiveCamera getCamera() {
  454.         return camera.get();
  455.     }
  456.  
  457.     public ReadOnlyObjectProperty cameraProperty() {
  458.         return camera.getReadOnlyProperty();
  459.     }
  460.  
  461.     /*
  462.      * ==========================================================================
  463.      * Callbacks | R | Up| F | | P| U |mxx|mxy|mxz| |tx| V |myx|myy|myz| |ty| N
  464.      * |mzx|mzy|mzz| |tz|
  465.      *
  466.      */
  467.     // Forward / look direction
  468.     private final Callback<Transform, Point3D> F = (a) -> {
  469.         return new Point3D(a.getMzx(), a.getMzy(), a.getMzz());
  470.     };
  471.     private final Callback<Transform, Point3D> N = (a) -> {
  472.         return new Point3D(a.getMxz(), a.getMyz(), a.getMzz());
  473.     };
  474.     // up direction
  475.     private final Callback<Transform, Point3D> UP = (a) -> {
  476.         return new Point3D(a.getMyx(), a.getMyy(), a.getMyz());
  477.     };
  478.     private final Callback<Transform, Point3D> V = (a) -> {
  479.         return new Point3D(a.getMxy(), a.getMyy(), a.getMzy());
  480.     };
  481.     // right direction
  482.     private final Callback<Transform, Point3D> R = (a) -> {
  483.         return new Point3D(a.getMxx(), a.getMxy(), a.getMxz());
  484.     };
  485.     private final Callback<Transform, Point3D> U = (a) -> {
  486.         return new Point3D(a.getMxx(), a.getMyx(), a.getMzx());
  487.     };
  488.     // position
  489.     private final Callback<Transform, Point3D> P = (a) -> {
  490.         return new Point3D(a.getTx(), a.getTy(), a.getTz());
  491.     };
  492.  
  493.     private Point3D getF() {
  494.         return F.call(getLocalToSceneTransform());
  495.     }
  496.  
  497.     public Point3D getLookDirection() {
  498.         return getF();
  499.     }
  500.  
  501.     private Point3D getN() {
  502.         return N.call(getLocalToSceneTransform());
  503.     }
  504.  
  505.     public Point3D getLookNormal() {
  506.         return getN();
  507.     }
  508.  
  509.     private Point3D getR() {
  510.         return R.call(getLocalToSceneTransform());
  511.     }
  512.  
  513.     private Point3D getU() {
  514.         return U.call(getLocalToSceneTransform());
  515.     }
  516.  
  517.     private Point3D getUp() {
  518.         return UP.call(getLocalToSceneTransform());
  519.     }
  520.  
  521.     private Point3D getV() {
  522.         return V.call(getLocalToSceneTransform());
  523.     }
  524.  
  525.     public final Point3D getPosition() {
  526.         return P.call(getLocalToSceneTransform());
  527.     }
  528.  
  529. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement