| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308 |
- // Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
- #pragma once
- #include "Components/MeshComponent.h"
- #include "RuntimeMeshCore.h"
- #include "RuntimeMeshSection.h"
- #include "RuntimeMeshGenericVertex.h"
- #include "RuntimeMeshBuilder.h"
- #include "PhysicsEngine/ConvexElem.h"
- #include "RuntimeMeshComponent.generated.h"
- // This set of macros is only meant for argument validation as it will return out of whatever scope.
- #if WITH_EDITOR
- #define RMC_CHECKINGAME_LOGINEDITOR(Condition, Message, RetVal) \
- { if (!(Condition)) \
- { \
- Log(TEXT(Message), true); \
- return RetVal; \
- } }
- #else
- #define RMC_CHECKINGAME_LOGINEDITOR(Condition, Message, RetVal) \
- check(Condition && Message);
- #endif
- #define RMC_VALIDATE_CREATIONPARAMETERS(SectionIndex, Vertices, Triangles, RetVal) \
- RMC_CHECKINGAME_LOGINEDITOR((SectionIndex >= 0), "SectionIndex cannot be negative.", RetVal); \
- RMC_CHECKINGAME_LOGINEDITOR((Vertices.Num() > 0), "Vertices length must not be 0.", RetVal); \
- RMC_CHECKINGAME_LOGINEDITOR((Triangles.Num() > 0), "Triangles length must not be 0", RetVal);
- #define RMC_VALIDATE_CREATIONPARAMETERS_DUALBUFFER(SectionIndex, Vertices, Triangles, Positions, RetVal) \
- RMC_VALIDATE_CREATIONPARAMETERS(SectionIndex, Vertices, Triangles, RetVal) \
- RMC_CHECKINGAME_LOGINEDITOR((Positions.Num() == Vertices.Num()), "Positions must be the same length as Vertices", RetVal);
- #define RMC_VALIDATE_BOUNDINGBOX(BoundingBox, RetVal) \
- RMC_CHECKINGAME_LOGINEDITOR(BoundingBox.IsValid, "BoundingBox must be valid.", RetVal);
- #define RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, RetVal) \
- RMC_CHECKINGAME_LOGINEDITOR((SectionIndex >= 0), "SectionIndex cannot be negative.", RetVal); \
- RMC_CHECKINGAME_LOGINEDITOR((SectionIndex < MeshSections.Num() && MeshSections[SectionIndex].IsValid()), "Invalid SectionIndex.", RetVal);
- #define RMC_VALIDATE_UPDATEPARAMETERS_INTERNALSECTION(SectionIndex, RetVal) \
- RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, RetVal) \
- RMC_CHECKINGAME_LOGINEDITOR((MeshSections[SectionIndex]->bIsLegacySectionType), "Section is not of legacy type.", RetVal);
-
- #define RMC_VALIDATE_UPDATEPARAMETERS_DUALBUFFER(SectionIndex, RetVal) \
- RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, RetVal) \
- RMC_CHECKINGAME_LOGINEDITOR((MeshSections[SectionIndex]->IsDualBufferSection()), "Section is not dual buffer.", RetVal);
- /*
- * This tick function is used to drive the collision cooker. It is enabled for one frame when we need to update collision.
- * This keeps from cooking on each individual create/update section as the original PMC did
- */
- USTRUCT()
- struct RUNTIMEMESHCOMPONENT_API FRuntimeMeshComponentPrePhysicsTickFunction : public FTickFunction
- {
- GENERATED_USTRUCT_BODY()
- /* Target RMC to tick */
- class URuntimeMeshComponent* Target;
- virtual void ExecuteTick(float DeltaTime, ELevelTick TickType, ENamedThreads::Type CurrentThread,
- const FGraphEventRef& MyCompletionGraphEvent) override;
- virtual FString DiagnosticMessage() override;
- };
- template<>
- #if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION <= 15
- struct TStructOpsTypeTraits<FRuntimeMeshComponentPrePhysicsTickFunction> : public TStructOpsTypeTraitsBase
- #else
- struct TStructOpsTypeTraits<FRuntimeMeshComponentPrePhysicsTickFunction> : public TStructOpsTypeTraitsBase2<FRuntimeMeshComponentPrePhysicsTickFunction>
- #endif
- {
- enum
- {
- WithCopy = false
- };
- };
- /**
- * Component that allows you to specify custom triangle mesh geometry for rendering and collision.
- */
- UCLASS(HideCategories = (Object, LOD), Meta = (BlueprintSpawnableComponent))
- class RUNTIMEMESHCOMPONENT_API URuntimeMeshComponent : public UMeshComponent, public IInterface_CollisionDataProvider
- {
- GENERATED_BODY()
- private:
-
- /* Creates an mesh section of a specified type at the specified index. */
- template<typename SectionType>
- TSharedPtr<SectionType> CreateOrResetSection(int32 SectionIndex, bool bWantsSeparatePositionBuffer, bool bInIsLegacySectionType = false)
- {
- // Ensure sections array is long enough
- if (SectionIndex >= MeshSections.Num())
- {
- MeshSections.SetNum(SectionIndex + 1, false);
- }
- // Create new section
- TSharedPtr<SectionType> NewSection = MakeShareable(new SectionType(bWantsSeparatePositionBuffer));
- NewSection->bIsLegacySectionType = bInIsLegacySectionType;
- // Store section at index
- MeshSections[SectionIndex] = NewSection;
- return NewSection;
- }
-
- /* Creates a mesh section of an internal type meant for the generic vertex and the old PMC style API */
- TSharedPtr<FRuntimeMeshSectionInterface> CreateOrResetSectionLegacyType(int32 SectionIndex, int32 NumUVChannels);
- /* Gets the material for a section or the default material if one's not provided. */
- UMaterialInterface* GetSectionMaterial(int32 Index)
- {
- auto Material = GetMaterial(Index);
- return Material ? Material : UMaterial::GetDefaultMaterial(MD_Surface);
- }
- /* Finishes creating a section, including entering it for batch updating, or updating the RT directly */
- void CreateSectionInternal(int32 SectionIndex, ESectionUpdateFlags UpdateFlags);
- /* Finishes updating a section, including entering it for batch updating, or updating the RT directly */
- void UpdateSectionInternal(int32 SectionIndex, bool bHadVertexPositionsUpdate, bool bHadVertexUpdates, bool bHadIndexUpdates, bool bNeedsBoundsUpdate, ESectionUpdateFlags UpdateFlags);
- /* Finishes updating a sections positions (Only used if section is dual vertex buffer), including entering it for batch updating, or updating the RT directly */
- void UpdateSectionVertexPositionsInternal(int32 SectionIndex, bool bNeedsBoundsUpdate);
- /* Finishes updating a sections properties, like visible/casts shadow, a*/
- void UpdateSectionPropertiesInternal(int32 SectionIndex, bool bUpdateRequiresProxyRecreateIfStatic);
-
- /* Internal log helper for the templates to be able to use the internal logger */
- static void Log(FString Text, bool bIsError = false)
- {
- if (bIsError)
- {
- UE_LOG(RuntimeMeshLog, Error, TEXT("%s"), *Text);
- }
- else
- {
- UE_LOG(RuntimeMeshLog, Warning, TEXT("%s"), *Text);
- }
- }
- public:
- URuntimeMeshComponent(const FObjectInitializer& ObjectInitializer);
- /**
- * Create/replace a section.
- * @param SectionIndex Index of the section to create or replace.
- * @param Vertices Vertex buffer all vertex data for this section.
- * @param Triangles Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
- * @param bCreateCollision Indicates whether collision should be created for this section. This adds significant cost.
- * @param UpdateFrequency Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
- * @param UpdateFlags Flags pertaining to this particular update.
- */
- template<typename VertexType>
- void CreateMeshSection(int32 SectionIndex, TArray<VertexType>& Vertices, TArray<int32>& Triangles, bool bCreateCollision = false,
- EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
- {
- // It is only safe to call these functions from the game thread.
- check(IsInGameThread());
- SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_CreateMeshSection_VertexType);
- // Validate all creation parameters
- RMC_VALIDATE_CREATIONPARAMETERS(SectionIndex, Vertices, Triangles, /*VoidReturn*/);
- // Create the section
- TSharedPtr<FRuntimeMeshSection<VertexType>> Section = CreateOrResetSection<FRuntimeMeshSection<VertexType>>(SectionIndex, false);
-
- // Set the vertex and index buffers
- bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
- Section->UpdateVertexBuffer(Vertices, nullptr, bShouldUseMove);
- Section->UpdateIndexBuffer(Triangles, bShouldUseMove);
- // Track collision status and update collision information if necessary
- Section->CollisionEnabled = bCreateCollision;
- Section->UpdateFrequency = UpdateFrequency;
- // Finalize section.
- CreateSectionInternal(SectionIndex, UpdateFlags);
- }
- /**
- * Create/replace a section.
- * @param SectionIndex Index of the section to create or replace.
- * @param Vertices Vertex buffer all vertex data for this section.
- * @param Triangles Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
- * @param BoundingBox The bounds of this section. Faster than the RMC automatically calculating it.
- * @param bCreateCollision Indicates whether collision should be created for this section. This adds significant cost.
- * @param UpdateFrequency Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
- * @param UpdateFlags Flags pertaining to this particular update.
- */
- template<typename VertexType>
- void CreateMeshSection(int32 SectionIndex, TArray<VertexType>& Vertices, TArray<int32>& Triangles, const FBox& BoundingBox, bool bCreateCollision = false,
- EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
- {
- // It is only safe to call these functions from the game thread.
- check(IsInGameThread());
- SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_CreateMeshSection_VertexType_WithBoundingBox);
- // Validate all creation parameters
- RMC_VALIDATE_CREATIONPARAMETERS(SectionIndex, Vertices, Triangles, /*VoidReturn*/);
- RMC_VALIDATE_BOUNDINGBOX(BoundingBox, /*VoidReturn*/);
- // Create the section
- TSharedPtr<FRuntimeMeshSection<VertexType>> Section = CreateOrResetSection<FRuntimeMeshSection<VertexType>>(SectionIndex, false);
- // Set the vertex and index buffers
- bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
- Section->UpdateVertexBuffer(Vertices, &BoundingBox, bShouldUseMove);
- Section->UpdateIndexBuffer(Triangles, bShouldUseMove);
- // Track collision status and update collision information if necessary
- Section->CollisionEnabled = bCreateCollision;
- Section->UpdateFrequency = UpdateFrequency;
- // Finalize section.
- CreateSectionInternal(SectionIndex, UpdateFlags);
- }
- /**
- * Create/replace a section using 2 vertex buffers. One contains positions only, the other contains all other data. This allows for very efficient updates of the positions of a mesh.
- * @param SectionIndex Index of the section to create or replace.
- * @param VertexPositions Vertex buffer containing only the position information for each vertex.
- * @param VertexData Vertex buffer containing everything except position for each vertex.
- * @param Triangles Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
- * @param bCreateCollision Indicates whether collision should be created for this section. This adds significant cost.
- * @param UpdateFrequency Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
- * @param UpdateFlags Flags pertaining to this particular update.
- */
- template<typename VertexType>
- void CreateMeshSectionDualBuffer(int32 SectionIndex, TArray<FVector>& VertexPositions, TArray<VertexType>& VertexData, TArray<int32>& Triangles, bool bCreateCollision = false,
- EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
- {
- SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_CreateMeshSectionDualBuffer_VertexType);
- // Validate all creation parameters
- RMC_VALIDATE_CREATIONPARAMETERS_DUALBUFFER(SectionIndex, VertexData, Triangles, VertexPositions, /*VoidReturn*/);
- TSharedPtr<FRuntimeMeshSection<VertexType>> Section = CreateOrResetSection<FRuntimeMeshSection<VertexType>>(SectionIndex, true);
- bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
- Section->UpdateVertexPositionBuffer(VertexPositions, nullptr, bShouldUseMove);
- Section->UpdateVertexBuffer(VertexData, nullptr, bShouldUseMove);
- Section->UpdateIndexBuffer(Triangles, bShouldUseMove);
- // Track collision status and update collision information if necessary
- Section->CollisionEnabled = bCreateCollision;
- Section->UpdateFrequency = UpdateFrequency;
- // Finalize section.
- CreateSectionInternal(SectionIndex, UpdateFlags);
- }
- /**
- * Create/replace a section using 2 vertex buffers. One contains positions only, the other contains all other data. This allows for very efficient updates of the positions of a mesh.
- * @param SectionIndex Index of the section to create or replace.
- * @param VertexPositions Vertex buffer containing only the position information for each vertex.
- * @param VertexData Vertex buffer containing everything except position for each vertex.
- * @param Triangles Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
- * @param BoundingBox The bounds of this section. Faster than the RMC automatically calculating it.
- * @param bCreateCollision Indicates whether collision should be created for this section. This adds significant cost.
- * @param UpdateFrequency Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
- * @param UpdateFlags Flags pertaining to this particular update.
- */
- template<typename VertexType>
- void CreateMeshSectionDualBuffer(int32 SectionIndex, TArray<FVector>& VertexPositions, TArray<VertexType>& VertexData, TArray<int32>& Triangles, const FBox& BoundingBox,
- bool bCreateCollision = false, EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
- {
- SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_CreateMeshSectionDualBuffer_VertexType_WithBoundingBox);
- // Validate all creation parameters
- RMC_VALIDATE_CREATIONPARAMETERS_DUALBUFFER(SectionIndex, VertexData, Triangles, VertexPositions, /*VoidReturn*/);
- RMC_VALIDATE_BOUNDINGBOX(BoundingBox, /*VoidReturn*/);
- TSharedPtr<FRuntimeMeshSection<VertexType>> Section = CreateOrResetSection<FRuntimeMeshSection<VertexType>>(SectionIndex, true);
- bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
- Section->UpdateVertexPositionBuffer(VertexPositions, &BoundingBox, bShouldUseMove);
- Section->UpdateVertexBuffer(VertexData, nullptr, bShouldUseMove);
- Section->UpdateIndexBuffer(Triangles, bShouldUseMove);
- // Track collision status and update collision information if necessary
- Section->CollisionEnabled = bCreateCollision;
- Section->UpdateFrequency = UpdateFrequency;
- // Finalize section.
- CreateSectionInternal(SectionIndex, UpdateFlags);
- }
-
- /**
- * Updates a section. This is faster than CreateMeshSection. If this is a dual buffer section, you cannot change the length of the vertices.
- * @param SectionIndex Index of the section to update.
- * @param Vertices Vertex buffer all vertex data for this section, or in the case of dual buffer section it contains everything but position.
- * @param UpdateFlags Flags pertaining to this particular update.
- */
- template<typename VertexType>
- void UpdateMeshSection(int32 SectionIndex, TArray<VertexType>& Vertices, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
- {
- SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSection_VertexType);
- // Validate all update parameters
- RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
-
- // Validate section type
- MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
- // Cast section to correct type
- TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
-
- // Check dual buffer section status
- if (Section->IsDualBufferSection() && Vertices.Num() != Section->VertexBuffer.Num())
- {
- Log(TEXT("UpdateMeshSection() - Vertices cannot change length unless the positions are updated as well."), true);
- return;
- }
- bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
- bool bNeedsBoundsUpdate = false;
- // Update vertices if supplied
- bool bUpdatedVertices = false;
- if (Vertices.Num() > 0)
- {
- bNeedsBoundsUpdate = Section->UpdateVertexBuffer(Vertices, nullptr, bShouldUseMove);
- bUpdatedVertices = true;
- }
- else
- {
- Log(TEXT("UpdateMeshSection() - Vertices empty. They will not be updated."));
- }
-
- // Finalize section update if we have anything to apply
- if (bUpdatedVertices)
- {
- UpdateSectionInternal(SectionIndex, false, bUpdatedVertices, false, bNeedsBoundsUpdate, UpdateFlags);
- }
- }
- /**
- * Updates a section. This is faster than CreateMeshSection. If this is a dual buffer section, you cannot change the length of the vertices.
- * @param SectionIndex Index of the section to update.
- * @param Vertices Vertex buffer all vertex data for this section, or in the case of dual buffer section it contains everything but position.
- * @param BoundingBox The bounds of this section. Faster than the RMC automatically calculating it.
- * @param UpdateFlags Flags pertaining to this particular update.
- */
- template<typename VertexType>
- void UpdateMeshSection(int32 SectionIndex, TArray<VertexType>& Vertices, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
- {
- SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSection_VertexType_WithBoundingBox);
- // Validate all update parameters
- RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
- RMC_VALIDATE_BOUNDINGBOX(BoundingBox, /*VoidReturn*/);
- // Validate section type
- MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
- // Cast section to correct type
- TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
- // Check dual buffer section status
- if (Section->IsDualBufferSection() && Vertices.Num() != Section->VertexBuffer.Num())
- {
- Log(TEXT("UpdateMeshSection() - Vertices cannot change length unless the positions are updated as well."), true);
- return;
- }
- bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
- bool bNeedsBoundsUpdate = false;
- // Update vertices if supplied
- bool bUpdatedVertices = false;
- if (Vertices.Num() > 0)
- {
- bNeedsBoundsUpdate = Section->UpdateVertexBuffer(Vertices, &BoundingBox, bShouldUseMove);
- bUpdatedVertices = true;
- }
- else
- {
- Log(TEXT("UpdateMeshSection() - Vertices empty. They will not be updated."));
- }
- // Finalize section update if we have anything to apply
- if (bUpdatedVertices)
- {
- UpdateSectionInternal(SectionIndex, false, bUpdatedVertices, false, bNeedsBoundsUpdate, UpdateFlags);
- }
- }
- /**
- * Updates a section. This is faster than CreateMeshSection. If this is a dual buffer section, you cannot change the length of the vertices.
- * @param SectionIndex Index of the section to update.
- * @param Vertices Vertex buffer all vertex data for this section, or in the case of dual buffer section it contains everything but position.
- * @param Triangles Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
- * @param UpdateFlags Flags pertaining to this particular update.
- */
- template<typename VertexType>
- void UpdateMeshSection(int32 SectionIndex, TArray<VertexType>& Vertices, TArray<int32>& Triangles, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
- {
- SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSection_VertexType_WithTriangles);
- // Validate all update parameters
- RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
- // Validate section type
- MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
- // Cast section to correct type
- TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
- // Check dual buffer section status
- if (Section->IsDualBufferSection() && Vertices.Num() != Section->VertexBuffer.Num())
- {
- Log(TEXT("UpdateMeshSection() - Vertices cannot change length unless the positions are updated as well."), true);
- return;
- }
- bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
- bool bNeedsBoundsUpdate = false;
- // Update vertices if supplied
- bool bUpdatedVertices = false;
- if (Vertices.Num() > 0)
- {
- bNeedsBoundsUpdate = Section->UpdateVertexBuffer(Vertices, nullptr, bShouldUseMove);
- bUpdatedVertices = true;
- }
- else
- {
- Log(TEXT("UpdateMeshSection() - Vertices empty. They will not be updated."));
- }
- // Update triangles if supplied
- bool bUpdatedIndices = false;
- if (Triangles.Num() > 0)
- {
- Section->UpdateIndexBuffer(Triangles, bShouldUseMove);
- bUpdatedIndices = true;
- }
- else
- {
- Log(TEXT("UpdateMeshSection() - Triangles empty. They will not be updated."));
- }
- // Finalize section update if we have anything to apply
- if (bUpdatedVertices || bUpdatedIndices)
- {
- UpdateSectionInternal(SectionIndex, false, bUpdatedVertices, bUpdatedIndices, bNeedsBoundsUpdate, UpdateFlags);
- }
- }
- /**
- * Updates a section. This is faster than CreateMeshSection. If this is a dual buffer section, you cannot change the length of the vertices.
- * @param SectionIndex Index of the section to update.
- * @param Vertices Vertex buffer all vertex data for this section, or in the case of dual buffer section it contains everything but position.
- * @param Triangles Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
- * @param BoundingBox The bounds of this section. Faster than the RMC automatically calculating it.
- * @param UpdateFlags Flags pertaining to this particular update.
- */
- template<typename VertexType>
- void UpdateMeshSection(int32 SectionIndex, TArray<VertexType>& Vertices, TArray<int32>& Triangles, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
- {
- SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSection_VertexType_WithTrianglesAndBoundinBox);
- // Validate all update parameters
- RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
- RMC_VALIDATE_BOUNDINGBOX(BoundingBox, /*VoidReturn*/);
- // Validate section type
- MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
- // Cast section to correct type
- TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
- // Check dual buffer section status
- if (Section->IsDualBufferSection() && Vertices.Num() != Section->VertexBuffer.Num())
- {
- Log(TEXT("UpdateMeshSection() - Vertices cannot change length unless the positions are updated as well."), true);
- return;
- }
- bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
- bool bNeedsBoundsUpdate = false;
- // Update vertices if supplied
- bool bUpdatedVertices = false;
- if (Vertices.Num() > 0)
- {
- bNeedsBoundsUpdate = Section->UpdateVertexBuffer(Vertices, &BoundingBox, bShouldUseMove);
- bUpdatedVertices = true;
- }
- else
- {
- Log(TEXT("UpdateMeshSection() - Vertices empty. They will not be updated."));
- }
- // Update indices if supplied
- bool bUpdatedIndices = false;
- if (Triangles.Num() > 0)
- {
- Section->UpdateIndexBuffer(Triangles, bShouldUseMove);
- bUpdatedIndices = true;
- }
- else
- {
- Log(TEXT("UpdateMeshSection() - Triangles empty. They will not be updated."));
- }
- // Finalize section update if we have anything to apply
- if (bUpdatedVertices || bUpdatedIndices)
- {
- UpdateSectionInternal(SectionIndex, false, bUpdatedVertices, bUpdatedIndices, bNeedsBoundsUpdate, UpdateFlags);
- }
- }
-
- /**
- * Updates a section. This is faster than CreateMeshSection. This is only for dual buffer sections. You cannot change the length of positions or vertex data unless you specify both together.
- * @param SectionIndex Index of the section to update.
- * @param VertexPositions Vertex buffer containing only the position information for each vertex.
- * @param VertexData Vertex buffer containing everything except position for each vertex.
- * @param UpdateFlags Flags pertaining to this particular update.
- */
- template<typename VertexType>
- void UpdateMeshSection(int32 SectionIndex, TArray<FVector>& VertexPositions, TArray<VertexType>& VertexData, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
- {
- SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSection_Dual_VertexType);
- // Validate all update parameters
- RMC_VALIDATE_UPDATEPARAMETERS_DUALBUFFER(SectionIndex, /*VoidReturn*/);
- // Validate section type
- MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
- // Cast section to correct type
- TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
- // Check dual buffer section status
- if (Section->IsDualBufferSection() &&
- VertexData.Num() != Section->VertexBuffer.Num() &&
- VertexPositions.Num() != VertexData.Num())
- {
- Log(TEXT("UpdateMeshSection() - Vertices cannot change length unless the positions are updated as well."), true);
- return;
- }
- bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
- bool bNeedsBoundsUpdate = false;
- // Update vertex positions if supplied
- bool bUpdatedVertexPositions = false;
- if (VertexPositions.Num() > 0)
- {
- bNeedsBoundsUpdate = Section->UpdateVertexPositionBuffer(VertexPositions, nullptr, bShouldUseMove);
- bUpdatedVertexPositions = true;
- }
- else
- {
- Log(TEXT("UpdatemeshSection() - Vertex positions empty. They will not be updated."));
- }
- // Update vertices if supplied
- bool bUpdatedVertices = false;
- if (VertexData.Num() > 0)
- {
- Section->UpdateVertexBuffer(VertexData, nullptr, bShouldUseMove);
- bUpdatedVertices = true;
- }
- else
- {
- Log(TEXT("UpdateMeshSection() - Vertices empty. They will not be updated."));
- }
- // Finalize section update if we have anything to apply
- if (bUpdatedVertexPositions || bUpdatedVertices)
- {
- UpdateSectionInternal(SectionIndex, bUpdatedVertexPositions, bUpdatedVertices, false, bNeedsBoundsUpdate, UpdateFlags);
- }
- }
- /**
- * Updates a section. This is faster than CreateMeshSection. This is only for dual buffer sections. You cannot change the length of positions or vertex data unless you specify both together.
- * @param SectionIndex Index of the section to update.
- * @param VertexPositions Vertex buffer containing only the position information for each vertex.
- * @param VertexData Vertex buffer containing everything except position for each vertex.
- * @param BoundingBox The bounds of this section. Faster than the RMC automatically calculating it.
- * @param UpdateFlags Flags pertaining to this particular update.
- */
- template<typename VertexType>
- void UpdateMeshSection(int32 SectionIndex, TArray<FVector>& VertexPositions, TArray<VertexType>& VertexData, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
- {
- SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSection_Dual_VertexType_WithBoundingBox);
- // Validate all update parameters
- RMC_VALIDATE_UPDATEPARAMETERS_DUALBUFFER(SectionIndex, /*VoidReturn*/);
- RMC_VALIDATE_BOUNDINGBOX(BoundingBox, /*VoidReturn*/);
- // Validate section type
- MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
- // Cast section to correct type
- TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
- // Check dual buffer section status
- if (Section->IsDualBufferSection() &&
- VertexData.Num() != Section->VertexBuffer.Num() &&
- VertexPositions.Num() != VertexData.Num())
- {
- Log(TEXT("UpdateMeshSection() - Vertices cannot change length unless the positions are updated as well."), true);
- return;
- }
- bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
- bool bNeedsBoundsUpdate = false;
- // Update vertex positions if supplied
- bool bUpdatedVertexPositions = false;
- if (VertexPositions.Num() > 0)
- {
- bNeedsBoundsUpdate = Section->UpdateVertexPositionBuffer(VertexPositions, &BoundingBox, bShouldUseMove);
- bUpdatedVertexPositions = true;
- }
- else
- {
- Log(TEXT("UpdatemeshSection() - Vertex positions empty. They will not be updated."));
- }
- // Update vertices if supplied
- bool bUpdatedVertices = false;
- if (VertexData.Num() > 0)
- {
- Section->UpdateVertexBuffer(VertexData, nullptr, bShouldUseMove);
- bUpdatedVertices = true;
- }
- else
- {
- Log(TEXT("UpdateMeshSection() - Vertices empty. They will not be updated."));
- }
- // Finalize section update if we have anything to apply
- if (bUpdatedVertexPositions || bUpdatedVertices)
- {
- UpdateSectionInternal(SectionIndex, bUpdatedVertexPositions, bUpdatedVertices, false, bNeedsBoundsUpdate, UpdateFlags);
- }
- }
- /**
- * Updates a section. This is faster than CreateMeshSection. This is only for dual buffer sections. You cannot change the length of positions or vertex data unless you specify both together.
- * @param SectionIndex Index of the section to update.
- * @param VertexPositions Vertex buffer containing only the position information for each vertex.
- * @param VertexData Vertex buffer containing everything except position for each vertex.
- * @param Triangles Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
- * @param UpdateFlags Flags pertaining to this particular update.
- */
- template<typename VertexType>
- void UpdateMeshSection(int32 SectionIndex, TArray<FVector>& VertexPositions, TArray<VertexType>& VertexData, TArray<int32>& Triangles, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
- {
- SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSection_Dual_VertexType_WithTriangles);
- // Validate all update parameters
- RMC_VALIDATE_UPDATEPARAMETERS_DUALBUFFER(SectionIndex, /*VoidReturn*/);
- // Validate section type
- MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
- // Cast section to correct type
- TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
- // Check dual buffer section status
- if (Section->IsDualBufferSection() &&
- VertexData.Num() != Section->VertexBuffer.Num() &&
- VertexPositions.Num() != VertexData.Num())
- {
- Log(TEXT("UpdateMeshSection() - Vertices cannot change length unless the positions are updated as well."), true);
- return;
- }
- bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
- bool bNeedsBoundsUpdate = false;
- // Update vertex positions if supplied
- bool bUpdatedVertexPositions = false;
- if (VertexPositions.Num() > 0)
- {
- bNeedsBoundsUpdate = Section->UpdateVertexPositionBuffer(VertexPositions, nullptr, bShouldUseMove);
- bUpdatedVertexPositions = true;
- }
- else
- {
- Log(TEXT("UpdatemeshSection() - Vertex positions empty. They will not be updated."));
- }
- // Update vertices if supplied
- bool bUpdatedVertices = false;
- if (VertexData.Num() > 0)
- {
- Section->UpdateVertexBuffer(VertexData, nullptr, bShouldUseMove);
- bUpdatedVertices = true;
- }
- else
- {
- Log(TEXT("UpdateMeshSection() - Vertices empty. They will not be updated."));
- }
- // Update triangles if supplied
- bool bUpdatedIndices = false;
- if (Triangles.Num() > 0)
- {
- Section->UpdateIndexBuffer(Triangles, bShouldUseMove);
- bUpdatedIndices = true;
- }
- else
- {
- Log(TEXT("UpdateMeshSection() - Triangles empty. They will not be updated."));
- }
- // Finalize section update if we have anything to apply
- if (bUpdatedVertexPositions || bUpdatedVertices || bUpdatedIndices)
- {
- UpdateSectionInternal(SectionIndex, bUpdatedVertexPositions, bUpdatedVertices, bUpdatedIndices, bNeedsBoundsUpdate, UpdateFlags);
- }
- }
- /**
- * Updates a section. This is faster than CreateMeshSection. This is only for dual buffer sections. You cannot change the length of positions or vertex data unless you specify both together.
- * @param SectionIndex Index of the section to update.
- * @param VertexPositions Vertex buffer containing only the position information for each vertex.
- * @param VertexData Vertex buffer containing everything except position for each vertex.
- * @param Triangles Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
- * @param BoundingBox The bounds of this section. Faster than the RMC automatically calculating it.
- * @param UpdateFlags Flags pertaining to this particular update.
- */
- template<typename VertexType>
- void UpdateMeshSection(int32 SectionIndex, TArray<FVector>& VertexPositions, TArray<VertexType>& VertexData, TArray<int32>& Triangles, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
- {
- SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSection_Dual_VertexType_WithTrianglesAndBoundinBox);
- // Validate all update parameters
- RMC_VALIDATE_UPDATEPARAMETERS_DUALBUFFER(SectionIndex, /*VoidReturn*/);
- RMC_VALIDATE_BOUNDINGBOX(BoundingBox, /*VoidReturn*/);
- // Validate section type
- MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
- // Cast section to correct type
- TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
- // Check dual buffer section status
- if (Section->IsDualBufferSection() &&
- VertexData.Num() != Section->VertexBuffer.Num() &&
- VertexPositions.Num() != VertexData.Num())
- {
- Log(TEXT("UpdateMeshSection() - Vertices cannot change length unless the positions are updated as well."), true);
- return;
- }
- bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
- bool bNeedsBoundsUpdate = false;
- // Update vertex positions if supplied
- bool bUpdatedVertexPositions = false;
- if (VertexPositions.Num() > 0)
- {
- bNeedsBoundsUpdate = Section->UpdateVertexPositionBuffer(VertexPositions, &BoundingBox, bShouldUseMove);
- bUpdatedVertexPositions = true;
- }
- else
- {
- Log(TEXT("UpdatemeshSection() - Vertex positions empty. They will not be updated."));
- }
- // Update vertices if supplied
- bool bUpdatedVertices = false;
- if (VertexData.Num() > 0)
- {
- Section->UpdateVertexBuffer(VertexData, nullptr, bShouldUseMove);
- bUpdatedVertices = true;
- }
- else
- {
- Log(TEXT("UpdateMeshSection() - Vertices empty. They will not be updated."));
- }
- // Update indices if supplied
- bool bUpdatedIndices = false;
- if (Triangles.Num() > 0)
- {
- Section->UpdateIndexBuffer(Triangles, bShouldUseMove);
- bUpdatedIndices = true;
- }
- else
- {
- Log(TEXT("UpdateMeshSection() - Triangles empty. They will not be updated."));
- }
- // Finalize section update if we have anything to apply
- if (bUpdatedVertexPositions || bUpdatedVertices || bUpdatedIndices)
- {
- UpdateSectionInternal(SectionIndex, bUpdatedVertexPositions, bUpdatedVertices, bUpdatedIndices, bNeedsBoundsUpdate, UpdateFlags);
- }
- }
-
- /**
- * Updates a sections position buffer only. This cannot be used on a non-dual buffer section. You cannot change the length of the vertex position buffer with this function.
- * @param SectionIndex Index of the section to update.
- * @param VertexPositions Vertex buffer containing only the position information for each vertex.
- * @param UpdateFlags Flags pertaining to this particular update.
- */
- void UpdateMeshSectionPositionsImmediate(int32 SectionIndex, TArray<FVector>& VertexPositions, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
- /**
- * Updates a sections position buffer only. This cannot be used on a non-dual buffer section. You cannot change the length of the vertex position buffer with this function.
- * @param SectionIndex Index of the section to update.
- * @param VertexPositions Vertex buffer containing only the position information for each vertex.
- * @param BoundingBox The bounds of this section. Faster than the RMC automatically calculating it.
- * @param UpdateFlags Flags pertaining to this particular update.
- */
- void UpdateMeshSectionPositionsImmediate(int32 SectionIndex, TArray<FVector>& VertexPositions, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
-
- /**
- * Starts an in place update of vertex positions.
- * @param SectionIndex Index of the section to update.
- */
- TArray<FVector>* BeginMeshSectionPositionUpdate(int32 SectionIndex);
- /**
- * Finishes an in place update of vertex positions.
- * This will push the update to the GPU and calculate the new Bounding Box
- * @param SectionIndex Index of the section to update.
- */
- void EndMeshSectionPositionUpdate(int32 SectionIndex);
- /**
- * Finishes an in place update of vertex positions.
- * This will push the update to the GPU
- * @param SectionIndex Index of the section to update.
- * @param BoundingBox The bounds of this section. Faster than the RMC automatically calculating it.
- */
- void EndMeshSectionPositionUpdate(int32 SectionIndex, const FBox& BoundingBox);
- template<typename VertexType>
- void BeginMeshSectionUpdate(int32 SectionIndex, TArray<VertexType>*& Vertices)
- {
- RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
- // Validate section type
- MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
- // Cast section to correct type
- TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
- Vertices = &Section->VertexBuffer;
- }
- template<typename VertexType>
- void BeginMeshSectionUpdate(int32 SectionIndex, TArray<VertexType>*& Vertices, TArray<int32>*& Triangles)
- {
- RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
- // Validate section type
- MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
- // Cast section to correct type
- TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
- Vertices = &Section->VertexBuffer;
- Triangles = &Section->IndexBuffer;
- }
- template<typename VertexType>
- void BeginMeshSectionUpdate(int32 SectionIndex, TArray<FVector>*& Positions, TArray<VertexType>*& Vertices)
- {
- RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
- // Validate section type
- MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
- // Cast section to correct type
- TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
- Positions = &Section->PositionVertexBuffer;
- Vertices = &Section->VertexBuffer;
- }
- template<typename VertexType>
- void BeginMeshSectionUpdate(int32 SectionIndex, TArray<FVector>*& Positions, TArray<VertexType>*& Vertices, TArray<int32>*& Triangles)
- {
- RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
- // Validate section type
- MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
- // Cast section to correct type
- TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
- Positions = &Section->PositionVertexBuffer;
- Vertices = &Section->VertexBuffer;
- Triangles = &Section->IndexBuffer;
- }
- void BeginMeshSectionUpdate(int32 SectionIndex, IRuntimeMeshVerticesBuilder*& Vertices, FRuntimeMeshIndicesBuilder*& Indices);
- void EndMeshSectionUpdate(int32 SectionIndex, ERuntimeMeshBuffer UpdatedBuffers, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
- void EndMeshSectionUpdate(int32 SectionIndex, ERuntimeMeshBuffer UpdatedBuffers, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
-
- /*
- * Gets a readonly pointer to the sections mesh data.
- * To be able to edit the section data use BegineMeshSectionUpdate()
- */
- void GetSectionMesh(int32 SectionIndex, const IRuntimeMeshVerticesBuilder*& Vertices, const FRuntimeMeshIndicesBuilder*& Indices);
- /**
- * Create/replace a section.
- * @param SectionIndex Index of the section to create or replace.
- * @param Vertices Vertex buffer of all vertex positions to use for this mesh section.
- * @param Triangles Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
- * @param Normals Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
- * @param UV0 Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
- * @param Colors Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
- * @param Tangents Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
- * @param bCreateCollision Indicates whether collision should be created for this section. This adds significant cost.
- * @param UpdateFrequency Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
- */
- void CreateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals,
- const TArray<FVector2D>& UV0, const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents, bool bCreateCollision = false,
- EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
- /**
- * Create/replace a section.
- * @param SectionIndex Index of the section to create or replace.
- * @param Vertices Vertex buffer of all vertex positions to use for this mesh section.
- * @param Triangles Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
- * @param Normals Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
- * @param UV0 Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
- * @param UV1 Optional array of texture co-ordinates for each vertex (UV Channel 1). If supplied, must be same length as Vertices array.
- * @param Colors Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
- * @param Tangents Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
- * @param bCreateCollision Indicates whether collision should be created for this section. This adds significant cost.
- * @param UpdateFrequency Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
- */
- void CreateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals,
- const TArray<FVector2D>& UV0, const TArray<FVector2D>& UV1, const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents,
- bool bCreateCollision = false, EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
- /**
- * Updates a section. This is faster than CreateMeshSection.
- * @param SectionIndex Index of the section to update.
- * @param Vertices Vertex buffer of all vertex positions to use for this mesh section.
- * @param Normals Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
- * @param UV1 Optional array of texture co-ordinates for each vertex (UV Channel 1). If supplied, must be same length as Vertices array.
- * @param Colors Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
- * @param Tangents Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
- */
- void UpdateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<FVector>& Normals, const TArray<FVector2D>& UV0,
- const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
- /**
- * Updates a section. This is faster than CreateMeshSection.
- * @param SectionIndex Index of the section to update.
- * @param Vertices Vertex buffer of all vertex positions to use for this mesh section.
- * @param Normals Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
- * @param UV0 Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
- * @param UV1 Optional array of texture co-ordinates for each vertex (UV Channel 1). If supplied, must be same length as Vertices array.
- * @param Colors Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
- * @param Tangents Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
- */
- void UpdateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<FVector>& Normals, const TArray<FVector2D>& UV0,
- const TArray<FVector2D>& UV1, const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
- /**
- * Updates a section. This is faster than CreateMeshSection.
- * @param SectionIndex Index of the section to update.
- * @param Vertices Vertex buffer of all vertex positions to use for this mesh section.
- * @param Triangles Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
- * @param Normals Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
- * @param UV0 Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
- * @param Colors Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
- * @param Tangents Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
- */
- void UpdateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals,
- const TArray<FVector2D>& UV0, const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
- /**
- * Updates a section. This is faster than CreateMeshSection.
- * @param SectionIndex Index of the section to update.
- * @param Vertices Vertex buffer of all vertex positions to use for this mesh section.
- * @param Triangles Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
- * @param Normals Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
- * @param UV0 Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
- * @param UV1 Optional array of texture co-ordinates for each vertex (UV Channel 1). If supplied, must be same length as Vertices array.
- * @param Colors Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
- * @param Tangents Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
- */
- void UpdateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals,
- const TArray<FVector2D>& UV0, const TArray<FVector2D>& UV1, const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
-
- /**
- * Create/replace a section.
- * @param SectionIndex Index of the section to create or replace.
- * @param Vertices Vertex buffer of all vertex positions to use for this mesh section.
- * @param Triangles Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
- * @param Normals Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
- * @param Tangents Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
- * @param UV0 Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
- * @param UV1 Optional array of texture co-ordinates for each vertex (UV Channel 1). If supplied, must be same length as Vertices array.
- * @param Colors Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
- * @param bCreateCollision Indicates whether collision should be created for this section. This adds significant cost.
- * @param bCalculateNormalTangent Indicates whether normal/tangent information should be calculated automatically. This can add significant cost.
- * @param bGenerateTessellationTriangles Indicates whether tessellation supporting triangles should be calculated. This can add significant cost.
- * @param UpdateFrequency Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
- */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh", meta = (DisplayName = "Create Mesh Section", AutoCreateRefTerm = "Normals,Tangents,UV0,UV1,Colors"))
- void CreateMeshSection_Blueprint(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals,
- const TArray<FRuntimeMeshTangent>& Tangents, const TArray<FVector2D>& UV0, const TArray<FVector2D>& UV1, const TArray<FLinearColor>& Colors,
- bool bCreateCollision, bool bCalculateNormalTangent, bool bGenerateTessellationTriangles, EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average);
- /**
- * Updates a section. This is faster than CreateMeshSection. If you change the vertices count, you must update the other components.
- * @param SectionIndex Index of the section to update.
- * @param Vertices Vertex buffer of all vertex positions to use for this mesh section.
- * @param Triangles Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
- * @param Normals Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
- * @param Tangents Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
- * @param UV0 Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
- * @param UV1 Optional array of texture co-ordinates for each vertex (UV Channel 1). If supplied, must be same length as Vertices array.
- * @param Colors Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
- * @param bCalculateNormalTangent Indicates whether normal/tangent information should be calculated automatically. This can add significant cost.
- * @param bGenerateTessellationTriangles Indicates whether tessellation supporting triangles should be calculated. This can add significant cost.
- */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh", meta = (DisplayName = "Update Mesh Section", AutoCreateRefTerm = "Triangles,Normals,Tangents,UV0,UV1,Colors"))
- void UpdateMeshSection_Blueprint(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals,
- const TArray<FRuntimeMeshTangent>& Tangents, const TArray<FVector2D>& UV0, const TArray<FVector2D>& UV1, const TArray<FLinearColor>& Colors, bool bCalculateNormalTangent, bool bGenerateTessellationTriangles);
-
- /**
- * Create/replace a section.
- * @param SectionIndex Index of the section to create or replace.
- * @param Vertices Vertex buffer all vertex data for this section.
- * @param Triangles Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
- * @param bCreateCollision Indicates whether collision should be created for this section. This adds significant cost.
- * @param UpdateFrequency Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
- * @param UpdateFlags Flags pertaining to this particular update.
- */
- void CreateMeshSection(int32 SectionIndex, IRuntimeMeshVerticesBuilder& Vertices, FRuntimeMeshIndicesBuilder& Indices, bool bCreateCollision = false,
- EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
- /**
- * Updates a section. This is faster than CreateMeshSection. If this is a dual buffer section, you cannot change the length of the vertices.
- * @param SectionIndex Index of the section to update.
- * @param Vertices Vertex buffer all vertex data for this section, or in the case of dual buffer section it contains everything but position.
- * @param Triangles Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
- * @param UpdateFlags Flags pertaining to this particular update.
- */
- void UpdateMeshSection(int32 SectionIndex, IRuntimeMeshVerticesBuilder& Vertices, FRuntimeMeshIndicesBuilder& Indices, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
- /** Clear a section of the procedural mesh. */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- void ClearMeshSection(int32 SectionIndex);
- /** Clear all mesh sections and reset to empty state */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- void ClearAllMeshSections();
- /** Sets the tessellation triangles needed to correctly support tessellation on a section. */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- void SetSectionTessellationTriangles(int32 SectionIndex, const TArray<int32>& TessellationTriangles, bool bShouldMoveArray = false);
- /** Gets the bounding box of a specific section */
- bool GetSectionBoundingBox(int32 SectionIndex, FBox& OutBoundingBox);
- /** Control visibility of a particular section */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- void SetMeshSectionVisible(int32 SectionIndex, bool bNewVisibility);
- /** Returns whether a particular section is currently visible */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- bool IsMeshSectionVisible(int32 SectionIndex) const;
- /** Control whether a particular section casts a shadow */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- void SetMeshSectionCastsShadow(int32 SectionIndex, bool bNewCastsShadow);
- /** Returns whether a particular section is currently casting shadows */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- bool IsMeshSectionCastingShadows(int32 SectionIndex) const;
- /** Control whether a particular section has collision */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- void SetMeshSectionCollisionEnabled(int32 SectionIndex, bool bNewCollisionEnabled);
- /** Returns whether a particular section has collision */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- bool IsMeshSectionCollisionEnabled(int32 SectionIndex);
- /** Returns number of sections currently created for this component */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- int32 GetNumSections() const;
- /** Returns whether a particular section currently exists */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- bool DoesSectionExist(int32 SectionIndex) const;
- /** Returns first available section index */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- int32 FirstAvailableMeshSectionIndex() const;
-
- /** Returns the last in use section index */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- int32 GetLastSectionIndex() const;
- /** Sets the geometry for a collision only section */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- void SetMeshCollisionSection(int32 CollisionSectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles);
- /** Clears the geometry for a collision only section */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- void ClearMeshCollisionSection(int32 CollisionSectionIndex);
- /** Clears the geometry for ALL collision only sections */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- void ClearAllMeshCollisionSections();
- /** Add simple collision convex to this component */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- void AddCollisionConvexMesh(TArray<FVector> ConvexVerts);
- /** Add simple collision convex to this component */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- void ClearCollisionConvexMeshes();
- /** Function to replace _all_ simple collision in one go */
- void SetCollisionConvexMeshes(const TArray< TArray<FVector> >& ConvexMeshes);
- /** Begins a batch of updates, delays updates until you call EndBatchUpdates() */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- void BeginBatchUpdates()
- {
- BatchState.StartBatch();
- }
- /** Ends a batch of updates started with BeginBatchUpdates() */
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- void EndBatchUpdates();
- /** Runs any pending collision cook (Not required to call this. This is only if you need to make sure all changes are cooked before doing something)*/
- UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
- void CookCollisionNow();
- /**
- * Controls whether the complex (Per poly) geometry should be treated as 'simple' collision.
- * Should be set to false if this component is going to be given simple collision and simulated.
- */
- UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "RuntimeMesh")
- bool bUseComplexAsSimpleCollision;
- /**
- * Controls whether the mesh data should be serialized with the component.
- */
- UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "RuntimeMesh")
- bool bShouldSerializeMeshData;
-
- /*
- * The current mode of the collision cooker
- * WARNING: This feature will only work in engine version 4.14 or above!
- */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "RuntimeMesh")
- ERuntimeMeshCollisionCookingMode CollisionMode;
-
- /** Collision data */
- UPROPERTY(Instanced)
- class UBodySetup* BodySetup;
- /* Serialize the entire RMC to the supplied archive. */
- void SerializeRMC(FArchive& Ar);
- /* Serialize the designated section into the supplied archive. */
- void SerializeRMCSection(FArchive& Ar, int32 SectionIndex);
- private:
- //~ Begin Interface_CollisionDataProvider Interface
- virtual bool GetPhysicsTriMeshData(struct FTriMeshCollisionData* CollisionData, bool InUseAllTriData) override;
- virtual bool ContainsPhysicsTriMeshData(bool InUseAllTriData) const override;
- virtual bool WantsNegXTriMesh() override { return false; }
- //~ End Interface_CollisionDataProvider Interface
- //~ Begin USceneComponent Interface.
- virtual FBoxSphereBounds CalcBounds(const FTransform& LocalToWorld) const override;
- virtual bool IsSupportedForNetworking() const override
- {
- return true;
- }
- //~ Begin USceneComponent Interface.
- //~ Begin UPrimitiveComponent Interface.
- virtual FPrimitiveSceneProxy* CreateSceneProxy() override;
- virtual class UBodySetup* GetBodySetup() override;
- //~ End UPrimitiveComponent Interface.
- //~ Begin UMeshComponent Interface.
- virtual int32 GetNumMaterials() const override;
- //~ End UMeshComponent Interface.
- /** Update LocalBounds member from the local box of each section */
- void UpdateLocalBounds(bool bMarkRenderTransform = true);
- /** Ensure ProcMeshBodySetup is allocated and configured */
- void EnsureBodySetupCreated();
- /** Mark collision data as dirty, and re-create on instance if necessary */
- void UpdateCollision();
- /* Marks the collision for an end of frame update */
- void MarkCollisionDirty();
- /* Cooks the new collision mesh updating the body */
- void BakeCollision();
- void UpdateNavigation();
- /* Serializes this component */
- virtual void Serialize(FArchive& Ar) override;
- void SerializeInternal(FArchive& Ar, bool bForceSaveAll = false);
- void SerializeLegacy(FArchive& Ar);
- /* Does post load fixups */
- virtual void PostLoad() override;
- /* Registers the pre-physics tick function used to cook new meshes when necessary */
- virtual void RegisterComponentTickFunctions(bool bRegister) override;
- /* Current state of a batch update. */
- FRuntimeMeshBatchUpdateState BatchState;
- /* Is the collision in need of a recook? */
- bool bCollisionDirty;
- /** Array of sections of mesh */
- TArray<RuntimeMeshSectionPtr> MeshSections;
- /* Array of collision only mesh sections*/
- UPROPERTY(Transient)
- TArray<FRuntimeMeshCollisionSection> MeshCollisionSections;
- /** Convex shapes used for simple collision */
- UPROPERTY(Transient)
- TArray<FRuntimeConvexCollisionSection> ConvexCollisionSections;
- /** Local space bounds of mesh */
- UPROPERTY(Transient)
- FBoxSphereBounds LocalBounds;
- /* Tick function used to cook collision when needed*/
- UPROPERTY(Transient)
- FRuntimeMeshComponentPrePhysicsTickFunction PrePhysicsTick;
- friend class FRuntimeMeshSceneProxy;
- friend struct FRuntimeMeshComponentPrePhysicsTickFunction;
- };
|