Initial import of Red Planet v4.10 Win32 source
Imports the current Win32 source for the pod-racing game 'Red Planet', built on the MUNGA engine and its L4 (Win32/DirectX) platform layer: - MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend - RP / RP_L4: Red Planet game logic and Win32 application - DivLoader, Setup1: asset loader and installer project - lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies Removed stale Subversion metadata and added .gitignore/.gitattributes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,508 @@
|
||||
#include "munga.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "audloc.h"
|
||||
#include "objstrm.h"
|
||||
#include "namelist.h"
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioLocation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
//
|
||||
//#############################################################################
|
||||
//#############################################################################
|
||||
//
|
||||
AudioLocation::AudioLocation(
|
||||
PlugStream *stream,
|
||||
Entity *entity
|
||||
):
|
||||
AudioComponent(stream),
|
||||
vectorToSource(0.0f, 0.0f, 0.0f),
|
||||
locationOffset(0.0f, 0.0f, 0.0f)
|
||||
{
|
||||
AudioFrameCount next_update_delay;
|
||||
Scalar clipping_scale;
|
||||
|
||||
MemoryStream_Read(stream, &locationOffset);
|
||||
MemoryStream_Read(stream, &next_update_delay);
|
||||
MemoryStream_Read(stream, &clipping_scale);
|
||||
|
||||
AudioLocationX(entity, next_update_delay, clipping_scale);
|
||||
}
|
||||
|
||||
//
|
||||
//#############################################################################
|
||||
//#############################################################################
|
||||
//
|
||||
AudioLocation::~AudioLocation()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
//#############################################################################
|
||||
//#############################################################################
|
||||
//
|
||||
void
|
||||
AudioLocation::AudioLocationX(
|
||||
Entity *entity,
|
||||
AudioFrameCount next_update_delay,
|
||||
Scalar clipping_scale
|
||||
)
|
||||
{
|
||||
Check(entity);
|
||||
linkedEntity = entity;
|
||||
entity->AddAudioComponent(this);
|
||||
|
||||
clippingScale = clipping_scale;
|
||||
isHeadSource = False;
|
||||
distanceToSource = 1.0f;
|
||||
dopplerCents = 0;
|
||||
#if 0
|
||||
angleOffOrientation = 0.0f;
|
||||
#endif
|
||||
azimuthOfSource = 0.0f;
|
||||
distanceVolumeScale = 1.0f;
|
||||
highFreqCutoffScale = 1.0f;
|
||||
#if 0
|
||||
reverbVolumeScale = 0.0f;
|
||||
#endif
|
||||
nextUpdateDelay = next_update_delay;
|
||||
nextUpdateFrame = NullAudioFrameCount;
|
||||
}
|
||||
|
||||
//
|
||||
//#############################################################################
|
||||
//#############################################################################
|
||||
//
|
||||
Logical
|
||||
AudioLocation::TestInstance() const
|
||||
{
|
||||
Component::TestInstance();
|
||||
return True;
|
||||
}
|
||||
|
||||
//
|
||||
//#############################################################################
|
||||
//#############################################################################
|
||||
//
|
||||
void
|
||||
AudioLocation::BuildFromPage(
|
||||
PlugStream *stream,
|
||||
NameList *name_list,
|
||||
ClassID class_ID,
|
||||
ObjectID object_ID
|
||||
)
|
||||
{
|
||||
AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID);
|
||||
|
||||
MEM_STRM_WRITE_ENTRY(*stream, name_list, Point3D, location_offset);
|
||||
|
||||
//
|
||||
// Read update delay
|
||||
//
|
||||
CString update_delay_string("update_delay");
|
||||
AudioFrameCount update_delay = DefaultAudioFrameDelay;
|
||||
|
||||
if (name_list->FindData(update_delay_string) != NULL)
|
||||
{
|
||||
Check_Pointer(name_list->FindData(update_delay_string));
|
||||
Convert_From_Ascii(
|
||||
(const char *)name_list->FindData(update_delay_string),
|
||||
&update_delay
|
||||
);
|
||||
}
|
||||
MemoryStream_Write(stream, &update_delay);
|
||||
|
||||
//
|
||||
// Read culling scale
|
||||
//
|
||||
CString clipping_scale_string("clipping_scale");
|
||||
Scalar clipping_scale = 1.0f;
|
||||
|
||||
if (name_list->FindData(clipping_scale_string) != NULL)
|
||||
{
|
||||
Check_Pointer(name_list->FindData(clipping_scale_string));
|
||||
Convert_From_Ascii(
|
||||
(const char *)name_list->FindData(clipping_scale_string),
|
||||
&clipping_scale
|
||||
);
|
||||
}
|
||||
MemoryStream_Write(stream, &clipping_scale);
|
||||
}
|
||||
|
||||
//
|
||||
//#############################################################################
|
||||
//#############################################################################
|
||||
//
|
||||
void
|
||||
AudioLocation::ReceiveControl(
|
||||
AudioControlID,
|
||||
AudioControlValue
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
//#############################################################################
|
||||
//#############################################################################
|
||||
//
|
||||
Logical
|
||||
AudioLocation::IsAudioLocationClipped(AudioHead *audio_head)
|
||||
{
|
||||
Check(this);
|
||||
Check(audio_head);
|
||||
|
||||
//
|
||||
// HACK - This is a rough approximation in that it does not
|
||||
// take into account the offset of the location from the
|
||||
// center of the entity. But, this is more efficient and is OK
|
||||
// as long as the clipping sphere does not exclude the location
|
||||
// unnaturally
|
||||
//
|
||||
Entity
|
||||
*head_entity;
|
||||
Vector3D
|
||||
difference;
|
||||
Scalar
|
||||
scaled_radius;
|
||||
|
||||
head_entity = audio_head->GetHeadEntity();
|
||||
Check(head_entity);
|
||||
Check(linkedEntity);
|
||||
difference.Subtract(
|
||||
head_entity->localOrigin.linearPosition,
|
||||
linkedEntity->localOrigin.linearPosition
|
||||
);
|
||||
scaled_radius = audio_head->GetClippingRadius() * clippingScale;
|
||||
return difference.LengthSquared() > scaled_radius * scaled_radius;
|
||||
}
|
||||
|
||||
//
|
||||
//#############################################################################
|
||||
//#############################################################################
|
||||
//
|
||||
void
|
||||
AudioLocation::UpdateSpatialModelImplementation(AudioHead *audio_head)
|
||||
{
|
||||
Check(this);
|
||||
Check(audio_head);
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Get head and source entity
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
Entity *source_entity = GetLinkedEntity();
|
||||
Entity *head_entity = audio_head->GetHeadEntity();
|
||||
|
||||
Check(source_entity);
|
||||
Check(head_entity);
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Catch case of head == source at origin
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
if (
|
||||
head_entity == source_entity &&
|
||||
locationOffset == Vector3D::Identity
|
||||
)
|
||||
{
|
||||
isHeadSource = True;
|
||||
vectorToSource = Vector3D::Identity;
|
||||
distanceToSource = 0.0f;
|
||||
dopplerCents = 0;
|
||||
#if 0
|
||||
angleOffOrientation = 0.0f;
|
||||
#endif
|
||||
azimuthOfSource = 0.0f;
|
||||
distanceVolumeScale = 1.0f;
|
||||
highFreqCutoffScale = 1.0f;
|
||||
#if 0
|
||||
reverbVolumeScale = audio_head->GetReverbToDryRatio();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
isHeadSource = False;
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Get the ear to world linear matrix
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
LinearMatrix ear_to_world = audio_head->GetEarToWorld();
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Calculate vector to source with respect to local coordinate system
|
||||
// of the ears
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
{
|
||||
//
|
||||
// Get the source location offset from the entity position in
|
||||
// world coordinates
|
||||
//
|
||||
Vector3D world_location_offset;
|
||||
Vector3D world_source_location;
|
||||
|
||||
world_location_offset.Multiply(
|
||||
locationOffset,
|
||||
source_entity->localToWorld
|
||||
);
|
||||
Check(&world_location_offset);
|
||||
|
||||
world_source_location.Add(
|
||||
source_entity->localOrigin.linearPosition,
|
||||
world_location_offset
|
||||
);
|
||||
Check(&world_source_location);
|
||||
|
||||
//
|
||||
// Get the vector from the ear to the source, note that the vector
|
||||
// is not calculated by the ears offset but from the entities location
|
||||
//
|
||||
Vector3D world_ear_to_source_vector;
|
||||
|
||||
world_ear_to_source_vector.Subtract(
|
||||
world_source_location,
|
||||
head_entity->localOrigin.linearPosition
|
||||
);
|
||||
Check(&world_ear_to_source_vector);
|
||||
|
||||
//
|
||||
// Transform the vector into ear coordinates
|
||||
//
|
||||
vectorToSource.MultiplyByInverse(
|
||||
world_ear_to_source_vector,
|
||||
ear_to_world
|
||||
);
|
||||
Check(&vectorToSource);
|
||||
}
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Calculate distance to source
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
distanceToSource = vectorToSource.Length();
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Calculate normal to source
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
Vector3D normal_to_source(0.0f, 0.0f, -1.0f);
|
||||
|
||||
if (!Small_Enough(distanceToSource))
|
||||
{
|
||||
normal_to_source.Normalize(vectorToSource);
|
||||
Check(&normal_to_source);
|
||||
}
|
||||
|
||||
#if 0
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Calculate angle between the orientation of the head and source
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
if (Small_Enough(distanceToSource))
|
||||
{
|
||||
angleOffOrientation = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
UnitVector direction;
|
||||
Scalar cosine;
|
||||
|
||||
ear_to_world.GetToAxis(Z_Axis, &direction);
|
||||
Check(&direction);
|
||||
|
||||
Check(&normal_to_source);
|
||||
cosine = normal_to_source * direction;
|
||||
Clamp(cosine, -1.0f, 1.0f);
|
||||
angleOffOrientation = Arccos(cosine);
|
||||
angleOffOrientation.Normalize();
|
||||
}
|
||||
Verify(
|
||||
angleOffOrientation <= 180.0f*RAD_PER_DEG &&
|
||||
angleOffOrientation >= -180.0f*RAD_PER_DEG
|
||||
);
|
||||
#endif
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Calculate azimuth
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
if (Small_Enough(vectorToSource.x) && Small_Enough(vectorToSource.z))
|
||||
{
|
||||
azimuthOfSource = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
Verify(!(Small_Enough(vectorToSource.x) && Small_Enough(vectorToSource.z)));
|
||||
azimuthOfSource = Arctan(vectorToSource.x, vectorToSource.z);
|
||||
}
|
||||
Verify(
|
||||
azimuthOfSource <= 180.0f*RAD_PER_DEG &&
|
||||
azimuthOfSource >= -180.0f*RAD_PER_DEG
|
||||
);
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Calculate distance volume scaling
|
||||
// Apply clipping scale to rolloff distance scale, thereby giving this
|
||||
// audio location a specifc rolloff characteristic
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
if (distanceToSource > audio_head->GetAmplitudeRollOffKnee())
|
||||
{
|
||||
//
|
||||
// y = 1 / 1 + (K(x - knee))^exp
|
||||
//
|
||||
Verify(!Small_Enough(clippingScale));
|
||||
const Scalar temp =
|
||||
(audio_head->GetAmplitudeRollOffDistanceScale() / clippingScale) *
|
||||
(distanceToSource - audio_head->GetAmplitudeRollOffKnee());
|
||||
const Scalar temp2 =
|
||||
1.0f + pow(temp, audio_head->GetAmplitudeRollOffExponent());
|
||||
|
||||
Verify(!Small_Enough(temp2));
|
||||
distanceVolumeScale = 1.0f / temp2;
|
||||
}
|
||||
else
|
||||
{
|
||||
distanceVolumeScale = 1.0f;
|
||||
}
|
||||
Verify(distanceVolumeScale >= 0.0f && distanceVolumeScale <= 1.0f);
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Calculate high frequency cutoff scaling
|
||||
// Apply clipping scale to high frequency rolloff distance scale, thereby
|
||||
// giving this audio location a specifc rolloff characteristic
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
if (distanceToSource > audio_head->GetHighFrequencyRollOffKnee())
|
||||
{
|
||||
//
|
||||
// y = 1 / 1 + (K(x - knee))^exp
|
||||
//
|
||||
Verify(!Small_Enough(clippingScale));
|
||||
const Scalar temp =
|
||||
(audio_head->GetHighFrequencyRollOffDistanceScale() / clippingScale) *
|
||||
(distanceToSource - audio_head->GetHighFrequencyRollOffKnee());
|
||||
const Scalar temp2 =
|
||||
1.0f + pow(temp, audio_head->GetHighFrequencyRollOffExponent());
|
||||
|
||||
Verify(!Small_Enough(temp2));
|
||||
highFreqCutoffScale = 1.0f / temp2;
|
||||
}
|
||||
else
|
||||
{
|
||||
highFreqCutoffScale = 1.0f;
|
||||
}
|
||||
Verify(highFreqCutoffScale >= 0.0f && highFreqCutoffScale <= 1.0f);
|
||||
|
||||
#if 0
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Calculate reverb volume scaling
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
if (distanceToSource > audio_head->GetAmplitudeRollOffKnee())
|
||||
{
|
||||
const Scalar temp =
|
||||
distanceToSource - audio_head->GetAmplitudeRollOffKnee() + 1.0f;
|
||||
|
||||
reverbVolumeScale =
|
||||
audio_head->GetReverbToDryRatio() *
|
||||
pow(temp, audio_head->GetAmplitudeRollOffExponent());
|
||||
if (reverbVolumeScale > 1.0f)
|
||||
reverbVolumeScale = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
reverbVolumeScale = audio_head->GetReverbToDryRatio();
|
||||
}
|
||||
Verify(reverbVolumeScale >= 0.0f && reverbVolumeScale <= 1.0f);
|
||||
#endif
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Calculate relative velocity of source
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
Vector3D relative_velocity_temp;
|
||||
Vector3D relative_velocity;
|
||||
|
||||
relative_velocity_temp.Subtract(
|
||||
source_entity->GetWorldLinearVelocity(),
|
||||
head_entity->GetWorldLinearVelocity()
|
||||
);
|
||||
Check(&relative_velocity_temp);
|
||||
|
||||
relative_velocity.MultiplyByInverse(
|
||||
relative_velocity_temp,
|
||||
head_entity->localToWorld
|
||||
);
|
||||
Check(&relative_velocity);
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Calculate doppler shift in cents
|
||||
// cents = (c / (c - v)) / ScaleRatio
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
if (!Small_Enough(distanceToSource))
|
||||
{
|
||||
AudioPitchCents
|
||||
cents;
|
||||
Scalar speed_of_source =
|
||||
normal_to_source * relative_velocity;
|
||||
const Scalar ear_radius =
|
||||
audio_head->GetDistanceBetweenEars() * 0.5f;
|
||||
|
||||
if (distanceToSource < ear_radius)
|
||||
{
|
||||
Verify(!Small_Enough(ear_radius));
|
||||
speed_of_source *= (distanceToSource / ear_radius);
|
||||
}
|
||||
|
||||
if (CalculateDoppler(audio_head, speed_of_source, ¢s))
|
||||
{
|
||||
dopplerCents = cents;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dopplerCents = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//#############################################################################
|
||||
//#############################################################################
|
||||
//
|
||||
Logical
|
||||
AudioLocation::CalculateDoppler(
|
||||
AudioHead *audio_head,
|
||||
Scalar speed,
|
||||
AudioPitchCents *result
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check(audio_head);
|
||||
Check_Pointer(result);
|
||||
|
||||
Scalar speed_of_sound = audio_head->GetAudioSoundSpeed();
|
||||
|
||||
Clamp(speed, -speed_of_sound, speed_of_sound);
|
||||
if (!Small_Enough(speed_of_sound - speed))
|
||||
{
|
||||
*result = audio_head->GetAudioDopplerConstant() *
|
||||
( 1 - speed_of_sound / (speed_of_sound - speed) );
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
Reference in New Issue
Block a user