Почему эти JavaFX TriangleMesh рендеринг с темными артефактами тени? - PullRequest
0 голосов
/ 09 июня 2018

Решено

Решение, связанное с группами сглаживания.

В методе loadFixedSphereMeshView () я добавил:

... after points array
int faceSmoothingGroups[] = {
    0, 0, 0, 0, 0, 0, 0, 0
};
... before faces array

, а затемдобавлено:

... after setting the faces
mesh.getFaceSmoothingGroups().setAll(faceSmoothingGroups);

Примечание: количество элементов в массиве faceSmootingGroups должно равняться количеству граней в сетке.


Мои два октаэдра на основе TriangleMesh отрисовываются со странной темнотой«тени», тогда как стандартная коробка отлично отрисовывается.Я пытаюсь понять, что я делаю неправильно, когда я строю октаэдры.

Пожалуйста, быстро взгляните на изображение и короткое видео, которое я включил, поскольку они иллюстрируют визуальный артефакт, который я пытаюсь понять.

Изображение, иллюстрирующее рендеринг

Короткое видео, иллюстрирующее рендеринг

Система координат, на которую я ссылаюсь

Я работаю над небольшим приложением, которое будет отображать сферическую трехмерную сетку, созданную MeshBuilder - классом в другом проекте.Отправной точкой для этой сферической сетки является простой октаэдр.Приведенный ниже код представляет собой небольшое приложение, предназначенное для меня, чтобы понять, как работает JavaFX 3D, поскольку я новичок в нем.

Программа отображает стандартный зеленый прямоугольник JavaFX в центре, красный октаэдр справа ивторой синий октаэдр слева.Есть флажки, которые изменяют рендеринг октаэдров во время работы программы.

Красный октаэдр создается «вручную» в методе loadFixedSphereMeshView (), а синий октаэдр создается с использованием MeshBuilder в loadProceeduralSphereMeshView ().Код в MeshBuilder тестируется модулем на жестко закодированном октаэдре, чтобы убедиться, что он строит тот же октаэдр.

Я настроил все так, чтобы я мог:

  • См.как визуализировать сетки, ссылаясь на поле
  • Измените код для красного октаэдра, чтобы заставить его правильно отображаться
  • Проведите модульное тестирование MeshBuilder против данных красного октаэдра, как только правильно отобразится

Я сосредоточен на попытках понять, что я делаю неправильно, когда я вручную строю красный октаэдр, что приводит к его рендерингу с этими «теневыми» артефактами.

Рывок видеопрограммное обеспечение захвата не программа.

Спасибо за чтение.

public class Main extends Application {

    private static final int VIEWPORT_SIZE = 800;

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

    private Image texture;
    private final PhongMaterial texturedMaterial = new PhongMaterial();
    private final PhongMaterial redMaterial = new PhongMaterial();
    private final PhongMaterial blueMaterial = new PhongMaterial();
    private final PhongMaterial greenMaterial = new PhongMaterial();
    private final MeshView fixedSphereMeshView = loadFixedSphereMeshView();
    private final MeshView proceeduralSphereMeshView = loadProceeduralSphereMeshView();

    @Override
    public void start(Stage stage) throws Exception {
        texture = new Image(textureLoc);
        texturedMaterial.setDiffuseMap(texture);
        redMaterial.setDiffuseColor(Color.RED);
        blueMaterial.setDiffuseColor(Color.BLUE);
        greenMaterial.setDiffuseColor(Color.GREEN);
        Group group = buildScene();
        RotateTransition rotate = rotate3dGroup(group);
        VBox layout = new VBox(
            createControls(rotate),
            createScene3D(group)
        );
    //        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
        Scene scene = new Scene(layout);
        stage.setTitle("Icosphere Viewer");
        stage.setScene(scene);
        stage.show();
    }

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

    private MeshView loadFixedSphereMeshView() {
        float[] points = {
            0, -1, 0, // p0
            0, 0, -1, // p1
            1, 0, 0, //  p2
            0, 0, 1, //  p3
            -1, 0, 0, // p4
            0, 1, 0 //   p5
        };
        float[] texCoords = {
            1, 1, // index t0
            1, 0, // index t1
            0, 1, // index t2
            0, 0 //  index t3
        };
        int[] faces = {
            0, 0, 1, 1, 2, 2, // p0 t0 p1 t1 p2 t2
            0, 0, 2, 2, 3, 3, // p0 t0 p2 t2 p3 t3
            0, 0, 3, 1, 4, 2, // p0 t0 p3 t1 p4 t2
            0, 0, 4, 2, 1, 3, // p0 t0 p4 t2 p1 t3
            5, 0, 2, 0, 1, 0, // p5 t0 p2 t0 p1 t0
            5, 0, 3, 0, 2, 0, // p5 t0 p3 t0 p2 t0
            5, 0, 4, 0, 3, 0, // p5 t0 p4 t0 p3 t0
            5, 0, 1, 0, 4, 0 //  p5 t0 p1 t0 p4 t0
        };

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

        return new MeshView(mesh);
    }

    private MeshView loadProceeduralSphereMeshView() {
        SphereMesh sphereMesh = MeshBuilder.buildOctosphereMesh(0);
        float[] points = sphereMesh.getPoints();
        float[] texCoords = {
            1, 1, // index t0
            1, 0, // index t1
            0, 1, // index t2
            0, 0 //  index t3
        };
        int[] faces = sphereMesh.getFaces();

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

        return new MeshView(mesh);
    }

    private Group buildScene() {
        Box box = new Box(1, 1, 1);
        box.setTranslateX(0);
        box.setTranslateY(0);
        box.setTranslateZ(0);
        box.setMaterial(greenMaterial);
        proceeduralSphereMeshView.setTranslateX(-2);
        proceeduralSphereMeshView.setTranslateY(0);
        proceeduralSphereMeshView.setTranslateZ(0);
        proceeduralSphereMeshView.setMaterial(blueMaterial);
        fixedSphereMeshView.setTranslateX(2);
        fixedSphereMeshView.setTranslateY(0);
        fixedSphereMeshView.setTranslateZ(0);
        fixedSphereMeshView.setMaterial(redMaterial);
        Group group = new Group(proceeduralSphereMeshView, fixedSphereMeshView, box);
        group.setTranslateZ(10);
        return group;
    }

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

    private VBox createControls(RotateTransition rotateTransition) {

        CheckBox cull = new CheckBox("Cull Back");
        proceeduralSphereMeshView.cullFaceProperty().bind(
            Bindings.when(
                    cull.selectedProperty())
                    .then(CullFace.BACK)
                    .otherwise(CullFace.NONE)
        );
        fixedSphereMeshView.cullFaceProperty().bind(
            Bindings.when(
                    cull.selectedProperty())
                    .then(CullFace.BACK)
                    .otherwise(CullFace.NONE)
        );

        CheckBox wireframe = new CheckBox("Wireframe");
        proceeduralSphereMeshView.drawModeProperty().bind(
            Bindings.when(
                    wireframe.selectedProperty())
                    .then(DrawMode.LINE)
                    .otherwise(DrawMode.FILL)
        );
        fixedSphereMeshView.drawModeProperty().bind(
            Bindings.when(
                    wireframe.selectedProperty())
                    .then(DrawMode.LINE)
                    .otherwise(DrawMode.FILL)
        );

        CheckBox texture = new CheckBox("Texture");
        proceeduralSphereMeshView.materialProperty().bind(
            Bindings.when(
                    texture.selectedProperty())
                    .then(texturedMaterial)
                    .otherwise((PhongMaterial) blueMaterial)
        );
        fixedSphereMeshView.materialProperty().bind(
            Bindings.when(
                    texture.selectedProperty())
                    .then(texturedMaterial)
                    .otherwise((PhongMaterial) redMaterial)
        );

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

        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;
    }

}
...