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
This commit is contained in:
@@ -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");
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
|
||||
#if defined(__APPLE__)
|
||||
# include <OpenAL/al.h>
|
||||
#elif defined(_WIN32)
|
||||
# include <al.h>
|
||||
#else
|
||||
# include <AL/al.h>
|
||||
#endif
|
||||
@@ -156,21 +158,22 @@ public:
|
||||
|
||||
protected:
|
||||
SGSoundMgr *_smgr;
|
||||
string _refname;
|
||||
bool _active;
|
||||
|
||||
private:
|
||||
float _volume;
|
||||
SGVec3d _position;
|
||||
SGVec3f _orientation;
|
||||
bool _tied_to_listener;
|
||||
|
||||
SGVec3d _position;
|
||||
SGVec3f _velocity;
|
||||
SGVec3f _orientation;
|
||||
|
||||
sample_map _samples;
|
||||
|
||||
bool testForALError(string s);
|
||||
bool testForError(void *p, string s);
|
||||
|
||||
string _refname;
|
||||
|
||||
void update_sample_config( SGSoundSample *sound );
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -47,6 +47,10 @@
|
||||
# include <OpenAL/al.h>
|
||||
# include <OpenAL/alc.h>
|
||||
# include <OpenAL/alut.h>
|
||||
#elif defined(_WIN32)
|
||||
# include <al.h>
|
||||
# include <alc.h>
|
||||
# include <AL/alut.h>
|
||||
#else
|
||||
# include <AL/al.h>
|
||||
# include <AL/alc.h>
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user