788 lines
20 KiB
C++
788 lines
20 KiB
C++
|
/*
|
||
|
** Command & Conquer Renegade(tm)
|
||
|
** Copyright 2025 Electronic Arts Inc.
|
||
|
**
|
||
|
** This program is free software: you can redistribute it and/or modify
|
||
|
** it under the terms of the GNU General Public License as published by
|
||
|
** the Free Software Foundation, either version 3 of the License, or
|
||
|
** (at your option) any later version.
|
||
|
**
|
||
|
** This program is distributed in the hope that it will be useful,
|
||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
** GNU General Public License for more details.
|
||
|
**
|
||
|
** You should have received a copy of the GNU General Public License
|
||
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||
|
***********************************************************************************************
|
||
|
* *
|
||
|
* Project Name : WWAudio *
|
||
|
* *
|
||
|
* $Archive:: /Commando/Code/WWAudio/Sound3D.cpp $*
|
||
|
* *
|
||
|
* Author:: Patrick Smith *
|
||
|
* *
|
||
|
* $Modtime:: 12/10/01 12:40p $*
|
||
|
* *
|
||
|
* $Revision:: 20 $*
|
||
|
* *
|
||
|
*---------------------------------------------------------------------------------------------*
|
||
|
* Functions: *
|
||
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||
|
|
||
|
|
||
|
#include "sound3d.h"
|
||
|
#include "soundbuffer.h"
|
||
|
#include "wwaudio.h"
|
||
|
#include "soundscene.h"
|
||
|
#include "utils.h"
|
||
|
#include "soundchunkids.h"
|
||
|
#include "persistfactory.h"
|
||
|
#include "chunkio.h"
|
||
|
#include "sound3dhandle.h"
|
||
|
#include "systimer.h"
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Static factories
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
SimplePersistFactoryClass<Sound3DClass, CHUNKID_SOUND3D> _Sound3DPersistFactory;
|
||
|
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
CHUNKID_VARIABLES = 0x11090955,
|
||
|
CHUNKID_BASE_CLASS
|
||
|
};
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
VARID_AUTO_CALC_VEL = 0x01,
|
||
|
VARID_CURR_VEL,
|
||
|
VARID_XXX1,
|
||
|
VARID_XXX2,
|
||
|
VARID_MAX_VOL_RADIUS,
|
||
|
VARID_IS_STATIC,
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Sound3DClass
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
Sound3DClass::Sound3DClass (void)
|
||
|
: m_bAutoCalcVel (true),
|
||
|
m_CurrentVelocity (0, 0, 0),
|
||
|
m_MaxVolRadius (0),
|
||
|
m_LastUpdate (0),
|
||
|
m_IsStatic (false),
|
||
|
m_IsTransformInitted (false)
|
||
|
{
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Sound3DClass
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
Sound3DClass::Sound3DClass (const Sound3DClass &src)
|
||
|
: m_bAutoCalcVel (true),
|
||
|
m_CurrentVelocity (0, 0, 0),
|
||
|
m_MaxVolRadius (0),
|
||
|
m_LastUpdate (0),
|
||
|
m_IsStatic (false),
|
||
|
m_IsTransformInitted (false),
|
||
|
AudibleSoundClass (src)
|
||
|
{
|
||
|
(*this) = src;
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// ~Sound3DClass
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
Sound3DClass::~Sound3DClass (void)
|
||
|
{
|
||
|
Free_Miles_Handle ();
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// operator=
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
const Sound3DClass &
|
||
|
Sound3DClass::operator= (const Sound3DClass &src)
|
||
|
{
|
||
|
m_bAutoCalcVel = src.m_bAutoCalcVel;
|
||
|
m_CurrentVelocity = src.m_CurrentVelocity;
|
||
|
m_MaxVolRadius = src.m_MaxVolRadius;
|
||
|
m_IsStatic = src.m_IsStatic;
|
||
|
m_LastUpdate = src.m_LastUpdate;
|
||
|
|
||
|
// Call the base class
|
||
|
AudibleSoundClass::operator= (src);
|
||
|
return (*this);
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Play
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
bool
|
||
|
Sound3DClass::Play (bool alloc_handle)
|
||
|
{
|
||
|
// Record our first 'tick' if we just started playing
|
||
|
if (m_State != STATE_PLAYING) {
|
||
|
m_LastUpdate = TIMEGETTIME ();
|
||
|
}
|
||
|
|
||
|
// Allow the base class to process this call
|
||
|
return AudibleSoundClass::Play (m_IsCulled == false);
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// On_Frame_Update
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
bool
|
||
|
Sound3DClass::On_Frame_Update (unsigned int milliseconds)
|
||
|
{
|
||
|
Matrix3D prev_tm = m_PrevTransform;
|
||
|
|
||
|
if (m_bDirty && (m_PhysWrapper != NULL)) {
|
||
|
m_Scene->Update_Sound (m_PhysWrapper);
|
||
|
m_bDirty = false;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Update the sound's position if its linked to a render object
|
||
|
//
|
||
|
Apply_Auto_Position ();
|
||
|
|
||
|
//
|
||
|
// Make sure the transform is initialized
|
||
|
//
|
||
|
if (m_IsTransformInitted == false) {
|
||
|
prev_tm = m_Transform;
|
||
|
}
|
||
|
|
||
|
// Disabling auto-velocity because hardware doppler is poor...
|
||
|
#if 0
|
||
|
|
||
|
//
|
||
|
// Update the current velocity if we are 'auto-calcing'.
|
||
|
//
|
||
|
if (m_bAutoCalcVel && Get_Class_ID () != CLASSID_LISTENER) {
|
||
|
Vector3 last_pos = prev_tm.Get_Translation ();
|
||
|
Vector3 curr_pos = m_Transform.Get_Translation ();
|
||
|
|
||
|
//
|
||
|
// Don't update the velocity if we haven't moved (optimization -- Miles calls
|
||
|
// can be really slow)
|
||
|
//
|
||
|
if (last_pos != curr_pos) {
|
||
|
Vector3 curr_vel;
|
||
|
|
||
|
//
|
||
|
// Extrapolate our current velocity given the last time slice and the distance
|
||
|
// we moved.
|
||
|
//
|
||
|
float secs_since_last_update = (TIMEGETTIME () - m_LastUpdate);
|
||
|
if (secs_since_last_update > 0) {
|
||
|
curr_vel = ((curr_pos - last_pos) / secs_since_last_update);
|
||
|
} else {
|
||
|
curr_vel.Set (0, 0, 0);
|
||
|
}
|
||
|
|
||
|
Set_Velocity (curr_vel);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif // doppler disable
|
||
|
|
||
|
//
|
||
|
// Remember when the last time we updated our 'auto-calc'
|
||
|
// variables.
|
||
|
//
|
||
|
m_LastUpdate = TIMEGETTIME ();
|
||
|
m_PrevTransform = m_Transform;
|
||
|
|
||
|
//
|
||
|
// If necessary, update the volume based on the distance
|
||
|
// from the edge of the dropoff radius.
|
||
|
//
|
||
|
if (m_SoundHandle != NULL) {
|
||
|
Update_Edge_Volume ();
|
||
|
}
|
||
|
|
||
|
return AudibleSoundClass::On_Frame_Update ();
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Update_Edge_Volume
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
Sound3DClass::Update_Edge_Volume (void)
|
||
|
{
|
||
|
if (m_DropOffRadius == 0.0F || As_SoundPseudo3DClass () != NULL) {
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Find the difference in the sound position and its listener's position
|
||
|
//
|
||
|
Vector3 sound_pos = m_ListenerTransform.Get_Translation () - m_Transform.Get_Translation ();
|
||
|
float distance = sound_pos.Quick_Length ();
|
||
|
|
||
|
const float FALLOFF_RANGE = 0.85F;
|
||
|
|
||
|
//
|
||
|
// Are we close to the edge of the dropoff radius?
|
||
|
//
|
||
|
float falloff_start = (m_DropOffRadius * FALLOFF_RANGE);
|
||
|
if (distance >= falloff_start && distance <= m_DropOffRadius) {
|
||
|
|
||
|
//
|
||
|
// Normalize our distance from the edge
|
||
|
//
|
||
|
float percent = (distance - falloff_start) / (m_DropOffRadius - falloff_start);
|
||
|
percent = WWMath::Clamp (1.0F - percent, 0.0F, 1.0F);
|
||
|
|
||
|
//
|
||
|
// Update the sound volume
|
||
|
//
|
||
|
Internal_Set_Volume (m_RealVolume * percent);
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Set_Transform
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
Sound3DClass::Set_Transform (const Matrix3D &transform)
|
||
|
{
|
||
|
if (transform == m_Transform) {
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Update our internal transform
|
||
|
m_PrevTransform = m_Transform;
|
||
|
m_Transform = transform;
|
||
|
Set_Dirty ();
|
||
|
|
||
|
if (m_IsTransformInitted == false) {
|
||
|
m_PrevTransform = transform;
|
||
|
m_IsTransformInitted = true;
|
||
|
}
|
||
|
|
||
|
Update_Miles_Transform ();
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Set_Listener_Transform
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
Sound3DClass::Set_Listener_Transform (const Matrix3D &tm)
|
||
|
{
|
||
|
//
|
||
|
// If the transform has changed, then cache the new transform
|
||
|
// and update the sound's position in the "Mile's" world
|
||
|
//
|
||
|
if (m_ListenerTransform != tm) {
|
||
|
m_ListenerTransform = tm;
|
||
|
|
||
|
Update_Miles_Transform ();
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Update_Miles_Transform
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
Sound3DClass::Update_Miles_Transform (void)
|
||
|
{
|
||
|
//
|
||
|
// Do we have a valid miles handle?
|
||
|
//
|
||
|
if (m_SoundHandle != NULL) {
|
||
|
|
||
|
//
|
||
|
// Build a matrix to transform coordinates from world-space to listener-space
|
||
|
//
|
||
|
Matrix3D world_to_listener_tm;
|
||
|
m_ListenerTransform.Get_Orthogonal_Inverse (world_to_listener_tm);
|
||
|
|
||
|
//
|
||
|
// Transform the object's TM into "listener-space"
|
||
|
//
|
||
|
Matrix3D listener_space_tm = world_to_listener_tm * m_Transform;
|
||
|
|
||
|
//
|
||
|
// Pass the sound's position onto miles
|
||
|
//
|
||
|
Vector3 position = listener_space_tm.Get_Translation ();
|
||
|
::AIL_set_3D_position (m_SoundHandle->Get_H3DSAMPLE (), -position.Y, position.Z, position.X);
|
||
|
|
||
|
//
|
||
|
// Pass the sound's orientation (facing) onto miles
|
||
|
//
|
||
|
Vector3 facing = listener_space_tm.Get_X_Vector ();
|
||
|
Vector3 up = listener_space_tm.Get_Z_Vector ();
|
||
|
|
||
|
::AIL_set_3D_orientation (m_SoundHandle->Get_H3DSAMPLE (),
|
||
|
-facing.Y,
|
||
|
facing.Z,
|
||
|
facing.X,
|
||
|
-up.Y,
|
||
|
up.Z,
|
||
|
up.X);
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Set_Position
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
Sound3DClass::Set_Position (const Vector3 &position)
|
||
|
{
|
||
|
//
|
||
|
// Pass the sound's position onto miles
|
||
|
//
|
||
|
if (m_Transform.Get_Translation () != position) {
|
||
|
// Update our internal transform
|
||
|
//
|
||
|
// SKB: 4/13/01 - Confirmed to be OK by Pat Smith.
|
||
|
// Took Set_Transform() outside of condition because even if sound is
|
||
|
// not playing I need to be able to change it's position.
|
||
|
// I had a problem that sounds would never be added to the scene because
|
||
|
// their positions stayed at 0,0,0 even after this Set_Postion() call.
|
||
|
m_PrevTransform = m_Transform;
|
||
|
m_Transform.Set_Translation (position);
|
||
|
Set_Dirty ();
|
||
|
|
||
|
if (m_IsTransformInitted == false) {
|
||
|
m_PrevTransform = m_Transform;
|
||
|
m_IsTransformInitted = true;
|
||
|
}
|
||
|
|
||
|
if (m_SoundHandle != NULL) {
|
||
|
|
||
|
//
|
||
|
// Transform the sound's position into 'listener-space'
|
||
|
//
|
||
|
Vector3 sound_pos = position;
|
||
|
Vector3 listener_space_pos;
|
||
|
Matrix3D::Inverse_Transform_Vector (m_ListenerTransform, sound_pos, &listener_space_pos);
|
||
|
|
||
|
//
|
||
|
// Update the object's position inside of Miles
|
||
|
//
|
||
|
::AIL_set_3D_position (m_SoundHandle->Get_H3DSAMPLE (), -listener_space_pos.Y,
|
||
|
listener_space_pos.Z, listener_space_pos.X);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Set_Velocity
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
Sound3DClass::Set_Velocity (const Vector3 &velocity)
|
||
|
{
|
||
|
MMSLockClass lock;
|
||
|
|
||
|
m_CurrentVelocity = velocity;
|
||
|
Set_Dirty ();
|
||
|
|
||
|
//
|
||
|
// Pass the sound's velocity onto miles
|
||
|
//
|
||
|
if (m_SoundHandle != NULL) {
|
||
|
|
||
|
//WWDEBUG_SAY (("Current Velocity: %.2f %.2f %.2f\n", m_CurrentVelocity.X, m_CurrentVelocity.Y, m_CurrentVelocity.Z));
|
||
|
::AIL_set_3D_velocity_vector (m_SoundHandle->Get_H3DSAMPLE (),
|
||
|
-m_CurrentVelocity.Y,
|
||
|
m_CurrentVelocity.Z,
|
||
|
m_CurrentVelocity.X);
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Set_DropOff_Radius
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
Sound3DClass::Set_DropOff_Radius (float radius)
|
||
|
{
|
||
|
//MMSLockClass lock;
|
||
|
|
||
|
m_DropOffRadius = radius;
|
||
|
Set_Dirty ();
|
||
|
|
||
|
// Pass attenuation settings onto miles
|
||
|
if (m_SoundHandle != NULL) {
|
||
|
::AIL_set_3D_sample_distances ( m_SoundHandle->Get_H3DSAMPLE (),
|
||
|
m_DropOffRadius,
|
||
|
(m_MaxVolRadius > 1.0F) ? m_MaxVolRadius : 1.0F);
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Set_Max_Vol_Radius
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
Sound3DClass::Set_Max_Vol_Radius (float radius)
|
||
|
{
|
||
|
m_MaxVolRadius = radius;
|
||
|
Set_Dirty ();
|
||
|
|
||
|
// Pass attenuation settings onto miles
|
||
|
if (m_SoundHandle != NULL) {
|
||
|
::AIL_set_3D_sample_distances ( m_SoundHandle->Get_H3DSAMPLE (),
|
||
|
m_DropOffRadius,
|
||
|
(m_MaxVolRadius > 1.0F) ? m_MaxVolRadius : 1.0F);
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Initialize_Miles_Handle
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
Sound3DClass::Initialize_Miles_Handle (void)
|
||
|
{
|
||
|
MMSLockClass lock;
|
||
|
|
||
|
// If this sound is already playing, then update its
|
||
|
// playing position to make sure we really should
|
||
|
// be playing it... (it will free the miles handle if not)
|
||
|
if (m_State == STATE_PLAYING) {
|
||
|
Update_Play_Position ();
|
||
|
}
|
||
|
|
||
|
// Do we have a valid sample handle from miles?
|
||
|
if (m_SoundHandle != NULL) {
|
||
|
|
||
|
//
|
||
|
// Pass the actual sound data onto the sample
|
||
|
//
|
||
|
m_SoundHandle->Initialize (m_Buffer);
|
||
|
|
||
|
//
|
||
|
// Record the total length of the sample in milliseconds...
|
||
|
//
|
||
|
m_SoundHandle->Get_Sample_MS_Position ((S32 *)&m_Length, NULL);
|
||
|
|
||
|
//
|
||
|
// Pass our cached settings onto miles
|
||
|
//
|
||
|
float real_volume = Determine_Real_Volume ();
|
||
|
m_SoundHandle->Set_Sample_Volume (int(real_volume * 127.0F));
|
||
|
m_SoundHandle->Set_Sample_Pan (int(m_Pan * 127.0F));
|
||
|
m_SoundHandle->Set_Sample_Loop_Count (m_LoopCount);
|
||
|
|
||
|
//
|
||
|
// Pass attenuation settings onto miles
|
||
|
//
|
||
|
::AIL_set_3D_sample_distances ( m_SoundHandle->Get_H3DSAMPLE (),
|
||
|
m_DropOffRadius,
|
||
|
(m_MaxVolRadius > 1.0F) ? m_MaxVolRadius : 1.0F);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Assign the 3D effects level accordingly (for reverb, etc)
|
||
|
//
|
||
|
::AIL_set_3D_sample_effects_level (m_SoundHandle->Get_H3DSAMPLE (),
|
||
|
WWAudioClass::Get_Instance ()->Get_Effects_Level ());
|
||
|
|
||
|
//
|
||
|
// Pass the sound's position and orientation onto Miles
|
||
|
//
|
||
|
Update_Miles_Transform ();
|
||
|
|
||
|
//
|
||
|
// Apply the pitch factor (if necessary)
|
||
|
//
|
||
|
if (m_PitchFactor != 1.0F) {
|
||
|
Set_Pitch_Factor (m_PitchFactor);
|
||
|
}
|
||
|
|
||
|
// If this sound is already playing (and just now got a handle)
|
||
|
// then make sure we start it.
|
||
|
if (m_State == STATE_PLAYING) {
|
||
|
m_SoundHandle->Start_Sample ();
|
||
|
|
||
|
// Update the loop count based on the number of loops left
|
||
|
m_SoundHandle->Set_Sample_Loop_Count (m_LoopsLeft);
|
||
|
}
|
||
|
|
||
|
// Seek to the position of the sound where we last left off.
|
||
|
// For example, this sound could have gotten bumped due to a low priority,
|
||
|
// but is now back and ready to resume at the position it would have been
|
||
|
// at if it was never bumped.
|
||
|
Seek (m_CurrentPosition);
|
||
|
|
||
|
// Associate this object instance with the handle
|
||
|
m_SoundHandle->Set_Sample_User_Data (INFO_OBJECT_PTR, (S32)this);
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Allocate_Miles_Handle
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
Sound3DClass::Allocate_Miles_Handle (void)
|
||
|
{
|
||
|
//MMSLockClass lock;
|
||
|
|
||
|
//
|
||
|
// If we need to, get a play-handle from the audio system
|
||
|
//
|
||
|
if (m_SoundHandle == NULL) {
|
||
|
Set_Miles_Handle ((MILES_HANDLE)WWAudioClass::Get_Instance ()->Get_3D_Sample (*this));
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Add_To_Scene
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
Sound3DClass::Add_To_Scene (bool start_playing)
|
||
|
{
|
||
|
SoundSceneClass *scene = WWAudioClass::Get_Instance ()->Get_Sound_Scene ();
|
||
|
if ((scene != NULL) && (m_Scene == NULL)) {
|
||
|
|
||
|
// Determine what culling system this sound belongs to
|
||
|
if (m_IsStatic) {
|
||
|
scene->Add_Static_Sound (this, start_playing);
|
||
|
} else {
|
||
|
scene->Add_Sound (this, start_playing);
|
||
|
}
|
||
|
m_Scene = scene;
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Remove_From_Scene
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
Sound3DClass::Remove_From_Scene (void)
|
||
|
{
|
||
|
if (m_Scene != NULL) {
|
||
|
|
||
|
// Determine what culling system this sound belongs to
|
||
|
if (m_IsStatic) {
|
||
|
m_Scene->Remove_Static_Sound (this);
|
||
|
} else {
|
||
|
m_Scene->Remove_Sound (this);
|
||
|
}
|
||
|
|
||
|
m_Scene = NULL;
|
||
|
m_PhysWrapper = NULL;
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// On_Loop_End
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
Sound3DClass::On_Loop_End (void)
|
||
|
{
|
||
|
// Allow the base class to process this message
|
||
|
AudibleSoundClass::On_Loop_End ();
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Get_Factory
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////////
|
||
|
const PersistFactoryClass &
|
||
|
Sound3DClass::Get_Factory (void) const
|
||
|
{
|
||
|
return _Sound3DPersistFactory;
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Save
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
bool
|
||
|
Sound3DClass::Save (ChunkSaveClass &csave)
|
||
|
{
|
||
|
csave.Begin_Chunk (CHUNKID_BASE_CLASS);
|
||
|
AudibleSoundClass::Save (csave);
|
||
|
csave.End_Chunk ();
|
||
|
|
||
|
csave.Begin_Chunk (CHUNKID_VARIABLES);
|
||
|
|
||
|
WRITE_MICRO_CHUNK (csave, VARID_AUTO_CALC_VEL, m_bAutoCalcVel);
|
||
|
WRITE_MICRO_CHUNK (csave, VARID_CURR_VEL, m_CurrentVelocity);
|
||
|
|
||
|
WRITE_MICRO_CHUNK (csave, VARID_MAX_VOL_RADIUS, m_MaxVolRadius);
|
||
|
WRITE_MICRO_CHUNK (csave, VARID_IS_STATIC, m_IsStatic);
|
||
|
|
||
|
csave.End_Chunk ();
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Load
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
bool
|
||
|
Sound3DClass::Load (ChunkLoadClass &cload)
|
||
|
{
|
||
|
while (cload.Open_Chunk ()) {
|
||
|
switch (cload.Cur_Chunk_ID ()) {
|
||
|
|
||
|
case CHUNKID_BASE_CLASS:
|
||
|
AudibleSoundClass::Load (cload);
|
||
|
break;
|
||
|
|
||
|
case CHUNKID_VARIABLES:
|
||
|
{
|
||
|
//
|
||
|
// Read all the variables from their micro-chunks
|
||
|
//
|
||
|
while (cload.Open_Micro_Chunk ()) {
|
||
|
switch (cload.Cur_Micro_Chunk_ID ()) {
|
||
|
|
||
|
READ_MICRO_CHUNK (cload, VARID_AUTO_CALC_VEL, m_bAutoCalcVel);
|
||
|
READ_MICRO_CHUNK (cload, VARID_CURR_VEL, m_CurrentVelocity);
|
||
|
READ_MICRO_CHUNK (cload, VARID_MAX_VOL_RADIUS, m_MaxVolRadius);
|
||
|
READ_MICRO_CHUNK (cload, VARID_IS_STATIC, m_IsStatic);
|
||
|
}
|
||
|
|
||
|
cload.Close_Micro_Chunk ();
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
cload.Close_Chunk ();
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Set_Miles_Handle
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
void
|
||
|
Sound3DClass::Set_Miles_Handle (MILES_HANDLE handle)
|
||
|
{
|
||
|
//
|
||
|
// Start fresh
|
||
|
//
|
||
|
Free_Miles_Handle ();
|
||
|
|
||
|
//
|
||
|
// Is our data valid?
|
||
|
//
|
||
|
if (handle != INVALID_MILES_HANDLE && m_Buffer != NULL) {
|
||
|
|
||
|
//
|
||
|
// Configure the sound handle
|
||
|
//
|
||
|
m_SoundHandle = new Sound3DHandleClass;
|
||
|
m_SoundHandle->Set_Miles_Handle (handle);
|
||
|
|
||
|
//
|
||
|
// Use this new handle
|
||
|
//
|
||
|
Initialize_Miles_Handle ();
|
||
|
}
|
||
|
|
||
|
return ;
|
||
|
}
|