diff --git a/.run/SteamAudioGodot.run.xml b/.run/SteamAudioGodot.run.xml
new file mode 100644
index 0000000..d13c9e0
--- /dev/null
+++ b/.run/SteamAudioGodot.run.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 149faca..7fd96a0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -134,7 +134,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE
)
# Installation setup
-set(INSTALL_DIR "${CMAKE_SOURCE_DIR}/install/${PROJECT_NAME}/")
+set(INSTALL_DIR "${CMAKE_SOURCE_DIR}/demo/addons/${PROJECT_NAME}/")
message(STATUS "Install directory: ${INSTALL_DIR}")
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION ${INSTALL_DIR}/${LIB_DIR}
diff --git a/demo/.editorconfig b/demo/.editorconfig
new file mode 100644
index 0000000..f28239b
--- /dev/null
+++ b/demo/.editorconfig
@@ -0,0 +1,4 @@
+root = true
+
+[*]
+charset = utf-8
diff --git a/demo/.gitattributes b/demo/.gitattributes
new file mode 100644
index 0000000..8ad74f7
--- /dev/null
+++ b/demo/.gitattributes
@@ -0,0 +1,2 @@
+# Normalize EOL for all files that Git considers text files.
+* text=auto eol=lf
diff --git a/demo/.gitignore b/demo/.gitignore
new file mode 100644
index 0000000..0af181c
--- /dev/null
+++ b/demo/.gitignore
@@ -0,0 +1,3 @@
+# Godot 4+ specific ignores
+.godot/
+/android/
diff --git a/demo/icon.svg b/demo/icon.svg
new file mode 100644
index 0000000..c6bbb7d
--- /dev/null
+++ b/demo/icon.svg
@@ -0,0 +1 @@
+
diff --git a/demo/icon.svg.import b/demo/icon.svg.import
new file mode 100644
index 0000000..de936f7
--- /dev/null
+++ b/demo/icon.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://ch0aljsxfwrd6"
+path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://icon.svg"
+dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/demo/project.godot b/demo/project.godot
new file mode 100644
index 0000000..850d8a4
--- /dev/null
+++ b/demo/project.godot
@@ -0,0 +1,15 @@
+; Engine configuration file.
+; It's best edited using the editor UI and not directly,
+; since the parameters that go here are not all obvious.
+;
+; Format:
+; [section] ; section goes between []
+; param=value ; assign values to parameters
+
+config_version=5
+
+[application]
+
+config/name="demo"
+config/features=PackedStringArray("4.5", "Forward Plus")
+config/icon="res://icon.svg"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 32ced1e..ad4dc0a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -3,19 +3,14 @@
target_sources( ${PROJECT_NAME}
PRIVATE
register_types.cpp
- register_types.h
steam_audio.cpp
- steam_audio.h
+ steam_audio_server.cpp
steam_audio_material.cpp
- steam_audio_material.h
- steam_audio_listener.h
steam_audio_listener.cpp
steam_audio_source.cpp
- steam_audio_source.h
- steam_audio_dynamic_mesh.h
steam_audio_dynamic_mesh.cpp
steam_audio_static_mesh.cpp
- steam_audio_static_mesh.h
+ steam_audio_source.cpp
)
target_include_directories( ${PROJECT_NAME}
diff --git a/src/register_types.cpp b/src/register_types.cpp
index 8235627..7e78895 100644
--- a/src/register_types.cpp
+++ b/src/register_types.cpp
@@ -1,29 +1,36 @@
-#include "register_types.h"
+#include "register_types.hpp"
using namespace godot;
+SteamAudioServer *srv;
+
void initialize_steam_audio(ModuleInitializationLevel p_level) {
- if (p_level!=MODULE_INITIALIZATION_LEVEL_SCENE) {
+ if (p_level!=MODULE_INITIALIZATION_LEVEL_SCENE && p_level != MODULE_INITIALIZATION_LEVEL_SERVERS) {
return;
}
- register_steam_audio_settings();
- GDREGISTER_CLASS(SteamAudio);
- GDREGISTER_CLASS(SteamAudioMaterial);
- GDREGISTER_RUNTIME_CLASS(SteamAudioListener);
- GDREGISTER_RUNTIME_CLASS(SteamAudioSource);
- GDREGISTER_RUNTIME_CLASS(SteamAudioStaticMesh)
- GDREGISTER_RUNTIME_CLASS(SteamAudioDynamicMesh)
+ if (p_level == MODULE_INITIALIZATION_LEVEL_SERVERS) {
+ GDREGISTER_CLASS(SteamAudioServer);
+ srv = memnew(SteamAudioServer);
+ }
+ if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) {
+ register_steam_audio_settings();
+ GDREGISTER_RUNTIME_CLASS(SteamAudioMaterial);
+ GDREGISTER_RUNTIME_CLASS(SteamAudioListener);
+ GDREGISTER_RUNTIME_CLASS(SteamAudioSource);
+ GDREGISTER_RUNTIME_CLASS(SteamAudioStaticMesh);
+ GDREGISTER_RUNTIME_CLASS(SteamAudioDynamicMesh);
+ }
}
void uninitialize_steam_audio(ModuleInitializationLevel p_level) {
- if (p_level!=MODULE_INITIALIZATION_LEVEL_SCENE) {
- return;
+ if (p_level == MODULE_INITIALIZATION_LEVEL_SERVERS) {
+ memdelete(srv);
}
}
void register_steam_audio_settings() {
- ProjectSettings *settings = ProjectSettings::get_singleton();
+ ProjectSettings *settings = ProjectSettings::get_singleton();
{//Raytracer enum
settings->set("steam_audio/ray_tracer/RayTracer",0);
Dictionary info;
@@ -33,7 +40,7 @@ void register_steam_audio_settings() {
info["hint_string"] = "Steam RT,Embree RT";
info["usage"] = PROPERTY_USAGE_DEFAULT;
settings->add_property_info(info);
- settings->set("steam_audio/ray_tracer/RayTracer",1);
+ settings->set_initial_value("steam_audio/ray_tracer/RayTracer",1);
}
{//spatialization mode enum
@@ -49,7 +56,31 @@ void register_steam_audio_settings() {
}
{
- settings->set("steam_audio/spatializer/HRTF/Volume",0);
+ settings->set("steam_audio/spatializer/HRTF/HRTF_Type",0);
+ Dictionary info;
+ info["name"] = "steam_audio/spatializer/HRTF/HRTF_Type";
+ info["type"] = Variant::INT;
+ info["hint"] = PROPERTY_HINT_ENUM;
+ info["hint_string"] = "Default,Custom";
+ info["usage"] = PROPERTY_USAGE_DEFAULT;
+ settings->add_property_info(info);
+ settings->set_initial_value("steam_audio/spatializer/HRTF/HRTF_Type",0);
+ }
+
+ {
+ settings->set("steam_audio/spatializer/HRTF/Sofa_File",0.0f);
+ Dictionary info;
+ info["name"] = "steam_audio/spatializer/HRTF/Sofa_File";
+ info["type"] = Variant::STRING;
+ info["hint"] = PROPERTY_HINT_FILE;
+ info["hint_string"] = "";
+ info["usage"] = PROPERTY_USAGE_DEFAULT;
+ settings->add_property_info(info);
+ settings->set_initial_value("steam_audio/spatializer/HRTF/Sofa_File","");
+ }
+
+ {
+ settings->set("steam_audio/spatializer/HRTF/Volume",1.0f);
Dictionary info;
info["name"] = "steam_audio/spatializer/HRTF/Volume";
info["type"] = Variant::FLOAT;
@@ -57,9 +88,42 @@ void register_steam_audio_settings() {
info["hint_string"] = "0.0,1.0,.01,slider";
info["usage"] = PROPERTY_USAGE_DEFAULT;
settings->add_property_info(info);
- settings->set("steam_audio/spatializer/HRTF/Volume",1);
+ settings->set_initial_value("steam_audio/spatializer/HRTF/Volume",1.0f);
}
+ {
+ settings->set("steam_audio/spatializer/HRTF/Norm_Type",0);
+ Dictionary info;
+ info["name"] = "steam_audio/spatializer/HRTF/Norm_Type";
+ info["type"] = Variant::INT;
+ info["hint"] = PROPERTY_HINT_ENUM;
+ info["hint_string"] = "NONE,Root Mean Squared";
+ info["usage"] = PROPERTY_USAGE_DEFAULT;
+ settings->add_property_info(info);
+ settings->set_initial_value("steam_audio/spatializer/HRTF/Norm_Type",0);
+ }
+
+ {
+ settings->set("steam_audio/sampling_rate",0);
+ Dictionary info;
+ info["name"] = "steam_audio/sampling_rate";
+ info["type"] = Variant::INT;
+ info["hint"] = PROPERTY_HINT_ENUM;
+ info["hint_string"] = "44100:44100,48000:48000";
+ settings->add_property_info(info);
+ settings->set_initial_value("steam_audio/sampling_rate",48000);
+ }
+
+ {
+ settings->set("steam_audio/buffer_size",0);
+ Dictionary info;
+ info["name"] = "steam_audio/buffer_size";
+ info["type"] = Variant::INT;
+ info["hint"] = PROPERTY_HINT_ENUM;
+ info["hint_string"] = "512:512,1024:1024";
+ settings->add_property_info(info);
+ settings->set_initial_value("steam_audio/buffer_size",1024);
+ }
}
extern "C" {
diff --git a/src/register_types.h b/src/register_types.hpp
similarity index 61%
rename from src/register_types.h
rename to src/register_types.hpp
index 914b7ac..f0d916c 100644
--- a/src/register_types.h
+++ b/src/register_types.hpp
@@ -3,12 +3,13 @@
#include
#include
-#include "steam_audio.h"
-#include "steam_audio_listener.h"
-#include "steam_audio_material.h"
-#include "steam_audio_source.h"
-#include "steam_audio_static_mesh.h"
-#include "steam_audio_dynamic_mesh.h"
+#include "steam_audio.hpp"
+#include "steam_audio_dynamic_mesh.hpp"
+#include "steam_audio_source.hpp"
+#include "steam_audio_listener.hpp"
+#include "steam_audio_server.hpp"
+#include "steam_audio_material.hpp"
+#include "steam_audio_static_mesh.hpp"
using namespace godot;
diff --git a/src/steam_audio.cpp b/src/steam_audio.cpp
index 3eb6cc4..e976daf 100644
--- a/src/steam_audio.cpp
+++ b/src/steam_audio.cpp
@@ -1,118 +1,32 @@
-#include "steam_audio.h"
+#include "steam_audio.hpp"
using namespace godot;
-IPLContext global_context = nullptr;
-IPLScene global_scene = nullptr;
-IPLSimulator global_simulator = nullptr;
-SteamAudio::SteamAudio() {
- steam_audio=this;
- initialize();
+ SteamAudio::SteamAudio() {
}
- SteamAudio::~SteamAudio()
-{
- steam_audio = nullptr;
- shutdown();
-}
-
void SteamAudio::_bind_methods() {
- ClassDB::bind_method(D_METHOD("initialize"), &SteamAudio::initialize);
- ClassDB::bind_method(D_METHOD("shutdown"), &SteamAudio::shutdown);
-
- ClassDB::bind_method(D_METHOD("get_hrtf"), &SteamAudio::get_hrtf);
- ClassDB::bind_method(D_METHOD("get_hrtf_settings"), &SteamAudio::get_hrtf_settings);
-
- ClassDB::bind_method(D_METHOD("get_simulator"), &SteamAudio::get_simulator);
- ClassDB::bind_method(D_METHOD("get_simulation_settings"), &SteamAudio::get_simulation_settings);
-
- ClassDB::bind_method(D_METHOD("get_context"),&SteamAudio::get_context);
- ClassDB::bind_method(D_METHOD("get_context_settings"),&SteamAudio::get_context_settings);
-
- ClassDB::bind_method(D_METHOD("get_scene"), &SteamAudio::get_scene);
- ClassDB::bind_method(D_METHOD("get_scene_settings"), &SteamAudio::get_scene_settings);
-
- ClassDB::bind_method(D_METHOD("get_embree_device"), &SteamAudio::get_embree_device);
- ClassDB::bind_method(D_METHOD("get_embree_device_settings"),&SteamAudio::get_embree_device_settings);
-}
-
-bool SteamAudio::initialize() {
- ctx_settings.version=STEAMAUDIO_VERSION;
- IPLContext ctx = nullptr;
- iplContextCreate(&ctx_settings, &ctx);
- iplSceneCreate(ctx,&scene_settings,&scene);
- iplSimulatorCreate(ctx,&simulation_settings,&simulator);
- int ray_mode = proj_settings->get_setting("steam_audio/ray_tracer");
- switch (ray_mode) {
- case 0://steam rt
- break;
- case 1: // embree rt
- iplEmbreeDeviceCreate(ctx,&embree_device_settings,&embree_device);
- break;
- default:
- ERR_PRINT("Unknown Raytracer");
- return false;
- }
- int spat_mode = proj_settings->get_setting("steam_audio/spatializer");
- switch (spat_mode) {
- case 0://panning
- break;
- case 1://HRTF
- iplHRTFCreate(ctx,&audio_settings,&hrtf_settings,&hrtf);
- break;
- case 2://ambisonic pan
- break;
- case 3://ambisonic binaural
- break;
- default:
- ERR_PRINT("Unknown Spatializer");
- return false;
- }
- print_line("Steam Audio Successfully initialized");
-
- return true;
-}
-
-void SteamAudio::update_static_scene() {
-
-}
-
-void SteamAudio::update_dynamic_scene() {
-
-}
-
-
-void SteamAudio::shutdown() {
- if (embree_device != nullptr) {
- iplEmbreeDeviceRelease(&embree_device);
- embree_device = nullptr;
- }
- if (ctx != nullptr) {
- iplContextRelease(&ctx);
- ctx = nullptr;
- }
- if (hrtf != nullptr) {
- iplHRTFRelease(&hrtf);
- hrtf = nullptr;
- }
- if (simulator != nullptr) {
- iplSimulatorRelease(&simulator);
- simulator = nullptr;
- }
- if (scene!= nullptr) {
- iplSceneRelease(&scene);
- scene = nullptr;
- }
-}
-bool SteamAudio::build_scene() {
- update_dynamic_scene();
- update_static_scene();
-}
-Array SteamAudio::get_nodes_with_child() {
}
+IPLContextSettings SteamAudio::ctx_default_settings = {
+ STEAMAUDIO_VERSION,
+ nullptr,
+ nullptr,
+ nullptr,
+ IPL_SIMDLEVEL_NEON,
+};
+IPLSimulationSettings SteamAudio::simulation_default_settings = {
+};
+IPLAudioSettings SteamAudio::audio_default_settings = {
+};
+IPLSceneSettings SteamAudio::scene_default_settings = {
+};
+IPLEmbreeDeviceSettings SteamAudio::embree_device_default_settings = {
+};
+IPLHRTFSettings SteamAudio::hrtf_default_settings = {
+};
IPLCoordinateSpace3 SteamAudio::godot_to_ipl_space(const Transform3D &t) {
IPLCoordinateSpace3 s{};
@@ -129,7 +43,6 @@ IPLCoordinateSpace3 SteamAudio::godot_to_ipl_space(const Transform3D &t) {
return s;
}
-
// Steam Audio → Godot space
Transform3D SteamAudio::ipl_space_to_godot(const IPLCoordinateSpace3 &s) {
// construct a Basis from column vectors
@@ -142,10 +55,45 @@ Transform3D SteamAudio::ipl_space_to_godot(const IPLCoordinateSpace3 &s) {
return Transform3D(b, Vector3(s.origin.x, s.origin.y, s.origin.z));
}
-void SteamAudio::_ready() {
- reflections_thread;
- build_scene();
- iplSimulatorRunDirect(simulator);
+IPLMatrix4x4 SteamAudio::transform_to_ipl_matrix(const Transform3D &t) {
+ // First compute the three axes using Godot’s forward = –Z
+ Vector3 right = t.basis.xform(Vector3(1, 0, 0));
+ Vector3 up = t.basis.xform(Vector3(0, 1, 0));
+ Vector3 forward = t.basis.xform(Vector3(0, 0, -1)); // ← same as .ahead above
+ IPLMatrix4x4 m{};
+ // Row-major: m[row][col]
+
+ // X axis → column 0
+ m.elements[0][0] = right.x; m.elements[1][0] = right.y; m.elements[2][0] = right.z;
+
+ // Y axis → column 1
+ m.elements[0][1] = up.x; m.elements[1][1] = up.y; m.elements[2][1] = up.z;
+
+ // Forward (–Z) → column 2
+ m.elements[0][2] = forward.x; m.elements[1][2] = forward.y; m.elements[2][2] = forward.z;
+
+ // Translation → column 3
+ m.elements[0][3] = t.origin.x; m.elements[1][3] = t.origin.y; m.elements[2][3] = t.origin.z;
+
+ // Bottom row for homogeneous
+ m.elements[3][0] = 0; m.elements[3][1] = 0; m.elements[3][2] = 0; m.elements[3][3] = 1;
+
+ return m;
}
+IPLMaterial SteamAudio::to_ipl_material(const SteamMaterial &material) {
+ IPLMaterial iplmaterial ={};
+
+ iplmaterial.absorption[0] = material.absorption.x;
+ iplmaterial.absorption[1] = material.absorption.y;
+ iplmaterial.absorption[2] = material.absorption.z;
+
+ iplmaterial.scattering = material.scattering;
+
+ iplmaterial.transmission[0] = material.transmission.x;
+ iplmaterial.transmission[1] = material.transmission.y;
+ iplmaterial.transmission[2] = material.transmission.z;
+
+ return iplmaterial;
+}
diff --git a/src/steam_audio.h b/src/steam_audio.h
deleted file mode 100644
index c07d078..0000000
--- a/src/steam_audio.h
+++ /dev/null
@@ -1,81 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "steam_audio_dynamic_mesh.h"
-#include "steam_audio_listener.h"
-#include "steam_audio_material.h"
-#include "steam_audio_source.h"
-#include "steam_audio_static_mesh.h"
-
-
-using namespace godot;
-
-class SteamAudio : public Node
-{
- GDCLASS( SteamAudio, Node ) // NOLINT(modernize-use-auto, hicpp-use-auto)
-
-private:
- IPLContextSettings ctx_settings{};
- IPLAudioSettings audio_settings{};
- IPLContext ctx = nullptr;
- IPLEmbreeDeviceSettings embree_device_settings{};
- IPLEmbreeDevice embree_device = nullptr;
- IPLScene scene = nullptr;
- IPLSceneSettings scene_settings{};
- IPLSimulationSettings simulation_settings{};
- IPLSimulator simulator = nullptr;
- IPLStaticMesh mesh = nullptr;
- IPLHRTFSettings hrtf_settings{};
- IPLHRTF hrtf = nullptr;
- ProjectSettings *proj_settings = ProjectSettings::get_singleton();
- Array dynamic_geometry;
- Array static_geometry;
- Array sources;
- Ref reflections_thread;
- Ref pathing_thread;
-protected:
- static void _bind_methods();
- void _ready() override;
-public:
- static SteamAudio *steam_audio;
- SteamAudio();
- ~SteamAudio() override;
- bool initialize();
- void shutdown();
-
- bool build_scene();
-
- void update_static_scene();
- void update_dynamic_scene();
-
- static Transform3D ipl_space_to_godot(const IPLCoordinateSpace3 &p_space);
- static IPLCoordinateSpace3 godot_to_ipl_space(const Transform3D &p_transform);
-
- [[nodiscard]] IPLContext get_context() const{return ctx;}
-
- [[nodiscard]] IPLEmbreeDevice get_embree_device() const{return embree_device;}
- [[nodiscard]] IPLEmbreeDeviceSettings get_embree_device_settings() const{return embree_device_settings;}
-
- [[nodiscard]] IPLScene get_scene() const{return scene;}
- [[nodiscard]] IPLSceneSettings get_scene_settings() const{return scene_settings;}
-
- [[nodiscard]] IPLSimulator get_simulator() const{return simulator;}
- [[nodiscard]] IPLSimulationSettings get_simulation_settings() const{return simulation_settings;}
-
- [[nodiscard]] IPLHRTF get_hrtf() const{return hrtf;}
- [[nodiscard]] IPLHRTFSettings get_hrtf_settings() const{return hrtf_settings;}
-
- [[nodiscard]] IPLContextSettings get_context_settings() const{return ctx_settings;}
-
-};
\ No newline at end of file
diff --git a/src/steam_audio.hpp b/src/steam_audio.hpp
new file mode 100644
index 0000000..fcfa695
--- /dev/null
+++ b/src/steam_audio.hpp
@@ -0,0 +1,61 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "steam_audio_listener.hpp"
+#include "steam_audio_material.hpp"
+
+using namespace godot;
+
+enum ProxyMode {
+ PROXY_NONE = 0,
+ PROXY_AUTO = 1,
+ PROXY_CUSTOM = 2,
+};
+
+class SteamAudio : public Resource
+{
+ GDCLASS( SteamAudio, Resource ) // NOLINT(modernize-use-auto, hicpp-use-auto)
+
+private:
+ static IPLContextSettings ctx_default_settings;
+ static IPLAudioSettings audio_default_settings;
+ static IPLEmbreeDeviceSettings embree_device_default_settings;
+ static IPLSceneSettings scene_default_settings;
+ static IPLSimulationSettings simulation_default_settings;
+ static IPLHRTFSettings hrtf_default_settings;
+ ProjectSettings *proj_settings = ProjectSettings::get_singleton();
+
+protected:
+ static void _bind_methods();
+
+public:
+ static SteamAudio *steam_audio;
+
+ SteamAudio();
+ ~SteamAudio() override = default;
+
+ static Transform3D ipl_space_to_godot(const IPLCoordinateSpace3 &p_space);
+ static IPLMatrix4x4 transform_to_ipl_matrix(const Transform3D &t);
+ static IPLMaterial to_ipl_material(const SteamMaterial &);
+
+ static IPLCoordinateSpace3 godot_to_ipl_space(const Transform3D &p_transform);
+
+ [[nodiscard]] static IPLEmbreeDeviceSettings get_embree_device_settings() {return embree_device_default_settings;}
+
+ [[nodiscard]] static IPLSceneSettings get_scene_settings() {return scene_default_settings;}
+
+ [[nodiscard]] static IPLSimulationSettings get_simulation_settings() {return simulation_default_settings;}
+
+ [[nodiscard]] static IPLHRTFSettings get_hrtf_settings() {return hrtf_default_settings;}
+
+ [[nodiscard]] static IPLContextSettings get_context_settings() {return ctx_default_settings;}
+
+};
\ No newline at end of file
diff --git a/src/steam_audio_dynamic_mesh.cpp b/src/steam_audio_dynamic_mesh.cpp
index f84184e..16b018c 100644
--- a/src/steam_audio_dynamic_mesh.cpp
+++ b/src/steam_audio_dynamic_mesh.cpp
@@ -1,92 +1,283 @@
-#include "steam_audio_dynamic_mesh.h"
-#include "steam_audio_globals.h" // holds global_context & global_scene
+// steam_audio_static_mesh.cpp
+#include "steam_audio_dynamic_mesh.hpp"
using namespace godot;
-SteamAudioDynamicMesh::SteamAudioDynamicMesh() {}
-SteamAudioDynamicMesh::~SteamAudioDynamicMesh() {
- if (instanced_mesh) {
- // remove & release the instance
- iplInstancedMeshRemove(instanced_mesh, global_scene);
- iplInstancedMeshRelease(&instanced_mesh);
- }
- if (proxy_subscene) {
- iplSceneRelease(&proxy_subscene);
- }
+Vector SteamAudioDynamicMesh::_instances;
+
+SteamAudioDynamicMesh::SteamAudioDynamicMesh() {
+ _instances.push_back(this);
}
+SteamAudioDynamicMesh::~SteamAudioDynamicMesh() {
+ _instances.erase(this);
+}
+
+const Vector &SteamAudioDynamicMesh::get_all_dynamic_meshes() {
+ return _instances;
+}
+
+
void SteamAudioDynamicMesh::_bind_methods() {
- // no exposed properties for now
+ ClassDB::bind_method(D_METHOD("set_proxy_mode", "mode"), &SteamAudioDynamicMesh::set_proxy_mode);
+ ClassDB::bind_method(D_METHOD("get_proxy_mode"), &SteamAudioDynamicMesh::get_proxy_mode);
+ ADD_PROPERTY(
+ PropertyInfo(Variant::INT, "proxy_mode",PROPERTY_HINT_ENUM,"None,Convex,Custom"), "set_proxy_mode","get_proxy_mode");
+
+ ClassDB::bind_method(D_METHOD("set_custom_proxy_mesh", "mesh"), &SteamAudioDynamicMesh::set_custom_proxy_mesh);
+ ClassDB::bind_method(D_METHOD("get_custom_proxy_mesh"), &SteamAudioDynamicMesh::get_custom_proxy_mesh);
+ ADD_PROPERTY(
+ PropertyInfo(Variant::OBJECT, "custom_proxy_mesh",PROPERTY_HINT_RESOURCE_TYPE,"Mesh"), "set_custom_proxy_mesh","get_custom_proxy_mesh");
}
-void SteamAudioDynamicMesh::_ready() {
- build_subscene();
-
- // instance it in the main scene, with initial transform
- IPLInstancedMeshSettings ims{};
- ims.subScene = proxy_subscene;
- ims.transform = to_ipl_matrix(get_global_transform());
-
- iplInstancedMeshCreate(global_scene, &ims, &instanced_mesh);
- iplInstancedMeshAdd(instanced_mesh, global_scene);
- iplSceneCommit(global_scene);
+// Setters & getters ---------------------------------------------------
+void SteamAudioDynamicMesh::set_proxy_mode(int mode) {
+ proxy_mode = mode;
}
-void SteamAudioDynamicMesh::_process(double /*delta*/) {
- if (!instanced_mesh) return;
-
- // update the world‐space transform
- IPLMatrix4x4 mat = to_ipl_matrix(get_global_transform());
- iplInstancedMeshUpdateTransform(instanced_mesh, global_scene, mat);
-
- // commit once per frame (best performance if after all updates) :contentReference[oaicite:0]{index=0}
- iplSceneCommit(global_scene);
+int SteamAudioDynamicMesh::get_proxy_mode() const {
+ return proxy_mode;
}
-void SteamAudioDynamicMesh::build_subscene() {
- // 1) create a fresh sub-scene
- IPLSceneSettings ss{};
- iplSceneCreate(global_context, &ss, &proxy_subscene);
-
- // 2) pull raw verts/indices out of this MeshInstance3D
- Ref mesh = cast_to(get_parent())->get_mesh();
- if (mesh.is_null()) return;
-
- // for simplicity, we assume a single surface:
- Array arr = mesh->surface_get_arrays(0);
- PackedVector3Array verts = arr[Mesh::ARRAY_VERTEX];
- PackedInt32Array idxs = arr[Mesh::ARRAY_INDEX];
-
- // fill out static‐mesh settings
- IPLStaticMeshSettings sms{};
- sms.numVertices = verts.size();
- sms.vertices = reinterpret_cast(const_cast(verts.ptr()));
- sms.numTriangles = idxs.size() / 3;
- // convert PoolIntArray → IPLTriangle*
- // …you’d build & fill an IPLTriangle array here…
- // sms.triangles = your_triangle_buffer;
-
- // add it to the proxy_subscene
- IPLStaticMesh sm = nullptr;
- iplStaticMeshCreate(proxy_subscene, &sms, &sm);
- iplStaticMeshAdd(sm, proxy_subscene);
-
- // finally commit the sub-scene so it’s ready to be instanced :contentReference[oaicite:1]{index=1}
- iplSceneCommit(proxy_subscene);
+void SteamAudioDynamicMesh::set_custom_proxy_mesh(Ref mesh) {
+ custom_proxy_mesh = mesh;
}
-IPLMatrix4x4 SteamAudioDynamicMesh::to_ipl_matrix(const Transform3D &t) {
- // row-major: each m[i][j] is row i, column j
- IPLMatrix4x4 m{};
- // basis X column
- m.elements[0][0] = t.basis[0][0]; m.elements[1][0] = t.basis[0][1]; m.elements[2][0] = t.basis[0][2];
- // basis Y column
- m.elements[0][1] = t.basis[1][0]; m.elements[1][1] = t.basis[1][1]; m.elements[2][1] = t.basis[1][2];
- // basis Z column
- m.elements[0][2] = t.basis[2][0]; m.elements[1][2] = t.basis[2][1]; m.elements[2][2] = t.basis[2][2];
- // origin
- m.elements[0][3] = t.origin.x; m.elements[1][3] = t.origin.y; m.elements[2][3] = t.origin.z;
- // bottom row
- m.elements[3][0] = 0; m.elements[3][1] = 0; m.elements[3][2] = 0; m.elements[3][3] = 1;
- return m;
+Ref SteamAudioDynamicMesh::get_custom_proxy_mesh() const {
+ return custom_proxy_mesh;
+}
+
+void SteamAudioDynamicMesh::_notification(int what) {
+ Transform3D current;
+ switch (what) {
+ case NOTIFICATION_ENTER_TREE:
+ needs_update=true;
+ break;
+ case NOTIFICATION_EXIT_TREE:
+ break;
+ case NOTIFICATION_TRANSFORM_CHANGED:
+ current = get_global_transform();
+ if (!last_transform.is_equal_approx(current)) {
+ last_transform = current;
+ needs_update=true;
+ }
+ default:
+ break;
+ }
+}
+
+ // Core functionality --------------------------------------------------
+Ref SteamAudioDynamicMesh::get_proxy_mesh() {
+ print_line("getting the proxy mesh");
+ print_line(vformat("proxy_mode: %f", proxy_mode));
+
+ MeshInstance3D *parent = cast_to(get_parent());
+ if (!parent) {
+ print_error("Parent is not a MeshInstance3D!");
+ return {};
+ }
+ Ref target_mesh;
+ Ref source_mesh = parent->get_mesh();
+ if (!source_mesh.is_valid()) {
+ print_error("Source mesh is invalid!");
+ return {};
+ }
+
+ print_line("using parent mesh");
+ print_line(vformat("Source mesh type: %s", source_mesh->get_class()));
+
+ switch (proxy_mode) {
+ case PROXY_NONE:
+ target_mesh = source_mesh;
+ break;
+ case PROXY_AUTO:
+
+ break;
+
+ case PROXY_CUSTOM:
+
+ break;
+ default:
+ print_error("Unknown proxy mode!");
+ return {};
+ }
+ return target_mesh;
+}
+void SteamAudioDynamicMesh::update_dynamic_mesh() {
+ IPLMatrix4x4 transform = SteamAudio::transform_to_ipl_matrix(get_global_transform());
+ iplInstancedMeshUpdateTransform(instanced_mesh,global_scene,transform);
+}
+
+
+void SteamAudioDynamicMesh::build_mesh(IPLScene scene,IPLContext ipl_context,IPLContextSettings ipl_context_settings) {
+ global_scene=scene;
+ iplSceneCreate(ipl_context,&scene_settings,&subscene);
+ if (!scene) {
+ ERR_PRINT("Invalid IPLScene passed to build_mesh");
+ return;
+ }
+
+ struct SurfaceData {
+ PackedVector3Array vertices;
+ PackedInt32Array indices;
+ IPLMaterial material;
+ };
+
+ Vector surface_data;
+ print_line("building a static mesh");
+ Ref mesh = get_proxy_mesh();
+
+ if (mesh.is_null()) {
+ ERR_PRINT("Failed to get valid proxy mesh");
+ return;
+ }
+ print_line("got the mesh");
+
+ for (int surface_idx = 0; surface_idx < mesh->get_surface_count(); surface_idx++) {
+ SurfaceData data;
+ Array arrays = mesh->surface_get_arrays(surface_idx);
+
+ if (arrays.is_empty()) {
+ ERR_PRINT(vformat("Surface %d has no arrays data", surface_idx));
+ continue;
+ }
+
+ // Get vertices and indices
+ PackedVector3Array vertices = arrays[Mesh::ARRAY_VERTEX];
+ PackedInt32Array indices = arrays[Mesh::ARRAY_INDEX];
+
+ if (vertices.is_empty()) {
+ ERR_PRINT(vformat("Surface %d has no vertices", surface_idx));
+ continue;
+ }
+
+ // If indices array is empty, create one from vertices
+ if (indices.is_empty()) {
+ indices.resize(vertices.size());
+ for (int i = 0; i < vertices.size(); i++) {
+ indices[i] = i;
+ }
+ }
+
+ // Create triangles if indices count is not a multiple of 3
+ if (indices.size() % 3 != 0) {
+ print_line("Surface " + itos(surface_idx) + " is not triangulated, converting to triangles");
+ PackedInt32Array new_indices;
+
+ // Simple triangulation for convex polygons
+ for (int i = 0; i < indices.size() - 2; i++) {
+ new_indices.push_back(indices[0]);
+ new_indices.push_back(indices[i + 1]);
+ new_indices.push_back(indices[i + 2]);
+ }
+
+ indices = new_indices;
+ }
+
+ data.vertices = vertices;
+ data.indices = indices;
+
+ // Get material for the surface
+ Ref material = mesh->surface_get_material(surface_idx);
+ if (material.is_valid() && material->has_meta("steam_audio_material")) {
+ Ref steam_audio_material = material->get_meta("steam_audio_material");
+ if (steam_audio_material.is_valid()) {
+ SteamMaterial steam_material = steam_audio_material->get_steam_material();
+ data.material = SteamAudio::to_ipl_material(steam_material);
+ } else {
+ WARN_PRINT(vformat("Invalid Steam Audio material for surface %d", surface_idx));
+ data.material = SteamAudio::to_ipl_material(SteamAudioMaterial::get_default_material());
+ }
+ } else {
+ data.material = SteamAudio::to_ipl_material(SteamAudioMaterial::get_default_material());
+ }
+
+ surface_data.push_back(data);
+ }
+
+ if (surface_data.is_empty()) {
+ ERR_PRINT("No valid surfaces found in mesh");
+ return;
+ }
+
+ // Calculate total counts
+ int total_vertices = 0;
+ int total_triangles = 0;
+ for (const SurfaceData &data: surface_data) {
+ total_vertices += data.vertices.size();
+ total_triangles += data.indices.size() / 3;
+ }
+
+ if (total_vertices == 0 || total_triangles == 0) {
+ ERR_PRINT("Mesh has no vertices or triangles");
+ return;
+ }
+
+ // Prepare final data arrays
+ PackedFloat32Array final_vertices;
+ PackedInt32Array final_triangles;
+ Vector final_materials;
+ PackedInt32Array material_indices;
+
+ final_vertices.resize(total_vertices * 3);
+ final_triangles.resize(total_triangles * 3);
+ material_indices.resize(total_triangles);
+
+ // Combine all surfaces
+ int vertex_offset = 0;
+ int triangle_offset = 0;
+ int material_index = 0;
+
+ for (const SurfaceData &data: surface_data) {
+ // Copy vertices
+ for (int i = 0; i < data.vertices.size(); i++) {
+ const Vector3 &v = data.vertices[i];
+ final_vertices[vertex_offset * 3 + 0] = v.x;
+ final_vertices[vertex_offset * 3 + 1] = v.y;
+ final_vertices[vertex_offset * 3 + 2] = v.z;
+ vertex_offset++;
+ }
+
+ // Copy triangles
+ int base_vertex = vertex_offset - data.vertices.size();
+ for (int i = 0; i < data.indices.size(); i += 3) {
+ final_triangles[triangle_offset * 3 + 0] = base_vertex + data.indices[i + 0];
+ final_triangles[triangle_offset * 3 + 1] = base_vertex + data.indices[i + 1];
+ final_triangles[triangle_offset * 3 + 2] = base_vertex + data.indices[i + 2];
+
+ material_indices[triangle_offset] = material_index;
+ triangle_offset++;
+ }
+
+ final_materials.push_back(data.material);
+ material_index++;
+ }
+
+ // Create Steam Audio static mesh
+ IPLStaticMeshSettings mesh_settings = {};
+ mesh_settings.numVertices = total_vertices;
+ mesh_settings.numTriangles = total_triangles;
+ mesh_settings.numMaterials = final_materials.size();
+ mesh_settings.vertices = const_cast(reinterpret_cast(final_vertices.ptr()));
+ mesh_settings.triangles = const_cast(reinterpret_cast(final_triangles.ptr()));
+ mesh_settings.materials = const_cast(final_materials.ptr());
+ mesh_settings.materialIndices = const_cast(material_indices.ptr());
+
+ IPLStaticMesh static_mesh;
+ IPLerror error = iplStaticMeshCreate(subscene, &mesh_settings, &static_mesh);
+ if (error != IPL_STATUS_SUCCESS) {
+ ERR_PRINT(vformat("Failed to create static mesh. Error code: %d", error));
+ return;
+ }
+
+ print_line(vformat("Successfully created static mesh with %d vertices and %d triangles", total_vertices,
+ total_triangles));
+ instanced_mesh_settings.subScene = subscene;
+ instanced_mesh_settings.transform = SteamAudio::transform_to_ipl_matrix(get_global_transform());
+
+ IPLerror imErr = iplInstancedMeshCreate(global_scene,&instanced_mesh_settings,&instanced_mesh);
+ if (imErr != IPL_STATUS_SUCCESS) {
+ ERR_PRINT(vformat("Failed to create instanced mesh. Error code: %d", imErr));
+ return;
+ }
}
diff --git a/src/steam_audio_dynamic_mesh.h b/src/steam_audio_dynamic_mesh.h
deleted file mode 100644
index 675a125..0000000
--- a/src/steam_audio_dynamic_mesh.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-
-using namespace godot;
-
-class SteamAudioDynamicMesh : public Node3D {
- GDCLASS(SteamAudioDynamicMesh, Node3D)
-
-private:
- IPLScene proxy_subscene = nullptr;
- IPLInstancedMesh instanced_mesh = nullptr;
-
- // helper: convert Godot Transform3D → IPLMatrix4x4
- static IPLMatrix4x4 to_ipl_matrix(const Transform3D &t);
-
- // builds a one-off IPLScene containing this mesh’s raw geometry
- void build_subscene();
-
-public:
- SteamAudioDynamicMesh();
- ~SteamAudioDynamicMesh() override;
-
- void _ready() override;
- void _process(double delta) override;
-
-protected:
- static void _bind_methods();
-};
\ No newline at end of file
diff --git a/src/steam_audio_dynamic_mesh.hpp b/src/steam_audio_dynamic_mesh.hpp
new file mode 100644
index 0000000..b425240
--- /dev/null
+++ b/src/steam_audio_dynamic_mesh.hpp
@@ -0,0 +1,65 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include // IPLStaticMesh, IPLStaticMeshSettings, IPLMaterial
+#include "steam_audio.hpp"
+#include "steam_audio_material.hpp"
+#include
+
+using namespace godot;
+
+class SteamAudioDynamicMesh : public Node3D {
+ GDCLASS(SteamAudioDynamicMesh, Node3D)
+
+private:
+ IPLScene subscene=nullptr;
+ IPLScene global_scene=nullptr;
+ IPLSceneSettings scene_settings;
+ IPLInstancedMesh instanced_mesh=nullptr;
+ IPLInstancedMeshSettings instanced_mesh_settings;
+ int proxy_mode = PROXY_NONE;
+ Ref custom_proxy_mesh;
+
+ Transform3D last_transform;
+ StringName bus;
+
+ bool needs_update = false;
+
+protected:
+ static void _bind_methods();
+
+
+public:
+ SteamAudioDynamicMesh();
+ ~SteamAudioDynamicMesh() override;
+
+ void _notification(int what);
+
+ // Setters & getters
+ void set_proxy_mode(int mode);
+ int get_proxy_mode() const;
+
+ void set_custom_proxy_mesh(Ref mesh);
+ Ref get_custom_proxy_mesh() const;
+
+ bool get_needs_update() {
+ return needs_update;
+ }
+ void build_mesh(IPLScene scene, IPLContext ipl_context, IPLContextSettings ipl_context_settings);
+ static Vector _instances;
+ static const Vector& get_all_dynamic_meshes();
+
+ // Regenerates Steam Audio proxies
+ Ref get_proxy_mesh();
+
+ void update_dynamic_mesh();
+};
diff --git a/src/steam_audio_globals.h b/src/steam_audio_globals.h
deleted file mode 100644
index 0a9ee6c..0000000
--- a/src/steam_audio_globals.h
+++ /dev/null
@@ -1,7 +0,0 @@
-// steam_audio_globals.h
-#pragma once
-#include
-#include
-extern IPLContext global_context;
-extern IPLScene global_scene;
-extern IPLSimulator global_simulator;
\ No newline at end of file
diff --git a/src/steam_audio_listener.cpp b/src/steam_audio_listener.cpp
index fdfe5af..e3b0c9f 100644
--- a/src/steam_audio_listener.cpp
+++ b/src/steam_audio_listener.cpp
@@ -1,46 +1,52 @@
-#include "steam_audio_listener.h"
-
-#include "phonon.h"
+#include "steam_audio_listener.hpp"
using namespace godot;
-SteamAudioListener::SteamAudioListener() = default;
-SteamAudioListener::~SteamAudioListener() = default;
+SteamAudioListener* SteamAudioListener::listener;
+
+SteamAudioListener::SteamAudioListener() {
+ listener=this;
+}
+
+SteamAudioListener::~SteamAudioListener() {
+ listener=nullptr;
+}
void SteamAudioListener::_bind_methods() {
-
}
-void SteamAudioListener::_process(double delta) {
+SteamAudioListener* SteamAudioListener::get_listener() {
+ return listener;
+}
+
+void SteamAudioListener::_notification(int p_what) {
+ Transform3D current_transform;
+ switch (p_what) {
+ case NOTIFICATION_TRANSFORM_CHANGED:
+ current_transform = get_global_transform();
+ if (!last_transform.is_equal_approx(current_transform)) {
+ needs_update = true;
+ last_transform = current_transform;
+ }
+ break;
+ case NOTIFICATION_ENTER_TREE:
+ needs_update = true;
+ break;
+ default:
+ break;
+ }
+}
+
+void SteamAudioListener::update_listener(IPLSimulator iplsim, IPLSimulationSharedInputs iplsiminputs) {
+ needs_update=false;
+
Transform3D transform = get_global_transform();
- IPLVector3 pos = {
- static_cast(transform.origin.x),
- static_cast(transform.origin.y),
- static_cast(transform.origin.z)
- };
- Vector3 godot_fwd = transform.basis.xform(Vector3(0, 0, -1));
- IPLVector3 fwd = {
- static_cast(godot_fwd.x),
- static_cast(godot_fwd.y),
- static_cast(godot_fwd.z)
- };
- Vector3 godot_up = transform.basis.xform(Vector3(0, 1, 0));
- IPLVector3 up = {
- static_cast(godot_up.x),
- static_cast(godot_up.y),
- static_cast(godot_up.z)
- };
- IPLVector3 right = {
- fwd.y * up.z - fwd.z * up.y,
- fwd.z * up.x - fwd.x * up.z,
- fwd.x * up.y - fwd.y * up.x
- };
- IPLCoordinateSpace3 listenerCS{};
- listenerCS.origin = pos;
- listenerCS.ahead = fwd;
- listenerCS.up = up;
- listenerCS.right = right;
- IPLSimulationSharedInputs sharedInputs{};
- sharedInputs.listener = listenerCS;
-}
+ IPLCoordinateSpace3 space = SteamAudio::godot_to_ipl_space(transform);
+
+ iplsiminputs.listener=space;
+
+ iplSimulatorSetSharedInputs(iplsim,IPL_SIMULATIONFLAGS_DIRECT,&iplsiminputs);
+ iplSimulatorSetSharedInputs(iplsim,IPL_SIMULATIONFLAGS_PATHING,&iplsiminputs);
+ iplSimulatorSetSharedInputs(iplsim,IPL_SIMULATIONFLAGS_REFLECTIONS,&iplsiminputs);
+}
\ No newline at end of file
diff --git a/src/steam_audio_listener.h b/src/steam_audio_listener.h
deleted file mode 100644
index 53fb237..0000000
--- a/src/steam_audio_listener.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-
-using namespace godot;
-
-class SteamAudioListener:public AudioListener3D
-{
- GDCLASS(SteamAudioListener,AudioListener3D)
-
-
-protected:
- static void _bind_methods();
- void _process(double p_delta) override;
-public:
- SteamAudioListener();
- ~SteamAudioListener() override;
-
-private:
-
-};
\ No newline at end of file
diff --git a/src/steam_audio_listener.hpp b/src/steam_audio_listener.hpp
new file mode 100644
index 0000000..5a53d3a
--- /dev/null
+++ b/src/steam_audio_listener.hpp
@@ -0,0 +1,41 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include "steam_audio.hpp"
+#include "phonon.h"
+
+using namespace godot;
+
+class SteamAudioListener:public AudioListener3D
+{
+ GDCLASS(SteamAudioListener,AudioListener3D)
+private:
+ bool needs_update = false;
+ Transform3D last_transform;
+
+protected:
+ static void _bind_methods();
+public:
+ bool get_needs_update() {
+ return needs_update;
+ }
+ static SteamAudioListener *listener;
+ SteamAudioListener();
+ ~SteamAudioListener() override;
+
+ void _notification(int p_what);
+
+ static SteamAudioListener* get_listener();
+ void update_listener(IPLSimulator iplsim, IPLSimulationSharedInputs iplsiminputs);
+ void set_listener_position(const Vector3 &p_position);
+ void set_listener_orientation(const Vector3 &p_forward, const Vector3 &p_up);
+ void set_listener_velocity(const Vector3 &p_velocity);
+ void set_listener_gain(const float p_gain);
+ void set_listener_doppler_factor(const float p_factor);
+ void set_listener_distance_model(const int p_model);
+ void set_listener_flags(const int p_flags);
+ void set_listener_channel_count(const int p_count);
+};
\ No newline at end of file
diff --git a/src/steam_audio_material.cpp b/src/steam_audio_material.cpp
index 5b068ad..a79c0b2 100644
--- a/src/steam_audio_material.cpp
+++ b/src/steam_audio_material.cpp
@@ -1,4 +1,4 @@
-#include "steam_audio_material.h"
+#include "steam_audio_material.hpp"
using namespace godot;
@@ -14,26 +14,22 @@ void SteamAudioMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT,"scattering"), "set_scattering", "get_scattering");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3,"transmission"), "set_transmission", "get_transmission");
}
-Vector3 SteamAudioMaterial::get_absorption() const {return absorption;}
-void SteamAudioMaterial::set_absorption(Vector3 value) { absorption = value; }
-float SteamAudioMaterial::get_scattering() const {return scattering;}
-void SteamAudioMaterial::set_scattering(float value) { scattering = value; }
-Vector3 SteamAudioMaterial::get_transmission() const {return transmission;}
-void SteamAudioMaterial::set_transmission(Vector3 value) { transmission = value; }
-IPLMaterial SteamAudioMaterial::to_ipl_material() const {
- IPLMaterial material ={};
- material.absorption[0] = absorption.x;
- material.absorption[1] = absorption.y;
- material.absorption[2] = absorption.z;
+SteamMaterial SteamAudioMaterial::default_material = {
+ Vector3(0.10f,0.20f,0.30f),
+ 0.05f,
+ Vector3(0.100f,0.050f,0.030f)
+};
- material.scattering = scattering;
-
- material.transmission[0] = transmission.x;
- material.transmission[1] = transmission.y;
- material.transmission[2] = transmission.z;
-
- return material;
+Vector3 SteamAudioMaterial::get_absorption() const {return material.absorption;}
+void SteamAudioMaterial::set_absorption(Vector3 value) { material.absorption = value; }
+float SteamAudioMaterial::get_scattering() const {return material.scattering;}
+void SteamAudioMaterial::set_scattering(float value) { material.scattering = value; }
+Vector3 SteamAudioMaterial::get_transmission() const {return material.transmission;}
+void SteamAudioMaterial::set_transmission(Vector3 value) { material.transmission = value; }
+const SteamMaterial &SteamAudioMaterial::get_default_material() {
+ return default_material;
}
-
-
+SteamMaterial SteamAudioMaterial::get_steam_material() const {
+ return material;
+}
\ No newline at end of file
diff --git a/src/steam_audio_material.h b/src/steam_audio_material.hpp
similarity index 64%
rename from src/steam_audio_material.h
rename to src/steam_audio_material.hpp
index 1c053a2..9a9d57e 100644
--- a/src/steam_audio_material.h
+++ b/src/steam_audio_material.hpp
@@ -1,27 +1,32 @@
#pragma once
-
+#include
#include
-#include "godot_cpp/godot.hpp"
#include
+#include "godot_cpp/classes/wrapped.hpp"
+#include "godot_cpp/godot.hpp"
#include "phonon.h"
using namespace godot;
-
+struct SteamMaterial {
+ Vector3 absorption;
+ float scattering;
+ Vector3 transmission;
+};
class SteamAudioMaterial : public Resource {
GDCLASS(SteamAudioMaterial,Resource) // NOLINT(modernize-use-auto, hicpp-use-auto)
protected:
static void _bind_methods();
private:
- Vector3 absorption = Vector3(0.2, 0.2, 0.2);
- float scattering = 0.0;
- Vector3 transmission = Vector3(0.0, 0.0, 0.0);
+ SteamMaterial material;
+
public:
+ static SteamMaterial default_material;
+ static const SteamMaterial& get_default_material();
void set_absorption(const Vector3 value);
void set_scattering(const float value);
void set_transmission(const Vector3 value);
Vector3 get_absorption() const;
[[nodiscard]] float get_scattering() const;
Vector3 get_transmission() const;
-
- [[nodiscard]] IPLMaterial to_ipl_material() const;
+ SteamMaterial get_steam_material() const;
};
\ No newline at end of file
diff --git a/src/steam_audio_server.cpp b/src/steam_audio_server.cpp
new file mode 100644
index 0000000..d5582fe
--- /dev/null
+++ b/src/steam_audio_server.cpp
@@ -0,0 +1,16 @@
+#include "steam_audio_server.hpp"
+
+using namespace godot;
+
+ SteamAudioServer::SteamAudioServer() {
+
+}
+
+ SteamAudioServer::~SteamAudioServer() {
+
+}
+
+// Core Godot Methods
+void SteamAudioServer::_bind_methods() {
+
+}
diff --git a/src/steam_audio_server.hpp b/src/steam_audio_server.hpp
new file mode 100644
index 0000000..71c4f86
--- /dev/null
+++ b/src/steam_audio_server.hpp
@@ -0,0 +1,28 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "steam_audio_dynamic_mesh.hpp"
+#include "steam_audio_source.hpp"
+#include "steam_audio_static_mesh.hpp"
+
+using namespace godot;
+
+
+class SteamAudioServer : public Object {
+ GDCLASS(SteamAudioServer, Object) // Godot class declaration macro
+private:
+
+public:
+ SteamAudioServer(); // Constructor
+ ~SteamAudioServer() override; // Destructor
+
+protected:
+ static void _bind_methods(); // Bind methods to Godot
+
+};
diff --git a/src/steam_audio_source.cpp b/src/steam_audio_source.cpp
index c7a39cb..fb904d1 100644
--- a/src/steam_audio_source.cpp
+++ b/src/steam_audio_source.cpp
@@ -1,22 +1,51 @@
-#include "steam_audio_source.h"
-
-#include "steam_audio_globals.h"
+#include "steam_audio_source.hpp"
using namespace godot;
+
+// Static vector to track all active audio sources
+Vector SteamAudioSource::_instances;
+
+// Constructor/Destructor
SteamAudioSource::SteamAudioSource() {
- iplSourceCreate(sa->get_simulator(),&settings,pSource);
+ // Disable default attenuation since Steam Audio handles it
+ set_attenuation_model(ATTENUATION_DISABLED);
+ _instances.push_back(this);
}
+
SteamAudioSource::~SteamAudioSource() {
- iplSourceRelease(pSource);
+ // Remove this instance from tracking vector
+ _instances.erase(this);
}
+
+// Static method to get all active audio sources
+const Vector &SteamAudioSource::get_all_sources() {
+ return _instances;
+}
+
+// Godot virtual methods
void SteamAudioSource::_bind_methods() {
+ // Bind directivity methods to make them accessible from GDScript
+ ClassDB::bind_method(D_METHOD("set_dipole_weight", "weight"), &SteamAudioSource::set_dipole_weight);
+ ClassDB::bind_method(D_METHOD("get_dipole_weight"), &SteamAudioSource::get_dipole_weight);
+ ClassDB::bind_method(D_METHOD("set_dipole_power", "power"), &SteamAudioSource::set_dipole_power);
+ ClassDB::bind_method(D_METHOD("get_dipole_power"), &SteamAudioSource::get_dipole_power);
+ ClassDB::bind_method(D_METHOD("set_directivity_enabled", "arg"), &SteamAudioSource::set_directivity_enabled);
+ ClassDB::bind_method(D_METHOD("is_directivity_enabled"), &SteamAudioSource::get_is_directivity_enabled);
+
+ // Add properties to editor interface
+ ADD_GROUP("Directivity", "directivity_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directivity_enabled"), "set_directivity_enabled",
+ "is_directivity_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "directivity_dipole_weight", PROPERTY_HINT_RANGE, "0,1,0.01"),
+ "set_dipole_weight", "get_dipole_weight");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "directivity_dipole_power", PROPERTY_HINT_RANGE, "0,10,0.1"),
+ "set_dipole_power", "get_dipole_power");
}
-void SteamAudioSource::_process(double delta) {
- update_position();
-}
-bool SteamAudioSource::update_position() {
- IPLCoordinateSpace3 current_pos = sa->godot_to_ipl_space(get_transform());
-
- iplSource
-}
+// Hide default AudioStreamPlayer3D properties that we don't use
+void SteamAudioSource::_validate_property(PropertyInfo &property) const {
+ if (property.name == StringName("attenuation_model") || property.name == StringName("unit_size") ||
+ property.name.begins_with("attenuation") || property.name.begins_with("emission_")) {
+ property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+}
\ No newline at end of file
diff --git a/src/steam_audio_source.h b/src/steam_audio_source.h
deleted file mode 100644
index eec3738..0000000
--- a/src/steam_audio_source.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include "steam_audio.h"
-#include "phonon.h"
-
-using namespace godot;
-
-class SteamAudioSource: public Node3D
-{
- GDCLASS(SteamAudioSource,Node3D)
-
- IPLSource *pSource = nullptr;
- SteamAudio *sa = SteamAudio::steam_audio;
- IPLSourceSettings settings{};
-protected:
- static void _bind_methods();
- void _process(double p_delta) override;
-public:
- SteamAudioSource();
- ~SteamAudioSource();
- bool update_position();
-
-};
\ No newline at end of file
diff --git a/src/steam_audio_source.hpp b/src/steam_audio_source.hpp
new file mode 100644
index 0000000..6ba4e84
--- /dev/null
+++ b/src/steam_audio_source.hpp
@@ -0,0 +1,63 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include "phonon.h"
+#include
+#include
+#include
+#include
+#include "steam_audio.hpp"
+
+
+using namespace godot;
+class SteamAudioSource: public AudioStreamPlayer3D
+{
+ GDCLASS(SteamAudioSource,AudioStreamPlayer3D) // NOLINT(*-unhandled-self-assignment)
+
+ AudioServer *audio_server = AudioServer::get_singleton();
+ bool is_directivity_enabled = true;
+ float dipole_weight=0.0f;
+ float dipole_power=1.0f;
+ int mix_rate=0;
+ int buffer_size=0;
+
+ IPLContext ipl_context = nullptr;
+ IPLSource *pSource = nullptr;
+ IPLSourceSettings settings{};
+ IPLSimulationInputs inputs{};
+ IPLDirectivity directivity{};
+
+ Transform3D last_transform;
+ bool needs_update = false;
+
+ Ref playback;
+ Vector audio_buffer;
+protected:
+ static void _bind_methods();
+ void _validate_property(PropertyInfo &property) const;
+public:
+ void _notification(int p_what);
+ void _process(double p_delta) override;
+
+ SteamAudioSource();
+ ~SteamAudioSource() override;
+
+ void update_source();
+
+ void set_directivity_enabled(bool enabled){is_directivity_enabled=enabled;}
+ void set_dipole_weight(float w){dipole_weight=w;}
+ void set_dipole_power(float p){dipole_power=p;}
+
+ [[nodiscard]] float get_dipole_weight() const{return dipole_weight;}
+ [[nodiscard]] float get_dipole_power() const{return dipole_power;}
+ [[nodiscard]] bool get_is_directivity_enabled() const{return is_directivity_enabled;}
+
+ static Vector _instances;
+ static const Vector& get_all_sources();
+
+ [[nodiscard]] bool get_needs_update() const {
+ return needs_update;}
+};
\ No newline at end of file
diff --git a/src/steam_audio_static_mesh.cpp b/src/steam_audio_static_mesh.cpp
index 89fd39c..8792423 100644
--- a/src/steam_audio_static_mesh.cpp
+++ b/src/steam_audio_static_mesh.cpp
@@ -1,25 +1,23 @@
// steam_audio_static_mesh.cpp
-#include "steam_audio_static_mesh.h"
-
-#include
-#include
-#include
-#include
-#include
-#include // IPLStaticMesh, IPLStaticMeshSettings, IPLMaterial
+#include "steam_audio_static_mesh.hpp"
using namespace godot;
-SteamAudioStaticMesh::SteamAudioStaticMesh() = default;
+Vector SteamAudioStaticMesh::_instances;
+
+SteamAudioStaticMesh::SteamAudioStaticMesh() {
+ _instances.push_back(this);
+}
SteamAudioStaticMesh::~SteamAudioStaticMesh() {
- // release any previously created Steam Audio meshes
- for (auto &sm : static_meshes) {
- iplStaticMeshRelease(&sm);
- }
- static_meshes.clear();
+ _instances.erase(this);
}
+const Vector &SteamAudioStaticMesh::get_all_static_meshes() {
+ return _instances;
+}
+
+
void SteamAudioStaticMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_proxy_mode", "mode"), &SteamAudioStaticMesh::set_proxy_mode);
ClassDB::bind_method(D_METHOD("get_proxy_mode"), &SteamAudioStaticMesh::get_proxy_mode);
@@ -30,19 +28,13 @@ void SteamAudioStaticMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_custom_proxy_mesh"), &SteamAudioStaticMesh::get_custom_proxy_mesh);
ADD_PROPERTY(
PropertyInfo(Variant::OBJECT, "custom_proxy_mesh",PROPERTY_HINT_RESOURCE_TYPE,"Mesh"), "set_custom_proxy_mesh","get_custom_proxy_mesh");
-
- ClassDB::bind_method(D_METHOD("set_default_material", "mat"), &SteamAudioStaticMesh::set_default_material);
- ClassDB::bind_method(D_METHOD("get_default_material"), &SteamAudioStaticMesh::get_default_material);
-
- // And still bind your proxy-generator:
- ClassDB::bind_method(D_METHOD("generate_proxy_mesh"), &SteamAudioStaticMesh::generate_proxy_mesh);
-
}
// Setters & getters ---------------------------------------------------
void SteamAudioStaticMesh::set_proxy_mode(int mode) {
proxy_mode = mode;
}
+
int SteamAudioStaticMesh::get_proxy_mode() const {
return proxy_mode;
}
@@ -50,132 +42,217 @@ int SteamAudioStaticMesh::get_proxy_mode() const {
void SteamAudioStaticMesh::set_custom_proxy_mesh(Ref mesh) {
custom_proxy_mesh = mesh;
}
+
Ref SteamAudioStaticMesh::get_custom_proxy_mesh() const {
return custom_proxy_mesh;
}
-void SteamAudioStaticMesh::set_default_material(Ref mat) {
- default_material = mat;
-}
-Ref SteamAudioStaticMesh::get_default_material() const {
- return default_material;
-}
-
// Core functionality --------------------------------------------------
-void SteamAudioStaticMesh::generate_proxy_mesh() {
- // 1) Clean up any old meshes
- for (auto &sm : static_meshes) {
- iplStaticMeshRelease(&sm);
- }
- static_meshes.clear();
+Ref SteamAudioStaticMesh::get_proxy_mesh() {
+ print_line("getting the proxy mesh");
+ print_line(vformat("proxy_mode: %f", proxy_mode));
+
+ MeshInstance3D* parent = cast_to(get_parent());
+ if (!parent) {
+ print_error("Parent is not a MeshInstance3D!");
+ return {};
+ }
+ Ref target_mesh;
+ Ref source_mesh = parent->get_mesh();
+ if (!source_mesh.is_valid()) {
+ print_error("Source mesh is invalid!");
+ return {};
+ }
+
+ print_line("using parent mesh");
+ print_line(vformat("Source mesh type: %s", source_mesh->get_class()));
- // 2) Pick which Mesh to read triangles from
- Ref target;
switch (proxy_mode) {
case PROXY_NONE:
- target = cast_to(get_parent())->get_mesh();
+ target_mesh = source_mesh;
break;
- case PROXY_CONVEX: {
- Ref hull_shape = cast_to(get_parent())->get_mesh()->create_convex_shape();
- ConvexPolygonShape3D *convex = cast_to(hull_shape.ptr());
- if (!convex) {
- ERR_PRINT("SteamAudioStaticMesh: convex cast failed");
- return;
- }
- Ref debug_mesh = convex->get_debug_mesh();
- if (!debug_mesh.is_valid()) {
- ERR_PRINT("SteamAudioStaticMesh: debug mesh invalid");
- return;
- }
- target = debug_mesh;
+ case PROXY_AUTO:
+
break;
- }
+
case PROXY_CUSTOM:
- if (!custom_proxy_mesh.is_valid()) {
- ERR_PRINT("SteamAudioStaticMesh: custom_proxy_mesh not set");
- return;
- }
- target = custom_proxy_mesh;
+
break;
default:
- ERR_PRINT("SteamAudioStaticMesh: unknown proxy_mode");
- return;
+ print_error("Unknown proxy mode!");
+ return {};
}
+ return target_mesh;
- if (!target.is_valid()) {
- ERR_PRINT("SteamAudioStaticMesh: target mesh invalid");
+}
+
+
+
+void SteamAudioStaticMesh::build_mesh(IPLScene scene) {
+ if (!scene) {
+ ERR_PRINT("Invalid IPLScene passed to build_mesh");
return;
}
- // 3) For each surface, build and add a Steam Audio static mesh
- const int surface_count = target->get_surface_count();
- for (int s = 0; s < surface_count; ++s) {
- Array arrays = target->surface_get_arrays(s);
- PackedVector3Array verts = arrays[Mesh::ARRAY_VERTEX];
- PackedInt32Array idxs = arrays[Mesh::ARRAY_INDEX];
+ struct SurfaceData {
+ PackedVector3Array vertices;
+ PackedInt32Array indices;
+ IPLMaterial material;
+ };
- // --- build IPLMaterial from metadata or default_material ---
- Ref gm = target->surface_get_material(s);
- Ref sa_mat;
- if (gm.is_valid() && gm->has_meta("steam_audio")) {
- sa_mat = gm->get_meta("steam_audio");
- }
- if (!sa_mat.is_valid()) {
- sa_mat = default_material;
- }
- IPLMaterial material{}; // zero initialize all fields
- // absorption[0..2]
- material.absorption[0] = sa_mat->get_absorption().x;
- material.absorption[1] = sa_mat->get_absorption().y;
- material.absorption[2] = sa_mat->get_absorption().z;
- // scattering
- material.scattering = sa_mat->get_scattering();
- // transmission[0..2]
- material.transmission[0] = sa_mat->get_transmission().x;
- material.transmission[1] = sa_mat->get_transmission().y;
- material.transmission[2] = sa_mat->get_transmission().z;
+ Vector surface_data;
+ print_line("building a static mesh");
+ Ref mesh = get_proxy_mesh();
- // --- fill out static mesh settings ---
- IPLStaticMeshSettings settings{};
+ if (mesh.is_null()) {
+ ERR_PRINT("Failed to get valid proxy mesh");
+ return;
+ }
+ print_line("got the mesh");
- // Number of vertices
- settings.numVertices = verts.size();
+ for (int surface_idx = 0; surface_idx < mesh->get_surface_count(); surface_idx++) {
+ SurfaceData data;
+ Array arrays = mesh->surface_get_arrays(surface_idx);
- // reinterpret Godot’s Vector3 buffer as Steam Audio’s IPLVector3[]
- const IPLVector3 *raw_vertices = reinterpret_cast(verts.ptr());
-
- // drop the const so it matches IPLStaticMeshSettings::vertices (IPLVector3*)
- IPLVector3 *writable_vertices = const_cast(raw_vertices);
- settings.vertices = writable_vertices;
-
- // Number of triangles
- settings.numTriangles = idxs.size() / 3;
-
- // build triangle array
- std::vector triangles;
- triangles.reserve(settings.numTriangles);
- for (int i = 0; i < settings.numTriangles; ++i) {
- IPLTriangle tri{};
- tri.indices[0] = static_cast(idxs[3*i + 0]);
- tri.indices[1] = static_cast(idxs[3*i + 1]);
- tri.indices[2] = static_cast(idxs[3*i + 2]);
- triangles.push_back(tri);
- }
- settings.triangles = triangles.data();
- settings.numMaterials = 1;
- settings.materials = &material;
-
- // --- create & add to Steam Audio scene ---
- /*IPLStaticMesh sm = nullptr;
- IPLerror err = iplStaticMeshCreate(global_scene, &settings, &sm);
- if (err != IPL_STATUS_SUCCESS) {
- ERR_PRINT("SteamAudioStaticMesh: iplStaticMeshCreate failed");
+ if (arrays.is_empty()) {
+ ERR_PRINT(vformat("Surface %d has no arrays data", surface_idx));
continue;
}
- iplStaticMeshAdd(sm, global_scene);
- static_meshes.push_back(sm);*/
+
+ // Get vertices and indices
+ PackedVector3Array vertices = arrays[Mesh::ARRAY_VERTEX];
+ PackedInt32Array indices = arrays[Mesh::ARRAY_INDEX];
+
+ if (vertices.is_empty()) {
+ ERR_PRINT(vformat("Surface %d has no vertices", surface_idx));
+ continue;
+ }
+
+ // If indices array is empty, create one from vertices
+ if (indices.is_empty()) {
+ indices.resize(vertices.size());
+ for (int i = 0; i < vertices.size(); i++) {
+ indices[i] = i;
+ }
+ }
+
+ // Create triangles if indices count is not a multiple of 3
+ if (indices.size() % 3 != 0) {
+ print_line("Surface " + itos(surface_idx) + " is not triangulated, converting to triangles");
+ PackedInt32Array new_indices;
+
+ // Simple triangulation for convex polygons
+ for (int i = 0; i < indices.size() - 2; i++) {
+ new_indices.push_back(indices[0]);
+ new_indices.push_back(indices[i + 1]);
+ new_indices.push_back(indices[i + 2]);
+ }
+
+ indices = new_indices;
+ }
+
+ data.vertices = vertices;
+ data.indices = indices;
+
+ // Get material for the surface
+ Ref material = mesh->surface_get_material(surface_idx);
+ if (material.is_valid() && material->has_meta("steam_audio_material")) {
+ Ref steam_audio_material = material->get_meta("steam_audio_material");
+ if (steam_audio_material.is_valid()) {
+ SteamMaterial steam_material = steam_audio_material->get_steam_material();
+ data.material = SteamAudio::to_ipl_material(steam_material);
+ } else {
+ WARN_PRINT(vformat("Invalid Steam Audio material for surface %d", surface_idx));
+ data.material = SteamAudio::to_ipl_material(SteamAudioMaterial::get_default_material());
+ }
+ } else {
+ data.material = SteamAudio::to_ipl_material(SteamAudioMaterial::get_default_material());
+ }
+
+ surface_data.push_back(data);
}
- // 4) Commit all additions at once
- // iplSceneCommit(global_scene);
+ if (surface_data.is_empty()) {
+ ERR_PRINT("No valid surfaces found in mesh");
+ return;
+ }
+
+ // Calculate total counts
+ int total_vertices = 0;
+ int total_triangles = 0;
+ for (const SurfaceData &data: surface_data) {
+ total_vertices += data.vertices.size();
+ total_triangles += data.indices.size() / 3;
+ }
+
+ if (total_vertices == 0 || total_triangles == 0) {
+ ERR_PRINT("Mesh has no vertices or triangles");
+ return;
+ }
+
+ // Prepare final data arrays
+ PackedFloat32Array final_vertices;
+ PackedInt32Array final_triangles;
+ Vector final_materials;
+ PackedInt32Array material_indices;
+
+ final_vertices.resize(total_vertices * 3);
+ final_triangles.resize(total_triangles * 3);
+ material_indices.resize(total_triangles);
+
+ // Combine all surfaces
+ int vertex_offset = 0;
+ int triangle_offset = 0;
+ int material_index = 0;
+
+ for (const SurfaceData &data: surface_data) {
+ // Copy vertices
+ for (int i = 0; i < data.vertices.size(); i++) {
+ const Vector3 &v = data.vertices[i];
+ final_vertices[vertex_offset * 3 + 0] = v.x;
+ final_vertices[vertex_offset * 3 + 1] = v.y;
+ final_vertices[vertex_offset * 3 + 2] = v.z;
+ vertex_offset++;
+ }
+
+ // Copy triangles
+ int base_vertex = vertex_offset - data.vertices.size();
+ for (int i = 0; i < data.indices.size(); i += 3) {
+ final_triangles[triangle_offset * 3 + 0] = base_vertex + data.indices[i + 0];
+ final_triangles[triangle_offset * 3 + 1] = base_vertex + data.indices[i + 1];
+ final_triangles[triangle_offset * 3 + 2] = base_vertex + data.indices[i + 2];
+
+ material_indices[triangle_offset] = material_index;
+ triangle_offset++;
+ }
+
+ final_materials.push_back(data.material);
+ material_index++;
+ }
+
+ // Create Steam Audio static mesh
+ IPLStaticMeshSettings mesh_settings = {};
+ mesh_settings.numVertices = total_vertices;
+ mesh_settings.numTriangles = total_triangles;
+ mesh_settings.numMaterials = final_materials.size();
+ mesh_settings.vertices = const_cast(reinterpret_cast(final_vertices.ptr()));
+ mesh_settings.triangles = const_cast(reinterpret_cast(final_triangles.ptr()));
+ mesh_settings.materials = const_cast(final_materials.ptr());
+ mesh_settings.materialIndices = const_cast(material_indices.ptr());
+
+ IPLStaticMesh static_mesh;
+ IPLerror error = iplStaticMeshCreate(scene, &mesh_settings, &static_mesh);
+ if (error != IPL_STATUS_SUCCESS) {
+ ERR_PRINT(vformat("Failed to create static mesh. Error code: %d", error));
+ return;
+ }
+
+ print_line(vformat("Successfully created static mesh with %d vertices and %d triangles", total_vertices,
+ total_triangles));
}
+
+
+void SteamAudioStaticMesh::update_static_mesh() {
+ return;
+}
+
diff --git a/src/steam_audio_static_mesh.h b/src/steam_audio_static_mesh.hpp
similarity index 63%
rename from src/steam_audio_static_mesh.h
rename to src/steam_audio_static_mesh.hpp
index e64a6e4..b6bab11 100644
--- a/src/steam_audio_static_mesh.h
+++ b/src/steam_audio_static_mesh.hpp
@@ -1,24 +1,23 @@
// steam_audio_proxy_mesh.h
#pragma once
-#include
-#include
-#include
-#include
-#include
#include
+#include
#include
-
-#include "steam_audio_material.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include // IPLStaticMesh, IPLStaticMeshSettings, IPLMaterial
+#include "steam_audio.hpp"
+#include "steam_audio_material.hpp"
using namespace godot;
// Proxy generation modes
-enum ProxyMode {
- PROXY_NONE = 0,
- PROXY_CONVEX = 1,
- PROXY_CUSTOM = 2,
-};
+
class SteamAudioStaticMesh : public Node3D {
GDCLASS(SteamAudioStaticMesh, Node3D)
@@ -26,9 +25,10 @@ class SteamAudioStaticMesh : public Node3D {
private:
int proxy_mode = PROXY_NONE;
Ref custom_proxy_mesh;
- Ref default_material;
Vector static_meshes;
+ bool needs_update = false;
+
protected:
static void _bind_methods();
@@ -44,9 +44,14 @@ public:
void set_custom_proxy_mesh(Ref mesh);
Ref get_custom_proxy_mesh() const;
- void set_default_material(Ref mat);
- Ref get_default_material() const;
+ bool get_needs_update() {
+ return needs_update;
+ }
+ void update_static_mesh();
+ void build_mesh(IPLScene scene);
+ static Vector _instances;
+ static const Vector& get_all_static_meshes();
// Regenerates Steam Audio proxies
- void generate_proxy_mesh();
+ Ref get_proxy_mesh();
};
diff --git a/support_files/SteamAudioEditorPlugin.gd b/support_files/SteamAudioEditorPlugin.gd
new file mode 100644
index 0000000..43fe985
--- /dev/null
+++ b/support_files/SteamAudioEditorPlugin.gd
@@ -0,0 +1,18 @@
+@tool
+extends EditorPlugin
+
+const AUTOLOAD_NAME = "STEAM_AUDIO"
+func _enable_plugin() -> void:
+ add_autoload_singleton(AUTOLOAD_NAME,"res://addons/SteamAudioGodot/steam_audio_manager.tscn")
+
+func _enter_tree() -> void:
+ # Initialization of the plugin goes here.
+ pass
+
+func _exit_tree() -> void:
+ # Clean-up of the plugin goes here.
+ pass
+
+func _disable_plugin() -> void:
+ remove_autoload_singleton(AUTOLOAD_NAME)
+
diff --git a/support_files/lib/android-armv7/libphonon.so b/support_files/lib/android-armv7/libphonon.so
index f2d57b8..eccb57e 100644
--- a/support_files/lib/android-armv7/libphonon.so
+++ b/support_files/lib/android-armv7/libphonon.so
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d27263d048ac69aac629b327c88f13e4d2629a9e7ec31fdfdd42ebf3b052e318
-size 18427692
+oid sha256:e9886b48d0c9dbeb1b2f4a4f5aa8fadcd06bdda728ea4fee6904bc6d0e13c6b8
+size 18905744
diff --git a/support_files/lib/android-armv8/libphonon.so b/support_files/lib/android-armv8/libphonon.so
index e251e70..49cb2c2 100644
--- a/support_files/lib/android-armv8/libphonon.so
+++ b/support_files/lib/android-armv8/libphonon.so
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:15204154edb198aa6ebbb19df24e805c335af3c97019ccace67599d51a174f2e
-size 20990312
+oid sha256:4e70d4fcff0bc19eb978371902528b4acfecd587ea9443290893c1844771ae58
+size 21513872
diff --git a/support_files/lib/android-x64/libphonon.so b/support_files/lib/android-x64/libphonon.so
index 673c22c..205001b 100644
--- a/support_files/lib/android-x64/libphonon.so
+++ b/support_files/lib/android-x64/libphonon.so
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:94c8abd4bfe3d7689e959ee6bcd8407d9c7b081431f59f7a06f05f39b03ba43d
-size 20455128
+oid sha256:fbbcefba36644ba33af886dc24feb91122839bade7c55cd61ba39bd74a040976
+size 20961200
diff --git a/support_files/lib/android-x86/libphonon.so b/support_files/lib/android-x86/libphonon.so
index 6338d66..e0e1e93 100644
--- a/support_files/lib/android-x86/libphonon.so
+++ b/support_files/lib/android-x86/libphonon.so
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:27561892cd5cd577f32c45bfd40103d6c8f7a9f9b4ee5a44b03ef76734a52542
-size 18245420
+oid sha256:31415d47ac2dd10e9837bc80bcaefde07f767e8fe57df428d001d30e0dd23263
+size 18691736
diff --git a/support_files/lib/ios/libphonon.a b/support_files/lib/ios/libphonon.a
index 04d847b..71ca697 100644
--- a/support_files/lib/ios/libphonon.a
+++ b/support_files/lib/ios/libphonon.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e3fae84e65c316c225968695b8844109d4c3488b16c47fd5a093d5bfc221c725
-size 7327480
+oid sha256:09402a0856dc8f1b1de28a4852e19cc73f32cd1708b649d0e169545a5d93daeb
+size 7424240
diff --git a/support_files/lib/linux-x64/libphonon.so b/support_files/lib/linux-x64/libphonon.so
index e9a573e..1db9933 100644
--- a/support_files/lib/linux-x64/libphonon.so
+++ b/support_files/lib/linux-x64/libphonon.so
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a2681a885655bb9c75d5d28b4e2ac2a2600bb3382a3aad1e17ac0cfc5ec5b4d2
-size 20858832
+oid sha256:f025f256bf7f537fc6b56979f4b24555e234ad14dc4e3f91f1906efb0499ae45
+size 40472944
diff --git a/support_files/lib/linux-x86/libphonon.so b/support_files/lib/linux-x86/libphonon.so
index 19e7000..7577937 100644
--- a/support_files/lib/linux-x86/libphonon.so
+++ b/support_files/lib/linux-x86/libphonon.so
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:f2e9a467a802675ae142e31f1dfc4ed8e4fcd433201d495d36c8b7e3543a60bd
-size 17566428
+oid sha256:b14421d36a161143f7b5c37c22b756d2fcfcf565eb3cac158f889a62808e8bdb
+size 38736636
diff --git a/support_files/lib/osx/libphonon.dylib b/support_files/lib/osx/libphonon.dylib
index cc6bb60..6407037 100644
--- a/support_files/lib/osx/libphonon.dylib
+++ b/support_files/lib/osx/libphonon.dylib
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b11800f94323aaec6918c4bced0b5366c7c0646a47c4f8ed9e530e4adf3b3e98
-size 27119584
+oid sha256:b376a9cda06f094c57aa995e1bec28719129e6a0c92e1dbbc174f14b8d877e31
+size 25456192
diff --git a/support_files/lib/osx/phonon.bundle/Contents/MacOS/phonon b/support_files/lib/osx/phonon.bundle/Contents/MacOS/phonon
index 303b52a..fddc826 100644
Binary files a/support_files/lib/osx/phonon.bundle/Contents/MacOS/phonon and b/support_files/lib/osx/phonon.bundle/Contents/MacOS/phonon differ
diff --git a/support_files/lib/wasm/libphonon.a b/support_files/lib/wasm/libphonon.a
index 0d77871..b435618 100644
--- a/support_files/lib/wasm/libphonon.a
+++ b/support_files/lib/wasm/libphonon.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:65a0bdf74293a4f1afc7f9e2559ccd255be6760119e411f3fec4a43dadee8417
-size 6992144
+oid sha256:ec55d2d58c90ce3402189b132a198d8fd866bb476a7c1c260b6fe345c4d968be
+size 7080770
diff --git a/support_files/plugin.cfg b/support_files/plugin.cfg
new file mode 100644
index 0000000..59fa233
--- /dev/null
+++ b/support_files/plugin.cfg
@@ -0,0 +1,7 @@
+[plugin]
+
+name="Steam Audio Godot"
+description="adds Steam Audio to Godot"
+author="The River Nyx"
+version=""
+script="SteamAudioEditorPlugin.gd"
diff --git a/support_files/steam_audio_manager.tscn b/support_files/steam_audio_manager.tscn
new file mode 100644
index 0000000..d746bd0
--- /dev/null
+++ b/support_files/steam_audio_manager.tscn
@@ -0,0 +1,3 @@
+[gd_scene load_steps=0 format=3 uid="uid://b28pa3dtdpc8d"]
+
+[node name="SteamAudio" type="SteamAudio"]