From 04f40ebdba4aa807edadcbdd3d91d0567dd2e700 Mon Sep 17 00:00:00 2001 From: Drombeys Date: Wed, 13 Dec 2023 23:38:44 +0300 Subject: [PATCH] Backport `IGame_Level::SoundEvent` methods from IX-Ray 1.6 --- src/xr_3da/IGame_Level.cpp | 128 ++++++++++++++++++++++- src/xr_3da/IGame_Level.h | 11 +- src/xr_3da/xrGame/CustomMonster.cpp | 6 ++ src/xr_3da/xr_area.cpp | 151 +++++++++------------------- src/xr_3da/xr_area.h | 9 +- 5 files changed, 189 insertions(+), 116 deletions(-) diff --git a/src/xr_3da/IGame_Level.cpp b/src/xr_3da/IGame_Level.cpp index 856d6bee..1b62d1d1 100644 --- a/src/xr_3da/IGame_Level.cpp +++ b/src/xr_3da/IGame_Level.cpp @@ -9,8 +9,11 @@ #include "gamefont.h" #include "xrLevel.h" #include "CameraManager.h" +#include "xr_object.h" +#include "feel_sound.h" ENGINE_API IGame_Level* g_pGameLevel = NULL; +extern BOOL g_bLoaded; IGame_Level::IGame_Level () { @@ -39,6 +42,9 @@ IGame_Level::~IGame_Level () Device.seqRender.Remove (this); Device.seqFrame.Remove (this); CCameraManager::ResetPP (); + + Sound->set_geometry_occ(NULL); + Sound->set_handler(NULL); } void IGame_Level::net_Stop () @@ -53,7 +59,14 @@ void IGame_Level::net_Stop () } //------------------------------------------------------------------------------------------- -extern CStatTimer tscreate; +void __stdcall _sound_event (ref_sound_data_ptr S, float range) +{ + if ( g_pGameLevel && S && S->feedback ) g_pGameLevel->SoundEvent_Register (S,range); +} +static void __stdcall build_callback (Fvector* V, int Vcnt, CDB::TRI* T, int Tcnt, void* params) +{ + g_pGameLevel->Load_GameSpecific_CFORM( T, Tcnt ); +} BOOL IGame_Level::Load (u32 dwNum) { @@ -76,7 +89,10 @@ BOOL IGame_Level::Load (u32 dwNum) // CForms g_pGamePersistent->LoadTitle ("st_loading_cform"); - ObjectSpace.Load (); + ObjectSpace.Load(build_callback); + //Sound->set_geometry_occ ( &Static ); + Sound->set_geometry_occ (ObjectSpace.GetStaticModel ()); + Sound->set_handler ( _sound_event ); pApp->LoadSwitch (); @@ -89,7 +105,6 @@ BOOL IGame_Level::Load (u32 dwNum) // Render-level Load Render->level_Load (LL_Stream); - tscreate.FrameEnd (); // Msg ("* S-CREATE: %f ms, %d times",tscreate.result,tscreate.count); // Objects @@ -180,3 +195,110 @@ void CServerInfo::AddItem( shared_str& name_, LPCSTR value_, u32 color_ ) data.push_back( it ); } } + +void IGame_Level::SetEntity( CObject* O ) +{ + pCurrentEntity=pCurrentViewEntity=O; +} + +void IGame_Level::SetViewEntity( CObject* O ) +{ + pCurrentViewEntity=O; +} + +void IGame_Level::SoundEvent_Register ( ref_sound_data_ptr S, float range ) +{ + if (!g_bLoaded) return; + if (!S) return; + if (S->g_object && S->g_object->getDestroy()) {S->g_object=0; return;} + if (0==S->feedback) return; + + clamp (range,0.1f,500.f); + + const CSound_params* p = S->feedback->get_params(); + Fvector snd_position = p->position; + if(S->feedback->is_2D()){ + snd_position.add (Sound->listener_position()); + } + + VERIFY (p && _valid(range) ); + range = _min(range,p->max_ai_distance); + VERIFY (_valid(snd_position)); + VERIFY (_valid(p->max_ai_distance)); + VERIFY (_valid(p->volume)); + + // Query objects + Fvector bb_size = {range,range,range}; + g_SpatialSpace->q_box (snd_ER,0,STYPE_REACTTOSOUND,snd_position,bb_size); + + // Iterate + xr_vector::iterator it = snd_ER.begin (); + xr_vector::iterator end = snd_ER.end (); + for (; it!=end; it++) { + Feel::Sound* L = (*it)->dcast_FeelSound (); + if (0==L) continue; + CObject* CO = (*it)->dcast_CObject(); VERIFY(CO); + if (CO->getDestroy()) continue; + + // Energy and signal + VERIFY (_valid((*it)->spatial.sphere.P)); + float dist = snd_position.distance_to((*it)->spatial.sphere.P); + if (dist>p->max_ai_distance) continue; + VERIFY (_valid(dist)); + VERIFY2 (!fis_zero(p->max_ai_distance), S->handle->file_name()); + float Power = (1.f-dist/p->max_ai_distance)*p->volume; + VERIFY (_valid(Power)); + if (Power>EPS_S) { + float occ = Sound->get_occlusion_to((*it)->spatial.sphere.P,snd_position); + VERIFY (_valid(occ)) ; + Power *= occ; + if (Power>EPS_S) { + _esound_delegate D = { L, S, Power }; + snd_Events.push_back (D) ; + } + } + } + snd_ER.clear(); +} + +void IGame_Level::SoundEvent_Dispatch ( ) +{ + while (!snd_Events.empty()) { + _esound_delegate& D = snd_Events.back (); + VERIFY (D.dest && D.source); + if (D.source->feedback) { + D.dest->feel_sound_new ( + D.source->g_object, + D.source->g_type, + D.source->g_userdata, + + D.source->feedback->is_2D() ? Device.vCameraPosition : + D.source->feedback->get_params()->position, + D.power + ); + } + snd_Events.pop_back (); + } +} + +// Lain: added +void IGame_Level::SoundEvent_OnDestDestroy (Feel::Sound* obj) +{ + struct rem_pred + { + rem_pred(Feel::Sound* obj) : m_obj(obj) {} + + bool operator () (const _esound_delegate& d) + { + return d.dest == m_obj; + } + + private: + Feel::Sound* m_obj; + }; + + snd_Events.erase( std::remove_if(snd_Events.begin(), snd_Events.end(), rem_pred(obj)), + snd_Events.end() ); +} + + diff --git a/src/xr_3da/IGame_Level.h b/src/xr_3da/IGame_Level.h index c0ff9877..fde354cc 100644 --- a/src/xr_3da/IGame_Level.h +++ b/src/xr_3da/IGame_Level.h @@ -1,7 +1,6 @@ #pragma once #include "iinputreceiver.h" -//#include "CameraManager.h" #include "xr_object_list.h" #include "xr_area.h" @@ -32,11 +31,10 @@ class ENGINE_API CServerInfo IC SItem_ServerInfo& operator[] ( u32 id ) { VERIFY( id < max_item ); return data[id]; } - //CServerInfo() {}; - //~CServerInfo() {}; + CServerInfo() {}; + ~CServerInfo() {}; }; - //----------------------------------------------------------------------------------------------------------- class ENGINE_API IGame_Level : public DLL_Pure, @@ -99,11 +97,12 @@ class ENGINE_API IGame_Level : // Main interface CObject* CurrentEntity ( void ) const { return pCurrentEntity; } CObject* CurrentViewEntity ( void ) const { return pCurrentViewEntity; } - void SetEntity ( CObject* O ) { pCurrentEntity=pCurrentViewEntity=O; } - void SetViewEntity ( CObject* O ) { pCurrentViewEntity=O; } + void SetEntity ( CObject* O );// { pCurrentEntity=pCurrentViewEntity=O; } + void SetViewEntity ( CObject* O );// { pCurrentViewEntity=O; } void SoundEvent_Register ( ref_sound_data_ptr S, float range ); void SoundEvent_Dispatch ( ); + void SoundEvent_OnDestDestroy (Feel::Sound*); // Loader interface ref_shader LL_CreateShader (int S, int T, int M, int C); diff --git a/src/xr_3da/xrGame/CustomMonster.cpp b/src/xr_3da/xrGame/CustomMonster.cpp index b098b0dd..cdd81000 100644 --- a/src/xr_3da/xrGame/CustomMonster.cpp +++ b/src/xr_3da/xrGame/CustomMonster.cpp @@ -96,6 +96,12 @@ CCustomMonster::~CCustomMonster () xr_delete (m_movement_manager); xr_delete (m_sound_player); + // Lain: added (asking GameLevel to forget about self) + if (g_pGameLevel) + { + g_pGameLevel->SoundEvent_OnDestDestroy(this); + } + #ifdef DEBUG Msg ("dumping client spawn manager stuff for object with id %d",ID()); if(!g_dedicated_server) diff --git a/src/xr_3da/xr_area.cpp b/src/xr_3da/xr_area.cpp index e05c8668..ebc339ad 100644 --- a/src/xr_3da/xr_area.cpp +++ b/src/xr_3da/xr_area.cpp @@ -1,95 +1,12 @@ #include "stdafx.h" -#include "igame_level.h" #include "xr_area.h" #include "xr_object.h" #include "xrLevel.h" -#include "feel_sound.h" -#include "x_ray.h" -#include "GameFont.h" +#include "xr_collide_form.h" using namespace collide; -extern BOOL g_bLoaded; - -void IGame_Level::SoundEvent_Register ( ref_sound_data_ptr S, float range ) -{ - if (!g_bLoaded) return; - if (!S) return; - if (S->g_object && S->g_object->getDestroy()) {S->g_object=0; return;} - if (0==S->feedback) return; - - clamp (range,0.1f,500.f); - - const CSound_params* p = S->feedback->get_params(); - Fvector snd_position = p->position; - if(S->feedback->is_2D()){ - snd_position.add (Sound->listener_position()); - } - - VERIFY (p && _valid(range) ); - range = _min(range,p->max_ai_distance); - VERIFY (_valid(snd_position)); - VERIFY (_valid(p->max_ai_distance)); - VERIFY (_valid(p->volume)); - - // Query objects - Fvector bb_size = {range,range,range}; - g_SpatialSpace->q_box (snd_ER,0,STYPE_REACTTOSOUND,snd_position,bb_size); - - // Iterate - xr_vector::iterator it = snd_ER.begin (); - xr_vector::iterator end = snd_ER.end (); - for (; it!=end; it++) { - Feel::Sound* L = (*it)->dcast_FeelSound (); - if (0==L) continue; - CObject* CO = (*it)->dcast_CObject(); VERIFY(CO); - if (CO->getDestroy()) continue; - - // Energy and signal - VERIFY (_valid((*it)->spatial.sphere.P)); - float dist = snd_position.distance_to((*it)->spatial.sphere.P); - if (dist>p->max_ai_distance) continue; - VERIFY (_valid(dist)); - VERIFY2 (!fis_zero(p->max_ai_distance), S->handle->file_name()); - float Power = (1.f-dist/p->max_ai_distance)*p->volume; - VERIFY (_valid(Power)); - if (Power>EPS_S) { - float occ = Sound->get_occlusion_to((*it)->spatial.sphere.P,snd_position); - VERIFY (_valid(occ)) ; - Power *= occ; - if (Power>EPS_S) { - _esound_delegate D = { L, S, Power }; - snd_Events.push_back (D) ; - } - } - } - snd_ER.clear(); -} - -void IGame_Level::SoundEvent_Dispatch ( ) -{ - while (!snd_Events.empty()) { - _esound_delegate& D = snd_Events.back (); - VERIFY (D.dest && D.source); - if (D.source->feedback) { - D.dest->feel_sound_new ( - D.source->g_object, - D.source->g_type, - D.source->g_userdata, - D.source->feedback->get_params()->position, - D.power - ); - } - snd_Events.pop_back (); - } -} - -void __stdcall _sound_event (ref_sound_data_ptr S, float range) -{ - if ( g_pGameLevel && S && S->feedback ) g_pGameLevel->SoundEvent_Register (S,range); -} - //---------------------------------------------------------------------- // Class : CObjectSpace // Purpose : stores space slots @@ -107,8 +24,6 @@ CObjectSpace::CObjectSpace ( ) //---------------------------------------------------------------------- CObjectSpace::~CObjectSpace ( ) { - Sound->set_geometry_occ (NULL); - Sound->set_handler (NULL); #ifdef DEBUG sh_debug.destroy (); #endif @@ -142,31 +57,55 @@ IC int CObjectSpace::GetNearest( xr_vector& q_nearest, ICollisionFor return GetNearest( q_nearest, O->spatial.sphere.P, range + O->spatial.sphere.R, O ); } -//---------------------------------------------------------------------- -static void __stdcall build_callback (Fvector* V, int Vcnt, CDB::TRI* T, int Tcnt, void* params) -{ - g_pGameLevel->Load_GameSpecific_CFORM( T, Tcnt ); +void CObjectSpace::Load(CDB::build_callback build_callback) { + Load("$level$", "level.cform", build_callback); } -void CObjectSpace::Load () -{ - IReader *F = FS.r_open ("$level$", "level.cform"); - R_ASSERT (F); - hdrCFORM H; - F->r (&H,sizeof(hdrCFORM)); - Fvector* verts = (Fvector*)F->pointer(); - CDB::TRI* tris = (CDB::TRI*)(verts+H.vertcount); - R_ASSERT (CFORM_CURRENT_VERSION==H.version); - Static.build ( verts, H.vertcount, tris, H.facecount, build_callback ); +void CObjectSpace::Load(LPCSTR path, LPCSTR fname, CDB::build_callback build_callback) { +#ifdef USE_ARENA_ALLOCATOR + Msg("CObjectSpace::Load, g_collision_allocator.get_allocated_size() - %d", int(g_collision_allocator.get_allocated_size() / 1024.0 / 1024)); +#endif // #ifdef USE_ARENA_ALLOCATOR + IReader* F = FS.r_open(path, fname); + R_ASSERT(F); + Load(F, build_callback); +} - m_BoundingVolume.set (H.aabb); - g_SpatialSpace->initialize (H.aabb); - g_SpatialSpacePhysic->initialize (H.aabb); - Sound->set_geometry_occ ( &Static ); - Sound->set_handler ( _sound_event ); +void CObjectSpace::Load(IReader* F, CDB::build_callback build_callback) { + hdrCFORM H; + F->r(&H, sizeof(hdrCFORM)); + Fvector* verts = (Fvector*)F->pointer(); + CDB::TRI* tris = (CDB::TRI*)(verts + H.vertcount); + Create(verts, tris, H, build_callback); + FS.r_close(F); +} - FS.r_close (F); + +void CObjectSpace::Create(Fvector* verts, CDB::TRI* tris, const hdrCFORM& H, CDB::build_callback build_callback) { + R_ASSERT(CFORM_CURRENT_VERSION == H.version); + Static.build(verts, H.vertcount, tris, H.facecount, build_callback); + m_BoundingVolume.set(H.aabb); + g_SpatialSpace->initialize(m_BoundingVolume); + g_SpatialSpacePhysic->initialize(m_BoundingVolume); } + + +//void CObjectSpace::Load () +//{ +// IReader *F = FS.r_open ("$level$", "level.cform"); +// R_ASSERT (F); +// +// hdrCFORM H; +// F->r (&H,sizeof(hdrCFORM)); +// Fvector* verts = (Fvector*)F->pointer(); +// CDB::TRI* tris = (CDB::TRI*)(verts+H.vertcount); +// R_ASSERT (CFORM_CURRENT_VERSION==H.version); +// Static.build ( verts, H.vertcount, tris, H.facecount, build_callback ); +// +// m_BoundingVolume.set (H.aabb); +// g_SpatialSpace->initialize (m_BoundingVolume); +// g_SpatialSpacePhysic->initialize (m_BoundingVolume); +// FS.r_close (F); +//} //---------------------------------------------------------------------- #ifdef DEBUG void CObjectSpace::dbgRender() diff --git a/src/xr_3da/xr_area.h b/src/xr_3da/xr_area.h index 639908d0..3c532642 100644 --- a/src/xr_3da/xr_area.h +++ b/src/xr_3da/xr_area.h @@ -9,9 +9,13 @@ class ENGINE_API ISpatial; class ENGINE_API ICollisionForm; class ENGINE_API CObject; +#include "../xrCDB/xrXRC.h" +#include "../xrCDB/xrcdb.h" + //----------------------------------------------------------------------------------------------------------- //Space Area //----------------------------------------------------------------------------------------------------------- +struct hdrCFORM; class ENGINE_API CObjectSpace { private: @@ -40,7 +44,10 @@ class ENGINE_API CObjectSpace CObjectSpace ( ); ~CObjectSpace ( ); - void Load ( ); + void Load(CDB::build_callback build_callback); + void Load(LPCSTR path, LPCSTR fname, CDB::build_callback build_callback); + void Load(IReader* R, CDB::build_callback build_callback); + void Create(Fvector* verts, CDB::TRI* tris, const hdrCFORM& H, CDB::build_callback build_callback); // Occluded/No BOOL RayTest ( const Fvector &start, const Fvector &dir, float range, collide::rq_target tgt, collide::ray_cache* cache, CObject* ignore_object);