From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/a02363.html | 2206 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2206 insertions(+) create mode 100644 docs/doxygen/nel/a02363.html (limited to 'docs/doxygen/nel/a02363.html') diff --git a/docs/doxygen/nel/a02363.html b/docs/doxygen/nel/a02363.html new file mode 100644 index 00000000..79d8a918 --- /dev/null +++ b/docs/doxygen/nel/a02363.html @@ -0,0 +1,2206 @@ + + +NeL: NLSOUND::CClusteredSound class Reference + + + +
+

NLSOUND::CClusteredSound Class Reference

#include <clustered_sound.h> +

+


Detailed Description

+This class will manage the clipping/positioning/occlusion of sound placed inside the cluster/portal system.

+

Author:
Boris Boucher

+Nevrax France

+
Date:
2002
+ +

+ +

+Definition at line 58 of file clustered_sound.h. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

typedef std::map< NL3D::CCluster *,
+ CClusterSoundStatus
TClusterStatusMap
 Container for audible cluster status.

typedef std::map< NL3D::CCluster *,
+ CSoundTravContext
TClusterTravContextMap
 Container for the next traversal step.


Public Member Functions

 CClusteredSound ()
 Constructor.

const TClusterStatusMapgetAudibleClusters ()
const std::vector< std::pair<
+ NLMISC::CVector, NLMISC::CVector > > & 
getAudioPath ()
const CClusterSoundStatusgetClusterSoundStatus (NL3D::CCluster *cluster)
NL3D::CClustergetRootCluster ()
void init (NL3D::CScene *scene, float portalInterpolate, float maxEarDistance, float minGain)
void update (const NLMISC::CVector &listenerPos, const NLMISC::CVector &view, const NLMISC::CVector &up)

Private Member Functions

bool addAudibleCluster (NL3D::CCluster *cluster, CClusterSoundStatus &soundStatus)
 Add a cluster into the list of audible cluster.

void addNextTraverse (NL3D::CCluster *cluster, CSoundTravContext &travContext)
 Add a cluster for the next traversal step.

NLMISC::CVector interpolateSourceDirection (const CSoundTravContext &context, float portalDist, const NLMISC::CVector &nearPoint, const NLMISC::CVector &realListener, NLMISC::CVector &d1, NLMISC::CVector &d2, float &alpha)
 Compute a positional blending depending on context.

void soundTraverse (const std::vector< NL3D::CCluster * > &clusters, CSoundTravContext &travContext)
 Traverse the cluster system to build/update the audible cluster set and theire respective status.

float getAABoxNearestPos (const NLMISC::CAABBox &box, const NLMISC::CVector &pos, NLMISC::CVector &nearPos)
float getPolyNearestPos (const std::vector< NLMISC::CVector > &poly, const NLMISC::CVector &pos, NLMISC::CVector &nearPoint)

Private Attributes

TClusterStatusMap _AudibleClusters
 The current audible cluster.

std::vector< std::pair< NLMISC::CVector,
+ NLMISC::CVector > > 
_AudioPath
 The segment of all the audio path.

std::hash_map< NLMISC::TStringId,
+ uint
_IdToEaxEnv
 The mapping for env name Id to EAX environement number.

std::hash_map< NLMISC::TStringId,
+ uint
_IdToMaterial
 The mapping for occlusion material name to material number.

uint _LastEnv
 The last setted environement.

float _MaxEarDistance
 Maximum earing distance.

float _MinGain
 Minimum gain.

TClusterTravContextMap _NextTraversalStep
 The cluster for the next travesal step.

float _PortalInterpolate
 Interpolation distance when listener is near a portal.

NL3D::CCluster_RootCluster
 The root cluster of the scene.

NL3D::CScene_Scene
 The scene of interest.

std::hash_map< NLMISC::TStringId,
+ NLMISC::TStringId
_SoundGroupToSound
 The sound_group to sound assoc.

std::hash_map< NLMISC::TStringId,
+ CClusterSound
_Sources
 The current cluster playing source indexed with sound group id.


Static Private Attributes

char * _EnvironmentNames []
 The environment name table for init.

char * _MaterialNames []
 The material name table for init.

+


Member Typedef Documentation

+

+ + + + +
+ + +
typedef std::map<NL3D::CCluster*, CClusterSoundStatus> NLSOUND::CClusteredSound::TClusterStatusMap +
+
+ + + + + +
+   + + +

+Container for audible cluster status. +

+ +

+Definition at line 87 of file clustered_sound.h. +

+Referenced by getAudibleClusters().

+

+ + + + +
+ + +
typedef std::map<NL3D::CCluster*, CSoundTravContext> NLSOUND::CClusteredSound::TClusterTravContextMap +
+
+ + + + + +
+   + + +

+Container for the next traversal step. +

+ +

+Definition at line 175 of file clustered_sound.h.

+


Constructor & Destructor Documentation

+

+ + + + +
+ + + + + + + + + +
NLSOUND::CClusteredSound::CClusteredSound  ) 
+
+ + + + + +
+   + + +

+Constructor. +

+ +

+Definition at line 222 of file clustered_sound.cpp. +

+References _EnvironmentNames, _IdToEaxEnv, _IdToMaterial, _MaterialNames, and uint. +

+

00223 :       _Scene(0),
+00224         _RootCluster(0),
+00225         _LastEnv(0xffffffff)
+00226 {
+00227         // fill the env name table
+00228         uint i;
+00229         for (i=0; _EnvironmentNames[i] != 0; ++i)
+00230         {
+00231                 _IdToEaxEnv.insert(make_pair(CStringMapper::map(string(_EnvironmentNames[i])), i));
+00232         }
+00233         // fill the material name table
+00234         for (i=0; _MaterialNames[i] != 0; ++i)
+00235         {
+00236                 _IdToMaterial.insert(make_pair(CStringMapper::map(string(_MaterialNames[i])), i));
+00237         }
+00238 
+00239 }
+
+


Member Function Documentation

+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
bool NLSOUND::CClusteredSound::addAudibleCluster NL3D::CCluster cluster,
CClusterSoundStatus soundStatus
[private]
+
+ + + + + +
+   + + +

+Add a cluster into the list of audible cluster. +

+ +

+Definition at line 957 of file clustered_sound.cpp. +

+References _AudibleClusters, _MaxEarDistance, NLSOUND::CClusteredSound::CClusterSoundStatus::Direction, NLSOUND::CClusteredSound::CClusterSoundStatus::Dist, nlassert, and NLMISC::CVector::norm(). +

+Referenced by soundTraverse(). +

+

00958 {
+00959         TClusterStatusMap::iterator it(_AudibleClusters.find(cluster));
+00960         nlassert(soundStatus.Dist < _MaxEarDistance);
+00961         nlassert(soundStatus.Direction.norm() <= 1.01f);
+00962 
+00963         if (it != _AudibleClusters.end())
+00964         {
+00965                 // get the best one (for now, based on shortest distance)
+00966                 if (soundStatus.Dist < it->second.Dist)
+00967                 {
+00968                         it->second = soundStatus;
+00969 
+00970                         return true;
+00971                 }
+00972         }
+00973         else
+00974         {
+00975                 _AudibleClusters.insert(make_pair(cluster, soundStatus));
+00976                 return true;
+00977         }
+00978 
+00979         return false;
+00980 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
void NLSOUND::CClusteredSound::addNextTraverse NL3D::CCluster cluster,
CSoundTravContext travContext
[private]
+
+ + + + + +
+   + + +

+Add a cluster for the next traversal step. +

+ +

+Definition at line 941 of file clustered_sound.cpp. +

+References _NextTraversalStep, and NLSOUND::CClusteredSound::CSoundTravContext::Dist. +

+Referenced by soundTraverse(). +

+

00942 {
+00943         std::map<CCluster*, CSoundTravContext>::iterator it = _NextTraversalStep.find(cluster);
+00944 
+00945         if (it != _NextTraversalStep.end())
+00946         {
+00947                 if (it->second.Dist > travContext.Dist)
+00948                 {
+00949                         it->second = travContext;
+00950                 }
+00951         }
+00952         else
+00953                 _NextTraversalStep.insert(make_pair(cluster, travContext));
+00954 
+00955 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
float NLSOUND::CClusteredSound::getAABoxNearestPos const NLMISC::CAABBox box,
const NLMISC::CVector pos,
NLMISC::CVector nearPos
[private]
+
+ + + + + +
+   + + +

+Compute the point in the bounding box that is the nearest from a given position. This point can be in the volume of the box, on a segment of one of the vertex. In addition, the method also return the distance from the nearest point to the reference position.

Parameters:
+ + + + +
poly The bounding box description.
pos The reference position.
nearPoint The nearest point (out var).
+
+
Returns:
The distance between pos and nearPoint.
+ +

+Definition at line 1155 of file clustered_sound.cpp. +

+References NLMISC::clamp(), NLMISC::CAABBox::getMax(), NLMISC::CAABBox::getMin(), NLMISC::CVector::x, NLMISC::CVector::y, and NLMISC::CVector::z. +

+Referenced by soundTraverse(). +

+

01156 {
+01157         CVector vMin, vMax;
+01158         box.getMin(vMin);
+01159         box.getMax(vMax);
+01160 
+01161 
+01162         nearPos = pos;
+01163         // X
+01164         clamp(nearPos.x, vMin.x, vMax.x);
+01165         // Y
+01166         clamp(nearPos.y, vMin.y, vMax.y);
+01167         // Z
+01168         clamp(nearPos.z, vMin.z, vMax.z);
+01169 
+01170         return (pos-nearPos).norm();
+01171 }
+
+

+ + + + +
+ + + + + + + + + +
const TClusterStatusMap& NLSOUND::CClusteredSound::getAudibleClusters  )  [inline]
+
+ + + + + +
+   + + +

+ +

+Definition at line 198 of file clustered_sound.h. +

+References _AudibleClusters, and TClusterStatusMap. +

+

00198 {return _AudibleClusters;}
+
+

+ + + + +
+ + + + + + + + + +
const std::vector<std::pair<NLMISC::CVector, NLMISC::CVector> >& NLSOUND::CClusteredSound::getAudioPath  )  [inline]
+
+ + + + + +
+   + + +

+ +

+Definition at line 200 of file clustered_sound.h. +

+References _AudioPath. +

+

00200 { return _AudioPath;}
+
+

+ + + + +
+ + + + + + + + + + +
const CClusteredSound::CClusterSoundStatus * NLSOUND::CClusteredSound::getClusterSoundStatus NL3D::CCluster cluster  ) 
+
+ + + + + +
+   + + +

+ +

+Definition at line 459 of file clustered_sound.cpp. +

+References _AudibleClusters. +

+Referenced by NLSOUND::CAudioMixerUser::update(), and NLSOUND::CBackgroundSoundManager::updateBackgroundStatus(). +

+

00460 {
+00461         TClusterStatusMap::iterator it(_AudibleClusters.find(cluster));
+00462 
+00463         if (it == _AudibleClusters.end())
+00464         {
+00465                 return 0;
+00466         }
+00467         else
+00468                 return &(it->second);
+00469 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
float NLSOUND::CClusteredSound::getPolyNearestPos const std::vector< NLMISC::CVector > &  poly,
const NLMISC::CVector pos,
NLMISC::CVector nearPoint
[private]
+
+ + + + + +
+   + + +

+Compute the point on the poly that is the nearest from a given position. This point can be on the surface of the poly, on a segment or on one of the vertex. In addition, the method also return the distance from the nearest point to the reference position.

Parameters:
+ + + + +
poly The polygone description.
pos The reference position.
nearPoint The nearest point (out var).
+
+
Returns:
The distance between pos and nearPoint.
+ +

+Definition at line 1098 of file clustered_sound.cpp. +

+References NLMISC::CPlane::getNormal(), NLMISC::CPlane::make(), NLMISC::CVector::norm(), NLMISC::CPlane::project(), NLMISC::CVector::sqrnorm(), and uint. +

+Referenced by soundTraverse(). +

+

01099 {
+01100         CPlane plane;
+01101         plane.make(poly[0], poly[1], poly[2]);
+01102         CVector proj = plane.project(pos);
+01103         float   minDist = FLT_MAX;
+01104         bool    projIn = true;
+01105         uint    nbVertex = poly.size();
+01106 
+01107         // loop throw all vertex
+01108         for (uint j=0; j<nbVertex; ++j)
+01109         {
+01110                 float d = (pos-poly[j]).sqrnorm();
+01111                 // check if the vertex is the nearest point
+01112                 if (d < minDist)
+01113                 {
+01114                         nearPoint = poly[j];
+01115                         minDist = d;
+01116                 }
+01117 //              if (projIn /*&& j<poly.size()-1*/)
+01118                 {
+01119                         // check each segment
+01120                         if (plane.getNormal()*((poly[(j+1)%nbVertex] - poly[j]) ^ (proj - poly[j])) < 0)
+01121                         {
+01122                                 // the point is not inside the poly surface !
+01123                                 projIn = false;
+01124                                 // check if the nearest point is on this segment
+01125                                 CVector v1 = (poly[(j+1)%nbVertex] - poly[j]);
+01126                                 float v1Len = v1.norm();
+01127                                 v1 = v1 / v1Len;
+01128                                 CVector v2 = proj - poly[j];
+01129                                 // project v2 on v1
+01130                                 float p = v1 * v2;
+01131                                 if (p>=0 && p<=v1Len)
+01132                                 {
+01133                                         // the nearest point is on the segment! 
+01134                                         nearPoint = poly[j] + v1 * p;
+01135                                         minDist = (nearPoint-pos).sqrnorm();
+01136                                         break;
+01137                                 }
+01138                         }
+01139                 }
+01140         }
+01141         if (projIn)
+01142         {
+01143                 float d = (proj-pos).sqrnorm();
+01144                 if (d < minDist)
+01145                 {
+01146                         // the nearest point is on the surface
+01147                         nearPoint = proj;
+01148                         minDist = d;
+01149                 }
+01150         }
+01151         
+01152         return sqrtf(minDist);
+01153 }
+
+

+ + + + +
+ + + + + + + + + +
NL3D::CCluster * NLSOUND::CClusteredSound::getRootCluster  ) 
+
+ + + + + +
+   + + +

+ +

+Definition at line 472 of file clustered_sound.cpp. +

+References NL3D::CScene::getClipTrav(). +

+Referenced by NLSOUND::CBackgroundSoundManager::updateBackgroundStatus(). +

+

00473 {
+00474         if (_Scene == 0)
+00475                 return 0;
+00476 
+00477         return _Scene->getClipTrav().RootCluster;
+00478 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void NLSOUND::CClusteredSound::init NL3D::CScene scene,
float  portalInterpolate,
float  maxEarDistance,
float  minGain
+
+ + + + + +
+   + + +

+Initialize the class

Parameters:
+ + + + + +
scene The scene of interest for cluster management.
portalInterpolate Ditance from listener to portal for interpolation.
maxEarDist The maximum traversal distance to limit graph traversal.
minGain The minimun gain to stop traversal.
+
+ +

+Definition at line 242 of file clustered_sound.cpp. +

+References _MaxEarDistance, _MinGain, _PortalInterpolate, _RootCluster, _SoundGroupToSound, NLSOUND::Container, and NL3D::CScene::getClipTrav(). +

+Referenced by NLSOUND::CAudioMixerUser::initClusteredSound(). +

+

00243 {
+00244         // load the sound_group sheets
+00245         ::loadForm("sound_group", CAudioMixerUser::instance()->getPackedSheetPath()+"sound_groups.packed_sheets", Container, CAudioMixerUser::instance()->getPackedSheetUpdate(), false);
+00246 
+00247         // copy the container data into internal structure
+00248         std::map<std::string, CSoundGroupSerializer>::iterator first(Container.begin()), last(Container.end());
+00249         for (; first != last; ++first)
+00250         {
+00251                 _SoundGroupToSound.insert(first->second._SoundGroupAssoc.begin(), first->second._SoundGroupAssoc.end());
+00252         }
+00253         
+00254         // and clear the temporary Container 
+00255         Container.clear();
+00256 
+00257         
+00258         _Scene = scene;
+00259         _PortalInterpolate = portalInterpolate;
+00260         _MaxEarDistance = maxEarDist;
+00261         _MinGain = minGain;
+00262         if(scene != 0)
+00263         {
+00264                 _RootCluster = _Scene->getClipTrav().RootCluster;
+00265         }
+00266         else
+00267                 _RootCluster = 0;
+00268 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CVector NLSOUND::CClusteredSound::interpolateSourceDirection const CSoundTravContext context,
float  portalDist,
const NLMISC::CVector nearPoint,
const NLMISC::CVector realListener,
NLMISC::CVector d1,
NLMISC::CVector d2,
float &  alpha
[private]
+
+ + + + + +
+   + + +

+Compute a positional blending depending on context. +

+ +

+Definition at line 982 of file clustered_sound.cpp. +

+References _PortalInterpolate, alpha, NLSOUND::CClusteredSound::CSoundTravContext::NbPortal, nlassert, NLMISC::CVector::norm(), and NLMISC::CVector::normed(). +

+Referenced by soundTraverse(). +

+

00983 {
+00984         CVector direction;// (context.Direction);
+00985 
+00986         if (portalDist > _PortalInterpolate || alpha >= 1.0f)
+00987         {
+00988                 // the portal is too far, no interpolation.
+00989                 if (context.NbPortal == 0)
+00990                 {
+00991                         // it's the first portal, compute the initial virtual sound direction
+00992                         direction = d1 = (nearPoint-realListener).normed();
+00993                 }
+00994                 else
+00995                 {
+00996                         direction = (nearPoint-realListener).normed();
+00997                         direction = (direction * (1-alpha) + d1 * (alpha)).normed();
+00998                         d1 = direction;
+00999                 }
+01000                 alpha = 1;
+01001         }
+01002         else
+01003         {
+01004                 // the portal is near the listener, interpolate the direction
+01005                 if (context.NbPortal == 0)
+01006                 {
+01007                         // It's the first portal, compute the initial direction
+01008                         alpha = (portalDist / _PortalInterpolate);
+01009 //                      alpha = alpha*alpha*alpha;
+01010                         direction = d1 = (nearPoint-realListener).normed();
+01011                 }
+01012 /*              else if (context.NbPortal == 1)
+01013                 {
+01014                         float factor = (1-alpha);
+01015 //                      factor = factor*factor*factor;
+01016                         direction = (nearPoint-realListener).normed();
+01017                         direction = d1 = (direction * factor + d1 * (1-factor)).normed();
+01018 
+01019 //                      alpha = 1-factor;
+01020                         alpha = factor;
+01021                 }
+01022 */              else 
+01023                 {
+01024                         // two or more portal
+01025                         float factor = (portalDist / _PortalInterpolate) * (1-alpha);
+01026 //                      factor = factor*factor*factor;
+01027                         direction = (nearPoint-realListener).normed();
+01028                         direction = d1 = (direction * factor + d1 * alpha).normed();
+01029 
+01030 //                      alpha = 1-factor;
+01031                         alpha = factor;
+01032                 }
+01033         }
+01034 
+01035         nlassert(direction.norm() <= 1.01f);
+01036         return direction;
+01037 /*
+01038         CVector direction (context.Direction);
+01039         d1 = context.Direction1;
+01040         d2 = context.Direction2;
+01041 
+01042 
+01043         if (portalDist < _PortalInterpolate)
+01044         {
+01045                 if (context.NbPortal == 0)
+01046                 {
+01047                         alpha = (portalDist / _PortalInterpolate);
+01048                         direction = d1 = (nearPoint-realListener).normed() * alpha;
+01049                         direction.normalize();
+01050                 }
+01051                 else if (context.NbPortal == 1)
+01052                 {
+01053                         alpha = alpha * (portalDist / _PortalInterpolate);
+01054 //                      d2 = (nearPoint-realListener).normed() * alpha;
+01055                         d2 = (nearPoint-context.ListenerPos).normed() * (1-alpha);
+01056                         direction = d1 + d2;
+01057                         direction.normalize();
+01058                 }
+01059                 else
+01060                 {
+01061                         alpha = alpha * (portalDist / _PortalInterpolate);
+01062 //                      d1 = d1+d2;
+01063                         d2 = (nearPoint-context.ListenerPos).normed() * (1-alpha);
+01064 //                      direction = d1 + d2 + (nearPoint-context.ListenerPos).normed() * (1-alpha);
+01065                         direction = d1 + d2;
+01066                         direction.normalize();
+01067                 }
+01068         }
+01069         else
+01070         {
+01071 //              alpha = 0.0f
+01072                 if (context.NbPortal == 0)
+01073                 {
+01074                         direction = d1 = (nearPoint-realListener).normed();
+01075                 }
+01076                 else if (context.NbPortal == 1)
+01077                 {
+01078                         d2 = (nearPoint-context.ListenerPos).normed() * (1-alpha);
+01079 //                      d2 = d1; //(nearPoint-context.ListenerPos).normed(); // * (1-alpha);
+01080                         direction = d1+d2;
+01081                         direction.normalize();
+01082                 }
+01083                 else
+01084                 {
+01085 //                      d2 = (nearPoint-context.ListenerPos).normed() * (1-alpha);
+01086                         d1 = d1+d2;
+01087 //                      d2 = (nearPoint-realListener).normed();
+01088 //                      direction = d1+d2+(nearPoint-context.ListenerPos).normed() * (1-alpha);
+01089                         direction.normalize();
+01090                 }
+01091         }
+01092 
+01093         return direction;
+01094 */
+01095 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
void NLSOUND::CClusteredSound::soundTraverse const std::vector< NL3D::CCluster * > &  clusters,
CSoundTravContext travContext
[private]
+
+ + + + + +
+   + + +

+Traverse the cluster system to build/update the audible cluster set and theire respective status. +

+ +

+Definition at line 481 of file clustered_sound.cpp. +

+References _AudibleClusters, _AudioPath, _IdToMaterial, _MaxEarDistance, _MinGain, _NextTraversalStep, _PortalInterpolate, _RootCluster, addAudibleCluster(), addNextTraverse(), NLSOUND::CClusteredSound::CSoundTravContext::Alpha, alpha, NLSOUND::CClusteredSound::CSoundTravContext::Direction, NLSOUND::CClusteredSound::CClusterSoundStatus::Direction, NLSOUND::CClusteredSound::CSoundTravContext::Direction1, NLSOUND::CClusteredSound::CSoundTravContext::Direction2, NLSOUND::CClusteredSound::CSoundTravContext::Dist, NLSOUND::CClusteredSound::CClusterSoundStatus::Dist, NLSOUND::CClusteredSound::CClusterSoundStatus::DistFactor, NLSOUND::EAX_MATERIAL_PARAM, NL3D::CCluster::FatherAudible, NLSOUND::CClusteredSound::CSoundTravContext::FilterUnvisibleChild, NLSOUND::CClusteredSound::CSoundTravContext::FilterUnvisibleFather, NLSOUND::CClusteredSound::CSoundTravContext::Gain, NLSOUND::CClusteredSound::CClusterSoundStatus::Gain, getAABoxNearestPos(), getPolyNearestPos(), H_AUTO, interpolateSourceDirection(), NLSOUND::CClusteredSound::CSoundTravContext::ListenerPos, min, NLSOUND::CClusteredSound::CSoundTravContext::NbPortal, nlassert, nlwarning, NLMISC::CVector::normed(), NLSOUND::CClusteredSound::CSoundTravContext::Obstruction, NLSOUND::CClusteredSound::CClusterSoundStatus::Obstruction, NLSOUND::CClusteredSound::CSoundTravContext::Occlusion, NLSOUND::CClusteredSound::CClusterSoundStatus::Occlusion, NLSOUND::CClusteredSound::CSoundTravContext::OcclusionLFFactor, NLSOUND::CClusteredSound::CClusterSoundStatus::OcclusionLFFactor, NLSOUND::CClusteredSound::CSoundTravContext::OcclusionRoomRatio, NLSOUND::CClusteredSound::CClusterSoundStatus::OcclusionRoomRatio, NLSOUND::CClusteredSound::CClusterSoundStatus::PosAlpha, NLSOUND::CClusteredSound::CClusterSoundStatus::Position, NLSOUND::CClusteredSound::CSoundTravContext::PreviousCluster, NLSOUND::CClusteredSound::CSoundTravContext::PreviousVector, sint32, and uint. +

+Referenced by update(). +

+

00482 {
+00483         H_AUTO(NLSOUND_soundTraverse)
+00484 //      std::map<CCluster*, CSoundTravContext>  nextTraverse;
+00485         std::vector<std::pair<const CCluster*, CSoundTravContext> >     curClusters;
+00486         CVector         realListener (travContext.ListenerPos);
+00487 
+00488         _AudioPath.clear();
+00489 
+00490         // fill the initial cluster liste
+00491         CClusterSoundStatus css;
+00492         css.Direction = CVector::Null;
+00493         css.DistFactor = 0.0f;
+00494         css.Dist = 0.0f;
+00495         css.Gain = 1.0f;
+00496         css.Occlusion = 0;
+00497         css.OcclusionLFFactor = 1.0f;
+00498         css.OcclusionRoomRatio = 1.0f;
+00499         css.Obstruction = 0;
+00500         css.PosAlpha = 0;
+00501 //      css.Position = CVector::Null;
+00502         css.Position = realListener;
+00503 
+00504         for (uint i=0; i<clusters.size(); ++i)
+00505         {
+00506                 bool valid = true;
+00507                 // eliminate cluster when listener is behind their portals AND inside the other cluster
+00508                 for (uint j=0; j<clusters[i]->getNbPortals(); j++)
+00509                 {                               
+00510                         CPortal *portal = clusters[i]->getPortal(j);
+00511                         const std::vector<CVector> &poly = portal->getPoly();
+00512 
+00513                         if (poly.size() < 3)
+00514                         {
+00515                                 // only warn once, avoid log flooding !
+00516                                 static std::set<std::string>    warned;
+00517                                 if (warned.find(clusters[i]->Name) == warned.end())
+00518                                 {
+00519                                         nlwarning("Cluster [%s] contains a portal [%s] with less than 3 vertex !", 
+00520                                                 clusters[i]->Name.c_str(), portal->getName().empty() ? "no name" : portal->getName().c_str());
+00521                                         warned.insert(clusters[i]->Name);
+00522                                 }
+00523                                 valid = false;
+00524                                 continue;
+00525                         }
+00526                         CVector normal = (poly[0] - poly[1]) ^ (poly[2] - poly[1]);
+00527 
+00528                         float dist = (realListener - poly[0]) * normal;
+00529                         float dist2 = (clusters[i]->getBBox().getCenter() - poly[0]) * normal;
+00530 
+00531                         if ((dist < 0 && dist2 > 0) || (dist > 0 && dist2 < 0))
+00532                         {
+00533                                 if (portal->getCluster(0) == clusters[i]) 
+00534                                 {
+00535                                         if (find(clusters.begin(), clusters.end(), portal->getCluster(1)) != clusters.end())
+00536                                         {
+00537                                                 valid = false;
+00538                                                 continue;
+00539                                         }
+00540                                 }
+00541                                 else if (find(clusters.begin(), clusters.end(), portal->getCluster(0)) != clusters.end())
+00542                                 {
+00543                                         valid = false;
+00544                                         continue;
+00545                                 }
+00546 
+00547                         }
+00548 
+00549 /*
+00550                         if (portal->getCluster(0) == clusters[i] && dist > 0)
+00551 //                              if (!portal->isInFront(realListener))
+00552                         {
+00553                                 valid = false;
+00554                                 continue;
+00555                         }
+00556                         else if (portal->getCluster(1) == clusters[i] && dist < 0)
+00557 //                              if (portal->isInFront(realListener))
+00558                         {
+00559                                 valid = false;
+00560                                 continue;
+00561                         }
+00562 */
+00563                 }
+00564                 if( valid)
+00565                 {
+00566                         curClusters.push_back(make_pair(clusters[i], travContext));
+00567                         addAudibleCluster(clusters[i], css);
+00568                 }
+00569         }
+00570 
+00571         do
+00572         {
+00573                 // add the next traverse (if any)
+00574                 std::copy(_NextTraversalStep.begin(), _NextTraversalStep.end(), std::back_inserter(curClusters));
+00575                 _NextTraversalStep.clear();
+00576 
+00577                 while (!curClusters.empty())
+00578                 {
+00579                         CCluster * cluster = const_cast<CCluster*>(curClusters.back().first);
+00580                         CSoundTravContext &travContext = curClusters.back().second;
+00581 
+00582                         CClusterSoundStatus css;
+00583                         css.Gain = travContext.Gain;
+00584                         css.Dist = travContext.Dist;
+00585                         css.Direction = travContext.Direction;
+00586                         css.Occlusion = travContext.Occlusion;
+00587                         css.OcclusionLFFactor = travContext.OcclusionLFFactor;
+00588                         css.OcclusionRoomRatio = travContext.OcclusionRoomRatio;
+00589                         css.Obstruction = travContext.Obstruction;
+00590 
+00591                         // store this cluster and it's parameters
+00592                         _AudibleClusters.insert(make_pair(cluster, css));
+00593 
+00594                         // 1st, look each portal
+00595                         uint i;
+00596                         for (i=0; i<cluster->getNbPortals(); ++i)
+00597                         {
+00598                                 CPortal *portal = cluster->getPortal(i);
+00599                                 // get the other cluster
+00600                                 CCluster *otherCluster = portal->getCluster(0);
+00601                                 bool    clusterInFront = true;
+00602                                 if (otherCluster == cluster)
+00603                                 {
+00604                                         otherCluster = portal->getCluster(1);
+00605                                         clusterInFront = false;
+00606                                 }
+00607                                 nlassert(otherCluster != cluster);
+00608 
+00609                                 if (otherCluster && travContext.PreviousCluster != otherCluster) // && (!travContext.FilterUnvisibleChild || otherCluster->AudibleFromFather))
+00610                                 {
+00611                                         const vector<CVector> &poly = portal->getPoly();
+00612 
+00613                                         // a security test 
+00614                                         if (poly.size() < 3)
+00615                                         {
+00616                                                 // only warn once, avoid log flooding !
+00617                                                 static std::set<std::string>    warned;
+00618                                                 if (warned.find(cluster->Name) == warned.end())
+00619                                                 {
+00620                                                         nlwarning("Cluster [%s] contains a portal [%s] with less than 3 vertex !", 
+00621                                                                 cluster->Name.c_str(), portal->getName().empty() ? "no name" : portal->getName().c_str());
+00622                                                         warned.insert(cluster->Name);
+00623                                                 }
+00624                                         }
+00625                                         else
+00626                                         {
+00627 
+00628                                                 // Test to skip portal with suface > 40 m2 (aprox)
+00629                                                 float surface = ((poly[2]-poly[1]) ^ (poly[0]-poly[1])).norm();
+00630                                                 if (surface > 340 /* && otherCluster->isIn(travContext.ListenerPos, travContext.MaxDist-travContext.Dist)*/)
+00631                                                 {
+00632                                                         float minDist;
+00633                                                         CVector nearPos;
+00634                                                         CAABBox box = otherCluster->getBBox();
+00635 
+00636                                                         minDist = getAABoxNearestPos(box, travContext.ListenerPos, nearPos);
+00637 
+00638                                                         if (travContext.Dist + minDist < _MaxEarDistance)
+00639                                                         {
+00640                                                                 CVector soundDir = (nearPos - travContext.ListenerPos).normed();
+00641                                                                 CClusterSoundStatus css;
+00642                                                                 css.Gain = travContext.Gain;
+00643                                                                 css.Dist = travContext.Dist + minDist;
+00644                                                                 css.Occlusion = travContext.Occlusion;
+00645                                                                 css.OcclusionLFFactor = travContext.OcclusionLFFactor;
+00646                                                                 css.Obstruction = travContext.Obstruction;
+00647                                                                 css.OcclusionRoomRatio = travContext.OcclusionRoomRatio;
+00648                                                                 css.DistFactor = css.Dist / _MaxEarDistance;
+00649                                                                 css.Direction = travContext.Direction;
+00650 
+00651                                                                 float alpha = travContext.Alpha;
+00652                                                                 CVector d1(travContext.Direction1), d2;
+00653 
+00654                                                                 css.Direction = interpolateSourceDirection(travContext, css.Dist+travContext.Dist, nearPos, travContext.ListenerPos /*realListener*/, d1, d2, alpha);
+00655                                                                 css.Position = nearPos + css.Dist * css.Direction;
+00656                                                                 css.PosAlpha = min(1.0f, css.Dist / _PortalInterpolate);
+00657 
+00658                                                                 if (addAudibleCluster(otherCluster, css))
+00659                                                                 {
+00660         //                                                              debugLines.push_back(CLine(travContext.ListenerPos, nearPos));
+00661                                                                         CSoundTravContext stc(travContext);
+00662                                                                         stc.FilterUnvisibleChild = true;
+00663                                                                         stc.Direction1 = d1;
+00664                                                                         stc.Direction2 = d2;
+00665                                                                         stc.Direction = css.Direction;
+00666                                                                         stc.PreviousCluster = cluster;
+00667                                                                         stc.Alpha = alpha;
+00668                                                                         stc.PreviousVector = (nearPos - travContext.ListenerPos).normed();
+00669                                                                         addNextTraverse(otherCluster, stc);
+00670                                                                         _AudioPath.push_back(make_pair(travContext.ListenerPos, nearPos));
+00671                                                                 }
+00672                                                         }
+00673                                                 }
+00674                                                 else
+00675                                                 {
+00676                                                         // find the nearest point of this portal (either on of the perimeter vertex or a point on the portal surface)
+00677                                                         float minDist;
+00678                                                         CVector nearPos;
+00679 
+00680                                                         minDist = getPolyNearestPos(poly, travContext.ListenerPos, nearPos);
+00681 
+00682                                                         if (travContext.Dist+minDist < _MaxEarDistance)
+00683                                                         {
+00684                                                                 // TODO : compute relative gain according to portal behavior.
+00685                                                                 CClusterSoundStatus css;
+00686                                                                 css.Gain = travContext.Gain;
+00687                                                                 CVector soundDir = (nearPos - travContext.ListenerPos).normed();
+00688                                                                 uint occId = portal->getOcclusionModelId();
+00689                                                                 std::hash_map<NLMISC::TStringId, uint>::iterator it(_IdToMaterial.find(occId));
+00690 
+00691         #if EAX_AVAILABLE == 1
+00692                                                                 if (it != _IdToMaterial.end())
+00693                                                                 {
+00694                                                                         // found an occlusion material for this portal
+00695                                                                         uint matId = it->second;
+00696                                                                         css.Occlusion = max(sint32(EAXBUFFER_MINOCCLUSION), sint32(travContext.Occlusion + EAX_MATERIAL_PARAM[matId][0])); //- 1800); //EAX_MATERIAL_THINDOOR;
+00697                                                                         css.OcclusionLFFactor = travContext.OcclusionLFFactor * EAX_MATERIAL_PARAM[matId][1]; //EAX_MATERIAL_THICKDOORLF; //0.66f; //0.0f; //min(EAX_MATERIAL_THINDOORLF, travContext.OcclusionLFFactor);
+00698                                                                         css.OcclusionRoomRatio = EAX_MATERIAL_PARAM[matId][2] * travContext.OcclusionRoomRatio;
+00699                                                                 }
+00700                                                                 else
+00701                                                                 {
+00702                                                                         // the id does not match any know material
+00703                                                                         css.Occlusion = travContext.Occlusion;
+00704                                                                         css.OcclusionLFFactor = travContext.OcclusionLFFactor;
+00705                                                                         css.OcclusionRoomRatio = travContext.OcclusionRoomRatio;
+00706                                                                 }
+00707         #else   // EAX_AVAILABLE
+00708                                                                 if (it != _IdToMaterial.end())
+00709                                                                 {
+00710                                                                         // found an occlusion material for this portal
+00711                                                                         uint matId = it->second;
+00712                                                                         css.Gain *= EAX_MATERIAL_PARAM[matId];
+00713                                                                 }
+00714         #endif  // EAX_AVAILABLE
+00715         /*                                                      if (portal->getOcclusionModel() == "wood door")
+00716                                                                 {
+00717         //                                                              css.Gain *= 0.5f;
+00718         #if EAX_AVAILABLE == 1
+00719                                                                         css.Occlusion = max(EAXBUFFER_MINOCCLUSION, travContext.Occlusion + EAX_MATERIAL_THICKDOOR); //- 1800); //EAX_MATERIAL_THINDOOR;
+00720                                                                         css.OcclusionLFFactor = 0.1f * travContext.OcclusionLFFactor; //EAX_MATERIAL_THICKDOORLF; //0.66f; //0.0f; //min(EAX_MATERIAL_THINDOORLF, travContext.OcclusionLFFactor);
+00721                                                                         css.OcclusionRoomRatio = EAX_MATERIAL_THICKDOORROOMRATION * travContext.OcclusionRoomRatio;
+00722         #else
+00723                                                                         css.Gain *= 0.5f;
+00724         #endif
+00725                                                                 }
+00726                                                                 else if (portal->getOcclusionModel() == "brick door")
+00727                                                                 {
+00728         #if EAX_AVAILABLE == 1
+00729                                                                         css.Occlusion = max(EAXBUFFER_MINOCCLUSION, travContext.Occlusion + EAX_MATERIAL_BRICKWALL);
+00730                                                                         css.OcclusionLFFactor = min(EAX_MATERIAL_BRICKWALLLF, travContext.OcclusionLFFactor);
+00731                                                                         css.OcclusionRoomRatio = EAX_MATERIAL_BRICKWALLROOMRATIO * travContext.OcclusionRoomRatio;
+00732         #else
+00733                                                                         css.Gain *= 0.2f;
+00734         #endif
+00735                                                                 }
+00736                                                                 else
+00737                                                                 {
+00738         #if EAX_AVAILABLE == 1
+00739                                                                         css.Occlusion = travContext.Occlusion;
+00740                                                                         css.OcclusionLFFactor = travContext.OcclusionLFFactor;
+00741                                                                         css.OcclusionRoomRatio = travContext.OcclusionRoomRatio;
+00742         #endif
+00743                                                                 }
+00744 
+00745         */                                                      // compute obstruction  
+00746                                                                 if (travContext.NbPortal >= 1)
+00747                                                                 {
+00748                                                                         float h = soundDir * travContext.PreviousVector;
+00749                                                                         float obst;
+00750 
+00751                                                                         if (h < 0)
+00752                                                                         {
+00753         //                                                                      obst = float(2000 + asinf(-(soundDir ^ travContext.PreviousVector).norm()) / (Pi/2) * 2000);
+00754                                                                                 obst = float(4000 - (soundDir ^ travContext.PreviousVector).norm() * 2000);
+00755                                                                         }
+00756                                                                         else
+00757                                                                         {
+00758         //                                                                      obst = float(asinf((soundDir ^ travContext.PreviousVector).norm()) / (Pi/2) * 2000);
+00759                                                                                 obst = float((soundDir ^ travContext.PreviousVector).norm() * 2000);
+00760                                                                         }
+00761 
+00762         //                                                              float sqrdist = (realListener - nearPoint).sqrnorm();
+00763                                                                         if (travContext.Dist < 2.0f)    // interpolate a 2 m
+00764                                                                                 obst *= travContext.Dist / 2.0f;
+00765         #if EAX_AVAILABLE == 1
+00766                                                                         css.Obstruction = max(sint32(EAXBUFFER_MINOBSTRUCTION), sint32(travContext.Obstruction - sint32(obst)));
+00767                                                                         css.OcclusionLFFactor = 0.50f * travContext.OcclusionLFFactor;
+00768         #else
+00769                                                                         css.Gain *= float(pow(10, -(obst/4)/2000));
+00770         #endif
+00771                                                                 }
+00772                                                                 else
+00773                                                                         css.Obstruction = travContext.Obstruction;
+00774         //                                                      css.Dist = travContext.Dist + float(sqrt(minDist));
+00775                                                                 css.Dist = travContext.Dist + minDist;
+00776                                                                 css.DistFactor = css.Dist / _MaxEarDistance;
+00777                                                                 float   portalDist = css.Dist; 
+00778                                                                 float   alpha = travContext.Alpha;
+00779                                                                 CVector d1(travContext.Direction1), d2(travContext.Direction2);
+00780 
+00781                                                                 css.Direction = interpolateSourceDirection(travContext, portalDist+travContext.Dist, nearPos, travContext.ListenerPos /*realListener*/, d1, d2, alpha);
+00782                                                                 css.Position = nearPos + css.Dist * css.Direction;
+00783                                                                 css.PosAlpha = min(1.0f, css.Dist / _PortalInterpolate);
+00784 
+00785                                                                 if (addAudibleCluster(otherCluster, css))
+00786                                                                 {
+00787         //                                                              debugLines.push_back(CLine(travContext.ListenerPos, nearPoint));
+00788                                                                         CSoundTravContext tc(nearPos, travContext.FilterUnvisibleChild, !cluster->AudibleFromFather);
+00789                                                                         tc.Dist = css.Dist;
+00790                                                                         tc.Gain = css.Gain;
+00791                                                                         tc.Occlusion = css.Occlusion;
+00792                                                                         tc.OcclusionLFFactor = css.OcclusionLFFactor;
+00793                                                                         tc.OcclusionRoomRatio = css.OcclusionRoomRatio;
+00794                                                                         tc.Obstruction = css.Obstruction;
+00795                                                                         tc.Direction1 = d1;
+00796                                                                         tc.Direction2 = d2;
+00797                                                                         tc.NbPortal = travContext.NbPortal+1;
+00798                                                                         tc.Direction = css.Direction;
+00799                                                                         tc.PreviousCluster = cluster;
+00800                                                                         tc.Alpha = alpha;
+00801                                                                         tc.PreviousVector = soundDir;
+00802 
+00803                                                                         addNextTraverse(otherCluster, tc);
+00804                                                                         _AudioPath.push_back(make_pair(travContext.ListenerPos, nearPos));
+00805                                                                 }
+00806                                                         }
+00807                                                 }
+00808                                         }
+00809                                 }
+00810                         }
+00811 
+00812                         // 2nd, look each child cluster
+00813                         for (i=0; i<cluster->Children.size(); ++i)
+00814                         {
+00815                                 CCluster *c = cluster->Children[i];
+00816                                 
+00817                                 // dont redown into an upstream
+00818                                 if (c != travContext.PreviousCluster)
+00819                                 {
+00820                                         // clip on distance.
+00821                                         if (c->AudibleFromFather && c->isIn(travContext.ListenerPos, _MaxEarDistance-travContext.Dist))
+00822                                         {
+00823                                                 float minDist;
+00824                                                 CVector nearPos;
+00825                                                 CAABBox box = c->getBBox();
+00826 
+00827                                                 minDist = getAABoxNearestPos(box, travContext.ListenerPos, nearPos);
+00828                                                 
+00829                                                 if (travContext.Dist + minDist < _MaxEarDistance)
+00830                                                 {
+00831                                                         CClusterSoundStatus css;
+00832                                                         css.Gain = travContext.Gain;
+00833                                                         css.Dist = travContext.Dist + minDist;
+00834                                                         css.DistFactor = css.Dist / _MaxEarDistance;
+00835                                                         css.Occlusion = travContext.Occlusion;
+00836                                                         css.OcclusionLFFactor = travContext.OcclusionLFFactor;
+00837                                                         css.OcclusionRoomRatio = travContext.OcclusionRoomRatio;
+00838                                                         css.Obstruction = travContext.Obstruction;
+00839 /*                                                      if (travContext.NbPortal == 0)
+00840                                                                 css.Direction = (nearPos - travContext.ListenerPos).normed();
+00841                                                         else
+00842                                                                 css.Direction = travContext.Direction1;
+00843 */
+00844                                                         float alpha = travContext.Alpha;
+00845                                                         CVector d1(travContext.Direction1), d2;
+00846 
+00847                                                         css.Direction = interpolateSourceDirection(travContext, css.Dist+travContext.Dist, nearPos, travContext.ListenerPos /*realListener*/, d1, d2, alpha);
+00848                                                         css.Position = nearPos + css.Dist * css.Direction;
+00849                                                         css.PosAlpha = min(1.0f, css.Dist / _PortalInterpolate);
+00850 
+00851                                                         if (addAudibleCluster(c, css))
+00852                                                         {
+00853 //                                                              debugLines.push_back(CLine(travContext.ListenerPos, nearPos));
+00854                                                                 CSoundTravContext stc(travContext);
+00855                                                                 stc.FilterUnvisibleChild = true;
+00856                                                                 stc.Direction1 = d1;
+00857                                                                 stc.Direction2 = d2;
+00858                                                                 stc.Direction = css.Direction;
+00859                                                                 stc.PreviousCluster = cluster;
+00860                                                                 stc.Alpha = alpha;
+00861                                                                 stc.PreviousVector = (nearPos - travContext.ListenerPos).normed();
+00862                                                                 addNextTraverse(c, stc);
+00863                                                                 _AudioPath.push_back(make_pair(travContext.ListenerPos, nearPos));
+00864                                                         }
+00865                                                 }
+00866                                         }
+00867                                 }
+00868                         }
+00869 
+00870                         // 3nd, look in father cluster
+00871                         if (cluster->Father && cluster->Father != travContext.PreviousCluster && cluster->FatherAudible)
+00872                         {
+00873 //                              if (!travContext.FilterUnvisibleFather || ((1.0f-travContext.Alpha) > travContext.MinGain))
+00874                                 {
+00875                                         CCluster *c = cluster->Father;
+00876                                         float minDist;
+00877                                         CVector nearPos;
+00878                                         CAABBox box = c->getBBox();
+00879 
+00880                                         if (c != _RootCluster)
+00881                                                 minDist = getAABoxNearestPos(box, travContext.ListenerPos, nearPos);
+00882                                         else
+00883                                         {
+00884                                                 // special case for root cluster coz it have a zero sized box and a zero position.
+00885                                                 nearPos = travContext.ListenerPos;
+00886                                                 minDist = 0;
+00887                                         }
+00888                                         
+00889                                         CClusterSoundStatus css;
+00890                                         css.Gain = travContext.Gain;
+00891 /*                                      if (travContext.FilterUnvisibleFather)
+00892                                         {
+00893                                                 // compute a gain
+00894                                                 float alpha = 1-(travContext.Dist / _PortalInterpolate);
+00895                                                 alpha = alpha * alpha * alpha;
+00896                                                 css.Gain = max(0.0f, alpha);
+00897                                         }
+00898                                         else
+00899                                                 css.Gain = travContext.Gain;
+00900 */
+00901 //                                      if (c->Name == "cluster_1")
+00902 //                                              nldebug("Cluster 1 : gain = %f", css.Gain);
+00903                                         float alpha = travContext.Alpha;
+00904                                         CVector d1(travContext.Direction1), d2;
+00905 
+00906                                         css.Direction = interpolateSourceDirection(travContext, travContext.Dist, nearPos, travContext.ListenerPos /*realListener*/, d1, d2, alpha);
+00907 
+00908                                         if (css.Gain > _MinGain)
+00909                                         {
+00910                                                 css.Dist = travContext.Dist; 
+00911 //                                              css.Direction = CVector::Null;
+00912                                                 css.DistFactor = css.Dist / _MaxEarDistance;
+00913                                                 css.Occlusion = travContext.Occlusion;
+00914                                                 css.OcclusionLFFactor = travContext.OcclusionLFFactor;
+00915                                                 css.OcclusionRoomRatio = travContext.OcclusionRoomRatio;
+00916                                                 css.Obstruction = travContext.Obstruction;
+00917                                                 css.Position = nearPos + css.Dist * css.Direction;
+00918                                                 css.PosAlpha = min(1.0f, css.Dist / _PortalInterpolate);
+00919 
+00920                                                 if (addAudibleCluster(c, css))
+00921                                                 {
+00922                                                         CSoundTravContext stc(travContext);
+00923                                                         stc.FilterUnvisibleFather = true;
+00924                                                         stc.PreviousCluster = cluster;
+00925                                                         stc.Direction1 = d1;
+00926                                                         stc.Direction2 = d2;
+00927                                                         stc.Direction = css.Direction;
+00928                                                         stc.Alpha = alpha;
+00929                                                         stc.PreviousVector = (nearPos - travContext.ListenerPos).normed();
+00930                                                         _NextTraversalStep.insert(make_pair(c, stc));
+00931                                                 }
+00932                                         }
+00933                                 }
+00934                         }
+00935                         curClusters.pop_back();
+00936                 }
+00937         }
+00938         while (!_NextTraversalStep.empty());
+00939 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
void NLSOUND::CClusteredSound::update const NLMISC::CVector listenerPos,
const NLMISC::CVector view,
const NLMISC::CVector up
+
+ + + + + +
+   + + +

+Update the cluster sound system. +

+css.DistFactor*css.DistFactor +

+Definition at line 270 of file clustered_sound.cpp. +

+References _AudibleClusters, _IdToEaxEnv, _RootCluster, _SoundGroupToSound, NLSOUND::CClusteredSound::CClusterSoundStatus::Direction, NLSOUND::CClusteredSound::CClusterSoundStatus::Dist, NLSOUND::CClusteredSound::CClusterSound::Distance, NLSOUND::CClusteredSound::CClusterSoundStatus::DistFactor, EAXLISTENER_MAXENVIRONMENTSIZE, NLSOUND::CClusteredSound::CClusterSoundStatus::Gain, NL3D::CScene::getClipTrav(), NLMISC::CAABBox::getHalfSize(), NLSOUND::CAudioMixerUser::getListener(), H_AUTO, min, NLMISC::minof(), nldebug, nlwarning, NLSOUND::IListener::setEnvironment(), NLSOUND::USource::setLooping(), NLSOUND::USource::setPos(), NLSOUND::USource::setRelativeGain(), size, soundTraverse(), NLSOUND::CClusteredSound::CClusterSound::Source, uint, NLMISC::CVector::x, NLMISC::CVector::y, and NLMISC::CVector::z. +

+Referenced by NLSOUND::CAudioMixerUser::update(). +

+

00271 {
+00272         H_AUTO(NLSOUND_ClusteredSoundUpdate)
+00273         if (_Scene == 0)
+00274         {
+00275                 // hum... what to do ?
+00276                 static bool bDisplayOnce = false;
+00277                 if (!bDisplayOnce)
+00278                 {
+00279                         nlwarning("CClusteredSound::update : no scene specified !");
+00280                         bDisplayOnce = true;
+00281                 }
+00282                 return;
+00283         }
+00284         
+00285         CClipTrav       &clipTrav = _Scene->getClipTrav ();
+00286 
+00287         // Retreive the list of cluster where the listener is
+00288         vector<CCluster*> vCluster;
+00289         clipTrav.fullSearch (vCluster, clipTrav.RootCluster->Group, listenerPos);
+00290 
+00291 
+00292         // reset the audible cluster map
+00293         _AudibleClusters.clear();
+00294 
+00295         // create the initial travesal context
+00296         CSoundTravContext stc(listenerPos, false, false);
+00297 
+00298         // and start the cluster traversal to find out what cluster is audible and how we ear it
+00299         soundTraverse(vCluster, stc);
+00300 
+00301         //-----------------------------------------------------
+00302         // update the clustered sound (create and stop sound)
+00303         //-----------------------------------------------------
+00304 
+00305         std::hash_map<uint, CClusterSound>              newSources;
+00306 
+00307         {
+00308                 // fake the distance for all playing source
+00309 //              std::map<std::string, CClusterSound>::iterator first(_Sources.begin()), last(_Sources.end());
+00310                 std::hash_map<NLMISC::TStringId, CClusterSound>::iterator first(_Sources.begin()), last(_Sources.end());
+00311                 for (; first != last; ++first)
+00312                 {
+00313                         first->second.Distance = FLT_MAX;
+00314                 }
+00315         }
+00316 
+00317         
+00318         TClusterStatusMap::const_iterator first(_AudibleClusters.begin()), last(_AudibleClusters.end());
+00319         for (; first != last; ++first )
+00320         {
+00321                 static NLMISC::TStringId NO_SOUND_GROUP = CStringMapper::emptyId();
+00322                 const CClusterSoundStatus &css = first->second;
+00323                 CCluster *cluster = first->first;
+00324                 NLMISC::TStringId soundGroup;
+00325 
+00326                 soundGroup = cluster->getSoundGroupId();
+00327 
+00328 
+00329                 if (soundGroup != NO_SOUND_GROUP)
+00330                 {
+00331                         // search an associated sound name
+00332                         std::hash_map<NLMISC::TStringId, CClusterSound>::iterator it(_Sources.find(soundGroup));
+00333                         if (it != _Sources.end())
+00334                         {
+00335                                 // the source is already playing, check and replace if needed
+00336                                 CClusterSound &cs = it->second;
+00337 
+00338                                 if (cs.Distance >= css.Dist)
+00339                                 {
+00340                                         // this one is better !
+00341                                         cs.Distance = css.Dist;
+00342                                         cs.Source->setPos(listenerPos + css.Direction * css.Dist + CVector(0,0,2));
+00343                                         if (css.DistFactor < 1.0f)
+00344                                                 cs.Source->setRelativeGain(css.Gain * (1.0f - (css.DistFactor*css.DistFactor*css.DistFactor*css.DistFactor)));
+00345                                         else
+00346                                                 cs.Source->setRelativeGain(css.Gain);
+00347                                 }
+00348                                 newSources.insert(make_pair(soundGroup, cs));
+00349                         }
+00350                         else
+00351                         {
+00352                                 // create a new source
+00353 
+00354 //                              nldebug("Searching sound assoc for group [%s]", CStringMapper::unmap(soundGroup).c_str());
+00355 
+00356                                 std::hash_map<NLMISC::TStringId, NLMISC::TStringId>::iterator it2(_SoundGroupToSound.find(soundGroup));
+00357                                 if (it2 != _SoundGroupToSound.end())
+00358                                 {
+00359                                         NLMISC::TStringId soundName = it2->second;
+00360                                         CClusterSound cs;
+00361 
+00362                                         nldebug("Found the sound [%s] for sound group [%s]", CStringMapper::unmap(soundName).c_str(), CStringMapper::unmap(soundGroup).c_str());
+00363                                         
+00364                                         cs.Distance = css.Dist;
+00365                                         cs.Source = CAudioMixerUser::instance()->createSource(soundName, false, NULL, NULL, cluster);
+00366                                         if (cs.Source != 0)
+00367                                         {
+00368                                                 cs.Source->setPos(listenerPos + css.Direction * css.Dist + CVector(0,0,2));
+00369                                                 if (css.DistFactor < 1.0f)
+00370                                                         cs.Source->setRelativeGain(css.Gain * (1.0f - (css.DistFactor*css.DistFactor)));
+00371                                                 else
+00372                                                         cs.Source->setRelativeGain(css.Gain);
+00373                                                 cs.Source->setLooping(true);
+00374                                                 newSources.insert(make_pair(soundGroup, cs));
+00375                                         }
+00376                                 }
+00377                         }
+00378                 }
+00379         }
+00380         // check for source to stop
+00381         {
+00382 #if _STLPORT_VERSION >= 0x450
+00383                 std::hash_map<NLMISC::TStringId, CClusterSound> oldSources;
+00384                 oldSources.swap(_Sources);
+00385 #else
+00386                 // there is a bug in the swap methode in stlport 4.5, so fallback to a
+00387                 // very less effective create by copy and clear.
+00388                 std::hash_map<NLMISC::TStringId, CClusterSound> oldSources(_Sources);
+00389                 _Sources.clear();
+00390 #endif
+00391 
+00392                 std::hash_map<uint, CClusterSound>::iterator first(newSources.begin()), last(newSources.end());
+00393                 for (; first != last; ++first)
+00394                 {
+00395                         _Sources.insert(*first);
+00396                         if (!first->second.Source->isPlaying())
+00397                                 first->second.Source->play();
+00398 
+00399                         oldSources.erase(first->first);
+00400                 }
+00401 
+00402                 while (!oldSources.empty())
+00403                 {
+00404                         CClusterSound &cs = oldSources.begin()->second;
+00405                         delete cs.Source;
+00406                         oldSources.erase(oldSources.begin());
+00407                 }
+00408         }
+00409 
+00410         // update the environnement effect (if any)
+00411         if (!vCluster.empty())
+00412         {
+00413                 H_AUTO(NLSOUND_ClusteredSound_updateEnvFx)
+00414                 CAudioMixerUser *mixer = CAudioMixerUser::instance();
+00415                 TStringId fxId = vCluster[0]->getEnvironmentFxId();
+00416 
+00417                 IListener *drvListener = static_cast<CListenerUser*>(mixer->getListener())->getListener();
+00418                 const CAABBox &box = vCluster[0]->getBBox();
+00419                 CVector vsize = box.getHalfSize();
+00420                 float   size = NLMISC::minof(vsize.x, vsize.y, vsize.z) * 2;
+00421 
+00422                 // special case for root cluster (ie, external)
+00423                 if (vCluster[0] == _RootCluster)
+00424                 {
+00425                         // this is the root cluster. This cluster have a size of 0 !
+00426                         size = EAXLISTENER_MAXENVIRONMENTSIZE;
+00427                 }
+00428                 else
+00429                 {
+00430                         // else, clip the env size to max eax supported size
+00431                         size = min(size, EAXLISTENER_MAXENVIRONMENTSIZE);
+00432                 }
+00433 
+00434                 uint newEnv;
+00435 
+00436                 // retreive the EAX environment number
+00437                 std::hash_map<NLMISC::TStringId, uint>::iterator it(_IdToEaxEnv.find(fxId));
+00438                 if (it != _IdToEaxEnv.end())
+00439                 {
+00440                         // there is an EAX effect
+00441                         newEnv = it->second;
+00442                 }
+00443                 else
+00444                 {
+00445                         // no effect, default to "PLAIN" effect
+00446                         static TStringId plain = CStringMapper::map("PLAIN");
+00447                         newEnv = _IdToEaxEnv[plain];
+00448                 }
+00449 
+00450                 // only update environement if there is some change.
+00451                 if (newEnv != _LastEnv)
+00452                 {
+00453                         drvListener->setEnvironment(newEnv, size);
+00454                         _LastEnv = newEnv;
+00455                 }
+00456         }
+00457 }
+
+


Field Documentation

+

+ + + + +
+ + +
TClusterStatusMap NLSOUND::CClusteredSound::_AudibleClusters [private] +
+
+ + + + + +
+   + + +

+The current audible cluster. +

+ +

+Definition at line 252 of file clustered_sound.h. +

+Referenced by addAudibleCluster(), getAudibleClusters(), getClusterSoundStatus(), soundTraverse(), and update().

+

+ + + + +
+ + +
std::vector<std::pair<NLMISC::CVector, NLMISC::CVector> > NLSOUND::CClusteredSound::_AudioPath [private] +
+
+ + + + + +
+   + + +

+The segment of all the audio path. +

+ +

+Definition at line 258 of file clustered_sound.h. +

+Referenced by getAudioPath(), and soundTraverse().

+

+ + + + +
+ + +
char * NLSOUND::CClusteredSound::_EnvironmentNames [static, private] +
+
+ + + + + +
+   + + +

+Initial value:

+{
+    "GENERIC",
+    "PADDEDCELL",
+    "ROOM",
+    "BATHROOM",
+    "LIVINGROOM",
+    "STONEROOM",
+    "AUDITORIUM",
+    "CONCERTHALL",
+    "CAVE",
+    "ARENA",
+    "HANGAR",
+    "CARPETEDHALLWAY",
+    "HALLWAY",
+    "STONECORRIDOR",
+    "ALLEY",
+    "FOREST",
+    "CITY",
+    "MOUNTAINS",
+    "QUARRY",
+    "PLAIN",
+    "PARKINGLOT",
+    "SEWERPIPE",
+    "UNDERWATER",
+    "DRUGGED",
+    "DIZZY",
+    "PSYCHOTIC",
+        NULL
+}
+
The environment name table for init. +

+ +

+Definition at line 51 of file clustered_sound.cpp. +

+Referenced by CClusteredSound().

+

+ + + + +
+ + +
std::hash_map<NLMISC::TStringId, uint> NLSOUND::CClusteredSound::_IdToEaxEnv [private] +
+
+ + + + + +
+   + + +

+The mapping for env name Id to EAX environement number. +

+ +

+Definition at line 267 of file clustered_sound.h. +

+Referenced by CClusteredSound(), and update().

+

+ + + + +
+ + +
std::hash_map<NLMISC::TStringId, uint> NLSOUND::CClusteredSound::_IdToMaterial [private] +
+
+ + + + + +
+   + + +

+The mapping for occlusion material name to material number. +

+ +

+Definition at line 269 of file clustered_sound.h. +

+Referenced by CClusteredSound(), and soundTraverse().

+

+ + + + +
+ + +
uint NLSOUND::CClusteredSound::_LastEnv [private] +
+
+ + + + + +
+   + + +

+The last setted environement. +

+ +

+Definition at line 256 of file clustered_sound.h.

+

+ + + + +
+ + +
char * NLSOUND::CClusteredSound::_MaterialNames [static, private] +
+
+ + + + + +
+   + + +

+Initial value:

 
+{
+        "SINGLEWINDOW",
+        "DOUBLEWINDOW",
+        "THINDOOR",
+        "THICKDOOR",
+        "WOODWALL",
+        "BRICKWALL",
+        "STONEWALL",
+        "CURTAIN",
+        NULL
+}
+
The material name table for init. +

+ +

+Definition at line 81 of file clustered_sound.cpp. +

+Referenced by CClusteredSound().

+

+ + + + +
+ + +
float NLSOUND::CClusteredSound::_MaxEarDistance [private] +
+
+ + + + + +
+   + + +

+Maximum earing distance. +

+ +

+Definition at line 244 of file clustered_sound.h. +

+Referenced by addAudibleCluster(), init(), and soundTraverse().

+

+ + + + +
+ + +
float NLSOUND::CClusteredSound::_MinGain [private] +
+
+ + + + + +
+   + + +

+Minimum gain. +

+ +

+Definition at line 246 of file clustered_sound.h. +

+Referenced by init(), and soundTraverse().

+

+ + + + +
+ + +
TClusterTravContextMap NLSOUND::CClusteredSound::_NextTraversalStep [private] +
+
+ + + + + +
+   + + +

+The cluster for the next travesal step. +

+ +

+Definition at line 254 of file clustered_sound.h. +

+Referenced by addNextTraverse(), and soundTraverse().

+

+ + + + +
+ + +
float NLSOUND::CClusteredSound::_PortalInterpolate [private] +
+
+ + + + + +
+   + + +

+Interpolation distance when listener is near a portal. +

+ +

+Definition at line 242 of file clustered_sound.h. +

+Referenced by init(), interpolateSourceDirection(), and soundTraverse().

+

+ + + + +
+ + +
NL3D::CCluster* NLSOUND::CClusteredSound::_RootCluster [private] +
+
+ + + + + +
+   + + +

+The root cluster of the scene. +

+ +

+Definition at line 248 of file clustered_sound.h. +

+Referenced by init(), soundTraverse(), and update().

+

+ + + + +
+ + +
NL3D::CScene* NLSOUND::CClusteredSound::_Scene [private] +
+
+ + + + + +
+   + + +

+The scene of interest. +

+ +

+Definition at line 240 of file clustered_sound.h.

+

+ + + + +
+ + +
std::hash_map<NLMISC::TStringId, NLMISC::TStringId> NLSOUND::CClusteredSound::_SoundGroupToSound [private] +
+
+ + + + + +
+   + + +

+The sound_group to sound assoc. +

+ +

+Definition at line 264 of file clustered_sound.h. +

+Referenced by init(), and update().

+

+ + + + +
+ + +
std::hash_map<NLMISC::TStringId, CClusterSound> NLSOUND::CClusteredSound::_Sources [private] +
+
+ + + + + +
+   + + +

+The current cluster playing source indexed with sound group id. +

+ +

+Definition at line 261 of file clustered_sound.h.

+


The documentation for this class was generated from the following files: +
Generated on Tue Mar 16 14:34:54 2004 for NeL by + +doxygen +1.3.6
+ + -- cgit v1.2.1