2118 lines
90 KiB
C++
2118 lines
90 KiB
C++
#include "vehiclereflectionsaudioentity.h"
|
|
#include "audiosynth/synthcore.h"
|
|
#include "debug/DebugScene.h"
|
|
#include "grcore/debugdraw.h"
|
|
#include "scene/entity.h"
|
|
#include "Peds/PedFactory.h"
|
|
#include "audio/vehicleaudioentity.h"
|
|
#include "audio/ambience/audambientzone.h"
|
|
#include "audio/northaudioengine.h"
|
|
#include "audio/scriptaudioentity.h"
|
|
#include "vehicles/vehicle.h"
|
|
#include "Peds/ped.h"
|
|
#include "audioeffecttypes/biquadfiltereffect.h"
|
|
#include "audioeffecttypes/variabledelayeffect.h"
|
|
#include "scene/playerswitch/PlayerSwitchInterface.h"
|
|
#include "fwscene/stores/staticboundsstore.h"
|
|
#include "camera/CamInterface.h"
|
|
#include "camera/cinematic/CinematicDirector.h"
|
|
|
|
AUDIO_VEHICLES_OPTIMISATIONS()
|
|
|
|
audVehicleReflectionsEntity g_ReflectionsAudioEntity;
|
|
extern f32 g_EngineVolumeTrim;
|
|
extern f32 g_ExhaustVolumeTrim;
|
|
extern CPlayerSwitchInterface g_PlayerSwitch;
|
|
extern f32 g_SpeakerReverbDamping;
|
|
|
|
f32 g_StereoEffectEngineVolumeTrim = 0.0f;
|
|
f32 g_StereoEffectExhaustVolumeTrim = 0.0f;
|
|
f32 g_WetReverbForReflections = 0.15f;
|
|
f32 g_ReflectionsStepRateSmoothing = 1.0f;
|
|
f32 g_MaxProbeDist = 25.0f;
|
|
f32 g_MinProbeDist = 0.0f;
|
|
f32 g_VehicleReflectionsActivationDist = 25.0f;
|
|
u32 g_ReflectionsAttackTime = 300u;
|
|
f32 g_RayCastForwardOffset = 5.0f;
|
|
f32 g_LeftOscillatorSpeed = 1.23f;
|
|
f32 g_RightOscillatorSpeed = 2.14f;
|
|
f32 g_LeftOscillatorDist = 0.0f;
|
|
f32 g_RightOscillatorDist = 0.4f;
|
|
f32 g_ProximityMinDistChangeRate = 1.0f;
|
|
f32 g_ProximityMaxProbeDistance = 3.0f;
|
|
u32 g_ProximityWhooshMinRepeatTime = 500;
|
|
f32 g_ProximityRayCastForwardOffset = 1.5f;
|
|
f32 g_StuntTunnelRayCastForwardOffset = 1.5f;
|
|
u32 g_StuntTunnelMinWhooshRepeatTimeMs = 1000;
|
|
u32 g_StuntBoostIntensityIncreaseDelay = 100;
|
|
u32 g_RechargeIntensityIncreaseDelay = 100;
|
|
f32 g_StuntTunnelMinWhooshExitDistance = 50.f;
|
|
f32 g_StuntTunnelRayCastLength = 50.f;
|
|
f32 g_StuntTunnelProbeHitTimeout = 0.2f;
|
|
s32 g_StereoLeftPan = 270;
|
|
s32 g_StereoRightPan = 90;
|
|
f32 g_StereoLeftAttenuation = -6.0f;
|
|
f32 g_StereoRightAttenuation = -6.0f;
|
|
f32 g_StereoDelayLFOHzLeft = 0.0f;
|
|
f32 g_StereoDelayLFOHzRight = 0.0f;
|
|
f32 g_StereoDelayLFOMagLeft = 0.0f;
|
|
f32 g_StereoDelayLFOMagRight = 0.0f;
|
|
f32 g_StereoDelayLFOOffsetLeft = 0.05f;
|
|
f32 g_StereoDelayLFOOffsetRight = 0.0f;
|
|
bool g_StereoDelayLFOEnabled = true;
|
|
bool g_BonnetCamStereoEffectEnabled = true;
|
|
bool g_InteriorReflectionsEnabled = true;
|
|
bool g_VehicleReflectionsEnabled = false;
|
|
bool g_ForceStuntTunnelProbesEnabled = false;
|
|
bool g_PointSourceVehicleReflections = false;
|
|
bool g_PanInteriorReflectionsWithHeadAngle = false;
|
|
|
|
audCurve audVehicleReflectionsEntity::sm_ReflectionsVehicleSpeedToVolCurve;
|
|
audCurve audVehicleReflectionsEntity::sm_ReflectionsVehicleRevRatioToVolCurve;
|
|
audCurve audVehicleReflectionsEntity::sm_ReflectionsVehicleMassToVolCurve;
|
|
audCurve audVehicleReflectionsEntity::sm_StaticReflectionsRollOffCurve;
|
|
audSoundSet audVehicleReflectionsEntity::sm_CameraSwitchSoundSet;
|
|
|
|
PF_PAGE(audVehicleReflectionsEntityPage, "audVehicleReflectionsEntity Values");
|
|
PF_GROUP(audVehicleReflectionsValues);
|
|
PF_LINK(audVehicleReflectionsEntityPage, audVehicleReflectionsValues);
|
|
PF_VALUE_FLOAT(LeftProbeDist, audVehicleReflectionsValues);
|
|
PF_VALUE_FLOAT(LeftProbeDistChangeRate, audVehicleReflectionsValues);
|
|
PF_VALUE_FLOAT(RightProbeDist, audVehicleReflectionsValues);
|
|
PF_VALUE_FLOAT(RightProbeDistChangeRate, audVehicleReflectionsValues);
|
|
|
|
#if __BANK
|
|
char g_TestReflectionsName[128]={0};
|
|
bool g_TestReflections = false;
|
|
extern f32 g_EngineVolumeTrim;
|
|
extern f32 g_ExhaustVolumeTrim;
|
|
bool g_DebugPrintInteriorTunnels = false;
|
|
bool g_DebugPrintInteriorsAll = false;
|
|
bool g_ReflectionsDebugDraw = false;
|
|
bool g_ReflectionsLocationPickerEnabled = false;
|
|
extern CEntity * g_pFocusEntity;
|
|
bool g_ForceSwitchProximityWhooshes = false;
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity constructor
|
|
// ----------------------------------------------------------------
|
|
audVehicleReflectionsEntity::audVehicleReflectionsEntity()
|
|
{
|
|
m_ActiveVehicle = NULL;
|
|
m_ReflectionsTypeLastFrame = AUD_REFLECTIONS_TYPE_MAX;
|
|
m_ProximityWhooshesEnabled = false;
|
|
m_OscillationTimer = 0.0f;
|
|
m_LastStuntTunnelWhooshPosition.Zero();
|
|
m_LastStuntTunnelWhooshWasEnter = false;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity destructor
|
|
// ----------------------------------------------------------------
|
|
audVehicleReflectionsEntity::~audVehicleReflectionsEntity()
|
|
{
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity InitClass
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::InitClass()
|
|
{
|
|
// If this fails, we have filter modes in the audio definitions that aren't in the synth, or vice-versa
|
|
CompileTimeAssert((int)NUM_FILTERMODE == (int)synthBiquadFilter::kNumBiquadModes);
|
|
sm_ReflectionsVehicleSpeedToVolCurve.Init(ATSTRINGHASH("VEHICLE_SPEED_TO_REFLECTIONS_VOL", 0xF5FC74E5));
|
|
sm_ReflectionsVehicleRevRatioToVolCurve.Init(ATSTRINGHASH("VEHICLE_REV_RATIO_TO_REFLECTIONS_VOL", 0xFDF12A3B));
|
|
sm_ReflectionsVehicleMassToVolCurve.Init(ATSTRINGHASH("VEHICLE_MASS_TO_REFLECTIONS_VOL", 0x7FED0285));
|
|
sm_StaticReflectionsRollOffCurve.Init(ATSTRINGHASH("DEFAULT_ROLLOFF", 0x3BD35057));
|
|
sm_CameraSwitchSoundSet.Init(ATSTRINGHASH("CameraSwitchSounds", 0x124A34BF));
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity Init
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::Init()
|
|
{
|
|
naAudioEntity::Init();
|
|
m_HasPlayedInteriorEnter = false;
|
|
m_HasPlayedInteriorExit = false;
|
|
m_IsFocusVehicleInStuntTunnel = false;
|
|
m_LastStuntTunnelWhooshSound = 0u;
|
|
m_LastBonnetCamUpdateTime = 0u;
|
|
|
|
RegisterStuntTunnelMaterial("STUNT_RAMP_SURFACE");
|
|
|
|
m_ReflectionsSourceSubmix = g_AudioEngine.GetEnvironment().GetReflectionsSourceSubmix();
|
|
|
|
for(u32 i = 0; i < AUD_NUM_REFLECTIONS_OUTPUT_SUBMIXES; i++)
|
|
{
|
|
g_AudioEngine.GetEnvironment().FreeReflectionsOutputSubmix(i);
|
|
}
|
|
|
|
for(u32 i = 0; i < INTERIOR_REFLECTION_MAX; i++)
|
|
{
|
|
m_InteriorReflections[i].m_ReflectionsEntity = NULL;
|
|
m_InteriorReflections[i].m_ProbeDist = g_MaxProbeDist;
|
|
m_InteriorReflections[i].m_ProbeDesc.SetResultsStructure(&m_InteriorReflections[i].m_ProbeResults);
|
|
m_InteriorReflections[i].m_ReflectionsVoice = NULL;
|
|
m_InteriorReflections[i].m_ProbeHitTimer = 0.0f;
|
|
m_InteriorReflections[i].m_OscillatorDist = i == INTERIOR_REFLECTION_LEFT? g_LeftOscillatorDist : g_RightOscillatorDist;
|
|
m_InteriorReflections[i].m_OscillatorSpeed = i == INTERIOR_REFLECTION_LEFT? g_LeftOscillatorSpeed : g_RightOscillatorSpeed;
|
|
m_InteriorReflections[i].m_FirstUpdate = true;
|
|
m_InteriorReflections[i].m_ProbeHit = false;
|
|
m_InteriorReflections[i].m_ReflectionsSubmixIndex = -1;
|
|
m_InteriorReflections[i].m_ReflectionsSubmix = NULL;
|
|
m_InteriorReflections[i].m_PrevTunnelDirection.Zero();
|
|
m_InteriorReflections[i].m_ProbeDistSmoother.Init(1.0f, 1.0f);
|
|
}
|
|
|
|
for(u32 i = 0; i < kMaxVehicleReflections; i++)
|
|
{
|
|
m_VehicleReflections[i].m_ReflectionsEntity = NULL;
|
|
m_VehicleReflections[i].m_ReflectionsVoice = NULL;
|
|
m_VehicleReflections[i].m_FirstUpdate = true;
|
|
m_VehicleReflections[i].m_ReflectionsSubmixIndex = -1;
|
|
m_VehicleReflections[i].m_ReflectionsSubmix = NULL;
|
|
m_VehicleReflections[i].m_DistSmoother.Init(1.0f, 1.0f);
|
|
}
|
|
|
|
for(u32 i = 0; i < 2; i++)
|
|
{
|
|
m_ProximityWhooshes[i].m_ProbeDesc.SetResultsStructure(&m_ProximityWhooshes[i].m_ProbeResults);
|
|
m_ProximityWhooshes[i].m_ProbeDist = 0.0f;
|
|
m_ProximityWhooshes[i].m_SmoothedProbeDist = 0.0f;
|
|
m_ProximityWhooshes[i].m_LastWhooshTime = 0;
|
|
}
|
|
|
|
for(u32 i = 0; i < kMaxStuntTunnelProbes; i++)
|
|
{
|
|
m_StuntTunnelProbes[i].m_ProbeDesc.SetResultsStructure(&m_StuntTunnelProbes[i].m_ProbeResults);
|
|
m_StuntTunnelProbes[i].m_ProbeHit = false;
|
|
m_StuntTunnelProbes[i].m_ProbeLastHitTimer = 10.0f;
|
|
}
|
|
|
|
// Game will start off with all engine/exhaust submixes connected to the reflections, so unhook them to begin with
|
|
for(s32 loop = 0; loop < EFFECT_ROUTE_VEHICLE_ENGINE_MAX - EFFECT_ROUTE_VEHICLE_ENGINE_MIN + 1; loop++)
|
|
{
|
|
audMixerSubmix* thisSubmix = g_AudioEngine.GetEnvironment().GetVehicleEngineSubmix(loop);
|
|
thisSubmix->DisconnectOutput(m_ReflectionsSourceSubmix->GetSubmixId(), false);
|
|
}
|
|
|
|
for(s32 loop = 0; loop < EFFECT_ROUTE_VEHICLE_EXHAUST_MAX - EFFECT_ROUTE_VEHICLE_EXHAUST_MIN + 1; loop++)
|
|
{
|
|
audMixerSubmix* thisSubmix = g_AudioEngine.GetEnvironment().GetVehicleExhaustSubmix(loop);
|
|
thisSubmix->DisconnectOutput(m_ReflectionsSourceSubmix->GetSubmixId(), false);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity Shutdown
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::Shutdown()
|
|
{
|
|
DetachFromAll();
|
|
m_ReflectionsPoints.clear();
|
|
audEntity::Shutdown();
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity SetZoneReflectionPosition
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::AddAmbientZoneReflectionPosition(const Vector3& pos, audAmbientZone* ambientZone)
|
|
{
|
|
for(u32 loop = 0; loop < m_ReflectionsPoints.GetCount(); loop++)
|
|
{
|
|
if(m_ReflectionsPoints[loop].type == audReflectionPoint::kReflectionPointType_AmbientZone &&
|
|
m_ReflectionsPoints[loop].parentZone == ambientZone)
|
|
{
|
|
m_ReflectionsPoints[loop].position = pos;
|
|
return;
|
|
}
|
|
}
|
|
|
|
audReflectionPoint newReflectionPoint;
|
|
newReflectionPoint.position = pos;
|
|
newReflectionPoint.type = audReflectionPoint::kReflectionPointType_AmbientZone;
|
|
newReflectionPoint.parentZone = ambientZone;
|
|
m_ReflectionsPoints.Push(newReflectionPoint);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity AddDebugReflectionPosition
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::AddDebugReflectionPosition(const Vector3& pos)
|
|
{
|
|
for(u32 loop = 0; loop < m_ReflectionsPoints.GetCount(); loop++)
|
|
{
|
|
if(m_ReflectionsPoints[loop].type == audReflectionPoint::kReflectionPointType_Debug)
|
|
{
|
|
m_ReflectionsPoints[loop].position = pos;
|
|
return;
|
|
}
|
|
}
|
|
|
|
audReflectionPoint newReflectionPoint;
|
|
newReflectionPoint.position = pos;
|
|
newReflectionPoint.type = audReflectionPoint::kReflectionPointType_Debug;
|
|
m_ReflectionsPoints.Push(newReflectionPoint);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity RemoveAmbientZoneReflectionPosition
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::RemoveAmbientZoneReflectionPosition(audAmbientZone* ambientZone)
|
|
{
|
|
for(u32 loop = 0; loop < m_ReflectionsPoints.GetCount(); loop++)
|
|
{
|
|
if(m_ReflectionsPoints[loop].parentZone == ambientZone)
|
|
{
|
|
m_ReflectionsPoints.Delete(loop);
|
|
loop--;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity DetachFromAll
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::DetachFromAll()
|
|
{
|
|
for(s32 loop = 0; loop < m_AttachedEngineSubmixes.GetCount(); loop++)
|
|
{
|
|
audMixerSubmix* thisSubmix = g_AudioEngine.GetEnvironment().GetVehicleEngineSubmix(m_AttachedEngineSubmixes[loop]);
|
|
thisSubmix->DisconnectOutput(m_ReflectionsSourceSubmix->GetSubmixId(), false);
|
|
m_AttachedEngineSubmixes.Delete(loop);
|
|
loop--;
|
|
}
|
|
|
|
for(s32 loop = 0; loop < m_AttachedExhaustSubmixes.GetCount(); loop++)
|
|
{
|
|
audMixerSubmix* thisSubmix = g_AudioEngine.GetEnvironment().GetVehicleExhaustSubmix(m_AttachedExhaustSubmixes[loop]);
|
|
thisSubmix->DisconnectOutput(m_ReflectionsSourceSubmix->GetSubmixId(), false);
|
|
m_AttachedExhaustSubmixes.Delete(loop);
|
|
loop--;
|
|
}
|
|
|
|
for(u32 i = 0; i < INTERIOR_REFLECTION_MAX; i++)
|
|
{
|
|
if(m_InteriorReflections[i].m_ReflectionsSubmixIndex >= 0)
|
|
{
|
|
g_AudioEngine.GetEnvironment().FreeReflectionsOutputSubmix(m_InteriorReflections[i].m_ReflectionsSubmixIndex);
|
|
}
|
|
|
|
StopAndForgetSounds(m_InteriorReflections[i].m_ReflectionsVoice);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity DetachFromVehicle
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::DetachFromVehicle(audVehicleAudioEntity* vehAudioEntity)
|
|
{
|
|
if(vehAudioEntity->HasValidEngineEffectRoute() && vehAudioEntity->HasValidExhaustEffectRoute())
|
|
{
|
|
s32 engineEffectRoute = vehAudioEntity->GetEngineEffectSubmixIndex();
|
|
s32 exhaustEffectRoute = vehAudioEntity->GetExhaustEffectSubmixIndex();
|
|
|
|
for(s32 loop = 0; loop < m_AttachedEngineSubmixes.GetCount(); loop++)
|
|
{
|
|
if(m_AttachedEngineSubmixes[loop] == engineEffectRoute)
|
|
{
|
|
audMixerSubmix* thisSubmix = g_AudioEngine.GetEnvironment().GetVehicleEngineSubmix(m_AttachedEngineSubmixes[loop]);
|
|
thisSubmix->DisconnectOutput(m_ReflectionsSourceSubmix->GetSubmixId(), false);
|
|
m_AttachedEngineSubmixes.Delete(loop);
|
|
loop--;
|
|
}
|
|
}
|
|
|
|
for(s32 loop = 0; loop < m_AttachedExhaustSubmixes.GetCount(); loop++)
|
|
{
|
|
if(m_AttachedExhaustSubmixes[loop] == exhaustEffectRoute)
|
|
{
|
|
audMixerSubmix* thisSubmix = g_AudioEngine.GetEnvironment().GetVehicleExhaustSubmix(m_AttachedExhaustSubmixes[loop]);
|
|
thisSubmix->DisconnectOutput(m_ReflectionsSourceSubmix->GetSubmixId(), false);
|
|
m_AttachedExhaustSubmixes.Delete(loop);
|
|
loop--;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(vehAudioEntity == m_ActiveVehicle)
|
|
{
|
|
m_ActiveVehicle = NULL;
|
|
|
|
for(u32 i = 0; i < INTERIOR_REFLECTION_MAX; i++)
|
|
{
|
|
if(m_InteriorReflections[i].m_ReflectionsSubmixIndex >= 0)
|
|
{
|
|
g_AudioEngine.GetEnvironment().FreeReflectionsOutputSubmix(m_InteriorReflections[i].m_ReflectionsSubmixIndex);
|
|
}
|
|
|
|
StopAndForgetSounds(m_InteriorReflections[i].m_ReflectionsVoice);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity AttachToVehicle
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::AttachToVehicle(audVehicleAudioEntity* vehAudioEntity)
|
|
{
|
|
if(vehAudioEntity->HasValidEngineEffectRoute() && vehAudioEntity->HasValidExhaustEffectRoute() && vehAudioEntity != m_ActiveVehicle)
|
|
{
|
|
s32 engineEffectRoute = vehAudioEntity->GetEngineEffectSubmixIndex();
|
|
s32 exhaustEffectRoute = vehAudioEntity->GetExhaustEffectSubmixIndex();
|
|
|
|
bool engineEffectRouteValid = false;
|
|
bool exhaustEffectRouteValid = false;
|
|
|
|
for(s32 loop = 0; loop < m_AttachedEngineSubmixes.GetCount(); loop++)
|
|
{
|
|
if(m_AttachedEngineSubmixes[loop] == engineEffectRoute)
|
|
{
|
|
engineEffectRouteValid = true;
|
|
}
|
|
else
|
|
{
|
|
audMixerSubmix* thisSubmix = g_AudioEngine.GetEnvironment().GetVehicleEngineSubmix(m_AttachedEngineSubmixes[loop]);
|
|
thisSubmix->DisconnectOutput(m_ReflectionsSourceSubmix->GetSubmixId(), false);
|
|
m_AttachedEngineSubmixes.Delete(loop);
|
|
loop--;
|
|
}
|
|
}
|
|
|
|
for(s32 loop = 0; loop < m_AttachedExhaustSubmixes.GetCount(); loop++)
|
|
{
|
|
if(m_AttachedExhaustSubmixes[loop] == exhaustEffectRoute)
|
|
{
|
|
exhaustEffectRouteValid = true;
|
|
}
|
|
else
|
|
{
|
|
audMixerSubmix* thisSubmix = g_AudioEngine.GetEnvironment().GetVehicleExhaustSubmix(m_AttachedExhaustSubmixes[loop]);
|
|
thisSubmix->DisconnectOutput(m_ReflectionsSourceSubmix->GetSubmixId(), false);
|
|
m_AttachedExhaustSubmixes.Delete(loop);
|
|
loop--;
|
|
}
|
|
}
|
|
|
|
ALIGNAS(16) f32 outputVolumes[g_MaxOutputChannels] ;
|
|
sysMemSet(&outputVolumes[0], 0, sizeof(outputVolumes));
|
|
static const f32 clippingVolumeFix = 0.707946f;
|
|
outputVolumes[0] = clippingVolumeFix;
|
|
|
|
if(!engineEffectRouteValid)
|
|
{
|
|
audMixerSubmix* engineSubmix = vehAudioEntity->GetEngineEffectSubmix();
|
|
engineSubmix->AddOutput(m_ReflectionsSourceSubmix->GetSubmixId(), true, false);
|
|
engineSubmix->SetOutputVolumes(4, outputVolumes);
|
|
m_AttachedEngineSubmixes.Push(engineEffectRoute);
|
|
}
|
|
|
|
if(!exhaustEffectRouteValid)
|
|
{
|
|
audMixerSubmix* exhaustSubmix = vehAudioEntity->GetExhaustEffectSubmix();
|
|
exhaustSubmix->AddOutput(m_ReflectionsSourceSubmix->GetSubmixId(), true, false);
|
|
exhaustSubmix->SetOutputVolumes(4, outputVolumes);
|
|
m_AttachedExhaustSubmixes.Push(exhaustEffectRoute);
|
|
}
|
|
|
|
m_ActiveVehicle = vehAudioEntity;
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// ReflectionsPoints comparison
|
|
// ----------------------------------------------------------------
|
|
int CbCompareReflectionPoints(const audVehicleReflectionsEntity::audReflectionPoint* pA, const audVehicleReflectionsEntity::audReflectionPoint* pB)
|
|
{
|
|
Vector3 sourcePos = g_ReflectionsAudioEntity.GetCurrentSourcePosition();
|
|
f32 pADist2 = pA->position.Dist2(sourcePos);
|
|
f32 pBDist2 = pB->position.Dist2(sourcePos);
|
|
|
|
// Currently just sort on distance, should probably do it on estimated volume too
|
|
return pADist2 < pBDist2 ? -1 : (pADist2 == pBDist2 ? 0 : 1);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity Update
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::Update()
|
|
{
|
|
eReflectionsType reflectionsType = AUD_REFLECTIONS_TYPE_MAX;
|
|
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::StepRateSmoothing, g_ReflectionsStepRateSmoothing);
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::TimeStep, fwTimer::GetTimeStep());
|
|
bool stuntTunnelStateUpdated = false;
|
|
|
|
if(g_BonnetCamStereoEffectEnabled && audNorthAudioEngine::IsRenderingFirstPersonVehicleCam())
|
|
{
|
|
UpdateBonnetCamStereoEffect();
|
|
reflectionsType = AUD_REFLECTIONS_TYPE_STEREO_EFFECT;
|
|
m_LastBonnetCamUpdateTime = fwTimer::GetTimeInMilliseconds();
|
|
}
|
|
else if(g_InteriorReflectionsEnabled)
|
|
{
|
|
if(m_ReflectionsTypeLastFrame == AUD_REFLECTIONS_TYPE_STEREO_EFFECT)
|
|
{
|
|
m_InteriorReflections[0].m_ProbeHitTimer = 1.f;
|
|
m_InteriorReflections[1].m_ProbeHitTimer = 1.f;
|
|
}
|
|
|
|
if(BANK_ONLY(!g_TestReflections && )SUPERCONDUCTOR.GetVehicleConductor().JumpConductorActive() && NetworkInterface::IsGameInProgress() BANK_ONLY(|| g_ForceStuntTunnelProbesEnabled))
|
|
{
|
|
UpdateStuntTunnelReflections();
|
|
stuntTunnelStateUpdated = true;
|
|
}
|
|
else
|
|
{
|
|
UpdateInteriorReflections();
|
|
}
|
|
|
|
reflectionsType = AUD_REFLECTIONS_TYPE_INTERIOR;
|
|
}
|
|
|
|
if(m_ReflectionsSourceSubmix && m_ReflectionsTypeLastFrame != reflectionsType)
|
|
{
|
|
for(u32 i = 0; i < g_MaxOutputChannels; i++)
|
|
{
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::ResetDelay + i, 1);
|
|
}
|
|
}
|
|
|
|
if(m_ProximityWhooshesEnabled BANK_ONLY(|| g_ForceSwitchProximityWhooshes))
|
|
{
|
|
UpdateProximityWhooshes(g_AudioEngine.GetEnvironment().GetPanningListenerMatrix(), NULL);
|
|
}
|
|
|
|
if(g_VehicleReflectionsEnabled)
|
|
{
|
|
UpdateVehicleReflections();
|
|
}
|
|
|
|
// Stop any DSP voices that we're not using any more
|
|
for(u32 loop = 0; loop < AUD_NUM_REFLECTIONS_OUTPUT_SUBMIXES; loop++)
|
|
{
|
|
bool bypass = g_AudioEngine.GetEnvironment().IsReflectionsOutputSubmixFree(loop);
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::BypassChannel + loop, bypass);
|
|
}
|
|
|
|
// Make sure we clear this flag if we didn't update the stunt tunnel probes (eg. they have been disabled)
|
|
if(!stuntTunnelStateUpdated)
|
|
{
|
|
m_IsFocusVehicleInStuntTunnel = false;
|
|
}
|
|
|
|
#if __BANK
|
|
UpdateDebug();
|
|
#endif
|
|
|
|
m_ReflectionsTypeLastFrame = reflectionsType;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity AreInteriorReflectionsActive
|
|
// ----------------------------------------------------------------
|
|
bool audVehicleReflectionsEntity::AreInteriorReflectionsActive() const
|
|
{
|
|
for(u32 i = 0; i < m_InteriorReflections.GetMaxCount(); i++)
|
|
{
|
|
if(m_InteriorReflections[i].m_ReflectionsVoice != NULL)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity StopAllReflectionsVoices
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::StopAllReflectionsVoices()
|
|
{
|
|
for(u32 i = 0; i < INTERIOR_REFLECTION_MAX; i++)
|
|
{
|
|
m_InteriorReflections[i].m_ProbeDistSmoother.Reset();
|
|
StopAndForgetSounds(m_InteriorReflections[i].m_ReflectionsVoice);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity RegisterStuntTunnelMaterial
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::RegisterStuntTunnelMaterial(const char* materialName)
|
|
{
|
|
phMaterialMgr::Id stuntMaterialID = PGTAMATERIALMGR->FindMaterialId(materialName);
|
|
if(stuntMaterialID != phMaterialMgr::MATERIAL_NOT_FOUND)
|
|
{
|
|
m_StuntTunnelMaterialIDs.PushAndGrow(stuntMaterialID);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity UpdateStuntTunnelReflections
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::UpdateStuntTunnelReflections()
|
|
{
|
|
for(u32 i = 0; i < kMaxStuntTunnelProbes; i++)
|
|
{
|
|
m_StuntTunnelProbes[i].m_ProbeLastHitTimer += fwTimer::GetTimeStep();
|
|
}
|
|
|
|
if(m_ActiveVehicle)
|
|
{
|
|
// Actually sounds better without this - should we maybe just always not oscillate when not using dynamic reflections?
|
|
// m_OscillationTimer += fwTimer::GetTimeStep();
|
|
|
|
Mat34V_In matrix = m_ActiveVehicle->GetVehicle()->GetMatrix();
|
|
Vector3 sourcePos = VEC3V_TO_VECTOR3(matrix.d());
|
|
Vector3 right = VEC3V_TO_VECTOR3(matrix.a());
|
|
Vector3 forward = VEC3V_TO_VECTOR3(matrix.b());
|
|
Vector3 up = VEC3V_TO_VECTOR3(matrix.c());
|
|
|
|
for(u32 i = 0; i < kMaxStuntTunnelProbes; i++)
|
|
{
|
|
if(!m_StuntTunnelProbes[i].m_ProbeResults.GetWaitingOnResults())
|
|
{
|
|
if(m_StuntTunnelProbes[i].m_ProbeResults.GetResultsReady())
|
|
{
|
|
#if __BANK
|
|
if(g_ReflectionsDebugDraw)
|
|
{
|
|
grcDebugDraw::Line(m_StuntTunnelProbes[i].m_ProbeDesc.GetStart(), m_StuntTunnelProbes[i].m_ProbeDesc.GetEnd(), Color32(1.f,1.f,1.f));
|
|
}
|
|
#endif
|
|
|
|
u32 resultIndex = 0;
|
|
bool hitTunnel = false;
|
|
|
|
if(m_StuntTunnelProbes[i].m_ProbeResults.GetNumHits() > 0)
|
|
{
|
|
do
|
|
{
|
|
const WorldProbe::CShapeTestHitPoint& probeResult = m_StuntTunnelProbes[i].m_ProbeResults[resultIndex];
|
|
const phInst* physInst = probeResult.GetHitInst();
|
|
|
|
if(physInst)
|
|
{
|
|
if(!IsStuntTunnelMaterial(probeResult.GetHitMaterialId()))
|
|
{
|
|
resultIndex++;
|
|
}
|
|
else
|
|
{
|
|
m_StuntTunnelProbes[i].m_ProbeLastHitTimer = 0.0f;
|
|
hitTunnel = true;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
resultIndex++;
|
|
}
|
|
} while (resultIndex < m_StuntTunnelProbes[i].m_ProbeResults.GetNumHits());
|
|
|
|
|
|
if(resultIndex < m_StuntTunnelProbes[i].m_ProbeResults.GetNumHits())
|
|
{
|
|
m_StuntTunnelProbes[i].m_ProbeHit = true;
|
|
m_StuntTunnelProbes[i].m_ProbeHitPos = m_StuntTunnelProbes[i].m_ProbeResults[resultIndex].GetHitPosition();
|
|
|
|
#if __BANK
|
|
if(g_ReflectionsDebugDraw)
|
|
{
|
|
grcDebugDraw::Sphere(m_StuntTunnelProbes[i].m_ProbeHitPos, 0.3f, Color32(1.0f, 1.0f, 0.0f, 0.6f), true, 5);
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
m_StuntTunnelProbes[i].m_ProbeHit = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_StuntTunnelProbes[i].m_ProbeHit = false;
|
|
}
|
|
|
|
m_StuntTunnelProbes[i].m_ProbeResults.Reset();
|
|
}
|
|
|
|
Vector3 source = sourcePos + (forward * g_StuntTunnelRayCastForwardOffset);
|
|
Vector3 target = source;
|
|
|
|
switch(i)
|
|
{
|
|
case 0:
|
|
target += right * g_StuntTunnelRayCastLength;
|
|
break;
|
|
case 1:
|
|
target -= right * g_StuntTunnelRayCastLength;
|
|
break;
|
|
case 2:
|
|
target += up * g_StuntTunnelRayCastLength;
|
|
break;
|
|
case 3:
|
|
target -= up * g_StuntTunnelRayCastLength;
|
|
break;
|
|
}
|
|
|
|
m_StuntTunnelProbes[i].m_ProbeDesc.SetStartAndEnd(source, target);
|
|
m_StuntTunnelProbes[i].m_ProbeDesc.SetContext(WorldProbe::LOS_Audio);
|
|
m_StuntTunnelProbes[i].m_ProbeDesc.SetIncludeFlags(ArchetypeFlags::GTA_OBJECT_TYPE);
|
|
WorldProbe::GetShapeTestManager()->SubmitTest(m_StuntTunnelProbes[i].m_ProbeDesc, WorldProbe::PERFORM_ASYNCHRONOUS_TEST);
|
|
}
|
|
}
|
|
}
|
|
|
|
u32 numProbesHit = 0;
|
|
|
|
for(u32 i = 0; i < kMaxStuntTunnelProbes; i++)
|
|
{
|
|
if(m_StuntTunnelProbes[i].m_ProbeLastHitTimer < g_StuntTunnelProbeHitTimeout)
|
|
{
|
|
numProbesHit++;
|
|
}
|
|
}
|
|
|
|
// All 4 probes have to hit the tunnel to consider it an enter, but
|
|
bool isInTunnel = m_IsFocusVehicleInStuntTunnel? numProbesHit > 2 : numProbesHit == 4;
|
|
ReflectionsSettings* reflectionsSettings = audNorthAudioEngine::GetObject<ReflectionsSettings>(ATSTRINGHASH("TUNNEL_STATIC_STUNT", 0x70C19F88));
|
|
|
|
if(m_ActiveVehicle && m_IsFocusVehicleInStuntTunnel != isInTunnel)
|
|
{
|
|
if(reflectionsSettings)
|
|
{
|
|
const u32 now = fwTimer::GetTimeInMilliseconds();
|
|
|
|
if(now - m_LastStuntTunnelWhooshSound > g_StuntTunnelMinWhooshRepeatTimeMs)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.Position = VEC3V_TO_VECTOR3(m_ActiveVehicle->GetVehicle()->GetMatrix().d());
|
|
|
|
if(now - m_LastStuntTunnelWhooshSound > 5000 || m_LastStuntTunnelWhooshWasEnter == isInTunnel || m_LastStuntTunnelWhooshPosition.Dist2(initParams.Position) > (g_StuntTunnelMinWhooshExitDistance * g_StuntTunnelMinWhooshExitDistance))
|
|
{
|
|
BANK_ONLY(audDisplayf("Triggering stunt tunnel whoosh at %.02fm from previous whoosh", m_LastStuntTunnelWhooshPosition.Dist(initParams.Position)));
|
|
CreateAndPlaySound(isInTunnel ? reflectionsSettings->EnterSound : reflectionsSettings->ExitSound, &initParams);
|
|
m_LastStuntTunnelWhooshSound = fwTimer::GetTimeInMilliseconds();
|
|
m_LastStuntTunnelWhooshPosition = initParams.Position;
|
|
m_LastStuntTunnelWhooshWasEnter = isInTunnel;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_IsFocusVehicleInStuntTunnel = isInTunnel;
|
|
|
|
// If we've got reflections attached to the focus vehicle, trigger the reflections submix voice
|
|
if(reflectionsSettings)
|
|
{
|
|
if(m_ActiveVehicle)
|
|
{
|
|
for(u32 i = 0; i < INTERIOR_REFLECTION_MAX; i++)
|
|
{
|
|
if(isInTunnel)
|
|
{
|
|
f32 delaySeconds = i == 0? reflectionsSettings->MinDelay : reflectionsSettings->MaxDelay;
|
|
f32 dist = delaySeconds * g_AudioEngine.GetConfig().GetSpeedOfSound();
|
|
m_InteriorReflections[i].m_ReflectionsSettings = reflectionsSettings;
|
|
m_InteriorReflections[i].m_ProbeHit = true;
|
|
m_InteriorReflections[i].m_DistanceToFilterInputCurve.Init(reflectionsSettings->DistanceToFilterInput);
|
|
m_InteriorReflections[i].m_ProbeHitPos = VEC3V_TO_VECTOR3(m_ActiveVehicle->GetVehicle()->GetMatrix().GetCol3());
|
|
m_InteriorReflections[i].m_ProbeDist = m_InteriorReflections[i].m_ProbeDistSmoother.CalculateValue(dist);
|
|
m_InteriorReflections[i].m_ProbeDistSmoother.SetRates(m_InteriorReflections[i].m_ReflectionsSettings->Smoothing, m_InteriorReflections[i].m_ReflectionsSettings->Smoothing);
|
|
m_InteriorReflections[i].m_TunnelRight = VEC3V_TO_VECTOR3(m_ActiveVehicle->GetVehicle()->GetMatrix().a());
|
|
m_InteriorReflections[i].m_ReflectionsSettings = reflectionsSettings;
|
|
|
|
UpdateInteriorReflectionsVoice(i);
|
|
}
|
|
else
|
|
{
|
|
StopInteriorReflectionsVoice(i);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(u32 i = 0; i < INTERIOR_REFLECTION_MAX; i++)
|
|
{
|
|
StopInteriorReflectionsVoice(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity AddVehicleReflection
|
|
// ----------------------------------------------------------------
|
|
bool audVehicleReflectionsEntity::AddVehicleReflection(audVehicleAudioEntity* vehicle)
|
|
{
|
|
if(g_VehicleReflectionsEnabled)
|
|
{
|
|
s32 firstFreeIndex = -1;
|
|
|
|
for(u32 loop = 0; loop < kMaxVehicleReflections; loop++)
|
|
{
|
|
if(!m_VehicleReflections[loop].m_ReflectionsEntity)
|
|
{
|
|
if(firstFreeIndex == -1)
|
|
{
|
|
firstFreeIndex = loop;
|
|
}
|
|
}
|
|
else if(m_VehicleReflections[loop].m_ReflectionsEntity == vehicle)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if(firstFreeIndex >= 0)
|
|
{
|
|
s32 reflectionsSubmixIndex = g_AudioEngine.GetEnvironment().AssignReflectionsOutputSubmix();
|
|
|
|
if(reflectionsSubmixIndex >= 0)
|
|
{
|
|
m_VehicleReflections[firstFreeIndex].m_ReflectionsSubmixIndex = reflectionsSubmixIndex;
|
|
m_VehicleReflections[firstFreeIndex].m_ReflectionsSubmix = g_AudioEngine.GetEnvironment().GetReflectionsOutputSubmix(reflectionsSubmixIndex);
|
|
m_VehicleReflections[firstFreeIndex].m_ReflectionsEntity = vehicle;
|
|
m_VehicleReflections[firstFreeIndex].m_ReflectionsSettings = audNorthAudioEngine::GetObject<ReflectionsSettings>(ATSTRINGHASH("VEHICLE_DEFAULT", 0xC8ED64B0));
|
|
m_VehicleReflections[firstFreeIndex].m_DistanceToFilterInputCurve.Init(m_VehicleReflections[firstFreeIndex].m_ReflectionsSettings->DistanceToFilterInput);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity RemoveVehicleReflections
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::RemoveVehicleReflections(audVehicleAudioEntity* vehicle)
|
|
{
|
|
for(u32 loop = 0; loop < kMaxVehicleReflections; loop++)
|
|
{
|
|
if(m_VehicleReflections[loop].m_ReflectionsEntity == vehicle)
|
|
{
|
|
if(m_VehicleReflections[loop].m_ReflectionsSubmixIndex >= 0)
|
|
{
|
|
g_AudioEngine.GetEnvironment().FreeReflectionsOutputSubmix(m_VehicleReflections[loop].m_ReflectionsSubmixIndex);
|
|
m_VehicleReflections[loop].m_ReflectionsSubmixIndex = -1;
|
|
m_VehicleReflections[loop].m_ReflectionsSubmix = NULL;
|
|
}
|
|
|
|
m_VehicleReflections[loop].m_ReflectionsEntity = NULL;
|
|
StopAndForgetSounds(m_VehicleReflections[loop].m_ReflectionsVoice);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity UpdateVehicleReflections
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::UpdateVehicleReflections()
|
|
{
|
|
CPed *localPlayer = CPedFactory::GetFactory()->GetLocalPlayer();
|
|
|
|
if(m_ActiveVehicle && localPlayer)
|
|
{
|
|
Vector3 forward = VEC3V_TO_VECTOR3(m_ActiveVehicle->GetVehicle()->GetMatrix().b());
|
|
f32 fwdSpeed = DotProduct(m_ActiveVehicle->GetVehicle()->GetVelocity(), forward);
|
|
|
|
for(u32 loop = 0; loop < kMaxVehicleReflections; loop++)
|
|
{
|
|
if(m_VehicleReflections[loop].m_ReflectionsEntity)
|
|
{
|
|
if(!m_VehicleReflections[loop].m_ReflectionsVoice)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.AttackTime = g_ReflectionsAttackTime;
|
|
initParams.SourceEffectSubmixId = (s16) m_VehicleReflections[loop].m_ReflectionsSubmix->GetSubmixId();
|
|
CreateAndPlaySound_Persistent(m_VehicleReflections[loop].m_ReflectionsSettings->SubmixVoice, &m_VehicleReflections[loop].m_ReflectionsVoice, &initParams);
|
|
m_VehicleReflections[loop].m_FirstUpdate = true;
|
|
m_VehicleReflections[loop].m_DistSmoother.Reset();
|
|
m_VehicleReflections[loop].m_DistSmoother.SetRates(m_VehicleReflections[loop].m_ReflectionsSettings->Smoothing, m_VehicleReflections[loop].m_ReflectionsSettings->Smoothing);
|
|
}
|
|
|
|
if(m_VehicleReflections[loop].m_ReflectionsVoice)
|
|
{
|
|
// Using the player ped as the listener position, so that we don't get reflections pitching up and down if the camera spins around
|
|
Vector3 closestPoint;
|
|
Vector3 forward = VEC3V_TO_VECTOR3(m_VehicleReflections[loop].m_ReflectionsEntity->GetVehicle()->GetMatrix().b());
|
|
Vector3 vehiclePosition = VEC3V_TO_VECTOR3(m_VehicleReflections[loop].m_ReflectionsEntity->GetPosition());
|
|
Vector3 sourcePosition = VEC3V_TO_VECTOR3(localPlayer->GetTransform().GetPosition());
|
|
|
|
if(g_PointSourceVehicleReflections)
|
|
{
|
|
closestPoint = vehiclePosition;
|
|
}
|
|
else
|
|
{
|
|
f32 vehicleLength = m_VehicleReflections[loop].m_ReflectionsEntity->GetVehicle()->GetBoundSphere().GetRadiusf();
|
|
fwGeom::fwLine positioningLine = fwGeom::fwLine(vehiclePosition - (forward * vehicleLength), vehiclePosition + (forward * vehicleLength));
|
|
positioningLine.FindClosestPointOnLine(sourcePosition, closestPoint);
|
|
|
|
#if __BANK
|
|
if(g_ReflectionsDebugDraw)
|
|
{
|
|
grcDebugDraw::Line(positioningLine.m_start, positioningLine.m_end, Color32(1.f,1.f,1.f));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
f32 distance = m_VehicleReflections[loop].m_DistSmoother.CalculateValue(closestPoint.Dist(sourcePosition));
|
|
f32 speedOfSound = g_AudioEngine.GetConfig().GetSpeedOfSound();
|
|
f32 delaySeconds = ((distance/speedOfSound) * m_VehicleReflections[loop].m_ReflectionsSettings->DelayTimeScalar) + m_VehicleReflections[loop].m_ReflectionsSettings->DelayTimeAddition;
|
|
delaySeconds = Clamp(delaySeconds, m_VehicleReflections[loop].m_ReflectionsSettings->MinDelay, m_VehicleReflections[loop].m_ReflectionsSettings->MaxDelay);
|
|
u32 delaySamples = (u32)(kMixerNativeSampleRate * delaySeconds);
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::DelayInSamples + loop, delaySamples);
|
|
|
|
const bool filterEnabled = AUD_GET_TRISTATE_VALUE(m_VehicleReflections[loop].m_ReflectionsSettings->Flags, FLAG_ID_REFLECTIONSSETTINGS_FILTERENABLED) == AUD_TRISTATE_TRUE;
|
|
const f32 distanceFactor = Clamp((f32)m_VehicleReflections[loop].m_DistanceToFilterInputCurve.CalculateValue(distance), 0.0f, 1.0f);
|
|
const f32 filterFrequency = m_VehicleReflections[loop].m_ReflectionsSettings->FilterFrequencyMin + ((m_VehicleReflections[loop].m_ReflectionsSettings->FilterFrequencyMax - m_VehicleReflections[loop].m_ReflectionsSettings->FilterFrequencyMin) * distanceFactor);
|
|
const f32 filterBandwidth = m_VehicleReflections[loop].m_ReflectionsSettings->FilterBandwidthMin + ((m_VehicleReflections[loop].m_ReflectionsSettings->FilterBandwidthMax - m_VehicleReflections[loop].m_ReflectionsSettings->FilterBandwidthMin) * distanceFactor);
|
|
const f32 filterResonance = m_VehicleReflections[loop].m_ReflectionsSettings->FilterResonanceMin + ((m_VehicleReflections[loop].m_ReflectionsSettings->FilterResonanceMax - m_VehicleReflections[loop].m_ReflectionsSettings->FilterResonanceMin) * distanceFactor);
|
|
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::FilterEnabled + m_VehicleReflections[loop].m_ReflectionsSubmixIndex, filterEnabled);
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::FilterMode + m_VehicleReflections[loop].m_ReflectionsSubmixIndex, m_VehicleReflections[loop].m_ReflectionsSettings->FilterMode);
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::FilterFrequency + m_VehicleReflections[loop].m_ReflectionsSubmixIndex, filterFrequency);
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::FilterBandwidth + m_VehicleReflections[loop].m_ReflectionsSubmixIndex, filterBandwidth);
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::FilterResonance + m_VehicleReflections[loop].m_ReflectionsSubmixIndex, filterResonance);
|
|
|
|
bool invertPhase = AUD_GET_TRISTATE_VALUE(m_VehicleReflections[loop].m_ReflectionsSettings->Flags, (FLAG_ID_REFLECTIONSSETTINGS_INVERTPHASECHANNEL0 + m_VehicleReflections[loop].m_ReflectionsSubmixIndex)) == AUD_TRISTATE_TRUE;
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::InvertPhase + m_VehicleReflections[loop].m_ReflectionsSubmixIndex, invertPhase);
|
|
|
|
if(m_VehicleReflections[loop].m_FirstUpdate)
|
|
{
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::ResetDelay + loop, 1);
|
|
m_VehicleReflections[loop].m_FirstUpdate = false;
|
|
}
|
|
|
|
f32 requestedVolume = sm_ReflectionsVehicleSpeedToVolCurve.CalculateValue(fwdSpeed);
|
|
|
|
if(m_VehicleReflections[loop].m_ReflectionsEntity->GetVehicle()->pHandling)
|
|
{
|
|
f32 mass = m_VehicleReflections[loop].m_ReflectionsEntity->GetVehicle()->pHandling->m_fMass;
|
|
requestedVolume *= sm_ReflectionsVehicleMassToVolCurve.CalculateValue(mass);
|
|
}
|
|
|
|
bool isFirstPersonVehicleCamActive = audNorthAudioEngine::IsRenderingFirstPersonVehicleCam();
|
|
f32 engineExhaustVolume = Max(m_ActiveVehicle->GetDSPSettings()->enginePostSubmixAttenuation - g_EngineVolumeTrim - (isFirstPersonVehicleCamActive? g_StereoEffectEngineVolumeTrim : 0.0f), m_ActiveVehicle->GetDSPSettings()->exhaustPostSubmixAttenuation - g_ExhaustVolumeTrim - (isFirstPersonVehicleCamActive? g_StereoEffectExhaustVolumeTrim : 0.0f));
|
|
m_VehicleReflections[loop].m_ReflectionsVoice->SetRequestedPosition(closestPoint);
|
|
m_VehicleReflections[loop].m_ReflectionsVoice->SetRequestedDopplerFactor(0.0f);
|
|
m_VehicleReflections[loop].m_ReflectionsVoice->SetRequestedVolumeCurveScale(m_VehicleReflections[loop].m_ReflectionsSettings->RollOffScale);
|
|
m_VehicleReflections[loop].m_ReflectionsVoice->SetRequestedPostSubmixVolumeAttenuation(audDriverUtil::ComputeDbVolumeFromLinear(requestedVolume) + engineExhaustVolume + (m_VehicleReflections[loop].m_ReflectionsSettings->PostSubmixVolumeAttenuation * 0.01f));
|
|
|
|
#if __BANK
|
|
if(g_ReflectionsDebugDraw)
|
|
{
|
|
grcDebugDraw::Sphere(m_VehicleReflections[loop].m_ReflectionsVoice->GetRequestedPosition(), 1.5f, Color32(1.0f, 0.0f, 0.0f, 0.6f));
|
|
|
|
char tempString[64];
|
|
f32 yCoord = 0.2f + (0.1f * loop);
|
|
|
|
sprintf(tempString, "Reflection %d: %d/%d samples", loop, delaySamples, DELAY_MAX_SAMPLES_UNALIGNED);
|
|
grcDebugDraw::Text(Vector2(0.05f, yCoord + 0.05f), Color32(255,255,255), tempString);
|
|
|
|
sprintf(tempString, " %0.2f/%0.2f seconds", delaySeconds, DELAY_TIME_MAX/1000.0f);
|
|
grcDebugDraw::Text(Vector2(0.07f, yCoord + 0.07f), Color32(255,255,255), tempString);
|
|
|
|
sprintf(tempString, " Dist: %0.2f m", distance);
|
|
grcDebugDraw::Text(Vector2(0.07f, yCoord + 0.09f), Color32(255,255,255), tempString);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity UpdateProximityWhooshes
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::UpdateProximityWhooshes(Mat34V_In matrix, CEntity* entity)
|
|
{
|
|
Vector3 sourcePos = VEC3V_TO_VECTOR3(matrix.d());
|
|
Vector3 forward = VEC3V_TO_VECTOR3(matrix.b());
|
|
Vector3 right = VEC3V_TO_VECTOR3(matrix.a());
|
|
|
|
for(u32 i = 0; i < 2; i++)
|
|
{
|
|
if(!m_ProximityWhooshes[i].m_ProbeResults.GetWaitingOnResults())
|
|
{
|
|
if(m_ProximityWhooshes[i].m_ProbeResults.GetResultsReady())
|
|
{
|
|
#if __BANK
|
|
if(g_ReflectionsDebugDraw)
|
|
{
|
|
grcDebugDraw::Line(m_ProximityWhooshes[i].m_ProbeDesc.GetStart(), m_ProximityWhooshes[i].m_ProbeDesc.GetEnd(), Color32(1.f,1.f,1.f));
|
|
}
|
|
#endif
|
|
|
|
u32 resultIndex = 0;
|
|
|
|
if(m_ProximityWhooshes[i].m_ProbeResults.GetNumHits() > 0)
|
|
{
|
|
do
|
|
{
|
|
phInst* physInst = m_ProximityWhooshes[i].m_ProbeResults[resultIndex].GetHitInst();
|
|
|
|
if(physInst)
|
|
{
|
|
CEntity* intersectionEntity = CPhysics::GetEntityFromInst(physInst);
|
|
|
|
if(intersectionEntity && (intersectionEntity == entity || intersectionEntity->GetIsTypePed()))
|
|
{
|
|
resultIndex++;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
resultIndex++;
|
|
}
|
|
} while (resultIndex < m_ProximityWhooshes[i].m_ProbeResults.GetNumHits());
|
|
|
|
|
|
if(resultIndex < m_ProximityWhooshes[i].m_ProbeResults.GetNumHits())
|
|
{
|
|
m_ProximityWhooshes[i].m_ProbeHit = true;
|
|
m_ProximityWhooshes[i].m_ProbeHitPos = m_ProximityWhooshes[i].m_ProbeResults[resultIndex].GetHitPosition();
|
|
m_ProximityWhooshes[i].m_ProbeDist = m_ProximityWhooshes[i].m_ProbeDesc.GetStart().Dist(m_ProximityWhooshes[i].m_ProbeResults[resultIndex].GetHitPosition());
|
|
|
|
#if __BANK
|
|
if(g_ReflectionsDebugDraw)
|
|
{
|
|
grcDebugDraw::Sphere(m_ProximityWhooshes[i].m_ProbeHitPos, 0.3f, Color32(1.0f, 1.0f, 0.0f, 0.6f), true, 5);
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
m_ProximityWhooshes[i].m_ProbeHit = false;
|
|
m_ProximityWhooshes[i].m_ProbeDist = g_ProximityMaxProbeDistance;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_ProximityWhooshes[i].m_ProbeHit = false;
|
|
m_ProximityWhooshes[i].m_ProbeDist = g_ProximityMaxProbeDistance;
|
|
}
|
|
|
|
const f32 filterFactor = 0.1f;
|
|
f32 prevSmoothedDist = m_ProximityWhooshes[i].m_SmoothedProbeDist;
|
|
m_ProximityWhooshes[i].m_SmoothedProbeDist = (m_ProximityWhooshes[i].m_SmoothedProbeDist * (1.0f - filterFactor)) + (m_ProximityWhooshes[i].m_ProbeDist * filterFactor);
|
|
f32 distChangeRate = (m_ProximityWhooshes[i].m_SmoothedProbeDist - prevSmoothedDist) * fwTimer::GetInvTimeStep();
|
|
|
|
if(distChangeRate < -g_ProximityMinDistChangeRate &&
|
|
fwTimer::GetTimeInMilliseconds() - m_ProximityWhooshes[i].m_LastWhooshTime > g_ProximityWhooshMinRepeatTime)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.Position = m_ProximityWhooshes[i].m_ProbeHitPos;
|
|
|
|
#if __BANK
|
|
if(g_ReflectionsDebugDraw)
|
|
{
|
|
grcDebugDraw::Sphere(initParams.Position, 0.4f, Color32(1.0f, 0.0f, 0.0f, 0.8f), true, 15);
|
|
}
|
|
#endif
|
|
|
|
CreateAndPlaySound(sm_CameraSwitchSoundSet.Find(ATSTRINGHASH("CameraSwitchWhoosh", 0xD9593FB5)), &initParams);
|
|
m_ProximityWhooshes[i].m_LastWhooshTime = fwTimer::GetTimeInMilliseconds();
|
|
}
|
|
|
|
if(i == 0)
|
|
{
|
|
PF_SET(LeftProbeDist, m_ProximityWhooshes[i].m_SmoothedProbeDist);
|
|
PF_SET(LeftProbeDistChangeRate, distChangeRate);
|
|
}
|
|
else
|
|
{
|
|
PF_SET(RightProbeDist, m_ProximityWhooshes[i].m_SmoothedProbeDist);
|
|
PF_SET(RightProbeDistChangeRate, distChangeRate);
|
|
}
|
|
|
|
m_ProximityWhooshes[i].m_ProbeResults.Reset();
|
|
}
|
|
|
|
f32 entityWidth = 0.0f;
|
|
|
|
if(entity)
|
|
{
|
|
entityWidth = entity->GetBaseModelInfo()->GetBoundingBox().GetExtent().GetYf()/2.0f;
|
|
}
|
|
|
|
Vector3 source = sourcePos + (forward * g_ProximityRayCastForwardOffset) + ((i == 0? -right : right) * entityWidth);
|
|
Vector3 target = source + ((i == 0? -right : right) * g_ProximityMaxProbeDistance);
|
|
m_ProximityWhooshes[i].m_ProbeDesc.SetStartAndEnd(source, target);
|
|
m_ProximityWhooshes[i].m_ProbeDesc.SetIncludeFlags(ArchetypeFlags::GTA_ALL_TYPES_MOVER);
|
|
m_ProximityWhooshes[i].m_ProbeDesc.SetContext(WorldProbe::LOS_Audio);
|
|
WorldProbe::GetShapeTestManager()->SubmitTest(m_ProximityWhooshes[i].m_ProbeDesc, WorldProbe::PERFORM_ASYNCHRONOUS_TEST);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity UpdateBonnetCamStereoEffect
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::UpdateBonnetCamStereoEffect()
|
|
{
|
|
CPed *localPlayer = CPedFactory::GetFactory()->GetLocalPlayer();
|
|
|
|
if(m_ActiveVehicle && localPlayer)
|
|
{
|
|
for(u32 i = 0; i < INTERIOR_REFLECTION_MAX; i++)
|
|
{
|
|
// Assign a submix
|
|
if(!m_InteriorReflections[i].m_ReflectionsSubmix)
|
|
{
|
|
s32 reflectionsSubmixIndex = g_AudioEngine.GetEnvironment().AssignReflectionsOutputSubmix();
|
|
|
|
if(reflectionsSubmixIndex >= 0)
|
|
{
|
|
m_InteriorReflections[i].m_ReflectionsSubmixIndex = reflectionsSubmixIndex;
|
|
m_InteriorReflections[i].m_ReflectionsSubmix = g_AudioEngine.GetEnvironment().GetReflectionsOutputSubmix(reflectionsSubmixIndex);
|
|
}
|
|
}
|
|
|
|
if(!m_InteriorReflections[i].m_ReflectionsSettings)
|
|
{
|
|
m_InteriorReflections[i].m_ReflectionsSettings = audNorthAudioEngine::GetObject<ReflectionsSettings>(ATSTRINGHASH("INTERNAL_VIEW_REFLECTIONS", 0x6CA03B12));
|
|
}
|
|
|
|
// Create a voice
|
|
if(m_InteriorReflections[i].m_ReflectionsSubmix &&
|
|
m_InteriorReflections[i].m_ReflectionsSettings &&
|
|
!m_InteriorReflections[i].m_ReflectionsVoice)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.AttackTime = g_ReflectionsAttackTime;
|
|
initParams.SourceEffectSubmixId = (s16) m_InteriorReflections[i].m_ReflectionsSubmix->GetSubmixId();
|
|
CreateAndPlaySound_Persistent(ATSTRINGHASH("DEFAULT_REFLECTIONS_SUBMIX_CONTROL", 0xCE8F80C), &m_InteriorReflections[i].m_ReflectionsVoice, &initParams);
|
|
m_InteriorReflections[i].m_FirstUpdate = true;
|
|
}
|
|
|
|
// Set voice filter and delay parameters
|
|
if(m_InteriorReflections[i].m_ReflectionsVoice)
|
|
{
|
|
f32 delaySeconds = 0.0f;
|
|
|
|
if(g_StereoDelayLFOEnabled)
|
|
{
|
|
f32 lfoHz = i == 0? g_StereoDelayLFOHzLeft : g_StereoDelayLFOHzRight;
|
|
f32 lfoDelay = i == 0? g_StereoDelayLFOMagLeft : g_StereoDelayLFOMagRight;
|
|
f32 lfoOffset = i == 0? g_StereoDelayLFOOffsetLeft : g_StereoDelayLFOOffsetRight;
|
|
delaySeconds = lfoOffset + (lfoDelay * 0.5f) + (lfoDelay * 0.5f * Sinf((fwTimer::GetTimeInMilliseconds() * 0.001f * lfoHz)));
|
|
}
|
|
else
|
|
{
|
|
delaySeconds = i == 0? m_InteriorReflections[i].m_ReflectionsSettings->MinDelay : m_InteriorReflections[i].m_ReflectionsSettings->MaxDelay;
|
|
}
|
|
|
|
u32 delaySamples = (u32)(kMixerNativeSampleRate * delaySeconds);
|
|
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::DelayInSamples + i, delaySamples);
|
|
|
|
if(m_InteriorReflections[i].m_FirstUpdate)
|
|
{
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::ResetDelay + i, 1);
|
|
m_InteriorReflections[i].m_FirstUpdate = false;
|
|
}
|
|
|
|
f32 headAngle = 0.0f;
|
|
|
|
if(g_PanInteriorReflectionsWithHeadAngle)
|
|
{
|
|
Vec3V vehicleForward = m_ActiveVehicle->GetVehicle()->GetTransform().GetForward();
|
|
vehicleForward.SetZ(ScalarV(V_ZERO));
|
|
vehicleForward = Normalize(vehicleForward);
|
|
|
|
Vec3V listenerForward = g_AudioEngine.GetEnvironment().GetPanningListenerMatrix().GetCol1();
|
|
listenerForward.SetZ(ScalarV(V_ZERO));
|
|
listenerForward = Normalize(listenerForward);
|
|
|
|
Vec3V forwardCross = Cross(vehicleForward, listenerForward);
|
|
f32 forwardDot = Dot(vehicleForward, listenerForward).Getf();
|
|
headAngle = AcosfSafe(forwardDot) * RtoD;
|
|
|
|
if(Dot(Vec3V(m_ActiveVehicle->GetVehicle()->GetTransform().GetUp()), forwardCross).Getf() < 0.0f)
|
|
{
|
|
headAngle *= -1.0f;
|
|
}
|
|
}
|
|
|
|
bool isFirstPersonVehicleCamActive = audNorthAudioEngine::IsRenderingFirstPersonVehicleCam();
|
|
s32 finalPan = i == 0? g_StereoLeftPan : g_StereoRightPan;
|
|
finalPan += (s32)headAngle;
|
|
|
|
if(finalPan < 0)
|
|
{
|
|
finalPan += 360;
|
|
}
|
|
else if(finalPan > 360)
|
|
{
|
|
finalPan -= 360;
|
|
}
|
|
|
|
f32 engineExhaustVolume = Max(m_ActiveVehicle->GetDSPSettings()->enginePostSubmixAttenuation - g_EngineVolumeTrim - (isFirstPersonVehicleCamActive? g_StereoEffectEngineVolumeTrim : 0.0f), m_ActiveVehicle->GetDSPSettings()->exhaustPostSubmixAttenuation - g_ExhaustVolumeTrim - (isFirstPersonVehicleCamActive? g_StereoEffectExhaustVolumeTrim : 0.0f));
|
|
m_InteriorReflections[i].m_ReflectionsVoice->SetRequestedDopplerFactor(0.0f);
|
|
m_InteriorReflections[i].m_ReflectionsVoice->SetRequestedPan(finalPan);
|
|
m_InteriorReflections[i].m_ReflectionsVoice->SetRequestedPostSubmixVolumeAttenuation(engineExhaustVolume + (i == 0? g_StereoLeftAttenuation : g_StereoRightAttenuation) + (m_InteriorReflections[i].m_ReflectionsSettings->PostSubmixVolumeAttenuation * 0.01f));
|
|
|
|
bool filterEnabled = AUD_GET_TRISTATE_VALUE(m_InteriorReflections[i].m_ReflectionsSettings->Flags, FLAG_ID_REFLECTIONSSETTINGS_FILTERENABLED) == AUD_TRISTATE_TRUE;
|
|
const f32 filterFrequency = i == 0? m_InteriorReflections[i].m_ReflectionsSettings->FilterFrequencyMin : m_InteriorReflections[i].m_ReflectionsSettings->FilterFrequencyMax;
|
|
const f32 filterBandwidth = i == 0? m_InteriorReflections[i].m_ReflectionsSettings->FilterBandwidthMin : m_InteriorReflections[i].m_ReflectionsSettings->FilterBandwidthMax;
|
|
const f32 filterResonance = i == 0? m_InteriorReflections[i].m_ReflectionsSettings->FilterResonanceMin : m_InteriorReflections[i].m_ReflectionsSettings->FilterResonanceMax;
|
|
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::FilterEnabled + m_InteriorReflections[i].m_ReflectionsSubmixIndex, filterEnabled);
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::FilterMode + m_InteriorReflections[i].m_ReflectionsSubmixIndex, m_InteriorReflections[i].m_ReflectionsSettings->FilterMode);
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::FilterFrequency + m_InteriorReflections[i].m_ReflectionsSubmixIndex, filterFrequency);
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::FilterBandwidth + m_InteriorReflections[i].m_ReflectionsSubmixIndex, filterBandwidth);
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::FilterResonance + m_InteriorReflections[i].m_ReflectionsSubmixIndex, filterResonance);
|
|
|
|
bool invertPhase = AUD_GET_TRISTATE_VALUE(m_InteriorReflections[i].m_ReflectionsSettings->Flags, (FLAG_ID_REFLECTIONSSETTINGS_INVERTPHASECHANNEL0 + m_InteriorReflections[i].m_ReflectionsSubmixIndex)) == AUD_TRISTATE_TRUE;
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::InvertPhase + m_InteriorReflections[i].m_ReflectionsSubmixIndex, invertPhase);
|
|
|
|
#if __BANK
|
|
if(g_ReflectionsDebugDraw)
|
|
{
|
|
char tempString[64];
|
|
f32 yCoord = 0.05f;
|
|
|
|
if(i == INTERIOR_REFLECTION_LEFT)
|
|
{
|
|
f32 xCoord = 0.05f;
|
|
sprintf(tempString, "Left Delay:");
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
xCoord = 0.02f;
|
|
yCoord += 0.02f;
|
|
|
|
sprintf(tempString, "%d/%d samples", delaySamples, DELAY_MAX_SAMPLES_UNALIGNED);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
sprintf(tempString, "%f", delaySeconds);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
sprintf(tempString, "Pan %d", finalPan);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
if(filterEnabled)
|
|
{
|
|
sprintf(tempString, "Filter Frequency: %0.2f", filterFrequency);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
sprintf(tempString, "Filter Bandwidth: %0.2f", filterBandwidth);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
sprintf(tempString, "Filter Resonance: %0.2f", filterResonance);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
}
|
|
else
|
|
{
|
|
sprintf(tempString, "Filter Disabled");
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
f32 xCoord = 0.75f;
|
|
sprintf(tempString, "Right Delay:");
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
xCoord += 0.02f;
|
|
yCoord += 0.02f;
|
|
|
|
sprintf(tempString, "%d/%d samples", delaySamples, DELAY_MAX_SAMPLES_UNALIGNED);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
sprintf(tempString, "%f seconds", delaySeconds);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
sprintf(tempString, "Pan %d", finalPan);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
if(filterEnabled)
|
|
{
|
|
sprintf(tempString, "Filter Frequency: %0.2f", filterFrequency);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
sprintf(tempString, "Filter Bandwidth: %0.2f", filterBandwidth);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
|
|
sprintf(tempString, "Filter Resonance: %0.2f", filterResonance);
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
}
|
|
else
|
|
{
|
|
sprintf(tempString, "Filter Disabled");
|
|
grcDebugDraw::Text(Vector2(xCoord, yCoord), Color32(255,255,255), tempString);
|
|
yCoord += 0.02f;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity UpdateInteriorReflections
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::UpdateInteriorReflections()
|
|
{
|
|
CPed *localPlayer = CPedFactory::GetFactory()->GetLocalPlayer();
|
|
|
|
if(m_ActiveVehicle && localPlayer)
|
|
{
|
|
if ((fwTimer::GetSystemFrameCount() & 31) == 23)
|
|
{
|
|
UpdateLoadedInteriors();
|
|
}
|
|
|
|
m_OscillationTimer += fwTimer::GetTimeStep();
|
|
m_CurrentSourcePos = VEC3V_TO_VECTOR3(m_ActiveVehicle->GetVehicle()->TransformIntoWorldSpace(m_ActiveVehicle->GetEngineOffsetPos()));
|
|
|
|
Vector3 forward = VEC3V_TO_VECTOR3(m_ActiveVehicle->GetVehicle()->GetMatrix().b());
|
|
forward.SetZ(0.0f);
|
|
u32 numProbesHit = 0;
|
|
|
|
for(u32 i = 0; i < INTERIOR_REFLECTION_MAX; i++)
|
|
{
|
|
if(!m_InteriorReflections[i].m_ProbeResults.GetWaitingOnResults())
|
|
{
|
|
if(m_InteriorReflections[i].m_ProbeResults.GetResultsReady())
|
|
{
|
|
#if __BANK
|
|
if(g_ReflectionsDebugDraw)
|
|
{
|
|
grcDebugDraw::Line(m_InteriorReflections[i].m_ProbeDesc.GetStart(), m_InteriorReflections[i].m_ProbeDesc.GetEnd(), Color32(1.f,1.f,1.f));
|
|
}
|
|
#endif
|
|
|
|
if(m_InteriorReflections[i].m_ProbeResults.GetNumHits() > 0)
|
|
{
|
|
s32 furthestHit = m_InteriorReflections[i].m_ProbeResults.GetNumHits() - 1;
|
|
ReflectionsSettings* reflectionsSettings = NULL;
|
|
CEntity* intersectionEntity = NULL;
|
|
|
|
while(furthestHit >= 0 && !reflectionsSettings)
|
|
{
|
|
// Have found a room in the material, lets try and get the interior entity
|
|
phInst* physInst = m_InteriorReflections[i].m_ProbeResults[furthestHit].GetHitInst();
|
|
intersectionEntity = NULL;
|
|
|
|
if(physInst)
|
|
{
|
|
intersectionEntity = CPhysics::GetEntityFromInst(physInst);
|
|
|
|
if(intersectionEntity)
|
|
{
|
|
CBaseModelInfo *modelInfo = intersectionEntity->GetBaseModelInfo();
|
|
|
|
if(modelInfo && modelInfo->GetModelType() == MI_TYPE_MLO)
|
|
{
|
|
if(intersectionEntity != m_InteriorReflections[i].m_ReflectionsEntity)
|
|
{
|
|
InteriorSettings* interiorSettings = audNorthAudioEngine::GetObject<InteriorSettings>(modelInfo->GetHashKey());
|
|
|
|
if(interiorSettings)
|
|
{
|
|
reflectionsSettings = audNorthAudioEngine::GetObject<ReflectionsSettings>(interiorSettings->InteriorReflections);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
reflectionsSettings = m_InteriorReflections[i].m_ReflectionsSettings;
|
|
}
|
|
}
|
|
else if (intersectionEntity->GetOwnedBy() == ENTITY_OWNEDBY_STATICBOUNDS)
|
|
{
|
|
strLocalIndex boundsStoreIndex = strLocalIndex(intersectionEntity->GetIplIndex());
|
|
Assert(g_StaticBoundsStore.IsValidSlot(boundsStoreIndex));
|
|
|
|
InteriorProxyIndex proxyId = -1;
|
|
strLocalIndex depSlot;
|
|
g_StaticBoundsStore.GetDummyBoundData(boundsStoreIndex, proxyId, depSlot);
|
|
|
|
if(proxyId >= 0)
|
|
{
|
|
CInteriorProxy* pInteriorProxy = CInteriorProxy::GetPool()->GetSlot(proxyId);
|
|
|
|
if(pInteriorProxy)
|
|
{
|
|
if(intersectionEntity != m_InteriorReflections[i].m_ReflectionsEntity)
|
|
{
|
|
InteriorSettings* interiorSettings = audNorthAudioEngine::GetObject<InteriorSettings>(pInteriorProxy->GetNameHash());
|
|
|
|
if(interiorSettings)
|
|
{
|
|
reflectionsSettings = audNorthAudioEngine::GetObject<ReflectionsSettings>(interiorSettings->InteriorReflections);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
reflectionsSettings = m_InteriorReflections[i].m_ReflectionsSettings;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!reflectionsSettings)
|
|
{
|
|
furthestHit--;
|
|
}
|
|
}
|
|
|
|
if(reflectionsSettings)
|
|
{
|
|
m_InteriorReflections[i].m_ProbeHit = true;
|
|
m_InteriorReflections[i].m_ReflectionsSettings = reflectionsSettings;
|
|
m_InteriorReflections[i].m_DistanceToFilterInputCurve.Init(reflectionsSettings->DistanceToFilterInput);
|
|
m_InteriorReflections[i].m_ProbeHitPos = m_InteriorReflections[i].m_ProbeResults[furthestHit].GetHitPosition();
|
|
m_InteriorReflections[i].m_ProbeDist = m_InteriorReflections[i].m_ProbeDesc.GetStart().Dist(m_InteriorReflections[i].m_ProbeResults[furthestHit].GetHitPosition());
|
|
m_InteriorReflections[i].m_ProbeDist = m_InteriorReflections[i].m_ProbeDistSmoother.CalculateValue(Clamp(m_InteriorReflections[i].m_ProbeDist, g_MinProbeDist, g_MaxProbeDist));
|
|
m_InteriorReflections[i].m_ProbeDistSmoother.SetRates(m_InteriorReflections[i].m_ReflectionsSettings->Smoothing, m_InteriorReflections[i].m_ReflectionsSettings->Smoothing);
|
|
}
|
|
else
|
|
{
|
|
m_InteriorReflections[i].m_ProbeHit = false;
|
|
}
|
|
|
|
m_InteriorReflections[i].m_ReflectionsEntity = intersectionEntity;
|
|
m_InteriorReflections[i].m_ProbeResults.Reset();
|
|
}
|
|
else
|
|
{
|
|
m_InteriorReflections[i].m_ProbeHit = false;
|
|
}
|
|
}
|
|
|
|
CInteriorProxy* closestInterior = IsPointInOrNearDynamicReflectionsInterior(m_CurrentSourcePos);
|
|
if(closestInterior && closestInterior->GetInteriorInst())
|
|
{
|
|
Vector3 tunnelDir;
|
|
CalculateTunnelDirection(closestInterior->GetInteriorInst(), m_CurrentSourcePos, tunnelDir);
|
|
|
|
if(tunnelDir.Dot(m_InteriorReflections[i].m_PrevTunnelDirection) < 0.0f)
|
|
{
|
|
tunnelDir *= -1.0f;
|
|
}
|
|
|
|
m_InteriorReflections[i].m_PrevTunnelDirection = tunnelDir;
|
|
Vector3 tunnelRight = tunnelDir;
|
|
tunnelRight.RotateZ(HALF_PI);
|
|
f32 forwardDot = forward.Dot(tunnelDir);
|
|
Vector3 source = m_CurrentSourcePos + (tunnelDir * g_RayCastForwardOffset * forwardDot);
|
|
Vector3 target = source + ((i == INTERIOR_REFLECTION_LEFT? -tunnelRight : tunnelRight) * g_MaxProbeDist);
|
|
m_InteriorReflections[i].m_ProbeDesc.SetStartAndEnd(source, target);
|
|
m_InteriorReflections[i].m_ProbeDesc.SetIncludeFlags(ArchetypeFlags::GTA_ALL_MAP_TYPES);
|
|
m_InteriorReflections[i].m_ProbeDesc.SetContext(WorldProbe::LOS_Audio);
|
|
m_InteriorReflections[i].m_TunnelRight = tunnelRight;
|
|
WorldProbe::GetShapeTestManager()->SubmitTest(m_InteriorReflections[i].m_ProbeDesc, WorldProbe::PERFORM_ASYNCHRONOUS_TEST);
|
|
}
|
|
else
|
|
{
|
|
m_InteriorReflections[i].m_ProbeHit = false;
|
|
}
|
|
}
|
|
|
|
#if __BANK
|
|
if(g_TestReflections)
|
|
{
|
|
ReflectionsSettings* reflectionsSettings = audNorthAudioEngine::GetObject<ReflectionsSettings>(g_TestReflectionsName);
|
|
|
|
if(reflectionsSettings && AUD_GET_TRISTATE_VALUE(reflectionsSettings->Flags, FLAG_ID_REFLECTIONSSETTINGS_STATICREFLECTIONS) == AUD_TRISTATE_TRUE)
|
|
{
|
|
// Static reflections have two delay lines at fixed offsets from one another
|
|
f32 delaySeconds = i == 0? reflectionsSettings->MinDelay : reflectionsSettings->MaxDelay;
|
|
f32 dist = delaySeconds * g_AudioEngine.GetConfig().GetSpeedOfSound();
|
|
|
|
m_InteriorReflections[i].m_ProbeHit = true;
|
|
m_InteriorReflections[i].m_ReflectionsSettings = reflectionsSettings;
|
|
m_InteriorReflections[i].m_DistanceToFilterInputCurve.Init(reflectionsSettings->DistanceToFilterInput);
|
|
m_InteriorReflections[i].m_ProbeHitPos = VEC3V_TO_VECTOR3(localPlayer->GetTransform().GetPosition());
|
|
m_InteriorReflections[i].m_ProbeDist = m_InteriorReflections[i].m_ProbeDistSmoother.CalculateValue(dist);
|
|
m_InteriorReflections[i].m_ProbeDistSmoother.SetRates(m_InteriorReflections[i].m_ReflectionsSettings->Smoothing, m_InteriorReflections[i].m_ReflectionsSettings->Smoothing);
|
|
m_InteriorReflections[i].m_TunnelRight = VEC3V_TO_VECTOR3(m_ActiveVehicle->GetVehicle()->GetMatrix().a());
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// No dynamic reflections? Check if we've got some static ones linked to this interior
|
|
if(!m_InteriorReflections[i].m_ProbeHit)
|
|
{
|
|
CInteriorInst* pIntInst = CPortalVisTracker::GetPrimaryInteriorInst();
|
|
|
|
if(pIntInst)
|
|
{
|
|
if(pIntInst->GetArchetype())
|
|
{
|
|
u32 modelName = pIntInst->GetArchetype()->GetModelNameHash();
|
|
InteriorSettings* interiorSettings = audNorthAudioEngine::GetObject<InteriorSettings>(modelName);
|
|
|
|
if(interiorSettings)
|
|
{
|
|
ReflectionsSettings* reflectionsSettings = audNorthAudioEngine::GetObject<ReflectionsSettings>(interiorSettings->InteriorReflections);
|
|
|
|
if(reflectionsSettings && AUD_GET_TRISTATE_VALUE(reflectionsSettings->Flags, FLAG_ID_REFLECTIONSSETTINGS_STATICREFLECTIONS) == AUD_TRISTATE_TRUE)
|
|
{
|
|
// Static reflections have two delay lines at fixed offsets from one another
|
|
f32 delaySeconds = i == 0? reflectionsSettings->MinDelay : reflectionsSettings->MaxDelay;
|
|
f32 dist = delaySeconds * g_AudioEngine.GetConfig().GetSpeedOfSound();
|
|
|
|
m_InteriorReflections[i].m_ProbeHit = true;
|
|
m_InteriorReflections[i].m_ReflectionsSettings = reflectionsSettings;
|
|
m_InteriorReflections[i].m_DistanceToFilterInputCurve.Init(reflectionsSettings->DistanceToFilterInput);
|
|
m_InteriorReflections[i].m_ProbeHitPos = VEC3V_TO_VECTOR3(localPlayer->GetTransform().GetPosition());
|
|
m_InteriorReflections[i].m_ProbeDist = m_InteriorReflections[i].m_ProbeDistSmoother.CalculateValue(dist);
|
|
m_InteriorReflections[i].m_ProbeDistSmoother.SetRates(m_InteriorReflections[i].m_ReflectionsSettings->Smoothing, m_InteriorReflections[i].m_ReflectionsSettings->Smoothing);
|
|
m_InteriorReflections[i].m_TunnelRight = VEC3V_TO_VECTOR3(m_ActiveVehicle->GetVehicle()->GetMatrix().a());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// No dynamic or static reflections? Check if the ambient zones are requesting any
|
|
if(!m_InteriorReflections[i].m_ProbeHit)
|
|
{
|
|
for(u32 loop = 0; loop < g_AmbientAudioEntity.GetNumActiveZones(); loop++)
|
|
{
|
|
const audAmbientZone* ambientZone = g_AmbientAudioEntity.GetActiveZone(loop);
|
|
|
|
bool isZoneActive = false;
|
|
|
|
if(AUD_GET_TRISTATE_VALUE(ambientZone->GetZoneData()->Flags, FLAG_ID_AMBIENTZONE_HASTUNNELREFLECTIONS) == AUD_TRISTATE_TRUE ||
|
|
AUD_GET_TRISTATE_VALUE(ambientZone->GetZoneData()->Flags, FLAG_ID_AMBIENTZONE_HASREVERBLINKEDREFLECTIONS) == AUD_TRISTATE_TRUE)
|
|
{
|
|
// BuiltUp factor unused in reflections zones, so used to designate cylinder radius
|
|
const ScalarV cylinderRadius = ScalarV(ambientZone->GetZoneData()->BuiltUpFactor * 100.0f);
|
|
const Vec3V localPlayerPos = localPlayer->GetTransform().GetPosition();
|
|
|
|
if(ambientZone->GetZoneData()->Shape == kAmbientZoneCuboidLineEmitter || ambientZone->GetZoneData()->Shape == kAmbientZoneSphereLineEmitter)
|
|
{
|
|
const Vec3V closestPoint = ambientZone->ComputeClosestPointOnPositioningZoneBoundary(localPlayerPos);
|
|
const Vec3V lineStart = RCC_VEC3V(ambientZone->GetPositioningLine()->m_start);
|
|
const Vec3V lineEnd = RCC_VEC3V(ambientZone->GetPositioningLine()->m_end);
|
|
const ScalarV distSquared = DistSquared(lineStart, lineEnd);
|
|
|
|
if(IsTrue(IsLessThan(DistSquared(localPlayerPos, lineStart), distSquared)) &&
|
|
IsTrue(IsLessThan(DistSquared(localPlayerPos, lineEnd), distSquared)) &&
|
|
IsTrue(IsLessThan(DistSquared(localPlayerPos, closestPoint), (cylinderRadius * cylinderRadius))))
|
|
{
|
|
isZoneActive = true;
|
|
}
|
|
}
|
|
else if(ambientZone->IsPointInPositioningZone(localPlayerPos))
|
|
{
|
|
isZoneActive = true;
|
|
}
|
|
}
|
|
|
|
if(isZoneActive)
|
|
{
|
|
if(AUD_GET_TRISTATE_VALUE(ambientZone->GetZoneData()->Flags, FLAG_ID_AMBIENTZONE_HASTUNNELREFLECTIONS) == AUD_TRISTATE_TRUE)
|
|
{
|
|
// Just hard coding this with a flag for now to keep ambient zone GO size down - if we have enough of these then we may need to make it configurable
|
|
ReflectionsSettings* reflectionsSettings = audNorthAudioEngine::GetObject<ReflectionsSettings>(ATSTRINGHASH("TUNNEL_STATIC_SMALL_ENCLOSED", 0xAB0B5B6A));
|
|
|
|
if(reflectionsSettings)
|
|
{
|
|
f32 delaySeconds = i == 0? reflectionsSettings->MinDelay : reflectionsSettings->MaxDelay;
|
|
f32 dist = delaySeconds * g_AudioEngine.GetConfig().GetSpeedOfSound();
|
|
m_InteriorReflections[i].m_ProbeHit = true;
|
|
m_InteriorReflections[i].m_ReflectionsSettings = reflectionsSettings;
|
|
m_InteriorReflections[i].m_DistanceToFilterInputCurve.Init(reflectionsSettings->DistanceToFilterInput);
|
|
m_InteriorReflections[i].m_ProbeHitPos = VEC3V_TO_VECTOR3(localPlayer->GetTransform().GetPosition());
|
|
m_InteriorReflections[i].m_ProbeDist = m_InteriorReflections[i].m_ProbeDistSmoother.CalculateValue(dist);
|
|
m_InteriorReflections[i].m_ProbeDistSmoother.SetRates(m_InteriorReflections[i].m_ReflectionsSettings->Smoothing, m_InteriorReflections[i].m_ReflectionsSettings->Smoothing);
|
|
m_InteriorReflections[i].m_TunnelRight = VEC3V_TO_VECTOR3(m_ActiveVehicle->GetVehicle()->GetMatrix().a());
|
|
}
|
|
|
|
break;
|
|
}
|
|
else if(AUD_GET_TRISTATE_VALUE(ambientZone->GetZoneData()->Flags, FLAG_ID_AMBIENTZONE_HASREVERBLINKEDREFLECTIONS) == AUD_TRISTATE_TRUE)
|
|
{
|
|
f32 speakerReverbWetAverage = 0.0f;
|
|
f32 invSpeakerDamping = 1.0f/g_SpeakerReverbDamping;
|
|
|
|
for(u32 loop = 0; loop < 4; loop++)
|
|
{
|
|
speakerReverbWetAverage += Max(audNorthAudioEngine::GetGtaEnvironment()->GetSpeakerReverbWet(loop, 0), audNorthAudioEngine::GetGtaEnvironment()->GetSpeakerReverbWet(loop, 1)) * invSpeakerDamping;
|
|
}
|
|
|
|
speakerReverbWetAverage /= 4.0f;
|
|
|
|
if(speakerReverbWetAverage > g_WetReverbForReflections)
|
|
{
|
|
// Just hard coding this with a flag for now to keep ambient zone GO size down - if we have enough of these then we may need to make it configurable
|
|
ReflectionsSettings* reflectionsSettings = audNorthAudioEngine::GetObject<ReflectionsSettings>(ATSTRINGHASH("TUNNEL_STATIC_CAR_PARK", 0x43CFB20A));
|
|
|
|
if(reflectionsSettings)
|
|
{
|
|
f32 delaySeconds = i == 0? reflectionsSettings->MinDelay : reflectionsSettings->MaxDelay;
|
|
f32 dist = delaySeconds * g_AudioEngine.GetConfig().GetSpeedOfSound();
|
|
m_InteriorReflections[i].m_ProbeHit = true;
|
|
m_InteriorReflections[i].m_ReflectionsSettings = reflectionsSettings;
|
|
m_InteriorReflections[i].m_DistanceToFilterInputCurve.Init(reflectionsSettings->DistanceToFilterInput);
|
|
m_InteriorReflections[i].m_ProbeHitPos = VEC3V_TO_VECTOR3(localPlayer->GetTransform().GetPosition());
|
|
m_InteriorReflections[i].m_ProbeDist = m_InteriorReflections[i].m_ProbeDistSmoother.CalculateValue(dist);
|
|
m_InteriorReflections[i].m_ProbeDistSmoother.SetRates(m_InteriorReflections[i].m_ReflectionsSettings->Smoothing, m_InteriorReflections[i].m_ReflectionsSettings->Smoothing);
|
|
m_InteriorReflections[i].m_TunnelRight = VEC3V_TO_VECTOR3(m_ActiveVehicle->GetVehicle()->GetMatrix().a());
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(m_InteriorReflections[i].m_ProbeHit)
|
|
{
|
|
m_InteriorReflections[i].m_ProbeHitTimer = 0.0f;
|
|
numProbesHit++;
|
|
UpdateInteriorReflectionsVoice(i);
|
|
}
|
|
else
|
|
{
|
|
m_InteriorReflections[i].m_ProbeHitTimer += fwTimer::GetTimeStep();
|
|
|
|
if(m_InteriorReflections[i].m_ProbeHitTimer > 1.0f)
|
|
{
|
|
StopInteriorReflectionsVoice(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(numProbesHit == INTERIOR_REFLECTION_MAX && !m_HasPlayedInteriorEnter)
|
|
{
|
|
if(fwTimer::GetTimeInMilliseconds() - m_LastBonnetCamUpdateTime > 500)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.Position = (m_InteriorReflections[INTERIOR_REFLECTION_LEFT].m_ProbeHitPos + m_InteriorReflections[INTERIOR_REFLECTION_RIGHT].m_ProbeHitPos)/2.0f;
|
|
CreateAndPlaySound(m_InteriorReflections[INTERIOR_REFLECTION_LEFT].m_ReflectionsSettings->EnterSound, &initParams);
|
|
|
|
#if __BANK
|
|
if(g_ReflectionsDebugDraw)
|
|
{
|
|
grcDebugDraw::Sphere(initParams.Position, 0.3f, Color32(1.0f, 1.0f, 0.0f, 0.6f), true, 30);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
m_HasPlayedInteriorEnter = true;
|
|
m_HasPlayedInteriorExit = false;
|
|
}
|
|
else if(numProbesHit == 0 && m_HasPlayedInteriorEnter && !m_HasPlayedInteriorExit)
|
|
{
|
|
if(m_InteriorReflections[INTERIOR_REFLECTION_LEFT].m_ReflectionsSettings)
|
|
{
|
|
if(fwTimer::GetTimeInMilliseconds() - m_LastBonnetCamUpdateTime > 500)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.Position = (m_InteriorReflections[INTERIOR_REFLECTION_LEFT].m_ProbeHitPos + m_InteriorReflections[INTERIOR_REFLECTION_RIGHT].m_ProbeHitPos)/2.0f;
|
|
CreateAndPlaySound(m_InteriorReflections[INTERIOR_REFLECTION_LEFT].m_ReflectionsSettings->ExitSound, &initParams);
|
|
|
|
#if __BANK
|
|
if(g_ReflectionsDebugDraw)
|
|
{
|
|
grcDebugDraw::Sphere(initParams.Position, 0.3f, Color32(1.0f, 1.0f, 0.0f, 0.6f), true, 30);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
m_HasPlayedInteriorEnter = false;
|
|
m_HasPlayedInteriorExit = true;
|
|
g_ScriptAudioEntity.PlayMobileGetSignal(0.6f);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(u32 i = 0; i < INTERIOR_REFLECTION_MAX; i++)
|
|
{
|
|
m_InteriorReflections[i].m_ProbeHitTimer += fwTimer::GetTimeStep();
|
|
|
|
if(m_InteriorReflections[i].m_ProbeHitTimer > 1.0f)
|
|
{
|
|
StopInteriorReflectionsVoice(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if __BANK
|
|
if(g_ReflectionsDebugDraw)
|
|
{
|
|
char tempString[64];
|
|
formatf(tempString, "Active Interiors: %d", m_CurrentlyLoadedInteriors.GetCount());
|
|
grcDebugDraw::Text(Vector2(0.4f, 0.09f), Color32(255,255,255), tempString);
|
|
|
|
formatf(tempString, "Dot Product: %02f", m_DotTest);
|
|
grcDebugDraw::Text(Vector2(0.4f, 0.11f), Color32(255,255,255), tempString);
|
|
|
|
for(u32 loop = 0; loop < kMaxVehicleReflections; loop++)
|
|
{
|
|
formatf(tempString, "Submix %d: %s", loop, g_AudioEngine.GetEnvironment().IsReflectionsOutputSubmixFree(loop)? "Free" : "In Use");
|
|
grcDebugDraw::Text(Vector2(0.4f, 0.13f + (0.02f * loop)), Color32(255,255,255), tempString);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Update interior reflections
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::UpdateInteriorReflectionsVoice(u32 i)
|
|
{
|
|
if(!m_InteriorReflections[i].m_ReflectionsSubmix)
|
|
{
|
|
s32 reflectionsSubmixIndex = g_AudioEngine.GetEnvironment().AssignReflectionsOutputSubmix();
|
|
|
|
if(reflectionsSubmixIndex >= 0)
|
|
{
|
|
m_InteriorReflections[i].m_ReflectionsSubmixIndex = reflectionsSubmixIndex;
|
|
m_InteriorReflections[i].m_ReflectionsSubmix = g_AudioEngine.GetEnvironment().GetReflectionsOutputSubmix(reflectionsSubmixIndex);
|
|
}
|
|
}
|
|
|
|
if(m_InteriorReflections[i].m_ReflectionsSubmix && !m_InteriorReflections[i].m_ReflectionsVoice)
|
|
{
|
|
audSoundInitParams initParams;
|
|
initParams.AttackTime = g_ReflectionsAttackTime;
|
|
initParams.SourceEffectSubmixId = (s16) m_InteriorReflections[i].m_ReflectionsSubmix->GetSubmixId();
|
|
CreateAndPlaySound_Persistent(m_InteriorReflections[i].m_ReflectionsSettings->SubmixVoice, &m_InteriorReflections[i].m_ReflectionsVoice, &initParams);
|
|
m_InteriorReflections[i].m_FirstUpdate = true;
|
|
}
|
|
|
|
if(m_InteriorReflections[i].m_ReflectionsVoice)
|
|
{
|
|
// Static emitter distances are faked - just play the sound from the listener position
|
|
if(AUD_GET_TRISTATE_VALUE(m_InteriorReflections[i].m_ReflectionsSettings->Flags, FLAG_ID_REFLECTIONSSETTINGS_STATICREFLECTIONS) == AUD_TRISTATE_TRUE)
|
|
{
|
|
Vector3 listenerPos = VEC3V_TO_VECTOR3(g_AudioEngine.GetEnvironment().GetPanningListenerMatrix().d());
|
|
m_InteriorReflections[i].m_ReflectionsVoice->SetRequestedPosition(listenerPos);
|
|
}
|
|
else
|
|
{
|
|
Vector3 right = m_InteriorReflections[i].m_TunnelRight;
|
|
m_InteriorReflections[i].m_ReflectionsVoice->SetRequestedPosition(m_CurrentSourcePos + ((i == INTERIOR_REFLECTION_LEFT? -right : right) * m_InteriorReflections[i].m_ProbeDist));
|
|
}
|
|
}
|
|
|
|
if(m_InteriorReflections[i].m_ReflectionsVoice)
|
|
{
|
|
// Using the player ped as the listener position, so that we don't get reflections pitching up and down if the camera spins around
|
|
CPed *localPlayer = CPedFactory::GetFactory()->GetLocalPlayer();
|
|
Vector3 listenerPos = VEC3V_TO_VECTOR3(localPlayer->GetTransform().GetPosition());
|
|
Vector3 position = VEC3V_TO_VECTOR3(m_InteriorReflections[i].m_ReflectionsVoice->GetRequestedPosition());
|
|
Vector3 sourcePos = GetCurrentSourcePosition();
|
|
f32 dist = 0.0f;
|
|
f32 volumeAttenuation = 0.0f;
|
|
|
|
// Static reflections are using a fake distance with the actual sounds positioned on the vehicle, so just apply a bit of volume attenuation depending on how far away they are supposed to sound
|
|
if(AUD_GET_TRISTATE_VALUE(m_InteriorReflections[i].m_ReflectionsSettings->Flags, FLAG_ID_REFLECTIONSSETTINGS_STATICREFLECTIONS) == AUD_TRISTATE_TRUE)
|
|
{
|
|
dist = m_InteriorReflections[i].m_ProbeDist;
|
|
volumeAttenuation = sm_StaticReflectionsRollOffCurve.CalculateValue(dist - listenerPos.Dist(position));
|
|
}
|
|
else
|
|
{
|
|
dist = sourcePos.Dist(position) + listenerPos.Dist(position);
|
|
}
|
|
|
|
dist += sin(m_OscillationTimer * m_InteriorReflections[i].m_OscillatorSpeed) * m_InteriorReflections[i].m_OscillatorDist;
|
|
f32 delaySeconds = ((dist/g_AudioEngine.GetConfig().GetSpeedOfSound()) * m_InteriorReflections[i].m_ReflectionsSettings->DelayTimeScalar) + m_InteriorReflections[i].m_ReflectionsSettings->DelayTimeAddition;
|
|
|
|
if(AUD_GET_TRISTATE_VALUE(m_InteriorReflections[i].m_ReflectionsSettings->Flags, FLAG_ID_REFLECTIONSSETTINGS_STATICREFLECTIONS) != AUD_TRISTATE_TRUE)
|
|
{
|
|
delaySeconds = Clamp(delaySeconds, m_InteriorReflections[i].m_ReflectionsSettings->MinDelay, m_InteriorReflections[i].m_ReflectionsSettings->MaxDelay);
|
|
}
|
|
|
|
u32 delaySamples = (u32)(kMixerNativeSampleRate * delaySeconds);
|
|
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::DelayInSamples + i, delaySamples);
|
|
|
|
if(m_InteriorReflections[i].m_FirstUpdate)
|
|
{
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::ResetDelay + i, 1);
|
|
m_InteriorReflections[i].m_FirstUpdate = false;
|
|
}
|
|
|
|
bool isFirstPersonVehicleCamActive = audNorthAudioEngine::IsRenderingFirstPersonVehicleCam();
|
|
f32 engineExhaustVolume = Max(m_ActiveVehicle->GetDSPSettings()->enginePostSubmixAttenuation - g_EngineVolumeTrim - (isFirstPersonVehicleCamActive? g_StereoEffectEngineVolumeTrim : 0.0f), m_ActiveVehicle->GetDSPSettings()->exhaustPostSubmixAttenuation - g_ExhaustVolumeTrim - (isFirstPersonVehicleCamActive? g_StereoEffectExhaustVolumeTrim : 0.0f));
|
|
|
|
// GTAV specific fix
|
|
if(m_ActiveVehicle->IsMonsterTruck())
|
|
{
|
|
// Monster trucks are super loud, need to reign this in a bit
|
|
engineExhaustVolume -= 7.0f;
|
|
}
|
|
else
|
|
{
|
|
const u32 modelNameHash = m_ActiveVehicle->GetVehicleModelNameHash();
|
|
|
|
if(modelNameHash == ATSTRINGHASH("INSURGENT", 0x9114EADA) ||
|
|
modelNameHash == ATSTRINGHASH("INSURGENT2", 0x7B7E56F0) ||
|
|
modelNameHash == ATSTRINGHASH("INSURGENT3", 0x8D4B7A8A))
|
|
{
|
|
engineExhaustVolume -= 10.0f;
|
|
}
|
|
}
|
|
// GTAV specific fix
|
|
|
|
m_InteriorReflections[i].m_ReflectionsVoice->SetRequestedDopplerFactor(0.0f);
|
|
m_InteriorReflections[i].m_ReflectionsVoice->SetRequestedPan(-1);
|
|
m_InteriorReflections[i].m_ReflectionsVoice->SetRequestedVolumeCurveScale(m_InteriorReflections[i].m_ReflectionsSettings->RollOffScale);
|
|
m_InteriorReflections[i].m_ReflectionsVoice->SetRequestedPostSubmixVolumeAttenuation(engineExhaustVolume + volumeAttenuation + (m_InteriorReflections[i].m_ReflectionsSettings->PostSubmixVolumeAttenuation * 0.01f));
|
|
|
|
bool filterEnabled = AUD_GET_TRISTATE_VALUE(m_InteriorReflections[i].m_ReflectionsSettings->Flags, FLAG_ID_REFLECTIONSSETTINGS_FILTERENABLED) == AUD_TRISTATE_TRUE;
|
|
const f32 distanceFactor = Clamp((f32)m_InteriorReflections[i].m_DistanceToFilterInputCurve.CalculateValue(dist), 0.0f, 1.0f);
|
|
const f32 filterFrequency = m_InteriorReflections[i].m_ReflectionsSettings->FilterFrequencyMin + ((m_InteriorReflections[i].m_ReflectionsSettings->FilterFrequencyMax - m_InteriorReflections[i].m_ReflectionsSettings->FilterFrequencyMin) * distanceFactor);
|
|
const f32 filterBandwidth = m_InteriorReflections[i].m_ReflectionsSettings->FilterBandwidthMin + ((m_InteriorReflections[i].m_ReflectionsSettings->FilterBandwidthMax - m_InteriorReflections[i].m_ReflectionsSettings->FilterBandwidthMin) * distanceFactor);
|
|
const f32 filterResonance = m_InteriorReflections[i].m_ReflectionsSettings->FilterResonanceMin + ((m_InteriorReflections[i].m_ReflectionsSettings->FilterResonanceMax - m_InteriorReflections[i].m_ReflectionsSettings->FilterResonanceMin) * distanceFactor);
|
|
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::FilterEnabled + m_InteriorReflections[i].m_ReflectionsSubmixIndex, filterEnabled);
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::FilterMode + m_InteriorReflections[i].m_ReflectionsSubmixIndex, m_InteriorReflections[i].m_ReflectionsSettings->FilterMode);
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::FilterFrequency + m_InteriorReflections[i].m_ReflectionsSubmixIndex, filterFrequency);
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::FilterBandwidth + m_InteriorReflections[i].m_ReflectionsSubmixIndex, filterBandwidth);
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::FilterResonance + m_InteriorReflections[i].m_ReflectionsSubmixIndex, filterResonance);
|
|
|
|
bool invertPhase = AUD_GET_TRISTATE_VALUE(m_InteriorReflections[i].m_ReflectionsSettings->Flags, (FLAG_ID_REFLECTIONSSETTINGS_INVERTPHASECHANNEL0 + m_InteriorReflections[i].m_ReflectionsSubmixIndex)) == AUD_TRISTATE_TRUE;
|
|
m_ReflectionsSourceSubmix->SetEffectParam(0, audVariableDelayEffect::InvertPhase + m_InteriorReflections[i].m_ReflectionsSubmixIndex, invertPhase);
|
|
|
|
#if __BANK
|
|
if(g_ReflectionsDebugDraw)
|
|
{
|
|
char tempString[64];
|
|
|
|
if(i == INTERIOR_REFLECTION_LEFT)
|
|
{
|
|
sprintf(tempString, "Left Delay: %d/%d samples", delaySamples, DELAY_MAX_SAMPLES_UNALIGNED);
|
|
grcDebugDraw::Text(Vector2(0.05f, 0.05f), Color32(255,255,255), tempString);
|
|
|
|
sprintf(tempString, " %0.2f/%0.2f seconds", delaySeconds, DELAY_TIME_MAX/1000.0f);
|
|
grcDebugDraw::Text(Vector2(0.07f, 0.07f), Color32(255,255,255), tempString);
|
|
|
|
sprintf(tempString, " Dist: %0.2f m", dist);
|
|
grcDebugDraw::Text(Vector2(0.07f, 0.09f), Color32(255,255,255), tempString);
|
|
|
|
const char* reflectionsName = audNorthAudioEngine::GetMetadataManager().GetObjectNameFromNameTableOffset(m_InteriorReflections[i].m_ReflectionsSettings->NameTableOffset);
|
|
sprintf(tempString, " Gameobject: %s", reflectionsName);
|
|
grcDebugDraw::Text(Vector2(0.07f, 0.11f), Color32(255,255,255), tempString);
|
|
|
|
f32 fwdSpeed = DotProduct(m_ActiveVehicle->GetVehicle()->GetVelocity(), VEC3V_TO_VECTOR3(m_ActiveVehicle->GetVehicle()->GetTransform().GetB()));
|
|
sprintf(tempString, " Speed: %0.2f m/s", fwdSpeed);
|
|
grcDebugDraw::Text(Vector2(0.4f, 0.05f), Color32(255,255,255), tempString);
|
|
}
|
|
else
|
|
{
|
|
sprintf(tempString, "Right Delay: %d/%d samples", delaySamples, DELAY_MAX_SAMPLES_UNALIGNED);
|
|
grcDebugDraw::Text(Vector2(0.75f, 0.05f), Color32(255,255,255), tempString);
|
|
|
|
sprintf(tempString, " %0.2f/%0.2f seconds", delaySeconds, DELAY_TIME_MAX/1000.0f);
|
|
grcDebugDraw::Text(Vector2(0.75f, 0.07f), Color32(255,255,255), tempString);
|
|
|
|
sprintf(tempString, " Dist: %0.2f m", dist);
|
|
grcDebugDraw::Text(Vector2(0.75f, 0.09f), Color32(255,255,255), tempString);
|
|
|
|
const char* reflectionsName = audNorthAudioEngine::GetMetadataManager().GetObjectNameFromNameTableOffset(m_InteriorReflections[i].m_ReflectionsSettings->NameTableOffset);
|
|
sprintf(tempString, " Gameobject: %s", reflectionsName);
|
|
grcDebugDraw::Text(Vector2(0.75f, 0.11f), Color32(255,255,255), tempString);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Stop the given interior reflections voice
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::StopInteriorReflectionsVoice(u32 i)
|
|
{
|
|
if(m_InteriorReflections[i].m_ReflectionsSubmixIndex >= 0)
|
|
{
|
|
g_AudioEngine.GetEnvironment().FreeReflectionsOutputSubmix(m_InteriorReflections[i].m_ReflectionsSubmixIndex);
|
|
m_InteriorReflections[i].m_ReflectionsSubmixIndex = -1;
|
|
m_InteriorReflections[i].m_ReflectionsSubmix = NULL;
|
|
}
|
|
|
|
m_InteriorReflections[i].m_ProbeDistSmoother.Reset();
|
|
StopAndForgetSounds(m_InteriorReflections[i].m_ReflectionsVoice);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Update which interiors are loaded
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::UpdateLoadedInteriors()
|
|
{
|
|
m_CurrentlyLoadedInteriors.clear();
|
|
CInteriorProxy* intProxy = NULL;
|
|
CInteriorProxy::Pool* pool = CInteriorProxy::GetPool();
|
|
|
|
if(pool)
|
|
{
|
|
s32 poolSize = pool->GetSize();
|
|
while(poolSize--)
|
|
{
|
|
intProxy = pool->GetSlot(poolSize);
|
|
if(intProxy && intProxy->GetInteriorInst())
|
|
{
|
|
m_CurrentlyLoadedInteriors.PushAndGrow(intProxy);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Check if a point is in or close to an interior
|
|
// ----------------------------------------------------------------
|
|
CInteriorProxy* audVehicleReflectionsEntity::IsPointInOrNearDynamicReflectionsInterior(const Vector3& position)
|
|
{
|
|
f32 closestInteriorDistanceSq = FLT_MAX;
|
|
CInteriorProxy* closestInterior = NULL;
|
|
|
|
for(s32 loop = 0; loop < m_CurrentlyLoadedInteriors.GetCount(); loop++)
|
|
{
|
|
if(m_CurrentlyLoadedInteriors[loop]->GetInteriorInst() && m_CurrentlyLoadedInteriors[loop]->GetInteriorInst()->GetInteriorSceneGraphNode() && m_CurrentlyLoadedInteriors[loop]->GetInteriorInst()->GetNumPortals() == 2)
|
|
{
|
|
spdAABB boundingBox;
|
|
m_CurrentlyLoadedInteriors[loop]->GetBoundBox(boundingBox);
|
|
spdSphere sphere = spdSphere(Vec3V(position), ScalarV(V_TEN));
|
|
|
|
if(boundingBox.IntersectsSphere(sphere))
|
|
{
|
|
f32 distSq = VEC3V_TO_VECTOR3(boundingBox.GetCenter()).Dist2(position);
|
|
if(distSq < closestInteriorDistanceSq)
|
|
{
|
|
CInteriorProxy* thisInterior = m_CurrentlyLoadedInteriors[loop];
|
|
InteriorSettings* interiorSettings = audNorthAudioEngine::GetObject<InteriorSettings>(thisInterior->GetNameHash());
|
|
|
|
if(interiorSettings)
|
|
{
|
|
ReflectionsSettings* reflectionsSettings = audNorthAudioEngine::GetObject<ReflectionsSettings>(interiorSettings->InteriorReflections);
|
|
|
|
if(reflectionsSettings && AUD_GET_TRISTATE_VALUE(reflectionsSettings->Flags, FLAG_ID_REFLECTIONSSETTINGS_STATICREFLECTIONS) != AUD_TRISTATE_TRUE)
|
|
{
|
|
closestInterior = m_CurrentlyLoadedInteriors[loop];
|
|
closestInteriorDistanceSq = distSq;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return closestInterior;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Calculate the forward direction through a tunnel
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::CalculateTunnelDirection(CInteriorInst* interiorInst, const Vector3& position, Vector3& direction)
|
|
{
|
|
if(audVerifyf(interiorInst->GetNumPortals() == 2, "Tunnel %s has > 2 exits", interiorInst->GetModelName()))
|
|
{
|
|
Vec3V position2D = RCC_VEC3V(position);
|
|
position2D.SetZ(ScalarV(V_ZERO));
|
|
|
|
const Vec3V portal0p0 = interiorInst->GetPortal(0).GetCornerV(0);
|
|
const Vec3V portal0p1 = interiorInst->GetPortal(0).GetCornerV(1);
|
|
const Vec3V portal0p2 = interiorInst->GetPortal(0).GetCornerV(2);
|
|
const Vec3V portal0p3 = interiorInst->GetPortal(0).GetCornerV(3);
|
|
Vec3V portal0Centre = (portal0p0 + portal0p1 + portal0p2 + portal0p3) * ScalarV(V_QUARTER);
|
|
Vec3V portal0Normal = Normalize(Cross(portal0p1 - portal0p0, portal0p2 - portal0p0) + Cross(portal0p2 - portal0p0, portal0p3 - portal0p0));
|
|
|
|
const Vec3V portal1p0 = interiorInst->GetPortal(1).GetCornerV(0);
|
|
const Vec3V portal1p1 = interiorInst->GetPortal(1).GetCornerV(1);
|
|
const Vec3V portal1p2 = interiorInst->GetPortal(1).GetCornerV(2);
|
|
const Vec3V portal1p3 = interiorInst->GetPortal(1).GetCornerV(3);
|
|
Vec3V portal1Centre = (portal1p0 + portal1p1 + portal1p2 + portal1p3) * ScalarV(V_QUARTER);
|
|
Vec3V portal1Normal = Normalize(Cross(portal1p1 - portal1p0, portal1p2 - portal1p0) + Cross(portal1p2 - portal1p0, portal1p3 - portal1p0));
|
|
|
|
if(Dot(portal0Normal, portal1Centre - portal0Centre).Getf() < 0.0f)
|
|
{
|
|
portal0Normal *= ScalarV(V_NEGONE);
|
|
}
|
|
|
|
if(Dot(portal1Normal, portal1Centre - portal0Centre).Getf() < 0.0f)
|
|
{
|
|
portal1Normal *= ScalarV(V_NEGONE);
|
|
}
|
|
|
|
#if __BANK
|
|
if(g_ReflectionsDebugDraw)
|
|
{
|
|
grcDebugDraw::Line(portal0Centre, portal0Centre + (portal0Normal * ScalarV(20.0f)), Color32(1.f,0.f,0.f), 5);
|
|
grcDebugDraw::Line(portal1Centre, portal1Centre + (portal1Normal * ScalarV(20.0f)), Color32(0.f,1.f,0.f), 5);
|
|
}
|
|
#endif
|
|
|
|
portal0Centre.SetZ(ScalarV(V_ZERO));
|
|
portal1Centre.SetZ(ScalarV(V_ZERO));
|
|
|
|
ScalarV distBetweenPortals = Dist(portal0Centre, portal1Centre);
|
|
ScalarV distToPortal0 = Dist(position2D, portal0Centre);
|
|
ScalarV fractionBetween = Clamp(distToPortal0/distBetweenPortals, ScalarV(V_ZERO), ScalarV(V_ONE));
|
|
Vec3V tunnelDirection = AddScaled(portal0Normal, portal1Normal - portal0Normal, fractionBetween);
|
|
tunnelDirection.SetZ(ScalarV(V_ZERO));
|
|
|
|
direction = VEC3V_TO_VECTOR3(Normalize(tunnelDirection));
|
|
}
|
|
}
|
|
|
|
#if __BANK
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity UpdateDebug
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::UpdateDebug()
|
|
{
|
|
if(g_ReflectionsDebugDraw)
|
|
{
|
|
CInteriorInst* pIntInst = CPortalVisTracker::GetPrimaryInteriorInst();
|
|
|
|
if(pIntInst && m_ActiveVehicle)
|
|
{
|
|
Vector3 tunnelDir;
|
|
CalculateTunnelDirection(pIntInst, m_CurrentSourcePos, tunnelDir);
|
|
Vector3 forward = VEC3V_TO_VECTOR3(m_ActiveVehicle->GetVehicle()->GetMatrix().b());
|
|
forward.SetZ(0.0f);
|
|
f32 forwardDot = forward.Dot(tunnelDir);
|
|
tunnelDir *= 20.0f;
|
|
grcDebugDraw::Line(m_CurrentSourcePos, m_CurrentSourcePos + (tunnelDir * forwardDot), Color32(1.f,1.f,1.f));
|
|
}
|
|
}
|
|
|
|
for(u32 i = 0; i < INTERIOR_REFLECTION_MAX; i++)
|
|
{
|
|
if(g_ReflectionsDebugDraw)
|
|
{
|
|
if(m_InteriorReflections[i].m_ReflectionsVoice)
|
|
{
|
|
grcDebugDraw::Sphere(m_InteriorReflections[i].m_ReflectionsVoice->GetRequestedPosition(), 0.3f, Color32(1.0f, 0.0f, 0.0f, 0.6f));
|
|
}
|
|
}
|
|
}
|
|
|
|
if(g_ReflectionsLocationPickerEnabled)
|
|
{
|
|
if(CDebugScene::GetMouseLeftPressed())
|
|
{
|
|
CDebugScene::GetWorldPositionUnderMouse(m_DebugWorldPos);
|
|
AddDebugReflectionPosition(m_DebugWorldPos);
|
|
}
|
|
}
|
|
|
|
if(g_DebugPrintInteriorTunnels || g_DebugPrintInteriorsAll)
|
|
{
|
|
CInteriorProxy* intProxy = NULL;
|
|
CInteriorProxy::Pool* pool = CInteriorProxy::GetPool();
|
|
|
|
if(pool)
|
|
{
|
|
s32 poolSize = pool->GetSize();
|
|
while(poolSize--)
|
|
{
|
|
intProxy = pool->GetSlot(poolSize);
|
|
|
|
if(intProxy && (g_DebugPrintInteriorsAll || atString(intProxy->GetModelName()).IndexOf("tun") >= 0))
|
|
{
|
|
spdAABB boundingBox;
|
|
intProxy->GetBoundBox(boundingBox);
|
|
audDisplayf("%s: %s %f %f %f", g_DebugPrintInteriorsAll? "Interior" : "Tunnel", intProxy->GetModelName(), boundingBox.GetCenter().GetXf(), boundingBox.GetCenter().GetYf(), boundingBox.GetCenter().GetZf());
|
|
}
|
|
}
|
|
}
|
|
|
|
g_DebugPrintInteriorTunnels = false;
|
|
g_DebugPrintInteriorsAll = false;
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// audVehicleReflectionsEntity AddWidgets
|
|
// ----------------------------------------------------------------
|
|
void audVehicleReflectionsEntity::AddWidgets(bkBank &bank)
|
|
{
|
|
bank.PushGroup("Vehicle Reflections",false);
|
|
bank.PushGroup("Debug Controls",false);
|
|
bank.PushGroup("Bonnet Cam Stereo Effect",false);
|
|
bank.AddToggle("Bonnet Cam Stereo Effect Enabled", &g_BonnetCamStereoEffectEnabled);
|
|
bank.AddToggle("Debug Draw", &g_ReflectionsDebugDraw);
|
|
bank.AddSlider("Left Pan", &g_StereoLeftPan, 0, 360, 1);
|
|
bank.AddSlider("Right Pan", &g_StereoRightPan, 0, 360, 1);
|
|
bank.AddSlider("Left Attenuation", &g_StereoLeftAttenuation, -100.0f, 0.0f, 0.1f);
|
|
bank.AddSlider("Right Attenuation", &g_StereoRightAttenuation, -100.0f, 0.0f, 0.01f);
|
|
bank.AddToggle("Delay LFO Enabled", &g_StereoDelayLFOEnabled);
|
|
bank.AddSlider("Delay LFO Hz (Left Channel)", &g_StereoDelayLFOHzLeft, 0.0f, 5000.0f, 0.0001f);
|
|
bank.AddSlider("Delay LFO Hz (Right Channel)", &g_StereoDelayLFOHzRight, 0.0f, 5000.0f, 0.0001f);
|
|
bank.AddSlider("Delay LFO Amplitude (Left Channel)", &g_StereoDelayLFOMagLeft, 0.0f, 2.0f, 0.0001f);
|
|
bank.AddSlider("Delay LFO Amplitude (Right Channel)", &g_StereoDelayLFOMagRight, 0.0f, 2.0f, 0.0001f);
|
|
bank.AddSlider("Delay LFO Offset (Left Channel)", &g_StereoDelayLFOOffsetLeft, 0.0f, 2.0f, 0.0001f);
|
|
bank.AddSlider("Delay LFO Offset (Right Channel)", &g_StereoDelayLFOOffsetRight, 0.0f, 2.0f, 0.0001f);
|
|
bank.AddSlider("Stereo Engine Volume Trim", &g_StereoEffectEngineVolumeTrim, -100.0f, 100.f, 0.1f);
|
|
bank.AddSlider("Stereo Exhaust Volume Trim", &g_StereoEffectExhaustVolumeTrim, -100.0f, 100.f, 0.1f);
|
|
bank.AddToggle("Pan Interior Reflections With Head Angle", &g_PanInteriorReflectionsWithHeadAngle);
|
|
bank.PopGroup();
|
|
bank.AddText("Test Static Reflections Name", g_TestReflectionsName, sizeof(g_TestReflectionsName));
|
|
bank.AddToggle("Test Static Reflections", &g_TestReflections);
|
|
bank.AddToggle("Debug Draw", &g_ReflectionsDebugDraw);
|
|
bank.AddToggle("Debug Print Tunnel Locations", &g_DebugPrintInteriorTunnels);
|
|
bank.AddToggle("Debug Print All Locations", &g_DebugPrintInteriorsAll);
|
|
bank.AddSlider("Engine Volume Trim", &g_EngineVolumeTrim, -100.0f, 100.f, 0.1f);
|
|
bank.AddSlider("Exhaust Volume Trim", &g_ExhaustVolumeTrim, -100.0f, 100.f, 0.1f);
|
|
bank.AddToggle("Interior Reflections Enabled", &g_InteriorReflectionsEnabled);
|
|
bank.AddToggle("Vehicle Reflections Enabled", &g_VehicleReflectionsEnabled);
|
|
bank.AddToggle("Force Stunt Tunnel Probes", &g_ForceStuntTunnelProbesEnabled);
|
|
bank.AddToggle("Point Source Vehicle Reflections", &g_PointSourceVehicleReflections);
|
|
bank.AddToggle("Location Picker Enabled ", &g_ReflectionsLocationPickerEnabled);
|
|
bank.AddSlider("Max Probe Distance", &g_MaxProbeDist, 0.0f, 100.f, 1.0f);
|
|
bank.AddSlider("Min Probe Distance", &g_MinProbeDist, 0.0f, 100.f, 1.0f);
|
|
bank.AddSlider("Vehicle Reflections Activation Distance", &g_VehicleReflectionsActivationDist, 0.0f, 100.f, 1.0f);
|
|
bank.AddSlider("Attack Time", &g_ReflectionsAttackTime, 0, 1000, 10);
|
|
bank.AddSlider("Ray Cast Forward Offset", &g_RayCastForwardOffset, 0.0f, 100.0F, 0.1f);
|
|
bank.AddSlider("Step Rate Smoothing", &g_ReflectionsStepRateSmoothing, 0.0001f, 10.f, 0.01f);
|
|
bank.AddSlider("Left Oscillator Speed", &g_LeftOscillatorSpeed, 0.01f, 10.f, 0.1f);
|
|
bank.AddSlider("Right Oscillator Speed", &g_RightOscillatorSpeed, 0.01f, 10.f, 0.1f);
|
|
bank.AddSlider("Left Oscillator Distance", &g_LeftOscillatorDist, 0.01f, 10.f, 0.1f);
|
|
bank.AddSlider("Right Oscillator Distance", &g_RightOscillatorDist, 0.01f, 10.f, 0.1f);
|
|
bank.AddButton("Detach Reflections", datCallback(MFA(audVehicleReflectionsEntity::DetachFromAll), (datBase*)this), "");
|
|
bank.AddToggle("Force Character Switch Proximity Whooshes", &g_ForceSwitchProximityWhooshes);
|
|
bank.AddSlider("Proximity Required Dist Change Rate", &g_ProximityMinDistChangeRate, 1.0f, 500.0f, 1.0f);
|
|
bank.AddSlider("Proximity Max Probe Dist", &g_ProximityMaxProbeDistance, 0.0f, 100.f, 0.1f);
|
|
bank.AddSlider("Proximity Min Repeat Time", &g_ProximityWhooshMinRepeatTime, 0, 5000, 10);
|
|
bank.AddSlider("Proximity Ray Cast Forward Offset", &g_ProximityRayCastForwardOffset, 0.0f, 100.0F, 0.1f);
|
|
bank.PushGroup("Stunt Tunnels",false);
|
|
bank.AddSlider("Stunt Tunnel Ray Cast Length", &g_StuntTunnelRayCastLength, 0.0f, 100.0F, 0.1f);
|
|
bank.AddSlider("Stunt Tunnel Probe Hit Timeout", &g_StuntTunnelProbeHitTimeout, 0.0f, 10.0F, 0.1f);
|
|
bank.AddSlider("Stunt Tunnel Ray Cast Forward Offset", &g_StuntTunnelRayCastForwardOffset, 0.0f, 100.0F, 0.1f);
|
|
bank.AddSlider("Stunt Tunnel Min Whoosh Repeat Time", &g_StuntTunnelMinWhooshRepeatTimeMs, 0, 50000, 1000);
|
|
bank.AddSlider("Stunt Boost Intensity Min Increase Time", &g_StuntBoostIntensityIncreaseDelay, 0, 1000, 10);
|
|
bank.AddSlider("Recharge Intensity Min Increase Time", &g_RechargeIntensityIncreaseDelay, 0, 1000, 10);
|
|
bank.AddSlider("Stunt Tunnel Whoosh Exit Min Dist", &g_StuntTunnelMinWhooshExitDistance, 0.f, 1000.f, 1.f);
|
|
bank.PopGroup();
|
|
bank.PopGroup();
|
|
bank.PopGroup();
|
|
}
|
|
#endif
|
|
|