qboolean snd_usethreadedmixing = false;
vec3_t listener_origin;
+static unsigned char *listener_pvs = NULL;
+static int listener_pvsbytes = 0;
matrix4x4_t listener_matrix[SND_LISTENERS];
mempool_t *snd_mempool;
cvar_t snd_spatialization_max = {CVAR_SAVE, "snd_spatialization_max", "0.95", "maximum spatialization of sounds"};
cvar_t snd_spatialization_power = {CVAR_SAVE, "snd_spatialization_power", "0", "exponent of the spatialization falloff curve (0: logarithmic)"};
cvar_t snd_spatialization_control = {CVAR_SAVE, "snd_spatialization_control", "0", "enable spatialization control (headphone friendly mode)"};
-cvar_t snd_spatialization_occlusion = {CVAR_SAVE, "snd_spatialization_occlusion", "1", "enable occlusion testing on spatialized sounds, which simply quiets sounds that are blocked by the world"};
+cvar_t snd_spatialization_occlusion = {CVAR_SAVE, "snd_spatialization_occlusion", "1", "enable occlusion testing on spatialized sounds, which simply quiets sounds that are blocked by the world; 1 enables PVS method, 2 enables LineOfSight method, 3 enables both"};
// Cvars declared in snd_main.h (shared with other snd_*.c files)
cvar_t _snd_mixahead = {CVAR_SAVE, "_snd_mixahead", "0.15", "how much sound to mix ahead of time"};
if (snd_spatialization_occlusion.integer)
{
- if (cl.worldmodel
- && cl.worldmodel->brush.TraceLineOfSight
- && !cl.worldmodel->brush.TraceLineOfSight(cl.worldmodel, listener_origin, ch->origin))
+ qboolean occluded = false;
+
+ if(snd_spatialization_occlusion.integer & 1)
+ if(listener_pvs)
{
- vol *= 0.5f;
+ int cluster = cl.worldmodel->brush.PointInLeaf(cl.worldmodel, ch->origin)->clusterindex;
+ if(cluster >= 0 && cluster < 8 * listener_pvsbytes && !CHECKPVSBIT(listener_pvs, cluster))
+ occluded = true;
+ }
+
+ if(snd_spatialization_occlusion.integer & 2)
+ if(!occluded)
+ if(cl.worldmodel && cl.worldmodel->brush.TraceLineOfSight && !cl.worldmodel->brush.TraceLineOfSight(cl.worldmodel, listener_origin, ch->origin))
+ {
+ occluded = true;
}
+
+ if(occluded)
+ vol *= 0.5f;
}
ch->listener_volume[i] = (int)bound(0, vol, 255);
Matrix4x4_Invert_Simple(&basematrix, listenermatrix);
Matrix4x4_OriginFromMatrix(listenermatrix, listener_origin);
+ if (cl.worldmodel && cl.worldmodel->brush.FatPVS && cl.worldmodel->brush.num_pvsclusterbytes && cl.worldmodel->brush.PointInLeaf)
+ {
+ if(cl.worldmodel->brush.num_pvsclusterbytes != listener_pvsbytes)
+ {
+ if(listener_pvs)
+ Mem_Free(listener_pvs);
+ listener_pvsbytes = cl.worldmodel->brush.num_pvsclusterbytes;
+ listener_pvs = Mem_Alloc(snd_mempool, listener_pvsbytes);
+ }
+ cl.worldmodel->brush.FatPVS(cl.worldmodel, listener_origin, 2, listener_pvs, listener_pvsbytes, 0);
+ }
+ else
+ {
+ if(listener_pvs)
+ {
+ Mem_Free(listener_pvs);
+ listener_pvs = NULL;
+ }
+ listener_pvsbytes = 0;
+ }
// calculate the current matrices
for (j = 0;j < SND_LISTENERS;j++)