2013-10-06 21 views
5

A causa delle nuove funzionalità di JavaFX 8, è diventato possibile combinare oggetti 3D con controlli dell'interfaccia utente 2D.JavaFX 3D - Come impostare telecamere diverse per Gruppo con oggetto 3D e SubScene con controlli UI?

Ho usato questi documenti come manuali: JavaFX Tutorial, Exploring JavaFX 3D.

Così, ho fatto questo codice:

public class CastAnalytics extends Application { 

    final Group root = new Group(); 
    final Group axisGroup = new Group(); 
    final XForm world = new XForm(); 
    final PerspectiveCamera camera = new PerspectiveCamera(true); 
    final PerspectiveCamera subSceneCamera = new PerspectiveCamera(false); 
    final XForm cameraXForm = new XForm(); 
    final XForm cameraXForm2 = new XForm(); 
    final XForm cameraXForm3 = new XForm(); 
    final double cameraDistance = 450; 
    final XForm moleculeGroup = new XForm(); 
    private Timeline timeline; 
    boolean timelinePlaying = false; 
    double CONTROL_MULTIPLIER = 0.1; 
    double SHIFT_MULTIPLIER = 0.1; 
    double ALT_MULTIPLIER = 0.5; 
    double mousePosX; 
    double mousePosY; 
    double mouseOldX; 
    double mouseOldY; 
    double mouseDeltaX; 
    double mouseDeltaY; 

    @Override 
    public void start(Stage primaryStage) throws Exception{ 
     buildScene(); 
     buildCamera(); 
     buildAxes(); 

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

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


     scene.setCamera(subSceneCamera); 
     scene.setCamera(camera); 
    } 

    private void buildScene() { 
     root.getChildren().add(world); 

     Label label = new Label("123"); 
     HBox hBox = new HBox(); 
     hBox.getChildren().add(label); 
     SubScene subScene = new SubScene(hBox, 200, 200); 
     subScene.setLayoutX(100); 
     subScene.setLayoutY(100); 

     root.getChildren().addAll(subScene); 
    } 

    private void buildCamera() { 
     root.getChildren().addAll(cameraXForm); 
     cameraXForm.getChildren().add(cameraXForm2); 
     cameraXForm2.getChildren().add(cameraXForm3); 
     cameraXForm3.getChildren().add(camera); 
     cameraXForm3.setRotateZ(180.0); 

     camera.setNearClip(0.1); 
     camera.setFarClip(10000.0); 
     camera.setTranslateZ(-cameraDistance); 
     cameraXForm.ry.setAngle(320.0); 
     cameraXForm.rx.setAngle(40); 
    } 

    private void buildAxes() { 
     Box box = new Box(200,200,200); 


     axisGroup.getChildren().addAll(box); 
     world.getChildren().addAll(axisGroup); 
    } 

    private void handleMouse(Scene scene, final Node root) { 
     scene.setOnMousePressed(new EventHandler<MouseEvent>() { 
      @Override public void handle(MouseEvent me) { 
       mousePosX = me.getSceneX(); 
       mousePosY = me.getSceneY(); 
       mouseOldX = me.getSceneX(); 
       mouseOldY = me.getSceneY(); 
      } 
     }); 
     scene.setOnMouseDragged(new EventHandler<MouseEvent>() { 
      @Override 
      public void handle(MouseEvent me) { 
       mouseOldX = mousePosX; 
       mouseOldY = mousePosY; 
       mousePosX = me.getSceneX(); 
       mousePosY = me.getSceneY(); 
       mouseDeltaX = (mousePosX - mouseOldX); 
       mouseDeltaY = (mousePosY - mouseOldY); 

       double modifier = 1.0; 
       double modifierFactor = 0.1; 

       if (me.isControlDown()) { 
        modifier = 0.1; 
       } 
       if (me.isShiftDown()) { 
        modifier = 10.0; 
       } 
       if (me.isPrimaryButtonDown()) { 
        cameraXForm.ry.setAngle(cameraXForm.ry.getAngle() - mouseDeltaX * modifierFactor * modifier * 2.0); // + 
        cameraXForm.rx.setAngle(cameraXForm.rx.getAngle() + mouseDeltaY * modifierFactor * modifier * 2.0); // - 
       } else if (me.isSecondaryButtonDown()) { 
        double z = camera.getTranslateZ(); 
        double newZ = z + mouseDeltaX * modifierFactor * modifier; 
        camera.setTranslateZ(newZ); 
       } else if (me.isMiddleButtonDown()) { 
        cameraXForm2.t.setX(cameraXForm2.t.getX() + mouseDeltaX * modifierFactor * modifier * 0.3); // - 
        cameraXForm2.t.setY(cameraXForm2.t.getY() + mouseDeltaY * modifierFactor * modifier * 0.3); // - 
       } 
      } 
     }); 
    } 

    private void handleKeyboard(Scene scene, final Node root) { 
     final boolean moveCamera = true; 
     scene.setOnKeyPressed(new EventHandler<KeyEvent>() { 
      @Override 
      public void handle(KeyEvent event) { 
       Duration currentTime; 
       switch (event.getCode()) { 
        case Z: 
         if (event.isShiftDown()) { 
          cameraXForm.ry.setAngle(0.0); 
          cameraXForm.rx.setAngle(0.0); 
          camera.setTranslateZ(-300.0); 
         } 
         cameraXForm2.t.setX(0.0); 
         cameraXForm2.t.setY(0.0); 
         break; 
        case X: 
         if (event.isControlDown()) { 
          if (axisGroup.isVisible()) { 
           axisGroup.setVisible(false); 
          } else { 
           axisGroup.setVisible(true); 
          } 
         } 
         break; 
        case S: 
         if (event.isControlDown()) { 
          if (moleculeGroup.isVisible()) { 
           moleculeGroup.setVisible(false); 
          } else { 
           moleculeGroup.setVisible(true); 
          } 
         } 
         break; 
        case SPACE: 
         if (timelinePlaying) { 
          timeline.pause(); 
          timelinePlaying = false; 
         } else { 
          timeline.play(); 
          timelinePlaying = true; 
         } 
         break; 
        case UP: 
         if (event.isControlDown() && event.isShiftDown()) { 
          cameraXForm2.t.setY(cameraXForm2.t.getY() - 10.0 * CONTROL_MULTIPLIER); 
         } else if (event.isAltDown() && event.isShiftDown()) { 
          cameraXForm.rx.setAngle(cameraXForm.rx.getAngle() - 10.0 * ALT_MULTIPLIER); 
         } else if (event.isControlDown()) { 
          cameraXForm2.t.setY(cameraXForm2.t.getY() - 1.0 * CONTROL_MULTIPLIER); 
         } else if (event.isAltDown()) { 
          cameraXForm.rx.setAngle(cameraXForm.rx.getAngle() - 2.0 * ALT_MULTIPLIER); 
         } else if (event.isShiftDown()) { 
          double z = camera.getTranslateZ(); 
          double newZ = z + 5.0 * SHIFT_MULTIPLIER; 
          camera.setTranslateZ(newZ); 
         } 
         break; 
        case DOWN: 
         if (event.isControlDown() && event.isShiftDown()) { 
          cameraXForm2.t.setY(cameraXForm2.t.getY() + 10.0 * CONTROL_MULTIPLIER); 
         } else if (event.isAltDown() && event.isShiftDown()) { 
          cameraXForm.rx.setAngle(cameraXForm.rx.getAngle() + 10.0 * ALT_MULTIPLIER); 
         } else if (event.isControlDown()) { 
          cameraXForm2.t.setY(cameraXForm2.t.getY() + 1.0 * CONTROL_MULTIPLIER); 
         } else if (event.isAltDown()) { 
          cameraXForm.rx.setAngle(cameraXForm.rx.getAngle() + 2.0 * ALT_MULTIPLIER); 
         } else if (event.isShiftDown()) { 
          double z = camera.getTranslateZ(); 
          double newZ = z - 5.0 * SHIFT_MULTIPLIER; 
          camera.setTranslateZ(newZ); 
         } 
         break; 
        case RIGHT: 
         if (event.isControlDown() && event.isShiftDown()) { 
          cameraXForm2.t.setX(cameraXForm2.t.getX() + 10.0 * CONTROL_MULTIPLIER); 
         } else if (event.isAltDown() && event.isShiftDown()) { 
          cameraXForm.ry.setAngle(cameraXForm.ry.getAngle() - 10.0 * ALT_MULTIPLIER); 
         } else if (event.isControlDown()) { 
          cameraXForm2.t.setX(cameraXForm2.t.getX() + 1.0 * CONTROL_MULTIPLIER); 
         } else if (event.isAltDown()) { 
          cameraXForm.ry.setAngle(cameraXForm.ry.getAngle() - 2.0 * ALT_MULTIPLIER); 
         } 
         break; 
        case LEFT: 
         if (event.isControlDown() && event.isShiftDown()) { 
          cameraXForm2.t.setX(cameraXForm2.t.getX() - 10.0 * CONTROL_MULTIPLIER); 
         } else if (event.isAltDown() && event.isShiftDown()) { 
          cameraXForm.ry.setAngle(cameraXForm.ry.getAngle() + 10.0 * ALT_MULTIPLIER); // - 
         } else if (event.isControlDown()) { 
          cameraXForm2.t.setX(cameraXForm2.t.getX() - 1.0 * CONTROL_MULTIPLIER); 
         } else if (event.isAltDown()) { 
          cameraXForm.ry.setAngle(cameraXForm.ry.getAngle() + 2.0 * ALT_MULTIPLIER); // - 
         } 
         break; 
       } 
      } 
     }); 
    } 



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

Ma te risultato non è che quello che mi aspettavo. Volevo avere Pane per i controlli dell'interfaccia utente sopra l'oggetto 3D, ma ciò che ottengo è questo:

enter image description here

Che cosa sto facendo di sbagliato?

risposta

0

Il problema è qui:

scene.setCamera(subSceneCamera); 
    scene.setCamera(camera); 

È possibile impostare una sola telecamera in scena (o Subscene). È necessario impostare la seconda videocamera in SubScene. Provare qualcosa di simile:

@Override 
public void start(Stage primaryStage) throws Exception{ 
    ... 
    primaryStage.show(); 
    scene.setCamera(camera); 
} 
private void buildScene() { 
    ... 
    subScene.setLayoutX(100); 
    subScene.setLayoutY(100); 
    subScene.setCamera(subSceneCamera); 
    root.getChildren().addAll(subScene); 
} 
+1

Ho provato questa variante troppo. E l'ho appena provato di nuovo. Sfortunatamente, lo stesso risultato. – Eugene

+0

C'è una sottoscrizione funzionante nell'applicazione FXTuxCube Ineractive Mesh. Ho provato a portarlo nella MoleculaSampleApp di Oracle, ma fino ad ora non aveva avuto successo. Indipendentemente dal modo in cui ho provato a ruotare correttamente la videocamera in abbonamento, sembra ancora nello screenshot qui sopra. Ma potresti solo cercare di capire cosa ha fatto August in TuxCube. Spero che aiuti un po '. – ajeh

+2

Da quanto ho visto in Tux Cube, sta usando solo una telecamera sia per la scena che per l'abbonato, e applica la trasformazione alla scena principale invece che alla fotocamera. Ritengo che Oracle abbia fatto un grosso disservizio a coloro che hanno imparato JavaFX 3D rilasciando MoleculeSampleApp che ha nascosto la trasformazione nella propria classe Xform. – ajeh

1

Da quello che ho capito dalle prove (limitato) che ho fatto, ci sono due opzioni:

  1. Impostare una macchina fotografica per un sub-scena e aggiungere che sub -scene alla radice. Utilizzerai solo una videocamera. Il tuo mondo dovrà essere un gruppo separato e la visione della telecamera volante/girevole dovrà essere realizzata trasformando il gruppo mondiale.

  2. Segnala un bug report con JavaFX jira.

Non ho avuto successo utilizzando una videocamera separata come videocamera secondaria. Nessuna trasformazione applicata alla telecamera o una scena secondaria stessa ha mai ruotato una scena secondaria dalla posizione predefinita simile a quella nella schermata. A questo punto con Oracle che non rilascia alcuna documentazione sulla scena secondaria, possiamo solo aspettare che vengano puliti e colmare le lacune. Fino ad allora possiamo considerare il supporto per l'abbonamento in JavaFX 3D interrotto.

0

ecco la soluzione

public class rotate3Dwithpanel extends Application 
{ 
    private double mouseOldX, mouseOldY = 0; 
    private Rotate rotateX = new Rotate(0, Rotate.X_AXIS); 
    private Rotate rotateY = new Rotate(0, Rotate.Y_AXIS); 
    private Rotate rotateZ = new Rotate(0, Rotate.Z_AXIS); 

    @Override 
    public void start(Stage stage) throws Exception 
    { 
     final PhongMaterial redMaterial = new PhongMaterial(); 
     redMaterial.setSpecularColor(Color.ORANGE); 
     redMaterial.setDiffuseColor(Color.RED); 

     Box myBox = new Box(100, 100, 100); 
     myBox.setTranslateX(400); 
     myBox.setTranslateY(300); 
     myBox.setTranslateZ(400); 
     myBox.setMaterial(redMaterial); 

     Rectangle rectangle = new Rectangle(); 
     rectangle.setX(200); 
     rectangle.setY(600); 
     rectangle.setWidth(200); 
     rectangle.setHeight(100); 
     rectangle.setFill(Color.GREY); 

     // to Set pivot points 
     rotateX.setPivotX(400); 
     rotateX.setPivotY(300); 
     rotateX.setPivotZ(400); 

     rotateY.setPivotX(400); 
     rotateY.setPivotY(300); 
     rotateY.setPivotZ(400); 

     rotateZ.setPivotX(400); 
     rotateZ.setPivotY(300); 
     rotateZ.setPivotZ(400); 


     // initialize the camera 
     PerspectiveCamera camera = new PerspectiveCamera(false); 
     camera.getTransforms().addAll (rotateX, rotateY, new Translate(0, 0, 0)); 

     Group root = new Group(); 
     Group subRoot = new Group(); 

     root.getChildren().add(rectangle); 

     Scene scene = new Scene(root, 1000, 1000, true); 
     SubScene subScene = new SubScene(subRoot, 800, 800, true, SceneAntialiasing.BALANCED); 

     subScene.setCamera(camera); 
     subRoot.getChildren().add(myBox); 
     root.getChildren().add(subScene); 

     // events for rotation 
     rectangle.setOnMousePressed(event -> { 
      mouseOldX = event.getSceneX(); 
      mouseOldY = event.getSceneY(); 
     }); 

     rectangle.setOnMouseDragged(event -> { 
      if(event.isPrimaryButtonDown()) 
      { 
       rotateX.setAngle(rotateX.getAngle() - (event.getSceneY() - mouseOldY)); 
       rotateY.setAngle(rotateY.getAngle() + (event.getSceneX() - mouseOldX)); 
       mouseOldX = event.getSceneX(); 
       mouseOldY = event.getSceneY(); 
      } 
     }); 

     stage.setTitle("JavaFX 3D Object"); 
     stage.setScene(scene); 
     stage.show(); 
    } 

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

}