mirror of https://github.com/bjornbytes/lovr.git
phonon: setGeometry test;
This commit is contained in:
parent
00a71870c2
commit
87bbec7018
|
@ -249,7 +249,8 @@ ifneq (@(CMAKE_DEPS),)
|
|||
|
||||
# Phonon
|
||||
CFLAGS_@(STEAM_AUDIO) += -I@(STEAM_AUDIO_PATH)/include
|
||||
LIBS_@(STEAM_AUDIO)_$(win32) += @(STEAM_AUDIO_PATH)/lib/Windows/x64/phonon.dll
|
||||
LIBS_@(STEAM_AUDIO)_$(win32) += @(STEAM_AUDIO_PATH)/bin/Windows/x64/phonon.dll
|
||||
LIBS_@(STEAM_AUDIO)_$(macos) += @(STEAM_AUDIO_PATH)/lib/OSX/libphonon.dylib
|
||||
LIBS_@(STEAM_AUDIO)_$(linux) += @(STEAM_AUDIO_PATH)/lib/Linux/x64/libphonon.so
|
||||
LIBS_@(STEAM_AUDIO)_$(android) += @(STEAM_AUDIO_PATH)/lib/Android/arm64/libphonon.so
|
||||
endif
|
||||
|
|
|
@ -341,3 +341,32 @@ void luax_readcolor(lua_State* L, int index, Color* color) {
|
|||
luaL_error(L, "Invalid color, expected a hexcode, 3 numbers, 4 numbers, or a table");
|
||||
}
|
||||
}
|
||||
|
||||
int luax_readtriangles(lua_State* L, int index, float** vertices, uint32_t* vertexCount, uint32_t** indices, uint32_t* indexCount, bool* shouldFree) {
|
||||
if (lua_istable(L, index)) {
|
||||
luaL_checktype(L, index + 1, LUA_TTABLE);
|
||||
*vertexCount = luax_len(L, index) / 3;
|
||||
*indexCount = luax_len(L, index + 1);
|
||||
lovrAssert(*indexCount % 3 == 0, "Index count must be a multiple of 3");
|
||||
*vertices = malloc(sizeof(float) * *vertexCount * 3);
|
||||
*indices = malloc(sizeof(uint32_t) * *indexCount);
|
||||
lovrAssert(vertices && indices, "Out of memory");
|
||||
*shouldFree = true;
|
||||
|
||||
for (uint32_t i = 0; i < *vertexCount * 3; i++) {
|
||||
lua_rawgeti(L, index, i + 1);
|
||||
(*vertices)[i] = luax_checkfloat(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < *indexCount; i++) {
|
||||
lua_rawgeti(L, index + 1, i + 1);
|
||||
(*indices)[i] = luaL_checkinteger(L, -1) - 1;
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
return index + 2;
|
||||
}
|
||||
|
||||
return luaL_argerror(L, index, "table or Model");
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#pragma once
|
||||
|
@ -158,6 +159,7 @@ int luax_setconf(lua_State* L);
|
|||
void luax_setmainthread(lua_State* L);
|
||||
void luax_atexit(lua_State* L, void (*destructor)(void));
|
||||
void luax_readcolor(lua_State* L, int index, struct Color* color);
|
||||
int luax_readtriangles(lua_State* L, int index, float** vertices, uint32_t* vertexCount, uint32_t** indices, uint32_t* indexCount, bool* shouldFree);
|
||||
|
||||
// Module helpers
|
||||
|
||||
|
|
|
@ -105,6 +105,21 @@ static int l_lovrAudioSetPose(lua_State *L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int l_lovrAudioSetGeometry(lua_State* L) {
|
||||
float* vertices;
|
||||
uint32_t* indices;
|
||||
uint32_t vertexCount, indexCount;
|
||||
bool shouldFree;
|
||||
luax_readtriangles(L, 1, &vertices, &vertexCount, &indices, &indexCount, &shouldFree);
|
||||
bool success = lovrAudioSetGeometry(vertices, indices, vertexCount, indexCount);
|
||||
if (shouldFree) {
|
||||
free(vertices);
|
||||
free(indices);
|
||||
}
|
||||
lua_pushboolean(L, success);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrAudioGetSpatializer(lua_State *L) {
|
||||
lua_pushstring(L, lovrAudioGetSpatializer());
|
||||
return 1;
|
||||
|
@ -151,6 +166,7 @@ static const luaL_Reg lovrAudio[] = {
|
|||
{ "setVolume", l_lovrAudioSetVolume },
|
||||
{ "getPose", l_lovrAudioGetPose },
|
||||
{ "setPose", l_lovrAudioSetPose },
|
||||
{ "setGeometry", l_lovrAudioSetGeometry },
|
||||
{ "getSpatializer", l_lovrAudioGetSpatializer },
|
||||
{ "getCaptureStream", l_lovrAudioGetCaptureStream },
|
||||
{ "newSource", l_lovrAudioNewSource },
|
||||
|
|
|
@ -328,6 +328,10 @@ void lovrAudioSetPose(float position[4], float orientation[4]) {
|
|||
state.spatializer->setListenerPose(position, orientation);
|
||||
}
|
||||
|
||||
bool lovrAudioSetGeometry(float* vertices, uint32_t* indices, uint32_t vertexCount, uint32_t indexCount) {
|
||||
return state.spatializer->setGeometry(vertices, indices, vertexCount, indexCount);
|
||||
}
|
||||
|
||||
const char* lovrAudioGetSpatializer() {
|
||||
return state.spatializer->name;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ float lovrAudioGetVolume(void);
|
|||
void lovrAudioSetVolume(float volume);
|
||||
void lovrAudioGetPose(float position[4], float orientation[4]);
|
||||
void lovrAudioSetPose(float position[4], float orientation[4]);
|
||||
bool lovrAudioSetGeometry(float* vertices, uint32_t* indices, uint32_t vertexCount, uint32_t indexCount);
|
||||
const char* lovrAudioGetSpatializer(void);
|
||||
struct Sound* lovrAudioGetCaptureStream(void);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ typedef struct {
|
|||
// return value is number of stereo frames written.
|
||||
uint32_t (*tail)(float* scratch, float* output, uint32_t frames);
|
||||
void (*setListenerPose)(float position[4], float orientation[4]);
|
||||
bool (*setGeometry)(float* vertices, uint32_t* indices, uint32_t vertexCount, uint32_t indexCount);
|
||||
void (*sourceCreate)(Source* source);
|
||||
void (*sourceDestroy)(Source* source);
|
||||
const char* name;
|
||||
|
|
|
@ -279,6 +279,10 @@ static void oculus_spatializer_setListenerPose(float position[4], float orientat
|
|||
ma_mutex_unlock(&state.poseLock);
|
||||
}
|
||||
|
||||
bool oculus_setGeometry(float* vertices, uint32_t* indices, uint32_t vertexCount, uint32_t indexCount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static void oculus_spatializer_source_create(Source* source) {
|
||||
intptr_t* spatializerMemo = lovrSourceGetSpatializerMemoField(source);
|
||||
*spatializerMemo = -1;
|
||||
|
@ -297,6 +301,7 @@ Spatializer oculusSpatializer = {
|
|||
.apply = oculus_spatializer_source_apply,
|
||||
.tail = oculus_spatializer_tail,
|
||||
.setListenerPose = oculus_spatializer_setListenerPose,
|
||||
.setGeometry = oculus_setGeometry,
|
||||
.sourceCreate = oculus_spatializer_source_create,
|
||||
.sourceDestroy = oculus_spatializer_source_destroy, // Need noop
|
||||
.name = "oculus"
|
||||
|
|
|
@ -12,7 +12,11 @@ static FARPROC phonon_dlsym(void* library, const char* symbol) { return GetProcA
|
|||
static void phonon_dlclose(void* library) { FreeLibrary(library); }
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#if __APPLE__
|
||||
#define PHONON_LIBRARY "libphonon.dylib"
|
||||
#else
|
||||
#define PHONON_LIBRARY "libphonon.so"
|
||||
#endif
|
||||
static void* phonon_dlopen(const char* library) { return dlopen(library, RTLD_NOW | RTLD_LOCAL); }
|
||||
static void* phonon_dlsym(void* library, const char* symbol) { return dlsym(library, symbol); }
|
||||
static void phonon_dlclose(void* library) { dlclose(library); }
|
||||
|
@ -21,6 +25,11 @@ static void phonon_dlclose(void* library) { dlclose(library); }
|
|||
typedef IPLerror fn_iplCreateContext(IPLLogFunction logCallback, IPLAllocateFunction allocateCallback, IPLFreeFunction freeCallback, IPLhandle* context);
|
||||
typedef IPLvoid fn_iplDestroyContext(IPLhandle* context);
|
||||
typedef IPLvoid fn_iplCleanup(void);
|
||||
typedef IPLerror fn_iplCreateScene(IPLhandle context, IPLhandle computeDevice, IPLSceneType sceneType, IPLint32 numMaterials, IPLMaterial* materials, IPLClosestHitCallback closestHitCallback, IPLAnyHitCallback anyHitCallback, IPLBatchedClosestHitCallback batchedClosestHitCallback, IPLBatchedAnyHitCallback batchedAnyHitCallback, IPLvoid* userData, IPLhandle* scene);
|
||||
typedef IPLerror fn_iplDestroyScene(IPLhandle* scene);
|
||||
typedef IPLvoid fn_iplSaveSceneAsObj(IPLhandle scene, IPLstring fileBaseName);
|
||||
typedef IPLerror fn_iplCreateStaticMesh(IPLhandle scene, IPLint32 numVertices, IPLint32 numTriangles, IPLVector3* vertices, IPLTriangle* triangles, IPLint32* materialIndices, IPLhandle* staticMesh);
|
||||
typedef IPLerror fn_iplDestroyStaticMesh(IPLhandle* staticMesh);
|
||||
typedef IPLerror fn_iplCreateEnvironment(IPLhandle context, IPLhandle computeDevice, IPLSimulationSettings simulationSettings, IPLhandle scene, IPLhandle probeManager, IPLhandle* environment);
|
||||
typedef IPLvoid fn_iplDestroyEnvironment(IPLhandle* environment);
|
||||
typedef IPLerror fn_iplCreateDirectSoundEffect(IPLAudioFormat inputFormat, IPLAudioFormat outputFormat, IPLRenderingSettings renderingSettings, IPLhandle* effect);
|
||||
|
@ -39,6 +48,11 @@ typedef IPLvoid fn_iplApplyBinauralEffect(IPLhandle effect, IPLhandle binauralRe
|
|||
X(iplCreateContext)\
|
||||
X(iplDestroyContext)\
|
||||
X(iplCleanup)\
|
||||
X(iplCreateScene)\
|
||||
X(iplDestroyScene)\
|
||||
X(iplSaveSceneAsObj)\
|
||||
X(iplCreateStaticMesh)\
|
||||
X(iplDestroyStaticMesh)\
|
||||
X(iplCreateEnvironment)\
|
||||
X(iplDestroyEnvironment)\
|
||||
X(iplCreateDirectSoundEffect)\
|
||||
|
@ -56,6 +70,8 @@ PHONON_FOREACH(PHONON_DECLARE)
|
|||
static struct {
|
||||
void* library;
|
||||
IPLhandle context;
|
||||
IPLhandle scene;
|
||||
IPLhandle mesh;
|
||||
IPLhandle environment;
|
||||
IPLhandle directSoundEffect;
|
||||
IPLhandle binauralRenderer;
|
||||
|
@ -124,6 +140,8 @@ void phonon_destroy() {
|
|||
if (state.binauralRenderer) phonon_iplDestroyBinauralRenderer(&state.binauralRenderer);
|
||||
if (state.directSoundEffect) phonon_iplDestroyDirectSoundEffect(&state.directSoundEffect);
|
||||
if (state.environment) phonon_iplDestroyEnvironment(&state.environment);
|
||||
if (state.mesh) phonon_iplDestroyStaticMesh(&state.mesh);
|
||||
if (state.scene) phonon_iplDestroyStaticMesh(&state.scene);
|
||||
if (state.context) phonon_iplDestroyContext(&state.context);
|
||||
phonon_iplCleanup();
|
||||
phonon_dlclose(state.library);
|
||||
|
@ -171,9 +189,9 @@ uint32_t phonon_apply(Source* source, const float* input, float* output, uint32_
|
|||
.airAbsorptionModel.coefficients = { absorption[0], absorption[1], absorption[2] }
|
||||
};
|
||||
|
||||
IPLDirectOcclusionMode occlusionMode = IPL_DIRECTOCCLUSION_NONE;
|
||||
IPLDirectOcclusionMethod occlusionMethod = IPL_DIRECTOCCLUSION_RAYCAST;
|
||||
IPLDirectSoundPath path = phonon_iplGetDirectSoundPath(state.environment, listenerPosition, listenerForward, listenerUp, iplSource, 0.f, 1, occlusionMode, occlusionMethod);
|
||||
IPLDirectOcclusionMode occlusionMode = IPL_DIRECTOCCLUSION_TRANSMISSIONBYFREQUENCY;
|
||||
IPLDirectOcclusionMethod occlusionMethod = IPL_DIRECTOCCLUSION_VOLUMETRIC;
|
||||
IPLDirectSoundPath path = phonon_iplGetDirectSoundPath(state.environment, listenerPosition, listenerForward, listenerUp, iplSource, .5f, 32, occlusionMode, occlusionMethod);
|
||||
|
||||
IPLDirectSoundEffectOptions options = {
|
||||
.applyDistanceAttenuation = falloff > 0.f ? IPL_TRUE : IPL_FALSE,
|
||||
|
@ -230,6 +248,61 @@ void phonon_setListenerPose(float position[4], float orientation[4]) {
|
|||
memcpy(state.listenerOrientation, orientation, sizeof(state.listenerOrientation));
|
||||
}
|
||||
|
||||
bool phonon_setGeometry(float* vertices, uint32_t* indices, uint32_t vertexCount, uint32_t indexCount) {
|
||||
if (state.mesh) phonon_iplDestroyStaticMesh(&state.mesh);
|
||||
if (state.scene) phonon_iplDestroyScene(&state.scene);
|
||||
if (state.environment) phonon_iplDestroyEnvironment(&state.environment);
|
||||
|
||||
IPLMaterial material = (IPLMaterial) {
|
||||
.lowFreqAbsorption = .1f,
|
||||
.midFreqAbsorption = .2f,
|
||||
.highFreqAbsorption = .3f,
|
||||
.scattering = .05f,
|
||||
.lowFreqTransmission = .1f,
|
||||
.midFreqTransmission = .05f,
|
||||
.highFreqTransmission = .03f
|
||||
};
|
||||
|
||||
IPLSimulationSettings settings = (IPLSimulationSettings) {
|
||||
.sceneType = IPL_SCENETYPE_PHONON,
|
||||
.maxNumOcclusionSamples = 32,
|
||||
.numRays = 4096,
|
||||
.numDiffuseSamples = 1024,
|
||||
.numBounces = 8,
|
||||
.numThreads = 1,
|
||||
.irDuration = 1.f,
|
||||
.ambisonicsOrder = 1,
|
||||
.maxConvolutionSources = 64,
|
||||
.bakingBatchSize = 1,
|
||||
.irradianceMinDistance = .1f
|
||||
};
|
||||
|
||||
IPLint32* materials = malloc(indexCount / 3 * sizeof(IPLint32));
|
||||
if (!materials) goto fail;
|
||||
memset(materials, 0, indexCount / 3 * sizeof(IPLint32));
|
||||
|
||||
IPLerror status;
|
||||
status = phonon_iplCreateScene(state.context, NULL, IPL_SCENETYPE_PHONON, 1, &material, NULL, NULL, NULL, NULL, NULL, &state.scene);
|
||||
if (status != IPL_STATUS_SUCCESS) goto fail;
|
||||
|
||||
status = phonon_iplCreateStaticMesh(state.scene, vertexCount, indexCount / 3, (IPLVector3*) vertices, (IPLTriangle*) indices, materials, &state.mesh);
|
||||
if (status != IPL_STATUS_SUCCESS) goto fail;
|
||||
|
||||
status = phonon_iplCreateEnvironment(state.context, NULL, settings, state.scene, NULL, &state.environment);
|
||||
if (status != IPL_STATUS_SUCCESS) goto fail;
|
||||
|
||||
free(materials);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
free(materials);
|
||||
if (state.mesh) phonon_iplDestroyStaticMesh(&state.mesh);
|
||||
if (state.scene) phonon_iplDestroyScene(&state.scene);
|
||||
if (state.environment) phonon_iplDestroyEnvironment(&state.environment);
|
||||
phonon_iplCreateEnvironment(state.context, NULL, settings, NULL, NULL, &state.environment);
|
||||
return false;
|
||||
}
|
||||
|
||||
void phonon_sourceCreate(Source* source) {
|
||||
//
|
||||
}
|
||||
|
@ -244,6 +317,7 @@ Spatializer phononSpatializer = {
|
|||
.apply = phonon_apply,
|
||||
.tail = phonon_tail,
|
||||
.setListenerPose = phonon_setListenerPose,
|
||||
.setGeometry = phonon_setGeometry,
|
||||
.sourceCreate = phonon_sourceCreate,
|
||||
.sourceDestroy = phonon_sourceDestroy,
|
||||
.name = "phonon"
|
||||
|
|
|
@ -51,6 +51,10 @@ void simple_spatializer_setListenerPose(float position[4], float orientation[4])
|
|||
mat4_rotateQuat(state.listener, orientation);
|
||||
}
|
||||
|
||||
bool simple_setGeometry(float* vertices, uint32_t* indices, uint32_t vertexCount, uint32_t indexCount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void simple_spatializer_source_create(Source* source) {
|
||||
//
|
||||
}
|
||||
|
@ -65,6 +69,7 @@ Spatializer simpleSpatializer = {
|
|||
.apply = simple_spatializer_source_apply,
|
||||
.tail = simple_spatializer_tail,
|
||||
.setListenerPose = simple_spatializer_setListenerPose,
|
||||
.setGeometry = simple_setGeometry,
|
||||
.sourceCreate = simple_spatializer_source_create,
|
||||
.sourceDestroy = simple_spatializer_source_destroy,
|
||||
.name = "simple"
|
||||
|
|
Loading…
Reference in New Issue