2017-09-12 1 views
1

가 수정되었습니다.자바 FX 3D 회전은 내가 X와 Y 마우스 드래그 이벤트가 직관적 인 방법으로 내 가상 트랙볼을 회전 가상 트랙볼 장치를 만들려면 자바 FX를 사용하여 가상 트랙볼</p> <p>만들기 축

  • X 바닥
  • Z 바로
  • Y 증가 상단 왼쪽 증가 뷰어를 향해 화면에 수직 증가 내 장면이되는 축이 (적어도 저)

    직관 수단

세로 마우스 끌기 이벤트를 사용하여 트랙볼이 장면 X 축을 중심으로 회전하고 마우스의 가로 끌기 이벤트가 발생하여 트랙 바 0 ~ 장면 Y 축을 중심으로 회전합니다. 빨강, Y : 녹색, Z : 파란색하는 PerspectiveCamera 축 원점에 대한 교육 카메라, 내 트랙볼 오라클 자바 FX SmampleApp 3D를 시작으로

, 내 장면 는 고정 축 X을 포함, 그래서 일을 수정 한 (현재는 큐브이므로 은 회전 할 때 어떻게 동작 하는지를 볼 수 있습니다).

  • 마우스 X 방향으로의 이동을 끌고가
  • 마우스 Y 방향으로 이동 끌고 트랙볼의 Y 축 주위 트랙볼을 회전하면 트랙볼 주위 트랙볼 회전 x 축

먼저 트랙볼을 45도 회전시킵니다. Y 축 ( 마우스를 수평으로 끌어서). 그런 다음 마우스를 세로로 드래그하면 트랙볼 이 X 축을 중심으로 회전합니다. 그러나 트랙볼의 X 축은 이제 이전 회전으로 45도를 통해 으로 회전했으며, 고정 된 X 축 (즉, 고정 된 빨간색 축이 나타나는 것처럼 트랙볼을 회전시키는 동작을 얻지 못합니다.

) 내 장면이 코드에서 원래의 코드를 기반으로합니다 : https://docs.oracle.com/javase/8/javafx/graphics-tutorial/sampleapp3d.htm

하는 XForms의 코드는 https://docs.oracle.com/javase/8/javafx/graphics-tutorial/sampleapp3d-code.htm#CJAGGIFG

에서 얼마나 내 목표를 달성하기 위해 코드를 변경해야합니까?

package moleculesampleapp; 

import javafx.application.Application; 
import javafx.scene.*; 
import javafx.scene.paint.Color; 
import javafx.stage.Stage; 
import javafx.scene.paint.PhongMaterial; 
import javafx.scene.shape.Box; 
import javafx.scene.shape.Shape3D; 

public class MoleculeSampleApp1 extends Application { 

    Group root = new Group(); 
    Xform axisXForm = new Xform(); 
    Xform boxXForm = new Xform(); 
    Xform worldXForm = new Xform(); 
    Xform cameraXform = new Xform(); 
    PhongMaterial redMaterial,greenMaterial,blueMaterial; 

    PerspectiveCamera camera = new PerspectiveCamera(true); 

    private static double CAMERA_INITIAL_DISTANCE = -450; 
    private static double CAMERA_INITIAL_X_ANGLE = -10.0; 
    private static double CAMERA_INITIAL_Y_ANGLE = 0.0; 
    private static double CAMERA_NEAR_CLIP = 0.1; 
    private static double CAMERA_FAR_CLIP = 10000.0; 
    private static double AXIS_LENGTH = 250.0; 
    private static double MOUSE_SPEED = 0.1; 
    private static double ROTATION_SPEED = 2.0; 

    double mousePosX, mousePosY; 
    double mouseOldX, mouseOldY; 
    double mouseDeltaX, mouseDeltaY; 

    private void handleMouse(Scene scene) { 

     scene.setOnMousePressed(me -> { 
      mousePosX = me.getSceneX(); 
      mousePosY = me.getSceneY(); 
      mouseOldX = me.getSceneX(); 
      mouseOldY = me.getSceneY(); 
     }); 

     scene.setOnMouseDragged(me -> { 
      mouseOldX = mousePosX; 
      mouseOldY = mousePosY; 
      mousePosX = me.getSceneX(); 
      mousePosY = me.getSceneY(); 
      mouseDeltaX = (mousePosX - mouseOldX); 
      mouseDeltaY = (mousePosY - mouseOldY); 

      if (me.isPrimaryButtonDown()) { 
       boxXForm.ry.setAngle(boxXForm.ry.getAngle() - mouseDeltaX * MOUSE_SPEED * ROTATION_SPEED); // left right 
       boxXForm.rx.setAngle(boxXForm.rx.getAngle() + mouseDeltaY * MOUSE_SPEED * ROTATION_SPEED); // up down 
      } 
     }); 
    } 

    private void handleKeyboard(Scene scene) { 
     scene.setOnKeyPressed(event -> { 
      switch (event.getCode()) { 
      case Z: 
       camera.setTranslateZ(CAMERA_INITIAL_DISTANCE); 
       cameraXform.ry.setAngle(CAMERA_INITIAL_Y_ANGLE); 
       cameraXform.rx.setAngle(CAMERA_INITIAL_X_ANGLE); 
       boxXForm.reset(); 
       break; 
      } 
     }); 
    } 

    PhongMaterial createMaterial(Color diffuseColor, Color specularColor) { 
     PhongMaterial material = new PhongMaterial(diffuseColor); 
     material.setSpecularColor(specularColor); 
     return material; 
    } 

    @Override 
    public void start(Stage primaryStage) { 
     root.getChildren().add(worldXForm); 
     root.setDepthTest(DepthTest.ENABLE); 

     // Create materials 
     redMaterial = createMaterial(Color.DARKRED,Color.RED); 
     greenMaterial = createMaterial(Color.DARKGREEN,Color.GREEN); 
     blueMaterial = createMaterial(Color.DARKBLUE,Color.BLUE); 

     // Build Camera 
     root.getChildren().add(camera); 
     cameraXform.getChildren().add(camera); 
     camera.setNearClip(CAMERA_NEAR_CLIP); 
     camera.setFarClip(CAMERA_FAR_CLIP); 
     camera.setTranslateZ(CAMERA_INITIAL_DISTANCE); 
     cameraXform.ry.setAngle(CAMERA_INITIAL_Y_ANGLE); 
     cameraXform.rx.setAngle(CAMERA_INITIAL_X_ANGLE); 

     // Build Axes 
     Box xAxis = new Box(AXIS_LENGTH, 1, 1); 
     Box yAxis = new Box(1, AXIS_LENGTH, 1); 
     Box zAxis = new Box(1, 1, AXIS_LENGTH); 
     xAxis.setMaterial(redMaterial); 
     yAxis.setMaterial(greenMaterial); 
     zAxis.setMaterial(blueMaterial); 
     axisXForm.getChildren().addAll(xAxis, yAxis, zAxis); 
     worldXForm.getChildren().addAll(axisXForm); 

     // Build shiney red box 
     Shape3D box = new Box(80, 80, 80); 
     box.setMaterial(redMaterial); 
     boxXForm.getChildren().add(box); 
     worldXForm.getChildren().addAll(boxXForm); 

     Scene scene = new Scene(root, 1024, 768, true); 
     scene.setFill(Color.GREY); 
     handleKeyboard(scene); 
     handleMouse(scene); 

     primaryStage.setTitle("Molecule Sample Application"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 

     scene.setCamera(camera); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 

} 
+0

왜 당신의 인생을 힘들게 만들고 오른쪽 좌표계를 사용하지 않겠습니까? https://en.wikipedia.org/wiki/Right-hand_rule을 참조하십시오. – mipa

+0

JavaFX 기본 좌표계를 사용하고 있습니다. 그러나 어쨌든 그것은 중요하지 않습니다. 문제는 객체가 좌표계를 소유하기보다는 고정 된 장면 좌표계를 기준으로 객체를 회전시키는 방법입니다. –

+0

사실이 아닙니다. JavaFX에서는 기본 Z 축이 뷰어에서 화면으로 사라집니다. – mipa

답변

0

질문을 올바르게 이해하면이 행을 바꿀 수 있습니다.

Xform cameraXform = new Xform(RotateOrder.ZYX); 

이렇게하면 단일 회전의 순환 순서가 변경되므로 필요한 것을 제공해야합니다.

+0

아아, 아니. 카메라가 고정 된 상태로 유지되기를 바랍니다. 내 마우스 처리 코드는 구체 만 회전해야합니다 (고정되어 있어야하는 다른 3D 개체가 내 장면에 있음). –

1

이 게시물의 bronkowitz에게 감사드립니다. JavaFX 3D rotations이 솔루션을 향한 나를 이끌어 냈습니다!

package moleculesampleapp; 

import javafx.application.Application; 
import javafx.geometry.Point3D; 
import javafx.scene.*; 
import javafx.scene.paint.Color; 
import javafx.stage.Stage; 
import javafx.scene.paint.PhongMaterial; 
import javafx.scene.shape.Box; 
import javafx.scene.shape.DrawMode; 
import javafx.scene.shape.Shape3D; 
import javafx.scene.shape.Sphere; 
import javafx.scene.transform.Affine; 
import javafx.scene.transform.Rotate; 

public class MoleculeSampleApp1 extends Application { 

    Group root = new Group(); 
    XformBox cameraXform = new XformBox(); 
    XformBox ballXForm = new XformBox(); 
    Shape3D ball; 
    PhongMaterial redMaterial, greenMaterial, blueMaterial; 

    PerspectiveCamera camera = new PerspectiveCamera(true); 

    private static double CAMERA_INITIAL_DISTANCE = -450; 
    private static double CAMERA_INITIAL_X_ANGLE = -10.0; 
    private static double CAMERA_INITIAL_Y_ANGLE = 0.0; 
    private static double CAMERA_NEAR_CLIP = 0.1; 
    private static double CAMERA_FAR_CLIP = 10000.0; 
    private static double AXIS_LENGTH = 250.0; 
    private static double MOUSE_SPEED = 0.1; 
    private static double ROTATION_SPEED = 2.0; 

    double mouseStartPosX, mouseStartPosY; 
    double mousePosX, mousePosY; 
    double mouseOldX, mouseOldY; 
    double mouseDeltaX, mouseDeltaY; 

    private void handleMouse(Scene scene) { 
     System.out.printf("handleMouse%n"); 

     scene.setOnMousePressed(me -> { 
      mouseStartPosX = me.getSceneX(); 
      mouseStartPosY = me.getSceneY(); 
      mousePosX = me.getSceneX(); 
      mousePosY = me.getSceneY(); 
      mouseOldX = me.getSceneX(); 
      mouseOldY = me.getSceneY(); 
     }); 

     scene.setOnMouseDragged(me -> { 
      mouseOldX = mousePosX; 
      mouseOldY = mousePosY; 
      mousePosX = me.getSceneX(); 
      mousePosY = me.getSceneY(); 
      mouseDeltaX = (mousePosX - mouseOldX); 
      mouseDeltaY = (mousePosY - mouseOldY); 

      if (me.isPrimaryButtonDown()) { 
       ballXForm.addRotation(-mouseDeltaX * MOUSE_SPEED * ROTATION_SPEED, Rotate.Y_AXIS); 
       ballXForm.addRotation(mouseDeltaY * MOUSE_SPEED * ROTATION_SPEED, Rotate.X_AXIS); 
      } 
     }); 
    } 

    private void handleKeyboard(Scene scene) { 
     scene.setOnKeyPressed(event -> ballXForm.reset()); 
    } 

    PhongMaterial createMaterial(Color diffuseColor, Color specularColor) { 
     PhongMaterial material = new PhongMaterial(diffuseColor); 
     material.setSpecularColor(specularColor); 
     return material; 
    } 

    @Override 
    public void start(Stage primaryStage) { 
     System.out.printf("start%n"); 
     root.setDepthTest(DepthTest.ENABLE); 

     // Create materials 
     redMaterial = createMaterial(Color.DARKRED, Color.RED); 
     greenMaterial = createMaterial(Color.DARKGREEN, Color.GREEN); 
     blueMaterial = createMaterial(Color.DARKBLUE, Color.BLUE); 

     // Build Camera 
     root.getChildren().add(camera); 
     cameraXform.getChildren().add(camera); 
     camera.setNearClip(CAMERA_NEAR_CLIP); 
     camera.setFarClip(CAMERA_FAR_CLIP); 
     camera.setTranslateZ(CAMERA_INITIAL_DISTANCE); 
     camera.setTranslateZ(CAMERA_INITIAL_DISTANCE); 
     cameraXform.addRotation(CAMERA_INITIAL_X_ANGLE, Rotate.X_AXIS); 
     cameraXform.addRotation(CAMERA_INITIAL_Y_ANGLE, Rotate.Y_AXIS); 

     // Build Axes 
     Box xAxis = new Box(AXIS_LENGTH, 1, 1); 
     Box yAxis = new Box(1, AXIS_LENGTH, 1); 
     Box zAxis = new Box(1, 1, AXIS_LENGTH); 
     xAxis.setMaterial(redMaterial); 
     yAxis.setMaterial(greenMaterial); 
     zAxis.setMaterial(blueMaterial); 
     root.getChildren().addAll(xAxis, yAxis, zAxis); 

     // Build shiney red ball 
     ball = new Sphere(50); 
     ball.setDrawMode(DrawMode.LINE); // draw mesh so we can watch how it rotates 
     ballXForm.getChildren().add(ball); 
     root.getChildren().addAll(ballXForm); 

     Scene scene = new Scene(root, 1024, 768, true); 
     scene.setFill(Color.GREY); 
     handleKeyboard(scene); 
     handleMouse(scene); 

     primaryStage.setTitle("TrackBall"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 

     scene.setCamera(camera); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 

} 

class XformBox extends Group { 

    XformBox() { 
     super(); 
     getTransforms().add(new Affine()); 
    } 

    /** 
    * Accumulate rotation about specified axis 
    * 
    * @param angle 
    * @param axis 
    */ 
    public void addRotation(double angle, Point3D axis) { 
     Rotate r = new Rotate(angle, axis); 
     /** 
     * This is the important bit and thanks to bronkowitz in this post 
     * https://stackoverflow.com/questions/31382634/javafx-3d-rotations for 
     * getting me to the solution that the rotations need accumulated in 
     * this way 
     */ 
     getTransforms().set(0, r.createConcatenation(getTransforms().get(0))); 
    } 

    /** 
    * Reset transform to identity transform 
    */ 
    public void reset() { 
     getTransforms().set(0, new Affine()); 
    } 
}