]> de.git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
sound occlusion: use PVS by default, make the cvar able to toggle between PVS and...
authordivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 9 Sep 2010 06:54:58 +0000 (06:54 +0000)
committerdivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 9 Sep 2010 06:54:58 +0000 (06:54 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@10449 d7cf8633-e32d-0410-b094-e92efae38249

snd_main.c

index 52dde53fa4c3df6045de3dd82eb68d56f2cfbb91..b9fe66027f69fed7fbd63c894e6088916e1e965b 100644 (file)
@@ -134,6 +134,8 @@ qboolean snd_threaded = false;
 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;
 
@@ -168,7 +170,7 @@ cvar_t snd_spatialization_min = {CVAR_SAVE, "snd_spatialization_min", "0.70", "m
 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"};
@@ -1406,12 +1408,25 @@ void SND_Spatialize(channel_t *ch, qboolean isstatic)
 
                                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);
@@ -1995,6 +2010,26 @@ void S_Update(const matrix4x4_t *listenermatrix)
 
        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++)