While our game may be running without any issues in the editor or even in…
Creating Procedural Meshes
In this post we’re going to see how to create a simple procedural mesh during runtime in Unreal Engine 4.
While there are several components and plugins (most notably RuntimeMeshComponent by Koderz) that you can use in order to create procedural meshes in UE4, I’m going to use the official Procedural Component that is provided with the engine.
Adding the required Dependencies
For this post I have created a C++ project using the 4.18.3 version of the engine. Then, I added the ProceduralMeshComponent as a dependency in the public module names in the <MyProject>.Build.cs file:
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "ProceduralMeshComponent" });Note that when you’ve added the dependency, you have to regenerate your project’s visual studio files via the .uproject file, otherwise when you attempt to access the necessary header files your project won’t be able to compile.
Creating the procedural mesh
The procedural mesh we’re going to create in this post is a simple cube. Create a new C++ class that inherits the actor class and declare the following properties on its header file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public: // Sets default values for this actor's properties AMyActor(); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; UPROPERTY(VisibleAnywhere,BlueprintReadWrite) UProceduralMeshComponent* CustomMesh; /* The vertices of the mesh */ TArray<FVector> Vertices; /* The triangles of the mesh */ TArray<int32> Triangles; /* Creates a triangle that connects the given vertices */ void AddTriangle(int32 V1, int32 V2, int32 V3); void GenerateCubeMesh(); public: // Called every frame virtual void Tick(float DeltaTime) override; |
Moreover, make sure to include the “ProceduralMeshComponent.h” file in your includes.
In order to create a mesh we need to provide a list of vertices and triangles to the Procedural Mesh Component so the engine can draw our geometry in the Viewport. Since we’re going to create a cube we need 8 vertices (one for each corner of the cube) and 12 triangles (2 for each face of the cube). Moreover, we’re going to provide a color for each vertex and colorize the whole cube later on. So here’s the whole code needed to draw a 100cm sized cube:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
// Sets default values AMyActor::AMyActor() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; CustomMesh = CreateDefaultSubobject<UProceduralMeshComponent>("CustomMesh"); SetRootComponent(CustomMesh); CustomMesh->bUseAsyncCooking = true; } // Called when the game starts or when spawned void AMyActor::BeginPlay() { Super::BeginPlay(); GenerateCubeMesh(); } void AMyActor::AddTriangle(int32 V1, int32 V2, int32 V3) { Triangles.Add(V1); Triangles.Add(V2); Triangles.Add(V3); } void AMyActor::GenerateCubeMesh() { //6 sides on cube, 4 verts each (corners) //These are relative locations to the placed Actor in the world Vertices.Add(FVector(0, -100, 0)); //lower left - 0 Vertices.Add(FVector(0, -100, 100)); //upper left - 1 Vertices.Add(FVector(0, 100, 0)); //lower right - 2 Vertices.Add(FVector(0, 100, 100)); //upper right - 3 Vertices.Add(FVector(100, -100, 0)); //lower front left - 4 Vertices.Add(FVector(100, -100, 100)); //upper front left - 5 Vertices.Add(FVector(100, 100, 100)); //upper front right - 6 Vertices.Add(FVector(100, 100, 0)); //lower front right - 7 //Back face of cube AddTriangle(0, 2, 3); AddTriangle(3, 1, 0); //Left face of cube AddTriangle(0, 1, 4); AddTriangle(4, 1, 5); //Front face of cube AddTriangle(4, 5, 7); AddTriangle(7, 5, 6); //Right face of cube AddTriangle(7, 6, 3); AddTriangle(3, 2, 7); //Top face AddTriangle(1, 3, 5); AddTriangle(6, 5, 3); //bottom face AddTriangle(2, 0, 4); AddTriangle(4, 7, 2); TArray<FLinearColor> VertexColors; VertexColors.Add(FLinearColor(0.f, 0.f, 1.f)); VertexColors.Add(FLinearColor(1.f, 0.f, 0.f)); VertexColors.Add(FLinearColor(1.f, 0.f, 0.f)); VertexColors.Add(FLinearColor(0.f, 1.f, 0.f)); VertexColors.Add(FLinearColor(0.5f, 1.f, 0.5f)); VertexColors.Add(FLinearColor(0.f, 1.f, 0.f)); VertexColors.Add(FLinearColor(1.f, 1.f, 0.f)); VertexColors.Add(FLinearColor(0.f, 1.f, 1.f)); CustomMesh->CreateMeshSection_LinearColor(0, Vertices, Triangles, TArray<FVector>(), TArray<FVector2D>(), VertexColors, TArray<FProcMeshTangent>(),true); } |
The AddTriangle function creates a triangle between the given vertices. So for example, when I add the vertices 0,2 and 3 the component will create a triangle connecting these three vertices (in this case the lower left, lower right and upper right corners of the cube). At this point, it is important to note that the way you’re adding your vertices in the triangles array matters. When you add your vertices in a counter-clockwise manner the engine will make sure that your triangle will face outwards instead of inwards. To display this, take a look at what happens if on the above code segment in line 45 we add the vertices 3,2,0 instead of 0,2,3:
For more information regarding the facing of your triangles check out this post on UE4 answerhub.
Adding colors on the generated mesh
At this point, you’re going to have a default colored mesh instead of the colors shown above. To colorize your mesh, create the following material and assign it in your CustomMesh component in the begin play function:
Note that the BP_ProcMeshActor is a Blueprint based on the C++ class we’ve created above.
Animating our mesh
Let’s say that we want to move our mesh forward. To do that we have to modify the location of each vertex and then tell our component to update the section of the mesh we modified. To move our cube 1 unit each frame, type in the following code on your Tick function:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// Called every frame void AMyActor::Tick(float DeltaTime) { Super::Tick(DeltaTime); //Moving the mesh for (int32 index = 0; index < Vertices.Num(); index++) { //Moving each vertex 1 unit forward Vertices[index] += FVector(1, 0, 0); } CustomMesh->UpdateMeshSection(0, Vertices, TArray<FVector>(), TArray<FVector2D>(), TArray<FColor>(), TArray<FProcMeshTangent>()); } |
Here’s a video displaying the final result of the post:
May be alot to ask for but could you show us how to make objects transparent between camera and player character?
Hi, do you know if there are any advantages to using procedural mesh over custom meshes?
you can edit the mesh at runtime
Thank You. This helped a lot.
i m using 4.7.6 n got compile err could not find ProceduralMeshComponent in the dependency cs please advise
When I create the BP_ProcMeshActor I do not have the inherited CustomMesh component? Should it appear there by default?