TriangleMesh - видны задние грани

Хорошего дня! У меня есть следующая проблема. Графическая модель отображается неправильно: некоторые задние грани модели, которые должны быть скрыты передней стороной, остаются видимыми. Вот несколько примеров для пояснения: (изометрия) введите описание изображения здесь

(Выпуск)

введите описание изображения здесь

Эта проблема особенно заметна при использовании света и материалов. Таким образом, вопрос в том, как это можно решить для JavaFX?

UPD:

public class VertexTest extends Application {

    PerspectiveCamera camera;
    Cam cam = new Cam();
    double mouseOldX, mouseOldY, mousePosX, mousePosY, mouseDeltaX, mouseDeltaY;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        TriangleMesh mesh = new Shape3DRectangle(100, 100, 100);
        MeshView view = new MeshView(mesh);
        view.setDrawMode(DrawMode.LINE);
        view.setMaterial(new PhongMaterial(Color.RED));

        cam.getChildren().add(view);

        Scene scene = new Scene(cam, 1000, 1000, true);

        addEvents(view, scene);

        camera = new PerspectiveCamera();
        camera.setTranslateX(-500);
        camera.setTranslateY(-500);
        camera.setTranslateZ(1000);


        scene.setCamera(camera);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void addEvents(MeshView view, Scene s) {

        s.setOnMouseDragged(new EventHandler<MouseEvent>() {
            public void handle(MouseEvent me) {
                mouseOldX = mousePosX;
                mouseOldY = mousePosY;
                mousePosX = me.getX();
                mousePosY = me.getY();
                mouseDeltaX = mousePosX - mouseOldX;
                mouseDeltaY = mousePosY - mouseOldY;
                cam.ry.setAngle(cam.ry.getAngle() - mouseDeltaX);
                cam.rx.setAngle(cam.rx.getAngle() + mouseDeltaY);
            }
        });
    }

    class Cam extends Group {
        Translate t = new Translate();
        Translate p = new Translate();
        Translate ip = new Translate();
        Rotate rx = new Rotate();
        {
            rx.setAxis(Rotate.X_AXIS);
        }
        Rotate ry = new Rotate();
        {
            ry.setAxis(Rotate.Y_AXIS);
        }
        Rotate rz = new Rotate();
        {
            rz.setAxis(Rotate.Z_AXIS);
        }
        Scale s = new Scale();

        public Cam() {
            super();
            getTransforms().addAll(t, p, rx, rz, ry, s, ip);
        }
    }



    public class Shape3DRectangle extends TriangleMesh {

        public Shape3DRectangle(float Width, float Height, float deep) {

            this.getPoints().setAll(-Width / 2, Height / 2, deep / 2, // idx p0
                    Width / 2, Height / 2, deep / 2, // idx p1
                    -Width / 2, -Height / 2, deep / 2, // idx p2
                    Width / 2, -Height / 2, deep / 2, // idx p3
                    -Width / 2, Height / 2, -deep / 2, // idx p4
                    Width / 2, Height / 2, -deep / 2, // idx p5
                    -Width / 2, -Height / 2, -deep / 2, // idx p6
                    Width, -Height / 2, -deep / 2 // idx p7
            );

            this.getTexCoords().addAll(0.0f, 0.0f);

            this.getFaces().addAll(5, 0, 4, 0, 0, 0 // P5,T1 ,P4,T0 ,P0,T3
                    , 5, 0, 0, 0, 1, 0 // P5,T1 ,P0,T3 ,P1,T4
                    , 0, 0, 4, 0, 6, 0 // P0,T3 ,P4,T2 ,P6,T7
                    , 0, 0, 6, 0, 2, 0 // P0,T3 ,P6,T7 ,P2,T8
                    , 1, 0, 0, 0, 2, 0 // P1,T4 ,P0,T3 ,P2,T8
                    , 1, 0, 2, 0, 3, 0 // P1,T4 ,P2,T8 ,P3,T9
                    , 5, 0, 1, 0, 3, 0 // P5,T5 ,P1,T4 ,P3,T9
                    , 5, 0, 3, 0, 7, 0 // P5,T5 ,P3,T9 ,P7,T10
                    , 4, 0, 5, 0, 7, 0 // P4,T6 ,P5,T5 ,P7,T10
                    , 4, 0, 7, 0, 6, 0 // P4,T6 ,P7,T10 ,P6,T11
                    , 3, 0, 2, 0, 6, 0 // P3,T9 ,P2,T8 ,P6,T12
                    , 3, 0, 6, 0, 7, 0 // P3,T9 ,P6,T12 ,P7,T13
            );
        }
    }

}

3 ответа

Решение

Я играл с твоим образцом и думаю, что выяснил причину твоих проблем.

Сначала я проверил извилистость лица. Все они против часовой стрелки, поэтому все их нормали выходят наружу, как и должно быть.

Затем я изменил другие вершины вместо последней. В некоторых случаях проблем не было, в других проблема все еще была.

В основном, проблема возникает, когда есть "вогнутые" поверхности, то есть две грани имеют нормали, которые будут пересекаться. И это не происходит, когда все поверхности "выпуклые", то есть их нормали направлены наружу и не пересекаются.

Это четкое изображение обоих типов мешей, взятых отсюда:

Возвращаясь к вашему примеру, вы определяете вогнутую сетку:

вопрос

Но если вместо изменения вершины № 7 мы увеличим размер № 5, у нас будет выпуклая сетка без проблем рендеринга:

нет проблем

Очевидно, что, хотя это решает проблему рендеринга, оно меняет вашу первоначальную форму.

Если вы хотите сохранить исходную геометрию, другим возможным решением является изменение граней, поэтому у вас нет вогнутых областей.

Давайте посмотрим на грани 5-1-3 и 5-3-7, и предположим, что мы хотим теперь переместить вершину #1.

Если мы сохраним ваши треугольники, грани 5-1-3 и 5-3-7 будут определять вогнутую поверхность для рендеринга (их нормали будут пересекаться), в то время как если мы изменим эти треугольники на 5-1-7 и 1-3-7, тогда поверхность будет выпуклой (их нормали не будут пересекаться):

нормативы

Возвращаясь к исходной форме, это изменение этих двух граней решит проблемы рендеринга.

решаемая

Хотя вершины одинаковы, геометрия немного отличается. Так что это требует некоторой доработки (больше элементов). Добавление этих элементов должно быть сделано с учетом этой выпуклой концепции. Однако проблема не является тривиальной, как вы можете видеть здесь.

Хороший анализ Хосе, но мне кажется, что ОП только что забыл разделить ширину на 2 в этой строке своего кода.

Width, -Height / 2, -deep / 2 // idx p7

должно быть

Width / 2, -Height / 2, -deep / 2 // idx p7

Класс называется Shape3DRectangle, но с этой ошибкой геометрия больше не является прямоугольной.

Вы можете установить cullFaceProperty для каждого Shape3D. Я думаю, это то, что вам нужно, но я не уверен, правильно ли я понял ваш вопрос.

Shape3D # cullFaceProperty

Другие вопросы по тегам