Position and orientation fixes thanks to Tim Moore (finaly). Code optimizations by moving code over from SGSoundSample to SGSampleGroup which means it will only run once for every sample group instead of once for every sample.

This commit is contained in:
ehofman
2009-11-02 10:31:05 +00:00
committed by Tim Moore
parent fd90dbb123
commit 1ac944b7c1
6 changed files with 110 additions and 87 deletions

View File

@@ -37,11 +37,14 @@ SGSampleGroup::SGSampleGroup () :
_smgr(NULL),
_refname(""),
_active(false),
_changed(false),
_pause(false),
_tied_to_listener(false),
_velocity(SGVec3d::zeros()),
_orientation(SGQuatd::zeros()),
_position(SGGeod())
_position(SGVec3d::zeros()),
_pos_offs(SGVec3d::zeros()),
_position_geod(SGGeod())
{
_samples.clear();
}
@@ -50,11 +53,14 @@ SGSampleGroup::SGSampleGroup ( SGSoundMgr *smgr, const string &refname ) :
_smgr(smgr),
_refname(refname),
_active(false),
_changed(false),
_pause(false),
_tied_to_listener(false),
_velocity(SGVec3d::zeros()),
_orientation(SGQuatd::zeros()),
_position(SGGeod())
_position(SGVec3d::zeros()),
_pos_offs(SGVec3d::zeros()),
_position_geod(SGGeod())
{
_smgr->add(this, refname);
_samples.clear();
@@ -111,6 +117,12 @@ void SGSampleGroup::update( double dt ) {
i++;
}
// Update the position and orientation information for all samples.
if ( _changed ) {
update_pos_and_orientation();
_changed = false;
}
sample_map_iterator sample_current = _samples.begin();
sample_map_iterator sample_end = _samples.end();
for ( ; sample_current != sample_end; ++sample_current ) {
@@ -327,29 +339,42 @@ void SGSampleGroup::set_velocity( const SGVec3f &vel ) {
}
// set the source position of all managed sounds
void SGSampleGroup::set_position_geod( const SGGeod& pos ) {
void SGSampleGroup::update_pos_and_orientation() {
SGVec3d position = SGVec3d::fromGeod( _position_geod );
SGVec3d pos_offs = SGVec3d::fromGeod( _smgr->get_position_geod() );
if (_position != position || _pos_offs != pos_offs) {
_position = position;
_pos_offs = pos_offs;
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( _position );
sample->set_position_offset( _pos_offs );
}
}
// The rotation rotating from the earth centerd frame to
// the horizontal local frame
SGQuatd hlOr = SGQuatd::fromLonLat(_position_geod);
// Rotate the x-forward, y-right, z-down coordinate system
// into the OpenGL camera system with x-right, y-up, z-back.
SGQuatd q(-0.5, -0.5, 0.5, 0.5);
// Compute the sounds orientation and position
// wrt the earth centered frame - that is global coorinates
SGQuatd sc2body = hlOr*_orientation*q;
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_geod( pos );
}
_position = pos;
}
// set the source orientation of all managed sounds
void SGSampleGroup::set_orientation( const SGQuatd& 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 );
}
_orientation = ori;
sample->set_orientation( _orientation );
sample->set_rotation( sc2body );
}
}
@@ -382,11 +407,13 @@ void SGSampleGroup::update_sample_config( SGSoundSample *sample ) {
velocity = sample->get_velocity();
}
if (length(position -_smgr->get_position()) > 20000)
#if 0
if (length(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");
if (isNaN(velocity.data())) printf("NaN in source velocity\n");
#endif
unsigned int source = sample->get_source();
alSourcefv( source, AL_POSITION, toVec3f(position).data() );

View File

@@ -196,13 +196,17 @@ public:
* This is in the same coordinate system as OpenGL; y=up, z=back, x=right.
* @param pos Base position
*/
void set_position_geod( const SGGeod& pos );
void set_position_geod( const SGGeod& pos ) {
_position_geod = pos; _changed = true;
}
/**
* Set the orientation of this sample group.
* @param ori Quaternation containing the orientation information
*/
void set_orientation( const SGQuatd& ori );
void set_orientation( const SGQuatd& ori ) {
_orientation = ori; _changed = true;
}
/**
* Tie this sample group to the listener position, orientation and velocity
@@ -215,13 +219,17 @@ protected:
bool _active;
private:
bool _changed;
bool _pause;
float _volume;
bool _tied_to_listener;
SGVec3f _velocity;
SGQuatd _orientation;
SGGeod _position;
SGVec3d _position;
SGVec3d _pos_offs;
SGGeod _position_geod;
sample_map _samples;
std::vector< SGSharedPtr<SGSoundSample> > _removed_samples;
@@ -229,6 +237,7 @@ private:
bool testForALError(string s);
bool testForError(void *p, string s);
void update_pos_and_orientation();
void update_sample_config( SGSoundSample *sound );
};

View File

@@ -48,8 +48,10 @@ SGSoundSample::SGSoundSample() :
_direction(SGVec3d::zeros()),
_velocity(SGVec3f::zeros()),
_orientation(SGQuatd::zeros()),
_rotation(SGQuatd::zeros()),
_orivec(SGVec3f::zeros()),
_base_pos(SGGeod::fromDeg(0,0)),
_base_pos(SGVec3d::zeros()),
_base_offs(SGVec3d::zeros()),
_refname(random_string()),
_data(NULL),
_format(AL_FORMAT_MONO8),
@@ -82,8 +84,10 @@ SGSoundSample::SGSoundSample( const char *path, const char *file ) :
_direction(SGVec3d::zeros()),
_velocity(SGVec3f::zeros()),
_orientation(SGQuatd::zeros()),
_rotation(SGQuatd::zeros()),
_orivec(SGVec3f::zeros()),
_base_pos(SGGeod::fromDeg(0,0)),
_base_pos(SGVec3d::zeros()),
_base_offs(SGVec3d::zeros()),
_refname(file),
_data(NULL),
_format(AL_FORMAT_MONO8),
@@ -122,8 +126,10 @@ SGSoundSample::SGSoundSample( const unsigned char** data,
_direction(SGVec3d::zeros()),
_velocity(SGVec3f::zeros()),
_orientation(SGQuatd::zeros()),
_rotation(SGQuatd::zeros()),
_orivec(SGVec3f::zeros()),
_base_pos(SGGeod::fromDeg(0,0)),
_base_pos(SGVec3d::zeros()),
_base_offs(SGVec3d::zeros()),
_refname(random_string()),
_format(format),
_size(len),
@@ -157,8 +163,10 @@ SGSoundSample::SGSoundSample( void** data, int len, int freq, int format ) :
_direction(SGVec3d::zeros()),
_velocity(SGVec3f::zeros()),
_orientation(SGQuatd::zeros()),
_rotation(SGQuatd::zeros()),
_orivec(SGVec3f::zeros()),
_base_pos(SGGeod::fromDeg(0,0)),
_base_pos(SGVec3d::zeros()),
_base_offs(SGVec3d::zeros()),
_refname(random_string()),
_format(format),
_size(len),
@@ -192,30 +200,17 @@ SGSoundSample::~SGSoundSample() {
}
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);
// Compute the sounds orientation and position
// wrt the earth centered frame - that is global coorinates
SGQuatd sc2body = hlOr*_orientation;
// 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);
// The cartesian position of the sounds base location
SGVec3d position = SGVec3d::fromGeod(_base_pos);
_absolute_pos = position;
#if 0
_absolute_pos = _base_pos - _base_offs;
if ( _relative_pos[0] || _relative_pos[1] || _relative_pos[2] ) {
_absolute_pos += (sc2body*q).backTransform(_relative_pos);
_absolute_pos += _rotation.backTransform(_relative_pos);
}
#endif
if ( _direction[0] || _direction[1] || _direction[2] ) {
_orivec = toVec3f( (sc2body*q).backTransform(_direction) );
_orivec = toVec3f( _rotation.rotate(_direction) );
}
else
_orivec = SGVec3f::zeros();
}
string SGSoundSample::random_string() {

View File

@@ -315,11 +315,19 @@ public:
}
/**
* Set the base position of this sound in Geodetic coordinates.
* @param pos Geodetic position
* Set the base position in Cartesian coordinates
* @param pos position in Cartesian coordinates
*/
inline void set_position_geod( const SGGeod& pos ) {
_base_pos = pos; _changed = true;
inline void set_position( const SGVec3d& pos ) {
_base_pos = pos; _changed = true;
}
/**
* Set the base position offset in Cartesian coordinates
* @param offs offset in Cartesian coordinates
*/
inline void set_position_offset( const SGVec3d& offs ) {
_base_offs = offs; _changed = true;
}
/**
@@ -337,6 +345,14 @@ public:
_orientation = ori; _changed = true;
}
/**
* Set the rotation quatgernion of this sound.
* @param rotation Quaternion containing the rotation information
*/
inline void set_rotation( const SGQuatd& rotation ) {
_rotation = rotation; _changed = true;
}
/**
* Set direction of this sound relative to the orientation.
* This is in the same coordinate system as OpenGL; y=up, z=back, x=right
@@ -453,8 +469,10 @@ private:
// The position and orientation of this sound
SGQuatd _orientation; // base orientation
SGQuatd _rotation; // rotation vector for relative offsets
SGVec3f _orivec; // orientation vector for OpenAL
SGGeod _base_pos; // base position
SGVec3d _base_pos; // base position
SGVec3d _base_offs; // base offset position
std::string _refname; // name or file path
unsigned char* _data;

View File

@@ -64,11 +64,9 @@ SGSoundMgr::SGSoundMgr() :
_device(NULL),
_context(NULL),
_position_geod(SGGeod::fromDeg(0,0)),
_position_offs(SGVec3d::zeros()),
_absolute_pos(SGVec3d::zeros()),
_velocity(SGVec3d::zeros()),
_orientation(SGQuatd::zeros()),
_orient_offs(SGQuatd::zeros()),
_devname(NULL)
{
#if defined(ALUT_API_MAJOR_VERSION) && ALUT_API_MAJOR_VERSION >= 1
@@ -255,13 +253,15 @@ void SGSoundMgr::update( double dt ) {
}
if (_changed) {
#if 0
if (isNaN(_at_up_vec)) printf("NaN in listener orientation\n");
if (isNaN(toVec3f(_absolute_pos).data())) printf("NaN in listener position\n");
if (isNaN(_velocity.data())) printf("NaN in listener velocity\n");
#endif
update_pos_and_orientation();
alListenerf( AL_GAIN, _volume );
alListenerfv( AL_ORIENTATION, _at_up_vec );
alListenerfv( AL_POSITION, toVec3f(_absolute_pos).data() );
// alListenerfv( AL_POSITION, toVec3f(_absolute_pos).data() );
alListenerfv( AL_VELOCITY, _velocity.data() );
// alDopplerVelocity(340.3); // TODO: altitude dependent
testForALError("update");
@@ -462,27 +462,8 @@ 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;
#if 0
if (_position_offs[0] || _position_offs[1] || _position_offs[2] ) {
_absolute_pos += (lc2body*q).backTransform( _position_offs );
}
#endif
_absolute_pos = SGVec3d::fromGeod( _position_geod );
/**
* Description: ORIENTATION is a pair of 3-tuples representing the
@@ -494,9 +475,8 @@ void SGSoundMgr::update_pos_and_orientation() {
* behavior is undefined.
* This is in the same coordinate system as OpenGL; y=up, z=back, x=right.
*/
SGQuatd lViewOrientation = hlOr*_orient_offs*q;
SGVec3d sgv_up = -lViewOrientation.rotate(SGVec3d::e2());
SGVec3d sgv_at = lViewOrientation.rotate(SGVec3d::e3());
SGVec3d sgv_at = _orientation.backTransform(-SGVec3d::e3());
SGVec3d sgv_up = _orientation.backTransform(SGVec3d::e2());
_at_up_vec[0] = sgv_at[0];
_at_up_vec[1] = sgv_at[1];
_at_up_vec[2] = sgv_at[2];

View File

@@ -160,16 +160,13 @@ public:
_position_geod = pos; _changed = true;
}
void set_position_offset( const SGVec3d& pos ) {
_position_offs = pos; _changed = true;
}
/**
* Get the position of the sound manager.
* This is in the same coordinate system as OpenGL; y=up, z=back, x=right
* @return OpenAL listener position
*/
SGVec3d& get_position() { return _absolute_pos; }
SGGeod& get_position_geod() { return _position_geod; }
/**
* Set the velocity vector (in meters per second) of the sound manager
@@ -191,8 +188,8 @@ public:
* Set the orientation of the sound manager
* @param ori Quaternation containing the orientation information
*/
void set_orientation( const SGQuatd& ori, const SGQuatd& offs ) {
_orientation = ori; _orient_offs = offs; _changed = true;
void set_orientation( const SGQuatd& ori ) {
_orientation = ori; _changed = true;
}
/**
@@ -200,7 +197,6 @@ public:
* @return Quaternation containing the orientation information
*/
inline const SGQuatd& get_orientation() { return _orientation; }
inline const SGQuatd& get_orientation_offset() { return _orient_offs; }
/**
* Get the direction vector of the sound manager
@@ -286,7 +282,6 @@ private:
// Position of the listener.
SGGeod _position_geod;
SGVec3d _position_offs;
SGVec3d _absolute_pos;
// Velocity of the listener.
@@ -295,7 +290,6 @@ private:
// Orientation of the listener.
// first 3 elements are "at" vector, second 3 are "up" vector
SGQuatd _orientation;
SGQuatd _orient_offs;
ALfloat _at_up_vec[6];
sample_group_map _sample_groups;