Skip to content

Commit

Permalink
Made Add/Remove Particles more solid
Browse files Browse the repository at this point in the history
  • Loading branch information
LukasFratzl committed Oct 27, 2024
1 parent 3cd7445 commit b04bd91
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 64 deletions.
Binary file modified Content/Resources/FXF_TurboSequence_KillParticleByID_Lf.uasset
Binary file not shown.
Binary file modified Content/Resources/FXF_TurboSequence_UpdateParticle_Lf.uasset
Binary file not shown.
Binary file modified Content/Resources/FXS_TurboSequence_Mesh_Lf.uasset
Binary file not shown.
Binary file modified Content/Resources/MF_TurboSequence_PositionOffset_Lf.uasset
Binary file not shown.
4 changes: 2 additions & 2 deletions Source/TurboSequence_Lf/Private/AddRemoveTSInstancesTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ void AAddRemoveTSInstancesTest::Tick(float DeltaTime)

if (bIsVisibleOnAnyCamera)
{
if (!ATurboSequence_Manager_Lf::ContainsMeshDataInUpdateGroup_Concurrent(TestInstance.MeshData, 0))
if (!TestInstance.bSpawned)
{
TestInstance.MeshData = ATurboSequence_Manager_Lf::AddSkinnedMeshInstance_GameThread(TestInstance.UsedSpawnData, TestInstance.SpawnTransform, GetWorld());
if (TestInstance.MeshData.IsMeshDataValid())
Expand All @@ -119,7 +119,7 @@ void AAddRemoveTSInstancesTest::Tick(float DeltaTime)
}
else
{
if (ATurboSequence_Manager_Lf::ContainsMeshDataInUpdateGroup_Concurrent(TestInstance.MeshData, 0))
if (TestInstance.bSpawned)
{

if (ATurboSequence_Manager_Lf::RemoveSkinnedMeshInstance_GameThread(TestInstance.MeshData, GetWorld()))
Expand Down
125 changes: 89 additions & 36 deletions Source/TurboSequence_Lf/Private/TurboSequence_Manager_Lf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,64 +83,65 @@ void ATurboSequence_Manager_Lf::Tick(float DeltaTime)
continue;
}

// if (RenderData.Value.bChangedCollectionSizeThisFrame)
// {
// UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayInt32(
// NiagaraComponent, RenderData.Value.GetParticleIDAddName(), RenderData.Value.ParticleIDs);
// RenderData.Value.bChangedCollectionSizePreviousFrame = true;
// UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayInt32(
// NiagaraComponent, RenderData.Value.GetParticleRemoveName(), RenderData.Value.ParticlesToRemove);
// }
if (RenderData.Value.bChangedCollectionSizeThisFrame)
{
// UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayInt32(
// NiagaraComponent, RenderData.Value.GetParticleIDName(), RenderData.Value.ParticleIDs);
RenderData.Value.bChangedCollectionSizePreviousFrame = true;
// UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayBool(
// NiagaraComponent, RenderData.Value.GetParticleRemoveName(), RenderData.Value.ParticlesToRemove);
}

NiagaraComponent->SetVariableBool("User.CollectionChangedThisFrame",
RenderData.Value.bChangedCollectionSizeThisFrame || RenderData.Value.
bChangedCollectionSizePreviousFrame);

UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayInt32(
NiagaraComponent, RenderData.Value.GetParticleIDName(), RenderData.Value.ParticleIDs);

// UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayInt32(
// NiagaraComponent, RenderData.Value.GetParticleIDRemoveName(), RenderData.Value.ParticleRemoveIDs);

UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayInt32(
NiagaraComponent, RenderData.Value.GetParticleRemoveName(), RenderData.Value.ParticlesToRemove);
if (RenderData.Value.bChangedCollectionSizePreviousFrame && !RenderData.Value.
bChangedCollectionSizeThisFrame)
{
RenderData.Value.bChangedCollectionSizePreviousFrame = false;
// UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayInt32(
// NiagaraComponent, RenderData.Value.GetParticleIDName(), RenderData.Value.ParticleIDs);

// UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayBool(
// NiagaraComponent, RenderData.Value.GetParticleRemoveName(), RenderData.Value.ParticlesToRemove);
}

UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayUInt8(
NiagaraComponent, RenderData.Value.GetLodName(), RenderData.Value.ParticleLevelOfDetails);
// UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayBool(
// NiagaraComponent, RenderData.Value.GetParticleRemoveName(), RenderData.Value.ParticlesToRemove);


if (RenderData.Value.bChangedLodCollectionThisFrame || RenderData.Value.bChangedCollectionSizeThisFrame)
{
UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayUInt8(
NiagaraComponent, RenderData.Value.GetLodName(), RenderData.Value.ParticleLevelOfDetails);
}

UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayFloat(
NiagaraComponent, RenderData.Value.GetCustomDataName(), RenderData.Value.ParticleCustomData);
if (RenderData.Value.bChangedCustomDataCollectionThisFrame || RenderData.Value.
bChangedCollectionSizeThisFrame)
{
UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayFloat(
NiagaraComponent, RenderData.Value.GetCustomDataName(), RenderData.Value.ParticleCustomData);
}

UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayPosition(
NiagaraComponent, RenderData.Value.GetPositionName(), RenderData.Value.ParticlePositions);
if (RenderData.Value.bChangedPositionCollectionThisFrame || RenderData.Value.
bChangedCollectionSizeThisFrame)
{
UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayPosition(
NiagaraComponent, RenderData.Value.GetPositionName(), RenderData.Value.ParticlePositions);
}

UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayVector4(
NiagaraComponent, RenderData.Value.GetRotationName(), RenderData.Value.ParticleRotations);
if (RenderData.Value.bChangedRotationCollectionThisFrame || RenderData.Value.
bChangedCollectionSizeThisFrame)
{
UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayVector4(
NiagaraComponent, RenderData.Value.GetRotationName(), RenderData.Value.ParticleRotations);
}

UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayVector(
NiagaraComponent, RenderData.Value.GetScaleName(), RenderData.Value.ParticleScales);
if (RenderData.Value.bChangedScaleCollectionThisFrame || RenderData.Value.bChangedCollectionSizeThisFrame)
{
UNiagaraDataInterfaceArrayFunctionLibrary::SetNiagaraArrayVector(
NiagaraComponent, RenderData.Value.GetScaleName(), RenderData.Value.ParticleScales);
}

RenderData.Value.bChangedLodCollectionThisFrame = false;
Expand All @@ -151,14 +152,22 @@ void ATurboSequence_Manager_Lf::Tick(float DeltaTime)

RenderData.Value.bChangedCollectionSizeThisFrame = false;
// ParticleIDs needs to have the last frame valid Indices
if (RenderData.Value.ParticlesToRemove.Num())
{
for (const int32 ParticleIDToRemove : RenderData.Value.ParticlesToRemove)
{
RenderData.Value.ParticleIDs.Remove(ParticleIDToRemove);
}
}
RenderData.Value.ParticlesToRemove.Empty();
// if (RenderData.Value.ParticlesToRemoveIndices.Num())
// {
// for (const int32 ParticleIndexToRemove : RenderData.Value.ParticlesToRemoveIndices)
// {
// RenderData.Value.ParticlesToRemove.RemoveAt(ParticleIndexToRemove);
// }
// }
// const int32 NumRemove = RenderData.Value.ParticlesToRemove.Num();
// for (int32 i = NumRemove - GET1_NUMBER; i >= GET0_NUMBER; --i)
// {
// if (RenderData.Value.ParticlesToRemove[i])
// {
// RenderData.Value.ParticlesToRemove.RemoveAt(i);
// }
// }
// RenderData.Value.ParticlesToRemoveIndices.Empty();

const FBox RendererBounds = FBox(RenderData.Value.MinBounds, RenderData.Value.MaxBounds);
NiagaraComponent->SetEmitterFixedBounds(RenderData.Value.GetEmitterName(), RendererBounds);
Expand All @@ -167,6 +176,49 @@ void ATurboSequence_Manager_Lf::Tick(float DeltaTime)
// so we add a default camera bounds extend to it for the next frame
FTurboSequence_Utility_Lf::UpdateCameraRendererBounds(RenderData.Value, GlobalLibrary.CameraViews,
GET100_NUMBER * GET10_NUMBER);

// for (const int32 MeshIDToRemove : RenderData.Value.MeshIDsToRemove)
// {
// const int32 InstanceIndex = RenderData.Value.InstanceMap[MeshIDToRemove];
// // RenderData.ParticlePositions[InstanceIndex] = FVector(-100000, -100000, -100000); // Remove Point
//
// RenderData.Value.InstanceMap.Remove(MeshIDToRemove);
// for (TTuple<int32, int32>& Item : RenderData.Value.InstanceMap)
// {
// if (Item.Value > InstanceIndex)
// {
// Item.Value--;
// }
// }
//
//
// RenderData.Value.ParticlePositions.RemoveAt(InstanceIndex);
// RenderData.Value.ParticleRotations.RemoveAt(InstanceIndex);
// RenderData.Value.ParticleScales.RemoveAt(InstanceIndex);
// RenderData.Value.ParticleLevelOfDetails.RemoveAt(InstanceIndex);
// //RenderData.ParticleIDs.RemoveAt(InstanceIndex);
// RenderData.Value.ParticlesToRemove.RemoveAt(InstanceIndex);
//
// // Removing IDs happens on the removal of this Array in Tick()
// //RenderData.ParticleIDMap.Remove(Runtime.GetMeshID());
// // RenderData.ParticlesToRemove[InstanceIndex] = true;
// // RenderData.ParticlesToRemoveIndices.Add(InstanceIndex);
//
// for (int16 i = FTurboSequence_Helper_Lf::NumInstanceCustomData - GET1_NUMBER; i >= GET0_NUMBER; --i)
// {
// int32 CustomDataIndex = InstanceIndex * FTurboSequence_Helper_Lf::NumInstanceCustomData + i;
// RenderData.Value.ParticleCustomData.RemoveAt(CustomDataIndex);
// }
// }
//RenderData.Value.MeshIDsToRemove.Empty();

// for (TTuple<int32, int32>& Item : RenderData.Value.InstanceMap)
// {
// if (RenderData.Value.InstanceMapCopy.Contains(Item.Key))
// {
// Item.Value = RenderData.Value.InstanceMapCopy[Item.Key];
// }
// }
}
}

Expand Down Expand Up @@ -222,6 +274,7 @@ void ATurboSequence_Manager_Lf::Tick(float DeltaTime)
FootprintAsset.Key->OnPostManagerUpdated_GameThread(DeltaTime);
}

GlobalLibrary.BlackListedMeshIDs.Empty();
if (GlobalLibrary.RuntimeSkinnedMeshes.Num())
{
// Otherwise the Critical Section grow in size until we run out of memory when we don't refresh it...
Expand Down Expand Up @@ -442,7 +495,7 @@ int32 ATurboSequence_Manager_Lf::AddSkinnedMeshInstance_GameThread(
}

// Now it's time to add the actual instance
FSkinnedMeshRuntime_Lf Runtime = FSkinnedMeshRuntime_Lf(GlobalLibrary.RuntimeSkinnedMeshes, FromAsset,
FSkinnedMeshRuntime_Lf Runtime = FSkinnedMeshRuntime_Lf(GlobalLibrary.RuntimeSkinnedMeshes, GlobalLibrary.BlackListedMeshIDs, FromAsset,
OverrideMeshID);
FSkinnedMeshRuntime_RenderThread_Lf Runtime_RenderThread = FSkinnedMeshRuntime_RenderThread_Lf(
Runtime.GetMeshID(), FromAsset);
Expand Down Expand Up @@ -585,7 +638,7 @@ bool ATurboSequence_Manager_Lf::RemoveSkinnedMeshInstance_GameThread(int32 MeshI
Library_RenderThread);

FSkinnedMeshReference_Lf& Reference = GlobalLibrary.PerReferenceData[Runtime.DataAsset];
FTurboSequence_Utility_Lf::RemoveRenderInstance(Reference, Runtime, ThreadContext->CriticalSection);
FTurboSequence_Utility_Lf::RemoveRenderInstance(Reference, Runtime, ThreadContext->CriticalSection, GlobalLibrary);

if (const FRenderData_Lf& RenderData = Reference.RenderData[Runtime.MaterialsHash]; !RenderData.InstanceMap.Num())
{
Expand Down
33 changes: 23 additions & 10 deletions Source/TurboSequence_Lf/Private/TurboSequence_Utility_Lf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1454,9 +1454,11 @@ void FTurboSequence_Utility_Lf::AddRenderInstance(FSkinnedMeshReference_Lf& Refe

const int32 InstanceIndex = RenderData.InstanceMap.Num();
RenderData.InstanceMap.Add(Runtime.GetMeshID(), InstanceIndex);
// const int32 InstanceCopyIndex = RenderData.InstanceMapCopy.Num();
// RenderData.InstanceMapCopy.Add(Runtime.GetMeshID(), InstanceCopyIndex);
//RenderData.ParticleRemoveIDs.Add(RenderData.GetUniqueID());
RenderData.ParticleIDMap.Add(Runtime.GetMeshID(), RenderData.GetUniqueID());
RenderData.ParticleIDs.Add(RenderData.GetUniqueID());
// RenderData.ParticleIDMap.Add(Runtime.GetMeshID(), RenderData.GetUniqueID());
// RenderData.ParticleIDs.Add(RenderData.GetUniqueID());

RenderData.ParticlePositions.Add(WorldSpaceTransform.GetLocation());
RenderData.ParticleRotations.Add(
Expand All @@ -1468,7 +1470,9 @@ void FTurboSequence_Utility_Lf::AddRenderInstance(FSkinnedMeshReference_Lf& Refe

RenderData.ParticleCustomData.AddDefaulted(FTurboSequence_Helper_Lf::NumInstanceCustomData);

RenderData.IncrementUniqueID(); // Use the same ID as Niagara
//RenderData.IncrementUniqueID(); // Use the same ID as Niagara
//RenderData.ParticlesToRemove.Add(false);


RenderData.bChangedCollectionSizeThisFrame = true;
}
Expand All @@ -1491,31 +1495,40 @@ void FTurboSequence_Utility_Lf::CleanNiagaraRenderer(

void FTurboSequence_Utility_Lf::RemoveRenderInstance(FSkinnedMeshReference_Lf& Reference,
const FSkinnedMeshRuntime_Lf& Runtime,
FCriticalSection& CriticalSection)
FCriticalSection& CriticalSection,
FSkinnedMeshGlobalLibrary_Lf& Library)
{
FScopeLock Lock(&CriticalSection);

FRenderData_Lf& RenderData = Reference.RenderData[Runtime.MaterialsHash];

//RenderData.MeshIDsToRemove.Add(Runtime.GetMeshID());
Library.BlackListedMeshIDs.Add(Runtime.GetMeshID(), false);

const int32 InstanceIndex = RenderData.InstanceMap[Runtime.GetMeshID()];
//RenderData.ParticlesToRemove[InstanceIndex] = true;
//RenderData.ParticlePositions[InstanceIndex] = FVector(-100000, -100000, -100000); // Remove Point

RenderData.InstanceMap.Remove(Runtime.GetMeshID());
for (TTuple<int32, int32>& Instance : RenderData.InstanceMap)
for (TTuple<int32, int32>& Item : RenderData.InstanceMap)
{
if (Instance.Value > InstanceIndex)
if (Item.Value > InstanceIndex)
{
Instance.Value--;
Item.Value--;
}
}

//
//
RenderData.ParticlePositions.RemoveAt(InstanceIndex);
RenderData.ParticleRotations.RemoveAt(InstanceIndex);
RenderData.ParticleScales.RemoveAt(InstanceIndex);
RenderData.ParticleLevelOfDetails.RemoveAt(InstanceIndex);
//RenderData.ParticleIDs.RemoveAt(InstanceIndex);

// Removing IDs happens on the removal of this Array in Tick()
RenderData.ParticlesToRemove.Add(RenderData.ParticleIDMap[Runtime.GetMeshID()]);
RenderData.ParticleIDMap.Remove(Runtime.GetMeshID());
//RenderData.ParticleIDMap.Remove(Runtime.GetMeshID());
// RenderData.ParticlesToRemove[InstanceIndex] = true;
// RenderData.ParticlesToRemoveIndices.Add(InstanceIndex);

for (int16 i = FTurboSequence_Helper_Lf::NumInstanceCustomData - GET1_NUMBER; i >= GET0_NUMBER; --i)
{
Expand Down
36 changes: 21 additions & 15 deletions Source/TurboSequence_Lf/Public/TurboSequence_Data_Lf.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,10 @@ struct TURBOSEQUENCE_LF_API FRenderData_Lf

// ID
TMap<int32, int32> InstanceMap; // < MeshID | Renderer Instance Index >
TArray<int32> ParticleIDs; // < Unique ID > -> Used internally for Niagara finding the Index
TMap<int32, int32> ParticleIDMap; // < MeshID | UniqueID >
//TMap<int32, int32> InstanceMapCopy; // < MeshID | Renderer Instance Index > Needed to Keep the Indices correct
//TArray<int32> MeshIDsToRemove;
//TArray<int32> ParticleIDs; // < Unique ID > -> Used internally for Niagara finding the Index
//TMap<int32, int32> ParticleIDMap; // < MeshID | UniqueID >

// Transform
TArray<FVector> ParticlePositions;
Expand All @@ -97,7 +99,8 @@ struct TURBOSEQUENCE_LF_API FRenderData_Lf

// Culling and Visibility
TArray<uint8> ParticleLevelOfDetails; // Index 32 -> Not Visible
TArray<int32> ParticlesToRemove;
//TArray<bool> ParticlesToRemove;
// TArray<int32> ParticlesToRemoveIndices;

// Custom Data
TArray<float> ParticleCustomData;
Expand Down Expand Up @@ -127,18 +130,18 @@ struct TURBOSEQUENCE_LF_API FRenderData_Lf
FName CustomDataName;
FName ParticleRemoveName;

int32 UniqueID = 0;
// int32 UniqueID = 0;

public:
FORCEINLINE int32 GetUniqueID() const
{
return UniqueID;
}

FORCEINLINE void IncrementUniqueID()
{
UniqueID++;
}
// FORCEINLINE int32 GetUniqueID() const
// {
// return UniqueID;
// }
//
// FORCEINLINE void IncrementUniqueID()
// {
// UniqueID++;
// }

FORCEINLINE FName& GetEmitterName()
{
Expand Down Expand Up @@ -606,18 +609,19 @@ struct TURBOSEQUENCE_LF_API FSkinnedMeshRuntime_Lf : public FSkinnedMeshRuntime_
}

explicit FSkinnedMeshRuntime_Lf(const TMap<int32, FSkinnedMeshRuntime_Lf>& InputCollection,
const TMap<int32, bool>& BlacklistedMeshIDs,
const TObjectPtr<UTurboSequence_MeshAsset_Lf> Asset,
const int32 OverrideMeshID = INDEX_NONE)
{
if (OverrideMeshID > INDEX_NONE && !InputCollection.Contains(OverrideMeshID))
if (OverrideMeshID > INDEX_NONE && !InputCollection.Contains(OverrideMeshID) && !BlacklistedMeshIDs.Contains(OverrideMeshID))
{
MeshID = OverrideMeshID;
}
else
{
MeshID = FMath::RandRange(0, INT32_MAX - 1);
MeshID++;
while (InputCollection.Contains(MeshID) || (!InputCollection.Contains(MeshID) && MeshID < GET0_NUMBER))
while ((InputCollection.Contains(MeshID) || BlacklistedMeshIDs.Contains(MeshID)) || ((!InputCollection.Contains(MeshID) && !BlacklistedMeshIDs.Contains(MeshID)) && MeshID < GET0_NUMBER))
{
MeshID = FMath::RandRange(0, INT32_MAX - 1);
MeshID++;
Expand Down Expand Up @@ -786,6 +790,8 @@ struct TURBOSEQUENCE_LF_API FSkinnedMeshGlobalLibrary_Lf

TMap<int32, FSkinnedMeshRuntime_Lf> RuntimeSkinnedMeshes;
TArray<int32> RuntimeSkinnedMeshesHashMap;
TMap<int32, bool> BlackListedMeshIDs;

// < MeshID | Data >
TMap<int32, FTurboSequence_MinimalMeshData_Lf> MeshIDToMinimalData;

Expand Down
3 changes: 2 additions & 1 deletion Source/TurboSequence_Lf/Public/TurboSequence_Utility_Lf.h
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,8 @@ class TURBOSEQUENCE_LF_API FTurboSequence_Utility_Lf
*/
static void RemoveRenderInstance(FSkinnedMeshReference_Lf& Reference,
const FSkinnedMeshRuntime_Lf& Runtime,
FCriticalSection& CriticalSection);
FCriticalSection& CriticalSection,
FSkinnedMeshGlobalLibrary_Lf& Library);
/**
* Updates the level of detail for a render instance concurrently.
*
Expand Down

0 comments on commit b04bd91

Please sign in to comment.