BVB Source Codes

CRYENGINE Show MFXParticleEffect.cpp Source code

Return Download CRYENGINE: download MFXParticleEffect.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4.  
  5. #include <CryParticleSystem/ParticleParams.h>
  6. #ifndef _LIB
  7.         #include <CryParticleSystem/ParticleParams_TypeInfo.h>
  8. #endif
  9. #include "MFXParticleEffect.h"
  10. #include "MaterialEffectsCVars.h"
  11. #include "IActorSystem.h"
  12.  
  13. CMFXParticleEffect::CMFXParticleEffect()
  14.         : CMFXEffectBase(eMFXPF_Particles)
  15.         , m_particleParams()
  16. {
  17. }
  18.  
  19. CMFXParticleEffect::~CMFXParticleEffect()
  20. {
  21. }
  22.  
  23. void CMFXParticleEffect::Execute(const SMFXRunTimeEffectParams& params)
  24. {
  25.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_ACTION);
  26.  
  27.         Vec3 pos = params.pos;
  28.         Vec3 dir = ZERO;
  29.         Vec3 inDir = params.dir[0];
  30.         Vec3 reverso = inDir * -1.0f;
  31.         switch (m_particleParams.directionType)
  32.         {
  33.         case SMFXParticleParams::eDT_Normal:
  34.                 dir = params.normal;
  35.                 break;
  36.         case SMFXParticleParams::eDT_Ricochet:
  37.                 dir = reverso.GetRotated(params.normal, gf_PI).normalize();
  38.                 break;
  39.         case SMFXParticleParams::eDT_ProjectileDir:
  40.                 dir = -inDir;
  41.                 break;
  42.         default:
  43.                 dir = params.normal;
  44.                 break;
  45.         }
  46.  
  47.         bool tryToAttachEffect = (CMaterialEffectsCVars::Get().mfx_EnableAttachedEffects != 0);
  48.         float distToPlayer = 0.f;
  49.         IActor* pClientActor = gEnv->pGameFramework->GetClientActor();
  50.         if (pClientActor)
  51.         {
  52.                 distToPlayer = (pClientActor->GetEntity()->GetWorldPos() - params.pos).GetLength();
  53.                 tryToAttachEffect = tryToAttachEffect && (pClientActor->GetEntityId() != params.trg);
  54.         }
  55.  
  56.         SMFXParticleEntries::const_iterator end = m_particleParams.m_entries.end();
  57.         for (SMFXParticleEntries::const_iterator it = m_particleParams.m_entries.begin(); it != end; ++it)
  58.         {
  59.                 // choose effect based on distance
  60.                 if ((it->maxdist == 0.f) || (distToPlayer <= it->maxdist) && !it->name.empty())
  61.                 {
  62.                         IParticleEffect* pParticle = gEnv->pParticleManager->FindEffect(it->name.c_str());
  63.  
  64.                         if (pParticle)
  65.                         {
  66.                                 const float pfx_minscale = (it->minscale != 0.f) ? it->minscale : CMaterialEffectsCVars::Get().mfx_pfx_minScale;
  67.                                 const float pfx_maxscale = (it->maxscale != 0.f) ? it->maxscale : CMaterialEffectsCVars::Get().mfx_pfx_maxScale;
  68.                                 const float pfx_maxdist = (it->maxscaledist != 0.f) ? it->maxscaledist : CMaterialEffectsCVars::Get().mfx_pfx_maxDist;
  69.  
  70.                                 const float truscale = pfx_minscale + ((pfx_maxscale - pfx_minscale) * (distToPlayer != 0.f ? min(1.0f, distToPlayer / pfx_maxdist) : 1.f));
  71.  
  72.                                 bool particleSpawnedAndAttached = tryToAttachEffect ? AttachToTarget(*it, params, pParticle, dir, truscale) : false;
  73.  
  74.                                 // If not attached, just spawn the particle
  75.                                 if (particleSpawnedAndAttached == false)
  76.                                 {
  77.                                         pParticle->Spawn(true, IParticleEffect::ParticleLoc(pos, dir, truscale));
  78.                                 }
  79.                         }
  80.  
  81.                         break;
  82.                 }
  83.         }
  84. }
  85.  
  86. bool CMFXParticleEffect::AttachToTarget(const SMFXParticleEntry& particleParams, const SMFXRunTimeEffectParams& params, IParticleEffect* pParticleEffect, const Vec3& dir, float scale)
  87. {
  88.         bool shouldTryToAttach = particleParams.attachToTarget && (params.trg != 0);
  89.         if (!shouldTryToAttach)
  90.         {
  91.                 return false;
  92.         }
  93.  
  94.         IEntity* pTargetEntity = gEnv->pEntitySystem->GetEntity(params.trg);
  95.         if (pTargetEntity)
  96.         {
  97.                 //Try to figure out if it's a character using physics type
  98.                 IPhysicalEntity* pTargetPhysics = pTargetEntity->GetPhysics();
  99.                 int physicsType = pTargetPhysics ? pTargetPhysics->GetType() : PE_NONE;
  100.  
  101.                 bool isCharacter = (physicsType == PE_LIVING) || (physicsType == PE_ARTICULATED);
  102.  
  103.                 if (isCharacter)
  104.                 {
  105.                         return AttachToCharacter(*pTargetEntity, particleParams, params, dir, scale);
  106.                 }
  107.                 //else
  108.                 //{
  109.                 //return AttachToEntity(*pTargetEntity, particleParams, params, pParticleEffect, dir, scale);
  110.                 //}
  111.         }
  112.  
  113.         return false;
  114. }
  115.  
  116. bool CMFXParticleEffect::AttachToCharacter(IEntity& targetEntity, const SMFXParticleEntry& particleParams, const SMFXRunTimeEffectParams& params, const Vec3& dir, float scale)
  117. {
  118.         if (params.partID >= 0)
  119.         {
  120.                 //Assume character is loaded in first slot
  121.                 //We could iterate through all available slots, but first one should be good enough
  122.                 ICharacterInstance* pCharacterInstace = targetEntity.GetCharacter(0);
  123.                 ISkeletonPose* pSkeletonPose = pCharacterInstace ? pCharacterInstace->GetISkeletonPose() : NULL;
  124.                 if (pSkeletonPose)
  125.                 {
  126.                         IDefaultSkeleton& rIDefaultSkeleton = pCharacterInstace->GetIDefaultSkeleton();
  127.                         //It hit the character, but probably in a physicalized attached part, like armor plates, etc
  128.                         if (params.partID >= rIDefaultSkeleton.GetJointCount())
  129.                         {
  130.                                 return false;
  131.                         }
  132.  
  133.                         //It hit some valid joint, create an attachment
  134.                         const char* boneName = rIDefaultSkeleton.GetJointNameByID(params.partID);
  135.                         TAttachmentName attachmentName;
  136.                         GetNextCharacterAttachmentName(attachmentName);
  137.  
  138.                         IAttachmentManager* pAttachmentManager = pCharacterInstace->GetIAttachmentManager();
  139.                         CRY_ASSERT(pAttachmentManager);
  140.  
  141.                         //Remove the attachment first (in case was created before)
  142.                         pAttachmentManager->RemoveAttachmentByName(attachmentName.c_str());
  143.  
  144.                         //Create attachment on nearest hit bone
  145.                         IAttachment* pAttachment = pAttachmentManager->CreateAttachment(attachmentName.c_str(), CA_BONE, boneName, false);
  146.                         if (pAttachment)
  147.                         {
  148.                                 //Apply relative offsets
  149.                                 const QuatT boneLocation = pSkeletonPose->GetAbsJointByID(params.partID);
  150.                                 Matrix34 inverseJointTM = targetEntity.GetWorldTM() * Matrix34(boneLocation);
  151.                                 inverseJointTM.Invert();
  152.                                 Vec3 attachmentOffsetPosition = inverseJointTM * params.pos;
  153.                                 Quat attachmentOffsetRotation = Quat(inverseJointTM) * targetEntity.GetRotation();
  154.  
  155.                                 CRY_ASSERT(attachmentOffsetPosition.IsValid());
  156.                                 //CRY_ASSERT(attachmentOffsetRotation.IsUnit());
  157.  
  158.                                 pAttachment->SetAttRelativeDefault(QuatT(attachmentOffsetRotation, attachmentOffsetPosition));
  159.  
  160.                                 //Finally attach the effect
  161.                                 CEffectAttachment* pEffectAttachment = new CEffectAttachment(particleParams.name.c_str(), Vec3(0, 0, 0), dir, scale);
  162.                                 pAttachment->AddBinding(pEffectAttachment);
  163.  
  164.                                 return true;
  165.                         }
  166.                 }
  167.         }
  168.  
  169.         return false;
  170. }
  171.  
  172. bool CMFXParticleEffect::AttachToEntity(IEntity& targetEntity, const SMFXParticleEntry& particleParams, const SMFXRunTimeEffectParams& params, IParticleEffect* pParticleEffect, const Vec3& dir, float scale)
  173. {
  174.         if (pParticleEffect)
  175.         {
  176.                 int effectSlot = targetEntity.LoadParticleEmitter(-1, pParticleEffect);
  177.                 if (effectSlot >= 0)
  178.                 {
  179.                         Matrix34 hitTM;
  180.                         hitTM.Set(Vec3(1.0f, 1.0f, 1.0f), Quat::CreateRotationVDir(dir), params.pos);
  181.  
  182.                         Matrix34 localEffectTM = targetEntity.GetWorldTM().GetInverted() * hitTM;
  183.                         localEffectTM.ScaleColumn(Vec3(scale, scale, scale));
  184.  
  185.                         CRY_ASSERT(localEffectTM.IsValid());
  186.  
  187.                         targetEntity.SetSlotLocalTM(effectSlot, localEffectTM);
  188.  
  189.                         return true;
  190.                 }
  191.         }
  192.  
  193.         return false;
  194. }
  195.  
  196. void CMFXParticleEffect::GetNextCharacterAttachmentName(TAttachmentName& attachmentName)
  197. {
  198.         static int nextId = 0;
  199.         const int maxAttachmentIds = 6;
  200.  
  201.         attachmentName.Format("Mfx_Particle_Attachment%d", nextId);
  202.  
  203.         nextId = (nextId < maxAttachmentIds) ? (nextId + 1) : 0;
  204. }
  205.  
  206. void CMFXParticleEffect::LoadParamsFromXml(const XmlNodeRef& paramsNode)
  207. {
  208.         // Xml data format
  209.         /*
  210.            <Particle>
  211.            <Name userdata="..." scale="..." maxdist="..." minscale="..." maxscale="..." maxscaledist="..." attach="...">particle.name</Name>
  212.            <Direction>DirectionType</Direction>
  213.            </Particle>
  214.          */
  215.  
  216.         for (int i = 0; i < paramsNode->getChildCount(); ++i)
  217.         {
  218.                 XmlNodeRef child = paramsNode->getChild(i);
  219.                 if (!strcmp(child->getTag(), "Name"))
  220.                 {
  221.                         SMFXParticleEntry entry;
  222.                         entry.name = child->getContent();
  223.  
  224.                         if (child->haveAttr("userdata"))
  225.                                 entry.userdata = child->getAttr("userdata");
  226.  
  227.                         if (child->haveAttr("scale"))
  228.                                 child->getAttr("scale", entry.scale);
  229.  
  230.                         if (child->haveAttr("maxdist"))
  231.                                 child->getAttr("maxdist", entry.maxdist);
  232.  
  233.                         if (child->haveAttr("minscale"))
  234.                                 child->getAttr("minscale", entry.minscale);
  235.  
  236.                         if (child->haveAttr("maxscale"))
  237.                                 child->getAttr("maxscale", entry.maxscale);
  238.  
  239.                         if (child->haveAttr("maxscaledist"))
  240.                                 child->getAttr("maxscaledist", entry.maxscaledist);
  241.  
  242.                         if (child->haveAttr("attach"))
  243.                                 child->getAttr("attach", entry.attachToTarget);
  244.  
  245.                         m_particleParams.m_entries.push_back(entry);
  246.                 }
  247.         }
  248.  
  249.         SMFXParticleParams::EDirectionType directionType = SMFXParticleParams::eDT_Normal;
  250.         XmlNodeRef dirType = paramsNode->findChild("Direction");
  251.         if (dirType)
  252.         {
  253.                 const char* val = dirType->getContent();
  254.                 if (!strcmp(val, "Normal"))
  255.                 {
  256.                         directionType = SMFXParticleParams::eDT_Normal;
  257.                 }
  258.                 else if (!strcmp(val, "Ricochet"))
  259.                 {
  260.                         directionType = SMFXParticleParams::eDT_Ricochet;
  261.                 }
  262.                 else if (!strcmp(val, "ProjectileDir"))
  263.                 {
  264.                         directionType = SMFXParticleParams::eDT_ProjectileDir;
  265.                 }
  266.         }
  267.         m_particleParams.directionType = directionType;
  268.  
  269. }
  270.  
  271. void CMFXParticleEffect::GetResources(SMFXResourceList& resourceList) const
  272. {
  273.         SMFXParticleListNode* listNode = SMFXParticleListNode::Create();
  274.  
  275.         if (!m_particleParams.m_entries.empty())
  276.         {
  277.                 const SMFXParticleEntry& entry = m_particleParams.m_entries.back();
  278.                 listNode->m_particleParams.name = entry.name.c_str();
  279.                 listNode->m_particleParams.userdata = entry.userdata.c_str();
  280.                 listNode->m_particleParams.scale = entry.scale;
  281.         }
  282.  
  283.         SMFXParticleListNode* next = resourceList.m_particleList;
  284.  
  285.         if (!next)
  286.                 resourceList.m_particleList = listNode;
  287.         else
  288.         {
  289.                 while (next->pNext)
  290.                         next = next->pNext;
  291.  
  292.                 next->pNext = listNode;
  293.         }
  294. }
  295.  
  296. void CMFXParticleEffect::PreLoadAssets()
  297. {
  298.         LOADING_TIME_PROFILE_SECTION;
  299.  
  300.         SMFXParticleEntries::iterator it = m_particleParams.m_entries.begin();
  301.         while (it != m_particleParams.m_entries.end())
  302.         {
  303.                 if (gEnv->pParticleManager->FindEffect(it->name.c_str()) == NULL)
  304.                 {
  305.                         CryLog("MFXParticleEffect: Unable to find effect <%s>; Removing from list", it->name.c_str());
  306.                         it = m_particleParams.m_entries.erase(it);
  307.                 }
  308.                 else
  309.                 {
  310.                         ++it;
  311.                 }
  312.  
  313.                 SLICE_AND_SLEEP();
  314.         }
  315. }
  316.  
  317. void CMFXParticleEffect::GetMemoryUsage(ICrySizer* pSizer) const
  318. {
  319.         pSizer->AddObject(this, sizeof(*this));
  320.         pSizer->AddObject(m_particleParams.m_entries);
  321.         for (size_t i = 0; i < m_particleParams.m_entries.size(); i++)
  322.         {
  323.                 pSizer->AddObject(m_particleParams.m_entries[i].name);
  324.                 pSizer->AddObject(m_particleParams.m_entries[i].userdata);
  325.         }
  326. }
  327.  
downloadMFXParticleEffect.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