Comment créer un modèle 3d personnalisé dans JavaFX 8?


J'ai essayé de faire un plan dans l'application JavaFX en utilisant le tutoriel officiel et a le code suivant:

Image diifuseMap = new Image(getClass().getResource("t.jpg").toExternalForm());
    TriangleMesh planeMesh = new TriangleMesh();
    float[] points = {
            -5, 5, 0,
            -5, -5, 0,
            5, 5, 0,
            5, -5, 0
    };
    float[] texCoords = {
            0, 0,
            0, 1,
            1, 0,
            1, 1
    };
    int[] faces = {
            0, 0, 1, 1, 2, 2,
            2, 2, 3, 3, 1, 1
    };
    planeMesh.getPoints().addAll(points);
    planeMesh.getTexCoords().addAll(texCoords);
    planeMesh.getFaces().addAll(faces);
    MeshView meshView =   new MeshView(planeMesh);
    meshView.setMaterial(new PhongMaterial(Color.BLACK, diifuseMap, null, null, null));
    Group3D plane = new Group3D(new MeshView(planeMesh));

, Mais, malheureusement, rien n'est apparu dans la scène. Quelqu'un peut-il expliquer comment créer mes propres modèles 3d dans JavaFX? Et est-il possible de les créer sans texture (je veux un modèle filaire)?

Author: Eugene, 2013-10-19

2 answers

Rien n'est apparu dans la scène

Votre exemple de maillage rendu OK pour moi.

Peut-être que vous n'avez pas configuré correctement votre caméra ou que votre maillage a été mis à l'échelle pour qu'il soit visible.

Votre maillage d'échantillon ne fait pas grand-chose, il s'agit d'un triangle orienté vers la caméra et d'un second triangle orienté vers l'extérieur de la caméra.

Et est-il possible de les créer sans texture (je veux un modèle filaire)?

Oui, DrawMode pour votre vue de maillage à Ligne.

Exemple d'explication du programme

J'ai changé l'ordre de vos visages pour qu'ils soient tous les deux orientés dans la même direction afin que vous obteniez un carré face au spectateur plutôt qu'un triangle face au spectateur et un autre éloigné du spectateur:

int[] faces = {
    2, 2, 1, 1, 0, 0,
    2, 2, 3, 3, 1, 1
};

La carte de texture doit également changer (pour que le tableau de faces ci-dessus obtienne la bonne orientation sur la texture afin qu'elle ne soit pas à l'envers).

float[] texCoords = {
    1, 1,
    1, 0,
    0, 1,
    0, 0
};

J'ai mis en place un abattez le contrôle arrière et animez la rotation du modèle afin que vous puissiez voir les côtés "arrière" des triangles (en noir) et il est clair ce qui est rendu. J'ai également ajouté la possibilité de basculer une carte diffuse (un peu de marbre) pour une texture ou un mode filaire.

Exemple de sortie de programme

plainefil de fertexture

Exemple De Programme

import javafx.animation.*;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.geometry.Insets;
import javafx.scene.*;
import javafx.scene.control.CheckBox;
import javafx.scene.image.Image;
import javafx.scene.layout.VBox;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Duration;

public class InlineModelViewer extends Application {

  private static final int VIEWPORT_SIZE = 800;

  private static final double MODEL_SCALE_FACTOR = 40;
  private static final double MODEL_X_OFFSET = 0;
  private static final double MODEL_Y_OFFSET = 0;
  private static final double MODEL_Z_OFFSET = VIEWPORT_SIZE / 2;

  private static final String textureLoc = "https://www.sketchuptextureclub.com/public/texture_f/slab-marble-emperador-cream-light-preview.jpg";

  private Image texture;
  private PhongMaterial texturedMaterial = new PhongMaterial();

  private MeshView meshView = loadMeshView();

  private MeshView loadMeshView() {
    float[] points = {
        -5, 5, 0,
        -5, -5, 0,
        5, 5, 0,
        5, -5, 0
    };
    float[] texCoords = {
        1, 1,
        1, 0,
        0, 1,
        0, 0
    };
    int[] faces = {
        2, 2, 1, 1, 0, 0,
        2, 2, 3, 3, 1, 1
    };

    TriangleMesh mesh = new TriangleMesh();
    mesh.getPoints().setAll(points);
    mesh.getTexCoords().setAll(texCoords);
    mesh.getFaces().setAll(faces);

    return new MeshView(mesh);
  }

  private Group buildScene() {
    meshView.setTranslateX(VIEWPORT_SIZE / 2 + MODEL_X_OFFSET);
    meshView.setTranslateY(VIEWPORT_SIZE / 2 * 9.0 / 16 + MODEL_Y_OFFSET);
    meshView.setTranslateZ(VIEWPORT_SIZE / 2 + MODEL_Z_OFFSET);
    meshView.setScaleX(MODEL_SCALE_FACTOR);
    meshView.setScaleY(MODEL_SCALE_FACTOR);
    meshView.setScaleZ(MODEL_SCALE_FACTOR);

    return new Group(meshView);
  }

  @Override
  public void start(Stage stage) {
    texture = new Image(textureLoc);
    texturedMaterial.setDiffuseMap(texture);

    Group group = buildScene();

    RotateTransition rotate = rotate3dGroup(group);

    VBox layout = new VBox(
        createControls(rotate),
        createScene3D(group)
    );

    stage.setTitle("Model Viewer");

    Scene scene = new Scene(layout, Color.CORNSILK);
    stage.setScene(scene);
    stage.show();
  }

  private SubScene createScene3D(Group group) {
    SubScene scene3d = new SubScene(group, VIEWPORT_SIZE, VIEWPORT_SIZE * 9.0/16, true, SceneAntialiasing.BALANCED);
    scene3d.setFill(Color.rgb(10, 10, 40));
    scene3d.setCamera(new PerspectiveCamera());
    return scene3d;
  }

  private VBox createControls(RotateTransition rotateTransition) {
    CheckBox cull      = new CheckBox("Cull Back");
    meshView.cullFaceProperty().bind(
        Bindings.when(
            cull.selectedProperty())
              .then(CullFace.BACK)
              .otherwise(CullFace.NONE)
    );
    CheckBox wireframe = new CheckBox("Wireframe");
    meshView.drawModeProperty().bind(
        Bindings.when(
            wireframe.selectedProperty())
              .then(DrawMode.LINE)
              .otherwise(DrawMode.FILL)
    );

    CheckBox rotate = new CheckBox("Rotate");
    rotate.selectedProperty().addListener(observable -> {
      if (rotate.isSelected()) {
        rotateTransition.play();
      } else {
        rotateTransition.pause();
      }
    });

    CheckBox texture = new CheckBox("Texture");
    meshView.materialProperty().bind(
        Bindings.when(
            texture.selectedProperty())
              .then(texturedMaterial)
              .otherwise((PhongMaterial) null)
    );

    VBox controls = new VBox(10, rotate, texture, cull, wireframe);
    controls.setPadding(new Insets(10));
    return controls;
  }

  private RotateTransition rotate3dGroup(Group group) {
    RotateTransition rotate = new RotateTransition(Duration.seconds(10), group);
    rotate.setAxis(Rotate.Y_AXIS);
    rotate.setFromAngle(0);
    rotate.setToAngle(360);
    rotate.setInterpolator(Interpolator.LINEAR);
    rotate.setCycleCount(RotateTransition.INDEFINITE);

    return rotate;
  }

  public static void main(String[] args) {
    System.setProperty("prism.dirtyopts", "false");
    launch(args);
  }
}

Quelqu'un Peut-il expliquer comment créer mes propres modèles 3d

C'est une question trop large pour StackOverflow. Il y a des universités et des écoles d'art qui distribuent des diplômes dans ce genre de choses.

Quelqu'un Peut-il expliquer pourquoi Maillage.setAll prend float [] alors que le reste de l'API utilise double?

L'implémentation JavaFX 3D fournit un wrapper autour des API natives qui communiquent avec le matériel graphique (par exemple DirectX et OpenGL). Ces API fonctionnent avec une précision flottante plutôt qu'avec une double précision. L'utilisation de float[] directement dans l'API signifie que les données du modèle de maillage peuvent être stocké plus efficacement et directement mappé aux API graphiques sous-jacentes que si double[] ou un ObservableList<Double> étaient utilisés.

 8
Author: jewelsea, 2017-10-30 00:39:24

Étape 1: Liste des points

Étape 1

cube.getPoints().addAll(
    0, 0, 100,      //P0
    100, 0, 100,    //P1
    0, 100, 100,    //P2
    100, 100, 100,  //P3
    0, 0, 0,        //P4
    100, 0, 0,      //P5
    0, 100, 0,      //P6
    100, 100, 0     //P7
);

Étape 2: Liste des points de texture

Étape 2

cube.getTexCoords().addAll(
    0.25f, 0,       //T0
    0.5f, 0,        //T1
    0, 0.25f,       //T2
    0.25f, 0.25f,   //T3
    0.5f, 0.25f,    //T4
    0.75f, 0.25f,   //T5
    1, 0.25f,       //T6
    0, 0.5f,        //T7
    0.25f, 0.5f,    //T8
    0.5f, 0.5f,     //T9
    0.75f, 0.5f,    //T10
    1, 0.5f,        //T11
    0.25f, 0.75f,   //T12
    0.5f, 0.75f     //T13
);

Étape 3: Lister les faces (il a mélangé des points 3D et des points de texture dans le sens inverse des aiguilles d'une montre (ou règle de droite))

cube.getFaces().addAll(
    5,1,4,0,0,3     //P5,T1 ,P4,T0  ,P0,T3
    ,5,1,0,3,1,4    //P5,T1 ,P0,T3  ,P1,T4
    ,0,3,4,2,6,7    //P0,T3 ,P4,T2  ,P6,T7
    ,0,3,6,7,2,8    //P0,T3 ,P6,T7  ,P2,T8
    ,1,4,0,3,2,8    //P1,T4 ,P0,T3  ,P2,T8
    ,1,4,2,8,3,9    //P1,T4 ,P2,T8  ,P3,T9
    ,5,5,1,4,3,9    //P5,T5 ,P1,T4  ,P3,T9
    ,5,5,3,9,7,10   //P5,T5 ,P3,T9  ,P7,T10
    ,4,6,5,5,7,10   //P4,T6 ,P5,T5  ,P7,T10
    ,4,6,7,10,6,11  //P4,T6 ,P7,T10 ,P6,T11
    ,3,9,2,8,6,12   //P3,T9 ,P2,T8  ,P6,T12
    ,3,9,6,12,7,13  //P3,T9 ,P6,T12 ,P7,T13
);
 10
Author: Kaiba Zax, 2016-01-07 19:24:33