BVB Source Codes

CRYENGINE Show ParticleEmitter.cpp Source code

Return Download CRYENGINE: download ParticleEmitter.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //  Created:     23/09/2014 by Filipe amim
  5. //  Description:
  6. // -------------------------------------------------------------------------
  7. //
  8. ////////////////////////////////////////////////////////////////////////////
  9.  
  10. #include "StdAfx.h"
  11. #include <CryEntitySystem/IEntitySystem.h>
  12. #include "ParticleManager.h"
  13. #include "FogVolumeRenderNode.h"
  14. #include "ParticleSystem.h"
  15. #include "ParticleEmitter.h"
  16. #include "ParticleDataTypes.h"
  17. #include "ParticleFeature.h"
  18.  
  19. CRY_PFX2_DBG
  20.  
  21. namespace pfx2
  22. {
  23.  
  24. //////////////////////////////////////////////////////////////////////////
  25. // CParticleEmitter
  26.  
  27. CParticleEmitter::CParticleEmitter(uint emitterId)
  28.         : m_pEffect(0)
  29.         , m_registered(false)
  30.         , m_bounds(0.0f)
  31.         , m_viewDistRatio(1.0f)
  32.         , m_active(false)
  33.         , m_location(IDENTITY)
  34.         , m_timeScale(1)
  35.         , m_editVersion(-1)
  36.         , m_entityId(0)
  37.         , m_entitySlot(-1)
  38.         , m_emitterGeometrySlot(-1)
  39.         , m_time(0.0f)
  40.         , m_initialSeed(0)
  41.         , m_emitterId(emitterId)
  42. {
  43.         m_currentSeed = m_initialSeed;
  44.         m_nInternalFlags |= IRenderNode::REQUIRES_FORWARD_RENDERING;
  45.         m_nInternalFlags |= IRenderNode::REQUIRES_NEAREST_CUBEMAP;
  46.  
  47.         auto smoothstep = [](float x) { return x*x*(3 - 2 * x); };
  48.         auto contrast = [](float x) { return x * 0.75f + 0.25f; };
  49.         float x = smoothstep(cry_random(0.0f, 1.0f));
  50.         float r = contrast(smoothstep(max(0.0f, -x * 2 + 1)));
  51.         float g = contrast(smoothstep(1 - abs((x - 0.5f) * 2)));
  52.         float b = contrast(smoothstep(max(0.0f, x * 2 - 1)));
  53.         m_profilerColor = ColorF(r, g, b);
  54. }
  55.  
  56. CParticleEmitter::~CParticleEmitter()
  57. {
  58.         SetCEffect(0);
  59.         gEnv->p3DEngine->FreeRenderNodeState(this);
  60.         ResetRenderObjects();
  61. }
  62.  
  63. EERType CParticleEmitter::GetRenderNodeType()
  64. {
  65.         return eERType_ParticleEmitter;
  66. }
  67.  
  68. const char* CParticleEmitter::GetEntityClassName() const
  69. {
  70.         return "ParticleEmitter";
  71. }
  72.  
  73. const char* CParticleEmitter::GetName() const
  74. {
  75.         return "";
  76. }
  77.  
  78. void CParticleEmitter::SetMatrix(const Matrix34& mat)
  79. {
  80.         if (mat.IsValid())
  81.                 SetLocation(QuatTS(mat));
  82. }
  83.  
  84. Vec3 CParticleEmitter::GetPos(bool bWorldOnly) const
  85. {
  86.         return m_location.t;
  87. }
  88.  
  89. void CParticleEmitter::Render(const struct SRendParams& rParam, const SRenderingPassInfo& passInfo)
  90. {
  91.         FUNCTION_PROFILER(GetISystem(), PROFILE_PARTICLE);
  92.         PARTICLE_LIGHT_PROFILER();
  93.  
  94.         if (!passInfo.RenderParticles() || passInfo.IsRecursivePass())
  95.                 return;
  96.         if (passInfo.IsShadowPass())
  97.                 return;
  98.  
  99.         CLightVolumesMgr& lightVolumeManager = m_p3DEngine->GetLightVolumeManager();
  100.         SRenderContext renderContext(rParam, passInfo);
  101.         renderContext.m_lightVolumeId = lightVolumeManager.RegisterVolume(GetPos(), GetBBox().GetRadius() * 0.5f, rParam.nClipVolumeStencilRef, passInfo);
  102.         renderContext.m_distance = GetPos().GetDistance(passInfo.GetCamera().GetPosition());
  103.         ColorF fogVolumeContrib;
  104.         CFogVolumeRenderNode::TraceFogVolumes(GetPos(), fogVolumeContrib, passInfo);
  105.         renderContext.m_fogVolumeId = GetRenderer()->PushFogVolumeContribution(fogVolumeContrib, passInfo);
  106.        
  107.         for (auto& pComponentRuntime : m_componentRuntimes)
  108.         {
  109.                 pComponentRuntime.pComponent->Render(this, pComponentRuntime.pRuntime, renderContext);
  110.         }
  111. }
  112.  
  113. void CParticleEmitter::Update()
  114. {
  115.         FUNCTION_PROFILER(GetISystem(), PROFILE_PARTICLE);
  116.  
  117.         m_time += gEnv->pTimer->GetFrameTime();
  118.         ++m_currentSeed;
  119.  
  120.         m_pEffect->Compile();
  121.         if (m_editVersion != m_pEffect->GetEditVersion())
  122.         {
  123.                 m_attributeInstance.Reset(&m_pEffect->GetAttributeTable(), EAttributeScope::PerEmitter);
  124.                 UpdateRuntimeRefs();
  125.         }
  126.         m_editVersion = m_pEffect->GetEditVersion();
  127.  
  128.         if (m_entityId != 0)
  129.                 UpdateFromEntity();
  130.         for (auto& pComponentRuntime : m_componentRuntimes)
  131.                 pComponentRuntime.pRuntime->MainPreUpdate();
  132.  
  133.         AABB newBounds = AABB(m_location.t, 0.25f);
  134.         for (auto& ref : m_componentRuntimes)
  135.                 newBounds.Add(ref.pRuntime->GetBounds());
  136.  
  137.         m_visEnviron.Invalidate();
  138.  
  139.         if (m_registered && !IsEquivalent(m_bounds, newBounds))
  140.                 Unregister();
  141.  
  142.         m_bounds = newBounds;
  143.         if (!m_registered)
  144.                 Register();
  145.  
  146.         if (!m_bounds.IsReset())
  147.         {
  148.                 m_visEnviron.Update(GetPos(), m_bounds);
  149.                 m_physEnviron.GetPhysAreas(
  150.                   CParticleManager::Instance()->GetPhysEnviron(), m_bounds,
  151.                   m_visEnviron.OriginIndoors(), ENV_GRAVITY | ENV_WIND | ENV_WATER, true, 0);
  152.         }
  153. }
  154.  
  155. void CParticleEmitter::PostUpdate()
  156. {
  157.         m_parentContainer.GetIOVec3Stream(EPVF_Velocity).Store(0, Vec3(ZERO));
  158.         m_parentContainer.GetIOVec3Stream(EPVF_AngularVelocity).Store(0, Vec3(ZERO));
  159. }
  160.  
  161. IPhysicalEntity* CParticleEmitter::GetPhysics() const
  162. {
  163.         return 0;
  164. }
  165.  
  166. void CParticleEmitter::SetPhysics(IPhysicalEntity*)
  167. {
  168. }
  169.  
  170. void CParticleEmitter::SetMaterial(IMaterial* pMat)
  171. {
  172. }
  173.  
  174. IMaterial* CParticleEmitter::GetMaterial(Vec3* pHitPos) const
  175. {
  176.         return 0;
  177. }
  178.  
  179. IMaterial* CParticleEmitter::GetMaterialOverride()
  180. {
  181.         return 0;
  182. }
  183.  
  184. float CParticleEmitter::GetMaxViewDist()
  185. {
  186.         float maxParticleSize = 0.0f;
  187.         size_t compCount = m_pEffect->GetNumComponents();
  188.         for (size_t i = 0; i < compCount; ++i)
  189.         {
  190.                 const auto& params = m_pEffect->GetCComponent(i)->GetComponentParams();
  191.                 maxParticleSize = max(maxParticleSize, params.m_maxParticleSize * params.m_visibility.m_viewDistanceMultiple);
  192.         }
  193.         IRenderer* pRenderer = GetRenderer();
  194.         float maxAngularDensity = pRenderer ? GetPSystem()->GetMaxAngularDensity(pRenderer->GetCamera()) : 1080.0f;
  195.         float maxDistance = maxAngularDensity * maxParticleSize * m_viewDistRatio;
  196.         return maxDistance;
  197. }
  198.  
  199. void CParticleEmitter::Precache()
  200. {
  201. }
  202.  
  203. void CParticleEmitter::GetMemoryUsage(ICrySizer* pSizer) const
  204. {
  205. }
  206.  
  207. const AABB CParticleEmitter::GetBBox() const
  208. {
  209.         return m_bounds;
  210. }
  211.  
  212. void CParticleEmitter::FillBBox(AABB& aabb)
  213. {
  214.         aabb = GetBBox();
  215. }
  216.  
  217. void CParticleEmitter::SetBBox(const AABB& WSBBox)
  218. {
  219. }
  220.  
  221. void CParticleEmitter::OffsetPosition(const Vec3& delta)
  222. {
  223. }
  224.  
  225. bool CParticleEmitter::IsAllocatedOutsideOf3DEngineDLL()
  226. {
  227.         return false;
  228. }
  229.  
  230. void CParticleEmitter::SetViewDistRatio(int nViewDistRatio)
  231. {
  232.         IRenderNode::SetViewDistRatio(nViewDistRatio);
  233.         m_viewDistRatio = GetViewDistRatioNormilized();
  234. }
  235.  
  236. void CParticleEmitter::ReleaseNode(bool bImmediate)
  237. {
  238.         Activate(false);
  239.         Unregister();
  240. }
  241.  
  242. const IParticleEffect* CParticleEmitter::GetEffect() const
  243. {
  244.         return m_pEffect;
  245. }
  246.  
  247. void CParticleEmitter::Activate(bool activate)
  248. {
  249.         if (!m_pEffect || activate == m_active)
  250.                 return;
  251.  
  252.         if (activate)
  253.         {
  254.                 m_parentContainer.AddParticleData(EPVF_Position);
  255.                 m_parentContainer.AddParticleData(EPQF_Orientation);
  256.                 m_parentContainer.AddParticleData(EPVF_Velocity);
  257.                 m_parentContainer.AddParticleData(EPVF_AngularVelocity);
  258.                 m_parentContainer.AddParticleData(EPDT_NormalAge);
  259.  
  260.                 UpdateRuntimeRefs();
  261.                 AddInstance();
  262.         }
  263.         else
  264.         {
  265.                 StopInstances();
  266.         }
  267.  
  268.         m_active = activate;
  269. }
  270.  
  271. void CParticleEmitter::Kill()
  272. {
  273.         for (auto& componentRef : m_componentRuntimes)
  274.         {
  275.                 auto pCpuComponent = componentRef.pRuntime->GetCpuRuntime();
  276.                 if (pCpuComponent)
  277.                 {
  278.                         pCpuComponent->RemoveAllSubInstances();
  279.                         pCpuComponent->Reset();
  280.                 }
  281.                 auto pGpuComponent = componentRef.pRuntime->GetGpuRuntime();
  282.                 if (pGpuComponent)
  283.                 {
  284.                         pGpuComponent->RemoveAllSubInstances();
  285.                 }
  286.         }
  287. }
  288.  
  289. bool CParticleEmitter::IsActive() const
  290. {
  291.         return m_active;
  292. }
  293.  
  294. void CParticleEmitter::Prime()
  295. {
  296.         // PFX2_TODO : implement
  297. }
  298.  
  299. void CParticleEmitter::SetLocation(const QuatTS& loc)
  300. {
  301.         const Vec3 prevPos = m_location.t;
  302.         const Quat prevQuat = m_location.q;
  303.         const Vec3 newPos = loc.t;
  304.         const Quat newQuat = loc.q;
  305.         m_parentContainer.GetIOVec3Stream(EPVF_Position).Store(0, newPos);
  306.         m_parentContainer.GetIOQuatStream(EPQF_Orientation).Store(0, newQuat);
  307.  
  308.         if (m_registered)
  309.         {
  310.                 const float deltaTime = gEnv->pTimer->GetFrameTime();
  311.                 const float invDeltaTime = abs(deltaTime) > FLT_EPSILON ? rcp_fast(deltaTime) : 0.0f;
  312.                 const Vec3 velocity0 = m_parentContainer.GetIOVec3Stream(EPVF_Velocity).Load(0);
  313.                 const Vec3 angularVelocity0 = m_parentContainer.GetIOVec3Stream(EPVF_AngularVelocity).Load(0);
  314.  
  315.                 const Vec3 velocity1 =
  316.                   velocity0 +
  317.                   (newPos - prevPos) * invDeltaTime;
  318.                 const Vec3 angularVelocity1 =
  319.                   angularVelocity0 +
  320.                   2.0f * Quat::log(newQuat * prevQuat.GetInverted()) * invDeltaTime;
  321.  
  322.                 m_parentContainer.GetIOVec3Stream(EPVF_Velocity).Store(0, velocity1);
  323.                 m_parentContainer.GetIOVec3Stream(EPVF_AngularVelocity).Store(0, angularVelocity1);
  324.         }
  325.  
  326.         m_location = loc;
  327. }
  328.  
  329. void CParticleEmitter::EmitParticle(const EmitParticleData* pData)
  330. {
  331.         // PFX2_TODO : this is awful, make it better
  332.         CParticleComponentRuntime::SInstance instance;
  333.         instance.m_parentId = m_parentContainer.GetLastParticleId();
  334.         m_parentContainer.AddParticle();
  335.         if (pData->bHasLocation)
  336.         {
  337.                 QuatT location = QuatT(pData->Location);
  338.                 m_parentContainer.GetIOVec3Stream(EPVF_Position).Store(instance.m_parentId, location.t);
  339.                 m_parentContainer.GetIOQuatStream(EPQF_Orientation).Store(instance.m_parentId, location.q);
  340.                 m_parentContainer.GetIOVec3Stream(EPVF_Velocity).Store(instance.m_parentId, Vec3(ZERO));
  341.                 m_parentContainer.GetIOVec3Stream(EPVF_AngularVelocity).Store(instance.m_parentId, Vec3(ZERO));
  342.         }
  343.  
  344.         TComponentId lastComponentId = m_pEffect->GetNumComponents();
  345.         for (TComponentId componentId = 0; componentId < lastComponentId; ++componentId)
  346.         {
  347.                 CParticleComponent* pComponent = m_pEffect->GetCComponent(componentId);
  348.                 const SComponentParams& params = pComponent->GetComponentParams();
  349.                 const bool isEnabled = pComponent->IsEnabled();
  350.                 const bool isvalid = params.IsValid();
  351.                 if (isEnabled && isvalid && !params.IsSecondGen())
  352.                         m_componentRuntimes.back().pRuntime->AddSubInstances(&instance, 1);
  353.         }
  354. }
  355.  
  356. void CParticleEmitter::SetEntity(IEntity* pEntity, int nSlot)
  357. {
  358.         if (pEntity)
  359.         {
  360.                 m_entityId = pEntity->GetId();
  361.                 m_entitySlot = nSlot;
  362.         }
  363.         else
  364.                 m_entityId = 0;
  365. }
  366.  
  367. //////////////////////////////////////////////////////////////////////////
  368. void CParticleEmitter::InvalidateCachedEntityData()
  369. {
  370.         UpdateFromEntity();
  371. }
  372.  
  373. void CParticleEmitter::SetTarget(const ParticleTarget& target)
  374. {
  375.         if ((int)target.bPriority >= (int)m_target.bPriority)
  376.                 m_target = target;
  377. }
  378.  
  379. bool CParticleEmitter::UpdateStreamableComponents(float fImportance, const Matrix34A& objMatrix, IRenderNode* pRenderNode, float fEntDistance, bool bFullUpdate, int nLod)
  380. {
  381.         FUNCTION_PROFILER_3DENGINE;
  382.  
  383.         const TComponentId numComponents = m_pEffect->GetNumComponents();
  384.         for (TComponentId componentId = 0; componentId < numComponents; ++componentId)
  385.         {
  386.                 CParticleComponent* pComponent = m_pEffect->GetCComponent(componentId);
  387.                 const SComponentParams& params = pComponent->GetComponentParams();
  388.  
  389.                 IMaterial* pMaterial = params.m_pMaterial;
  390.                 CMatInfo*  pMatInfo  = reinterpret_cast<CMatInfo*>(pMaterial);
  391.                 if (pMatInfo)
  392.                         pMatInfo->PrecacheMaterial(fEntDistance, nullptr, bFullUpdate);
  393.  
  394.                 IMeshObj* pMesh = params.m_pMesh;
  395.                 if (pMesh)
  396.                 {
  397.                         CStatObj* pStatObj = static_cast<CStatObj*>(pMesh);
  398.                         IMaterial* pMaterial = pStatObj->GetMaterial();
  399.                         m_pObjManager->PrecacheStatObj(pStatObj, nLod, objMatrix, pMaterial, fImportance, fEntDistance, bFullUpdate, false);
  400.                 }
  401.         }
  402.  
  403.         return true;
  404. }
  405.  
  406. void CParticleEmitter::GetSpawnParams(SpawnParams& sp) const
  407. {
  408.         sp = SpawnParams();
  409.         sp.fTimeScale = m_timeScale;
  410. }
  411.  
  412. void CParticleEmitter::SetSpawnParams(const SpawnParams& spawnParams)
  413. {
  414.         m_timeScale = spawnParams.fTimeScale;
  415.        
  416.         const int forcedSeed = GetCVars()->e_ParticlesForceSeed;
  417.         if (spawnParams.nSeed != -1)
  418.         {
  419.                 m_initialSeed = uint32(spawnParams.nSeed);
  420.                 m_time = 0.0f;
  421.         }
  422.         else if (forcedSeed != 0)
  423.         {
  424.                 m_initialSeed = forcedSeed;
  425.                 m_time = 0.0f;
  426.         }
  427.         else
  428.         {
  429.                 m_initialSeed = cry_random_uint32();
  430.                 m_time = gEnv->pTimer->GetCurrTime();
  431.         }
  432.         m_currentSeed = m_initialSeed;
  433. }
  434.  
  435. void CParticleEmitter::UpdateRuntimeRefs()
  436. {
  437.         // #PFX2_TODO : clean up and optimize this function. Way too messy.
  438.  
  439.         ResetRenderObjects();
  440.  
  441.         TComponentRuntimes newRuntimes;
  442.  
  443.         TComponentId lastComponentId = m_pEffect->GetNumComponents();
  444.  
  445.         for (TComponentId componentId = 0; componentId < lastComponentId; ++componentId)
  446.         {
  447.                 CParticleComponent* pComponent = m_pEffect->GetCComponent(componentId);
  448.  
  449.                 auto it = std::find_if(m_componentRuntimes.begin(), m_componentRuntimes.end(),
  450.                                        [=](const SRuntimeRef& ref)
  451.                         {
  452.                                 return ref.pComponent == pComponent;
  453.                   });
  454.  
  455.                 SRuntimeRef runtimeRef;
  456.                 const SRuntimeInitializationParameters& params = pComponent->GetRuntimeInitializationParameters();
  457.  
  458.                 bool createNew = false;
  459.                 if (it == m_componentRuntimes.end())
  460.                         createNew = true;
  461.                 else
  462.                 {
  463.                         // exists, but wrong runtime type
  464.                         // (can mean wrong cpu/gpu type, or wrong maximum number of particles, etc)
  465.                         createNew = !it->pRuntime->IsValidRuntimeForInitializationParameters(params);
  466.                 }
  467.  
  468.                 if (createNew)
  469.                         runtimeRef = SRuntimeRef(m_pEffect, this, pComponent, params);
  470.                 else
  471.                         runtimeRef = *it;
  472.  
  473.                 newRuntimes.push_back(runtimeRef);
  474.         }
  475.  
  476.         m_componentRuntimes = newRuntimes;
  477.         for (TComponentId componentId = 0; componentId < lastComponentId; ++componentId)
  478.         {
  479.                 bool isActive = true;
  480.                 TComponentId thisComponentId = componentId;
  481.                 while (thisComponentId != gInvalidId)
  482.                 {
  483.                         const CParticleComponent* pComponent = m_pEffect->GetCComponent(thisComponentId);
  484.                         const SComponentParams& params = pComponent->GetComponentParams();
  485.                         const bool isEnabled = pComponent->IsEnabled();
  486.                         const bool isValid = params.IsValid();
  487.                         // #PFX2_TODO : Cache canMakeRuntime, it is evaluating same components more than once for secondgen.
  488.                         const bool canMakeRuntime = pComponent->CanMakeRuntime(this);
  489.                         if (!(isEnabled && isValid && canMakeRuntime))
  490.                         {
  491.                                 isActive = false;
  492.                                 break;
  493.                         }
  494.                         thisComponentId = params.m_parentId;
  495.                 }
  496.  
  497.                 CParticleComponent* component = m_pEffect->GetCComponent(componentId);
  498.                 ICommonParticleComponentRuntime* pCommonRuntime = m_componentRuntimes[componentId].pRuntime;
  499.                 if (!component->GetRuntimeInitializationParameters().usesGpuImplementation)
  500.                 {
  501.                         CParticleComponentRuntime* pRuntime    = pCommonRuntime->GetCpuRuntime();
  502.                         const SComponentParams&    params      = pRuntime->GetComponentParams();
  503.                         const bool                 wasActive   = pRuntime->IsActive();
  504.                         const bool                 isSecondGen = params.IsSecondGen();
  505.                         pRuntime->RemoveAllSubInstances();
  506.                         pRuntime->SetActive(isActive);
  507.                         if (isActive)
  508.                                 pRuntime->Initialize();
  509.                         else
  510.                                 pRuntime->Reset();
  511.                         if (m_active && !isSecondGen)
  512.                         {
  513.                                 CParticleComponentRuntime::SInstance instance;
  514.                                 instance.m_parentId = 0;
  515.                                 pRuntime->AddSubInstances(&instance, 1);
  516.                         }
  517.                 }
  518.                 else
  519.                 {
  520.                         gpu_pfx2::IParticleComponentRuntime* pRuntime =
  521.                                 pCommonRuntime->GetGpuRuntime();
  522.                         pRuntime->RemoveAllSubInstances();
  523.                         pRuntime->SetActive(isActive);
  524.                         const bool isSecondGen = pRuntime->IsSecondGen();
  525.                         if (isActive && !isSecondGen)
  526.                         {
  527.                                 CParticleComponentRuntime::SInstance instance;
  528.                                 instance.m_parentId = 0;
  529.                                 pRuntime->AddSubInstances(&instance, 1);
  530.                         }
  531.                 }
  532.                 component->PrepareRenderObjects(this);
  533.         }
  534.  
  535.         m_editVersion = m_pEffect->GetEditVersion();
  536. }
  537.  
  538. void CParticleEmitter::ResetRenderObjects()
  539. {
  540.         if (!m_pEffect)
  541.                 return;
  542.  
  543.         const uint numROs = m_pEffect->GetNumRenderObjectIds();
  544.         for (uint threadId = 0; threadId < RT_COMMAND_BUF_COUNT; ++threadId)
  545.                 m_pRenderObjects[threadId].resize(numROs, nullptr);
  546.  
  547.         const TComponentId lastComponentId = m_pEffect->GetNumComponents();
  548.         for (TComponentId componentId = 0; componentId < lastComponentId; ++componentId)
  549.         {
  550.                 CParticleComponent* pComponent = m_pEffect->GetCComponent(componentId);
  551.                 pComponent->ResetRenderObjects(this);
  552.         }
  553. }
  554.  
  555. void CParticleEmitter::AddInstance()
  556. {
  557.         m_parentContainer.AddParticle();
  558.  
  559.         CParticleComponentRuntime::SInstance instance;
  560.         instance.m_parentId = 0;
  561.  
  562.         for (auto& ref : m_componentRuntimes)
  563.         {
  564.                 if (auto pRuntime = ref.pRuntime->GetCpuRuntime())
  565.                 {
  566.                         const SComponentParams& params = pRuntime->GetComponentParams();
  567.                         const bool isSecondGen = params.IsSecondGen();
  568.                         if (!isSecondGen)
  569.                                 ref.pRuntime->AddSubInstances(&instance, 1);
  570.                 }
  571.         }
  572. }
  573.  
  574. void CParticleEmitter::StopInstances()
  575. {
  576.         for (auto& ref : m_componentRuntimes)
  577.         {
  578.                 if (auto pRuntime = ref.pRuntime->GetCpuRuntime())
  579.                 {
  580.                         const SComponentParams& params = pRuntime->GetComponentParams();
  581.                         const bool isSecondGen = params.IsSecondGen();
  582.                         if (!isSecondGen)
  583.                                 pRuntime->RemoveAllSubInstances();
  584.                 }
  585.                 else if (auto pRuntime = ref.pRuntime->GetGpuRuntime())
  586.                 {
  587.                         const bool isSecondGen = pRuntime->IsSecondGen();
  588.                         if (!isSecondGen)
  589.                                 pRuntime->RemoveAllSubInstances();
  590.                 }
  591.         }
  592. }
  593.  
  594. void CParticleEmitter::UpdateFromEntity()
  595. {
  596.         IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_entityId);
  597.         if (!pEntity)
  598.                 return;
  599.         UpdateTargetFromEntity(pEntity);
  600. }
  601.  
  602. IEntity* CParticleEmitter::GetEmitGeometryEntity() const
  603. {
  604.         IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_entityId);
  605.         if (pEntity)
  606.         {
  607.                 // Override m_emitterGeometry with geometry of owning or attached entity if it exists
  608.                 if (IEntity* pParent = pEntity->GetParent())
  609.                         pEntity = pEntity->GetParent();
  610.         }
  611.         return pEntity;
  612. }
  613.  
  614. void CParticleEmitter::UpdateEmitGeomFromEntity()
  615. {
  616.         IEntity* pEntity = GetEmitGeometryEntity();
  617.         m_emitterGeometrySlot = m_emitterGeometry.Set(pEntity, m_entitySlot);
  618. }
  619.  
  620. QuatTS CParticleEmitter::GetEmitterGeometryLocation() const
  621. {
  622.         if (IEntity* pEntity = GetEmitGeometryEntity())
  623.         {
  624.                 SEntitySlotInfo slotInfo;
  625.                 if (pEntity->GetSlotInfo(m_emitterGeometrySlot, slotInfo))
  626.                 {
  627.                         if (slotInfo.pWorldTM)
  628.                                 return QuatTS(*slotInfo.pWorldTM);
  629.                 }
  630.  
  631.         }
  632.         return m_location;
  633. }
  634.  
  635. CRenderObject* CParticleEmitter::GetRenderObject(uint threadId, uint renderObjectIdx)
  636. {
  637.         CRY_PFX2_ASSERT(threadId < RT_COMMAND_BUF_COUNT);
  638.         if (m_pRenderObjects[threadId].empty())
  639.                 return nullptr;
  640.         return m_pRenderObjects[threadId][renderObjectIdx];
  641. }
  642.  
  643. void CParticleEmitter::SetRenderObject(CRenderObject* pRenderObject, uint threadId, uint renderObjectIdx)
  644. {
  645.         CRY_PFX2_ASSERT(threadId < RT_COMMAND_BUF_COUNT);
  646.         m_pRenderObjects[threadId][renderObjectIdx] = pRenderObject;
  647. }
  648.  
  649. void CParticleEmitter::UpdateTargetFromEntity(IEntity* pEntity)
  650. {
  651.         if (m_target.bPriority)
  652.                 return;
  653.  
  654.         ParticleTarget target;
  655.         for (IEntityLink* pLink = pEntity->GetEntityLinks(); pLink; pLink = pLink->next)
  656.         {
  657.                 IEntity* pTarget = gEnv->pEntitySystem->GetEntity(pLink->entityId);
  658.                 if (pTarget)
  659.                 {
  660.                         target.bTarget = true;
  661.                         target.vTarget = pTarget->GetPos();
  662.  
  663.                         target.vVelocity = Vec3(ZERO);  // PFX2_TODO : grab velocity from entity's physical object
  664.  
  665.                         AABB boundingBox;
  666.                         pTarget->GetLocalBounds(boundingBox);
  667.                         target.fRadius = boundingBox.GetRadius();
  668.  
  669.                         break;
  670.                 }
  671.         }
  672.         m_target = target;
  673. }
  674.  
  675. void CParticleEmitter::GetParentData(const int parentComponentId, const uint* parentParticleIds, const int numParentParticleIds, SInitialData* data) const
  676. {
  677.         const CParticleContainer& container = (parentComponentId < 0)
  678.                                               ? m_parentContainer
  679.                                               : GetRuntimes()[parentComponentId].pRuntime->GetCpuRuntime()->GetContainer();
  680.  
  681.         IVec3Stream parentPositions = container.GetIVec3Stream(EPVF_Position);
  682.         IVec3Stream parentVelocities = container.GetIVec3Stream(EPVF_Velocity);
  683.  
  684.         for (int i = 0; i < numParentParticleIds; ++i)
  685.         {
  686.                 data[i].position = parentPositions.Load(parentParticleIds[i]);
  687.                 data[i].velocity = parentVelocities.Load(parentParticleIds[i]);
  688.         }
  689. }
  690.  
  691. void CParticleEmitter::SetCEffect(CParticleEffect* pEffect)
  692. {
  693.         Unregister();
  694.         Activate(false);
  695.         if (!pEffect)
  696.                 ResetRenderObjects();
  697.         m_pEffect = pEffect;
  698.         if (m_pEffect)
  699.                 m_attributeInstance.Reset(&m_pEffect->GetAttributeTable(), EAttributeScope::PerEmitter);
  700.         else
  701.                 m_attributeInstance.Reset();
  702. }
  703.  
  704. void CParticleEmitter::Register()
  705. {
  706.         if (m_registered)
  707.                 return;
  708.         bool posContained = GetBBox().IsContainPoint(GetPos());
  709.         SetRndFlags(ERF_REGISTER_BY_POSITION, posContained);
  710.         SetRndFlags(ERF_CASTSHADOWMAPS, false);
  711.         gEnv->p3DEngine->RegisterEntity(this);
  712.         m_registered = true;
  713. }
  714.  
  715. void CParticleEmitter::Unregister()
  716. {
  717.         if (!m_registered)
  718.                 return;
  719.         // PFX2_TODO - UnRegisterEntityDirect should only be needed to update bbox on 3dengine
  720.         // gEnv->p3DEngine->UnRegisterEntityAsJob(this);
  721.         gEnv->p3DEngine->UnRegisterEntityDirect(this);
  722.         m_registered = false;
  723. }
  724.  
  725. bool CParticleEmitter::HasParticles() const
  726. {
  727.         CRY_PFX2_ASSERT(m_pEffect != 0);
  728.         for (auto& ref : m_componentRuntimes)
  729.         {
  730.                 if (auto pRuntime = ref.pRuntime->GetCpuRuntime())
  731.                 {
  732.                         if (pRuntime->GetContainer().GetLastParticleId() != 0)
  733.                                 return true;
  734.                 }
  735.                 else if (auto pRuntime = ref.pRuntime->GetGpuRuntime())
  736.                 {
  737.                         if (pRuntime->HasParticles())
  738.                                 return true;
  739.                 }
  740.         }
  741.         return false;
  742. }
  743.  
  744. void CParticleEmitter::AccumCounts(SParticleCounts& counts)
  745. {
  746.         counts.EmittersRendered += m_emitterCounts.EmittersRendered;
  747.         counts.ParticlesRendered += m_emitterCounts.ParticlesRendered;
  748.         counts.ParticlesClip += m_emitterCounts.ParticlesClip;
  749.         for (auto& ref : m_componentRuntimes)
  750.         {
  751.                 ref.pRuntime->AccumCounts(counts);
  752.         }
  753.         m_emitterCounts = SContainerCounts();
  754. }
  755.  
  756. void CParticleEmitter::AddDrawCallCounts(int numRendererdParticles, int numClippedParticles)
  757. {
  758.         m_countsMutex.Lock();
  759.         m_emitterCounts.EmittersRendered += 1.0f;
  760.         m_emitterCounts.ParticlesRendered += float(numRendererdParticles);
  761.         m_emitterCounts.ParticlesClip += float(numClippedParticles);
  762.         m_countsMutex.Unlock();
  763. }
  764.  
  765. CParticleEmitter::SRuntimeRef::SRuntimeRef(CParticleEffect* effect, CParticleEmitter* emitter, CParticleComponent* component, const SRuntimeInitializationParameters& params)
  766. {
  767.         if (params.usesGpuImplementation)
  768.                 pRuntime = gEnv->pRenderer->GetGpuParticleManager()->CreateParticleComponentRuntime(component, params);
  769.         else
  770.                 pRuntime = new CParticleComponentRuntime(effect, emitter, component);
  771.  
  772.         pComponent = component;
  773. }
  774.  
  775. }
  776.  
downloadParticleEmitter.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