BVB Source Codes

CRYENGINE Show FeatureSpawn.cpp Source code

Return Download CRYENGINE: download FeatureSpawn.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //  Created:     29/09/2014 by Filipe amim
  5. //  Description:
  6. // -------------------------------------------------------------------------
  7. //
  8. ////////////////////////////////////////////////////////////////////////////
  9.  
  10. #include "StdAfx.h"
  11. #include "ParticleSystem/ParticleFeature.h"
  12. #include "ParamMod.h"
  13. #include <CryRenderer/IGpuParticles.h>
  14.  
  15. CRY_PFX2_DBG
  16.  
  17. namespace pfx2
  18. {
  19.  
  20. typedef TValue<float, USoftLimit<15000>> UFloatCount;
  21.  
  22. struct CRY_ALIGN(CRY_PFX2_PARTICLES_ALIGNMENT) SSpawnData
  23. {
  24.         float m_amount;
  25.         float m_spawned;
  26.         float m_delay;
  27.         float m_duration;
  28.         float m_restart;
  29.         float m_timer;
  30. };
  31.  
  32. // PFX2_TODO : not enough self documented code. Refactor!
  33.  
  34. class CParticleFeatureSpawnBase : public CParticleFeature
  35. {
  36. protected:
  37.         typedef CParamMod<SModInstanceCounter, UFloatCount> TCountParam;
  38.         typedef CParamMod<SModInstanceTimer, UFloat10>      TTimeParams;
  39.  
  40. public:
  41.         CParticleFeatureSpawnBase(gpu_pfx2::EGpuFeatureType gpuType)
  42.                 : m_amount(1.0f)
  43.                 , m_delay(0.0)
  44.                 , m_duration(0.0f)
  45.                 , m_restart(1.0f)
  46.                 , m_useDuration(false)
  47.                 , m_useRestart(false)
  48.                 , CParticleFeature(gpuType) {}
  49.  
  50.         virtual EFeatureType GetFeatureType() override
  51.         {
  52.                 return EFT_Spawn;
  53.         }
  54.  
  55.         virtual void AddToComponent(CParticleComponent* pComponent, SComponentParams* pParams) override
  56.         {
  57.                 pComponent->AddToUpdateList(EUL_InitSubInstance, this);
  58.                 pComponent->AddToUpdateList(EUL_Spawn, this);
  59.                 m_spawnDataOff = pComponent->AddInstanceData(sizeof(SSpawnData));
  60.                 m_amount.AddToComponent(pComponent, this);
  61.                 m_delay.AddToComponent(pComponent, this);
  62.                 m_duration.AddToComponent(pComponent, this);
  63.                 m_restart.AddToComponent(pComponent, this);
  64.  
  65.                 if (auto pInt = GetGpuInterface())
  66.                 {
  67.                         gpu_pfx2::SFeatureParametersSpawn params;
  68.                         params.amount = m_amount.GetBaseValue();
  69.                         params.delay = m_delay.GetBaseValue();
  70.                         params.duration = m_duration.GetBaseValue();
  71.                         params.restart = m_restart.GetBaseValue();
  72.                         params.useDelay = m_delay.GetBaseValue() > 0.0f;
  73.                         params.useDuration = m_useDuration;
  74.                         params.useRestart = m_useRestart;
  75.                         pInt->SetParameters(params);
  76.                 }
  77.         }
  78.  
  79.         virtual void InitSubInstance(CParticleComponentRuntime* pComponentRuntime, size_t firstInstance, size_t lastInstance) override
  80.         {
  81.                 SUpdateRange range;
  82.                 range.m_firstParticleId = 0;
  83.                 range.m_lastParticleId = lastInstance - firstInstance;
  84.                 SUpdateContext context(pComponentRuntime, range);
  85.                 RestartInstances(context, firstInstance, lastInstance, true);
  86.         }
  87.  
  88.         virtual void Serialize(Serialization::IArchive& ar) override
  89.         {
  90.                 struct SEnabledValue
  91.                 {
  92.                         SEnabledValue(TTimeParams& value, bool& state)
  93.                                 : m_value(value), m_state(state) {}
  94.                         TTimeParams& m_value;
  95.                         bool&        m_state;
  96.                         void         Serialize(Serialization::IArchive& ar)
  97.                         {
  98.                                 ar(m_state, "State", "^");
  99.                                 if (m_state)
  100.                                         ar(m_value, "Value", "^");
  101.                                 else
  102.                                         ar(m_value, "Value", "!^");
  103.                         }
  104.                 };
  105.  
  106.                 CParticleFeature::Serialize(ar);
  107.                 ar(m_amount, "Amount", "Amount");
  108.  
  109.                 if (ar.isInput() && GetVersion(ar) < 9)
  110.                 {
  111.                         bool useDelay = false;
  112.                         ar(SEnabledValue(m_delay, useDelay), "Delay", "Delay");
  113.                         if (!useDelay)
  114.                                 m_delay = TTimeParams(0.0f);
  115.                 }
  116.                 else
  117.                 {
  118.                         ar(m_delay, "Delay", "Delay");
  119.                 }
  120.                 ar(SEnabledValue(m_duration, m_useDuration), "Duration", "Duration");
  121.                 if (m_useDuration)
  122.                         ar(SEnabledValue(m_restart, m_useRestart), "Restart", "Restart");
  123.         }
  124.  
  125.         void UpdateAmounts(const SUpdateContext& context, Array<float, uint> amounts) const {}
  126.  
  127. protected:
  128.         void SetUseDuration(bool value) { m_useDuration = value; }
  129.  
  130.         template<typename Impl>
  131.         void SpawnParticlesT(Impl& impl, const SUpdateContext& context)
  132.         {
  133.                 CRY_PFX2_PROFILE_DETAIL;
  134.  
  135.                 CParticleComponentRuntime& runtime = context.m_runtime;
  136.                 const size_t numInstances = runtime.GetNumInstances();
  137.                 if (numInstances == 0)
  138.                         return;
  139.  
  140.                 const float dT = context.m_deltaTime;
  141.                 const float invDT = dT ? 1.0f / dT : 0.0f;
  142.                 SUpdateRange range(0, numInstances);
  143.  
  144.                 if (m_useRestart)
  145.                         RestartInstances(context, 0, numInstances + 1, false);
  146.  
  147.                 TFloatArray amounts(*context.m_pMemHeap, numInstances);
  148.                 for (size_t i = 0; i < numInstances; ++i)
  149.                 {
  150.                         SSpawnData* pSpawn = GetSpawnData(runtime, i);
  151.                         amounts[i] = pSpawn->m_amount * context.m_params.m_scaleParticleCount;
  152.                 }
  153.                 m_amount.ModifyUpdate(context, amounts.data(), range);
  154.  
  155.                 impl.UpdateAmounts(context, amounts);
  156.  
  157.                 for (size_t i = 0; i < numInstances; ++i)
  158.                 {
  159.                         SSpawnData* pSpawn = GetSpawnData(runtime, i);
  160.  
  161.                         const float startTime = max(pSpawn->m_timer, pSpawn->m_delay);
  162.                         const float endTime = min(pSpawn->m_timer + dT, pSpawn->m_delay + pSpawn->m_duration);
  163.                         const float spawnTime = endTime - startTime;
  164.                         const float amount = amounts[i];
  165.  
  166.                         if (spawnTime >= 0.0f && amount > 0.0f)
  167.                         {
  168.                                 auto& instance = runtime.GetInstance(i);
  169.  
  170.                                 CParticleContainer::SSpawnEntry entry = {};
  171.                                 entry.m_parentId = instance.m_parentId;
  172.                                 entry.m_ageBegin = (pSpawn->m_timer - startTime) * invDT;
  173.  
  174.                                 const float spawnedBefore = pSpawn->m_spawned;
  175.  
  176.                                 impl.UpdateSpawnInfo(*pSpawn, entry, context, amount, spawnTime);
  177.  
  178.                                 entry.m_count = uint(ceil_tpl(pSpawn->m_spawned) - ceil_tpl(spawnedBefore));
  179.  
  180.                                 const float spawnPast = 1.0f - (spawnedBefore - floor_tpl(spawnedBefore));
  181.                                 entry.m_ageBegin += spawnPast * entry.m_ageIncrement - 1.0f;
  182.                                 entry.m_fractionBegin = floor_tpl(spawnedBefore) * entry.m_fractionCounter + entry.m_fractionCounter;
  183.  
  184.                                 runtime.SpawnParticles(entry);
  185.                         }
  186.  
  187.                         pSpawn->m_timer += context.m_deltaTime;
  188.                 }
  189.         }
  190.  
  191.         void RestartInstances(const SUpdateContext& context, size_t firstInstance, size_t lastInstance, bool restartAll)
  192.         {
  193.                 CRY_PFX2_PROFILE_DETAIL;
  194.  
  195.                 const size_t numInstances = lastInstance - firstInstance;
  196.                 CParticleComponentRuntime& runtime = context.m_runtime;
  197.  
  198.                 typedef TParticleHeap::Array<size_t> TIndicesArray;
  199.                 TIndicesArray indicesArray(*context.m_pMemHeap);
  200.                 indicesArray.reserve(numInstances);
  201.                 if (restartAll)
  202.                 {
  203.                         indicesArray.resize(numInstances);
  204.                         for (size_t i = 0; i < numInstances; ++i)
  205.                                 indicesArray[i] = firstInstance + i;
  206.                 }
  207.                 else
  208.                 {
  209.                         for (size_t i = 0; i < numInstances; ++i)
  210.                         {
  211.                                 const size_t idx = i + firstInstance;
  212.                                 SSpawnData* pSpawn = GetSpawnData(runtime, idx);
  213.                                 pSpawn->m_restart -= context.m_deltaTime;
  214.                                 if (pSpawn->m_restart <= 0.0f)
  215.                                         indicesArray.push_back(idx);
  216.                         }
  217.                 }
  218.  
  219.                 if (indicesArray.empty())
  220.                         return;
  221.  
  222.                 const uint numRestarts = indicesArray.size();
  223.                 SUpdateRange restartRange;
  224.                 restartRange.m_firstParticleId = 0;
  225.                 restartRange.m_lastParticleId = numRestarts;
  226.                 TFloatArray amounts(*context.m_pMemHeap, numRestarts);
  227.                 TFloatArray delays(*context.m_pMemHeap, numRestarts);
  228.                 TFloatArray durations(*context.m_pMemHeap, numRestarts);
  229.                 TFloatArray restarts(*context.m_pMemHeap, numRestarts);
  230.                 m_amount.ModifyInit(context, amounts.data(), restartRange);
  231.                 m_delay.ModifyInit(context, delays.data(), restartRange);
  232.                 if (m_useDuration)
  233.                         m_duration.ModifyInit(context, durations.data(), restartRange);
  234.                 if (m_useRestart)
  235.                         m_restart.ModifyInit(context, restarts.data(), restartRange);
  236.  
  237.                 for (size_t i = 0; i < numRestarts; ++i)
  238.                 {
  239.                         const size_t idx = indicesArray[i];
  240.                         SSpawnData* pSpawn = GetSpawnData(runtime, idx);
  241.                         pSpawn->m_timer = 0.0f;
  242.                         pSpawn->m_spawned = -FLT_EPSILON;
  243.                         pSpawn->m_amount = amounts[i];
  244.                         pSpawn->m_delay = delays[i];
  245.                         pSpawn->m_duration = m_useDuration ? durations[i] : gInfinity;
  246.                         pSpawn->m_restart = m_useRestart ? restarts[i] : gInfinity;
  247.                 }
  248.         }
  249.  
  250. private:
  251.         SSpawnData* GetSpawnData(CParticleComponentRuntime& runtime, size_t idx) { return runtime.GetSubInstanceData<SSpawnData>(idx, m_spawnDataOff); }
  252.  
  253. private:
  254.         TCountParam         m_amount;
  255.         TTimeParams         m_delay;
  256.         TTimeParams         m_duration;
  257.         TTimeParams         m_restart;
  258.         TInstanceDataOffset m_spawnDataOff;
  259.         bool                m_useDuration;
  260.         bool                m_useRestart;
  261. };
  262.  
  263. class CFeatureSpawnCount : public CParticleFeatureSpawnBase
  264. {
  265. public:
  266.         CRY_PFX2_DECLARE_FEATURE
  267.  
  268.         CFeatureSpawnCount()
  269.                 : CParticleFeatureSpawnBase(gpu_pfx2::eGpuFeatureType_SpawnCount)
  270.         {
  271.                 // Default duration = 0 for SpawnCount
  272.                 SetUseDuration(true);
  273.         }
  274.  
  275.         virtual void Serialize(Serialization::IArchive& ar) override
  276.         {
  277.                 CParticleFeatureSpawnBase::Serialize(ar);
  278.                 if (GetVersion(ar) < 9)
  279.                 {
  280.                         // Infinite lifetime was impossible. Default disabled behavior was lifetime = 0.
  281.                         SetUseDuration(true);
  282.                 }
  283.         }
  284.  
  285.         virtual void SpawnParticles(const SUpdateContext& context) override
  286.         {
  287.                 SpawnParticlesT(*this, context);
  288.         }
  289.  
  290.         ILINE void UpdateSpawnInfo(SSpawnData& spawn, CParticleContainer::SSpawnEntry& entry, const SUpdateContext& context, float amount, float dt) const
  291.         {
  292.                 const float spawnTime = min(context.m_params.m_baseParticleLifeTime, spawn.m_duration);
  293.                 if (spawnTime > 0.0f)
  294.                 {
  295.                         const float rate = amount * rcp_fast(spawnTime);
  296.                         spawn.m_spawned += rate * dt;
  297.                         entry.m_ageIncrement = rcp_safe(rate * context.m_deltaTime);
  298.                 }
  299.                 else
  300.                 {
  301.                         spawn.m_spawned = amount;
  302.                         entry.m_ageIncrement = 0.0f;
  303.                 }
  304.                 entry.m_fractionCounter = rcp_fast(max(amount - 1.0f, 1.0f));
  305.         }
  306. };
  307.  
  308. CRY_PFX2_IMPLEMENT_FEATURE(CParticleFeature, CFeatureSpawnCount, "Spawn", "Count", colorSpawn);
  309.  
  310. //////////////////////////////////////////////////////////////////////////
  311.  
  312. SERIALIZATION_DECLARE_ENUM(ESpawnRateMode,
  313.                            ParticlesPerSecond,
  314.                            _SecondPerParticle, SecondsPerParticle = _SecondPerParticle
  315.                            )
  316.  
  317. class CFeatureSpawnRate : public CParticleFeatureSpawnBase
  318. {
  319. public:
  320.         CRY_PFX2_DECLARE_FEATURE
  321.  
  322.         CFeatureSpawnRate()
  323.                 : m_mode(ESpawnRateMode::ParticlesPerSecond)
  324.                 , CParticleFeatureSpawnBase(gpu_pfx2::eGpuFeatureType_SpawnRate)
  325.         {}
  326.  
  327.         virtual void AddToComponent(CParticleComponent* pComponent, SComponentParams* pParams) override
  328.         {
  329.                 if (GetGpuInterface())
  330.                 {
  331.                         gpu_pfx2::SFeatureParametersSpawnMode params;
  332.                         params.mode = (m_mode == ESpawnRateMode::ParticlesPerSecond
  333.                                        ? gpu_pfx2::ESpawnRateMode::ParticlesPerSecond
  334.                                        : gpu_pfx2::ESpawnRateMode::SecondPerParticle);
  335.                         GetGpuInterface()->SetParameters(params);
  336.                 }
  337.  
  338.                 CParticleFeatureSpawnBase::AddToComponent(pComponent, pParams);
  339.         }
  340.  
  341.         virtual void Serialize(Serialization::IArchive& ar) override
  342.         {
  343.                 CParticleFeatureSpawnBase::Serialize(ar);
  344.                 ar(m_mode, "Mode", "Mode");
  345.         }
  346.  
  347.         virtual void SpawnParticles(const SUpdateContext& context) override
  348.         {
  349.                 SpawnParticlesT(*this, context);
  350.         }
  351.  
  352.         ILINE void UpdateSpawnInfo(SSpawnData& spawn, CParticleContainer::SSpawnEntry& entry, const SUpdateContext& context, float amount, float dt) const
  353.         {
  354.                 const float spawned = dt * (m_mode == ESpawnRateMode::ParticlesPerSecond ? amount : rcp(amount));
  355.                 spawn.m_spawned += spawned;
  356.                 entry.m_ageIncrement = rcp_safe(spawned);
  357.         }
  358.  
  359. private:
  360.         ESpawnRateMode m_mode;
  361. };
  362.  
  363. CRY_PFX2_IMPLEMENT_FEATURE(CParticleFeature, CFeatureSpawnRate, "Spawn", "Rate", colorSpawn);
  364.  
  365. //////////////////////////////////////////////////////////////////////////
  366.  
  367. SERIALIZATION_DECLARE_ENUM(ESpawnDistanceMode,
  368.                            ParticlesPerMeter,
  369.                            MetersPerParticle
  370.                            )
  371.  
  372. class CFeatureSpawnDistance : public CParticleFeatureSpawnBase
  373. {
  374. public:
  375.         CRY_PFX2_DECLARE_FEATURE
  376.  
  377.         CFeatureSpawnDistance()
  378.                 : CParticleFeatureSpawnBase(gpu_pfx2::eGpuFeatureType_None)
  379.                 , m_mode(ESpawnDistanceMode::ParticlesPerMeter) {}
  380.  
  381.         virtual void Serialize(Serialization::IArchive& ar) override
  382.         {
  383.                 CParticleFeatureSpawnBase::Serialize(ar);
  384.                 ar(m_mode, "Mode", "Mode");
  385.         }
  386.  
  387.         virtual void SpawnParticles(const SUpdateContext& context) override
  388.         {
  389.                 SpawnParticlesT(*this, context);
  390.         }
  391.  
  392.         ILINE void UpdateSpawnInfo(SSpawnData& spawn, CParticleContainer::SSpawnEntry& entry, const SUpdateContext& context, float amount, float dt) const
  393.         {
  394.                 const CParticleContainer& parentContainer = context.m_parentContainer;
  395.                 const IVec3Stream parentVelocities = parentContainer.GetIVec3Stream(EPVF_Velocity);
  396.                 const Vec3 parentVelocity = parentVelocities.Load(entry.m_parentId);
  397.                 const float parentSpeed = parentVelocity.GetLength();
  398.                 const float distance = parentSpeed * dt;
  399.                 const float spawned = distance * (m_mode == ESpawnDistanceMode::ParticlesPerMeter ? amount : rcp(amount));
  400.                 spawn.m_spawned += spawned;
  401.                 entry.m_ageIncrement = rcp_safe(spawned);
  402.         }
  403.  
  404. private:
  405.         ESpawnDistanceMode m_mode;
  406. };
  407.  
  408. CRY_PFX2_IMPLEMENT_FEATURE(CParticleFeature, CFeatureSpawnDistance, "Spawn", "Distance", colorSpawn);
  409.  
  410. class CFeatureSpawnDensity : public CFeatureSpawnCount
  411. {
  412. public:
  413.         CRY_PFX2_DECLARE_FEATURE
  414.  
  415.         CFeatureSpawnDensity()
  416.         {
  417.                 SetUseDuration(false);
  418.         }
  419.  
  420.         virtual void Serialize(Serialization::IArchive& ar) override
  421.         {
  422.                 CParticleFeatureSpawnBase::Serialize(ar);
  423.         }
  424.  
  425.         virtual void SpawnParticles(const SUpdateContext& context) override
  426.         {
  427.                 SpawnParticlesT(*this, context);
  428.         }
  429.  
  430.         void UpdateAmounts(const SUpdateContext& context, Array<float, uint> amounts) const
  431.         {
  432.                 CParticleComponentRuntime& runtime = context.m_runtime;
  433.                 const size_t numInstances = runtime.GetNumInstances();
  434.  
  435.                 TFloatArray extents(*context.m_pMemHeap, numInstances);
  436.                 extents.fill(0.0f);
  437.                 runtime.GetSpatialExtents(context, amounts, extents);
  438.                 for (size_t i = 0; i < numInstances; ++i)
  439.                 {
  440.                         amounts[i] = extents[i];
  441.                 }
  442.         }
  443. };
  444.  
  445. CRY_PFX2_IMPLEMENT_FEATURE(CParticleFeature, CFeatureSpawnDensity, "Spawn", "Density", colorSpawn);
  446.  
  447. }
  448.  
downloadFeatureSpawn.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top