summaryrefslogtreecommitdiff
path: root/Runtime/Graphics/ParticleSystem/Modules/ClampVelocityModule.cpp
blob: 362fbffd62e8d817fe39df9a318afee56e75794b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include "UnityPrefix.h"
#include "Runtime/BaseClasses/ObjectDefines.h"
#include "Runtime/Serialize/TransferFunctions/SerializeTransfer.h"
#include "ClampVelocityModule.h"
#include "Runtime/Graphics/ParticleSystem/ParticleSystemUtils.h"
#include "Runtime/Misc/BuildSettings.h"

inline float DampenOutsideLimit (float v, float limit, float dampen)
{
	float sgn = Sign (v);
	float abs = Abs (v);
	if (abs > limit)
		abs = Lerp(abs, limit, dampen);
	return abs * sgn;
}

ClampVelocityModule::ClampVelocityModule () : ParticleSystemModule(false)
,	m_SeparateAxis (false)
,	m_InWorldSpace (false)
,	m_Dampen (1.0f)
{
}

template<ParticleSystemCurveEvalMode mode>
void MagnitudeUpdateTpl(const MinMaxCurve& magnitude, ParticleSystemParticles& ps, size_t fromIndex, size_t toIndex, float dampen)
{
	for (size_t q = fromIndex; q < toIndex; ++q)
	{
		float limit = Evaluate<mode> (magnitude, NormalizedTime(ps, q), GenerateRandom(ps.randomSeed[q] + kParticleSystemClampVelocityCurveId));
		Vector3f vel = ps.velocity[q] + ps.animatedVelocity[q];
		vel = NormalizeSafe (vel) * DampenOutsideLimit (Magnitude (vel), limit, dampen);
		ps.velocity[q] = vel - ps.animatedVelocity[q];
	}
}

void ClampVelocityModule::Update (const ParticleSystemReadOnlyState& roState, const ParticleSystemState& state, ParticleSystemParticles& ps, const size_t fromIndex, const size_t toIndex)
{
	if (m_SeparateAxis)
	{
		Matrix4x4f matrix;
		Matrix4x4f invMatrix;
		bool transform;
		if(IS_CONTENT_NEWER_OR_SAME (kUnityVersion4_0_a1))
			transform = GetTransformationMatrices(matrix, invMatrix, !roState.useLocalSpace, m_InWorldSpace, state.localToWorld);
		else		
			transform = false; // Revert to old broken behavior

		for (size_t q = fromIndex; q < toIndex; ++q)
		{
			Vector3f random;
			GenerateRandom3(random, ps.randomSeed[q] + kParticleSystemClampVelocityCurveId);
			const float time = NormalizedTime(ps, q);

			Vector3f vel = ps.velocity[q] + ps.animatedVelocity[q];
			if(transform)
				vel = matrix.MultiplyVector3 (vel);
			const Vector3f limit (Evaluate (m_X, time, random.x), Evaluate (m_Y, time, random.y), Evaluate (m_Z, time, random.z));
			vel.x = DampenOutsideLimit (vel.x, limit.x, m_Dampen);
			vel.y = DampenOutsideLimit (vel.y, limit.y, m_Dampen);
			vel.z = DampenOutsideLimit (vel.z, limit.z, m_Dampen);
			vel = vel - ps.animatedVelocity[q];
			if(transform)
				vel = invMatrix.MultiplyVector3 (vel);
			ps.velocity[q] = vel;
		}
	}
	else
	{
		if(m_Magnitude.minMaxState == kMMCScalar)
			MagnitudeUpdateTpl<kEMScalar> (m_Magnitude, ps, fromIndex, toIndex, m_Dampen);
		else if(m_Magnitude.IsOptimized() && m_Magnitude.UsesMinMax())
			MagnitudeUpdateTpl<kEMOptimizedMinMax> (m_Magnitude, ps, fromIndex, toIndex, m_Dampen);
		else if(m_Magnitude.IsOptimized())
			MagnitudeUpdateTpl<kEMOptimized> (m_Magnitude, ps, fromIndex, toIndex, m_Dampen);
		else
			MagnitudeUpdateTpl<kEMSlow> (m_Magnitude, ps, fromIndex, toIndex, m_Dampen);
	}
}

void ClampVelocityModule::CheckConsistency ()
{
	m_Dampen = clamp<float> (m_Dampen, 0.0f, 1.0f);
	m_X.SetScalar(std::max<float> (0.0f, m_X.GetScalar()));
	m_Y.SetScalar(std::max<float> (0.0f, m_Y.GetScalar()));
	m_Z.SetScalar(std::max<float> (0.0f, m_Z.GetScalar()));
	m_Magnitude.SetScalar(std::max<float> (0.0f, m_Magnitude.GetScalar()));
}


template<class TransferFunction>
void ClampVelocityModule::Transfer (TransferFunction& transfer)
{
	ParticleSystemModule::Transfer (transfer);
	transfer.Transfer (m_X, "x");
	transfer.Transfer (m_Y, "y");
	transfer.Transfer (m_Z, "z");
	transfer.Transfer (m_Magnitude, "magnitude");
	transfer.Transfer (m_SeparateAxis, "separateAxis");
	transfer.Transfer (m_InWorldSpace, "inWorldSpace"); transfer.Align ();
	transfer.Transfer (m_Dampen, "dampen");
}
INSTANTIATE_TEMPLATE_TRANSFER(ClampVelocityModule)