diff options
Diffstat (limited to 'Runtime/Terrain/Wind.cpp')
-rw-r--r-- | Runtime/Terrain/Wind.cpp | 149 |
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; +} |