JavaFX 3d sous-scène en 2d Scène


Je développe une interface graphique pour un jeu et je veux mélanger un sous-scène 3D avec un volet 2D dans JavaFX. J'ai un groupe appelé root3D qui contient tous mes objets 3d déjà définis correctement, puis je crée un volet à l'aide d'un fichier FXML défini via JavaFX Scene Builder. Mais rien n'apparaît et je ne peux voir que mes objets 3D.

       PerspectiveCamera camera = new PerspectiveCamera(true);
       camera.setTranslateZ(-30);
       Group root3D = new Group(model1,model2,model3); //various 3d models I imported
       SubScene subScene = new SubScene(root3D, 1280, 700, true,SceneAntialiasing.BALANCED);
       subScene.setCamera(camera);
       FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/file.fxml"));
       AnchorPane pane = loader.load();
       pane.getChildren().add(subScene);
       Scene scene = new Scene(pane);
       primaryStage.setScene(scene);
       primaryStage.setResizable(false);
       primaryStage.show();

Fichier FXML:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.TextField?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.text.Font?>

<AnchorPane prefHeight="700.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <StackPane prefHeight="150.0" prefWidth="200.0">
         <children>
            <ImageView fitHeight="214.0" fitWidth="169.0" pickOnBounds="true" preserveRatio="true">
               <image>
                  <Image url="@../Sprite/Cards/Small/podium-characters-Poseidon.png" />
               </image>
            </ImageView>
            <TextField prefHeight="62.0" prefWidth="274.0" text="APOLLO">
               <font>
                  <Font name="Trebuchet MS Bold Italic" size="22.0" />
               </font>
            </TextField>
         </children>
      </StackPane>
   </children>
</AnchorPane>

Aucun signe de la mise en page FXML

EDIT: J'ai découvert que le redimensionnement du sous-domaine, je peux voir les éléments FXML. Apparemment ils sont "couverts" par la subscene. Est-ce que quelqu'un sait comment poser les éléments FXML au-dessus du sous-domaine et non le contraire comme cela se passe maintenant? Le sous-domaine couvre la mise en page FXML que j'ai créée

Author: gouessej, 2020-05-26

2 answers

Bien que vous ayez trouvé une solution, je poste une réponse dans l'espoir de rendre les choses un peu plus claires en ce qui concerne pourquoi appeler toBack() sur vos SubScene fonctionne.

Z-Ordre

Chaque Parent, dont toutes les mises en page héritent, peut avoir un ou plusieurs enfants. Si deux (ou plus) enfants occupent le même espace dans le Parent alors l'un sera rendu sur l'autre. Quel enfant est tiré sur l'autre est déterminé par deux choses:

  1. L'ordre de les enfants dans le Parent's liste des enfants.
  2. (Depuis JavaFX 9) La valeur de chaque enfant viewOrder propriété par rapport aux autres enfants dans la même Parent.

Le Z-Order dans JavaFX Q&A va plus en détail.

Le problème dans votre code

Votre fichier FXML décrit un AnchorPane qui a un StackPane comme seul enfant. Cela signifie que ce qui suit:

AnchorPane pane = loader.load();

Vous Donne un AnchorPane avec StackPane dans sa liste d'enfants, à l'indice zéro. Ensuite, vous ajoutez immédiatement votre SubScene en utilisant:

pane.getChildren().add(subScene);

Le add la méthode que vous utilisez ajoute l'élément à la fin de la liste. Cela signifie donc que l'ordre de la liste des enfants de AnchorPane est:

  1. StackPane
  2. SubScene

Puisque le SubScene vient après le StackPane le premier est rendu au-dessus du second.

Votre solution

La solution que vous avez choisie est d'appeler toBack() sur votre SubScene après l'avoir ajouté au AnchorPane. Voici la documentation de cette méthode:

Déplace ce Node à l'arrière de ses nœuds frères en termes d'ordre z. Ceci est accompli en déplaçant ce Node à la première position dans le contenu de son parent ObservableList. Cette fonction n'a aucun effet si ce Node ne fait pas partie d'un groupe.

En d'autres termes, après avoir appelé cette méthode, l'ordre de la liste des enfants de AnchorPane devient:

  1. SubScene
  2. StackPane

C'est pourquoi le SubScene est maintenant rendu sous le StackPane, parce que vous avez changé l'ordre des enfants.

Notez que la méthode toBack() fait partie de la classe Node, pas SubScene. Ce dernier hérite du premier. J'apporte cela pour souligner que le problème que vous aviez n'est pas spécifique à SubScene ou même mélanger des graphiques de scène 2D et 3D ensemble. Votre StackPane et votre SubScene font partie d'un Scene 2D (c'est-à-dire pas de tampon de profondeur), ce qui signifie que leur ordre z est uniquement régi par ce qui est discuté ci-dessus*. Le fait que le SubScene soit en 3D (c'est-à-dire que la mise en mémoire tampon de profondeur est activée) n'est pas pertinent pour le problème en question; ce fait n'affecte que les descendants dudit SubScene.

* Dans une scène 3D à la coordonnée z d'un nœud devient pertinente.

Autres solutions

Voici quelques autres approches qui pourraient être utilisées pour résoudre votre problème:

  • Ajouter le SubScene au début des enfants du AnchorPane liste:

    pane.getChildren().add(0, subScene);
    
  • Si vous utilisez JavaFX 9+, définissez la propriété viewOrder du {[6] } sur quelque chose de moins que celle de la propriété AnchorPane (par défaut, la valeur de cette propriété est 0):

    subScene.setViewOrder(-1);
    
  • Définir votre SubScene dans le fichier FXML avant le StackPane (notez que cette approche nécessite l'utilisation de un contrôleur FXML):

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.control.TextField?>
    <?import javafx.scene.Group?>
    <?import javafx.scene.image.Image?>
    <?import javafx.scene.image.ImageView?>
    <?import javafx.scene.layout.AnchorPane?>
    <?import javafx.scene.layout.StackPane?>
    <?import javafx.scene.SceneAntialiasing?>
    <?import javafx.scene.SubScene?>
    <?import javafx.scene.text.Font?>
    
    <AnchorPane prefHeight="700.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/11.0.1"
                xmlns:fx="http://javafx.com/fxml/1">
      <children>
    
        <!-- Define the SubScene before the StackPane -->
        <SubScene fx:id="subScene" width="1280" height="700" depthBuffer="true">
          <antiAliasing>
            <SceneAntialiasing fx:constant="BALANCED"/>
          </antiAliasing>
    
          <!-- 
            Unfortunately, as far as I can tell, you can't set your PerspectiveCamera in FXML because you
            want 'fixedEyeAtCameraZero' to be true. That property can only be set during construction but
            the constructor with that parameter does not annotate said parameter with @NamedArg, thus the
            FXMLLoader can't see it. And the no-arg constructor sets the value to false, not true. This
            means you have to inject the SubScene into your controller and add the PerspectiveCamera in
            code.
           -->
    
          <root>
            <!-- Inject the root into the controller in order to add your models to it in code -->
            <Group fx:id="root3D"/>
          </root>
        </SubScene>
    
        <StackPane prefHeight="150.0" prefWidth="200.0">
          <children>
            <ImageView fitHeight="214.0" fitWidth="169.0" pickOnBounds="true" preserveRatio="true">
              <image>
                <Image url="@../Sprite/Cards/Small/podium-characters-Poseidon.png"/>
              </image>
            </ImageView>
            <TextField prefHeight="62.0" prefWidth="274.0" text="APOLLO">
              <font>
                <Font name="Trebuchet MS Bold Italic" size="22.0"/>
              </font>
            </TextField>
          </children>
        </StackPane>
    
      </children>
    </AnchorPane>
    
 3
Author: Slaw, 2020-05-27 16:27:12

Comme @Slaw l'a indirectement souligné, ce dont j'avais besoin était de définir le sous-domaine.toBack () pour définir un ordre Z correct dans ma scène. Merci beaucoup! En lisant sur les sous-scènes, je n'ai rien trouvé à ce sujet, donc j'espère que cela pourra aider certains débutants 3d à l'avenir. résultat final

 2
Author: anonymflaco, 2020-06-28 15:37:41