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