Как реализовать объединение вершин гексагона в треугольники на C++?
Сейчас я для своего опыта и интереса делаю проект на С++ в Ue4 (тут больше вопрос не по нему), в котором мне нужно генерировать гексагональную планету. Прочитав много статьей, я пришел к нескольким этапам:
- Создание икосаэдра;
- Разбиение его треугольников на меньшие;
- Нахождение центров треугольников - вершины гексагонов (и пентагонов);
- Соединение вершин гексагонов в треугольники.
Я смог сделать первые 3 пункта. На 4 я жестко подзавис, ибо надо ещё правильно объединять: против часовой стрелки.
Вот такие у меня массивы:
TArray<FVector> Vertices;
TArray<int32> Triangles;
TArray<FVector> VerticesHexagons;
TArray<int32> HexTriangles;
HexTriangles <- его я хочу использовать в ProceduralMesh, поэтому основная задача: заполнение этого массива
Использую UProceduralMeshComponent:
ProceduralMesh->CreateMeshSection(0, VerticesHexagons, HexTriangles, TArray<FVector>(), TArray<FVector2D>(), TArray<FColor>(), TArray<FProcMeshTangent>(), true);
А вот собственно генерация вершин гексагонов:
void AHexagonalSphere::CreateHexagons()
{
TMap<int32, TSet<FVector>> HexagonVerticesMap;
TMap<int32, TSet<int32>> VertexTriangleMap;
TMap<int32, TSet<int32>> TriangleNeighborsMap;
TSet<FVector> tmpVerticesHexagon;
int32 hexagonIndex = 0;
for (int32 i = 0; i < Triangles.Num() / 3; ++i)
{
int32 VertexIndex1 = Triangles[i * 3];
int32 VertexIndex2 = Triangles[i * 3 + 1];
int32 VertexIndex3 = Triangles[i * 3 + 2];
VertexTriangleMap.FindOrAdd(VertexIndex1).Add(i);
VertexTriangleMap.FindOrAdd(VertexIndex2).Add(i);
VertexTriangleMap.FindOrAdd(VertexIndex3).Add(i);
}
// Соседние треугольники (не самый лучший способ)
for (const auto& Pair : VertexTriangleMap)
{
const TSet<int32>& TrianglesSet = Pair.Value;
for (int32 TriangleA : TrianglesSet)
{
for (int32 TriangleB : TrianglesSet)
{
if (TriangleA != TriangleB)
{
TriangleNeighborsMap.FindOrAdd(TriangleA).Add(TriangleB);
}
}
}
}
for (int32 i = 0; i < Vertices.Num(); ++i)
{
const TSet<int32>& TrianglesSet = VertexTriangleMap[i];
TSet<FVector> hexagonVertices;
for (int32 Triangle : TrianglesSet)
{
int32 VertexIndex0 = Triangles[Triangle * 3];
int32 VertexIndex1 = Triangles[Triangle * 3 + 1];
int32 VertexIndex2 = Triangles[Triangle * 3 + 2];
FVector Vertex0 = Vertices[VertexIndex0];
FVector Vertex1 = Vertices[VertexIndex1];
FVector Vertex2 = Vertices[VertexIndex2];
FVector TriangleCenter = NormalizeVector((Vertex0 + Vertex1 + Vertex2) / 3.0f) * ScaleFactor;
hexagonVertices.Add(TriangleCenter);
}
HexagonVerticesMap.Add(hexagonIndex, hexagonVertices);
tmpVerticesHexagon.Append(hexagonVertices.Array());
hexagonIndex++;
}
VerticesHexagons.Append(tmpVerticesHexagon.Array());
}
TMap<int32, TSet> HexagonVerticesMap: Ключ - индекс шестиугольника (я взял вершину треугольника икосферы); значение - множество вершин, которые образуют шестиугольник
VertexTriangleMap (TMap<int32, TSet): Ключ - индекс вершины треугольника икосферы; значение - множество треугольников, которые образуют этот шестиугольник
Сам код - это мои мысли: набросок того, как я видел создание гексагонов. В одной из статьей, что я читал, были ссылки на википедию о многограннике Голдберга и нотации многогранников Конвея <- и я попытался это реализовать: что у меня почти получилось.
На изображении, снизу я показал приблезительные соединения. Желтые точки - центры многоугольников, информация о них у меня имеется: TArray Vertices;
Ответы (1 шт):
У сферы из икосаидера есть точки пятиугольников. С них начать.
Точка это центр первого пятиугольника. Собрать все треугольники с этой точкой и многоугольник готов.
Потом последовательно также создать остальные. Новые центры это углы треугольников у которых грань прилегает к существующему многоугольнику.