From babf58f8d2700b3ba84089e7b59f8838c685d6ca Mon Sep 17 00:00:00 2001 From: ehofman Date: Sun, 11 Oct 2009 13:38:27 +0000 Subject: [PATCH] Correct (and verrified) position, orientation and velocity vector. Todo: proper sound orientation (the all face forward using the airplane orientation now) and disabling doppler effect when tied to the listener --- simgear/sound/sample_group.cxx | 46 ++++++++++++--------- simgear/sound/sample_group.hxx | 9 ++-- simgear/sound/sample_openal.cxx | 27 +++++++++++- simgear/sound/sample_openal.hxx | 15 +++++-- simgear/sound/soundmgr_openal.cxx | 69 ++++++++++++++++--------------- simgear/sound/soundmgr_openal.hxx | 34 +++++++++------ simgear/sound/xmlsound.cxx | 43 +++++++------------ 7 files changed, 141 insertions(+), 102 deletions(-) diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index dabf79bf..22f9f9bf 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -43,24 +43,27 @@ extern "C" int isinf (double); SGSampleGroup::SGSampleGroup () : _smgr(NULL), + _refname(""), _active(false), - _position(SGVec3d::zeros().data()), - _orientation(SGVec3f::zeros().data()), - _tied_to_listener(false) + _tied_to_listener(false), + _position(SGVec3d::zeros()), + _velocity(SGVec3f::zeros()), + _orientation(SGVec3f::zeros()) { _samples.clear(); } SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) : _smgr(smgr), + _refname(refname), _active(false), - _position(SGVec3d::zeros().data()), - _orientation(SGVec3f::zeros().data()), - _tied_to_listener(false) + _tied_to_listener(false), + _position(SGVec3d::zeros()), + _velocity(SGVec3f::zeros()), + _orientation(SGVec3f::zeros()) { _smgr->add(this, refname); _active = _smgr->is_working(); - _refname = refname; _samples.clear(); } @@ -300,13 +303,14 @@ void SGSampleGroup::set_position( SGVec3d pos ) { return; } - if ( !_tied_to_listener ) { + if ( !_tied_to_listener && _position != pos ) { sample_map_iterator sample_current = _samples.begin(); sample_map_iterator sample_end = _samples.end(); for ( ; sample_current != sample_end; ++sample_current ) { SGSoundSample *sample = sample_current->second; sample->set_base_position( pos ); } + _position = pos; } } @@ -318,11 +322,13 @@ void SGSampleGroup::set_velocity( SGVec3f vel ) { return; } - sample_map_iterator sample_current = _samples.begin(); - sample_map_iterator sample_end = _samples.end(); - for ( ; sample_current != sample_end; ++sample_current ) { - SGSoundSample *sample = sample_current->second; - sample->set_velocity( vel ); + if (_velocity != vel) { + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + sample->set_velocity( vel ); + } } } @@ -334,11 +340,13 @@ void SGSampleGroup::set_orientation( SGVec3f ori ) { return; } - sample_map_iterator sample_current = _samples.begin(); - sample_map_iterator sample_end = _samples.end(); - for ( ; sample_current != sample_end; ++sample_current ) { - SGSoundSample *sample = sample_current->second; - sample->set_orientation( ori ); + if (_orientation != ori) { + sample_map_iterator sample_current = _samples.begin(); + sample_map_iterator sample_end = _samples.end(); + for ( ; sample_current != sample_end; ++sample_current ) { + SGSoundSample *sample = sample_current->second; + sample->set_orientation( ori ); + } } } @@ -347,7 +355,7 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { unsigned int source = sample->get_source(); alSourcefv( source, AL_POSITION, sample->get_position()); - alSourcefv( source, AL_DIRECTION, sample->get_direction() ); + alSourcefv( source, AL_DIRECTION, sample->get_orientation() ); alSourcefv( source, AL_VELOCITY, sample->get_velocity() ); testForALError("position and orientation"); diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index b3170696..1344df44 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -35,6 +35,8 @@ #if defined(__APPLE__) # include +#elif defined(_WIN32) +# include #else # include #endif @@ -156,21 +158,22 @@ public: protected: SGSoundMgr *_smgr; + string _refname; bool _active; private: float _volume; + bool _tied_to_listener; + SGVec3d _position; + SGVec3f _velocity; SGVec3f _orientation; - bool _tied_to_listener; sample_map _samples; bool testForALError(string s); bool testForError(void *p, string s); - string _refname; - void update_sample_config( SGSoundSample *sound ); }; diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index 011e0fd3..8eb83a68 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -42,6 +42,7 @@ SGSoundSample::SGSoundSample() : _absolute_pos(SGVec3d::zeros().data()), _relative_pos(SGVec3f::zeros().data()), _base_pos(SGVec3d::zeros().data()), + _orientation(SGVec3f::zeros().data()), _direction(SGVec3f::zeros().data()), _velocity(SGVec3f::zeros().data()), _sample_name(""), @@ -74,6 +75,7 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) : _absolute_pos(SGVec3d::zeros().data()), _relative_pos(SGVec3f::zeros().data()), _base_pos(SGVec3d::zeros().data()), + _orientation(SGVec3f::zeros().data()), _direction(SGVec3f::zeros().data()), _velocity(SGVec3f::zeros().data()), _format(AL_FORMAT_MONO8), @@ -112,6 +114,7 @@ SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format _absolute_pos(SGVec3d::zeros().data()), _relative_pos(SGVec3f::zeros().data()), _base_pos(SGVec3d::zeros().data()), + _orientation(SGVec3f::zeros().data()), _direction(SGVec3f::zeros().data()), _velocity(SGVec3f::zeros().data()), _data(data), @@ -145,6 +148,16 @@ SGSoundSample::SGSoundSample( unsigned char *data, int len, int freq, int format SGSoundSample::~SGSoundSample() { } +float *SGSoundSample::get_orientation() { +#if 0 + SGQuatf quat = SGQuatf::fromAngleAxis(_orientation); + SGVec3f orient = quat.transform(_direction); + return orient.data(); +#else + return _orientation.data(); +#endif +} + void SGSoundSample::set_base_position( SGVec3d pos ) { _base_pos = pos; update_absolute_position(); @@ -157,14 +170,24 @@ void SGSoundSample::set_relative_position( SGVec3f pos ) { _changed = true; } -void SGSoundSample::set_orientation( SGVec3f dir ) { +void SGSoundSample::set_orientation( SGVec3f ori ) { + _orientation = ori; + update_absolute_position(); + _changed = true; +} + +void SGSoundSample::set_direction( SGVec3f dir ) { _direction = dir; update_absolute_position(); _changed = true; } void SGSoundSample::update_absolute_position() { - SGQuatf orient = SGQuatf::fromAngleAxis(_direction); +#if 0 + SGQuatf orient = SGQuatf::fromAngleAxis(_orientation); SGVec3f modified_relative_pos = orient.transform(_relative_pos); _absolute_pos = _base_pos + toVec3d(modified_relative_pos); +#else + _absolute_pos = _base_pos; +#endif } diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index 5d4baf62..f44596a8 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -58,7 +58,8 @@ private: SGVec3d _base_pos; // base position // The orientation of the sound (direction and cut-off angles) - SGVec3f _direction; + SGVec3f _orientation; // base orientation + SGVec3f _direction; // orientation offset // Velocity of the source sound. SGVec3f _velocity; @@ -337,7 +338,13 @@ public: * Set the orientation of the sound source, both for direction * and audio cut-off angles. */ - void set_orientation( SGVec3f dir ); + void set_orientation( SGVec3f ori ); + + /** + * Set the relative direction of the sound source, both for direction + * and audio cut-off angles. + */ + void set_direction( SGVec3f dir ); /** * Define the audio cone parameters for directional audio @@ -353,8 +360,8 @@ public: * Get the orientation of the sound source, the inner or outer angle * or outer gain. */ - inline float *get_orientation() { return _direction.data(); } - inline float *get_direction() { return _direction.data(); } + float *get_orientation(); + inline float get_innerangle() { return _inner_angle; } inline float get_outerangle() { return _outer_angle; } inline float get_outergain() { return _outer_gain; } diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 4f49416a..d082d6c3 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -59,8 +59,8 @@ SGSoundMgr::SGSoundMgr() : _volume(0.0), _device(NULL), _context(NULL), - _listener_pos(SGVec3d::zeros().data()), - _listener_vel(SGVec3f::zeros().data()), + _position(SGVec3d::zeros().data()), + _velocity(SGVec3f::zeros().data()), _devname(NULL) { #if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1 @@ -111,15 +111,15 @@ void SGSoundMgr::init() { _context = context; _working = true; - _listener_ori[0] = 0.0; _listener_ori[1] = 0.0; _listener_ori[2] = -1.0; - _listener_ori[3] = 0.0; _listener_ori[4] = 1.0; _listener_ori[5] = 0.0; + _orientation[0] = 0.0; _orientation[1] = 0.0; _orientation[2] = -1.0; + _orientation[3] = 0.0; _orientation[4] = 1.0; _orientation[5] = 0.0; alListenerf( AL_GAIN, 0.2f ); - alListenerfv( AL_POSITION, toVec3f(_listener_pos).data() ); - alListenerfv( AL_ORIENTATION, _listener_ori ); - alListenerfv( AL_VELOCITY, _listener_vel.data() ); + alListenerfv( AL_POSITION, toVec3f(_position).data() ); + alListenerfv( AL_ORIENTATION, _orientation ); + alListenerfv( AL_VELOCITY, _velocity.data() ); - alDopplerFactor(1.0); + alDopplerFactor(0.5); alDopplerVelocity(340.3); // speed of sound in meters per second. if ( alIsExtensionPresent((const ALchar*)"EXT_exponent_distance") ) { @@ -227,9 +227,9 @@ void SGSoundMgr::update_late( double dt ) { if (_changed) { alListenerf( AL_GAIN, _volume ); - alListenerfv( AL_VELOCITY, _listener_vel.data() ); - alListenerfv( AL_ORIENTATION, _listener_ori ); - alListenerfv( AL_POSITION, toVec3f(_listener_pos).data() ); + alListenerfv( AL_VELOCITY, _velocity.data() ); + alListenerfv( AL_ORIENTATION, _orientation ); + alListenerfv( AL_POSITION, toVec3f(_position).data() ); // alDopplerVelocity(340.3); // TODO: altitude dependent testForALError("update"); _changed = false; @@ -321,6 +321,30 @@ void SGSoundMgr::set_volume( float v ) _changed = true; } +/** + * set the orientation of the listener (in opengl coordinates) + * + * Description: ORIENTATION is a pair of 3-tuples representing the + * 'at' direction vector and 'up' direction of the Object in + * Cartesian space. AL expects two vectors that are orthogonal to + * each other. These vectors are not expected to be normalized. If + * one or more vectors have zero length, implementation behavior + * is undefined. If the two vectors are linearly dependent, + * behavior is undefined. + */ +void SGSoundMgr::set_orientation( SGQuatd ori ) +{ + SGVec3d sgv_up = ori.rotate(SGVec3d::e2()); + SGVec3d sgv_at = ori.rotate(SGVec3d::e3()); + _orientation[0] = sgv_at[0]; + _orientation[1] = sgv_at[1]; + _orientation[2] = sgv_at[2]; + _orientation[3] = sgv_up[0]; + _orientation[4] = sgv_up[1]; + _orientation[5] = sgv_up[2]; + _changed = true; +} + // Get an unused source id // // The Sound Manager should keep track of the sources in use, the distance @@ -482,29 +506,6 @@ bool SGSoundMgr::load(string &samplepath, void **dbuf, int *fmt, } -/** - * set the orientation of the listener (in opengl coordinates) - * - * Description: ORIENTATION is a pair of 3-tuples representing the - * 'at' direction vector and 'up' direction of the Object in - * Cartesian space. AL expects two vectors that are orthogonal to - * each other. These vectors are not expected to be normalized. If - * one or more vectors have zero length, implementation behavior - * is undefined. If the two vectors are linearly dependent, - * behavior is undefined. - */ -void SGSoundMgr::set_orientation( SGQuatd ori ) -{ - SGVec3d sgv_up = ori.rotate(SGVec3d::e3()); - SGVec3d sgv_at = ori.rotate(SGVec3d::e2()); - for (int i=0; i<3; i++) { - _listener_ori[i] = sgv_at[i]; - _listener_ori[i+3] = sgv_up[i]; - } - _changed = true; -} - - bool SGSoundMgr::testForError(void *p, string s) { if (p == NULL) { diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index ef46df8f..ba1e5522 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -47,6 +47,10 @@ # include # include # include +#elif defined(_WIN32) +# include +# include +# include #else # include # include @@ -130,23 +134,27 @@ public: /** * set the position of the listener (in opengl coordinates) */ - inline void set_position( SGVec3d pos ) { - _listener_pos = pos; - _changed = true; + void set_position( SGVec3d pos ) { + if (_position != pos) { + _position = pos; + _changed = true; + } } - inline double *get_position() { return _listener_pos.data(); } - inline SGVec3d get_position_vec() { return _listener_pos; }; + inline double *get_position() { return _position.data(); } + inline SGVec3d get_position_vec() { return _position; }; /** * set the velocity of the listener (in opengl coordinates) */ - inline void set_velocity( SGVec3f vel ) { - _listener_vel = vel; - _changed = true; + void set_velocity( SGVec3f vel ) { + if (_velocity != vel) { + _velocity = vel; + _changed = true; + } } - inline SGVec3f get_velocity() { return _listener_vel; } + inline SGVec3f get_velocity() { return _velocity; } /** * set the orientation of the listener (in opengl coordinates) @@ -154,7 +162,7 @@ public: void set_orientation( SGQuatd ori ); inline SGVec3f get_direction() { - return SGVec3f(_listener_ori[0], _listener_ori[1], _listener_ori[2]); + return SGVec3f(_orientation[0], _orientation[1], _orientation[2]); } enum { @@ -210,14 +218,14 @@ private: ALCcontext *_context; // Position of the listener. - SGVec3d _listener_pos; + SGVec3d _position; // Velocity of the listener. - SGVec3f _listener_vel; + SGVec3f _velocity; // Orientation of the listener. // first 3 elements are "at" vector, second 3 are "up" vector - ALfloat _listener_ori[6]; + ALfloat _orientation[6]; sample_group_map _sample_groups; buffer_map _buffers; diff --git a/simgear/sound/xmlsound.cxx b/simgear/sound/xmlsound.cxx index 919f0837..9fe4fdb1 100644 --- a/simgear/sound/xmlsound.cxx +++ b/simgear/sound/xmlsound.cxx @@ -230,11 +230,11 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, // Relative position // SGVec3f offset_pos = SGVec3f::zeros(); - SGPropertyNode_ptr pos = node->getChild("position"); - if ( pos != NULL ) { - offset_pos[0] = pos->getDoubleValue("x", 0.0); - offset_pos[1] = -pos->getDoubleValue("y", 0.0); - offset_pos[2] = pos->getDoubleValue("z", 0.0); + SGPropertyNode_ptr prop = node->getChild("position"); + if ( prop != NULL ) { + offset_pos[0] = prop->getDoubleValue("x", 0.0); + offset_pos[1] = -prop->getDoubleValue("y", 0.0); + offset_pos[2] = prop->getDoubleValue("z", 0.0); } // @@ -244,40 +244,29 @@ SGXmlSound::init(SGPropertyNode *root, SGPropertyNode *node, float inner, outer, outer_gain; inner = outer = 360.0; outer_gain = 0.0; - pos = node->getChild("orientation"); - if ( pos != NULL ) { - dir[0] = pos->getDoubleValue("x", 0.0); - dir[1] = -pos->getDoubleValue("y", 0.0); - dir[2] = pos->getDoubleValue("z", 0.0); - inner = pos->getDoubleValue("inner-angle", 360.0); - outer = pos->getDoubleValue("outer-angle", 360.0); - outer_gain = pos->getDoubleValue("outer-gain", 0.0); + prop = node->getChild("orientation"); + if ( prop != NULL ) { + dir[0] = prop->getDoubleValue("x", 0.0); + dir[1] = -prop->getDoubleValue("y", 0.0); + dir[2] = prop->getDoubleValue("z", 0.0); + inner = prop->getDoubleValue("inner-angle", 360.0); + outer = prop->getDoubleValue("outer-angle", 360.0); + outer_gain = prop->getDoubleValue("outer-gain", 0.0); } // // Initialize the sample // _sgrp = sgrp; - if ( (_sample = _sgrp->find(_name)) == NULL ) { - // FIXME: Does it make sense to overwrite a previous entry's - // configuration just because a new entry has the same name? - // Note that we can't match on identical "path" because we the - // new entry could be at a different location with different - // configuration so we need a new sample which creates a new - // "alSource". The semantics of what is going on here seems - // confused and needs to be thought through more carefully. - _sample = new SGSoundSample( path.c_str(), - node->getStringValue("path", "") ); - _sgrp->add( _sample, _name ); - } - + _sample = new SGSoundSample( path.c_str(), node->getStringValue("path", "")); _sample->set_relative_position( offset_pos ); - _sample->set_orientation( dir ); + _sample->set_direction( dir ); _sample->set_audio_cone(inner, outer, outer_gain); _sample->set_reference_dist( reference_dist ); _sample->set_max_dist( max_dist ); _sample->set_volume(v); _sample->set_pitch(p); + _sgrp->add( _sample, _name ); } void -- 2.39.5