From a79a7551b32f09260803cb12490a9cbdcf77cb6d Mon Sep 17 00:00:00 2001 From: Nyx Date: Mon, 12 May 2025 22:18:09 -0600 Subject: [PATCH] more stuffs --- .clang-tidy | 147 ++++++++++++++ .../SteamAudioGodot.gdextension | 11 -- src/CMakeLists.txt | 12 +- src/register_types.cpp | 64 +++++-- src/register_types.h | 22 ++- src/steam_audio.cpp | 172 +++++++++++++---- src/steam_audio.h | 74 +++++-- src/steam_audio_dynamic_mesh.cpp | 92 +++++++++ src/steam_audio_dynamic_mesh.h | 31 +++ src/steam_audio_globals.h | 7 + src/steam_audio_listener.cpp | 56 ++++-- src/steam_audio_listener.h | 26 +-- src/steam_audio_material.cpp | 39 ++++ src/steam_audio_material.h | 27 +++ src/steam_audio_scene.cpp | 95 --------- src/steam_audio_scene.h | 34 ---- src/steam_audio_source.cpp | 38 ++-- src/steam_audio_source.h | 37 ++-- src/steam_audio_static_mesh.cpp | 181 ++++++++++++++++++ src/steam_audio_static_mesh.h | 52 +++++ 20 files changed, 936 insertions(+), 281 deletions(-) create mode 100644 .clang-tidy delete mode 100644 install/SteamAudioGodot/SteamAudioGodot.gdextension create mode 100644 src/steam_audio_dynamic_mesh.cpp create mode 100644 src/steam_audio_dynamic_mesh.h create mode 100644 src/steam_audio_globals.h create mode 100644 src/steam_audio_material.cpp create mode 100644 src/steam_audio_material.h delete mode 100644 src/steam_audio_scene.cpp delete mode 100644 src/steam_audio_scene.h create mode 100644 src/steam_audio_static_mesh.cpp create mode 100644 src/steam_audio_static_mesh.h diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..cc9da32 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,147 @@ +# Generated from CLion Inspection settings +--- +Checks: '-*, +bugprone-argument-comment, +bugprone-assert-side-effect, +bugprone-bad-signal-to-kill-thread, +bugprone-branch-clone, +bugprone-copy-constructor-init, +bugprone-dangling-handle, +bugprone-dynamic-static-initializers, +bugprone-fold-init-type, +bugprone-forward-declaration-namespace, +bugprone-forwarding-reference-overload, +bugprone-inaccurate-erase, +bugprone-incorrect-roundings, +bugprone-integer-division, +bugprone-lambda-function-name, +bugprone-macro-parentheses, +bugprone-macro-repeated-side-effects, +bugprone-misplaced-operator-in-strlen-in-alloc, +bugprone-misplaced-pointer-arithmetic-in-alloc, +bugprone-misplaced-widening-cast, +bugprone-move-forwarding-reference, +bugprone-multiple-statement-macro, +bugprone-no-escape, +bugprone-parent-virtual-call, +bugprone-posix-return, +bugprone-reserved-identifier, +bugprone-sizeof-container, +bugprone-sizeof-expression, +bugprone-spuriously-wake-up-functions, +bugprone-string-constructor, +bugprone-string-integer-assignment, +bugprone-string-literal-with-embedded-nul, +bugprone-suspicious-enum-usage, +bugprone-suspicious-include, +bugprone-suspicious-memset-usage, +bugprone-suspicious-missing-comma, +bugprone-suspicious-semicolon, +bugprone-suspicious-string-compare, +bugprone-suspicious-memory-comparison, +bugprone-suspicious-realloc-usage, +bugprone-swapped-arguments, +bugprone-terminating-continue, +bugprone-throw-keyword-missing, +bugprone-too-small-loop-variable, +bugprone-undefined-memory-manipulation, +bugprone-undelegated-constructor, +bugprone-unhandled-self-assignment, +bugprone-unused-raii, +bugprone-unused-return-value, +bugprone-use-after-move, +bugprone-virtual-near-miss, +cert-dcl21-cpp, +cert-dcl58-cpp, +cert-err34-c, +cert-err52-cpp, +cert-err60-cpp, +cert-flp30-c, +cert-msc50-cpp, +cert-msc51-cpp, +cert-str34-c, +cppcoreguidelines-interfaces-global-init, +cppcoreguidelines-narrowing-conversions, +cppcoreguidelines-pro-type-member-init, +cppcoreguidelines-pro-type-static-cast-downcast, +cppcoreguidelines-slicing, +google-default-arguments, +google-explicit-constructor, +google-runtime-operator, +hicpp-exception-baseclass, +hicpp-multiway-paths-covered, +misc-misplaced-const, +misc-new-delete-overloads, +misc-no-recursion, +misc-non-copyable-objects, +misc-throw-by-value-catch-by-reference, +misc-unconventional-assign-operator, +misc-uniqueptr-reset-release, +modernize-avoid-bind, +modernize-concat-nested-namespaces, +modernize-deprecated-headers, +modernize-deprecated-ios-base-aliases, +modernize-loop-convert, +modernize-make-shared, +modernize-make-unique, +modernize-pass-by-value, +modernize-raw-string-literal, +modernize-redundant-void-arg, +modernize-replace-auto-ptr, +modernize-replace-disallow-copy-and-assign-macro, +modernize-replace-random-shuffle, +modernize-return-braced-init-list, +modernize-shrink-to-fit, +modernize-unary-static-assert, +modernize-use-auto, +modernize-use-bool-literals, +modernize-use-emplace, +modernize-use-equals-default, +modernize-use-equals-delete, +modernize-use-nodiscard, +modernize-use-noexcept, +modernize-use-nullptr, +modernize-use-override, +modernize-use-transparent-functors, +modernize-use-uncaught-exceptions, +mpi-buffer-deref, +mpi-type-mismatch, +openmp-use-default-none, +performance-faster-string-find, +performance-for-range-copy, +performance-implicit-conversion-in-loop, +performance-inefficient-algorithm, +performance-inefficient-string-concatenation, +performance-inefficient-vector-operation, +performance-move-const-arg, +performance-move-constructor-init, +performance-no-automatic-move, +performance-noexcept-move-constructor, +performance-trivially-destructible, +performance-type-promotion-in-math-fn, +performance-unnecessary-copy-initialization, +performance-unnecessary-value-param, +portability-simd-intrinsics, +readability-avoid-const-params-in-decls, +readability-const-return-type, +readability-container-size-empty, +readability-convert-member-functions-to-static, +readability-delete-null-pointer, +readability-deleted-default, +readability-inconsistent-declaration-parameter-name, +readability-make-member-function-const, +readability-misleading-indentation, +readability-misplaced-array-index, +readability-non-const-parameter, +readability-redundant-control-flow, +readability-redundant-declaration, +readability-redundant-function-ptr-dereference, +readability-redundant-smartptr-get, +readability-redundant-string-cstr, +readability-redundant-string-init, +readability-simplify-subscript-expr, +readability-static-accessed-through-instance, +readability-static-definition-in-anonymous-namespace, +readability-string-compare, +readability-uniqueptr-delete-release, +readability-use-anyofallof' \ No newline at end of file diff --git a/install/SteamAudioGodot/SteamAudioGodot.gdextension b/install/SteamAudioGodot/SteamAudioGodot.gdextension deleted file mode 100644 index 0d737af..0000000 --- a/install/SteamAudioGodot/SteamAudioGodot.gdextension +++ /dev/null @@ -1,11 +0,0 @@ -[configuration] -entry_symbol = "steam_audio_library_init" -compatibility_minimum = 4.1 - -[icons] -Example = "icons/Example.svg" - -[libraries] -linux.debug.x86_64 = "lib/Linux-x86_64/libSteamAudioGodot-d.so" -macos.debug = "lib/Darwin-Universal/libSteamAudioGodot-d.dylib" -windows.debug.x86_64 = "lib/Windows-AMD64/libSteamAudioGodot-d.dll" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0a86659..32ced1e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,8 +6,16 @@ target_sources( ${PROJECT_NAME} register_types.h steam_audio.cpp steam_audio.h - steam_audio_scene.cpp - steam_audio_scene.h + 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 ) target_include_directories( ${PROJECT_NAME} diff --git a/src/register_types.cpp b/src/register_types.cpp index c8d730f..8235627 100644 --- a/src/register_types.cpp +++ b/src/register_types.cpp @@ -1,31 +1,71 @@ -// src/register_types.cpp -#include "register_types.h" -#include "steam_audio.h" // your SteamAudio class declaration -#include "steam_audio_scene.h" - +#include "register_types.h" using namespace godot; void initialize_steam_audio(ModuleInitializationLevel p_level) { - if (p_level!=MODULE_INITIALIZATION_LEVEL_SERVERS) { + if (p_level!=MODULE_INITIALIZATION_LEVEL_SCENE) { return; } - /*if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) { - GDREGISTER_CLASS(SteamAudioEditorPlugin); - }*/ + register_steam_audio_settings(); GDREGISTER_CLASS(SteamAudio); - GDREGISTER_CLASS(SteamAudioScene); + GDREGISTER_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_SERVERS) { + if (p_level!=MODULE_INITIALIZATION_LEVEL_SCENE) { return; } } +void register_steam_audio_settings() { + ProjectSettings *settings = ProjectSettings::get_singleton(); + + {//Raytracer enum + settings->set("steam_audio/ray_tracer/RayTracer",0); + Dictionary info; + info["name"] = "steam_audio/ray_tracer/RayTracer"; + info["type"] = Variant::INT; + info["hint"] = PROPERTY_HINT_ENUM; + 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); + } + + {//spatialization mode enum + settings->set("steam_audio/spatializer/spatializer",0); + Dictionary info; + info["name"] = "steam_audio/spatializer/spatializer"; + info["type"] = Variant::INT; + info["hint"] = PROPERTY_HINT_ENUM; + info["hint_string"] = "Panning,HRTF,Ambisonic Pan,Ambisonic Binaural"; + info["usage"] = PROPERTY_USAGE_DEFAULT; + settings->add_property_info(info); + settings->set_initial_value("steam_audio/spatializer/spatializer",1); + } + + { + settings->set("steam_audio/spatializer/HRTF/Volume",0); + Dictionary info; + info["name"] = "steam_audio/spatializer/HRTF/Volume"; + info["type"] = Variant::FLOAT; + info["hint"] = PROPERTY_HINT_RANGE; + 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); + } + +} + extern "C" { // Initialization. GDExtensionBool GDE_EXPORT steam_audio_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, const GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) { - godot::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization); + GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization); init_obj.register_initializer(initialize_steam_audio); init_obj.register_terminator(uninitialize_steam_audio); diff --git a/src/register_types.h b/src/register_types.h index ad76b8b..914b7ac 100644 --- a/src/register_types.h +++ b/src/register_types.h @@ -1,11 +1,19 @@ -// -// Created by bryce on 5/7/2025. -// -#pragma once +#pragma once + +#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 // for ClassDB using namespace godot; -// Called by the InitObject below to register your SteamAudio class. +// Called by the InitObject to register your SteamAudio class. void initialize_steam_audio(ModuleInitializationLevel p_level); -void uninitialize_steam_audio(ModuleInitializationLevel p_level); \ No newline at end of file +void uninitialize_steam_audio(ModuleInitializationLevel p_level); +//registers settings in godot +void register_steam_audio_settings(); \ No newline at end of file diff --git a/src/steam_audio.cpp b/src/steam_audio.cpp index 0e38fac..3eb6cc4 100644 --- a/src/steam_audio.cpp +++ b/src/steam_audio.cpp @@ -1,43 +1,151 @@ -// -// Created by bryce on 5/7/2025. -// - -#include "steam_audio.h" +#include "steam_audio.h" using namespace godot; +IPLContext global_context = nullptr; +IPLScene global_scene = nullptr; +IPLSimulator global_simulator = nullptr; + +SteamAudio::SteamAudio() { + steam_audio=this; + initialize(); + +} + SteamAudio::~SteamAudio() { - if (context) - { - iplContextRelease(&context); - context=nullptr; - } - if (embree_device) { - iplEmbreeDeviceRelease(&embree_device); - embree_device=nullptr; - } + 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); } -SteamAudio::SteamAudio() = default; - -bool SteamAudio::initialize() - { - IPLContextSettings settings{}; - settings.version = STEAMAUDIO_VERSION; - - if ( IPLerror err = iplContextCreate( &settings, &context ); err != IPL_STATUS_SUCCESS) - { - UtilityFunctions::printerr("SteamAudio::initialize()", err); - return false; - } - IPLEmbreeDeviceSettings emb_device_settings{}; - if (iplEmbreeDeviceCreate(context, &emb_device_settings, &embree_device) != IPL_STATUS_SUCCESS) { - UtilityFunctions::printerr("SteamAudio::initialize(): failed to create Embree device"); - return false; +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; } - return true; - } \ No newline at end of file + 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() { + +} + +IPLCoordinateSpace3 SteamAudio::godot_to_ipl_space(const Transform3D &t) { + IPLCoordinateSpace3 s{}; + // pull columns via Basis.xform() + Vector3 right = t.basis.xform(Vector3(1, 0, 0)); + Vector3 up = t.basis.xform(Vector3(0, 1, 0)); + Vector3 ahead = t.basis.xform(Vector3(0, 0, -1)); // Godot forward is -Z + + s.right = { right.x, right.y, right.z }; + s.up = { up.x, up.y, up.z }; + s.ahead = { ahead.x, ahead.y, ahead.z }; + s.origin = { t.origin.x, t.origin.y, t.origin.z }; + + return s; +} + + +// Steam Audio → Godot space +Transform3D SteamAudio::ipl_space_to_godot(const IPLCoordinateSpace3 &s) { + // construct a Basis from column vectors + Basis b( + Vector3(s.right .x, s.right .y, s.right .z), + Vector3(s.up .x, s.up .y, s.up .z), + Vector3(-s.ahead.x, -s.ahead.y, -s.ahead.z) // invert ahead back to -Z + ); + + return Transform3D(b, Vector3(s.origin.x, s.origin.y, s.origin.z)); +} + +void SteamAudio::_ready() { + reflections_thread; + build_scene(); + iplSimulatorRunDirect(simulator); + +} + diff --git a/src/steam_audio.h b/src/steam_audio.h index e4c14d8..c07d078 100644 --- a/src/steam_audio.h +++ b/src/steam_audio.h @@ -1,31 +1,81 @@ -// -// Created by bryce on 5/7/2025. -// +#pragma once -#pragma once - -#include -#include +#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 RefCounted +class SteamAudio : public Node { - GDCLASS( SteamAudio,RefCounted ) // NOLINT(readability-use-auto) + GDCLASS( SteamAudio, Node ) // NOLINT(modernize-use-auto, hicpp-use-auto) private: - IPLContext context = nullptr; + 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;} - [[nodiscard]] IPLContext getContext() const{return context;} - [[nodiscard]] IPLEmbreeDevice getEmbreeDevice() const{return embree_device;} }; \ No newline at end of file diff --git a/src/steam_audio_dynamic_mesh.cpp b/src/steam_audio_dynamic_mesh.cpp new file mode 100644 index 0000000..f84184e --- /dev/null +++ b/src/steam_audio_dynamic_mesh.cpp @@ -0,0 +1,92 @@ +#include "steam_audio_dynamic_mesh.h" +#include "steam_audio_globals.h" // holds global_context & global_scene + +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); + } +} + +void SteamAudioDynamicMesh::_bind_methods() { + // no exposed properties for now +} + +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); +} + +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); +} + +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); +} + +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; +} diff --git a/src/steam_audio_dynamic_mesh.h b/src/steam_audio_dynamic_mesh.h new file mode 100644 index 0000000..675a125 --- /dev/null +++ b/src/steam_audio_dynamic_mesh.h @@ -0,0 +1,31 @@ +#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_globals.h b/src/steam_audio_globals.h new file mode 100644 index 0000000..0a9ee6c --- /dev/null +++ b/src/steam_audio_globals.h @@ -0,0 +1,7 @@ +// 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 f021d0e..fdfe5af 100644 --- a/src/steam_audio_listener.cpp +++ b/src/steam_audio_listener.cpp @@ -1,32 +1,46 @@ -// -// Created by bryce on 5/8/2025. -// +#include "steam_audio_listener.h" -#include "steam_audio_listener.h" +#include "phonon.h" using namespace godot; +SteamAudioListener::SteamAudioListener() = default; +SteamAudioListener::~SteamAudioListener() = default; + void SteamAudioListener::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_context", "ctx"), &SteamAudioListener::set_context); - ClassDB::bind_method(D_METHOD("_process","delta"), &SteamAudioListener::_process); - ADD_PROPERTY( - PropertyInfo(Variant::OBJECT, "context", PROPERTY_HINT_RESOURCE_TYPE, "SteamAudio"), - "set_context", "" - ); -} - -void SteamAudioListener::set_context(const Ref &p_ctx) { - ERR_FAIL_COND(!p_ctx.is_valid()); - ctx = p_ctx; } void SteamAudioListener::_process(double delta) { - ERR_FAIL_COND(!ctx.is_valid()); Transform3D transform = get_global_transform(); - IPLCoordinateSpace3 ls{}; - ls.origin = {transform.origin.x, transform.origin.y, transform.origin.z}; - Vector3 fwd = transform.basis.xform(Vector3(0,0,-1)), upv = transform.basis.xform(Vector3(0,1,0)); - ls.ahead = {fwd.x, fwd.y, fwd.z}; - ls.up = {upv.x, upv.y, upv.z}; + + 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; } diff --git a/src/steam_audio_listener.h b/src/steam_audio_listener.h index 9c3fd1e..53fb237 100644 --- a/src/steam_audio_listener.h +++ b/src/steam_audio_listener.h @@ -1,22 +1,24 @@ -// -// Created by bryce on 5/8/2025. -// +#pragma once -#pragma once -#include +#include #include -#include -#include "steam_audio.h" -#include +#include +#include using namespace godot; -class SteamAudioListener : public AudioListener3D { +class SteamAudioListener:public AudioListener3D +{ GDCLASS(SteamAudioListener,AudioListener3D) - Ref ctx; + + protected: static void _bind_methods(); + void _process(double p_delta) override; public: - void set_context(const Ref &p_ctx); - void _process(double delta) override; + SteamAudioListener(); + ~SteamAudioListener() override; + +private: + }; \ No newline at end of file diff --git a/src/steam_audio_material.cpp b/src/steam_audio_material.cpp new file mode 100644 index 0000000..5b068ad --- /dev/null +++ b/src/steam_audio_material.cpp @@ -0,0 +1,39 @@ +#include "steam_audio_material.h" + +using namespace godot; + +void SteamAudioMaterial::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_absorption"), &SteamAudioMaterial::get_absorption); + ClassDB::bind_method(D_METHOD("set_absorption","value"), &SteamAudioMaterial::set_absorption); + ClassDB::bind_method(D_METHOD("get_scattering"), &SteamAudioMaterial::get_scattering); + ClassDB::bind_method(D_METHOD("set_scattering","value"), &SteamAudioMaterial::set_scattering); + ClassDB::bind_method(D_METHOD("get_transmission"), &SteamAudioMaterial::get_transmission); + ClassDB::bind_method(D_METHOD("set_transmission","value"), &SteamAudioMaterial::set_transmission); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3,"absorption"), "set_absorption", "get_absorption"); + 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; + + material.scattering = scattering; + + material.transmission[0] = transmission.x; + material.transmission[1] = transmission.y; + material.transmission[2] = transmission.z; + + return material; +} + + diff --git a/src/steam_audio_material.h b/src/steam_audio_material.h new file mode 100644 index 0000000..1c053a2 --- /dev/null +++ b/src/steam_audio_material.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include "godot_cpp/godot.hpp" +#include +#include "phonon.h" + +using namespace godot; + +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); +public: + 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; +}; \ No newline at end of file diff --git a/src/steam_audio_scene.cpp b/src/steam_audio_scene.cpp deleted file mode 100644 index ee04e66..0000000 --- a/src/steam_audio_scene.cpp +++ /dev/null @@ -1,95 +0,0 @@ -// -// Created by bryce on 5/8/2025. -// - -#include "steam_audio_scene.h" - -using namespace godot; - - SteamAudioScene::SteamAudioScene() = default; - SteamAudioScene::~SteamAudioScene() { - if (scene) { - iplSceneRelease(&scene); - } - } - -void SteamAudioScene::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_context","ctx"), &SteamAudioScene::set_context); - ClassDB::bind_method(D_METHOD("add_mesh","mesh_node"), &SteamAudioScene::add_mesh); - ClassDB::bind_method(D_METHOD("commit"), &SteamAudioScene::commit); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"context",PROPERTY_HINT_RESOURCE_TYPE,"SteamAudio"), "set_context",""); - } - -void SteamAudioScene::set_context(const Ref &p_ctx) { - ERR_FAIL_COND(!p_ctx.is_valid()); - ctx = p_ctx; - if (scene) { - iplSceneRelease(&scene); - scene = nullptr; - } - IPLSceneSettings settings{}; - - settings.type = ctx-> getEmbreeDevice() ? IPL_SCENETYPE_EMBREE : IPL_SCENETYPE_DEFAULT; - settings.embreeDevice = ctx-> getEmbreeDevice(); - iplSceneCreate(ctx->getContext(), &settings, &scene); - } - -void SteamAudioScene::commit() const { - ERR_FAIL_COND(!scene); - ERR_FAIL_COND(!ctx.is_valid()); - iplSceneCommit(scene) ; - } -void SteamAudioScene::add_mesh(MeshInstance3D *mesh_node) { - ERR_FAIL_COND(!ctx.is_valid()); - ERR_FAIL_COND(!scene); - ERR_FAIL_COND(!mesh_node); - - // 1) Fetch the ArrayMesh from the MeshInstance3D - Ref mesh = mesh_node->get_mesh(); - ERR_FAIL_COND(!mesh.is_valid()); - - ArrayMesh *raw_am = Object::cast_to(mesh.ptr()); - ERR_FAIL_COND(!raw_am); - Ref am(raw_am); - ERR_FAIL_COND(!am.is_valid()); - - // 2) Pull out the raw arrays - Array arrays = am->surface_get_arrays(0); - PackedVector3Array verts = arrays[ArrayMesh::ARRAY_VERTEX]; - PackedInt32Array idxs = arrays[ArrayMesh::ARRAY_INDEX]; - - int vertex_count = verts.size(); - int index_count = idxs.size(); - int triangle_count = index_count / 3; - - // 3) Build Steam Audio’s settings struct - IPLStaticMeshSettings sm{}; - sm.numVertices = vertex_count; - sm.numTriangles = triangle_count; - sm.numMaterials = 0; - sm.vertices = reinterpret_cast( - const_cast(verts.ptr()) - ); - sm.materialIndices = nullptr; - sm.materials = nullptr; - - // 4) Convert the flat index list into IPLTriangle[] - IPLTriangle *tris = static_cast( - malloc(sizeof(IPLTriangle) * triangle_count) - ); - for (int i = 0; i < triangle_count; ++i) { - tris[i].indices[0] = idxs.ptr()[3*i + 0]; - tris[i].indices[1] = idxs.ptr()[3*i + 1]; - tris[i].indices[2] = idxs.ptr()[3*i + 2]; - } - sm.triangles = tris; - - // 5) Create & add the static mesh to the scene - IPLStaticMesh static_mesh = nullptr; - iplStaticMeshCreate(scene, &sm, &static_mesh); - iplStaticMeshAdd (static_mesh, scene); - iplStaticMeshRelease(&static_mesh); - - // 6) Clean up our temporary triangle array - ::free(tris); - } \ No newline at end of file diff --git a/src/steam_audio_scene.h b/src/steam_audio_scene.h deleted file mode 100644 index 9f79d20..0000000 --- a/src/steam_audio_scene.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include "godot_cpp/godot.hpp" -#include "phonon.h" -#include "steam_audio.h" - -using namespace godot; - -class SteamAudioScene : public RefCounted { - GDCLASS(SteamAudioScene, RefCounted); - - IPLScene scene = nullptr; - Ref ctx; - -protected: - static void _bind_methods(); -public: - SteamAudioScene(); - ~SteamAudioScene() override; - - void set_context(const Ref &p_ctx); - - void add_mesh(MeshInstance3D *mesh_node); - - void commit() const; -}; \ No newline at end of file diff --git a/src/steam_audio_source.cpp b/src/steam_audio_source.cpp index 0b5b688..c7a39cb 100644 --- a/src/steam_audio_source.cpp +++ b/src/steam_audio_source.cpp @@ -1,30 +1,22 @@ -// -// Created by bryce on 5/9/2025. -// +#include "steam_audio_source.h" -#include "steam_audio_source.h" - -#include "steam_audio.h" +#include "steam_audio_globals.h" using namespace godot; - - SteamAudioSource::SteamAudioSource() { - +SteamAudioSource::SteamAudioSource() { + iplSourceCreate(sa->get_simulator(),&settings,pSource); } - SteamAudioSource::~SteamAudioSource() { - if (steam_audio_source) { - iplSourceRelease(&steam_audio_source); - steam_audio_source = nullptr; - } +SteamAudioSource::~SteamAudioSource() { + iplSourceRelease(pSource); } - void SteamAudioSource::_bind_methods() { - ClassDB::bind_method(D_METHOD("play"), &SteamAudioSource::play); - ClassDB::bind_method(D_METHOD("stop"), &SteamAudioSource::stop); - ClassDB::bind_method(D_METHOD("set_stream","stream"), &SteamAudioSource::set_stream); - } +} -void SteamAudioSource::play() { - audio_player = memnew(AudioStreamPlayer3D); - add_child(audio_player); - } \ No newline at end of file +void SteamAudioSource::_process(double delta) { + update_position(); +} +bool SteamAudioSource::update_position() { + IPLCoordinateSpace3 current_pos = sa->godot_to_ipl_space(get_transform()); + + iplSource +} diff --git a/src/steam_audio_source.h b/src/steam_audio_source.h index 0cadc58..eec3738 100644 --- a/src/steam_audio_source.h +++ b/src/steam_audio_source.h @@ -1,32 +1,29 @@ -// -// Created by bryce on 5/9/2025. -// +#pragma once -#pragma once -#include #include - +#include +#include +#include +#include +#include +#include "steam_audio.h" #include "phonon.h" using namespace godot; -class SteamAudioSource:Node3D { - GDCLASS(SteamAudioSource, Node3D) -private: - AudioStreamPlayer3D* audio_player = nullptr; - IPLSource steam_audio_source = nullptr; +class SteamAudioSource: public Node3D +{ + GDCLASS(SteamAudioSource,Node3D) - bool initialized = false; + 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(); - void _ready() override; - void _process(double p_delta) override; - - void play(); - void stop(); - void set_stream(const Ref& p_stream); -protected: - static void _bind_methods(); }; \ No newline at end of file diff --git a/src/steam_audio_static_mesh.cpp b/src/steam_audio_static_mesh.cpp new file mode 100644 index 0000000..89fd39c --- /dev/null +++ b/src/steam_audio_static_mesh.cpp @@ -0,0 +1,181 @@ +// steam_audio_static_mesh.cpp +#include "steam_audio_static_mesh.h" + +#include +#include +#include +#include +#include +#include // IPLStaticMesh, IPLStaticMeshSettings, IPLMaterial + +using namespace godot; + +SteamAudioStaticMesh::SteamAudioStaticMesh() = default; + +SteamAudioStaticMesh::~SteamAudioStaticMesh() { + // release any previously created Steam Audio meshes + for (auto &sm : static_meshes) { + iplStaticMeshRelease(&sm); + } + static_meshes.clear(); +} + +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); + 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"), &SteamAudioStaticMesh::set_custom_proxy_mesh); + 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; +} + +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(); + + // 2) Pick which Mesh to read triangles from + Ref target; + switch (proxy_mode) { + case PROXY_NONE: + target = cast_to(get_parent())->get_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; + 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; + } + + if (!target.is_valid()) { + ERR_PRINT("SteamAudioStaticMesh: target mesh invalid"); + 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]; + + // --- 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; + + // --- fill out static mesh settings --- + IPLStaticMeshSettings settings{}; + + // Number of vertices + settings.numVertices = verts.size(); + + // 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"); + continue; + } + iplStaticMeshAdd(sm, global_scene); + static_meshes.push_back(sm);*/ + } + + // 4) Commit all additions at once + // iplSceneCommit(global_scene); +} diff --git a/src/steam_audio_static_mesh.h b/src/steam_audio_static_mesh.h new file mode 100644 index 0000000..e64a6e4 --- /dev/null +++ b/src/steam_audio_static_mesh.h @@ -0,0 +1,52 @@ +// steam_audio_proxy_mesh.h +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "steam_audio_material.h" + +using namespace godot; + +// Proxy generation modes +enum ProxyMode { + PROXY_NONE = 0, + PROXY_CONVEX = 1, + PROXY_CUSTOM = 2, +}; + +class SteamAudioStaticMesh : public Node3D { + GDCLASS(SteamAudioStaticMesh, Node3D) + +private: + int proxy_mode = PROXY_NONE; + Ref custom_proxy_mesh; + Ref default_material; + Vector static_meshes; + +protected: + static void _bind_methods(); + + +public: + SteamAudioStaticMesh(); + ~SteamAudioStaticMesh() override; + + // 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; + + void set_default_material(Ref mat); + Ref get_default_material() const; + + // Regenerates Steam Audio proxies + void generate_proxy_mesh(); +};