Announcement

Collapse
No announcement yet.

Runtime Mesh Component

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • replied
    I've started playing with RMC today, have been backporting an example into C++, and I'm having some trouble actually generating something visible. As far as I can tell, everything I'm passing into CreateMeshSection is valid, and it isn't dropping out early, but I never see anything in the engine.

    Here's a snippet - am I missing something obvious / vital?
    Code:
    		//URuntimeMeshComponent* NewTile = CreateDefaultSubobject<URuntimeMeshComponent>(TEXT("TerrainTile"));
    		URuntimeMeshComponent* NewTile = NewObject<URuntimeMeshComponent>();
    		NewTile->SetupAttachment(RootComponent);
    
    		//NewTile->bUseComplexAsSimpleCollision = true;
    		//NewTile->bShouldSerializeMeshData = true;
    
    		NewTile->SetRelativeLocation(RelativeTileLocations[TilesToSpawn - 1]);
    
    		TArray<FVector> Vertices;
    
    		for (int i = 0; i < TilesPerAxis; i++)
    			for (int j = 0; j < TilesPerAxis; j++)
    			{
    				FVector NewVert = FVector(0, 0, 0);
    
    				NewVert.X = j * (TileSize / TilesPerAxis);
    				NewVert.Y = i * (TileSize / TilesPerAxis);
    
    				Vertices.Add(NewVert);
    			}
    
    		int32 NumRowsColumns = FMath::TruncToInt(FMath::Sqrt(Vertices.Num()));
    
    		TArray<FVector2D> UVs;
    
    		//££ Todo: Duplicate UVs into Lightmap UVs.
    		TArray<FVector2D> LightmapUVs;
    
    		//Calculate UVs
    		for(int i = 0; i < NumRowsColumns; i++)
    			for (int j = 0; j < NumRowsColumns; j++)
    			{
    				FVector2D Coords = FVector2D(j * TileSize, i * TileSize);
    				UVs.Add(Coords);
    			}
    
    		//Generate Tris
    		TArray<int32> Triangles;
    
    		UKismetProceduralMeshLibrary::CreateGridMeshTriangles(NumRowsColumns, NumRowsColumns, true, Triangles);
    
    		//Calc Tangents
    		TArray<FVector> Normals;
    		TArray<FProcMeshTangent> KPTangents;
    
    		UKismetProceduralMeshLibrary::CalculateTangentsForMesh(Vertices, Triangles, UVs, Normals, KPTangents);
    
    		TArray<FRuntimeMeshTangent> Tangents;
    
    		for (FProcMeshTangent Tangent : KPTangents)
    		{
    			FRuntimeMeshTangent NewTangent = FRuntimeMeshTangent(Tangent.TangentX, false);
    
    			Tangents.Add(NewTangent);
    		}
    
    		//££ build black/white colour array.
    		TArray<FLinearColor> VertexColours;
    
    
    		//void URuntimeMeshComponent::CreateMeshSection_Blueprint(int32, const TArray<FVector, FDefaultAllocator> &, const TArray<ElementType, FDefaultAllocator> &, const TArray<FVector, FDefaultAllocator> &, const TArray<FRuntimeMeshTangent, FDefaultAllocator> &, const TArray<FVector2D, FDefaultAllocator> &, const TArray<FVector2D, FDefaultAllocator> &, const TArray<FLinearColor, FDefaultAllocator> &, bool, EUpdateFrequency)': cannot convert argument 7 from 'int' to 'const TArray<FVector2D, FDefaultAllocator> &'
    		NewTile->CreateMeshSection_Blueprint(0, Vertices, Triangles, Normals, Tangents, UVs, LightmapUVs, VertexColours, true, EUpdateFrequency::Frequent);
    
    		NewTile->SetMaterial(0, Material);
    Last edited by ambershee; 10-18-2016, 01:15 PM.

    Leave a comment:


  • replied
    Ahh ok, thanks Koderz! I will look into it some more and see if I can come up with a new method of achieving what I am looking for.

    Leave a comment:


  • replied
    Originally posted by rizzlewizzle View Post
    Hi,

    I don't know if this is possible but I have been trying to set the animated mesh to use a custom material that varies in colour with world position (varying from blue to red in the z-direction). The material works with other meshes but not the RMC. Is there any way to get this to work with the RMC? I'm pretty new to UE4 so don't fully understand how the RMC works. Images attached.
    If I'm not mistaken, the WorldAlignedBlend works by blending on the normal of the mesh, not the z position of the vertex like what it sounds like you're wanting. The RMC will work fine with either case, but that plane doesn't have its normals computed as there's 600k vertices IIRC and the usual normal/tangent calculator is entirely too slow to calculate that in real-time. With something like the cubes in that scene it should work correctly.

    Leave a comment:


  • replied
    Originally posted by wilberolive View Post
    @Koderz I'm not sure if I've found a bug or if this is just the way it is supposed to work.

    For some reason CreateMeshSection() was failing to create a mesh, even though all the inputs were valid (I stepped though my C++ and inspected them). After calling it, the RMC was still showing as having no mesh sections internally. After hours of scratching my head and fiddling I eventually figured out that it has to do with the way you create the FBox bounding box. It turns out my FBox was not valid.

    Here is the code I was using.

    Code:
    FBox Bounds;
    Bounds.Min.Set(Start.X, Start.Y, 0.0f);
    Bounds.Max.Set(End.X, End.Y, Z);
    Looks perfectly fine. However, the problem is that the internal FBox IsValid flag is not being set since I'm setting the Min/Max directly rather than going through the FBox constructor. So I changed the code to this.

    Code:
    FBox Bounds = FBox(FVector(Start.X, Start.Y, 0.0f), FVector(End.X, End.Y, Z));
    Now the IsValid flag is being set and CreateMeshSection() produces a mesh section. Great!

    So my question... Is this intended? Seems odd that the mesh section isn't created just because the IsValid flag was not set. It means you have to always create the FBox using one of its constructors. You can't manually create an FBox.

    This is indeed intended behavior. If the box is not valid, it can't be used for culling and such so it will bail when it sees an invalid box. In editor it should log an error message, in a packaged game it will outright crash you. Those are picked up by the validation logic which can be found at the top of RuntimeMeshComponent.h

    As for creating the box, there's a couple ways to do it. First is like you just showed...

    Code:
    FBox Bounds = FBox(FVector(Start.X, Start.Y, 0.0f), FVector(End.X, End.Y, Z));
    The next would be like you did originally with 1 addition.

    Code:
    FBox Bounds;
    Bounds.Min.Set(Start.X, Start.Y, 0.0f);
    Bounds.Max.Set(End.X, End.Y, Z);
    Bounds.IsValid = true;
    The third way is useful when you just need to sum up the points and don't know directly which is to do something along the lines of...

    Code:
    FBox Bounds(0);
    Bounds += Point;
    where 'Point' is a FVector point that the box needs to adjust to fit.

    I hope that helped!

    Leave a comment:


  • replied
    Hi,

    I don't know if this is possible but I have been trying to set the animated mesh to use a custom material that varies in colour with world position (varying from blue to red in the z-direction). The material works with other meshes but not the RMC. Is there any way to get this to work with the RMC? I'm pretty new to UE4 so don't fully understand how the RMC works. Images attached.

    Thanks in advance!

    RMC(with edited height variable):
    Click image for larger version

Name:	RMCwithMaterial - Copy.PNG
Views:	1
Size:	478.0 KB
ID:	1116670
    Custom material:
    Click image for larger version

Name:	customMaterial.PNG
Views:	1
Size:	347.1 KB
ID:	1116671
    Attached Files

    Leave a comment:


  • replied
    [MENTION=141752]Koderz[/MENTION] I'm not sure if I've found a bug or if this is just the way it is supposed to work.

    For some reason CreateMeshSection() was failing to create a mesh, even though all the inputs were valid (I stepped though my C++ and inspected them). After calling it, the RMC was still showing as having no mesh sections internally. After hours of scratching my head and fiddling I eventually figured out that it has to do with the way you create the FBox bounding box. It turns out my FBox was not valid.

    Here is the code I was using.

    Code:
    FBox Bounds;
    Bounds.Min.Set(Start.X, Start.Y, 0.0f);
    Bounds.Max.Set(End.X, End.Y, Z);
    Looks perfectly fine. However, the problem is that the internal FBox IsValid flag is not being set since I'm setting the Min/Max directly rather than going through the FBox constructor. So I changed the code to this.

    Code:
    FBox Bounds = FBox(FVector(Start.X, Start.Y, 0.0f), FVector(End.X, End.Y, Z));
    Now the IsValid flag is being set and CreateMeshSection() produces a mesh section. Great!

    So my question... Is this intended? Seems odd that the mesh section isn't created just because the IsValid flag was not set. It means you have to always create the FBox using one of its constructors. You can't manually create an FBox.

    Leave a comment:


  • replied
    Hi

    I tried to compile this plugin for PS4 and Linux and it seems like your code has some issues with clang. We implemented some workarounds but you might want to look into it

    Leave a comment:


  • replied
    Originally posted by Koderz View Post
    I'll let you know when the normal/tangent work is done and pushed to github! (It's the next thing being pushed once I find one last bug) The smc->rmc conversions are done on github.
    Thanks for the update. Super excited about the work you are doing. I've only been using the v1.2 plugin at the moment as I'm not really familiar with the process of compiling and installing a plugin from GitHub.

    Leave a comment:


  • replied
    First off. Sorry for the delay everyone, I am still working on v2 very slowly, just haven't had much time due to other things going on. I hope to get everything but collision fully finalized this week, not sure about collision as it requires me having more time to work in one consecutive shot then I've had recently.

    [MENTION=28104]wilberolive[/MENTION] I'll let you know when the normal/tangent work is done and pushed to github! (It's the next thing being pushed once I find one last bug) The smc->rmc conversions are done on github.
    [MENTION=19211]Thumper[/MENTION]...

    Wilber is on the right track, so I'll break down the major areas that affect what it sounds like you're trying to do...

    First up the difference between BeginMeshSectionUpdate/EndMeshSectionUpdate and UpdateMeshSection is that the first allows you to access and edit the RMC's stored version which removes one potentially costly copy operation and also allows you to skip storing it yourself as well.
    The problem is for both of these paths the next part is identical. When you commit an update either view EndMeshSectionUpdate or implicitly in UpdateMeshSection it copies the entire section and passes is to the render thread, which then locks a GPU buffer and copies that data to the GPU. This means that there's 2 types of impact you'll get from this. first is the obvious time to copy those 2 times, and the second is the time required to lock the GPU buffer. So many tiny buffers updating frequently can be slow dominated by lock time, and giant buffers are slow due to copy time.

    The other thing that's probably the far bigger factor is collision, and I'd be interested to see what the performance difference is for you with collision off. Unfortunately the PMC and RMC (Currently) have a rather brute force setup for collision. For PhysX (The underlying physics engine) to work with things like static meshes it must first 'cook' them which does a list of things to improve detection performance. The problem is this is slow (like 20+ms slow in some cases) and will very quickly destroy your fps. This is the big thing I'm working on for v2, and hope to have a testable version here pretty quick.
    The quick breakdown on the collision issue with the PMC/RMC is when you update any 1 section, it will cause that entire PMC/RMC to batch all the sections back together into one giant mesh and send it to the PhysX cooker on the game thread thereby halting your execuation while it cooks.

    What you can do for now is like wilber said, divide up the mesh, and if you're using collision separate them between multiple RMC's to reduce the collision impact. This will increase draw calls, but it should reduce update times substantially.

    Leave a comment:


  • replied
    Originally posted by Thumper View Post
    When I move those polygons I see my frame rate dip down (below 90 FPS because I'm in VR).
    Now I could be off base with this as I'm no expert on the subject. However, I believe that the entire list of vertices needs to be pushed to VRAM regardless of how many you actually change. So it makes sense that a list of ~700k vertices will take more time to send across than a ~200k list. At least my own testing verified this for me, so that's the assumption I'm rolling with for now until corrected.

    So what I did to get around the problem was to break my world up into multiple RMC's. I used a quad-tree approach to break the world up into even square chunks. Vertices are then assigned to a chunk based on their initial world location. So instead of one RMC with ~700k vertices, you end up with say 16 RMC's with ~40k vertices each. Then when you update a triangle, you are only updating that one chunk. I can now update multiple chunks every frame with no noticeable hit on frame time.

    Bare in mind that this approach results in 16 draw calls as opposed to 1 draw call. That was an acceptable trade-off for me as I update the chunks frequently. You would need to decide what is acceptable to you based on how often you update.

    Oh and one more thing... don't try any of this in BP. Stick to C++ for this kind of stuff. Not just for the performance of it, but because BP would get out of control with the math and what not going on.
    Last edited by wilberolive; 09-18-2016, 09:56 PM.

    Leave a comment:


  • replied
    When you update faces in place does it really matter how large the container is (within reason)? For instance I have a container that has 737,280 triangle faces in it. Now I want to move 13 polygons to a new location. My polygons have collision on them. When I move those polygons I see my frame rate dip down (below 90 FPS because I'm in VR). However if I do the same thing on the next subdivision level lower (184,320 triangles), my framerate is fine. It's still only modifying 13 triangles, and the matter in which those triangles are discovered is identical. There's a visible stutter in the CV1 when I use the higher subdivision container. Any ideas how I can improve this?

    Leave a comment:


  • replied
    I recently migrated my project to VR on the CV1. I'm noticing a huge delay when I use BeginMeshSectionPositionUpdate vs SetMeshSectionVisible. In the first, I fetch a triangle from a raycast and then grab the local neighbors which are precalculated creating a list of 13 triangles, which I multiply their Z value to move them down and out of the way. This method causes me to cross over the 90 FPS requirement. So instead I use the same method of fetching neighbors only this time I grab the lower subdivision levels and put the grouped lower subdivision levels on their own section on the RMT. So when my raycast hits and fetches the neighbors (sections neighbors) I turn that section off. This cause no delay and is the same number of triangle loops where instead of neighbors per face I'm grabbing per subdivision neighbors and turning the groups of triangles of. Technically its' more triangles because each section is many polygons whereas the original method was only 13 triangles.

    Leave a comment:


  • replied
    Originally posted by Koderz View Post
    V1.2 the current marketplace version is what will be updated until v2 is done, which I'm working on completing asap but honestly can't give a definitive date, just hopefully within a week.
    Hey, just checking in to see if v2 is any closer yet? Just curious as I've paused my work with RMC for the moment while I wait. I'm really interested in exploring the SMC -> RMC and Normal/Tangent calculations as these two features alone can save huge amounts of time in building meshes for RMC. I'm also hoping that v2 will solve the shadowing and nav mesh issues I raised earlier. Sorry, not trying to be pushy, just really excited for where this can go and eager to get my hands on it.

    Leave a comment:


  • replied
    For all of you wanting to update to 4.13 using the marketplace installed version. It is coming, but Epic is having a slight technical issue that will take a little time to work through. If you want to go ahead and move to 4.13 you can download the marketplace (or even a newer version) from github at the link below and install it either to your engine plugins folder or your project plugins folder. Instructions for this can be found on the github wiki.

    https://github.com/Koderz/UE4RuntimeMeshComponent

    Leave a comment:


  • replied
    Originally posted by Koderz View Post
    Ok. A few weeks back I said that I hoped to have v2 out a few weeks ago if all went to plan. Obviously it didn't unfortunately so here's where it stands.

    First up the marketplace doesn't support 4.13 yet, I just sent a message to Epic to ask them to update it as it should be updated soon. V1.2 the current marketplace version is what will be updated until v2 is done, which I'm working on completing asap but honestly can't give a definitive date, just hopefully within a week.

    Next, what is currently done and on github for v2.
    • RuntimeMesh <-> StaticMesh conversions. This should work in both directions in editor with all engine versions 4.10+, and it also supports RMC -> SMC at runtime on engine 4.13+
    • The new vertex struct is done and up, with that much better serialization support will be soon.
    • Mesh builder, this is used internally to support the utilities and you can use it as well. It still needs some work, and would welcome input as to what would work best.



    What's coming to github very soon (hopefully today/tomorrow)
    • Normal/Tangent calculation
    • Tessellation
    • A couple of bug fixes


    The big remaining part is collision for v2.
    The expectation here, assuming everything works as intended is the RMC will gain 3 modes of operation when it comes to collision. The first is the normal cook on commit which will halt the game thread and will be inserted on the following frame. This is the way the PMC and the RMC currently operate. The second is an internal thread pool. When you commit an update to a section it will queue a build on a shared threadpool and will update collision whenever the cook finishes. This might be on the next frame, it might not, but it won't halt the game thread to cook. The third is an option you have to supply the RMC with cooked collision data, and a utility you can call from your own threads to cook a mesh. This means you have complete control of what thread cooks it, and when it gets inserted. You can even save the cooked result and load it back later.

    V2 of the RMC will still support engine versions 4.10+ and certain features like the extended collision support and SMC -> RMC runtime conversion will only enable themselves and function when they're used with a supported engine version. In the case of SMC->RMC runtime conversion that is engine version 4.13 and the collision is TBD as that will require engine changes to hopefully work through the PR process.

    If you have questions/comments, feel free to message me on the Unreal Slackers new Discord.

    Github: https://github.com/Koderz/UE4RuntimeMeshComponent
    i just think there's a queue for updates and new marketplace content. plus i also think the launcher needs to handle a lot of content and servers need updating to accept that.

    Leave a comment:

Working...
X