mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-22 02:06:03 +08:00
1216 lines
51 KiB
C++
1216 lines
51 KiB
C++
// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "RuntimeMeshCore.h"
|
|
#include "RuntimeMeshComponent.h"
|
|
|
|
#define RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(TaskType, DataType, DataPtr, RuntimeMesh, Code) \
|
|
class FParallelRuntimeMeshComponentTask_##TaskType \
|
|
{ \
|
|
TWeakObjectPtr<URuntimeMeshComponent> RuntimeMeshComponent; \
|
|
DataType* RMCCallData; \
|
|
public: \
|
|
FParallelRuntimeMeshComponentTask_##TaskType(TWeakObjectPtr<URuntimeMeshComponent> InRMC, DataType* InData) \
|
|
: RuntimeMeshComponent(InRMC), RMCCallData(InData) \
|
|
{ \
|
|
} \
|
|
\
|
|
~FParallelRuntimeMeshComponentTask_##TaskType() \
|
|
{ \
|
|
if (RMCCallData != nullptr) \
|
|
{ \
|
|
delete RMCCallData; \
|
|
} \
|
|
} \
|
|
\
|
|
FORCEINLINE TStatId GetStatId() const \
|
|
{ \
|
|
RETURN_QUICK_DECLARE_CYCLE_STAT(FParallelRuntimeMeshComponentTask_##TaskType, STATGROUP_TaskGraphTasks); \
|
|
} \
|
|
\
|
|
static ENamedThreads::Type GetDesiredThread() \
|
|
{ \
|
|
return ENamedThreads::GameThread; \
|
|
} \
|
|
\
|
|
static ESubsequentsMode::Type GetSubsequentsMode() \
|
|
{ \
|
|
return ESubsequentsMode::FireAndForget; \
|
|
} \
|
|
\
|
|
void DoTask(ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent) \
|
|
{ \
|
|
DataType* Data = RMCCallData; \
|
|
if (URuntimeMeshComponent* Mesh = RuntimeMeshComponent.Get()) \
|
|
{ \
|
|
Code \
|
|
} \
|
|
} \
|
|
}; \
|
|
TGraphTask<FParallelRuntimeMeshComponentTask_##TaskType>::CreateTask().ConstructAndDispatchWhenReady(RuntimeMesh, DataPtr);
|
|
|
|
|
|
|
|
|
|
class RUNTIMEMESHCOMPONENT_API FRuntimeMeshAsync
|
|
{
|
|
|
|
|
|
|
|
public:
|
|
|
|
/**
|
|
* 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>
|
|
static void CreateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<VertexType>& Vertices, TArray<int32>& Triangles,
|
|
bool bCreateCollision = false, EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<VertexType> Vertices;
|
|
TArray<int32> Triangles;
|
|
bool bCreateCollision;
|
|
EUpdateFrequency UpdateFrequency;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->Vertices = MoveTemp(Vertices);
|
|
CallData->Triangles = MoveTemp(Triangles);
|
|
}
|
|
else
|
|
{
|
|
CallData->Vertices = Vertices;
|
|
CallData->Triangles = Triangles;
|
|
}
|
|
CallData->bCreateCollision = bCreateCollision;
|
|
CallData->UpdateFrequency = UpdateFrequency;
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(CreateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->CreateMeshSection(Data->SectionIndex, Data->Vertices, Data->Triangles, Data->bCreateCollision, Data->UpdateFrequency, Data->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>
|
|
static void CreateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<VertexType>& Vertices, TArray<int32>& Triangles,
|
|
const FBox& BoundingBox, bool bCreateCollision = false, EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<VertexType> Vertices;
|
|
TArray<int32> Triangles;
|
|
FBox BoundingBox;
|
|
bool bCreateCollision;
|
|
EUpdateFrequency UpdateFrequency;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->Vertices = MoveTemp(Vertices);
|
|
CallData->Triangles = MoveTemp(Triangles);
|
|
}
|
|
else
|
|
{
|
|
CallData->Vertices = Vertices;
|
|
CallData->Triangles = Triangles;
|
|
}
|
|
CallData->BoundingBox = BoundingBox;
|
|
CallData->bCreateCollision = bCreateCollision;
|
|
CallData->UpdateFrequency = UpdateFrequency;
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(CreateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->CreateMeshSection(Data->SectionIndex, Data->Vertices, Data->Triangles, Data->BoundingBox, Data->bCreateCollision, Data->UpdateFrequency, Data->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>
|
|
static void CreateMeshSectionDualBuffer(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<FVector>& VertexPositions,
|
|
TArray<VertexType>& VertexData, TArray<int32>& Triangles, bool bCreateCollision = false,
|
|
EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<FVector> VertexPositions;
|
|
TArray<VertexType> Vertices;
|
|
TArray<int32> Triangles;
|
|
bool bCreateCollision;
|
|
EUpdateFrequency UpdateFrequency;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->VertexPositions = MoveTemp(VertexPositions);
|
|
CallData->Vertices = MoveTemp(VertexData);
|
|
CallData->Triangles = MoveTemp(Triangles);
|
|
}
|
|
else
|
|
{
|
|
CallData->VertexPositions = VertexPositions;
|
|
CallData->Vertices = VertexData;
|
|
CallData->Triangles = Triangles;
|
|
}
|
|
CallData->bCreateCollision = bCreateCollision;
|
|
CallData->UpdateFrequency = UpdateFrequency;
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(CreateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->CreateMeshSection(Data->SectionIndex, Data->VertexPositions, Data->Vertices, Data->Triangles, Data->bCreateCollision, Data->UpdateFrequency, Data->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>
|
|
static void CreateMeshSectionDualBuffer(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, 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)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<FVector> VertexPositions;
|
|
TArray<VertexType> Vertices;
|
|
TArray<int32> Triangles;
|
|
FBox BoundingBox;
|
|
bool bCreateCollision;
|
|
EUpdateFrequency UpdateFrequency;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->VertexPositions = MoveTemp(VertexPositions);
|
|
CallData->Vertices = MoveTemp(VertexData);
|
|
CallData->Triangles = MoveTemp(Triangles);
|
|
}
|
|
else
|
|
{
|
|
CallData->VertexPositions = VertexPositions;
|
|
CallData->Vertices = VertexData;
|
|
CallData->Triangles = Triangles;
|
|
}
|
|
CallData->BoundingBox = BoundingBox;
|
|
CallData->bCreateCollision = bCreateCollision;
|
|
CallData->UpdateFrequency = UpdateFrequency;
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(CreateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->CreateMeshSection(Data->SectionIndex, Data->VertexPositions, Data->Vertices, Data->Triangles, Data->BoundingBox, Data->bCreateCollision, Data->UpdateFrequency, Data->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>
|
|
static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<VertexType>& Vertices,
|
|
ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<VertexType> Vertices;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->Vertices = MoveTemp(Vertices);
|
|
}
|
|
else
|
|
{
|
|
CallData->Vertices = Vertices;
|
|
}
|
|
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->UpdateMeshSection(Data->SectionIndex, Data->Vertices, Data->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>
|
|
static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<VertexType>& Vertices,
|
|
const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<VertexType> Vertices;
|
|
FBox BoundingBox;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->Vertices = MoveTemp(Vertices);
|
|
}
|
|
else
|
|
{
|
|
CallData->Vertices = Vertices;
|
|
}
|
|
|
|
CallData->BoundingBox = BoundingBox;
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->UpdateMeshSection(Data->SectionIndex, Data->Vertices, Data->BoundingBox, Data->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>
|
|
static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<VertexType>& Vertices,
|
|
TArray<int32>& Triangles, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<VertexType> Vertices;
|
|
TArray<int32> Triangles;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->Vertices = MoveTemp(Vertices);
|
|
CallData->Triangles = MoveTemp(Triangles);
|
|
}
|
|
else
|
|
{
|
|
CallData->Vertices = Vertices;
|
|
CallData->Triangles = Triangles;
|
|
}
|
|
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->UpdateMeshSection(Data->SectionIndex, Data->Vertices, Data->Triangles, Data->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>
|
|
static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<VertexType>& Vertices,
|
|
TArray<int32>& Triangles, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<VertexType> Vertices;
|
|
TArray<int32> Triangles;
|
|
FBox BoundingBox;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->Vertices = MoveTemp(Vertices);
|
|
CallData->Triangles = MoveTemp(Triangles);
|
|
}
|
|
else
|
|
{
|
|
CallData->Vertices = Vertices;
|
|
CallData->Triangles = Triangles;
|
|
}
|
|
|
|
CallData->BoundingBox = BoundingBox;
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->UpdateMeshSection(Data->SectionIndex, Data->Vertices, Data->Triangles, Data->BoundingBox, Data->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 Vertices Vertex buffer containing everything except position for each vertex.
|
|
* @param UpdateFlags Flags pertaining to this particular update.
|
|
*/
|
|
template<typename VertexType>
|
|
static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<FVector>& VertexPositions,
|
|
TArray<VertexType>& Vertices, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<FVector> VertexPositions;
|
|
TArray<VertexType> Vertices;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->VertexPositions = MoveTemp(VertexPositions);
|
|
CallData->Vertices = MoveTemp(Vertices);
|
|
}
|
|
else
|
|
{
|
|
CallData->VertexPositions = VertexPositions;
|
|
CallData->Vertices = Vertices;
|
|
}
|
|
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->UpdateMeshSection(Data->SectionIndex, Data->VertexPositions, Data->Vertices, Data->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 Vertices 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>
|
|
static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<FVector>& VertexPositions,
|
|
TArray<VertexType>& Vertices, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<FVector> VertexPositions;
|
|
TArray<VertexType> Vertices;
|
|
FBox BoundingBox;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->VertexPositions = MoveTemp(VertexPositions);
|
|
CallData->Vertices = MoveTemp(Vertices);
|
|
}
|
|
else
|
|
{
|
|
CallData->VertexPositions = VertexPositions;
|
|
CallData->Vertices = Vertices;
|
|
}
|
|
|
|
CallData->BoundingBox = BoundingBox;
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->UpdateMeshSection(Data->SectionIndex, Data->VertexPositions, Data->Vertices, Data->BoundingBox, Data->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 Vertices 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>
|
|
static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<FVector>& VertexPositions,
|
|
TArray<VertexType>& Vertices, TArray<int32>& Triangles, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<FVector> VertexPositions;
|
|
TArray<VertexType> Vertices;
|
|
TArray<int32> Triangles;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->VertexPositions = MoveTemp(VertexPositions);
|
|
CallData->Vertices = MoveTemp(Vertices);
|
|
CallData->Triangles = MoveTemp(Triangles);
|
|
}
|
|
else
|
|
{
|
|
CallData->VertexPositions = VertexPositions;
|
|
CallData->Vertices = Vertices;
|
|
CallData->Triangles = Triangles;
|
|
}
|
|
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->UpdateMeshSection(Data->SectionIndex, Data->VertexPositions, Data->Vertices, Data->Triangles, Data->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 Vertices 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>
|
|
static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<FVector>& VertexPositions,
|
|
TArray<VertexType>& Vertices, TArray<int32>& Triangles, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<FVector> VertexPositions;
|
|
TArray<VertexType> Vertices;
|
|
TArray<int32> Triangles;
|
|
FBox BoundingBox;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->VertexPositions = MoveTemp(VertexPositions);
|
|
CallData->Vertices = MoveTemp(Vertices);
|
|
CallData->Triangles = MoveTemp(Triangles);
|
|
}
|
|
else
|
|
{
|
|
CallData->VertexPositions = VertexPositions;
|
|
CallData->Vertices = Vertices;
|
|
CallData->Triangles = Triangles;
|
|
}
|
|
|
|
CallData->BoundingBox = BoundingBox;
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->UpdateMeshSection(Data->SectionIndex, Data->VertexPositions, Data->Vertices, Data->Triangles, Data->BoundingBox, Data->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.
|
|
*/
|
|
static void UpdateMeshSectionPositionsImmediate(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex,
|
|
TArray<FVector>& VertexPositions, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<FVector> VertexPositions;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->VertexPositions = MoveTemp(VertexPositions);
|
|
}
|
|
else
|
|
{
|
|
CallData->VertexPositions = VertexPositions;
|
|
}
|
|
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSectionPositionsImmediate, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->UpdateMeshSectionPositionsImmediate(Data->SectionIndex, Data->VertexPositions, Data->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 BoundingBox The bounds of this section. Faster than the RMC automatically calculating it.
|
|
* @param UpdateFlags Flags pertaining to this particular update.
|
|
*/
|
|
static void UpdateMeshSectionPositionsImmediate(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex,
|
|
TArray<FVector>& VertexPositions, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<FVector> VertexPositions;
|
|
FBox BoundingBox;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->VertexPositions = MoveTemp(VertexPositions);
|
|
}
|
|
else
|
|
{
|
|
CallData->VertexPositions = VertexPositions;
|
|
}
|
|
|
|
CallData->BoundingBox = BoundingBox;
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSectionPositionsImmediate, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->UpdateMeshSectionPositionsImmediate(Data->SectionIndex, Data->VertexPositions, Data->BoundingBox, Data->UpdateFlags);
|
|
});
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
static void CreateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, 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)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<FVector> Vertices;
|
|
TArray<int32> Triangles;
|
|
TArray<FVector> Normals;
|
|
TArray<FVector2D> UV0;
|
|
TArray<FColor> Colors;
|
|
TArray<FRuntimeMeshTangent> Tangents;
|
|
bool bCreateCollision = false;
|
|
EUpdateFrequency UpdateFrequency;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->Vertices = MoveTemp(Vertices);
|
|
CallData->Triangles = MoveTemp(Triangles);
|
|
CallData->Normals = MoveTemp(Normals);
|
|
CallData->UV0 = MoveTemp(UV0);
|
|
CallData->Colors = MoveTemp(Colors);
|
|
CallData->Tangents = MoveTemp(Tangents);
|
|
}
|
|
else
|
|
{
|
|
CallData->Vertices = Vertices;
|
|
CallData->Triangles = Triangles;
|
|
CallData->Normals = Normals;
|
|
CallData->UV0 = UV0;
|
|
CallData->Colors = Colors;
|
|
CallData->Tangents = Tangents;
|
|
}
|
|
|
|
CallData->bCreateCollision = bCreateCollision;
|
|
CallData->UpdateFrequency = UpdateFrequency;
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(CreateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->CreateMeshSection(Data->SectionIndex, Data->Vertices, Data->Triangles, Data->Normals, Data->UV0, Data->Colors,
|
|
Data->Tangents, Data->bCreateCollision, Data->UpdateFrequency, Data->UpdateFlags);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
static void CreateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, 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)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<FVector> Vertices;
|
|
TArray<int32> Triangles;
|
|
TArray<FVector> Normals;
|
|
TArray<FVector2D> UV0;
|
|
TArray<FVector2D> UV1;
|
|
TArray<FColor> Colors;
|
|
TArray<FRuntimeMeshTangent> Tangents;
|
|
bool bCreateCollision = false;
|
|
EUpdateFrequency UpdateFrequency;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->Vertices = MoveTemp(Vertices);
|
|
CallData->Triangles = MoveTemp(Triangles);
|
|
CallData->Normals = MoveTemp(Normals);
|
|
CallData->UV0 = MoveTemp(UV0);
|
|
CallData->UV1 = MoveTemp(UV1);
|
|
CallData->Colors = MoveTemp(Colors);
|
|
CallData->Tangents = MoveTemp(Tangents);
|
|
}
|
|
else
|
|
{
|
|
CallData->Vertices = Vertices;
|
|
CallData->Triangles = Triangles;
|
|
CallData->Normals = Normals;
|
|
CallData->UV0 = UV0;
|
|
CallData->UV1 = UV1;
|
|
CallData->Colors = Colors;
|
|
CallData->Tangents = Tangents;
|
|
}
|
|
|
|
CallData->bCreateCollision = bCreateCollision;
|
|
CallData->UpdateFrequency = UpdateFrequency;
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(CreateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->CreateMeshSection(Data->SectionIndex, Data->Vertices, Data->Triangles, Data->Normals, Data->UV0, Data->UV1, Data->Colors,
|
|
Data->Tangents, Data->bCreateCollision, Data->UpdateFrequency, Data->UpdateFlags);
|
|
});
|
|
}
|
|
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, 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)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<FVector> Vertices;
|
|
TArray<FVector> Normals;
|
|
TArray<FVector2D> UV0;
|
|
TArray<FVector2D> UV1;
|
|
TArray<FColor> Colors;
|
|
TArray<FRuntimeMeshTangent> Tangents;
|
|
bool bCreateCollision = false;
|
|
EUpdateFrequency UpdateFrequency;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->Vertices = MoveTemp(Vertices);
|
|
CallData->Normals = MoveTemp(Normals);
|
|
CallData->UV0 = MoveTemp(UV0);
|
|
CallData->Colors = MoveTemp(Colors);
|
|
CallData->Tangents = MoveTemp(Tangents);
|
|
}
|
|
else
|
|
{
|
|
CallData->Vertices = Vertices;
|
|
CallData->Normals = Normals;
|
|
CallData->UV0 = UV0;
|
|
CallData->Colors = Colors;
|
|
CallData->Tangents = Tangents;
|
|
}
|
|
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->UpdateMeshSection(Data->SectionIndex, Data->Vertices, Data->Normals, Data->UV0, Data->Colors, Data->Tangents, Data->UpdateFlags);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, 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)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<FVector> Vertices;
|
|
TArray<FVector> Normals;
|
|
TArray<FVector2D> UV0;
|
|
TArray<FVector2D> UV1;
|
|
TArray<FColor> Colors;
|
|
TArray<FRuntimeMeshTangent> Tangents;
|
|
bool bCreateCollision = false;
|
|
EUpdateFrequency UpdateFrequency;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->Vertices = MoveTemp(Vertices);
|
|
CallData->Normals = MoveTemp(Normals);
|
|
CallData->UV0 = MoveTemp(UV0);
|
|
CallData->UV1 = MoveTemp(UV1);
|
|
CallData->Colors = MoveTemp(Colors);
|
|
CallData->Tangents = MoveTemp(Tangents);
|
|
}
|
|
else
|
|
{
|
|
CallData->Vertices = Vertices;
|
|
CallData->Normals = Normals;
|
|
CallData->UV0 = UV0;
|
|
CallData->UV1 = UV1;
|
|
CallData->Colors = Colors;
|
|
CallData->Tangents = Tangents;
|
|
}
|
|
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->UpdateMeshSection(Data->SectionIndex, Data->Vertices, Data->Normals, Data->UV0, Data->UV1, Data->Colors, Data->Tangents, Data->UpdateFlags);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, 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)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<FVector> Vertices;
|
|
TArray<int32> Triangles;
|
|
TArray<FVector> Normals;
|
|
TArray<FVector2D> UV0;
|
|
TArray<FColor> Colors;
|
|
TArray<FRuntimeMeshTangent> Tangents;
|
|
bool bCreateCollision = false;
|
|
EUpdateFrequency UpdateFrequency;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->Vertices = MoveTemp(Vertices);
|
|
CallData->Triangles = MoveTemp(Triangles);
|
|
CallData->Normals = MoveTemp(Normals);
|
|
CallData->UV0 = MoveTemp(UV0);
|
|
CallData->Colors = MoveTemp(Colors);
|
|
CallData->Tangents = MoveTemp(Tangents);
|
|
}
|
|
else
|
|
{
|
|
CallData->Vertices = Vertices;
|
|
CallData->Triangles = Triangles;
|
|
CallData->Normals = Normals;
|
|
CallData->UV0 = UV0;
|
|
CallData->Colors = Colors;
|
|
CallData->Tangents = Tangents;
|
|
}
|
|
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->UpdateMeshSection(Data->SectionIndex, Data->Vertices, Data->Triangles, Data->Normals, Data->UV0, Data->Colors, Data->Tangents, Data->UpdateFlags);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, 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)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<FVector> Vertices;
|
|
TArray<int32> Triangles;
|
|
TArray<FVector> Normals;
|
|
TArray<FVector2D> UV0;
|
|
TArray<FVector2D> UV1;
|
|
TArray<FColor> Colors;
|
|
TArray<FRuntimeMeshTangent> Tangents;
|
|
bool bCreateCollision = false;
|
|
EUpdateFrequency UpdateFrequency;
|
|
ESectionUpdateFlags UpdateFlags;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
|
|
{
|
|
CallData->Vertices = MoveTemp(Vertices);
|
|
CallData->Triangles = MoveTemp(Triangles);
|
|
CallData->Normals = MoveTemp(Normals);
|
|
CallData->UV0 = MoveTemp(UV0);
|
|
CallData->UV1 = MoveTemp(UV1);
|
|
CallData->Colors = MoveTemp(Colors);
|
|
CallData->Tangents = MoveTemp(Tangents);
|
|
}
|
|
else
|
|
{
|
|
CallData->Vertices = Vertices;
|
|
CallData->Triangles = Triangles;
|
|
CallData->Normals = Normals;
|
|
CallData->UV0 = UV0;
|
|
CallData->UV1 = UV1;
|
|
CallData->Colors = Colors;
|
|
CallData->Tangents = Tangents;
|
|
}
|
|
|
|
CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->UpdateMeshSection(Data->SectionIndex, Data->Vertices, Data->Triangles, Data->Normals, Data->UV0, Data->UV1, Data->Colors, Data->Tangents, Data->UpdateFlags);
|
|
});
|
|
}
|
|
|
|
|
|
|
|
/** Clear a section of the procedural mesh. */
|
|
static void ClearMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
};
|
|
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(ClearMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->ClearMeshSection(Data->SectionIndex);
|
|
});
|
|
}
|
|
|
|
/** Clear all mesh sections and reset to empty state */
|
|
static void ClearAllMeshSections(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
};
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(ClearAllMeshSections, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->ClearAllMeshSections();
|
|
});
|
|
}
|
|
|
|
|
|
/** Sets the tessellation triangles needed to correctly support tessellation on a section. */
|
|
static void SetSectionTessellationTriangles(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex,
|
|
const TArray<int32>& TessellationTriangles, bool bShouldMoveArray = false)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 SectionIndex;
|
|
TArray<int32> TessellationTriangles;
|
|
};
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->SectionIndex = SectionIndex;
|
|
|
|
if (bShouldMoveArray)
|
|
{
|
|
CallData->TessellationTriangles = MoveTemp(TessellationTriangles);
|
|
}
|
|
else
|
|
{
|
|
CallData->TessellationTriangles = TessellationTriangles;
|
|
}
|
|
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(SetSectionTessellationTriangles, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->SetSectionTessellationTriangles(Data->SectionIndex, Data->TessellationTriangles, true);
|
|
});
|
|
}
|
|
|
|
|
|
/** Sets the geometry for a collision only section */
|
|
static void SetMeshCollisionSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 CollisionSectionIndex,
|
|
const TArray<FVector>& Vertices, const TArray<int32>& Triangles)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 CollisionSectionIndex;
|
|
TArray<FVector> Vertices;
|
|
TArray<int32> Triangles;
|
|
};
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->CollisionSectionIndex = CollisionSectionIndex;
|
|
CallData->Vertices = Vertices;
|
|
CallData->Triangles = Triangles;
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(SetMeshCollisionSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->SetMeshCollisionSection(Data->CollisionSectionIndex, Data->Vertices, Data->Triangles);
|
|
});
|
|
}
|
|
|
|
/** Clears the geometry for a collision only section */
|
|
static void ClearMeshCollisionSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 CollisionSectionIndex)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 CollisionSectionIndex;
|
|
};
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->CollisionSectionIndex = CollisionSectionIndex;
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(ClearMeshCollisionSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->ClearMeshCollisionSection(Data->CollisionSectionIndex);
|
|
});
|
|
}
|
|
|
|
/** Clears the geometry for ALL collision only sections */
|
|
static void ClearAllMeshCollisionSections(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 CollisionSectionIndex;
|
|
};
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(ClearAllMeshCollisionSections, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->ClearAllMeshCollisionSections();
|
|
});
|
|
}
|
|
|
|
|
|
/** Add simple collision convex to this component */
|
|
static void AddCollisionConvexMesh(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, TArray<FVector> ConvexVerts)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
TArray<FVector> ConvexVerts;
|
|
};
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->ConvexVerts = ConvexVerts;
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(AddCollisionConvexMesh, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->AddCollisionConvexMesh(Data->ConvexVerts);
|
|
});
|
|
}
|
|
|
|
/** Add simple collision convex to this component */
|
|
static void ClearCollisionConvexMeshes(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
int32 CollisionSectionIndex;
|
|
};
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(ClearCollisionConvexMeshes, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->ClearCollisionConvexMeshes();
|
|
});
|
|
}
|
|
|
|
/** Function to replace _all_ simple collision in one go */
|
|
static void SetCollisionConvexMeshes(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, const TArray< TArray<FVector> >& ConvexMeshes)
|
|
{
|
|
struct FRMCAsyncData
|
|
{
|
|
TArray<TArray<FVector>> ConvexMeshes;
|
|
};
|
|
FRMCAsyncData* CallData = new FRMCAsyncData;
|
|
CallData->ConvexMeshes = ConvexMeshes;
|
|
|
|
RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(SetCollisionConvexMeshes, FRMCAsyncData, CallData, InRuntimeMeshComponent,
|
|
{
|
|
Mesh->SetCollisionConvexMeshes(Data->ConvexMeshes);
|
|
});
|
|
}
|
|
};
|