Триангуляция полигонов Libgdx

Итак, у меня есть многоугольник (простой, но вогнутый), который я пытаюсь разрезать на треугольники, чтобы он столкнулся с другим многоугольником.

Я знал, что мой полигон был вогнутым, поэтому я решил использовать LibGDX EarClippingTriangulator, чтобы разделить его на треугольники.

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

public void triangulate()
    {
        Vector<float[]> trianglesVertices = new Vector<float[]>();
        ShortArray pointsCoords = new ShortArray();
        EarClippingTriangulator triangulator = new EarClippingTriangulator();

        // Cut in triangles
        pointsCoords = triangulator.computeTriangles(this.getTransformedVertices());

        // Make triangles
        for (int i = 0; i < pointsCoords.size / 6; i++)
        {
            trianglesVertices.add(new float[] {
                    pointsCoords.get(i), pointsCoords.get(i+1),
                    pointsCoords.get(i+2), pointsCoords.get(i+3),
                    pointsCoords.get(i+4), pointsCoords.get(i+5),
            });
            Polygon triangle = new Polygon(trianglesVertices.get(i));
            triangles.add(triangle);
        }

        System.out.printf("Triangulation made %d triangles.\n", pointsCoords.size / 6);
    }

Но когда я пытаюсь нарисовать эти треугольники, которые я только что сделал, они просто складываются в координате 0,0... И нормально ли, что все треугольники кажутся почти одинаковыми, я имею в виду, что они все имеют одинаковую ориентацию?

Я не нашел так много информации об этом использовании трангуляции для libgdx. Вы можете помочь?

(Извините за мой английский, я француз, и извините за отсутствие фотографий, я здесь слишком молод)

РЕДАКТИРОВАТЬ: Это мой многоугольник (в CCW)

hitbox.setVertices(new float[]{  
                this.getX() + 13, this.getY() - 60,
                this.getX() + 16, this.getY() - 74,
                this.getX() + 39, this.getY() - 74,
                this.getX() + 45, this.getY() - 105,
                this.getX() + 81, this.getY() - 105,
                this.getX() + 88, this.getY() - 74,
                this.getX() + 108, this.getY() - 74,
                this.getX() + 114, this.getY() - 61,
                this.getX() + 106, this.getY() - 30, // Top right
                this.getX() + 101, this.getY() - 29,
                this.getX() + 101, this.getY() - 57,
                this.getX() + 83, this.getY() - 62,
                this.getX() + 75, this.getY() - 50,
                this.getX() + 65, this.getY() - 4, // Top mid
                this.getX() + 62, this.getY() - 4, // Top mid
                this.getX() + 52, this.getY() - 50,
                this.getX() + 44, this.getY() - 62,
                this.getX() + 25, this.getY() - 56, 
                this.getX() + 25, this.getY() - 30,
                this.getX() + 19, this.getY() - 30,  // Top left
                });

РЕДАКТИРОВАТЬ 2: Теперь я получил достаточно очков, чтобы показать вам многоугольник здесь

2 ответа

Решение

Проблема в вашем цикле:

        // Make triangles
        for (int i = 0; i < pointsCoords.size / 6; i++)
        {
            trianglesVertices.add(new float[] {
                    pointsCoords.get(i), pointsCoords.get(i+1),
                    pointsCoords.get(i+2), pointsCoords.get(i+3),
                    pointsCoords.get(i+4), pointsCoords.get(i+5),
            });
            Polygon triangle = new Polygon(trianglesVertices.get(i));
            triangles.add(triangle);
        }

Первый треугольник будет иметь правильные координаты, а второй будет использовать 1, 2, 3, 4, 5, 6 элементов pointsCoords это не имеет никакого смысла. Вы должны умножить i на 6 внутри цикла, чтобы учесть смещение:

                    pointsCoords.get(i*6), pointsCoords.get(i*6 + 1),
                    pointsCoords.get(i*6 + 2), pointsCoords.get(i*6 + 3),
                    pointsCoords.get(i*6 + 4), pointsCoords.get(i*6 + 5),

Проблема здесь в том, что EarClippingTriangulator.computeTriangles возвращает другой результат, чем вы ожидаете. Он возвращает массив индексов, где каждый индекс представляет вершину в массиве, который вы передали изначально. Так что, если вы передадите массив размером 8, это будет представлять 4 вершины; возвращаемый массив будет размером 6 (3 вершины для треугольника 1, 3 вершины для треугольника 2).

Например, если вы передаете вершины для прямоугольника 2 x 3 с нижним левым краем в (5, 5):

[5, 5, 7, 5, 7, 10, 5, 10]

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

[0, 3, 2, 2, 1, 0]

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

Треугольник 1: (5, 5) -> (5, 10) -> (7, 10)

Треугольник 2: (7, 10) -> (7, 5) -> (5, 5)

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

Вот код, который я закончил, который будет правильно рисовать Polygon экземпляры, хотя вы можете сделать то же самое с любым правильно сформулированным массивом вершин:

private void drawFilledPolygon(Polygon polygon, Color color) {
    shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
    shapeRenderer.setColor(color);

    float[] vertices = polygon.getTransformedVertices();

    // NOTE: you probably don't want to create a new EarClippingTriangulator each frame
    ShortArray triangleIndices = new EarClippingTriangulator().computeTriangles(vertices);
    for (int i = 0; i < triangleIndices.size; i += 3) {
        shapeRenderer.triangle(
            vertices[triangleIndices.get(i) * 2], vertices[triangleIndices.get(i) * 2 + 1],
            vertices[triangleIndices.get(i + 1) * 2], vertices[triangleIndices.get(i + 1) * 2 + 1],
            vertices[triangleIndices.get(i + 2) * 2], vertices[triangleIndices.get(i + 2) * 2 + 1]
        );
    }

    shapeRenderer.end();
}
Другие вопросы по тегам