You're breathtaking!
This commit is contained in:
158
Source/Engine/Particles/ParticlesSimulation.cpp
Normal file
158
Source/Engine/Particles/ParticlesSimulation.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#include "ParticlesSimulation.h"
|
||||
#include "ParticleManager.h"
|
||||
#include "ParticleSystem.h"
|
||||
#include "ParticleEmitter.h"
|
||||
|
||||
ParticleEmitterInstance::ParticleEmitterInstance()
|
||||
{
|
||||
}
|
||||
|
||||
ParticleEmitterInstance::~ParticleEmitterInstance()
|
||||
{
|
||||
if (Buffer)
|
||||
{
|
||||
ParticleManager::RecycleParticleBuffer(Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEmitterInstance::ClearState()
|
||||
{
|
||||
Version = 0;
|
||||
Time = 0;
|
||||
SpawnModulesData.Clear();
|
||||
#if COMPILE_WITH_GPU_PARTICLES
|
||||
GPU.DeltaTime = 0.0f;
|
||||
GPU.SpawnCount = 0;
|
||||
#endif
|
||||
if (Buffer)
|
||||
{
|
||||
ParticleManager::RecycleParticleBuffer(Buffer);
|
||||
Buffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEmitterInstance::Sync(ParticleSystemInstance& systemInstance, ParticleSystem* system, int32 emitterIndex)
|
||||
{
|
||||
auto emitter = system->Emitters[emitterIndex].Get();
|
||||
|
||||
// Sync instance version
|
||||
if (Version != emitter->Graph.Version)
|
||||
{
|
||||
ClearState();
|
||||
Version = emitter->Graph.Version;
|
||||
systemInstance.ParametersVersion++;
|
||||
|
||||
// Synchronize parameters
|
||||
ParticleSystem::EmitterParameterOverrideKey key;
|
||||
key.First = emitterIndex;
|
||||
Parameters.Resize(emitter->Graph.Parameters.Count(), false);
|
||||
for (int32 i = 0; i < emitter->Graph.Parameters.Count(); i++)
|
||||
{
|
||||
auto& e = emitter->Graph.Parameters.At(i);
|
||||
key.Second = e.Identifier;
|
||||
if (!system->EmittersParametersOverrides.TryGet(key, Parameters[i]))
|
||||
Parameters[i] = e.Value;
|
||||
}
|
||||
|
||||
if (SpawnModulesData.Count() != emitter->Graph.SpawnModules.Count())
|
||||
{
|
||||
SpawnModulesData.Resize(emitter->Graph.SpawnModules.Count(), false);
|
||||
|
||||
SpawnerData data;
|
||||
data.SpawnCounter = 0;
|
||||
data.NextSpawnTime = 0;
|
||||
SpawnModulesData.SetAll(data);
|
||||
}
|
||||
}
|
||||
|
||||
// Sync buffer version
|
||||
if (Buffer && Buffer->Version != Version)
|
||||
{
|
||||
ParticleManager::RecycleParticleBuffer(Buffer);
|
||||
Buffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ParticleSystemInstance::~ParticleSystemInstance()
|
||||
{
|
||||
SAFE_DELETE_GPU_RESOURCE(GPUParticlesCountReadback);
|
||||
}
|
||||
|
||||
int32 ParticleSystemInstance::GetParticlesCount() const
|
||||
{
|
||||
int32 result = 0;
|
||||
|
||||
// CPU particles
|
||||
for (const auto& emitter : Emitters)
|
||||
{
|
||||
if (emitter.Buffer && emitter.Buffer->Mode == ParticlesSimulationMode::CPU)
|
||||
{
|
||||
result += emitter.Buffer->CPU.Count;
|
||||
}
|
||||
}
|
||||
|
||||
// GPU particles
|
||||
if (GPUParticlesCountReadback && GPUParticlesCountReadback->IsAllocated())
|
||||
{
|
||||
auto data = static_cast<uint32*>(GPUParticlesCountReadback->Map(GPUResourceMapMode::Read));
|
||||
for (const auto& emitter : Emitters)
|
||||
{
|
||||
if (emitter.Buffer && emitter.Buffer->Mode == ParticlesSimulationMode::GPU && emitter.Buffer->GPU.HasValidCount)
|
||||
{
|
||||
result += *data;
|
||||
}
|
||||
++data;
|
||||
}
|
||||
GPUParticlesCountReadback->Unmap();
|
||||
}
|
||||
else if (Emitters.HasItems())
|
||||
{
|
||||
// Initialize readback buffer (next GPU particles simulation update will copy the particle counters)
|
||||
if (!GPUParticlesCountReadback)
|
||||
GPUParticlesCountReadback = GPUDevice::Instance->CreateBuffer(TEXT("GPUParticlesCountReadback"));
|
||||
const auto desc = GPUBufferDescription::Buffer(Emitters.Count() * sizeof(uint32), GPUBufferFlags::None, PixelFormat::Unknown, nullptr, sizeof(uint32), GPUResourceUsage::StagingReadback);
|
||||
if (GPUParticlesCountReadback->Init(desc))
|
||||
{
|
||||
LOG(Error, "Failed to create GPU particles coun readback buffer.");
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ParticleSystemInstance::ClearState()
|
||||
{
|
||||
Version = 0;
|
||||
Time = 0;
|
||||
LastUpdateTime = -1;
|
||||
Emitters.Resize(0);
|
||||
if (GPUParticlesCountReadback)
|
||||
GPUParticlesCountReadback->ReleaseGPU();
|
||||
}
|
||||
|
||||
void ParticleSystemInstance::Sync(ParticleSystem* system)
|
||||
{
|
||||
// Prepare instance data
|
||||
if (Version != system->Version)
|
||||
{
|
||||
ClearState();
|
||||
Version = system->Version;
|
||||
ParametersVersion++;
|
||||
Emitters.Resize(system->Emitters.Count(), false);
|
||||
if (GPUParticlesCountReadback)
|
||||
GPUParticlesCountReadback->ReleaseGPU();
|
||||
}
|
||||
ASSERT(Emitters.Count() == system->Emitters.Count());
|
||||
}
|
||||
|
||||
bool ParticleSystemInstance::ContainsEmitter(ParticleEmitter* emitter) const
|
||||
{
|
||||
for (int32 i = 0; i < Emitters.Count(); i++)
|
||||
{
|
||||
if (Emitters[i].Buffer && Emitters[i].Buffer->Emitter == emitter)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user