BVB Source Codes

CRYENGINE Show FeatureMotion.cpp Source code

Return Download CRYENGINE: download FeatureMotion.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. #include "FeatureMotion.h"
  5. #include "ParticleSystem/ParticleEmitter.h"
  6. #include <CrySerialization/Math.h>
  7. #include "FeatureCollision.h"
  8.  
  9. CRY_PFX2_DBG
  10.  
  11. namespace pfx2
  12. {
  13.  
  14. void ILocalEffector::Serialize(Serialization::IArchive& ar)
  15. {
  16.         ar(m_enabled);
  17. }
  18.  
  19. //////////////////////////////////////////////////////////////////////////
  20. // CFeatureMotionPhysics
  21.  
  22. EParticleDataType PDT(EPDT_Gravity, float, 1, BHasInit(true));
  23. EParticleDataType PDT(EPDT_Drag, float, 1, BHasInit(true));
  24. EParticleDataType PDT(EPVF_Acceleration, float, 3);
  25. EParticleDataType PDT(EPVF_VelocityField, float, 3);
  26.  
  27. CFeatureMotionPhysics::CFeatureMotionPhysics()
  28.         : m_gravity(0.0f)
  29.         , m_drag(0.0f)
  30.         , m_windMultiplier(1.0f)
  31.         , m_angularDragMultiplier(1.0f)
  32.         , m_uniformAcceleration(ZERO)
  33.         , m_uniformWind(ZERO)
  34.         , m_linearIntegrator(EI_Linear)
  35.         , m_pCollisionFeature(nullptr)
  36.         , CParticleFeature(gpu_pfx2::eGpuFeatureType_Motion)
  37. {
  38. }
  39.  
  40. void CFeatureMotionPhysics::AddToComponent(CParticleComponent* pComponent, SComponentParams* pParams)
  41. {
  42.         pComponent->AddToUpdateList(EUL_Update, this);
  43.  
  44.         m_gravity.AddToComponent(pComponent, this, EPDT_Gravity);
  45.         m_drag.AddToComponent(pComponent, this, EPDT_Drag);
  46.  
  47.         auto it = std::remove_if(m_localEffectors.begin(), m_localEffectors.end(), [](const PLocalEffector& ptr) { return !ptr; });
  48.         m_localEffectors.erase(it, m_localEffectors.end());
  49.         m_computeList.clear();
  50.         m_moveList.clear();
  51.         for (PLocalEffector pEffector : m_localEffectors)
  52.         {
  53.                 if (pEffector->IsEnabled())
  54.                         pEffector->AddToMotionFeature(pComponent, this);
  55.         }
  56.  
  57.         const bool hasDrag = m_drag.GetBaseValue() != 0.0f;
  58.         const bool hasGravity = m_gravity.GetBaseValue() != 0.0f || !m_uniformAcceleration.IsZero();
  59.         const bool hasEffectors = !m_localEffectors.empty();
  60.  
  61.         if (hasDrag || hasGravity || hasEffectors)
  62.                 m_linearIntegrator = EI_DragFast;
  63.         else
  64.                 m_linearIntegrator = EI_Linear;
  65.         m_angularIntegrator = m_linearIntegrator;
  66.         if (m_angularDragMultiplier == 0.0f)
  67.                 m_angularIntegrator = EI_Linear;
  68.  
  69.         if (auto pInt = GetGpuInterface())
  70.         {
  71.                 gpu_pfx2::SFeatureParametersMotionPhysics params;
  72.                 params.gravity = m_gravity.GetBaseValue();
  73.                 params.drag = m_drag.GetBaseValue();
  74.                 params.uniformAcceleration = m_uniformAcceleration;
  75.                 params.uniformWind = m_uniformWind;
  76.                 params.windMultiplier = m_windMultiplier;
  77.                 pInt->SetParameters(params);
  78.  
  79.                 for (PLocalEffector pEffector : m_localEffectors)
  80.                 {
  81.                         if (pEffector->IsEnabled())
  82.                                 pEffector->SetParameters(pInt);
  83.                 }
  84.         }
  85.  
  86.         m_pCollisionFeature = pComponent->GetCFeatureByType<CFeatureCollision>();
  87.         if (m_pCollisionFeature && m_pCollisionFeature->IsActive())
  88.         {
  89.                 pComponent->AddToUpdateList(EUL_InitUpdate, this);
  90.                 pComponent->AddParticleData(EPDT_ContactPoint);
  91.         }
  92.         else
  93.                 m_pCollisionFeature = nullptr;
  94. }
  95.  
  96. void CFeatureMotionPhysics::Serialize(Serialization::IArchive& ar)
  97. {
  98.         CParticleFeature::Serialize(ar);
  99.         ar(m_gravity, "gravity", "Gravity Scale");
  100.         ar(m_drag, "drag", "Drag");
  101.         ar(m_uniformAcceleration, "UniformAcceleration", "Uniform Acceleration");
  102.         ar(m_uniformWind, "UniformWind", "Uniform Wind");
  103.         ar(m_windMultiplier, "windMultiplier", "Level Wind Scale");
  104.         if (!ar(m_angularDragMultiplier, "AngularDragMultiplier", "Angular Drag Multiplier"))
  105.                 m_angularDragMultiplier = 0.0f;
  106.         ar(m_localEffectors, "localEffectors", "Local Effectors");
  107. }
  108.  
  109. void CFeatureMotionPhysics::InitParticles(const SUpdateContext& context)
  110. {
  111.         m_gravity.InitParticles(context, EPDT_Gravity);
  112.         m_drag.InitParticles(context, EPDT_Drag);
  113.  
  114.         CParticleContainer& container = context.m_container;
  115.         const SContactPoint defaultVal;
  116.         const SUpdateRange spawnRange(container.GetFirstSpawnParticleId(), container.GetLastParticleId());
  117.         container.FillData(EPDT_ContactPoint, defaultVal, spawnRange);
  118. }
  119.  
  120. void CFeatureMotionPhysics::Update(const SUpdateContext& context)
  121. {
  122.         CRY_PFX2_PROFILE_DETAIL;
  123.  
  124.         CParticleContainer& container = context.m_container;
  125.         m_gravity.Update(context, EPDT_Gravity);
  126.         m_drag.Update(context, EPDT_Drag);
  127.  
  128.         if (m_pCollisionFeature)
  129.                 ProcessCollisions(context);
  130.  
  131.         IOVec3Stream velocityField = container.GetIOVec3Stream(EPVF_VelocityField);
  132.         IOVec3Stream accelerations = container.GetIOVec3Stream(EPVF_Acceleration);
  133.         for (ILocalEffector* pEffector : m_computeList)
  134.                 pEffector->ComputeEffector(context, velocityField, accelerations);
  135.  
  136.         if (!m_moveList.empty())
  137.         {
  138.                 STempVec3Stream moveBefore(context.m_pMemHeap, context.m_updateRange);
  139.                 STempVec3Stream moveAfter(context.m_pMemHeap, context.m_updateRange);
  140.                 moveBefore.Clear(context.m_updateRange);
  141.                 moveAfter.Clear(context.m_updateRange);
  142.  
  143.                 for (ILocalEffector* pEffector : m_moveList)
  144.                         pEffector->ComputeMove(context, moveBefore.GetIOVec3Stream(), 0.0f);
  145.                
  146.                 Integrate(context);
  147.                
  148.                 for (ILocalEffector* pEffector : m_moveList)
  149.                         pEffector->ComputeMove(context, moveAfter.GetIOVec3Stream(), context.m_deltaTime);
  150.  
  151.                 IOVec3Stream positions = container.GetIOVec3Stream(EPVF_Position);
  152.                 CRY_PFX2_FOR_ACTIVE_PARTICLESGROUP(context)
  153.                 {
  154.                         const Vec3v position0 = positions.Load(particleGroupId);
  155.                         const Vec3v move0 = moveBefore.GetIOVec3Stream().Load(particleGroupId);
  156.                         const Vec3v move1 = moveAfter.GetIOVec3Stream().Load(particleGroupId);
  157.                         const Vec3v position1 = position0 + (move1 - move0);
  158.                         positions.Store(particleGroupId, position1);
  159.                 }
  160.                 CRY_PFX2_FOR_END;
  161.         }
  162.         else
  163.         {
  164.                 Integrate(context);
  165.         }
  166.  
  167.         if (m_pCollisionFeature)
  168.                 CollisionResponse(context);
  169. }
  170.  
  171. void CFeatureMotionPhysics::AddToComputeList(ILocalEffector* pEffector)
  172. {
  173.         if (std::find(m_computeList.begin(), m_computeList.end(), pEffector) == m_computeList.end())
  174.                 m_computeList.push_back(pEffector);
  175. }
  176.  
  177. void CFeatureMotionPhysics::AddToMoveList(ILocalEffector* pEffector)
  178. {
  179.         if (std::find(m_moveList.begin(), m_moveList.end(), pEffector) == m_moveList.end())
  180.                 m_moveList.push_back(pEffector);
  181. }
  182.  
  183. void CFeatureMotionPhysics::Integrate(const SUpdateContext& context)
  184. {
  185.         CParticleContainer& container = context.m_container;
  186.  
  187.         switch (m_linearIntegrator)
  188.         {
  189.         case EI_Linear:
  190.                 LinearSimpleIntegral(context);
  191.                 break;
  192.         case EI_DragFast:
  193.                 LinearDragFastIntegral(context);
  194.                 break;
  195.         }
  196.  
  197.         const bool spin2D = container.HasData(EPDT_Spin2D) && container.HasData(EPDT_Angle2D);
  198.         const bool spin3D = container.HasData(EPVF_AngularVelocity) && container.HasData(EPQF_Orientation);
  199.         if (spin2D || spin3D)
  200.         {
  201.                 switch (m_angularIntegrator)
  202.                 {
  203.                 case EI_Linear:
  204.                         AngularSimpleIntegral(context);
  205.                         break;
  206.                 case EI_DragFast:
  207.                         AngularDragFastIntegral(context);
  208.                         break;
  209.                 }
  210.         }
  211. }
  212.  
  213. void CFeatureMotionPhysics::LinearSimpleIntegral(const SUpdateContext& context)
  214. {
  215.         CRY_PFX2_PROFILE_DETAIL;
  216.  
  217.         CParticleContainer& container = context.m_container;
  218.         IOVec3Stream position = container.GetIOVec3Stream(EPVF_Position);
  219.         IVec3Stream velocity = container.GetIVec3Stream(EPVF_Velocity);
  220.         IFStream normAges = container.GetIFStream(EPDT_NormalAge);
  221.         const float deltaTime = context.m_deltaTime;
  222.         const floatv deltaTimeV = ToFloatv(deltaTime);
  223.        
  224.         CRY_PFX2_FOR_ACTIVE_PARTICLESGROUP(context)
  225.         {
  226.                 const Vec3v p0 = position.Load(particleGroupId);
  227.                 const Vec3v v0 = velocity.Load(particleGroupId);
  228.                 const floatv normAge = normAges.Load(particleGroupId);
  229.                 const floatv dT = DeltaTime(normAge, deltaTimeV);
  230.                 const Vec3v p1 = MAdd(v0, dT, p0);
  231.                 position.Store(particleGroupId, p1);
  232.         }
  233.         CRY_PFX2_FOR_END;
  234. }
  235.  
  236. void CFeatureMotionPhysics::LinearDragFastIntegral(const SUpdateContext& context)
  237. {
  238.         CRY_PFX2_PROFILE_DETAIL;
  239.  
  240.         CParticleEmitter* pEmitter = context.m_runtime.GetEmitter();
  241.         CParticleContainer& container = context.m_container;
  242.  
  243.         IOVec3Stream positions = container.GetIOVec3Stream(EPVF_Position);
  244.         IOVec3Stream velocities = container.GetIOVec3Stream(EPVF_Velocity);
  245.         IVec3Stream velocityField = container.GetIVec3Stream(EPVF_VelocityField);
  246.         IVec3Stream accelerations = container.GetIVec3Stream(EPVF_Acceleration);
  247.         IFStream gravities = container.GetIFStream(EPDT_Gravity, 0.0f);
  248.         IFStream drags = container.GetIFStream(EPDT_Drag);
  249.         IFStream normAges = container.GetIFStream(EPDT_NormalAge);
  250.         const floatv fTime = ToFloatv(context.m_deltaTime);
  251.  
  252.         const Vec3v physAccel = ToVec3v(pEmitter->GetPhysicsEnv().m_UniformForces.vAccel);
  253.         const Vec3v physWind = ToVec3v(pEmitter->GetPhysicsEnv().m_UniformForces.vWind * m_windMultiplier + m_uniformWind);
  254.         const Vec3v uniformAccel = ToVec3v(m_uniformAcceleration);
  255.  
  256.         const float maxDragFactor = m_drag.GetValueRange(context).end * context.m_deltaTime;
  257.         const floatv dragReduction = ToFloatv(div_min(1.0f - exp(-maxDragFactor), maxDragFactor, 1.0f));
  258.  
  259.         CRY_PFX2_FOR_ACTIVE_PARTICLESGROUP(context)
  260.         {
  261.                 const floatv normAge = normAges.Load(particleGroupId);
  262.                 const floatv dT = DeltaTime(normAge, fTime);
  263.                 const floatv dTh = dT * ToFloatv(0.5f);
  264.  
  265.                 const Vec3v partAccel = accelerations.SafeLoad(particleGroupId);
  266.                 const floatv gravMult = gravities.SafeLoad(particleGroupId);
  267.                 const Vec3v p0 = positions.Load(particleGroupId);
  268.                 const Vec3v v0 = velocities.Load(particleGroupId);
  269.  
  270.                 Vec3v a = MAdd(physAccel, gravMult, partAccel) + uniformAccel;
  271.                 if (maxDragFactor > 0.0f)
  272.                 {
  273.                         const Vec3v fieldVel = velocityField.SafeLoad(particleGroupId);
  274.                         const Vec3v partVel = physWind + fieldVel;
  275.                         const floatv drag = drags.SafeLoad(particleGroupId) * dragReduction;
  276.                         a = MAdd(partVel - v0, drag, a);                        // (partVel-v0)*drag + a
  277.                 }
  278.                 const Vec3v v1 = MAdd(a, dT, v0);                         // a*dT + v0
  279.                 const Vec3v p1 = MAdd(v0 + v1, dTh, p0);                  // (v0 + v1)/2 * dT + p0
  280.  
  281.                 positions.Store(particleGroupId, p1);
  282.                 velocities.Store(particleGroupId, v1);
  283.         }
  284.         CRY_PFX2_FOR_END;
  285. }
  286.  
  287. void CFeatureMotionPhysics::AngularSimpleIntegral(const SUpdateContext& context)
  288. {
  289.         CRY_PFX2_PROFILE_DETAIL;
  290.  
  291.         CParticleContainer& container = context.m_container;
  292.         const IFStream normAges = container.GetIFStream(EPDT_NormalAge);
  293.         const IFStream spins = container.GetIFStream(EPDT_Spin2D);
  294.         const IVec3Stream angularVelocities = container.GetIVec3Stream(EPVF_AngularVelocity);
  295.         const float deltaTime = context.m_deltaTime;
  296.         const floatv deltaTimeV = ToFloatv(deltaTime);
  297.         IOFStream angles = container.GetIOFStream(EPDT_Angle2D);
  298.         IOQuatStream orientations = container.GetIOQuatStream(EPQF_Orientation);
  299.  
  300.         const bool spin2D = container.HasData(EPDT_Spin2D) && container.HasData(EPDT_Angle2D);
  301.         const bool spin3D = container.HasData(EPVF_AngularVelocity) && container.HasData(EPQF_Orientation);
  302.  
  303.         CRY_PFX2_FOR_ACTIVE_PARTICLESGROUP(context)
  304.         {
  305.                 const floatv normAge = normAges.Load(particleGroupId);
  306.                 const floatv dT = DeltaTime(normAge, deltaTimeV);
  307.  
  308.                 if (spin2D)
  309.                 {
  310.                         const floatv spin0 = spins.Load(particleGroupId);
  311.                         const floatv angle0 = angles.Load(particleGroupId);
  312.                         const floatv angle1 = MAdd(spin0, deltaTimeV, angle0);
  313.                         angles.Store(particleGroupId, angle1);
  314.                 }
  315.  
  316.                 if (spin3D)
  317.                 {
  318.                         const Vec3v angularVelocity = angularVelocities.Load(particleGroupId);
  319.                         const Quatv orientation0 = orientations.Load(particleGroupId);
  320.                         const Quatv orientation1 = AddAngularVelocity(orientation0, angularVelocity, deltaTimeV);
  321.                         orientations.Store(particleGroupId, orientation1);
  322.                 }
  323.         }
  324.         CRY_PFX2_FOR_END;
  325. }
  326.  
  327. void CFeatureMotionPhysics::AngularDragFastIntegral(const SUpdateContext& context)
  328. {
  329.         CRY_PFX2_PROFILE_DETAIL;
  330.  
  331.         CParticleContainer& container = context.m_container;
  332.         const IFStream normAges = container.GetIFStream(EPDT_NormalAge);
  333.         const IFStream drags = container.GetIFStream(EPDT_Drag);
  334.         const float deltaTime = context.m_deltaTime;
  335.         const floatv deltaTimeV = ToFloatv(deltaTime);
  336.         IOFStream spins = container.GetIOFStream(EPDT_Spin2D);
  337.         IOVec3Stream angularVelocities = container.GetIOVec3Stream(EPVF_AngularVelocity);
  338.         IOFStream angles = container.GetIOFStream(EPDT_Angle2D);
  339.         IOQuatStream orientations = container.GetIOQuatStream(EPQF_Orientation);
  340.  
  341.         const float maxDragFactor = m_drag.GetValueRange(context).end * context.m_deltaTime * m_angularDragMultiplier;
  342.         const floatv dragReduction = ToFloatv(div_min(1.0f - exp_tpl(-maxDragFactor), maxDragFactor, 1.0f));
  343.  
  344.         const bool spin2D = container.HasData(EPDT_Spin2D) && container.HasData(EPDT_Angle2D);
  345.         const bool spin3D = container.HasData(EPVF_AngularVelocity) && container.HasData(EPQF_Orientation);
  346.  
  347.         CRY_PFX2_FOR_ACTIVE_PARTICLESGROUP(context)
  348.         {
  349.                 const floatv normAge = normAges.Load(particleGroupId);
  350.                 const floatv dT = DeltaTime(normAge, deltaTimeV);
  351.                 const floatv drag = drags.SafeLoad(particleGroupId) * dragReduction;
  352.  
  353.                 if (spin2D)
  354.                 {
  355.                         const floatv angle0 = angles.Load(particleGroupId);
  356.                         const floatv spin0 = spins.Load(particleGroupId);
  357.                         const floatv a = -spin0 * drag;
  358.                         const floatv spin1 = MAdd(a, dT, spin0);
  359.                         const floatv angle1 = MAdd(spin1, deltaTimeV, angle0);
  360.                         angles.Store(particleGroupId, angle1);
  361.                         spins.Store(particleGroupId, spin1);
  362.                 }
  363.  
  364.                 if (spin3D)
  365.                 {
  366.                         const Quatv orientation0 = orientations.Load(particleGroupId);
  367.                         const Vec3v angularVelocity0 = angularVelocities.Load(particleGroupId);
  368.                         const Vec3v a = -angularVelocity0 * drag;
  369.                         const Vec3v angularVelocity1 = MAdd(a, dT, angularVelocity0);
  370.                         const Quatv orientation1 = AddAngularVelocity(orientation0, angularVelocity1, deltaTimeV);
  371.                         orientations.Store(particleGroupId, orientation1);
  372.                         angularVelocities.Store(particleGroupId, angularVelocity1);
  373.                 }
  374.         }
  375.         CRY_PFX2_FOR_END;
  376. }
  377.  
  378. void CFeatureMotionPhysics::ProcessCollisions(const SUpdateContext& context)
  379. {
  380.         // #PFX2_TODO : raytrace caching not implemented yet
  381.  
  382.         IPhysicalWorld* pPhysics = gEnv->pPhysicalWorld;
  383.  
  384.         const int collisionsFlags = sf_max_pierceable | (geom_colltype_ray | geom_colltype13) << rwi_colltype_bit | rwi_colltype_any | rwi_ignore_noncolliding;
  385.         const int raytraceFilter = m_pCollisionFeature->GetRayTraceFilter();
  386.  
  387.         CParticleContainer& container = context.m_container;
  388.         IOVec3Stream positions = container.GetIOVec3Stream(EPVF_Position);
  389.         IOVec3Stream velocities = container.GetIOVec3Stream(EPVF_Velocity);
  390.         IFStream sizes = container.GetIFStream(EPDT_Size);
  391.         const IFStream normAges = container.GetIFStream(EPDT_NormalAge);
  392.         const float deltaTime = context.m_deltaTime;
  393.         const float threshold = 1.0f / 1024.0f;
  394.         TIOStream<SContactPoint> contactPoints = container.GetTIOStream<SContactPoint>(EPDT_ContactPoint);
  395.  
  396.         CRY_PFX2_FOR_ACTIVE_PARTICLES(context)
  397.         {
  398.                 SContactPoint contact = contactPoints.Load(particleId);
  399.                 contact.m_flags &= ~uint(EContactPointsFlags::Collided);
  400.                 if (!(contact.m_flags & uint(EContactPointsFlags::Sliding)))
  401.                         contact.m_flags &= ~uint(EContactPointsFlags::Active);
  402.                 contactPoints.Store(particleId, contact);
  403.                 if (contact.m_flags & uint(EContactPointsFlags::Ignore))
  404.                         continue;
  405.  
  406.                 const Vec3 position0 = positions.Load(particleId);
  407.                 const Vec3 velocity0 = velocities.Load(particleId);
  408.                 const float normAge = normAges.Load(particleId);
  409.                 const float dT = DeltaTime(normAge, deltaTime);
  410.                 const Vec3 rayStart = position0;
  411.                 const Vec3 rayDir = velocity0 * dT;
  412.                 const float size = sizes.Load(particleId);
  413.  
  414.                 if (rayDir.GetLengthSquared() < threshold)
  415.                         continue;
  416.  
  417.                 ray_hit rayHit;
  418.                 const int numHits = pPhysics->RayWorldIntersection(
  419.                         rayStart, rayDir, raytraceFilter, collisionsFlags,
  420.                         &rayHit, 1);
  421.                 if (numHits == 0)
  422.                         continue;
  423.                 if (rayHit.n.Dot(velocity0) >= 0.0f)
  424.                         continue;
  425.  
  426.                 contact.m_point = rayHit.pt;
  427.                 contact.m_normal = rayHit.n;
  428.                 contact.m_totalCollisions++;
  429.                 contact.m_flags = uint(EContactPointsFlags::Active) | uint(EContactPointsFlags::Collided);
  430.                 contactPoints.Store(particleId, contact);
  431.         }
  432.         CRY_PFX2_FOR_END;
  433. }
  434.  
  435. void CFeatureMotionPhysics::CollisionResponse(const SUpdateContext& context)
  436. {
  437.         CParticleContainer& container = context.m_container;
  438.         TIOStream<SContactPoint> contactPoints = container.GetTIOStream<SContactPoint>(EPDT_ContactPoint);
  439.         IOVec3Stream positions = container.GetIOVec3Stream(EPVF_Position);
  440.         IOVec3Stream velocities = container.GetIOVec3Stream(EPVF_Velocity);
  441.         const float elasticity = m_pCollisionFeature->GetElasticity();
  442.  
  443.         CRY_PFX2_FOR_ACTIVE_PARTICLES(context)
  444.         {
  445.                 SContactPoint contact = contactPoints.Load(particleId);
  446.                 if (!(contact.m_flags & uint(EContactPointsFlags::Active)))
  447.                         continue;
  448.                 if (contact.m_flags & uint(EContactPointsFlags::Ignore))
  449.                         continue;
  450.  
  451.                 const Vec3 normal = contact.m_normal;
  452.                 const Plane plane = Plane(normal, -contact.m_point.Dot(normal));
  453.                 const Vec3 position0 = positions.Load(particleId);
  454.                 const Vec3 velocity0 = velocities.Load(particleId);
  455.  
  456.                 const float distToPlane = -plane.DistFromPlane(position0);
  457.                 if (distToPlane < 0.0f)
  458.                         continue;
  459.                 if (normal.Dot(velocity0) > 0.0f)
  460.                         continue;
  461.                 const Vec3 position1 = position0 + normal * distToPlane;
  462.                 positions.Store(particleId, position1);
  463.  
  464.                 const Vec3 normalVelocity0 = normal * normal.Dot(velocity0);
  465.                 const Vec3 tangentVelocity0 = velocity0 - normalVelocity0;
  466.                 const Vec3 velocity1 = -normalVelocity0 * elasticity + tangentVelocity0;
  467.  
  468.                 const float collideBufferDist = 1.0f / 1024.0f;
  469.                 const float velBounce = (normalVelocity0 * elasticity).GetLengthSquared();
  470.                 if (velBounce <= collideBufferDist)
  471.                 {
  472.                         contact.m_flags |= uint(EContactPointsFlags::Sliding);
  473.                         contactPoints.Store(particleId, contact);
  474.                 }
  475.  
  476.                 velocities.Store(particleId, velocity1);
  477.  
  478.                 if (contact.m_flags & uint(EContactPointsFlags::Sliding))
  479.                 {
  480.                         contact.m_point = position1;
  481.                         contactPoints.Store(particleId, contact);
  482.                 }
  483.         }
  484.         CRY_PFX2_FOR_END;
  485. }
  486.  
  487. CRY_PFX2_IMPLEMENT_FEATURE(CParticleFeature, CFeatureMotionPhysics, "Motion", "Physics", colorMotion);
  488.  
  489. //////////////////////////////////////////////////////////////////////////
  490. // CFeatureMotionCryPhysics
  491.  
  492. EParticleDataType PDT(EPDT_PhysicalEntity, IPhysicalEntity*);
  493.  
  494. CFeatureMotionCryPhysics::CFeatureMotionCryPhysics()
  495.         : m_gravity(1.0f)
  496.         , m_drag(0.0f)
  497.         , m_density(1.0f)
  498.         , m_thickness(0.0f)
  499.         , m_uniformAcceleration(ZERO)
  500. {
  501. }
  502.  
  503. void CFeatureMotionCryPhysics::AddToComponent(CParticleComponent* pComponent, SComponentParams* pParams)
  504. {
  505.         pComponent->AddToUpdateList(EUL_PostInitUpdate, this);
  506.         pComponent->AddToUpdateList(EUL_Update, this);
  507.         pComponent->AddParticleData(EPDT_PhysicalEntity);
  508.         pComponent->AddParticleData(EPVF_Position);
  509.         pComponent->AddParticleData(EPVF_Velocity);
  510.         pComponent->AddParticleData(EPVF_AngularVelocity);
  511.         pComponent->AddParticleData(EPQF_Orientation);
  512. }
  513.  
  514. void CFeatureMotionCryPhysics::Serialize(Serialization::IArchive& ar)
  515. {
  516.         CParticleFeature::Serialize(ar);
  517.         ar(m_surfaceTypeName, "SurfaceType", "Surface Type");
  518.         ar(m_gravity, "gravity", "Gravity Scale");
  519.         ar(m_drag, "drag", "Drag");
  520.         ar(m_density, "density", "Density");
  521.         ar(m_thickness, "thickness", "Thickness");
  522.         ar(m_uniformAcceleration, "UniformAcceleration", "Uniform Acceleration");
  523. }
  524.  
  525. void CFeatureMotionCryPhysics::PostInitParticles(const SUpdateContext& context)
  526. {
  527.         CRY_PFX2_PROFILE_DETAIL;
  528.  
  529.         IPhysicalWorld* pPhysicalWorld = gEnv->pPhysicalWorld;
  530.         CParticleEmitter* pEmitter = context.m_runtime.GetEmitter();
  531.         const SPhysEnviron& physicsEnv = pEmitter->GetPhysicsEnv();
  532.  
  533.         CParticleContainer& container = context.m_container;
  534.         auto physicalEntities = container.GetTIOStream<IPhysicalEntity*>(EPDT_PhysicalEntity);
  535.         const IVec3Stream positions = container.GetIVec3Stream(EPVF_Position);
  536.         const IVec3Stream velocities = container.GetIVec3Stream(EPVF_Velocity);
  537.         const IVec3Stream angularVelocities = container.GetIVec3Stream(EPVF_AngularVelocity);
  538.         const IQuatStream orientations = container.GetIQuatStream(EPQF_Orientation);
  539.         const IFStream sizes = container.GetIFStream(EPDT_Size);
  540.         const float sphereVolume = 4.0f / 3.0f * gf_PI;
  541.         const Vec3 uniformAcceleration = physicsEnv.m_UniformForces.vAccel * m_gravity + m_uniformAcceleration;
  542.         ISurfaceType* pSurfaceType = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceTypeByName(m_surfaceTypeName.c_str());
  543.         const int surfaceTypeId = pSurfaceType ? pSurfaceType->GetId() : 0;
  544.  
  545.         CRY_PFX2_FOR_SPAWNED_PARTICLES(context)
  546.         {
  547.                 pe_params_pos particlePosition;
  548.                 particlePosition.pos = positions.Load(particleId);
  549.                 particlePosition.q = orientations.Load(particleId);
  550.  
  551.                 IPhysicalEntity* pPhysicalEntity = pPhysicalWorld->CreatePhysicalEntity(
  552.                         PE_PARTICLE,
  553.                         &particlePosition);
  554.                 pe_params_particle particleParams;
  555.  
  556.                 // Compute particle mass from volume of object.
  557.                 const float size = sizes.Load(particleId);
  558.                 const float sizeCube = size * size * size;
  559.                 particleParams.size = size;
  560.                 particleParams.mass = m_density * sizeCube * sphereVolume;
  561.  
  562.                 const Vec3 velocity = velocities.Load(particleId);
  563.                 particleParams.thickness = m_thickness * size;
  564.                 particleParams.velocity = velocity.GetLength();
  565.                 if (particleParams.velocity > 0.f)
  566.                         particleParams.heading = velocity / particleParams.velocity;
  567.  
  568.                 particleParams.surface_idx = surfaceTypeId;
  569.                 particleParams.flags = particle_no_path_alignment;
  570.                 particleParams.kAirResistance = m_drag;
  571.                 particleParams.gravity = uniformAcceleration;
  572.                 particleParams.q0 = particlePosition.q;
  573.                 particleParams.wspin = angularVelocities.Load(particleId);
  574.  
  575.                 pPhysicalEntity->SetParams(&particleParams);
  576.  
  577.                 pe_params_flags particleFlags;
  578.                 particleFlags.flagsOR = pef_never_affect_triggers;
  579.                 particleFlags.flagsOR |= pef_log_collisions;
  580.                 pPhysicalEntity->SetParams(&particleFlags);
  581.                 pPhysicalEntity->AddRef();
  582.  
  583.                 physicalEntities.Store(particleId, pPhysicalEntity);
  584.         }
  585.         CRY_PFX2_FOR_END;
  586. }
  587.  
  588. void CFeatureMotionCryPhysics::Update(const SUpdateContext& context)
  589. {
  590.         CRY_PFX2_PROFILE_DETAIL;
  591.  
  592.         IPhysicalWorld* pPhysicalWorld = gEnv->pPhysicalWorld;
  593.         CParticleContainer& container = context.m_container;
  594.         auto physicalEntities = container.GetTIOStream<IPhysicalEntity*>(EPDT_PhysicalEntity);
  595.         IOVec3Stream positions = container.GetIOVec3Stream(EPVF_Position);
  596.         IOVec3Stream velocities = container.GetIOVec3Stream(EPVF_Velocity);
  597.         IOVec3Stream angularVelocities = container.GetIOVec3Stream(EPVF_AngularVelocity);
  598.         IOQuatStream orientations = container.GetIOQuatStream(EPQF_Orientation);
  599.         auto states = container.GetTIStream<uint8>(EPDT_State);
  600.  
  601.         CRY_PFX2_FOR_ACTIVE_PARTICLES(context)
  602.         {
  603.                 IPhysicalEntity* pPhysicalEntity = physicalEntities.Load(particleId);
  604.                 if (!pPhysicalEntity)
  605.                         continue;
  606.  
  607.                 pe_status_pos statusPosition;
  608.                 if (pPhysicalEntity->GetStatus(&statusPosition))
  609.                 {
  610.                         positions.Store(particleId, statusPosition.pos);
  611.                         orientations.Store(particleId, statusPosition.q);
  612.                 }
  613.  
  614.                 pe_status_dynamics statusDynamics;
  615.                 if (pPhysicalEntity->GetStatus(&statusDynamics))
  616.                 {
  617.                         velocities.Store(particleId, statusDynamics.v);
  618.                         angularVelocities.Store(particleId, statusDynamics.w);
  619.                 }
  620.  
  621.                 const uint8 state = states.Load(particleId);
  622.                 if (state == ES_Expired)
  623.                 {
  624.                         pPhysicalWorld->DestroyPhysicalEntity(pPhysicalEntity);
  625.                         physicalEntities.Store(particleId, 0);
  626.                 }
  627.         }
  628.         CRY_PFX2_FOR_END;
  629. }
  630.  
  631. CRY_PFX2_IMPLEMENT_FEATURE(CParticleFeature, CFeatureMotionCryPhysics, "Motion", "CryPhysics", colorMotion);
  632.  
  633. //////////////////////////////////////////////////////////////////////////
  634. // CFeatureMoveRelativeToEmitter
  635.  
  636. class CFeatureMoveRelativeToEmitter : public CParticleFeature
  637. {
  638. public:
  639.         CRY_PFX2_DECLARE_FEATURE
  640.  
  641.                 CFeatureMoveRelativeToEmitter()
  642.                 : m_positionInherit(1.0f)
  643.                 , m_velocityInherit(1.0f)
  644.                 , m_angularInherit(0.0f)
  645.                 , m_velocityInheritAfterDeath(0.0f) {}
  646.  
  647.         virtual void AddToComponent(CParticleComponent* pComponent, SComponentParams* pParams) override
  648.         {
  649.                 const bool inheritPositions = (m_positionInherit != 0.0f);
  650.                 const bool inheritVelocities = (m_velocityInherit != 0.0f);
  651.                 const bool inheritAngles = (m_angularInherit != 0.0f);
  652.                 const bool inheritVelOnDeath = (m_velocityInheritAfterDeath != 0.0f);
  653.  
  654.                 if (inheritPositions || inheritVelocities || inheritAngles)
  655.                         pComponent->AddToUpdateList(EUL_PreUpdate, this);
  656.                 if (inheritPositions)
  657.                         pComponent->AddParticleData(EPVF_LocalPosition);
  658.                 if (inheritVelocities)
  659.                         pComponent->AddParticleData(EPVF_LocalVelocity);
  660.                 if (inheritAngles)
  661.                 {
  662.                         pComponent->AddParticleData(EPQF_Orientation);
  663.                         pComponent->AddParticleData(EPQF_LocalOrientation);
  664.                 }
  665.                 if (inheritVelOnDeath)
  666.                         pComponent->AddToUpdateList(EUL_Update, this);
  667.         }
  668.  
  669.         virtual void Serialize(Serialization::IArchive& ar) override
  670.         {
  671.                 CParticleFeature::Serialize(ar);
  672.                 ar(m_positionInherit, "PositionInherit", "Position Inherit");
  673.                 ar(m_velocityInherit, "VelocityInherit", "Velocity Inherit");
  674.                 ar(m_angularInherit, "AngularInherit", "Angular Inherit");
  675.                 ar(m_velocityInheritAfterDeath, "VelocityInheritAfterDeath", "Velocity Inherit After Death");
  676.         }
  677.  
  678.         virtual void PreUpdate(const SUpdateContext& context) override
  679.         {
  680.                 CRY_PROFILE_FUNCTION(PROFILE_PARTICLE);
  681.  
  682.                 CParticleContainer& container = context.m_container;
  683.                 const CParticleContainer& parentContainer = context.m_parentContainer;
  684.                 const IPidStream parentIds = container.GetIPidStream(EPDT_ParentId);
  685.                 const auto parentStates = parentContainer.GetTIStream<uint8>(EPDT_State);
  686.                 const IVec3Stream parentPositions = parentContainer.GetIVec3Stream(EPVF_Position);
  687.                 const IQuatStream parentOrientations = parentContainer.GetIQuatStream(EPQF_Orientation);
  688.                 const IVec3Stream localPositions = container.GetIVec3Stream(EPVF_LocalPosition);
  689.                 const IVec3Stream localVelocities = container.GetIVec3Stream(EPVF_LocalVelocity);
  690.                 const IQuatStream localOrientations = container.GetIQuatStream(EPQF_LocalOrientation);
  691.                 IOVec3Stream worldPositions = container.GetIOVec3Stream(EPVF_Position);
  692.                 IOVec3Stream worldVelocities = container.GetIOVec3Stream(EPVF_Velocity);
  693.                 IOQuatStream worldOrientations = container.GetIOQuatStream(EPQF_Orientation);
  694.  
  695.                 const bool inheritPositions = (m_positionInherit != 0.0f);
  696.                 const bool inheritVelocities = (m_velocityInherit != 0.0f);
  697.                 const bool inheritAngles = (m_angularInherit != 0.0f);
  698.  
  699.                 CRY_PFX2_FOR_ACTIVE_PARTICLES(context)
  700.                 {
  701.                         const TParticleId parentId = parentIds.Load(particleId);
  702.                         const uint8 parentState = (parentId != gInvalidId) ? parentStates.Load(parentId) : ES_Dead;
  703.                         if (parentState == ES_Dead)
  704.                                 continue;
  705.  
  706.                         const Vec3 wParentPos = parentPositions.SafeLoad(parentId);
  707.                         const Quat parentOrientation = parentOrientations.SafeLoad(parentId);
  708.                         const QuatT parentToWorld = QuatT(wParentPos, parentOrientation);
  709.  
  710.                         if (inheritPositions)
  711.                         {
  712.                                 const Vec3 wPosition0 = worldPositions.Load(particleId);
  713.                                 const Vec3 oPosition = localPositions.Load(particleId);
  714.                                 const Vec3 wPosition1 = Lerp(
  715.                                         wPosition0, parentToWorld * oPosition,
  716.                                         m_positionInherit);
  717.                                 worldPositions.Store(particleId, wPosition1);
  718.                         }
  719.  
  720.                         if (inheritVelocities)
  721.                         {
  722.                                 const Vec3 wVelocity0 = worldVelocities.Load(particleId);
  723.                                 const Vec3 oVelocity = localVelocities.Load(particleId);
  724.                                 const Vec3 wVelocity1 = Lerp(
  725.                                         wVelocity0, parentToWorld.q * oVelocity,
  726.                                         m_velocityInherit);
  727.                                 worldVelocities.Store(particleId, wVelocity1);
  728.                         }
  729.  
  730.                         if (inheritAngles)
  731.                         {
  732.                                 const Quat wOrientation0 = worldOrientations.Load(particleId);
  733.                                 const Quat oOrientation = localOrientations.Load(particleId);
  734.                                 const Quat wOrientation1 = Lerp(
  735.                                         wOrientation0, parentToWorld.q * oOrientation,
  736.                                         m_angularInherit);
  737.                                 worldOrientations.Store(particleId, wOrientation1);
  738.                         }
  739.                 }
  740.                 CRY_PFX2_FOR_END;
  741.         }
  742.  
  743.         virtual void Update(const SUpdateContext& context) override
  744.         {
  745.                 CRY_PROFILE_FUNCTION(PROFILE_PARTICLE);
  746.  
  747.                 CParticleContainer& container = context.m_container;
  748.                 const CParticleContainer& parentContainer = context.m_parentContainer;
  749.                 const IPidStream parentIds = container.GetIPidStream(EPDT_ParentId);
  750.                 const auto parentStates = parentContainer.GetTIStream<uint8>(EPDT_State);
  751.                 const IVec3Stream parentVelocities = parentContainer.GetIVec3Stream(EPVF_Velocity);
  752.                 IOVec3Stream worldVelocities = container.GetIOVec3Stream(EPVF_Velocity);
  753.  
  754.                 CRY_PFX2_FOR_ACTIVE_PARTICLES(context)
  755.                 {
  756.                         const TParticleId parentId = parentIds.Load(particleId);
  757.                         const uint8 parentState = (parentId != gInvalidId) ? parentStates.Load(parentId) : 0;
  758.                         if (parentState == ES_Expired)
  759.                         {
  760.                                 const Vec3 wParentVelocity = parentVelocities.Load(parentId);
  761.                                 const Vec3 wVelocity0 = worldVelocities.Load(particleId);
  762.                                 const Vec3 wVelocity1 = wParentVelocity * m_velocityInheritAfterDeath + wVelocity0;
  763.                                 worldVelocities.Store(particleId, wVelocity1);
  764.                         }
  765.                 }
  766.                 CRY_PFX2_FOR_END;
  767.         }
  768.  
  769. private:
  770.         SFloat m_positionInherit;
  771.         SFloat m_velocityInherit;
  772.         SFloat m_angularInherit;
  773.         SFloat m_velocityInheritAfterDeath;
  774. };
  775.  
  776. CRY_PFX2_IMPLEMENT_FEATURE(CParticleFeature, CFeatureMoveRelativeToEmitter, "Motion", "MoveRelativeToEmitter", colorMotion);
  777. CRY_PFX2_LEGACY_FEATURE(CParticleFeature, CFeatureMoveRelativeToEmitter, "VelocityMoveRelativeToEmitter");
  778.  
  779. }
  780.  
downloadFeatureMotion.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