Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
c0b763c
empty initialize AudGeometry
phevosccp Feb 4, 2026
364fbb6
initialize the AKSpatialAudioSDK
phevosccp Feb 4, 2026
dcfd314
add blue file for audGeometry
phevosccp Feb 4, 2026
73e2c70
add conversion and blue file
phevosccp Feb 6, 2026
51c23c3
minor fix for surfaces
phevosccp Feb 6, 2026
878f037
uncomment and finalize RemoveGeometry, SetGeometryTransform methods
phevosccp Feb 9, 2026
c8cf4c6
fix for IDs per mesh because of the use of pointers, no overlapping
phevosccp Feb 9, 2026
93864a7
fix for geometry instance indexing
phevosccp Feb 10, 2026
a735658
add check for degenerate triangles
phevosccp Feb 11, 2026
9c69ddf
disable EnableDiffractionOnBoundaryEdges because its causing wwise to…
phevosccp Feb 12, 2026
ecbac37
AudGeometry transform conversion by validating orientation vectors an…
phevosccp Feb 18, 2026
90b494d
lower transmittion param to 0.7
phevosccp Feb 20, 2026
c50f1a9
Simplify conversion methods and move them to Utilities
phevosccp Feb 24, 2026
a36b9d9
Implement obstruction and occlusion in a new class and querry diffrac…
phevosccp Feb 24, 2026
c24eb75
change interpolation from expo to linear also reduce the time which d…
phevosccp Feb 24, 2026
1e48875
optimise init settings for spatial audio
phevosccp Feb 24, 2026
5a27c67
add cmake include for AudObstruction
phevosccp Feb 24, 2026
0efb844
minor change
phevosccp Feb 24, 2026
9c3ff3c
Orthogonalize because Wwise rejects transforms where dot(front, up)^2…
phevosccp Feb 25, 2026
7c0ce48
remove degenerate triangle checks , fix for transform
phevosccp Feb 26, 2026
6ba8016
minor docs change
phevosccp Feb 26, 2026
e26cb8f
add back declaration accidentaly removed
phevosccp Feb 26, 2026
c1be78d
add doxygen
phevosccp Feb 27, 2026
d85e32b
Rename AudObstruction to AudObstructionOcclusion and add doxygen
phevosccp Feb 27, 2026
1c2d4c0
change class name in cmakelists too
phevosccp Feb 27, 2026
5cd754f
add const for IPrioritizedObject
phevosccp Mar 2, 2026
f55b03c
various fixes for transform and geoemtry settings
phevosccp Mar 6, 2026
f075c28
simplify transform
phevosccp Mar 9, 2026
8ad6dbc
settings improvement
phevosccp Mar 10, 2026
a9061dd
switch between HQ spatial mode and basic occlusion
phevosccp Mar 11, 2026
0e664d1
1. Adds a global occlusion OFF mode 2. Exposes global transmittion lo…
phevosccp Mar 11, 2026
fc0d74f
doxygen update with modes
phevosccp Mar 11, 2026
bc93241
set occlusion by default off
phevosccp Mar 11, 2026
0a446da
update safeguard
phevosccp Mar 11, 2026
1026a22
fix listener conversion
phevosccp Mar 11, 2026
f1b8a06
make occ mode initialization default to off in AudManager
phevosccp Mar 11, 2026
67d587f
apply transmittion directly in basic mode
phevosccp Mar 13, 2026
4333c64
limit settings for basic occlusion even further
phevosccp Mar 13, 2026
14818c5
remove basic mode and keep only On/Off
phevosccp Mar 13, 2026
c264dd5
Full exposure of spatial audio occlusion settings
phevosccp Mar 13, 2026
550acf0
fix cmake issues
phevosccp Mar 13, 2026
0d07ebf
refactor AudGeometry
phevosccp Mar 16, 2026
a59cde8
also expose EnableDiffraction and EnableDiffractionOnBoundaryEdges pl…
phevosccp Mar 16, 2026
accd75d
update wrapper doxygen and remove reduntant parameter
phevosccp Mar 16, 2026
9097f39
make occlusion off by default
phevosccp Mar 16, 2026
7d99ddb
make a method that populates all spatial settings to debloat the poor…
phevosccp Mar 16, 2026
b5ef3c6
- Replace AudOcclusion enum with a bool spatial audio geometry toggle…
phevosccp Mar 16, 2026
fbc3882
Merge branch 'main' into aud-geometry-clean
phevosccp Jun 24, 2026
b31acca
Merge branch 'main' into aud-geometry-rebased
phevosccp Jun 30, 2026
1a0e8e3
Merge remote-tracking branch 'origin/main' into aud-geometry-rebased
phevosccp Jun 30, 2026
419ce41
registering the spatial audio listener should be behind the correspon…
phevosccp Jun 30, 2026
46030ff
Merge branch 'aud-geometry-rebased' of https://github.com/carbonengin…
phevosccp Jul 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ build/
# Wwise
.backup*
.cache*
build*
*.akd
*.prof
*.validationcache
Expand Down
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ ccp_add_library(CarbonAudio SHARED
src/AudEventKey.cpp
src/AudEventKey_Blue.cpp
src/AudGameObjResource.cpp
src/AudGeometry.cpp
src/AudGeometry_Blue.cpp
src/SpatialAudioSettings.cpp
src/audio2.cpp
src/AudGameObjResource_Blue.cpp
src/stdafx.cpp
Expand Down Expand Up @@ -79,6 +82,8 @@ target_sources(CarbonAudio PRIVATE
src/AudStaticDataRepository.h
src/AudUIPlayer.h
src/AudMusicPlayer.h
src/AudGeometry.h
src/SpatialAudioSettings.h
src/autoversion.h
src/DebugUtilities.h
src/LogBridge.h
Expand Down
178 changes: 178 additions & 0 deletions src/AudGeometry.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
#include "stdafx.h"
#include "AudGeometry.h"
#include "Utilities.h"
#include "Vector3.h"
#include "AudManager.h"

static CcpLogChannel_t s_ch = CCP_LOG_DEFINE_CHANNEL( "AudGeometry" );

namespace
{
std::vector<AkVertex> ConvertVertices( const std::vector<Vector3>& vertices )
{
std::vector<AkVertex> akVertices( vertices.size() );
for( size_t i = 0; i < vertices.size(); ++i )
{
const Vector3& v = vertices[i];
akVertices[i] = AkVertex( static_cast<float>( v.x ), static_cast<float>( v.y ), static_cast<float>( -v.z ) );
}
return akVertices;
}

std::vector<AkTriangle> ConvertTriangles( const std::vector<uint32_t>& indices )
{
size_t numTriangles = indices.size() / 3;
std::vector<AkTriangle> akTriangles( numTriangles );
for( size_t i = 0; i < numTriangles; ++i )
{
akTriangles[i] = AkTriangle(
static_cast<AkVertIdx>( indices[i * 3 + 0] ),
static_cast<AkVertIdx>( indices[i * 3 + 1] ),
static_cast<AkVertIdx>( indices[i * 3 + 2] ),
0
);
}
return akTriangles;
}

}

AudGeometry::AudGeometry( IRoot* lockobj )
{}

AudGeometry::~AudGeometry()
{}

void AudGeometry::ClearAllGeometry()
{
if( s_geometrySetRefCounts.empty() )
{
return;
}

if( AK::SoundEngine::IsInitialized() )
{
for( const auto& geometrySetEntry : s_geometrySetRefCounts )
{
AK::SpatialAudio::RemoveGeometry( geometrySetEntry.first );
}
}

s_geometrySetRefCounts.clear();
}

AkGeometryInstanceParams AudGeometry::MakeInstanceParams(
uint64_t geometrySetId, const Matrix& worldTransform )
{
AkGeometryInstanceParams params;
params.GeometrySetID = geometrySetId;
AkTransform transform;
RH2LH::convertTransform( worldTransform, transform );
params.PositionAndOrientation = transform;
params.Scale = RH2LH::extractScale( worldTransform );
return params;
}

void AudGeometry::SetGeometry(
uint64_t geometrySetId,
uint64_t instanceId,
const Tr2AudGeometryData& geometryData,
const Matrix& worldTransform )
{
if( geometryData.m_vertices.empty() || geometryData.m_indices.empty() )
{
return;
}

if( !g_audioManager || !g_audioManager->GetSpatialAudioGeometryEnabled() )
{
return;
}

auto it = s_geometrySetRefCounts.find( geometrySetId );
if( it == s_geometrySetRefCounts.end() )
{
std::vector<AkVertex> akVertices = ConvertVertices( geometryData.m_vertices );
std::vector<AkTriangle> akTriangles = ConvertTriangles( geometryData.m_indices );

AkAcousticSurface surface;
surface.strName = "default";
surface.textureID = AK_INVALID_UNIQUE_ID;
surface.transmissionLoss = g_audioManager->GetTransmissionLoss();

AkGeometryParams params;
params.Vertices = akVertices.data();
params.NumVertices = static_cast<AkVertIdx>( akVertices.size() );
params.Triangles = akTriangles.data();
params.NumTriangles = static_cast<AkTriIdx>( akTriangles.size() );
params.Surfaces = &surface;
params.NumSurfaces = 1;
params.EnableDiffraction = g_audioManager->GetEnableDiffraction();
params.EnableDiffractionOnBoundaryEdges = g_audioManager->GetEnableDiffractionOnBoundaryEdges();

AKRESULT result = AK::SpatialAudio::SetGeometry( geometrySetId, params );
if( result != AK_Success )
{
CCP_LOGERR_CH( s_ch, "Failed to set geometry for set %llu, AKRESULT: %d", geometrySetId, result );
return;
}

s_geometrySetRefCounts[geometrySetId] = 1;
}
else
{
it->second++;
}

AKRESULT result = AK::SpatialAudio::SetGeometryInstance(
instanceId, MakeInstanceParams( geometrySetId, worldTransform ) );
if( result != AK_Success )
{
CCP_LOGERR_CH( s_ch, "Failed to set geometry instance %llu (set %llu), AKRESULT: %d",
instanceId, geometrySetId, result );
}
}

void AudGeometry::SetGeometryTransform(
uint64_t geometrySetId,
uint64_t instanceId,
const Matrix& worldTransform )
{
if( !g_audioManager || !g_audioManager->GetSpatialAudioGeometryEnabled() )
{
return;
}

if( s_geometrySetRefCounts.find( geometrySetId ) == s_geometrySetRefCounts.end() )
{
return;
}

AKRESULT result = AK::SpatialAudio::SetGeometryInstance(
instanceId, MakeInstanceParams( geometrySetId, worldTransform ) );
if( result != AK_Success )
{
CCP_LOGERR_CH( s_ch, "Failed to update geometry instance transform for instance %llu (set %llu), AKRESULT: %d",
instanceId, geometrySetId, result );
}
}

void AudGeometry::RemoveGeometry(
uint64_t geometrySetId,
uint64_t instanceId )
{
auto it = s_geometrySetRefCounts.find( geometrySetId );
if( it == s_geometrySetRefCounts.end() )
{
return;
}

AK::SpatialAudio::RemoveGeometryInstance( instanceId );

it->second--;
if( it->second == 0 )
{
AK::SpatialAudio::RemoveGeometry( geometrySetId );
s_geometrySetRefCounts.erase( it );
}
}
91 changes: 91 additions & 0 deletions src/AudGeometry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
////////////////////////////////////////////////////////////
//
// Creator: Phevos Rinis
// Creation Date: Jan 2026
// Copyright (c) 2026 CCP Games
//

#pragma once


#include <ITr2AudGeometry.h>
#include <ITr2AudEmitter.h>

#include <unordered_map>


/**
* @brief Registers meshes from Trinity as Spatial Audio geometry sets and manages their lifecycle.
*
* Implements the ITr2AudGeometry interface to register meshes to
* AK::SpatialAudio as geeometry sets. A geometry set is a set of vertices, triangles,
* and acoustic surfaces (see AkGeometryParams). Each geometry instance represents a unique
* placement of a geometry set in the world with a transform — position,
* orientation, and scale.
*/
BLUE_CLASS(AudGeometry) :
public ITr2AudGeometry

{
public:
AudGeometry(IRoot* lockobj = NULL);
virtual ~AudGeometry();

EXPOSE_TO_BLUE();


// ITr2AudGeometry interface

/**
* @brief Registers a geometry set instance and places it in the world.
*
* @param geometrySetId Shared geometry set identifier.
* @param instanceId Unique geometry instance identifier.
* @param geometryData Triangle mesh data.
* @param worldTransform World position, orientation and scale.
*
*/
void SetGeometry(
uint64_t geometrySetId,
uint64_t instanceId,
const Tr2AudGeometryData& geometryData,
const Matrix& worldTransform) override;

/**
* @brief Updates the world transform of an existing geometry instance
*
* @param geometrySetId Geometry set the instance references.
* @param instanceId Geometry instance to update.
* @param worldTransform New world-space position, orientation and scale.
*
*/
void SetGeometryTransform(
uint64_t geometrySetId,
uint64_t instanceId,
const Matrix& worldTransform) override;

/**
* @brief Removes a geometry instance and releases the geometry set when
* its reference count reaches zero.
*
* @param geometrySetId Geometry set to dereference.
* @param instanceId Geometry instance to remove.
*
*/
void RemoveGeometry(
uint64_t geometrySetId,
uint64_t instanceId) override;

/// Removes all registered geometry sets from the Wwise engine.
static void ClearAllGeometry();

private:
/// Builds AkGeometryInstanceParams from a geometry set ID and world transform.
static AkGeometryInstanceParams MakeInstanceParams(
uint64_t geometrySetId, const Matrix& worldTransform );

/// Tracks how many active instances reference each geometry set.
inline static std::unordered_map<uint64_t, uint32_t> s_geometrySetRefCounts;
};

TYPEDEF_BLUECLASS( AudGeometry );
12 changes: 12 additions & 0 deletions src/AudGeometry_Blue.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include "stdafx.h"
#include "AudGeometry.h"

BLUE_DEFINE( AudGeometry );
BLUE_DEFINE_INTERFACE( ITr2AudGeometry );

const Be::ClassInfo* AudGeometry::ExposeToBlue()
{
EXPOSURE_BEGIN( AudGeometry, "Audio geometry for Wwise Spatial Audio occlusion/diffraction" )
MAP_INTERFACE( ITr2AudGeometry )
EXPOSURE_END()
}
20 changes: 16 additions & 4 deletions src/AudListener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "stdafx.h"
#include "AudListener.h"

#include "AudManager.h"
#include "Vector3.h"
#include "Utilities.h"

Expand All @@ -15,8 +16,12 @@ AudListener::AudListener( IRoot* lockobj ) : AudGameObjResource( LISTENER_GAME_O

AudListener::~AudListener()
{
AK::SoundEngine::RemoveDefaultListener(m_ID);
AK::SoundEngine::UnregisterGameObj(m_ID);
if( g_audioManager != nullptr && g_audioManager->GetSpatialAudioGeometryEnabled() )
{
AK::SpatialAudio::UnregisterListener( m_ID );
}
AK::SoundEngine::RemoveDefaultListener( m_ID );
AK::SoundEngine::UnregisterGameObj( m_ID );
}

void AudListener::RegisterWwiseObject()
Expand All @@ -27,6 +32,13 @@ void AudListener::RegisterWwiseObject()
{
AK::SoundEngine::RegisterGameObj(m_ID, m_name.c_str());
AK::SoundEngine::AddDefaultListener(m_ID);

// Register listener for occlusion/diffraction processing
if( g_audioManager != nullptr && g_audioManager->GetSpatialAudioGeometryEnabled() )
{
AK::SpatialAudio::RegisterListener( m_ID );
}

m_gameObjRegistered = true;
}
}
Expand All @@ -48,7 +60,7 @@ int AudListener::SetPositionHelper( const Vector3& front, const Vector3& top, co
Vector3 correctFront = Normalize( front );
Vector3 correctUp = Normalize( top );
correctUp = Normalize( Cross( Cross( correctFront, correctUp ), correctFront ) );
tmp.Set( MakeAkVector(position), MakeAkVector(correctFront), MakeAkVector(correctUp) );
tmp.Set( MakeAkVector( position ), MakeAkVector( correctFront ), MakeAkVector( correctUp ) );

// all vectors come in RH, but WWISE is LH, so convert
AkSoundPosition soundPosLH;
Expand All @@ -58,4 +70,4 @@ int AudListener::SetPositionHelper( const Vector3& front, const Vector3& top, co
}
}
return AK_Success;
}
}
Loading