2015-07-13 4 views
1

Mes problèmes sont les suivants:rotations JavaFX 3D

  1. le code ci-dessous est basé sur le "MolecularSampleApp" de l'oracle site tutoriel, mais très simplifié. Il montre seulement une boîte et une sphère rouge à des fins d'orientation. La séquence des rotations est autour de l'axe des abscisses puis de l'axe des y et enfin de l'axe des z. Les rotations suivantes sont apparemment effectuées dans des axes de coordonnées qui sont tournés avec les rotations précédentes. (Je l'ai vérifié encore et encore avec un cube et des séquences de rotations de 90 °) Donc, quand l'utilisateur tourne la caméra avec la souris, c'est très peu intuitif car le comportement de rotation change après rotation autour de l'axe vertical l'axe horizontal sera ensuite tourné aussi). Essayez-le avec mon code ci-dessous, ou avec le MolecularSampleApp - c'est le même sentiment non naturel. Y a-t-il un moyen facile de surmonter cela?
  2. Mais ce que je ne comprends même pas, c'est le comportement lorsque le code mousePressed est exécuté: Ici, la caméra est toujours tournée dans un système FIXED! Les axes ne sont PAS tournés avec la caméra, bien que ce soit essentiellement le même code (sauf que l'angle de rotation n'est bien sûr pas accumulé ici). Quelqu'un sait comment c'est possible?
package trafotest; 

import javafx.application.Application; 
import static javafx.application.Application.launch; 
import javafx.scene.DepthTest; 
import javafx.scene.Group; 
import javafx.scene.PerspectiveCamera; 
import javafx.scene.Scene; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.paint.Color; 
import javafx.scene.paint.PhongMaterial; 
import javafx.scene.shape.Box; 
import javafx.scene.shape.Sphere; 
import javafx.scene.transform.Rotate; 
import javafx.scene.transform.Translate; 
import javafx.stage.Stage; 

public class TrafoTest extends Application { 

    final Group root = new Group(); 
    final XformWorld world = new XformWorld(); 
    final PerspectiveCamera camera = new PerspectiveCamera(true); 
    final XformCamera cameraXform = new XformCamera(); 
    private static final double CAMERA_INITIAL_DISTANCE = -1000; 
    private static final double CAMERA_NEAR_CLIP = 0.1; 
    private static final double CAMERA_FAR_CLIP = 10000.0; 
    double mousePosX, mousePosY, mouseOldX, mouseOldY, mouseDeltaX, mouseDeltaY; 

    @Override 
    public void start(Stage primaryStage) { 
     root.getChildren().add(world); 
     root.setDepthTest(DepthTest.ENABLE); 
     buildCamera(); 
     buildBodySystem(); 
     Scene scene = new Scene(root, 800, 600, true); 
     scene.setFill(Color.GREY); 
     handleMouse(scene); 
     primaryStage.setTitle("Transformationen"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
     scene.setCamera(camera); 
    } 

    private void buildCamera() { 
     root.getChildren().add(cameraXform); 
     cameraXform.getChildren().add(camera); 
     camera.setNearClip(CAMERA_NEAR_CLIP); 
     camera.setFarClip(CAMERA_FAR_CLIP); 
     camera.setTranslateZ(CAMERA_INITIAL_DISTANCE); 
    } 

    private void buildBodySystem() { 
     PhongMaterial whiteMaterial = new PhongMaterial(); 
     whiteMaterial.setDiffuseColor(Color.WHITE); 
     whiteMaterial.setSpecularColor(Color.LIGHTBLUE); 
     Box box = new Box(400, 200, 100); 
     box.setMaterial(whiteMaterial); 
     PhongMaterial redMaterial = new PhongMaterial(); 
     redMaterial.setDiffuseColor(Color.DARKRED); 
     redMaterial.setSpecularColor(Color.RED); 
     Sphere sphere = new Sphere(5); 
     sphere.setMaterial(redMaterial); 
     sphere.setTranslateZ(-50.0); 
     world.getChildren().addAll(box); 
     world.getChildren().addAll(sphere); 
    } 

    private void handleMouse(Scene scene) { 
     scene.setOnMousePressed((MouseEvent me) -> { 
      mousePosX = me.getSceneX(); 
      mousePosY = me.getSceneY(); 
      mouseOldX = me.getSceneX(); 
      mouseOldY = me.getSceneY(); 
      // this is done after clicking and the rotations are apearently 
      // performed in coordinates that are NOT rotated with the camera. 
      // (pls activate the two lines below for clicking) 
      //cameraXform.rx.setAngle(-90.0); 
      //cameraXform.ry.setAngle(180.0); 
     }); 
     scene.setOnMouseDragged((MouseEvent me) -> { 
      mouseOldX = mousePosX; 
      mouseOldY = mousePosY; 
      mousePosX = me.getSceneX(); 
      mousePosY = me.getSceneY(); 
      mouseDeltaX = (mousePosX - mouseOldX); 
      mouseDeltaY = (mousePosY - mouseOldY); 
      if (me.isPrimaryButtonDown()) { 
       // this is done when the mouse is dragged and each rotation is 
       // performed in coordinates, that are rotated with the camera.    
       cameraXform.ry.setAngle(cameraXform.ry.getAngle() + mouseDeltaX * 0.2); 
       cameraXform.rx.setAngle(cameraXform.rx.getAngle() - mouseDeltaY * 0.2);     
      } 
     }); 
    } 

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

} 

class XformWorld extends Group { 

    final Translate t = new Translate(0.0, 0.0, 0.0); 
    final Rotate rx = new Rotate(0, 0, 0, 0, Rotate.X_AXIS); 
    final Rotate ry = new Rotate(0, 0, 0, 0, Rotate.Y_AXIS); 
    final Rotate rz = new Rotate(0, 0, 0, 0, Rotate.Z_AXIS); 

    public XformWorld() { 
     super(); 
     this.getTransforms().addAll(t, rx, ry, rz); 
    } 

} 

class XformCamera extends Group { 

    final Translate t = new Translate(0.0, 0.0, 0.0); 
    final Rotate rx = new Rotate(0, 0, 0, 0, Rotate.X_AXIS); 
    final Rotate ry = new Rotate(0, 0, 0, 0, Rotate.Y_AXIS); 
    final Rotate rz = new Rotate(0, 0, 0, 0, Rotate.Z_AXIS); 

    public XformCamera() { 
     super(); 
     this.getTransforms().addAll(t, rx, ry, rz); 
    } 

} 
+0

Bienvenue sur StackOverflow. S'il vous plaît lisez ce http://stackoverflow.com/help/how-to-ask pour apprendre à poser une bonne question. Vous devriez essayer d'isoler le code autant que possible afin de motiver les autres à le lire. –

Répondre

7

J'ai trouvé une solution qui fonctionne pour moi, juste au cas où quelqu'un d'autre est intéressé aussi:

package trafotest; 

import javafx.application.Application; 
import static javafx.application.Application.launch; 
import javafx.geometry.Point3D; 
import javafx.scene.DepthTest; 
import javafx.scene.Group; 
import javafx.scene.PerspectiveCamera; 
import javafx.scene.Scene; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.paint.Color; 
import javafx.scene.paint.PhongMaterial; 
import javafx.scene.shape.Box; 
import javafx.scene.shape.Sphere; 
import javafx.scene.transform.Rotate; 
import javafx.scene.transform.Transform; 
import javafx.scene.transform.Translate; 
import javafx.stage.Stage; 

public class TrafoTest extends Application { 
    final Group root = new Group(); 
    final XformWorld world = new XformWorld(); 
    final PerspectiveCamera camera = new PerspectiveCamera(true); 
    final XformCamera cameraXform = new XformCamera(); 
    private static final double CAMERA_INITIAL_DISTANCE = -1000; 
    private static final double CAMERA_NEAR_CLIP = 0.1; 
    private static final double CAMERA_FAR_CLIP = 10000.0; 
    double mousePosX, mousePosY, mouseOldX, mouseOldY, mouseDeltaX, mouseDeltaY; 
    double mouseFactorX, mouseFactorY; 

    @Override 
    public void start(Stage primaryStage) { 
     root.getChildren().add(world); 
     root.setDepthTest(DepthTest.ENABLE); 
     buildCamera(); 
     buildBodySystem(); 
     Scene scene = new Scene(root, 800, 600, true); 
     scene.setFill(Color.GREY); 
     handleMouse(scene); 
     primaryStage.setTitle("TrafoTest"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
     scene.setCamera(camera); 
     mouseFactorX = 180.0/scene.getWidth(); 
     mouseFactorY = 180.0/scene.getHeight(); 
    } 

    private void buildCamera() { 
     root.getChildren().add(cameraXform); 
     cameraXform.getChildren().add(camera); 
     camera.setNearClip(CAMERA_NEAR_CLIP); 
     camera.setFarClip(CAMERA_FAR_CLIP); 
     camera.setTranslateZ(CAMERA_INITIAL_DISTANCE); 
    } 

    private void buildBodySystem() { 
     PhongMaterial whiteMaterial = new PhongMaterial(); 
     whiteMaterial.setDiffuseColor(Color.WHITE); 
     whiteMaterial.setSpecularColor(Color.LIGHTBLUE); 
     Box box = new Box(400, 200, 100); 
     box.setMaterial(whiteMaterial); 
     PhongMaterial redMaterial = new PhongMaterial(); 
     redMaterial.setDiffuseColor(Color.DARKRED); 
     redMaterial.setSpecularColor(Color.RED); 
     Sphere sphere = new Sphere(5); 
     sphere.setMaterial(redMaterial); 
     sphere.setTranslateX(200.0); 
     sphere.setTranslateY(-100.0); 
     sphere.setTranslateZ(-50.0); 
     world.getChildren().addAll(box); 
     world.getChildren().addAll(sphere); 
    } 

    private void handleMouse(Scene scene) { 
     scene.setOnMousePressed((MouseEvent me) -> { 
      mousePosX = me.getSceneX(); 
      mousePosY = me.getSceneY(); 
      mouseOldX = me.getSceneX(); 
      mouseOldY = me.getSceneY(); 
     }); 
     scene.setOnMouseDragged((MouseEvent me) -> { 
      mouseOldX = mousePosX; 
      mouseOldY = mousePosY; 
      mousePosX = me.getSceneX(); 
      mousePosY = me.getSceneY(); 
      mouseDeltaX = (mousePosX - mouseOldX); 
      mouseDeltaY = (mousePosY - mouseOldY); 
      if (me.isPrimaryButtonDown()) { 
       cameraXform.ry(mouseDeltaX * 180.0/scene.getWidth()); 
       cameraXform.rx(-mouseDeltaY * 180.0/scene.getHeight()); 
      } else if (me.isSecondaryButtonDown()) { 
       camera.setTranslateZ(camera.getTranslateZ() + mouseDeltaY); 
      } 
     }); 
    } 

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

} 

class XformWorld extends Group { 
    final Translate t = new Translate(0.0, 0.0, 0.0); 
    final Rotate rx = new Rotate(0, 0, 0, 0, Rotate.X_AXIS); 
    final Rotate ry = new Rotate(0, 0, 0, 0, Rotate.Y_AXIS); 
    final Rotate rz = new Rotate(0, 0, 0, 0, Rotate.Z_AXIS); 

    public XformWorld() { 
     super(); 
     this.getTransforms().addAll(t, rx, ry, rz); 
    } 
} 

class XformCamera extends Group { 
    Point3D px = new Point3D(1.0, 0.0, 0.0); 
    Point3D py = new Point3D(0.0, 1.0, 0.0); 
    Rotate r; 
    Transform t = new Rotate(); 

    public XformCamera() { 
     super(); 
    } 

    public void rx(double angle) { 
     r = new Rotate(angle, px); 
     this.t = t.createConcatenation(r); 
     this.getTransforms().clear(); 
     this.getTransforms().addAll(t); 
    } 

    public void ry(double angle) { 
     r = new Rotate(angle, py); 
     this.t = t.createConcatenation(r); 
     this.getTransforms().clear(); 
     this.getTransforms().addAll(t); 
    } 

} 
+0

Merci beaucoup pour cela. Cela m'a conduit à résoudre mon propre problème ici: https://stackoverflow.com/questions/46176489/javafx-3d-rotation-around-scene-fixed-axes –