mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-22 02:06:03 +08:00
1309 lines
60 KiB
C++
1309 lines
60 KiB
C++
// 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;
|
|
};
|