So this is my first time trying to use Marching Cubes and this keeps on happening, the vertices are just not connecting to each other and I don’t know what I am doing wrong.
Here is my marching cubes file
#include "MarchingCubesMeshComponent.h"
void UMarchingCubesMeshComponent::MarchCube(
const FVector& Position,
const TArray<float>& CornerValues,
TArray<FVector>& Vertices,
TArray<int32>& Triangles,
TArray<FVector>& Normals)
{
int32 CubeIndex = 0;
for (int32 i = 0; i < 8; i++)
{
if (CornerValues[i] < SurfaceLevel)
{
CubeIndex |= (1 << i);
}
}
int32 EdgeFlags = CubeEdgeFlags[CubeIndex];
if (EdgeFlags == 0) return;
TArray<FVector> EdgeVertices;
EdgeVertices.SetNum(12);
const float Scale = 100.0f;
for (int32 i = 0; i < 12; i++)
{
if ((EdgeFlags & (1 << i)) != 0)
{
int32 V1 = EdgeConnection[i][0];
int32 V2 = EdgeConnection[i][1];
FVector P1 = Position + FVector(
VertexOffset[V1][0],
VertexOffset[V1][1],
VertexOffset[V1][2]
) * Scale;
FVector P2 = Position + FVector(
VertexOffset[V2][0],
VertexOffset[V2][1],
VertexOffset[V2][2]
) * Scale;
EdgeVertices[i] = InterpolateVerts(P1, P2, CornerValues[V1], CornerValues[V2]);
}
}
TMap<FVector, int32> VertexIndices;
int32 BaseVertexIndex = Vertices.Num();
for (int32 i = 0; TriangleConnectionTable[CubeIndex][i] != -1; i += 3)
{
TArray<int32> TriIndices;
TriIndices.SetNum(3);
for (int32 j = 0; j < 3; j++)
{
int32 EdgeIndex = TriangleConnectionTable[CubeIndex][i + j];
FVector Vertex = EdgeVertices[EdgeIndex];
const int32* ExistingIndex = VertexIndices.Find(Vertex);
if (ExistingIndex)
{
TriIndices[j] = *ExistingIndex;
}
else
{
int32 NewIndex = Vertices.Add(Vertex);
VertexIndices.Add(Vertex, NewIndex);
TriIndices[j] = NewIndex;
FVector Normal;
if (j == 0)
{
FVector Edge1 = EdgeVertices[TriangleConnectionTable[CubeIndex][i + 1]] - Vertex;
FVector Edge2 = EdgeVertices[TriangleConnectionTable[CubeIndex][i + 2]] - Vertex;
Normal = FVector::CrossProduct(Edge1, Edge2).GetSafeNormal();
}
else if (j == 1)
{
FVector Edge1 = EdgeVertices[TriangleConnectionTable[CubeIndex][i + 2]] - Vertex;
FVector Edge2 = EdgeVertices[TriangleConnectionTable[CubeIndex][i]] - Vertex;
Normal = FVector::CrossProduct(Edge1, Edge2).GetSafeNormal();
}
else
{
FVector Edge1 = EdgeVertices[TriangleConnectionTable[CubeIndex][i]] - Vertex;
FVector Edge2 = EdgeVertices[TriangleConnectionTable[CubeIndex][i + 1]] - Vertex;
Normal = FVector::CrossProduct(Edge1, Edge2).GetSafeNormal();
}
Normals.Add(Normal);
}
}
// Front face
Triangles.Add(TriIndices[0]);
Triangles.Add(TriIndices[1]);
Triangles.Add(TriIndices[2]);
// Back face
Triangles.Add(TriIndices[0]);
Triangles.Add(TriIndices[2]);
Triangles.Add(TriIndices[1]);
}
}
FVector UMarchingCubesMeshComponent::InterpolateVerts(
const FVector& v1,
const FVector& v2,
float val1,
float val2)
{
const float EPSILON = 1e-6f;
if (FMath::Abs(val1 - val2) < EPSILON)
{
return (v1 + v2) * 0.5f;
}
if (FMath::Abs(val1 - SurfaceLevel) < EPSILON) return v1;
if (FMath::Abs(val2 - SurfaceLevel) < EPSILON) return v2;
float mu = (SurfaceLevel - val1) / (val2 - val1);
mu = FMath::Clamp(mu, 0.0f, 1.0f);
FVector interpolatedPos = v1 + (v2 - v1) * mu;
return interpolatedPos;
}
And here is my GenerateWorld() function
void AVoxelWorld::GenerateWorld()
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, TEXT("Starting world generation"));
TerrainMesh->ClearAllMeshSections();
TArray<FVector> Vertices;
TArray<int32> Triangles;
TArray<FVector> Normals;
TArray<FVector2D> UVs;
TArray<FLinearColor> VertexColors;
TArray<FProcMeshTangent> Tangents;
for (int32 X = -ChunksRadius; X <= ChunksRadius; X++)
{
for (int32 Y = -ChunksRadius; Y <= ChunksRadius; Y++)
{
UVoxelChunk* ChunkData = GenerateChunk(FVoxel(X, Y, 0));
for (int32 VX = 0; VX < ChunkData->GetSize() - 1; VX++)
{
for (int32 VY = 0; VY < ChunkData->GetSize() - 1; VY++)
{
for (int32 VZ = 0; VZ < ChunkData->GetSize() - 1; VZ++)
{
TArray<float> CubeValues;
CubeValues.SetNum(8);
for (int32 i = 0; i < 8; i++)
{
int32 cx = VX + (i & 1);
int32 cy = VY + ((i & 2) >> 1);
int32 cz = VZ + ((i & 4) >> 2);
CubeValues[i] = ChunkData->GetDensity(cx, cy, cz);
}
FVector Position = ChunkData->VoxelIndexToWorld(VX, VY, VZ);
MarchingCubesMeshGenerator->MarchCube(Position, CubeValues,
Vertices, Triangles, Normals);
}
}
}
}
}
VertexColors.Init(FLinearColor::White, Vertices.Num());
for (const FVector& Vertex : Vertices)
{
UVs.Add(FVector2D(Vertex.X, Vertex.Y) / (ChunkSize * VoxelSize));
}
Tangents.Init(FProcMeshTangent(0.0f, -1.0f, 0.0f), Vertices.Num());
TerrainMesh->CreateMeshSection_LinearColor(
0,
Vertices,
Triangles,
Normals,
UVs,
VertexColors,
Tangents,
true
);
UVoxelMeshComponent::ConfigureCollision(TerrainMesh);
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green,
FString::Printf(TEXT("Generated %d vertices"), Vertices.Num()));
}
Please if you have any ideas why this is happening I would love to hear them. Thank you in advance!
PS. If you need any other information or files please let me know and I will send them!