diff --git a/simgear/sound/openal_test3.cxx b/simgear/sound/openal_test3.cxx index 79269f10..dccbd3d5 100644 --- a/simgear/sound/openal_test3.cxx +++ b/simgear/sound/openal_test3.cxx @@ -22,7 +22,7 @@ int main( int argc, char *argv[] ) { smgr->init(); sgr = smgr->find("default", true); smgr->set_volume(0.9); - smgr->set_position( SGVec3d::fromGeod(SGGeod::fromDeg(0,0)) ); + smgr->set_position_geod( SGGeod::fromDeg(0,0) ); smgr->activate(); printf("default position and orientation\n"); @@ -39,8 +39,8 @@ int main( int argc, char *argv[] ) { sleep(1); printf("source at lat,lon = (10,-10), listener at (9.99,-9.99)\n"); - sample1->set_position( SGGeod::fromDeg(10,-10) ); - smgr->set_position( SGVec3d::fromGeod(SGGeod::fromDeg(9.99,-9.99)) ); + sample1->set_position_geod( SGGeod::fromDeg(10,-10) ); + smgr->set_position( SGGeod::fromDeg(9.99,-9.99) ); sample1->play_looped(); smgr->update(1.0); printf("playing sample\n"); diff --git a/simgear/sound/sample_group.cxx b/simgear/sound/sample_group.cxx index a5d19641..82c4e6e7 100644 --- a/simgear/sound/sample_group.cxx +++ b/simgear/sound/sample_group.cxx @@ -327,13 +327,13 @@ void SGSampleGroup::set_velocity( const SGVec3f &vel ) { } // set the source position of all managed sounds -void SGSampleGroup::set_position( const SGGeod& pos ) { +void SGSampleGroup::set_position_geod( const SGGeod& 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_position( pos ); + sample->set_position_geod( pos ); } _position = pos; } @@ -376,13 +376,13 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) { position = _smgr->get_position(); velocity = _smgr->get_velocity(); } else { - sample->update_absolute_position(); + sample->update_pos_and_orientation(); orientation = sample->get_orientation(); position = sample->get_position(); velocity = sample->get_velocity(); } - if (dist(position, _smgr->get_position()) > 10000) + if (length(position -_smgr->get_position()) > 20000) printf("source and listener distance greater than 20km!\n"); if (isNaN(toVec3f(position).data())) printf("NaN in source position\n"); if (isNaN(orientation.data())) printf("NaN in source orientation\n"); diff --git a/simgear/sound/sample_group.hxx b/simgear/sound/sample_group.hxx index d74866e7..645e18b8 100644 --- a/simgear/sound/sample_group.hxx +++ b/simgear/sound/sample_group.hxx @@ -186,7 +186,7 @@ public: /** * Set the velocity vector of this sample group. - * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. + * This is in the local frame coordinate system; x=north, y=east, z=down * @param vel Velocity vector */ void set_velocity( const SGVec3f& vel ); @@ -196,7 +196,7 @@ public: * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. * @param pos Base position */ - void set_position( const SGGeod& pos ); + void set_position_geod( const SGGeod& pos ); /** * Set the orientation of this sample group. diff --git a/simgear/sound/sample_openal.cxx b/simgear/sound/sample_openal.cxx index b66c3628..7e06a64e 100644 --- a/simgear/sound/sample_openal.cxx +++ b/simgear/sound/sample_openal.cxx @@ -191,7 +191,7 @@ SGSoundSample::~SGSoundSample() { if (_data) free(_data); } -void SGSoundSample::update_absolute_position() { +void SGSoundSample::update_pos_and_orientation() { // The rotation rotating from the earth centerd frame to // the horizontal local frame SGQuatd hlOr = SGQuatd::fromLonLat(_base_pos); @@ -208,12 +208,10 @@ void SGSoundSample::update_absolute_position() { SGVec3d position = SGVec3d::fromGeod(_base_pos); _absolute_pos = position; - if ( !(_relative_pos[0] == 0 && _relative_pos[1] == 0 && - _relative_pos[2] == 0) ) - { + if ( _relative_pos[0] || _relative_pos[1] || _relative_pos[2] ) { _absolute_pos += (sc2body*q).backTransform(_relative_pos); } - if ( !(_direction[0] == 0 && _direction[1] == 0 && _direction[2] == 0) ) { + if ( _direction[0] || _direction[1] || _direction[2] ) { _orivec = toVec3f((sc2body*q).backTransform(toVec3d(_direction))); } } diff --git a/simgear/sound/sample_openal.hxx b/simgear/sound/sample_openal.hxx index 0d924246..d419d767 100644 --- a/simgear/sound/sample_openal.hxx +++ b/simgear/sound/sample_openal.hxx @@ -311,7 +311,7 @@ public: * Set the base position of this sound in Geodetic coordinates. * @param pos Geodetic position */ - inline void set_position( const SGGeod& pos ) { + inline void set_position_geod( const SGGeod& pos ) { _base_pos = pos; _changed = true; } @@ -381,7 +381,7 @@ public: /** * Set the velocity vector (in meters per second) of this sound. - * This is in the same coordinate system as OpenGL; y=up, z=back, x=right + * This is in the local frame coordinate system; x=north, y=east, z=down * @param Velocity vector */ inline void set_velocity( const SGVec3f& vel ) { @@ -435,7 +435,7 @@ public: */ inline std::string get_sample_name() const { return _refname; } - void update_absolute_position(); + void update_pos_and_orientation(); private: diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 6b530e53..c01f144f 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -63,7 +63,9 @@ SGSoundMgr::SGSoundMgr() : _volume(0.0), _device(NULL), _context(NULL), - _position(SGVec3d::zeros()), + _position_geod(SGGeod::fromDeg(0,0)), + _position_offs(SGVec3d::zeros()), + _absolute_pos(SGVec3d::zeros()), _velocity(SGVec3d::zeros()), _orientation(SGQuatd::zeros()), _orient_offs(SGQuatd::zeros()), @@ -254,11 +256,12 @@ void SGSoundMgr::update( double dt ) { if (_changed) { if (isNaN(_at_up_vec)) printf("NaN in listener orientation\n"); -if (isNaN(toVec3f(_position).data())) printf("NaN in listener position\n"); +if (isNaN(toVec3f(_absolute_pos).data())) printf("NaN in listener position\n"); if (isNaN(_velocity.data())) printf("NaN in listener velocity\n"); + update_pos_and_orientation(); alListenerf( AL_GAIN, _volume ); alListenerfv( AL_ORIENTATION, _at_up_vec ); - alListenerfv( AL_POSITION, toVec3f(_position).data() ); + alListenerfv( AL_POSITION, toVec3f(_absolute_pos).data() ); alListenerfv( AL_VELOCITY, _velocity.data() ); // alDopplerVelocity(340.3); // TODO: altitude dependent testForALError("update"); @@ -336,33 +339,6 @@ 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( const SGQuatd& ori, const SGQuatd& offs ) -{ - _orientation = ori; - _orient_offs = offs; - - SGVec3d sgv_up = offs.rotate(SGVec3d::e2()); - SGVec3d sgv_at = offs.rotate(SGVec3d::e3()); - _at_up_vec[0] = sgv_at[0]; - _at_up_vec[1] = sgv_at[1]; - _at_up_vec[2] = sgv_at[2]; - _at_up_vec[3] = sgv_up[0]; - _at_up_vec[4] = sgv_up[1]; - _at_up_vec[5] = sgv_up[2]; - _changed = true; -} - // Get an unused source id // // The Sound Manager should keep track of the sources in use, the distance @@ -485,6 +461,45 @@ void SGSoundMgr::release_buffer(SGSoundSample *sample) } } +void SGSoundMgr::update_pos_and_orientation() { + // The rotation rotating from the earth centerd frame to + // the horizontal local frame + SGQuatd hlOr = SGQuatd::fromLonLat( _position_geod ); + + // Compute the listeners orientation and position + // wrt the earth centered frame - that is global coorinates + SGQuatd lc2body = hlOr*_orientation; + + // cartesian position of the listener + SGVec3d position = SGVec3d::fromGeod( _position_geod ); + + // This is rotates the x-forward, y-right, z-down coordinate system where + // simulation runs into the OpenGL camera system with x-right, y-up, z-back. + SGQuatd q(-0.5, -0.5, 0.5, 0.5); + + _absolute_pos = position + (lc2body*q).backTransform( _position_offs ); + + /** + * 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. + * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. + */ + SGQuatd lViewOrientation = lc2body*_orient_offs*q; + SGVec3d sgv_up = lViewOrientation.rotate(SGVec3d::e2()); + SGVec3d sgv_at = lViewOrientation.rotate(SGVec3d::e3()); + _at_up_vec[0] = sgv_at[0]; + _at_up_vec[1] = sgv_at[1]; + _at_up_vec[2] = sgv_at[2]; + _at_up_vec[3] = sgv_up[0]; + _at_up_vec[4] = sgv_up[1]; + _at_up_vec[5] = sgv_up[2]; +} + bool SGSoundMgr::load(string &samplepath, void **dbuf, int *fmt, size_t *sz, int *frq ) { diff --git a/simgear/sound/soundmgr_openal.hxx b/simgear/sound/soundmgr_openal.hxx index 74e6b89f..8cba4ac7 100644 --- a/simgear/sound/soundmgr_openal.hxx +++ b/simgear/sound/soundmgr_openal.hxx @@ -153,13 +153,15 @@ public: SGSampleGroup *find( const string& refname, bool create = false ); /** - * Set the position of the sound manager. - * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. + * Set the Geodetic position of the sound manager. * @param pos OpenAL listener position */ - void set_position( const SGVec3d& pos ) { - _position = pos; - _changed = true; + void set_position_geod( const SGGeod& pos ) { + _position_geod = pos; _changed = true; + } + + void set_position_offset( const SGVec3d& pos ) { + _position_offs = pos; _changed = true; } /** @@ -167,14 +169,14 @@ public: * This is in the same coordinate system as OpenGL; y=up, z=back, x=right * @return OpenAL listener position */ - SGVec3d& get_position() { return _position; } + SGVec3d& get_position() { return _absolute_pos; } /** - * Set the velocity vector of the sound manager - * This is in the same coordinate system as OpenGL; y=up, z=back, x=right. - * @param vel Velocity vector of the OpenAL listener + * Set the velocity vector (in meters per second) of the sound manager + * This is the horizontal local frame; x=north, y=east, z=down + * @param Velocity vector */ - void set_velocity( SGVec3f& vel ) { + void set_velocity( const SGVec3f& vel ) { _velocity = vel; _changed = true; } @@ -189,7 +191,9 @@ public: * Set the orientation of the sound manager * @param ori Quaternation containing the orientation information */ - void set_orientation( const SGQuatd& ori, const SGQuatd& offs ); + void set_orientation( const SGQuatd& ori, const SGQuatd& offs ) { + _orientation = ori; _orient_offs = offs; _changed = true; + } /** * Get the orientation of the sound manager @@ -281,7 +285,9 @@ private: ALCcontext *_context; // Position of the listener. - SGVec3d _position; + SGGeod _position_geod; + SGVec3d _position_offs; + SGVec3d _absolute_pos; // Velocity of the listener. SGVec3f _velocity; @@ -305,6 +311,7 @@ private: bool testForALUTError(string s); bool testForError(void *p, string s); + void update_pos_and_orientation(); void update_sample_config( SGSampleGroup *sound ); };