当前位置:网站首页>Mesh merging under ue4/ue5 runtime
Mesh merging under ue4/ue5 runtime
2022-07-07 15:43:00 【WhiteTian】
Original article , Reprint please indicate the source .
StaticMesh The merger of
Preface
Engine version :4.27.2
The premise of the merger : stay UE4.26.2 after , Runtime components are allowed UStaticmesh. The previous method only supports importing under the editor ,
After importing, it will be converted to UStaticMesh Of RenderData Rendering ;
Why merge :
The source of demand is software. We want to use UE4.27.2 Of runtime Under the udatasmith Import function ,
But because datasmith The original intention of our design is to split the model as small as possible , The particle size is very small .
So there are udatasmith After importing, there will be tens of thousands of... In the level , Very low frame rate .
That's why there is this article Merge at run time StaticMesh.
The optimization scheme of the combined batch is as follows
In fact, there are many that can be approved together .
therefore , Here I will focus on udatasmith Import this function , Studied the scheme of joint approval ;
| programme | advantage | shortcoming |
|---|---|---|
| 1> modify datasmith Import the code of some plug-ins | Highest efficiency | Difficult to maintain |
| 2> Make your own set | The efficiency is lower than the scheme 1, Easy maintenance | Easy maintenance |
| 3> modify datasmith Export plug-ins | Not sure | Difficult to maintain |
Which scheme to use ?
programme 1 In a word , Change DataSmith Source code , I think efficiency is the best .
Why? :
Let's start with the plan 1 How to do it : One by one actor Not yet spawn,mesh Not yet build,collsion, There is no such information as material build Before , Let's filter in advance Mesh Can be merged , After that spawn MeshActor,build StaticMesh Of vertex,collision,material.
Let's talk about the plan 2 How to do it : be-all actor Already in the world spawn Come out ,StaticMesh Of vertex,collision,material This information has been build Okay . Then filter what is good Mesh Can be merged , After that spawn MeshActor,build StaticMesh Of vertex,collision,material.
The scheme is implemented temporarily 2
In contrast , programme 1 It's better than the plan 2 Efficient . But the plan 1 It's more troublesome to change , And I don't think it's easy to maintain . After watching it all day , I realized the scheme first 2.
Video effects :Merge Then the frame rate and DC Significantly improve Jump Watch
UE4/UE5 Runtime Lower merger Mesh
Class diagram

Editor With the implementation of the
Reference resources MergeActor Tool
Use the... Under the editor MergeActorTool The function of the tool , The merging logic will soon be implemented in the editor .Standlone You can also merge .
But it should be noted that this can only be used under the editor , Take a break when you pack .
The specific code of merging under the editor is as follows , As a reference :
// Merge method under editor
void UMyBlueprintFunctionLibrary::MergeMy(const TArray<UPrimitiveComponent*>& ComponentsToMerge, UWorld* World,
const FMeshMergingSettings& InSettings, UMaterialInterface* InBaseMaterial,
UPackage* InOuter, const FString& InBasePackageName,
TArray<UObject*>& OutAssetsToSync, FVector& OutMergedActorLocation,
const float ScreenSize, bool bSilent /*= false*/, FString AppendName)
{
const IMeshMergeUtilities& MeshUtilities = FModuleManager::Get().
LoadModuleChecked<IMeshMergeModule>("MeshMergeUtilities").GetUtilities();
MeshUtilities.MergeComponentsToStaticMeshWithName(ComponentsToMerge, GWorld, InSettings, InBaseMaterial, InOuter, InBasePackageName,
OutAssetsToSync, OutMergedActorLocation, ScreenSize, bSilent, AppendName);
}
// Merge specific logic , Put the same material Mesh Pass it in to complete the merger .
TArray<UObject*> OutAssetsToSync;
FVector OutMergedActorLocation;
const float ScreenAreaSize = TNumericLimits<float>::Max();
FMeshMergingSettings setting;
setting.bMergePhysicsData = 1;
MergeMy(mergedata.Value, GWorld,
setting, nullptr, GetTransientPackage(), FString(),
OutAssetsToSync, OutMergedActorLocation,
ScreenAreaSize, true, mergedata.Key);
UStaticMesh* UtilitiesMergedMesh = nullptr;
if (!OutAssetsToSync.FindItemByClass(&UtilitiesMergedMesh))
{
// Error, TEXT("MergeStaticMeshActors failed. No mesh was created.
continue;
}
for (auto obj : OutAssetsToSync)
{
auto umesh = Cast<UStaticMesh>(obj);
if (!umesh)
continue;
/*auto mat0 = umesh->GetMaterial(0); if (!UKismetSystemLibrary::IsValid(mat0)) continue;*/
OutMergedActorLocation+=FVector(0,0,500);
auto MergedActor = GWorld->SpawnActor<AStaticMeshActor>(AStaticMeshActor::StaticClass(), OutMergedActorLocation, FRotator(0, 0, 0));
if (MergedActor)
{
MergedActor->SetMobility(EComponentMobility::Movable);
if (!MergedActor->GetStaticMeshComponent())
continue;
MergedActor->GetStaticMeshComponent()->SetStaticMesh(umesh);
if (mergedata.Value.Num() > 0)
{
UStaticMeshComponent* pSTM = Cast<UStaticMeshComponent>(mergedata.Value[0]);
if (pSTM)
{
//umesh->SetStaticMaterials(pSTM->GetStaticMesh()->GetStaticMaterials());
}
}
GWorld->UpdateCullDistanceVolumes(MergedActor, MergedActor->GetStaticMeshComponent());
MergedActor->AttachToActor(RootActor, FAttachmentTransformRules::KeepWorldTransform);
#if WITH_EDITOR
MergedActor->SetActorLabel(UKismetSystemLibrary::GetDisplayName(umesh));
#endif // endif
}
// Delete the replaced RootActor
for (auto willremovecomp : mergedata.Value)
{
if(!IsValid(DeleteActorArray[willremovecomp]))
continue;
if(!DeleteActorArray[willremovecomp]->IsValidLowLevel())
continue;
TArray<UActorComponent*> OutComponent;
OutComponent = DeleteActorArray[willremovecomp]->K2_GetComponentsByClass(UStaticMeshComponent::StaticClass());
if (OutComponent.Num() < 2)
{
GWorld->DestroyActor(DeleteActorArray[willremovecomp]);
}
else
{
willremovecomp->DestroyComponent();
}
}
}
Runtime With the implementation of the
difficulty 1,StaticMesh Of RenderData turn FMeshDescription
In fact, if you've seen this StaticMesh You should know , The code merged under the editor is used under the editor StaticMesh Unique data to merge , This is the picture below . The variables used are SourceModels
also , Under the editor StaticMesh The build will eventually call Build Method , But these are not available at runtime .
We need to use... In the new version of the engine BuildFromStaticMeshDescriptions To generate UStaticMesh.
BuildFromStaticMeshDescriptions What this method needs is FMeshDescription,FMeshDescription After importing in the editor, there will be , But at runtime UStaticMesh Of SourceModels Does not exist. , What do I do ?
We need to push back , The final rendered data exists UStaticMesh Of RenderData in , So we start from RenderData It turns the data into FMeshDescription Just array .
In turn, merge each one that can be merged Mesh The data from RenderData convert to FMeshDescription, Then put these
FMeshDescription Add once , Give it to UStaticMesh Of BuildFromStaticMeshDescriptions Pass it in and it's done ( Note the size of the data here ,UE Serialization of cannot exceed 2G, But fortunately, we wrote this by ourselves , And then splicing FMeshDescription Let's just control the memory when we need it , This is also related to the speed of merger )
To sum up, the specific steps are :
1>RenderData turn FMeshDescription
2> Splice all FMeshDescription
3> call BuildFromStaticMeshDescriptions
difficulty 2,StaticMesh Build complex collisions
To build complex collisions , So call
UBodySetup->CreatePhysicsMeshes(), If you follow carefully , When you go in, you'll find , stay Runtime Next ,build Collision will call ProcessFormatData_PhysX perhaps ProcessFormatData_Chaos, But the preconditions must be met IsRuntime The judgment of the .
The reason I found this is , After the merger , I'm creating UStaticMesh Objects are written in a common way ,NewObect(xxxxxxx), It turns out that IsRuntime My judgment there has always been false.
if (IsRuntime(this))
{
#if WITH_PHYSX && PHYSICS_INTERFACE_PHYSX
bClearMeshes = !RuntimeCookPhysics_PhysX();
#elif WITH_CHAOS
bClearMeshes = !RuntimeCookPhysics_Chaos();
#endif
}
void UBodySetup::CreatePhysicsMeshes()
{
TRACE_CPUPROFILER_EVENT_SCOPE(UBodySetup::CreatePhysicsMeshes);
SCOPE_CYCLE_COUNTER(STAT_CreatePhysicsMeshes);
// Create meshes from cooked data if not already done
if(bCreatedPhysicsMeshes)
{
return;
}
// If we don't have any convex/trimesh data we can skip this whole function
if (bNeverNeedsCookedCollisionData)
{
return;
}
bool bClearMeshes = true;
// Find or create cooked physics data
static FName PhysicsFormatName(FPlatformProperties::GetPhysicsFormat());
FByteBulkData* FormatData = GetCookedData(PhysicsFormatName);
// On dedicated servers we may be cooking generic data and sharing it
if (FormatData == nullptr && IsRunningDedicatedServer())
{
FormatData = GetCookedData(FGenericPlatformProperties::GetPhysicsFormat());
}
if (FormatData)
{
#if WITH_PHYSX && PHYSICS_INTERFACE_PHYSX
bClearMeshes = !ProcessFormatData_PhysX(FormatData);
#elif WITH_CHAOS
bClearMeshes = !ProcessFormatData_Chaos(FormatData);
#endif
}
else
{
if (IsRuntime(this))// This place is in Runtime Next, if you use UStaticMesh Words , It's impossible to pass .
{
#if WITH_PHYSX && PHYSICS_INTERFACE_PHYSX
bClearMeshes = !RuntimeCookPhysics_PhysX();
#elif WITH_CHAOS
bClearMeshes = !RuntimeCookPhysics_Chaos();
#endif
}
}
// fix up invalid transform to use identity
// this can be here because BodySetup isn't blueprintable
if ( GetLinkerUE4Version() < VER_UE4_FIXUP_BODYSETUP_INVALID_CONVEX_TRANSFORM )
{
for (int32 i=0; i<AggGeom.ConvexElems.Num(); ++i)
{
if ( AggGeom.ConvexElems[i].GetTransform().IsValid() == false )
{
AggGeom.ConvexElems[i].SetTransform(FTransform::Identity);
}
}
}
#if WITH_CHAOS
// For drawing of convex elements we require an index buffer, previously we could
// get this from a PxConvexMesh but Chaos doesn't maintain that data. Instead now
// it is a part of the element rather than the physics geometry, if we load in an
// element without that data present, generate a convex hull from the convex vert
// data and extract the index data from there.
for(FKConvexElem& Convex : AggGeom.ConvexElems)
{
Convex.ComputeChaosConvexIndices();
}
#endif
if(bClearMeshes)
{
ClearPhysicsMeshes();
}
bCreatedPhysicsMeshes = true;
}
After looking at the code , Follow code , I found a solution .
1> First of all, you need to UStaticMesh Derive a class ;
2> And this kind of bAllowCPUAccess It has to be for true;
3> And reload GetWorld();
Then I'm adding one SetWorld Method ;
The specific code of this class is as follows :
/* * from UStaticMesh Derived classes , Allow collision meshes to be cooked at runtime * Do that ,bAllowCPUAccess It has to be for true, And the way GetWorld() A valid... Must be returned world * Otherwise, in the Cook There was a IsRuntime() My judgment is always false */
UCLASS()
class EASYKITRUNTIMEMERGEMESH_API UEKRMM_RuntimeMesh : public UStaticMesh
{
GENERATED_BODY()
public:
UEKRMM_RuntimeMesh()
: World(nullptr)
{
// Set up bAllowCPUAccess by true, Allows you to copy rendered data triangles into the collision mesh
bAllowCPUAccess = true;
}
// UObject Cover
// Overrides allow cooking to collide with the mesh , Simple and complex , From the static grid at run time
virtual UWorld* GetWorld() const override {
return World ? World : UStaticMesh::GetWorld(); }
// end UObject Cover
// Use an effective world , Allow collision meshes , Simple and complex , From the static grid at run time
void SetWorld(UWorld* InWorld) {
World = InWorld; }
private:
UWorld* World;
};
It's easy to use , as follows , And then I'll call UBodySetup->CreatePhysicsMeshes() Just OK 了 :
UEKRMM_RuntimeMesh* StaticMesh = NewObject< UEKRMM_RuntimeMesh >(GetTransientPackage(), MeshName, RF_Public | RF_Standalone);
if(!StaticMesh)
continue;
StaticMesh->InitResources();
// The world must be set
StaticMesh->SetWorld(RootActor->GetWorld());
difficulty 3,StaticMesh texture of material
Plug in encapsulation , Introduction to existing functions and subsequent plans
Features currently supported :
1> All of the same material mesh Merge together : Pass in a AActor Object as RootActor, To be able to RootActor All materials under the are the same UStaticmeshComponent Merge into a single UStaticMesh;
2> The material is correct
3> Ensure there are complex collisions
4> The coordinates are correct
5> To be added : Size calculation before merging , Block : The main purpose is to meet serialization and merge efficiency
6> To be added : Facet reduction plug-in , When merging, you can dynamically reduce faces , I'm going to get a plug-in out as well , Runtime subtraction algorithm
7> To be added :USkeletalMesh Of Merge
8> To be added : serialize
Reference article
Datasmith Runtime Official Blog
Unreal Engine 4.27 Datasmith Runtime Import
UE – StaticMesh analysis
边栏推荐
- Jacobo code coverage
- The "go to definition" in VS2010 does not respond or prompts the solution of "symbol not found"
- Streaming end, server end, player end
- What is data leakage
- STM32F103C8T6 PWM驱动舵机(SG90)
- Spin animation of Cocos performance optimization
- Monthly observation of internet medical field in May 2022
- Connecting FTP server tutorial
- Unity's ASE achieves full screen sand blowing effect
- Window环境下配置Mongodb数据库
猜你喜欢

2022全开源企业发卡网修复短网址等BUG_2022企业级多商户发卡平台源码

Getting started with webgl (1)

Getting started with webgl (2)

【数字IC验证快速入门】20、SystemVerilog学习之基本语法7(覆盖率驱动...内含实践练习)

2022 all open source enterprise card issuing network repair short website and other bugs_ 2022 enterprise level multi merchant card issuing platform source code

【数字IC验证快速入门】18、SystemVerilog学习之基本语法5(并发线程...内含实践练习)

简述keepalived工作原理

OpenGL's distinction and understanding of VAO, VBO and EBO

Spin animation of Cocos performance optimization

MySQL bit类型解析
随机推荐
./ Functions of configure, make and make install
Typescript release 4.8 beta
Briefly describe the working principle of kept
Shader Language
简述keepalived工作原理
STM32F103C8T6 PWM驱动舵机(SG90)
[quick start of Digital IC Verification] 24. AHB sramc of SystemVerilog project practice (4) (AHB continues to deepen)
[Lanzhou University] information sharing of postgraduate entrance examination and re examination
【OBS】RTMPSockBuf_ Fill, remote host closed connection.
Getting started with webgl (2)
[quick start of Digital IC Verification] 26. Ahb-sramc of SystemVerilog project practice (6) (basic points of APB protocol)
【数字IC验证快速入门】20、SystemVerilog学习之基本语法7(覆盖率驱动...内含实践练习)
全日制研究生和非全日制研究生的区别!
jacoco代码覆盖率
[quick start of Digital IC Verification] 29. Ahb-sramc (9) (ahb-sramc svtb overview) of SystemVerilog project practice
【数字IC验证快速入门】19、SystemVerilog学习之基本语法6(线程内部通信...内含实践练习)
连接ftp服务器教程
最安全的证券交易app都有哪些
webgl_ Graphic transformation (rotation, translation, zoom)
Super simple and fully automated generation super signature system (cloud Xiaoduo minclouds.com cloud service instance), free application in-house test app distribution and hosting platform, maintenan