From 15740faf9fe9fe4be08965098bbf2947e096aeeb Mon Sep 17 00:00:00 2001
From: chai <chaifix@163.com>
Date: Wed, 14 Aug 2019 22:50:43 +0800
Subject: +Unity Runtime code

---
 Runtime/Terrain/Wind.cpp | 149 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 149 insertions(+)
 create mode 100644 Runtime/Terrain/Wind.cpp

(limited to 'Runtime/Terrain/Wind.cpp')

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;
+}
-- 
cgit v1.1-26-g67d0