BVB Source Codes

CRYENGINE Show ParticleComponent.cpp Source code

Return Download CRYENGINE: download ParticleComponent.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/01/2015 by Filipe amim
  5. //  Description:
  6. // -------------------------------------------------------------------------
  7. //
  8. ////////////////////////////////////////////////////////////////////////////
  9.  
  10. #include "StdAfx.h"
  11. #include <CrySerialization/STL.h>
  12. #include <CrySerialization/IArchive.h>
  13. #include <CrySerialization/SmartPtr.h>
  14. #include <CrySerialization/Math.h>
  15. #include "ParticleComponent.h"
  16. #include "ParticleEffect.h"
  17. #include "ParticleFeature.h"
  18. #include "Features/FeatureMotion.h"
  19.  
  20. CRY_PFX2_DBG
  21.  
  22. namespace pfx2
  23. {
  24.  
  25. EParticleDataType PDT(EPDT_SpawnId, TParticleId);
  26. EParticleDataType PDT(EPDT_ParentId, TParticleId);
  27. EParticleDataType PDT(EPDT_State, uint8);
  28. EParticleDataType PDT(EPDT_SpawnFraction, float);
  29. EParticleDataType PDT(EPDT_NormalAge, float);
  30. EParticleDataType PDT(EPDT_LifeTime, float);
  31. EParticleDataType PDT(EPDT_InvLifeTime, float);
  32. EParticleDataType PDT(EPDT_Random, float);
  33.  
  34. EParticleDataType PDT(EPVF_Position, float, 3);
  35. EParticleDataType PDT(EPVF_Velocity, float, 3);
  36. EParticleDataType PDT(EPQF_Orientation, float, 4);
  37. EParticleDataType PDT(EPVF_AngularVelocity, float, 3);
  38. EParticleDataType PDT(EPVF_LocalPosition, float, 3);
  39. EParticleDataType PDT(EPVF_LocalVelocity, float, 3);
  40. EParticleDataType PDT(EPQF_LocalOrientation, float, 4);
  41.  
  42.  
  43.  
  44. void STextureAnimation::Serialize(Serialization::IArchive& ar)
  45. {
  46.         ar(m_frameCount, "FrameCount", "Frame Count");
  47.         ar(m_frameRate, "FrameRate", "Frame Rate");
  48.         ar(m_cycleMode, "CycleMode", "Cycle Mode");
  49.         ar(m_frameBlending, "FrameBlending", "Frame Blending");
  50.  
  51.         if (ar.isInput())
  52.                 Update();
  53. }
  54.  
  55. void STextureAnimation::Update()
  56. {
  57.         m_ageScale = m_frameRate / m_frameCount;
  58.  
  59.         // Scale animation position to frame number
  60.         if (m_cycleMode != EAnimationCycle::Once)
  61.                 m_animPosScale = float(m_frameCount);
  62.         else if (m_frameBlending)
  63.                 m_animPosScale = float(m_frameCount - 1);
  64.         else
  65.                 // If not cycling, reducing slightly to avoid hitting 1
  66.                 m_animPosScale = float(m_frameCount) - 0.001f;
  67. }
  68.  
  69. //////////////////////////////////////////////////////////////////////////
  70. // SModuleParams
  71.  
  72. SComponentParams::SComponentParams()
  73.         : m_pComponent(0)
  74. {
  75.         Reset();
  76. }
  77.  
  78. SComponentParams::SComponentParams(const CParticleComponent& component)
  79.         : m_pComponent(&component)
  80. {
  81.         Reset();
  82. }
  83.  
  84. void SComponentParams::Serialize(Serialization::IArchive& ar)
  85. {
  86.         if (!m_pComponent || !ar.isEdit() || !ar.isOutput())
  87.                 return;
  88.         char buffer[1024];
  89.  
  90.         bool first = true;
  91.         buffer[0] = 0;
  92.         uint32 bytesPerParticle = 0;
  93.         for (auto type : EParticleDataType::values())
  94.         {
  95.                 if (m_pComponent->UseParticleData(type))
  96.                 {
  97.                         if (first)
  98.                                 cry_sprintf(buffer, "%s", type.name());
  99.                         else
  100.                                 cry_sprintf(buffer, "%s, %s", buffer, type.name());
  101.                         first = false;
  102.                         bytesPerParticle += type.info().typeSize() * type.info().step();
  103.                 }
  104.         }
  105.         ar(string(buffer), "", "!Fields used:");
  106.  
  107.         cry_sprintf(buffer, "%d", bytesPerParticle);
  108.         ar(string(buffer), "", "!Bytes per Particle:");
  109. }
  110.  
  111. void SComponentParams::Reset()
  112. {
  113.         m_shaderData = SParticleShaderData();
  114.         m_visibility = SVisibilityParams();
  115.         m_renderObjectFlags = 0;
  116.         m_instanceDataStride = 0;
  117.         m_scaleParticleCount = 1.0f;
  118.         m_baseParticleLifeTime = 0.0f;
  119.         m_particleRange = 0;
  120.         m_renderStateFlags = OS_ALPHA_BLEND;
  121.         m_maxParticleSize = 0.0f;
  122.         m_meshCentered = false;
  123.         m_isValid = false;
  124.         m_parentId = gInvalidId;
  125.         m_diffuseMap = "EngineAssets/Textures/white.dds";
  126.         m_pMaterial = 0;
  127.         m_particleObjFlags = 0;
  128.         m_renderObjectSortBias = 0.0f;
  129.  
  130.         m_subComponentIds.clear();
  131. }
  132.  
  133. void SComponentParams::Validate(CParticleComponent* pComponent, Serialization::IArchive* ar)
  134. {
  135.         bool output = pComponent && ar;
  136.         bool isValid = true;
  137. #define CRY_PFX2_CHECK(cond, msg) if (!(cond)) { if (output) ar->warning(*pComponent, msg); isValid = false; } \
  138.   else
  139.  
  140.         CRY_PFX2_CHECK(pComponent->GetNumFeatures(EFT_Spawn) != 0, "At least one spawn feature required");
  141.         CRY_PFX2_CHECK(pComponent->GetNumFeatures(EFT_Size) != 0, "At least one size feature required")
  142.         {
  143.                 CRY_PFX2_CHECK(m_maxParticleSize > 0.0f, "Particles size are set to 0");
  144.         }
  145.         CRY_PFX2_CHECK(pComponent->GetNumFeatures(EFT_Life) != 0, "At least one life time feature required");
  146.         CRY_PFX2_CHECK(pComponent->GetNumFeatures(EFT_Render) < 2, "Too many render features.");
  147.         CRY_PFX2_CHECK(pComponent->GetNumFeatures(EFT_Motion) < 2, "Too many motion features.");
  148.  
  149.         if (!isValid && output)
  150.                 ar->error(*pComponent, "This component is invalid and will not render");
  151.  
  152.         m_isValid = isValid;
  153.  
  154. #undef CRY_PFX2_CHECK
  155. }
  156.  
  157. void SComponentParams::MakeMaterial(CParticleComponent* pComponent)
  158. {
  159.         enum EGpuParticlesVertexShaderFlags
  160.         {
  161.                 eGpuParticlesVertexShaderFlags_None           = 0x0,
  162.                 eGpuParticlesVertexShaderFlags_FacingVelocity = 0x2000
  163.         };
  164.  
  165.         if (m_pMaterial)
  166.                 return;
  167.         const SRuntimeInitializationParameters& params = pComponent->GetRuntimeInitializationParameters();
  168.         const char* shaderName = params.usesGpuImplementation ? "Particles.ParticlesGpu" : "Particles";
  169.         string materialName = string(pComponent->GetEffect()->GetName()) + pComponent->GetName();
  170.         m_pMaterial = gEnv->p3DEngine->GetMaterialManager()->CreateMaterial(materialName);
  171.         if (gEnv->pRenderer)
  172.         {
  173.                 SInputShaderResourcesPtr pResources = gEnv->pRenderer->EF_CreateInputShaderResource();
  174.                 pResources->m_Textures[EFTT_DIFFUSE].m_Name = m_diffuseMap;
  175.                 uint32 mask = eGpuParticlesVertexShaderFlags_None;
  176.                 if (params.facingMode == 1)
  177.                         mask |= eGpuParticlesVertexShaderFlags_FacingVelocity;
  178.                 SShaderItem shaderItem = gEnv->pRenderer->EF_LoadShaderItem(shaderName, false, 0, pResources, mask);
  179.                 m_pMaterial->AssignShaderItem(shaderItem);
  180.         }
  181.         Vec3 white = Vec3(1.0f, 1.0f, 1.0f);
  182.         float defaultOpacity = 1.0f;
  183.         m_pMaterial->SetGetMaterialParamVec3("diffuse", white, false);
  184.         m_pMaterial->SetGetMaterialParamFloat("opacity", defaultOpacity, false);
  185.         m_pMaterial->RequestTexturesLoading(0.0f);
  186. }
  187.  
  188. float SComponentParams::GetPrimeTime() const
  189. {
  190.         return m_baseParticleLifeTime;
  191. }
  192.  
  193. //////////////////////////////////////////////////////////////////////////
  194. // CParticleComponent
  195.  
  196. CParticleComponent::CParticleComponent()
  197.         : m_dirty(true)
  198.         , m_pEffect(0)
  199.         , m_componentId(gInvalidId)
  200.         , m_componentParams(*this)
  201.         , m_nodePosition(-1.0f, -1.0f)
  202. {
  203.         m_useParticleData.fill(false);
  204. }
  205.  
  206. void CParticleComponent::SetChanged()
  207. {
  208.         m_dirty = true;
  209.         if (m_pEffect)
  210.                 m_pEffect->SetChanged();
  211. }
  212.  
  213. IParticleFeature* CParticleComponent::GetFeature(uint featureIdx) const
  214. {
  215.         return m_features[featureIdx].get();
  216. }
  217.  
  218. void CParticleComponent::AddFeature(uint placeIdx, const SParticleFeatureParams& featureParams)
  219. {
  220.         IParticleFeature* pNewFeature = (featureParams.m_pFactory)();
  221.         m_features.insert(
  222.           m_features.begin() + placeIdx,
  223.           static_cast<CParticleFeature*>(pNewFeature));
  224.         SetChanged();
  225. }
  226.  
  227. void CParticleComponent::RemoveFeature(uint featureIdx)
  228. {
  229.         m_features.erase(m_features.begin() + featureIdx);
  230.         SetChanged();
  231. }
  232.  
  233. void CParticleComponent::SwapFeatures(const uint* swapIds, uint numSwapIds)
  234. {
  235.         CRY_PFX2_ASSERT(numSwapIds == m_features.size());
  236.         decltype(m_features)newFeatures;
  237.         newFeatures.resize(m_features.size());
  238.         for (uint i = 0; i < numSwapIds; ++i)
  239.                 newFeatures[i] = m_features[swapIds[i]];
  240.         std::swap(m_features, newFeatures);
  241.         SetChanged();
  242. }
  243.  
  244. Vec2 CParticleComponent::GetNodePosition() const
  245. {
  246.         return m_nodePosition;
  247. }
  248.  
  249. void CParticleComponent::SetNodePosition(Vec2 position)
  250. {
  251.         m_nodePosition = position;
  252. }
  253.  
  254. uint CParticleComponent::GetNumFeatures(EFeatureType type) const
  255. {
  256.         size_t count = 0;
  257.         for (auto& it : m_features)
  258.                 count += (it->IsEnabled() && (it->GetFeatureType() & type) != 0) ? 1 : 0;
  259.         return count;
  260. }
  261.  
  262. CParticleFeature* CParticleComponent::GetCFeatureByType(const SParticleFeatureParams* pSearchParams) const
  263. {
  264.         for (auto& pFeature : m_features)
  265.         {
  266.                 if (pFeature->IsEnabled() && &pFeature->GetFeatureParams() == pSearchParams)
  267.                         return pFeature.get();
  268.         }
  269.         return nullptr;
  270. }
  271.  
  272. void CParticleComponent::AddToUpdateList(EUpdateList list, CParticleFeature* pFeature)
  273. {
  274.         if (std::find(m_updateLists[list].begin(), m_updateLists[list].end(), pFeature) != m_updateLists[list].end())
  275.                 return;
  276.         m_updateLists[list].push_back(pFeature);
  277.         if (pFeature->GetGpuInterface())
  278.         {
  279.                 if (std::find(m_gpuUpdateLists[list].begin(), m_gpuUpdateLists[list].end(), pFeature->GetGpuInterface()) != m_gpuUpdateLists[list].end())
  280.                         return;
  281.                 m_gpuUpdateLists[list].push_back(pFeature->GetGpuInterface());
  282.         }
  283.         SetChanged();
  284. }
  285.  
  286. TInstanceDataOffset CParticleComponent::AddInstanceData(size_t size)
  287. {
  288.         CRY_PFX2_ASSERT(size > 0);        // instance data of 0 bytes makes no sense
  289.         SetChanged();
  290.         TInstanceDataOffset offset = TInstanceDataOffset(m_componentParams.m_instanceDataStride);
  291.         m_componentParams.m_instanceDataStride += size;
  292.         return offset;
  293. }
  294.  
  295. void CParticleComponent::AddParticleData(EParticleDataType type)
  296. {
  297.         SetChanged();
  298.         uint dim = type.info().dimension;
  299.         for (uint i = type; i < type + dim; ++i)
  300.                 m_useParticleData[i] = true;
  301. }
  302.  
  303. bool CParticleComponent::SetSecondGeneration(CParticleComponent* pParentComponent)
  304. {
  305.         if (m_componentParams.m_parentId != gInvalidId)
  306.                 return false;   // PFX2_TODO - user error - a component can only have one parent component at a time
  307.         m_componentParams.m_parentId = pParentComponent->GetComponentId();
  308.         m_runtimeInitializationParameters.parentId = m_componentParams.m_parentId;
  309.         m_runtimeInitializationParameters.isSecondGen = m_componentParams.IsSecondGen();
  310.         auto& subIds = pParentComponent->m_componentParams.m_subComponentIds;
  311.         auto it = std::find(subIds.begin(), subIds.end(), m_componentId);
  312.         if (it == subIds.end())
  313.                 subIds.push_back(m_componentId);
  314.         return true;
  315. }
  316.  
  317. CParticleComponent* CParticleComponent::GetParentComponent() const
  318. {
  319.         if (m_componentParams.m_parentId != gInvalidId)
  320.                 return m_pEffect->GetCComponent(m_componentParams.m_parentId);
  321.         return 0;
  322. }
  323.  
  324. void CParticleComponent::PrepareRenderObjects(CParticleEmitter* pEmitter)
  325. {
  326.         CRY_PROFILE_FUNCTION(PROFILE_PARTICLE);
  327.  
  328.         for (auto& it : GetUpdateList(EUL_Render))
  329.                 it->PrepareRenderObjects(pEmitter, this);
  330. }
  331.  
  332. void CParticleComponent::ResetRenderObjects(CParticleEmitter* pEmitter)
  333. {
  334.         CRY_PROFILE_FUNCTION(PROFILE_PARTICLE);
  335.  
  336.         for (auto& it : GetUpdateList(EUL_Render))
  337.                 it->ResetRenderObjects(pEmitter, this);
  338. }
  339.  
  340. void CParticleComponent::Render(CParticleEmitter* pEmitter, ICommonParticleComponentRuntime* pRuntime, const SRenderContext& renderContext)
  341. {
  342.         if (IsVisible())
  343.         {
  344.                 CRY_PROFILE_FUNCTION(PROFILE_PARTICLE);
  345.  
  346.                 const bool isGpuParticles = (pRuntime->GetGpuRuntime() != nullptr);
  347.  
  348.                 for (auto& it : GetUpdateList(EUL_Render))
  349.                         it->Render(pEmitter, pRuntime, this, renderContext);           
  350.                
  351.                 if (!GetUpdateList(EUL_RenderDeferred).empty() && !isGpuParticles)
  352.                 {
  353.                         CParticleJobManager& jobManager = GetPSystem()->GetJobManager();
  354.                         CParticleComponentRuntime* pCpuRuntime = static_cast<CParticleComponentRuntime*>(pRuntime);
  355.                         jobManager.AddDeferredRender(pCpuRuntime, renderContext);
  356.                 }
  357.         }
  358. }
  359.  
  360. void CParticleComponent::RenderDeferred(CParticleEmitter* pEmitter, ICommonParticleComponentRuntime* pRuntime, const SRenderContext& renderContext)
  361. {
  362.         CRY_PROFILE_FUNCTION(PROFILE_PARTICLE);
  363.  
  364.         for (auto& it : GetUpdateList(EUL_RenderDeferred))
  365.                 it->Render(pEmitter, pRuntime, this, renderContext);
  366. }
  367.  
  368. bool CParticleComponent::CanMakeRuntime(CParticleEmitter* pEmitter) const
  369. {
  370.         for (auto& pFeature : m_features)
  371.         {
  372.                 if (pFeature->IsEnabled() && !pFeature->CanMakeRuntime(pEmitter))
  373.                         return false;
  374.         }
  375.         return true;
  376. }
  377.  
  378. gpu_pfx2::IParticleFeatureGpuInterface** CParticleComponent::GetGpuUpdateList(EUpdateList list, int& size) const
  379. {
  380.         size = m_gpuUpdateLists[list].size();
  381.         if (size)
  382.                 return (gpu_pfx2::IParticleFeatureGpuInterface**)&m_gpuUpdateLists[list][0];
  383.         else
  384.                 return nullptr;
  385. }
  386.  
  387. void CParticleComponent::PreCompile()
  388. {
  389.         if (!m_dirty)
  390.                 return;
  391.  
  392.         for (size_t i = 0; i < EUL_Count; ++i)
  393.                 m_updateLists[i].clear();
  394.         for (size_t i = 0; i < EUL_Count; ++i)
  395.                 m_gpuUpdateLists[i].clear();
  396.  
  397.         // eliminates features that point to null
  398.         auto it = std::remove_if(
  399.           m_features.begin(), m_features.end(),
  400.           [](decltype(*m_features.begin()) pFeature)
  401.                 {
  402.                         return !pFeature;
  403.           });
  404.         m_features.erase(it, m_features.end());
  405.  
  406.         // add default particle data
  407.         m_useParticleData.fill(false);
  408.         AddParticleData(EPDT_ParentId);
  409.         AddParticleData(EPVF_Position);
  410.         AddParticleData(EPVF_Velocity);
  411.         AddParticleData(EPDT_NormalAge);
  412.         AddParticleData(EPDT_InvLifeTime);
  413.         AddParticleData(EPDT_LifeTime);
  414.         AddParticleData(EPDT_State);
  415.  
  416.         // add default motion feature
  417.         const bool hasMotion = GetNumFeatures(EFT_Motion) != 0;
  418.         m_defaultMotionFeature.reset(hasMotion ? nullptr : new CFeatureMotionPhysics());
  419. }
  420.  
  421. void CParticleComponent::ResolveDependencies()
  422. {
  423.         if (!m_dirty)
  424.                 return;
  425.  
  426.         m_runtimeInitializationParameters = SRuntimeInitializationParameters();
  427.  
  428.         for (auto& it : m_features)
  429.         {
  430.                 if (it->IsEnabled())
  431.                         it->ResolveDependency(this);
  432.         }
  433. }
  434.  
  435. void CParticleComponent::Compile()
  436. {
  437.         if (!m_dirty)
  438.                 return;
  439.  
  440.         for (auto& it : m_features)
  441.         {
  442.                 if (it->IsEnabled())
  443.                 {
  444.                         it->SetGpuInterfaceNeeded(m_runtimeInitializationParameters.usesGpuImplementation);
  445.                         it->AddToComponent(this, &m_componentParams);
  446.                 }
  447.         }
  448.         if (m_defaultMotionFeature)
  449.                 m_defaultMotionFeature->AddToComponent(this, &m_componentParams);
  450. }
  451.  
  452. void CParticleComponent::FinalizeCompile()
  453. {
  454.         SComponentParams& params = m_componentParams;
  455.  
  456.         params.MakeMaterial(this);
  457.         params.Validate(this);
  458.  
  459.         m_dirty = false;
  460. }
  461.  
  462. void CParticleComponent::Serialize(Serialization::IArchive& ar)
  463. {
  464.         ar(m_enabled);
  465.         ar(m_visible, "Visible");
  466.         if (ar.isOutput())
  467.                 ar(m_name, "Name", "^");
  468.         else if (ar.isInput())
  469.         {
  470.                 string inputName;
  471.                 ar(inputName, "Name", "^");
  472.                 SetName(inputName.c_str());
  473.         }
  474.         m_componentParams.m_pComponent = this;
  475.         ar(m_componentParams, "Stats", "Component Statistics");
  476.         ar(m_nodePosition, "nodePos", "Node Position");
  477.         ar(m_features, "Features", "^");
  478.         if (ar.isInput())
  479.                 SetChanged();
  480. }
  481.  
  482. void CParticleComponent::SetName(const char* name)
  483. {
  484.         if (!m_pEffect)
  485.         {
  486.                 m_name = name;
  487.                 return;
  488.         }
  489.  
  490.         string oldName = m_name;
  491.  
  492.         m_name = m_pEffect->MakeUniqueName(m_componentId, name);
  493.  
  494.         // #PFX2_TODO - not the best solution but needed for 5.3. Deprecate after SecondGen is reimplemented using UIDs
  495.         const uint numComponents = m_pEffect->GetNumComponents();
  496.         for (uint componentIdx = 0; componentIdx < numComponents; ++componentIdx)
  497.         {
  498.                 IParticleComponent* pComponent = m_pEffect->GetComponent(componentIdx);
  499.                 const uint numFeatures = pComponent->GetNumFeatures();
  500.                 for (uint featureIdx = 0; featureIdx < numFeatures; ++featureIdx)
  501.                 {
  502.                         IParticleFeature* pFeature = pComponent->GetFeature(featureIdx);
  503.                         const uint numConnectors = pFeature->GetNumConnectors();
  504.                         for (uint connectorIdx = 0; connectorIdx < numConnectors; ++connectorIdx)
  505.                         {
  506.                                 if (strcmp(pFeature->GetConnectorName(connectorIdx), oldName.c_str()) == 0)
  507.                                 {
  508.                                         pFeature->DisconnectFrom(oldName);
  509.                                         pFeature->ConnectTo(m_name.c_str());
  510.                                 }
  511.                         }
  512.                 }
  513.         }
  514. }
  515.  
  516. SERIALIZATION_CLASS_NAME(CParticleComponent, CParticleComponent, "Component", "Component");
  517.  
  518. }
  519.  
downloadParticleComponent.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