|
|
@@ -36,6 +36,7 @@ namespace Urho3D
|
|
|
static const float DEFAULT_NEARDISTANCE = 0.0f;
|
|
|
static const float DEFAULT_FARDISTANCE = 100.0f;
|
|
|
static const float DEFAULT_ROLLOFF = 2.0f;
|
|
|
+static const float DEFAULT_ANGLE = 360.0f;
|
|
|
static const float MIN_ROLLOFF = 0.1f;
|
|
|
|
|
|
extern const char* AUDIO_CATEGORY;
|
|
|
@@ -44,6 +45,8 @@ SoundSource3D::SoundSource3D(Context* context) :
|
|
|
SoundSource(context),
|
|
|
nearDistance_(DEFAULT_NEARDISTANCE),
|
|
|
farDistance_(DEFAULT_FARDISTANCE),
|
|
|
+ outerAngle_(DEFAULT_ANGLE),
|
|
|
+ innerAngle_(DEFAULT_ANGLE),
|
|
|
rolloffFactor_(DEFAULT_ROLLOFF)
|
|
|
{
|
|
|
// Start from zero volume until attenuation properly calculated
|
|
|
@@ -60,6 +63,8 @@ void SoundSource3D::RegisterObject(Context* context)
|
|
|
REMOVE_ATTRIBUTE(SoundSource3D, "Panning");
|
|
|
ATTRIBUTE(SoundSource3D, VAR_FLOAT, "Near Distance", nearDistance_, DEFAULT_NEARDISTANCE, AM_DEFAULT);
|
|
|
ATTRIBUTE(SoundSource3D, VAR_FLOAT, "Far Distance", farDistance_, DEFAULT_FARDISTANCE, AM_DEFAULT);
|
|
|
+ ATTRIBUTE(SoundSource3D, VAR_FLOAT, "Inner Angle", innerAngle_, DEFAULT_ANGLE, AM_DEFAULT);
|
|
|
+ ATTRIBUTE(SoundSource3D, VAR_FLOAT, "Outer Angle", outerAngle_, DEFAULT_ANGLE, AM_DEFAULT);
|
|
|
ATTRIBUTE(SoundSource3D, VAR_FLOAT, "Rolloff Factor", rolloffFactor_, DEFAULT_ROLLOFF, AM_DEFAULT);
|
|
|
}
|
|
|
|
|
|
@@ -77,6 +82,13 @@ void SoundSource3D::SetDistanceAttenuation(float nearDistance, float farDistance
|
|
|
MarkNetworkUpdate();
|
|
|
}
|
|
|
|
|
|
+void SoundSource3D::SetAngleAttenuation(float innerAngle, float outerAngle)
|
|
|
+{
|
|
|
+ innerAngle_ = Clamp(innerAngle, 0.0f, DEFAULT_ANGLE);
|
|
|
+ outerAngle_ = Clamp(outerAngle, 0.0f, DEFAULT_ANGLE);
|
|
|
+ MarkNetworkUpdate();
|
|
|
+}
|
|
|
+
|
|
|
void SoundSource3D::SetFarDistance(float distance)
|
|
|
{
|
|
|
farDistance_ = Max(distance, 0.0f);
|
|
|
@@ -89,6 +101,18 @@ void SoundSource3D::SetNearDistance(float distance)
|
|
|
MarkNetworkUpdate();
|
|
|
}
|
|
|
|
|
|
+void SoundSource3D::SetInnerAngle(float angle)
|
|
|
+{
|
|
|
+ innerAngle_ = Clamp(angle, 0.0f, DEFAULT_ANGLE);
|
|
|
+ MarkNetworkUpdate();
|
|
|
+}
|
|
|
+
|
|
|
+void SoundSource3D::SetOuterAngle(float angle)
|
|
|
+{
|
|
|
+ outerAngle_ = Clamp(angle, 0.0f, DEFAULT_ANGLE);
|
|
|
+ MarkNetworkUpdate();
|
|
|
+}
|
|
|
+
|
|
|
void SoundSource3D::SetRolloffFactor(float factor)
|
|
|
{
|
|
|
rolloffFactor_ = Max(factor, MIN_ROLLOFF);
|
|
|
@@ -101,7 +125,7 @@ void SoundSource3D::CalculateAttenuation()
|
|
|
return;
|
|
|
|
|
|
float interval = farDistance_ - nearDistance_;
|
|
|
- if (interval > 0.0f && node_)
|
|
|
+ if (node_)
|
|
|
{
|
|
|
SoundListener* listener = audio_->GetListener();
|
|
|
|
|
|
@@ -110,12 +134,40 @@ void SoundSource3D::CalculateAttenuation()
|
|
|
{
|
|
|
Node* listenerNode = listener->GetNode();
|
|
|
Vector3 relativePos(listenerNode->GetWorldRotation().Inverse() * (node_->GetWorldPosition() - listenerNode->GetWorldPosition()));
|
|
|
- float distance = Clamp(relativePos.Length() - nearDistance_, 0.0f, interval);
|
|
|
- float attenuation = powf(1.0f - distance / interval, rolloffFactor_);
|
|
|
- float panning = relativePos.Normalized().x_;
|
|
|
-
|
|
|
- attenuation_ = attenuation;
|
|
|
- panning_ = panning;
|
|
|
+ float distance = relativePos.Length();
|
|
|
+
|
|
|
+ // Distance attenuation
|
|
|
+ if (interval > 0.0f)
|
|
|
+ attenuation_ = powf(1.0f - Clamp(distance - nearDistance_, 0.0f, interval) / interval, rolloffFactor_);
|
|
|
+ else
|
|
|
+ attenuation_ = distance <= nearDistance_ ? 1.0f : 0.0f;
|
|
|
+
|
|
|
+ // Panning
|
|
|
+ panning_ = relativePos.Normalized().x_;
|
|
|
+
|
|
|
+ // Angle attenuation
|
|
|
+ if (innerAngle_ < DEFAULT_ANGLE)
|
|
|
+ {
|
|
|
+ Vector3 listenerRelativePos(node_->GetWorldRotation().Inverse() * (listenerNode->GetWorldPosition() -
|
|
|
+ node_->GetWorldPosition()));
|
|
|
+ float listenerDot = Vector3::FORWARD.DotProduct(listenerRelativePos.Normalized());
|
|
|
+ float listenerAngle = acosf(listenerDot) * M_RADTODEG * 2.0f;
|
|
|
+ float angleInterval = Max(outerAngle_ - innerAngle_, 0.0f);
|
|
|
+ float angleAttenuation = 1.0f;
|
|
|
+
|
|
|
+ if (angleInterval > 0.0f)
|
|
|
+ {
|
|
|
+ if (listenerAngle > innerAngle_)
|
|
|
+ {
|
|
|
+ angleAttenuation = powf(1.0f - Clamp(listenerAngle - innerAngle_, 0.0f, angleInterval) / angleInterval,
|
|
|
+ rolloffFactor_);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ angleAttenuation = listenerAngle <= innerAngle_ ? 1.0f : 0.0f;
|
|
|
+
|
|
|
+ attenuation_ *= angleAttenuation;
|
|
|
+ }
|
|
|
}
|
|
|
else
|
|
|
attenuation_ = 0.0f;
|