Skip to content

Instantly share code, notes, and snippets.

@wxvyjb
Created July 9, 2024 03:00
Show Gist options
  • Save wxvyjb/9be5790a09457563819bc7b23341a06b to your computer and use it in GitHub Desktop.
Save wxvyjb/9be5790a09457563819bc7b23341a06b to your computer and use it in GitHub Desktop.
Random notes/code snippets for using the Realtime Mesh Component plugin for Unreal Engine.
I could not find many working examples for this. May create a repo for this later.
///////////////////////////////////////////////////////////////////////////////////////////////
// Code for Normal and Tangent calculation to make stuff less flat since it's just a flat plane with a height map projected
FVector3f left = x > 0 ? VertexPositions[(y * TerrainGeneratorParameters.TerrainSizeVertices) + (x - 1)] : VertexPositions[i];
FVector3f right = x < TerrainGeneratorParameters.TerrainSizeVertices - 1 ? VertexPositions[(y * TerrainGeneratorParameters.TerrainSizeVertices) + (x + 1)] : VertexPositions[i];
FVector3f bottom = y > 0 ? VertexPositions[((y - 1) * TerrainGeneratorParameters.TerrainSizeVertices) + x] : VertexPositions[i];
FVector3f top = y < TerrainGeneratorParameters.TerrainSizeVertices - 1 ? VertexPositions[((y + 1) * TerrainGeneratorParameters.TerrainSizeVertices) + x] : VertexPositions[i];
// Calculate the tangent vectors along the x and y directions
FVector3f TangentX = right - left;
FVector3f TangentY = top - bottom;
// The normal vector is the cross product of the tangent vectors
Normals[i] = FVector3f::CrossProduct(TangentX, TangentY).GetSafeNormal();
Tangents[i] = TangentX.GetSafeNormal();
///////////////////////////////////////////////////////////////////////////////////////////////
// Boilerplate code to needed generate a single square mesh
FRealtimeMeshTriMeshData RealtimeMeshData;
TArray<FVector> Verts;
Verts.Add(FVector::ZeroVector);
Verts.Add(FVector(100.0f, 0.0f, 0.0f));
Verts.Add(FVector(0.0f, 100.0f, 0.0f));
Verts.Add(FVector(0.0f, -100.0f, 0.0f));
TArray<int32> Tris;
Tris.Add(0);
Tris.Add(2);
Tris.Add(1);
Tris.Add(0);
Tris.Add(1);
Tris.Add(3);
TArray<int32> MI;
MI.Add(0);
MI.Add(0);
TArray<FVector2D> UV0;
UV0.Add(FVector2D(0.0f, 0.0f));
UV0.Add(FVector2D(0.0f, 1.0f));
UV0.Add(FVector2D(1.0f, 1.0f));
UV0.Add(FVector2D(1.0f, 0.0f));
TArray<FVector> Normals;
RealtimeMeshData.UV0 = UV0;
RealtimeMeshData.Positions = Verts;
RealtimeMeshData.Triangles = Tris;
RealtimeMeshData.MaterialIndex = MI;
RealtimeMeshData.Normals = Normals;
///////////////////////////////////////////////////////////////////////////////////////////////
// Code to generate a wavy Sin/Cos plane using the RealtimeMeshComponent plugin.
RealtimeMesh = nullptr;
RealtimeMesh = GetRealtimeMeshComponent()->InitializeRealtimeMesh<URealtimeMeshSimple>();
FRealtimeMeshStreamSet StreamSet;
TRealtimeMeshBuilderLocal<uint16, FPackedNormal, FVector2DHalf, 1> Builder(StreamSet);
Builder.EnableTangents();
Builder.EnableTexCoords();
Builder.EnableColors();
// Poly groups allow us to easily create a single set of buffers with multiple sections by adding an index to the triangle data
Builder.EnablePolyGroups();
// initialize vertices
for (uint32 y = 0; y < chunk_y; y++)
{
for (uint32 x = 0; x < chunk_x; x++)
{
//vertices.Add(
Builder
.AddVertex(FVector3f(x * 10.f, y * 10.f, (sin(x) * cos(y) * 10.f)))
.SetNormalAndTangent(FVector3f(0.0f, 0.0f, 1.0f), FVector3f(1.0f, 0.0f, 0.0f))
.SetColor(FColor::Red)
.SetTexCoord(FVector2f(static_cast<float>(x) / (chunk_x - 1), static_cast<float>(y) / (chunk_y - 1)));
//);
}
}
for (uint32 y = 0; y < chunk_y - 1; y++)
{
for (uint32 x = 0; x < chunk_x - 1; x++)
{
uint32 v0 = (y * chunk_x) + x;
uint32 v1 = (y * chunk_x) + x + 1;
uint32 v2 = ((y + 1) * chunk_x) + x;
uint32 v3 = ((y + 1) * chunk_x) + x + 1;
uint32 tri1 = Builder.AddTriangle(v2, v1, v0, 0);
uint32 tri2 = Builder.AddTriangle(v1, v2, v3, 0);
}
}
// setup material slots
RealtimeMesh->SetupMaterialSlot(0, "PrimaryMaterial");
const FRealtimeMeshSectionGroupKey GroupKey = FRealtimeMeshSectionGroupKey::Create(0, FName("TestTriangle"));
const FRealtimeMeshSectionKey PolyGroup0SectionKey = FRealtimeMeshSectionKey::CreateForPolyGroup(GroupKey, 0);
// Now we create the section group, since the stream set has polygroups, this will create the sections as well
RealtimeMesh->CreateSectionGroup(GroupKey, StreamSet);
// Update the configuration of both the polygroup sections.
RealtimeMesh->UpdateSectionConfig(PolyGroup0SectionKey, FRealtimeMeshSectionConfig(ERealtimeMeshSectionDrawType::Static, 0));
Super::OnGenerateMesh_Implementation();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment