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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
#include "UnityPrefix.h"
#include "Wind.h"
#include "Runtime/Serialize/TransferFunctions/SerializeTransfer.h"
#include "Runtime/Input/TimeManager.h"
#include "Runtime/Graphics/Transform.h"
#include "Runtime/Geometry/AABB.h"
#include "Runtime/Math/Vector4.h"
// --------------------------------------------------------------------------
WindZone::WindZone (MemLabelId label, ObjectCreationMode mode)
: Super (label, mode)
, m_Mode (Directional)
, m_Radius (20)
, m_WindMain (1)
, m_WindTurbulence (1)
, m_WindPulseMagnitude (0.5f)
, m_WindPulseFrequency (0.01f)
, m_Node (this)
{
}
WindZone::~WindZone ()
{
}
template<class TransferFunc>
void WindZone::Transfer (TransferFunc& transfer)
{
Super::Transfer (transfer);
TRANSFER_ENUM(m_Mode);
transfer.Transfer (m_Radius, "m_Radius");
transfer.Transfer (m_WindMain, "m_WindMain");
transfer.Transfer (m_WindTurbulence, "m_WindTurbulence");
transfer.Transfer (m_WindPulseMagnitude, "m_WindPulseMagnitude");
transfer.Transfer (m_WindPulseFrequency, "m_WindPulseFrequency");
}
Vector4f WindZone::ComputeWindForce (const AABB& bounds, float time) const
{
// use point mid way between center and top center, as leaves are likely to be placed there
Vector3f center = bounds.GetCenter ();
// TODO : could use GetExtent instead
center.y += (bounds.GetMax ().y - bounds.GetMin ().y) * 0.25f;
float windPhase = time * kPI * m_WindPulseFrequency;
float phase = windPhase + center.x * 0.1f + center.z * 0.1f;
float pulse = (cos (phase) + cos (phase * 0.375f) + cos (phase * 0.05f)) * 0.333f;
pulse = 1.0f + (pulse * m_WindPulseMagnitude);
const Transform& transform = GetComponent (Transform);
const Vector3f position = transform.GetPosition ();
if (m_Mode == Directional)
{
// Directional
float power = pulse;
// TODO : could do this when m_direction is set
Vector3f delta = transform.TransformDirection (Vector3f::zAxis);
delta = Normalize (delta);
return Vector4f (
delta.x * m_WindMain * power,
delta.y * m_WindMain * power,
delta.z * m_WindMain * power,
m_WindTurbulence * power);
}
else
{
// Spherical with falloff
float power = 1.0f - CalculateSqrDistance (position, bounds) / (m_Radius * m_Radius);
if (power > 0.0f)
{
power *= pulse;
Vector3f delta = center - position;
delta = Normalize (delta);
return Vector4f(
delta.x * m_WindMain * power,
delta.y * m_WindMain * power,
delta.z * m_WindMain * power,
m_WindTurbulence * power);
}
}
return Vector4f(0,0,0,0);
}
// --------------------------------------------------------------------------
void WindZone::AddToManager ()
{
WindManager::GetInstance ().AddWindZone (m_Node);
}
void WindZone::RemoveFromManager ()
{
m_Node.RemoveFromList();
}
IMPLEMENT_CLASS(WindZone)
IMPLEMENT_OBJECT_SERIALIZE(WindZone)
// --------------------------------------------------------------------------
// Empty destructor so it won't be autogenerated all over the place
WindManager::~WindManager()
{
}
// No need to allocate this dynamically, it's a tiny class
WindManager WindManager::s_WindManager;
WindManager& WindManager::GetInstance ()
{
return s_WindManager;
}
WindManager::WindZoneList& WindManager::GetList ()
{
return m_WindZones;
}
Vector4f WindManager::ComputeWindForce (const AABB& bounds)
{
float time = GetTimeManager ().GetTimeSinceLevelLoad ();
Vector4f force (0, 0, 0, 0);
for (WindZoneList::iterator it = m_WindZones.begin (); it != m_WindZones.end (); ++it)
{
const WindZone& zone = **it;
force = force + zone.ComputeWindForce (bounds, time);
}
return force;
}
|