summaryrefslogtreecommitdiff
path: root/Runtime/Terrain/Wind.cpp
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-08-14 22:50:43 +0800
committerchai <chaifix@163.com>2019-08-14 22:50:43 +0800
commit15740faf9fe9fe4be08965098bbf2947e096aeeb (patch)
treea730ec236656cc8cab5b13f088adfaed6bb218fb /Runtime/Terrain/Wind.cpp
+Unity Runtime codeHEADmaster
Diffstat (limited to 'Runtime/Terrain/Wind.cpp')
-rw-r--r--Runtime/Terrain/Wind.cpp149
1 files changed, 149 insertions, 0 deletions
diff --git a/Runtime/Terrain/Wind.cpp b/Runtime/Terrain/Wind.cpp
new file mode 100644
index 0000000..3fe6234
--- /dev/null
+++ b/Runtime/Terrain/Wind.cpp
@@ -0,0 +1,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;
+}