Runtime Mesh Component

Hi,

I’m using the plugin through it’s sources. The integration into my project works fine for about 3 months. Basically I’m using it to import user data at runtime from files (FBX, SKP, …). I have to mention that I’m using only the C++ API.

Since yesterday, I switched from the 4.14.3 version of the engine to the 4.15 version. Since then, when I load user data, no geometry appears on the screen. I checked on my code, everything seems fine.

The fun fact is that I made a BP creating a RMC and fill it with a simple quad (two triangles). That worked, when I hit play, the quad appears on the screen.

I stepped into the code, it seems that both my code and the BP I created enters the same methods …

Any idea on what changed in 4.15 that may cause this issue ?

Tested on 4.12. I’m not sure about 4.13+. It bugged If you reference to actor containing ProceduralMeshComponent or RMC (plugin ver. 2) from FPC actor (for example to get variables from target). Can't find file for asset with ProceduralMeshComponent - Programming & Scripting - Epic Developer Community Forums

Don’t you use fbxsdk?:confused:

Thanks. Though Epic’s update process must be painfully slow. Such a tease having a shiny new engine version that I can’t update to. :frowning:

Usually they’re pretty quick for updates, but I haven’t heard anything back… Wondering if the email failed to go through because now that I look back I don’t even have the automated response I usually get from the ticket system it goes too. Just resent it, we’ll see how it goes!

Hi, I really like the plugin, congratulations for your work. I’m completely new to UE4. I am also implementing Dual Contouring algorithm and at the begining was using Procedural Mesh Component. After a while I found your Runtime Mesh Component, I wanted to try it out. The issue I am having is: I would like to have a colored vertices, instead of materials. Could you help me with this?

I tried changing your examples a bit to fill the ColorBuffer with apropriate colors:
RuntimeMeshLibrary.cpp:



void URuntimeMeshLibrary::CreateBoxMesh1(FVector BoxRadius, TArray<FVector>& Vertices, TArray<int32>& Triangles, TArray<FVector>& Normals, TArray<FVector2D>& UVs, TArray<FRuntimeMeshTangent>& Tangents, TArray<FColor>& Colors)
{
	// Generate verts
	FVector BoxVerts[8];
	BoxVerts[0] = FVector(-BoxRadius.X, BoxRadius.Y, BoxRadius.Z);
	BoxVerts[1] = FVector(BoxRadius.X, BoxRadius.Y, BoxRadius.Z);
	BoxVerts[2] = FVector(BoxRadius.X, -BoxRadius.Y, BoxRadius.Z);
	BoxVerts[3] = FVector(-BoxRadius.X, -BoxRadius.Y, BoxRadius.Z);

	BoxVerts[4] = FVector(-BoxRadius.X, BoxRadius.Y, -BoxRadius.Z);
	BoxVerts[5] = FVector(BoxRadius.X, BoxRadius.Y, -BoxRadius.Z);
	BoxVerts[6] = FVector(BoxRadius.X, -BoxRadius.Y, -BoxRadius.Z);
	BoxVerts[7] = FVector(-BoxRadius.X, -BoxRadius.Y, -BoxRadius.Z);

	// Generate triangles (from quads)
	Triangles.Reset();

	const int32 NumVerts = 24; // 6 faces x 4 verts per face

	Colors.Reset(); 
	Colors.AddUninitialized(NumVerts);

	for (int i = 0; i < NumVerts; i++)
		Colors.Add(FColor(255, 0, 0, 255)); 

	Vertices.Reset();
	Vertices.AddUninitialized(NumVerts);

	Normals.Reset();
	Normals.AddUninitialized(NumVerts);

	Tangents.Reset();
	Tangents.AddUninitialized(NumVerts);

	Vertices[0] = BoxVerts[0];
	Vertices[1] = BoxVerts[1];
	Vertices[2] = BoxVerts[2];
	Vertices[3] = BoxVerts[3];
	ConvertQuadToTriangles(Triangles, 0, 1, 2, 3);
	Normals[0] = Normals[1] = Normals[2] = Normals[3] = FVector(0, 0, 1);
	Tangents[0] = Tangents[1] = Tangents[2] = Tangents[3] = FRuntimeMeshTangent(0.f, -1.f, 0.f);

	Vertices[4] = BoxVerts[4];
	Vertices[5] = BoxVerts[0];
	Vertices[6] = BoxVerts[3];
	Vertices[7] = BoxVerts[7];
	ConvertQuadToTriangles(Triangles, 4, 5, 6, 7);
	Normals[4] = Normals[5] = Normals[6] = Normals[7] = FVector(-1, 0, 0);
	Tangents[4] = Tangents[5] = Tangents[6] = Tangents[7] = FRuntimeMeshTangent(0.f, -1.f, 0.f);

	Vertices[8] = BoxVerts[5];
	Vertices[9] = BoxVerts[1];
	Vertices[10] = BoxVerts[0];
	Vertices[11] = BoxVerts[4];
	ConvertQuadToTriangles(Triangles, 8, 9, 10, 11);
	Normals[8] = Normals[9] = Normals[10] = Normals[11] = FVector(0, 1, 0);
	Tangents[8] = Tangents[9] = Tangents[10] = Tangents[11] = FRuntimeMeshTangent(-1.f, 0.f, 0.f);

	Vertices[12] = BoxVerts[6];
	Vertices[13] = BoxVerts[2];
	Vertices[14] = BoxVerts[1];
	Vertices[15] = BoxVerts[5];
	ConvertQuadToTriangles(Triangles, 12, 13, 14, 15);
	Normals[12] = Normals[13] = Normals[14] = Normals[15] = FVector(1, 0, 0);
	Tangents[12] = Tangents[13] = Tangents[14] = Tangents[15] = FRuntimeMeshTangent(0.f, 1.f, 0.f);

	Vertices[16] = BoxVerts[7];
	Vertices[17] = BoxVerts[3];
	Vertices[18] = BoxVerts[2];
	Vertices[19] = BoxVerts[6];
	ConvertQuadToTriangles(Triangles, 16, 17, 18, 19);
	Normals[16] = Normals[17] = Normals[18] = Normals[19] = FVector(0, -1, 0);
	Tangents[16] = Tangents[17] = Tangents[18] = Tangents[19] = FRuntimeMeshTangent(1.f, 0.f, 0.f);

	Vertices[20] = BoxVerts[7];
	Vertices[21] = BoxVerts[6];
	Vertices[22] = BoxVerts[5];
	Vertices[23] = BoxVerts[4];
	ConvertQuadToTriangles(Triangles, 20, 21, 22, 23);
	Normals[20] = Normals[21] = Normals[22] = Normals[23] = FVector(0, 0, -1);
	Tangents[20] = Tangents[21] = Tangents[22] = Tangents[23] = FRuntimeMeshTangent(0.f, 1.f, 0.f);

	// UVs
	UVs.Reset();
	UVs.AddUninitialized(NumVerts);

	UVs[0] = UVs[4] = UVs[8] = UVs[12] = UVs[16] = UVs[20] = FVector2D(0.f, 0.f);
	UVs[1] = UVs[5] = UVs[9] = UVs[13] = UVs[17] = UVs[21] = FVector2D(0.f, 1.f);
	UVs[2] = UVs[6] = UVs[10] = UVs[14] = UVs[18] = UVs[22] = FVector2D(1.f, 1.f);
	UVs[3] = UVs[7] = UVs[11] = UVs[15] = UVs[19] = UVs[23] = FVector2D(1.f, 0.f);
}


RuntimeMeshLibrary.h:



UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
	static void CreateBoxMesh1(FVector BoxRadius, TArray<FVector>& Vertices, TArray<int32>& Triangles, TArray<FVector>& Normals, TArray<FVector2D>& UVs, TArray<FRuntimeMeshTangent>& Tangents, TArray<FColor>& Colors); 



BasicRMCActor.cpp:



void ABasicRMCActor::OnConstruction(const FTransform& Transform)
{
	TArray<FVector> Vertices;
	TArray<FVector> Normals;
	TArray<FRuntimeMeshTangent> Tangents;
	TArray<FVector2D> TextureCoordinates;
	TArray<int32> Triangles;
	TArray<FColor> Colors;

	URuntimeMeshLibrary::CreateBoxMesh1(FVector(500, 500, 500), Vertices, Triangles, Normals, TextureCoordinates, Tangents, Colors);

	// Create the mesh section specifying collision
	RuntimeMesh->CreateMeshSection(0, Vertices, Triangles, Normals, TextureCoordinates, Colors, Tangents, true, EUpdateFrequency::Infrequent);
}


But the effect is as shown in the image below:

@PJ87: Are you using the vertex colors in your material? You need to apply a material to the mesh that uses the vertex color.

Actually probably not, I am googling on how to do it, but I couldn’t find the exact way to do it.

//EDIT: I am posting the blueprint of the material I am using. This material doesn’t show the vertex colors.

//EDIT2: I also tried changing it, so it would look like in the picture below, but still no luck.

I finally managed to solve the problem. I will post it if somebody encounters a similar problem.



for (int i = 0; i < NumVerts / 3; i++)
	{
		Colors[i * 3] = FColor(255, 0, 0); 
		Colors[i * 3 + 1] = FColor(0, 255, 0);
		Colors[i * 3 + 2] = FColor(0, 0, 255);
	}


Hey, just found your plugin and it appears to be awesome, I am on 4.15 however and 2.0 from github doesn’t compile. Any chance to get an updated version? Otherwise I will go and try to fix the compiler errors.

Edit: Pulled master branch and it works.

First off, sorry for the double post, but I got it working and I love that I was just able to pop it in for the ProceduralMeshComponent.
I have a few questions though.

I am working on a pretty large and complex procedural hex grid terrain.

c7ddb93937054ff25c3e71586bdaad43197bb49c.jpeg

It gets pretty complex on the highest LOD level.

At the moment I have everyting separated into 8x8 chunks to make use of automated frustum culling
(chunks are actually of variable size, so I can tweak frustum culling vs draw calls)

It actually blows the ProceduralMeshComponent out of the water in terms of performance. But, the more chunks I add the more it slows down though. Which would be expected but frustum culling should also make sure that the meshes out of the view can just be ignored for the most part.
So my main question is: how to get the most out of this for large terrains with high poly count (other than a dynamic LOD system - which I am working on atm). Mesh extraction/polygonizing is quite costly and I’d like to implement a multithreaded solution for it, but not sure how the UpdateFrequency thing works.
Could you give me some hints? :slight_smile:

Hey @, I’m trying out your Runtime Mesh Component (on 4.15) as performance is critical on what I am doing but I think I found a crash :frowning: Calling URuntimeMeshLibrary::CalculateTangentsForMesh for a simple plane mesh causes a crash on GetUv() line 786 on RuntimeMeshBuilder.cpp, this is called by line 241 of the same file. It seems it’s counting on a second Uv Map but there is none because CalculateTangentsForMesh passes a nullptr to the UV1 argument on the vertex builder.
My Mesh as only one uv map, but nonetheless even if it had two only the first one is used to calculate normals/tangents so I think this might be a bug.

As a “workaround” I am using Epic’s implementation of CalculateTangentsForMesh which works but the problem is, not only to I not gain the speed upgrade of RMC’s function as I have to spend more cycles converting back and forth between the FProcMeshTangent and FRuntimeMeshTangent.

Maybe you could take a look at it? It might be an easy fix for you as I am sure you know that class like the palm of your hand by now :stuck_out_tongue:

I just checked again then and the epic turtle hasn’t moved yet. I’m wondering if there is something wrong, like they aren’t receiving any of your communication or something.

Looks like Epic just updated the plugin to 4.15! Thanks !

Marketplace RMC on UE4.15!

As Feifox already mentioned… The marketplace version of the RMC has been updated to 4.15 as of this afternoon!

It’s a tradeoff. You’re going to have to accept some overdraw and things as the overhead of too many individual chunks will outweigh the speed benefit of not rendering parts. Frustum/occlusion culling are obviously very useful but having 100k draw calls just to have chunks so small as to not have much overdraw or offscreen is going to hurt more than the gain. With my voxel engine I was running variable size chunks based on LOD/distance and it will depend too much on what you’re doing for me to give you an accurate balance point.

There’s some things coming in v3 that might help with what you’re doing, especially the threading parts, and LOD. I have no real estimate on a release date on that yet, it’s coming along, but slowly due to work/school.

The UpdateFrequency is used internally to control how the rendering is setup. I’m going to slightly oversimplify this but, basically UE4 has a static and dynamic draw path. The static path is generally faster for multiple reasons but it can only be configured when the scene proxy is created, which right now requires a resync of all the the mesh data to the GPU. The dynamic path doesn’t require recreating the scene proxy, and instead updates only what’s necessary so the updates are faster but the draw speed is a little bit slower. Now, at the GPU memory buffer level, the RMC uses 2 possible configurations, static and dynamic (this doesn’t relate to UE4’s 2 rendering paths). static buffers are meant to be set and used over and over, whereas dynamic can be set multiple times. That UpdateFrequency flag controls which combination the RMC uses for that section…

UpdateFrequency::Frequent = Dynamic Render Path + Dynamic Buffers (Use this if you update super frequently, like every frame)
UpdateFrequency::Average = Dynamic Render Path + Static Buffers (This is the happy middleground if you need to update some sections sometimes but not all of them at once)
UpdateFrequency::Infrequent = Static Render Path + Static Buffers (This is only for sections that update very infrequently as it forces a total resync of the entire RMC, but provides the fastest rendering path)

In RMCv3 this won’t be exactly the same as the mesh data is stored separately and so won’t be resynced on recreate of the scene proxy which means it will more frequently use the static draw path (probably for both Infrequent and Average).

Right now the RMC’s normal/tangent calculation isn’t really faster than the PMC’s. That will change in v3. I might try to push a update soon to fix a few small things like this in the interim till v3 is done though.

I ended up rolling code to “manually” calculate the tangents and normals, the PMC’s code is dreadfully slow not even suitable for editor time let alone runtime. if you’re are going to push an update to v2 (which I would really appreaciate) and I am the only one affected by the CalculateMeshTangents problem then I would say not to brother fixing it for me cause I’m no longer using that functionand V3 is coming anyways. However…there is something else that bothers me with V2…I’ve looked through your code and examples to find the cause and I found a few hints. When selecting (in editor) an actor with a RMC the “selected outline” (that little orange line that outlines the selected object) actually fills the entire component/mesh instead of just outlining. To make matters worse, if the update frequency is set to “Infrequent” the outline/fill will Never disappear! not even by unselecting the object. when the update frequency is set to “Average” the outline/fill disappears when the actor is deselected…but the problem is the outline is not a outline but rather it fills the entire mesh changing it’s color and making debugging and level design a lot harder as it drastically changes the color of the mesh. Where’s a picture of the problem:

I know your time is limited and if you can only push a fix or two I would rather you fix the outline problem than the tangents one :slight_smile:

P.S - Please note they bug out more often when freshly dragged in from the content browser (100%) but they can also get stuck after being saved in a level, it’s just more rare. But in all cases I would rather have an outline instead of that annoying “fill” effect.

I’m having trouble getting RMC to work in UE4 4.15. Is it possible to get the plugin with the project file? There’s no way for me to rebuild the plugin (fixing any dll issues) because it isn’t included in the zip file.

Hello,i’m trying add collision to the mesh.I used function RuntimeMesh->AddCollisionConvexMesh(Positions);.
However,The collision body is not exactly the same as the mesh shape.As the picture shows,when i use TArray Positions create the wave-shaped mesh,the collision body seems like a big cuboid.And when i create a mesh that middle part raised,the collision body seems like a Round table body。
I added fluid to see collision body shape.the red line draws the collision body shape i am looking for.


so the problem is,when i use l lot of point to create a complex collision body,it will be a convex hull instead of the mesh shape.
How should i solve it?
please help me!

Since updating to 4.15 I’m getting an odd exception in PrimitiveSceneProxy.cpp. My C++ code is identical between my 4.14 and 4.15 projects. I compile and run both projects, the 4.14 version runs fine, but the 4.15 version triggers a breakpoint with an exception.

The exception occurs on line 599 of PrimitiveSceneProxy.cpp, which is an engine file. Here is the actual code from that file. Line 599 is at the ensureMsgf call.


void FPrimitiveSceneProxy::VerifyUsedMaterial(const FMaterialRenderProxy* MaterialRenderProxy) const
{
	// Only verify GetUsedMaterials if uncooked and we can compile shaders, because FShaderCompilingManager::PropagateMaterialChangesToPrimitives is what needs GetUsedMaterials to be accurate
#if WITH_EDITOR

	if (bVerifyUsedMaterials)
	{
		const UMaterialInterface* MaterialInterface = MaterialRenderProxy->GetMaterialInterface();

		if (MaterialInterface 
			&& !UsedMaterialsForVerification.Contains(MaterialInterface)
			&& MaterialInterface != UMaterial::GetDefaultMaterial(MD_Surface))
		{
			// Shader compiling uses GetUsedMaterials to detect which components need their scene proxy recreated, so we can only render with materials present in that list
			ensureMsgf(false, TEXT("PrimitiveComponent tried to render with Material %s, which was not present in the component's GetUsedMaterials results
    Owner: %s, Resource: %s"), *MaterialInterface->GetName(), *GetOwnerName().ToString(), *GetResourceName().ToString());
		}
	}
	
#endif
}

Here is the call stack. You can see it seems to be originating in RuntimeMeshComponent from FRuntimeMeshSceneProxy::GetDynamicMeshElements(…) at line 320.


UE4Editor-Engine.dll!FPrimitiveSceneProxy::VerifyUsedMaterial(const FMaterialRenderProxy * MaterialRenderProxy) Line 599
UE4Editor-Engine.dll!FMeshElementCollector::AddMesh(int ViewIndex, FMeshBatch & MeshBatch) Line 233
UE4Editor-RuntimeMeshComponent.dll!FRuntimeMeshSceneProxy::GetDynamicMeshElements(const TArray<FSceneView const *,FDefaultAllocator> & Views, const FSceneViewFamily & ViewFamily, unsigned int VisibilityMap, FMeshElementCollector & Collector) Line 320
UE4Editor-Renderer.dll!FSceneRenderer::GatherDynamicMeshElements(TArray<FViewInfo,FDefaultAllocator> & InViews, const FScene * InScene, const FSceneViewFamily & InViewFamily, const TArray<unsigned char,SceneRenderingAllocator> & HasDynamicMeshElementsMasks, const TArray<unsigned char,SceneRenderingAllocator> & HasDynamicEditorMeshElementsMasks, FMeshElementCollector & Collector) Line 1958
UE4Editor-Renderer.dll!FSceneRenderer::ComputeViewVisibility(FRHICommandListImmediate & RHICmdList) Line 2617
UE4Editor-Renderer.dll!FDeferredShadingSceneRenderer::InitViews(FRHICommandListImmediate & RHICmdList, FILCUpdatePrimTaskData & ILCTaskData, TArray<TRefCountPtr<FGraphEvent>,TInlineAllocator<4,FDefaultAllocator> > & SortEvents) Line 2860
UE4Editor-Renderer.dll!FDeferredShadingSceneRenderer::Render(FRHICommandListImmediate & RHICmdList) Line 589
UE4Editor-Renderer.dll!RenderViewFamily_RenderThread(FRHICommandListImmediate & RHICmdList, FSceneRenderer * SceneRenderer) Line 1728
[Inline Frame] UE4Editor-Renderer.dll!FRendererModule::BeginRenderingViewFamily::__l21::EURCMacro_FDrawSceneCommand::DoTask(ENamedThreads::Type) Line 1896
UE4Editor-Renderer.dll!TGraphTask<`FRendererModule::BeginRenderingViewFamily'::`21'::EURCMacro_FDrawSceneCommand>::ExecuteTask(TArray<FBaseGraphTask *,FDefaultAllocator> & NewTasks, ENamedThreads::Type CurrentThread) Line 883
[Inline Frame] UE4Editor-Core.dll!FBaseGraphTask::Execute(TArray<FBaseGraphTask *,FDefaultAllocator> & CurrentThread, ENamedThreads::Type) Line 488
UE4Editor-Core.dll!FNamedTaskThread::ProcessTasksNamedThread(int QueueIndex, bool bAllowStall) Line 954	
UE4Editor-Core.dll!FNamedTaskThread::ProcessTasksUntilQuit(int QueueIndex) Line 701
UE4Editor-RenderCore.dll!RenderingThreadMain(FEvent * TaskGraphBoundSyncEvent) Line 325
UE4Editor-RenderCore.dll!FRenderingThread::Run() Line 476	
UE4Editor-Core.dll!FRunnableThreadWin::Run() Line 76
UE4Editor-Core.dll!FRunnableThreadWin::GuardedRun() Line 25

This exception comes up when I try to create a runtime mesh section for the first time. I have a valid material assigned to the mesh section. If I close the breakpoint exception dialog in Visual Studio and click Continue, then it continues running as per normal and the runtime mesh works fine from that point forward, until I close and run again, then I hit it again. So every time I run my project, I hit the breakpoint, close the exception dialog, then click Continue to keep going. Any idea what might be causing this @?

Hi ,

I’m Going To Build My Own Theme Park With Blackjack and Hookers (c), but I need your amazing plugin for that! With best colliders on mobile platforms/HTML5, with great skeletal mesh creation possibility, with a lot of other unbelieveable stuff :slight_smile: Please keep this (membership in my Theme Park?) in mind next time when you open up your project!

(Hmm, almost 's style, it seems that I read his posts a lot :slight_smile:

Anyway man, you are the best, please keep the work, I wish you a lot of energy and positive ideas!
Will wait for next version! cheers!

Hey . In out project it can happen that really small actors are created, talking about 0.0001cm³. This causes issues, as it seems, with collision cooking for the RMC. The following error is dispatched.

PHYSX: (D:\Build++UE4+Release-4.15+PhysX_Compile\Sync\Engine\Source\ThirdParty\PhysX\PhysX_3.4\Source\PhysXCooking\src\mesh\TriangleMeshBuilder.cpp 1080) eINTERNAL_ERROR : cleaning the mesh failed

You now if this is something that could get fixed? Or a way for us to get a notification about that issue and provide a self made collision shape in that case?