123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- //
- // ExternalForcesModule.cpp
- // libcocos2d Mac
- //
- // Created by 徐俊杰 on 2020/4/24.
- //
- #include "rparticle/Modules/ExternalForcesModule.h"
- //#include "UnityPrefix.h"
- //#include "rparticle/Modules/ExternalForcesModule.h"
- //#include "Runtime/BaseClasses/ObjectDefines.h"
- #include "rparticle/Serialize/TransferFunctions/SerializeTransfer.h"
- #include "rparticle/ParticleSystemUtils.h"
- #include "rparticle/Utilities/Transform.h"
- //#include "Runtime/Geometry/Intersection.h"
- //#include "Runtime/Geometry/Sphere.h"
- //#include "Runtime/Terrain/Wind.h"
- //#include "Runtime/Input/TimeManager.h"
- NS_RRP_BEGIN
- void ApplyRadialForce(ParticleSystemParticles& ps, const size_t fromIndex, const size_t toIndex, const Vector3f position, const float radius, const float force, const float dt)
- {
- for(int q = fromIndex; q < toIndex; q++)
- {
- Vector3f toForce = position - ps.position[q];
- float distanceToForce = Magnitude(toForce);
- toForce = NormalizeSafe(toForce);
- float forceFactor = clamp(distanceToForce/radius, 0.0f, 1.0f);
- forceFactor = 1.0f - forceFactor * forceFactor;
- Vector3f delta = toForce * force * forceFactor * dt;
- ps.velocity[q] += delta;
- }
- }
- void ApplyDirectionalForce(ParticleSystemParticles& ps, const size_t fromIndex, const size_t toIndex, const Vector3f position, const Vector3f direction, const float radius, const float force, const float dt)
- {
- for(int q = fromIndex; q < toIndex; q++)
- {
- Vector3f delta = direction * force * dt;
- ps.velocity[q] += delta;
- }
- }
- ExternalForcesModule::ExternalForcesModule () : ParticleSystemModule(false)
- , m_Multiplier (1.0f)
- {
- }
- void ExternalForcesModule::Update (const ParticleSystemReadOnlyState& roState, const ParticleSystemState& state, ParticleSystemParticles& ps, const size_t fromIndex, const size_t toIndex, float dt)
- {
- Matrix4x4f matrix = Matrix4x4f::IDENTITY;
- if(roState.useLocalSpace)
- Matrix4x4f::Invert_General3D(state.localToWorld, matrix);
-
- auto aabb = state.minMaxAABB;
- for(int i = 0; i < state.numCachedForces; i++)
- {
- const ParticleSystemExternalCachedForce& cachedForce = state.cachedForces[i];
- const Vector3f position = matrix.MultiplyPoint3(cachedForce.position);
- const Vector3f direction = matrix.MultiplyVector3(cachedForce.direction);
- const float radius = cachedForce.radius;
- const float force = cachedForce.forceMain * m_Multiplier;
-
- //TODO: WindZone
- /*
- const WindZone::WindZoneMode forceType = (WindZone::WindZoneMode)cachedForce.forceType;
- if(WindZone::Spherical == forceType)
- {
- Sphere sphere (position, radius);
- if(!IntersectAABBSphere (aabb, sphere))
- continue;
- ApplyRadialForce(ps, fromIndex, toIndex, position, radius, force, dt);
- }
- else if(WindZone::Directional == forceType)
- ApplyDirectionalForce(ps, fromIndex, toIndex, position, direction, radius, force, dt);
- */
- }
- }
- // TODO: Perform culling here, instead of caching all of them
- void ExternalForcesModule::AllocateAndCache(const ParticleSystemReadOnlyState& roState, ParticleSystemState& state)
- {
- //TODO: WindManager, TimeManager
- /*
- float time = GetTimeManager ().GetTimeSinceLevelLoad ();
- WindManager::WindZoneList& windZones = WindManager::GetInstance().GetList();
-
- state.numCachedForces = 0;
- for (WindManager::WindZoneList::iterator it = windZones.begin (); it != windZones.end (); ++it)
- state.numCachedForces++;
-
- // Allocate
- state.cachedForces = ALLOC_TEMP_MANUAL(ParticleSystemExternalCachedForce, state.numCachedForces);
-
- // Cache
- int i = 0;
- for (WindManager::WindZoneList::iterator it = windZones.begin (); it != windZones.end (); ++it)
- {
- const WindZone& zone = **it;
- ParticleSystemExternalCachedForce& cachedForce = state.cachedForces[i++];
- cachedForce.position = zone.GetComponent (Transform).GetPosition();
- cachedForce.direction = zone.GetComponent (Transform).GetLocalToWorldMatrix().GetAxisZ();
- cachedForce.forceType = zone.GetMode();
- cachedForce.radius = zone.GetRadius();
-
- float phase = time * kPI * zone.GetWindPulseFrequency();
- float pulse = (cos (phase) + cos (phase * 0.375f) + cos (phase * 0.05f)) * 0.333f;
- pulse = 1.0f + (pulse * zone.GetWindPulseMagnitude());
- cachedForce.forceMain = zone.GetWindMain() * pulse;
- // Maybe implement using turbulence and time based phasing?
- // ForceTurbulenceMultiply (maybe) // @TODO: Figure out what to do about turbulence. Do perlin field? Expensive but maybe cool! If use it: only do it when turbulence force is set to something
-
- //cachedForce.force = 1.0f;
- }
- */
- }
- void ExternalForcesModule::FreeCache(ParticleSystemState& state)
- {
- if(state.cachedForces)
- FREE_TEMP_MANUAL(state.cachedForces);
- state.cachedForces = NULL;
- state.numCachedForces = 0;
- }
- template<class TransferFunction>
- void ExternalForcesModule::Transfer (TransferFunction& transfer)
- {
- ParticleSystemModule::Transfer (transfer);
- transfer.Transfer (m_Multiplier, "multiplier");
- }
- INSTANTIATE_TEMPLATE_TRANSFER(ExternalForcesModule)
- NS_RRP_END
|