Problème avec l'ajout de plusieurs maillages triangulaires à une scène dans javafx


J'espère que quelqu'un peut m'aider avec ce problème.

J'utilise javafx et triangle mesh pour construire un objet de type sphère à partir de triangles (comme un ballon de football). Les différentes tuiles de la forme se distinguent par la couleur, mais je veux ajouter des lignes entre les tuiles. Comme dans ce football:

Les lignes 2D fournies de javafx apportent des performances terribles dans l'espace 3D. Par conséquent, j'ai trouvé le FXyzLib qui fournit un PolyLine3D . C'est en fait juste un autre maillage triangulaire qui crée une ligne dans un espace 3D.

Avec cela, je peux créer des lignes 3D. Mais si je veux les ajouter à mon maillage triangle d'origine, tout le reste devient noir. Il est également dans l'autre sens. J'ai expérimenté avec l'exemple fourni de la bibliothèque trouvée ici. Il crée une ligne 3D de fantaisie mais quand j'ai essayé d'ajouter une simple sphère de couleur rouge à la scène, la sphère était juste noire comme ceci:

ce.

Je ne suis pas un expert en la matière et nouveau à javafx et n'a pas pu trouver le problème dans le code du PolyLine3D . Cela ne devrait pas être un problème d'ajouter un maillage triangle multiple à une scène. Y a-t-il des effets de lumière ou de caméra que je ne connais pas?

EDIT: J'ai résolu le problème. La lumière ambiante utilisée dans le Polyline3D a causé le problème. Si vous ajoutez de la lumière pour vos autres objets, cela devrait aller.

Author: Erdbeer0815, 2018-09-28

1 answers

Bien qu'il n'y ait rien de mal à ajouter plusieurs maillages triangulaires à une scène, il existe une approche plus simple lorsque vous souhaitez créer un maillage comme celui de l'image de football, vous pouvez donc avoir pour effet de mettre en évidence certains bords mais pas tous les triangles du maillage.

Cela peut être fait avec un PolygonMesh qui prend n'importe quel polygone fermé valide comme visage.

Cette implémentation existe déjà, dans le projet 3DViewer, qui est open source et peut être trouvé ici. Il existe un contrôle PolygonMeshView qui peut rendre un PolygonMesh.

Notez que si vous utilisez ces deux classes uniquement dans votre projet, vous devrez ignorer le maillage de subdivision pour l'instant.

Cette réponse utilise déjà un maillage quadrilatéral pour un rendu d'une boîte sans les bords diagonaux d'un maillage triangle.

Sous le capot, le maillage polygonal utilise un maillage triangulaire et convertit en interne les polygones que vous fournissez en triangles.

Tronqué Maille d'icosaèdre

Nous pouvons donc faire quelque chose de similaire pour générer le maillage d'un icosaèdre tronqué, qui est le nom de la figure géométrique que nous pouvons utiliser pour générer un modèle de football simplifié.

Il a 12 faces pentagonales régulières, 20 faces hexagonales régulières et 60 sommets.

Nous avons besoin des coordonnées 3D de ces sommets, les coordonnées 2D des textures, et les indices de sommets et de textures pour chacun des 32 face.

J'ai utilisé le sandbox en ligne gratuit WolframCloud resource pour récupérer ces valeurs.

Par exemple, vous pouvez exécuter:

Flatten[PolyhedronData["TruncatedIcosahedron","VertexCoordinates"]//N]

Pour obtenir la liste des coordonnées des vertices:

Out[1]= {-0.16246,-2.11803,1.27598,-0.16246,2.11803,...}

Et, vous pouvez obtenir les visages:

PolyhedronData["TruncatedIcosahedron","FaceIndices"]
Out[2]= {{53,11,24,23,9},{51,39,40,52,30},...}

Enfin, vous avez besoin des coordonnées et des indices de textures, et qui peuvent être récupérés via le réseau de l'icosaèdre :

PolyhedronData["TruncatedIcosahedron","Net"]
PolyhedronData["TruncatedIcosahedron","NetCoordinates"]

Dans ce cas, vous obtenez les coordonnées 2D des 32 faces. Donné que nous voulons avoir la même texture pour tous les pentagones et la même pour tous les hexagones, j'ai dôme une manipulation de ces coordonnées pour arriver à cette image de texture:

Avec seulement 9 sommets, et leurs coordonnées (dans le système de coordonnées JavaFX).

Cette méthode contient les informations requises pour créer le maillage:

private PolygonMesh getTruncatedIcosahedron() {
    float[] points = new float[]{
        -0.16246f,-2.11803f,1.27598f,       -0.16246f,2.11803f,1.27598f, 
        0.16246f,-2.11803f,-1.27598f,       0.16246f,2.11803f,-1.27598f,
        -0.262866f,-0.809017f,-2.32744f,    -0.262866f,-2.42705f,-0.425325f,
        -0.262866f,0.809017f,-2.32744f,     -0.262866f,2.42705f,-0.425325f,
        0.262866f,-0.809017f,2.32744f,      0.262866f,-2.42705f,0.425325f, 
        0.262866f,0.809017f,2.32744f,       0.262866f,2.42705f,0.425325f,
        0.688191f,-0.5f,-2.32744f,          0.688191f,0.5f,-2.32744f,
        1.21392f,-2.11803f,0.425325f,       1.21392f,2.11803f,0.425325f,
        -2.06457f,-0.5f,1.27598f,           -2.06457f,0.5f,1.27598f,
        -1.37638f,-1.f,1.80171f,            -1.37638f,1.f,1.80171f,
        -1.37638f,-1.61803f,-1.27598f,      -1.37638f,1.61803f,-1.27598f,
        -0.688191f,-0.5f,2.32744f,          -0.688191f,0.5f,2.32744f,
        1.37638f,-1.f,-1.80171f,            1.37638f,1.f,-1.80171f,
        1.37638f,-1.61803f,1.27598f,        1.37638f,1.61803f,1.27598f,
        -1.7013f,0.f,-1.80171f,             1.7013f,0.f,1.80171f,
        -1.21392f,-2.11803f,-0.425325f,     -1.21392f,2.11803f,-0.425325f,
        -1.96417f,-0.809017f,-1.27598f,     -1.96417f,0.809017f,-1.27598f,
        2.06457f,-0.5f,-1.27598f,           2.06457f,0.5f,-1.27598f,
        2.22703f,-1.f,-0.425325f,           2.22703f,1.f,-0.425325f,
        2.38949f,-0.5f,0.425325f,           2.38949f,0.5f,0.425325f,
        -1.11352f,-1.80902f,1.27598f,       -1.11352f,1.80902f,1.27598f,
        1.11352f,-1.80902f,-1.27598f,       1.11352f,1.80902f,-1.27598f,
        -2.38949f,-0.5f,-0.425325f,         -2.38949f,0.5f,-0.425325f,
        -1.63925f,-1.80902f,0.425325f,      -1.63925f,1.80902f,0.425325f,
        1.63925f,-1.80902f,-0.425325f,      1.63925f,1.80902f,-0.425325f,
        1.96417f,-0.809017f,1.27598f,       1.96417f,0.809017f,1.27598f,
        0.850651f,0.f,2.32744f,             -2.22703f,-1.f,0.425325f,
        -2.22703f,1.f,0.425325f,            -0.850651f,0.f,-2.32744f,
        -0.525731f,-1.61803f,-1.80171f,     -0.525731f,1.61803f,-1.80171f,
        0.525731f,-1.61803f,1.80171f,       0.525731f,1.61803f,1.80171f};

    float[] texCoords = new float[]{0.904508f,0.820298f, 0.75f,0.529535f, 0.25f,0.529535f, 0.0954915f,0.820298f, 0.5f,1f, 
                                    1f,0.264767f, 0.75f,0f, 0.25f,0f, 0f,0.264767f};

    int faces[][] = new int[][]{{52,0,10,1,23,2,22,3,8,4},
                        {50,0,38,1,39,2,51,3,29,4},
                        {59,0,27,1,15,2,11,3,1,4},
                        {19,0,41,1,47,2,54,3,17,4},
                        {18,0,16,1,53,2,46,3,40,4},
                        {0,0,9,1,14,2,26,3,58,4},
                        {35,0,25,1,43,2,49,3,37,4},
                        {3,0,57,1,21,2,31,3,7,4},
                        {33,0,28,1,32,2,44,3,45,4},
                        {20,0,56,1,2,2,5,3,30,4},
                        {36,0,48,1,42,2,24,3,34,4},
                        {12,0,4,1,55,2,6,3,13,4},
                        {8,1,58,5,26,6,50,7,29,8,52,2},
                        {52,1,29,5,51,6,27,7,59,8,10,2},
                        {10,1,59,5,1,6,41,7,19,8,23,2},
                        {23,1,19,5,17,6,16,7,18,8,22,2},
                        {22,1,18,5,40,6,0,7,58,8,8,2},
                        {12,1,24,5,42,6,2,7,56,8,4,2},
                        {4,1,56,5,20,6,32,7,28,8,55,2},
                        {55,1,28,5,33,6,21,7,57,8,6,2},
                        {6,1,57,5,3,6,43,7,25,8,13,2},
                        {13,1,25,5,35,6,34,7,24,8,12,2},
                        {39,1,37,5,49,6,15,7,27,8,51,2},
                        {15,1,49,5,43,6,3,7,7,8,11,2},
                        {11,1,7,5,31,6,47,7,41,8,1,2},
                        {47,1,31,5,21,6,33,7,45,8,54,2},
                        {54,1,45,5,44,6,53,7,16,8,17,2},
                        {53,1,44,5,32,6,20,7,30,8,46,2},
                        {46,1,30,5,5,6,9,7,0,8,40,2},
                        {9,1,5,5,2,6,42,7,48,8,14,2},
                        {14,1,48,5,36,6,38,7,50,8,26,2},
                        {38,1,36,5,34,6,35,7,37,8,39,2}};

    int[] smooth = new int[] {
        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 
        11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 
        21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 
        31, 32
    };

    PolygonMesh mesh = new PolygonMesh(points, texCoords, faces);
    mesh.getFaceSmoothingGroups().addAll(smooth);
    return mesh;
}

Maintenant, vous pouvez facilement l'ajouter à une scène:

private double mouseOldX, mouseOldY = 0;
private final Rotate rotateX = new Rotate(0, Rotate.X_AXIS);
private final Rotate rotateY = new Rotate(0, Rotate.Y_AXIS);

@Override
public void start(Stage primaryStage) {

    PolygonMeshView meshView = new PolygonMeshView(getTruncatedIcosahedron());

    final PhongMaterial phongMaterial = new PhongMaterial();
    meshView.setDrawMode(DrawMode.LINE);
    meshView.setMaterial(phongMaterial);
    final Group group = new Group(meshView);
    group.getTransforms().add(new Scale(50, 50, 50));
    Scene scene = new Scene(group, 500, 300, true, SceneAntialiasing.BALANCED);
    scene.setOnMousePressed(event -> {
        mouseOldX = event.getSceneX();
        mouseOldY = event.getSceneY();
    });

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

    PerspectiveCamera camera = new PerspectiveCamera(false);
    camera.setNearClip(0.1);
    camera.setFarClip(1000.0);
    camera.getTransforms().addAll(rotateX, rotateY, new Translate(-250, -150, 0));
    scene.setCamera(camera);

    primaryStage.setTitle("JavaFX 3D - Truncated Icosahedron");
    primaryStage.setScene(scene);
    primaryStage.show();
}

Vous donnera le fil de fer:

fil de fer

Et si vous ajoutez l'image de la texture, vous obtiendrez votre football:

phongMaterial.setDiffuseMap(new Image(getClass().getResourceAsStream("net3.png")));
meshView.setDrawMode(DrawMode.FILL);       

football

Maintenant, c'est à vous de manipuler à votre convenance cette information, et de modifier ce maillage en celui que vous recherchez.

 2
Author: José Pereda, 2018-09-29 13:03:49