more stuffs
This commit is contained in:
147
.clang-tidy
Normal file
147
.clang-tidy
Normal file
@@ -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'
|
||||||
@@ -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"
|
|
||||||
@@ -6,8 +6,16 @@ target_sources( ${PROJECT_NAME}
|
|||||||
register_types.h
|
register_types.h
|
||||||
steam_audio.cpp
|
steam_audio.cpp
|
||||||
steam_audio.h
|
steam_audio.h
|
||||||
steam_audio_scene.cpp
|
steam_audio_material.cpp
|
||||||
steam_audio_scene.h
|
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}
|
target_include_directories( ${PROJECT_NAME}
|
||||||
|
|||||||
@@ -1,31 +1,71 @@
|
|||||||
// src/register_types.cpp
|
#include "register_types.h"
|
||||||
#include "register_types.h"
|
|
||||||
#include "steam_audio.h" // your SteamAudio class declaration
|
|
||||||
#include "steam_audio_scene.h"
|
|
||||||
|
|
||||||
|
|
||||||
using namespace godot;
|
using namespace godot;
|
||||||
|
|
||||||
void initialize_steam_audio(ModuleInitializationLevel p_level) {
|
void initialize_steam_audio(ModuleInitializationLevel p_level) {
|
||||||
if (p_level!=MODULE_INITIALIZATION_LEVEL_SERVERS) {
|
if (p_level!=MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/*if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
|
register_steam_audio_settings();
|
||||||
GDREGISTER_CLASS(SteamAudioEditorPlugin);
|
|
||||||
}*/
|
|
||||||
GDREGISTER_CLASS(SteamAudio);
|
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) {
|
void uninitialize_steam_audio(ModuleInitializationLevel p_level) {
|
||||||
if (p_level!=MODULE_INITIALIZATION_LEVEL_SERVERS) {
|
if (p_level!=MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||||
return;
|
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" {
|
extern "C" {
|
||||||
// Initialization.
|
// Initialization.
|
||||||
GDExtensionBool GDE_EXPORT steam_audio_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, const GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_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_initializer(initialize_steam_audio);
|
||||||
init_obj.register_terminator(uninitialize_steam_audio);
|
init_obj.register_terminator(uninitialize_steam_audio);
|
||||||
|
|||||||
@@ -1,11 +1,19 @@
|
|||||||
//
|
#pragma once
|
||||||
// Created by bryce on 5/7/2025.
|
|
||||||
//
|
#include <godot_cpp/classes/project_settings.hpp>
|
||||||
#pragma once
|
#include <godot_cpp/core/class_db.hpp>
|
||||||
|
|
||||||
|
#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 <godot_cpp/core/class_db.hpp> // for ClassDB
|
|
||||||
using namespace godot;
|
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 initialize_steam_audio(ModuleInitializationLevel p_level);
|
||||||
void uninitialize_steam_audio(ModuleInitializationLevel p_level);
|
void uninitialize_steam_audio(ModuleInitializationLevel p_level);
|
||||||
|
//registers settings in godot
|
||||||
|
void register_steam_audio_settings();
|
||||||
@@ -1,43 +1,151 @@
|
|||||||
//
|
#include "steam_audio.h"
|
||||||
// Created by bryce on 5/7/2025.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "steam_audio.h"
|
|
||||||
|
|
||||||
using namespace godot;
|
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()
|
||||||
{
|
{
|
||||||
if (context)
|
steam_audio = nullptr;
|
||||||
{
|
shutdown();
|
||||||
iplContextRelease(&context);
|
|
||||||
context=nullptr;
|
|
||||||
}
|
|
||||||
if (embree_device) {
|
|
||||||
iplEmbreeDeviceRelease(&embree_device);
|
|
||||||
embree_device=nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SteamAudio::_bind_methods() {
|
void SteamAudio::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("initialize"), &SteamAudio::initialize);
|
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() {
|
||||||
|
ctx_settings.version=STEAMAUDIO_VERSION;
|
||||||
bool SteamAudio::initialize()
|
IPLContext ctx = nullptr;
|
||||||
{
|
iplContextCreate(&ctx_settings, &ctx);
|
||||||
IPLContextSettings settings{};
|
iplSceneCreate(ctx,&scene_settings,&scene);
|
||||||
settings.version = STEAMAUDIO_VERSION;
|
iplSimulatorCreate(ctx,&simulation_settings,&simulator);
|
||||||
|
int ray_mode = proj_settings->get_setting("steam_audio/ray_tracer");
|
||||||
if ( IPLerror err = iplContextCreate( &settings, &context ); err != IPL_STATUS_SUCCESS)
|
switch (ray_mode) {
|
||||||
{
|
case 0://steam rt
|
||||||
UtilityFunctions::printerr("SteamAudio::initialize()", err);
|
break;
|
||||||
return false;
|
case 1: // embree rt
|
||||||
}
|
iplEmbreeDeviceCreate(ctx,&embree_device_settings,&embree_device);
|
||||||
IPLEmbreeDeviceSettings emb_device_settings{};
|
break;
|
||||||
if (iplEmbreeDeviceCreate(context, &emb_device_settings, &embree_device) != IPL_STATUS_SUCCESS) {
|
default:
|
||||||
UtilityFunctions::printerr("SteamAudio::initialize(): failed to create Embree device");
|
ERR_PRINT("Unknown Raytracer");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
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<NodePath> 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,31 +1,81 @@
|
|||||||
//
|
#pragma once
|
||||||
// Created by bryce on 5/7/2025.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
#include <godot_cpp/classes/os.hpp>
|
||||||
|
#include <godot_cpp/classes/engine.hpp>
|
||||||
#include <godot_cpp/godot.hpp>
|
#include <godot_cpp/classes/node.hpp>
|
||||||
#include<godot_cpp/core/class_db.hpp>
|
#include <godot_cpp/classes/project_settings.hpp>
|
||||||
#include <godot_cpp/classes/ref.hpp>
|
#include <godot_cpp/classes/ref.hpp>
|
||||||
|
#include <godot_cpp/classes/scene_tree.hpp>
|
||||||
|
#include <godot_cpp/classes/thread.hpp>
|
||||||
|
#include <godot_cpp/classes/time.hpp>
|
||||||
|
#include <godot_cpp/core/class_db.hpp>
|
||||||
|
#include <godot_cpp/godot.hpp>
|
||||||
#include <godot_cpp/variant/utility_functions.hpp>
|
#include <godot_cpp/variant/utility_functions.hpp>
|
||||||
#include <phonon.h>
|
#include <phonon.h>
|
||||||
|
#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;
|
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:
|
private:
|
||||||
IPLContext context = nullptr;
|
IPLContextSettings ctx_settings{};
|
||||||
|
IPLAudioSettings audio_settings{};
|
||||||
|
IPLContext ctx = nullptr;
|
||||||
|
IPLEmbreeDeviceSettings embree_device_settings{};
|
||||||
IPLEmbreeDevice embree_device = nullptr;
|
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<SteamAudioDynamicMesh> dynamic_geometry;
|
||||||
|
Array<SteamAudioStaticMesh> static_geometry;
|
||||||
|
Array<SteamAudioSource> sources;
|
||||||
|
Ref<Thread> reflections_thread;
|
||||||
|
Ref<Thread> pathing_thread;
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
void _ready() override;
|
||||||
public:
|
public:
|
||||||
|
static SteamAudio *steam_audio;
|
||||||
SteamAudio();
|
SteamAudio();
|
||||||
~SteamAudio() override;
|
~SteamAudio() override;
|
||||||
bool initialize();
|
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;}
|
|
||||||
};
|
};
|
||||||
92
src/steam_audio_dynamic_mesh.cpp
Normal file
92
src/steam_audio_dynamic_mesh.cpp
Normal file
@@ -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> mesh = cast_to<MeshInstance3D>(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<IPLVector3*>(const_cast<Vector3*>(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;
|
||||||
|
}
|
||||||
31
src/steam_audio_dynamic_mesh.h
Normal file
31
src/steam_audio_dynamic_mesh.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <godot_cpp/classes/mesh_instance3d.hpp>
|
||||||
|
#include <godot_cpp/core/class_db.hpp>
|
||||||
|
#include <phonon.h>
|
||||||
|
|
||||||
|
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();
|
||||||
|
};
|
||||||
7
src/steam_audio_globals.h
Normal file
7
src/steam_audio_globals.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
// steam_audio_globals.h
|
||||||
|
#pragma once
|
||||||
|
#include <phonon.h>
|
||||||
|
#include <godot_cpp/core/class_db.hpp>
|
||||||
|
extern IPLContext global_context;
|
||||||
|
extern IPLScene global_scene;
|
||||||
|
extern IPLSimulator global_simulator;
|
||||||
@@ -1,32 +1,46 @@
|
|||||||
//
|
#include "steam_audio_listener.h"
|
||||||
// Created by bryce on 5/8/2025.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "steam_audio_listener.h"
|
#include "phonon.h"
|
||||||
|
|
||||||
using namespace godot;
|
using namespace godot;
|
||||||
|
|
||||||
|
SteamAudioListener::SteamAudioListener() = default;
|
||||||
|
SteamAudioListener::~SteamAudioListener() = default;
|
||||||
|
|
||||||
void SteamAudioListener::_bind_methods() {
|
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<SteamAudio> &p_ctx) {
|
|
||||||
ERR_FAIL_COND(!p_ctx.is_valid());
|
|
||||||
ctx = p_ctx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SteamAudioListener::_process(double delta) {
|
void SteamAudioListener::_process(double delta) {
|
||||||
ERR_FAIL_COND(!ctx.is_valid());
|
|
||||||
Transform3D transform = get_global_transform();
|
Transform3D transform = get_global_transform();
|
||||||
IPLCoordinateSpace3 ls{};
|
|
||||||
ls.origin = {transform.origin.x, transform.origin.y, transform.origin.z};
|
IPLVector3 pos = {
|
||||||
Vector3 fwd = transform.basis.xform(Vector3(0,0,-1)), upv = transform.basis.xform(Vector3(0,1,0));
|
static_cast<float>(transform.origin.x),
|
||||||
ls.ahead = {fwd.x, fwd.y, fwd.z};
|
static_cast<float>(transform.origin.y),
|
||||||
ls.up = {upv.x, upv.y, upv.z};
|
static_cast<float>(transform.origin.z)
|
||||||
|
};
|
||||||
|
Vector3 godot_fwd = transform.basis.xform(Vector3(0, 0, -1));
|
||||||
|
IPLVector3 fwd = {
|
||||||
|
static_cast<float>(godot_fwd.x),
|
||||||
|
static_cast<float>(godot_fwd.y),
|
||||||
|
static_cast<float>(godot_fwd.z)
|
||||||
|
};
|
||||||
|
Vector3 godot_up = transform.basis.xform(Vector3(0, 1, 0));
|
||||||
|
IPLVector3 up = {
|
||||||
|
static_cast<float>(godot_up.x),
|
||||||
|
static_cast<float>(godot_up.y),
|
||||||
|
static_cast<float>(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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,24 @@
|
|||||||
//
|
#pragma once
|
||||||
// Created by bryce on 5/8/2025.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
#include<godot_cpp/godot.hpp>
|
||||||
#include <godot_cpp/classes/node3d.hpp>
|
|
||||||
#include <godot_cpp/classes/audio_listener3d.hpp>
|
#include <godot_cpp/classes/audio_listener3d.hpp>
|
||||||
#include <godot_cpp/godot.hpp>
|
#include <godot_cpp/core/class_db.hpp>
|
||||||
#include "steam_audio.h"
|
#include <godot_cpp/classes/wrapped.hpp>
|
||||||
#include <phonon.h>
|
|
||||||
|
|
||||||
using namespace godot;
|
using namespace godot;
|
||||||
|
|
||||||
class SteamAudioListener : public AudioListener3D {
|
class SteamAudioListener:public AudioListener3D
|
||||||
|
{
|
||||||
GDCLASS(SteamAudioListener,AudioListener3D)
|
GDCLASS(SteamAudioListener,AudioListener3D)
|
||||||
Ref<SteamAudio> ctx;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
void _process(double p_delta) override;
|
||||||
public:
|
public:
|
||||||
void set_context(const Ref<SteamAudio> &p_ctx);
|
SteamAudioListener();
|
||||||
void _process(double delta) override;
|
~SteamAudioListener() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
};
|
};
|
||||||
39
src/steam_audio_material.cpp
Normal file
39
src/steam_audio_material.cpp
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
27
src/steam_audio_material.h
Normal file
27
src/steam_audio_material.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <godot_cpp/classes/resource.hpp>
|
||||||
|
#include "godot_cpp/godot.hpp"
|
||||||
|
#include <godot_cpp/core/class_db.hpp>
|
||||||
|
#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;
|
||||||
|
};
|
||||||
@@ -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<SteamAudio> &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 = mesh_node->get_mesh();
|
|
||||||
ERR_FAIL_COND(!mesh.is_valid());
|
|
||||||
|
|
||||||
ArrayMesh *raw_am = Object::cast_to<ArrayMesh>(mesh.ptr());
|
|
||||||
ERR_FAIL_COND(!raw_am);
|
|
||||||
Ref<ArrayMesh> 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<IPLVector3*>(
|
|
||||||
const_cast<Vector3*>(verts.ptr())
|
|
||||||
);
|
|
||||||
sm.materialIndices = nullptr;
|
|
||||||
sm.materials = nullptr;
|
|
||||||
|
|
||||||
// 4) Convert the flat index list into IPLTriangle[]
|
|
||||||
IPLTriangle *tris = static_cast<IPLTriangle*>(
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <godot_cpp/classes/array_mesh.hpp>
|
|
||||||
#include <godot_cpp/classes/mesh_instance3d.hpp>
|
|
||||||
#include <godot_cpp/classes/ref_counted.hpp>
|
|
||||||
#include <godot_cpp/variant/typed_array.hpp>
|
|
||||||
#include <godot_cpp/variant/utility_functions.hpp>
|
|
||||||
#include <godot_cpp/variant/packed_vector3_array.hpp>
|
|
||||||
#include <godot_cpp/variant/packed_int32_array.hpp>
|
|
||||||
#include <godot_cpp/classes/object.hpp>
|
|
||||||
#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<SteamAudio> ctx;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static void _bind_methods();
|
|
||||||
public:
|
|
||||||
SteamAudioScene();
|
|
||||||
~SteamAudioScene() override;
|
|
||||||
|
|
||||||
void set_context(const Ref<SteamAudio> &p_ctx);
|
|
||||||
|
|
||||||
void add_mesh(MeshInstance3D *mesh_node);
|
|
||||||
|
|
||||||
void commit() const;
|
|
||||||
};
|
|
||||||
@@ -1,30 +1,22 @@
|
|||||||
//
|
#include "steam_audio_source.h"
|
||||||
// Created by bryce on 5/9/2025.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "steam_audio_source.h"
|
#include "steam_audio_globals.h"
|
||||||
|
|
||||||
#include "steam_audio.h"
|
|
||||||
|
|
||||||
using namespace godot;
|
using namespace godot;
|
||||||
|
SteamAudioSource::SteamAudioSource() {
|
||||||
SteamAudioSource::SteamAudioSource() {
|
iplSourceCreate(sa->get_simulator(),&settings,pSource);
|
||||||
|
|
||||||
}
|
}
|
||||||
SteamAudioSource::~SteamAudioSource() {
|
SteamAudioSource::~SteamAudioSource() {
|
||||||
if (steam_audio_source) {
|
iplSourceRelease(pSource);
|
||||||
iplSourceRelease(&steam_audio_source);
|
|
||||||
steam_audio_source = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SteamAudioSource::_bind_methods() {
|
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() {
|
void SteamAudioSource::_process(double delta) {
|
||||||
audio_player = memnew(AudioStreamPlayer3D);
|
update_position();
|
||||||
add_child(audio_player);
|
}
|
||||||
}
|
bool SteamAudioSource::update_position() {
|
||||||
|
IPLCoordinateSpace3 current_pos = sa->godot_to_ipl_space(get_transform());
|
||||||
|
|
||||||
|
iplSource
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,32 +1,29 @@
|
|||||||
//
|
#pragma once
|
||||||
// Created by bryce on 5/9/2025.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include <godot_cpp/classes/audio_stream_player3d.hpp>
|
|
||||||
#include <godot_cpp/classes/node3d.hpp>
|
#include <godot_cpp/classes/node3d.hpp>
|
||||||
|
#include <godot_cpp/classes/audio_stream_generator.hpp>
|
||||||
|
#include <godot_cpp/classes/audio_stream_generator_playback.hpp>
|
||||||
|
#include <godot_cpp/classes/audio_stream_player3d.hpp>
|
||||||
|
#include <godot_cpp/godot.hpp>
|
||||||
|
#include <godot_cpp/core/class_db.hpp>
|
||||||
|
#include "steam_audio.h"
|
||||||
#include "phonon.h"
|
#include "phonon.h"
|
||||||
|
|
||||||
using namespace godot;
|
using namespace godot;
|
||||||
|
|
||||||
class SteamAudioSource:Node3D {
|
class SteamAudioSource: public Node3D
|
||||||
GDCLASS(SteamAudioSource, Node3D)
|
{
|
||||||
private:
|
GDCLASS(SteamAudioSource,Node3D)
|
||||||
AudioStreamPlayer3D* audio_player = nullptr;
|
|
||||||
IPLSource steam_audio_source = nullptr;
|
|
||||||
|
|
||||||
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:
|
public:
|
||||||
SteamAudioSource();
|
SteamAudioSource();
|
||||||
~SteamAudioSource();
|
~SteamAudioSource();
|
||||||
|
bool update_position();
|
||||||
|
|
||||||
void _ready() override;
|
|
||||||
void _process(double p_delta) override;
|
|
||||||
|
|
||||||
void play();
|
|
||||||
void stop();
|
|
||||||
void set_stream(const Ref<AudioStream>& p_stream);
|
|
||||||
protected:
|
|
||||||
static void _bind_methods();
|
|
||||||
};
|
};
|
||||||
181
src/steam_audio_static_mesh.cpp
Normal file
181
src/steam_audio_static_mesh.cpp
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
// steam_audio_static_mesh.cpp
|
||||||
|
#include "steam_audio_static_mesh.h"
|
||||||
|
|
||||||
|
#include <godot_cpp/classes/array_mesh.hpp>
|
||||||
|
#include <godot_cpp/classes/convex_polygon_shape3d.hpp>
|
||||||
|
#include <godot_cpp/classes/shape3d.hpp>
|
||||||
|
#include <godot_cpp/variant/packed_int32_array.hpp>
|
||||||
|
#include <godot_cpp/variant/packed_vector3_array.hpp>
|
||||||
|
#include <phonon.h> // 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> mesh) {
|
||||||
|
custom_proxy_mesh = mesh;
|
||||||
|
}
|
||||||
|
Ref<Mesh> SteamAudioStaticMesh::get_custom_proxy_mesh() const {
|
||||||
|
return custom_proxy_mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SteamAudioStaticMesh::set_default_material(Ref<SteamAudioMaterial> mat) {
|
||||||
|
default_material = mat;
|
||||||
|
}
|
||||||
|
Ref<SteamAudioMaterial> 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<Mesh> target;
|
||||||
|
switch (proxy_mode) {
|
||||||
|
case PROXY_NONE:
|
||||||
|
target = cast_to<MeshInstance3D>(get_parent())->get_mesh();
|
||||||
|
break;
|
||||||
|
case PROXY_CONVEX: {
|
||||||
|
Ref<Shape3D> hull_shape = cast_to<MeshInstance3D>(get_parent())->get_mesh()->create_convex_shape();
|
||||||
|
ConvexPolygonShape3D *convex = cast_to<ConvexPolygonShape3D>(hull_shape.ptr());
|
||||||
|
if (!convex) {
|
||||||
|
ERR_PRINT("SteamAudioStaticMesh: convex cast failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Ref<ArrayMesh> 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<Material> gm = target->surface_get_material(s);
|
||||||
|
Ref<SteamAudioMaterial> 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<const IPLVector3 *>(verts.ptr());
|
||||||
|
|
||||||
|
// drop the const so it matches IPLStaticMeshSettings::vertices (IPLVector3*)
|
||||||
|
IPLVector3 *writable_vertices = const_cast<IPLVector3 *>(raw_vertices);
|
||||||
|
settings.vertices = writable_vertices;
|
||||||
|
|
||||||
|
// Number of triangles
|
||||||
|
settings.numTriangles = idxs.size() / 3;
|
||||||
|
|
||||||
|
// build triangle array
|
||||||
|
std::vector<IPLTriangle> triangles;
|
||||||
|
triangles.reserve(settings.numTriangles);
|
||||||
|
for (int i = 0; i < settings.numTriangles; ++i) {
|
||||||
|
IPLTriangle tri{};
|
||||||
|
tri.indices[0] = static_cast<uint32_t>(idxs[3*i + 0]);
|
||||||
|
tri.indices[1] = static_cast<uint32_t>(idxs[3*i + 1]);
|
||||||
|
tri.indices[2] = static_cast<uint32_t>(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);
|
||||||
|
}
|
||||||
52
src/steam_audio_static_mesh.h
Normal file
52
src/steam_audio_static_mesh.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// steam_audio_proxy_mesh.h
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <godot_cpp/core/class_db.hpp>
|
||||||
|
#include <godot_cpp/classes/mesh_instance3d.hpp>
|
||||||
|
#include <godot_cpp/classes/mesh.hpp>
|
||||||
|
#include <godot_cpp/classes/shape3d.hpp>
|
||||||
|
#include <godot_cpp/classes/convex_polygon_shape3d.hpp>
|
||||||
|
#include <godot_cpp/classes/array_mesh.hpp>
|
||||||
|
#include <godot_cpp/classes/material.hpp>
|
||||||
|
|
||||||
|
#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<Mesh> custom_proxy_mesh;
|
||||||
|
Ref<SteamAudioMaterial> default_material;
|
||||||
|
Vector<IPLStaticMesh> 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> mesh);
|
||||||
|
Ref<Mesh> get_custom_proxy_mesh() const;
|
||||||
|
|
||||||
|
void set_default_material(Ref<SteamAudioMaterial> mat);
|
||||||
|
Ref<SteamAudioMaterial> get_default_material() const;
|
||||||
|
|
||||||
|
// Regenerates Steam Audio proxies
|
||||||
|
void generate_proxy_mesh();
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user