2016-02-06 5 views
4

Mon problème est avec Z-Buffer dans JavaFX 3D, il ne semble pas fonctionner comme prévu sur ma machine.JavaFX 8 Z-buffer issue

Je suis au courant des questions: Overlapping shapes et ...Z Order...

Cependant j'ai Z-buffer activé et les noeuds sont encore rendus dans l'ordre dans lequel ils sont ajoutés à la SceneGraph.

Peut-être qu'il me manque des dépendances ou quoi que ce soit?

Je poste le code, j'espère que quelqu'un peut m'aider. Je crée une transition qui déplace le nœud autour d'un autre sur un chemin elliptique.

Merci d'avance!

public class OrbitExp extends Application { 
Group root = new Group(); 
Scene scene = new Scene(root, 800, 600, true, SceneAntialiasing.BALANCED); 
PerspectiveCamera camera = new PerspectiveCamera(); 
@Override 
public void start(Stage primaryStage) { 
    root.setDepthTest(DepthTest.ENABLE); 
//Tried to set Depthtest explicitly. Assumed maybe it did not inherit:S 
    System.out.println(
     "3D supported? " + 
     Platform.isSupported(ConditionalFeature.SCENE3D) 
    ); // returns true 

    System.out.println("root z-buffer: " + root.getDepthTest()); 
    initCamera(); 
    Box 
      box1 = new Box(50,50,50), 
      box2 = new Box(10,10,10); 
    root.setTranslateX(scene.getWidth()/2); 
    root.setTranslateY(scene.getHeight()/2); 
    PhongMaterial 
      pmat = new PhongMaterial(Color.BLUE), 
      pmat2 = new PhongMaterial(Color.RED); 
    box1.setMaterial(pmat); 
    box2.setMaterial(pmat2); 
    scene.setFill(Color.LIGHTGREEN); 
    root.getChildren().addAll(box1,box2); 
    SequentialTransition sqt = orbit(box1, box2, 40, 40, Duration.seconds(3), 360); 
    sqt.play(); 
    scene.setOnMouseClicked(click->{ 
     Node node = (Node)(click.getPickResult().getIntersectedNode()); 
     System.out.println("Tx: "+node.getTranslateX()); 
     System.out.println("Ty: "+node.getTranslateY()); 
     System.out.println("Tz: "+node.getTranslateZ()); 
    }); 
// just for debugging, but coords does seem to be alright 
    primaryStage.setScene(scene); 
    primaryStage.show(); 
} 
public static void main(String[] args) { 
    launch(args); 
} 
private void initCamera() { 
    camera.setTranslateZ(-50); 
    camera.setTranslateY(20); 
    camera.setFarClip(5000); 
    camera.setNearClip(0); 
    scene.setCamera(camera); 
} 
SequentialTransition orbit(Node node1, Node node2,double a, double b, Duration totalDuration, int N) { 
    SequentialTransition sqt = new SequentialTransition(); 
    Duration dur = new Duration(totalDuration.toMillis()*(1.0d/N)); 
    node2.setTranslateX(a+node1.getTranslateX()); 
    node2.setTranslateZ(node1.getTranslateZ()); 
    for (int i = 1; i < N; i++) { 
     TranslateTransition tt = new TranslateTransition(dur, node2); 
     double 
       angle = i*(360.0d/N), 
       toX = (Math.cos(Math.toRadians(angle))*a)+node1.getTranslateX(), 
       toZ = (Math.sin(Math.toRadians(angle))*b)+node1.getTranslateZ(); 
     tt.setToX(toX); 
     tt.setToZ(toZ); 
     tt.setInterpolator(Interpolator.LINEAR); 
     sqt.getChildren().add(tt); 
     System.out.println("angle = " + angle + "\nangle in rads: " + Math.toRadians(angle) + "\ntoX = " + toX + "\ntoZ = " + toZ); 
    } 
    sqt.setCycleCount(Timeline.INDEFINITE); 
    return sqt; 
} 

}

Ce fut mon premier message par la voie :)

Répondre

4

Si vous vérifiez le code à link vous rectangles fournis en utilisant, tampon de profondeur fonctionne très bien.

La modification des rectangles pour utiliser des boîtes 3D fonctionne également.

La question est de savoir comment vous définissez la rotation de l'une des cases liées à l'autre, donc au lieu d'utiliser un RotateTransition ou un SequentialTransition de TranslateTransition comme vous le faites, je l'ai appliqué un Rotate transform à la boîte rouge fixer une pivoter dans le centre du bleu, et utilisé AnimationTimer pour modifier l'angle de cette rotation pour créer l'effet 'orbite'.

Vous pouvez même utiliser la transparence sur la grande boîte (depuis 8u60) pour voir le petit dessous.

private final Group shapes = new Group(); 
private long lastTimerCall; 
private AnimationTimer timeline; 

@Override 
public void start(Stage stage) throws Exception { 
    Scene scene = new Scene(createRotatingShapes(), 400, 300, 
      true, SceneAntialiasing.BALANCED); 
    scene.setFill(Color.LIGHTGREEN); 
    final PerspectiveCamera camera = new PerspectiveCamera(); 
    camera.setRotationAxis(Rotate.X_AXIS); 
    camera.setRotate(10); 
    camera.setTranslateZ(200); 
    scene.setCamera(camera); 

    stage.setScene(scene); 
    stage.show(); 
} 

private Group createRotatingShapes() { 
    final Box box1 = new Box(50, 50, 50); 
    // Transparency in box1: last node of the group 
    box1.setMaterial(new PhongMaterial(Color.web("#0000FF80"))); 

    box1.setTranslateZ(50); 

    final Box box2 = new Box(10, 10, 10); 
    box2.setMaterial(new PhongMaterial(Color.RED)); 

    box2.setTranslateZ(-50); 

    shapes.getChildren().addAll(box2, box1); 

    shapes.setTranslateX(200); 
    shapes.setTranslateY(150); 

    rotateAroundYAxis(box2); 

    return shapes; 
} 

private int count = 0; 
private void rotateAroundYAxis(Node node) { 
    Rotate r = new Rotate(0, 0, 0, 100, Rotate.Y_AXIS); 
    node.getTransforms().add(r); 
    lastTimerCall = System.nanoTime(); 
    timeline = new AnimationTimer() { 
     @Override public void handle(long now) { 
      if (now > lastTimerCall + 100_000_000l) { 
       r.setAngle((count++)%360); 
      } 
     } 
    }; 
    timeline.start(); 
} 


@Override 
public void stop() { 
    timeline.stop(); 
} 

Devant la boîte:

In front of

Derrière la boîte bleue:

Behind

EDIT

Si vous un coup d'oeil à la caméra pour JavaDoc nearClip:

Indique la distance de l'œil du plan de coupe près de cette caméra dans l'œil espace de coordonnées. Les objets situés plus près de l'œil que nearClip ne sont pas dessinés. nearClip est spécifié comme valeur supérieur à que zéro. Une valeur inférieure à supérieure ou égale à zéro est traitée comme un très petit nombre positif.

(le gras est le mien).

Le problème avec votre code était cette ligne:

camera.setNearClip(0); 

changer juste à:

camera.setNearClip(0.01); 

et il fonctionnera comme prévu.

+0

Merci pour votre réponse rapide, je vois que votre solution fonctionne bien, et je l'accepte volontiers comme une réponse. Cependant, je n'arrive pas à voir pourquoi cube1 derrière cube2 est toujours rendu avant cube2 dans mon programme, pourriez-vous préciser sur "comment vous définissez la rotation de l'une des boîtes liées à l'autre". Des tas de remerciements! –

+1

Le 'Rotate r' utilise' pivotZ = 100', la distance entre les deux cases, vous n'avez donc qu'à faire pivoter la case rouge. Avec le tampon de profondeur, l'ordre des boîtes dans le groupe n'est pas pertinent, sinon pour définir la transparence dans le bleu. Si vous changez la commande, cela fonctionnera, mais la boîte bleue ne sera pas transparente. –

+1

Vérifiez les paramètres de votre caméra et changez ceci: 'camera.setNearClip (0.01);'. Votre code fonctionnera maintenant. J'ai édité ma réponse avec ceci. –