Триангуляция полигонов 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();
}