#include "c_api/TEngine.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Log.hpp" #include "MathUtils.hpp" #ifdef __cplusplus namespace thermion { extern "C" { using namespace filament; #endif uint64_t TSWAP_CHAIN_CONFIG_TRANSPARENT = filament::backend::SWAP_CHAIN_CONFIG_TRANSPARENT; uint64_t TSWAP_CHAIN_CONFIG_READABLE = filament::backend::SWAP_CHAIN_CONFIG_READABLE; uint64_t TSWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER = filament::backend::SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER; uint64_t TSWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER = filament::backend::SWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER; EMSCRIPTEN_KEEPALIVE TEngine *Engine_create( TBackend backend, void* tPlatform, void* tSharedContext, uint8_t stereoscopicEyeCount, bool disableHandleUseAfterFreeCheck) { filament::Engine::Config config; config.stereoscopicEyeCount = stereoscopicEyeCount; config.disableHandleUseAfterFreeCheck = disableHandleUseAfterFreeCheck; auto *platform = reinterpret_cast(tPlatform); auto *engine = filament::Engine::create( static_cast(backend), platform, tSharedContext, &config ); return reinterpret_cast(engine); } EMSCRIPTEN_KEEPALIVE void Engine_destroy(TEngine *tEngine) { auto *engine = reinterpret_cast(tEngine); Engine::destroy(engine); } EMSCRIPTEN_KEEPALIVE TRenderer *Engine_createRenderer(TEngine *tEngine) { auto *engine = reinterpret_cast(tEngine); auto *renderer = engine->createRenderer(); return reinterpret_cast(renderer); } EMSCRIPTEN_KEEPALIVE TSwapChain *Engine_createSwapChain(TEngine *tEngine, void *window, uint64_t flags) { auto *engine = reinterpret_cast(tEngine); auto *swapChain = engine->createSwapChain(window, flags); return reinterpret_cast(swapChain); } EMSCRIPTEN_KEEPALIVE TSwapChain *Engine_createHeadlessSwapChain(TEngine *tEngine, uint32_t width, uint32_t height, uint64_t flags) { auto *engine = reinterpret_cast(tEngine); auto *swapChain = engine->createSwapChain(width, height, flags); return reinterpret_cast(swapChain); } EMSCRIPTEN_KEEPALIVE void Engine_destroySwapChain(TEngine *tEngine, TSwapChain *tSwapChain) { auto *engine = reinterpret_cast(tEngine); auto *swapChain = reinterpret_cast(tSwapChain); engine->destroy(swapChain); } EMSCRIPTEN_KEEPALIVE TView *Engine_createView(TEngine *tEngine) { auto *engine = reinterpret_cast(tEngine); auto *view = engine->createView(); return reinterpret_cast(view); } EMSCRIPTEN_KEEPALIVE TTransformManager *Engine_getTransformManager(TEngine *tEngine) { auto *engine = reinterpret_cast(tEngine); auto &transformManager = engine->getTransformManager(); return reinterpret_cast(&transformManager); } EMSCRIPTEN_KEEPALIVE TRenderableManager *Engine_getRenderableManager(TEngine *tEngine) { auto *engine = reinterpret_cast(tEngine); auto &renderableManager = engine->getRenderableManager(); return reinterpret_cast(&renderableManager); } EMSCRIPTEN_KEEPALIVE TLightManager *Engine_getLightManager(TEngine *tEngine) { auto *engine = reinterpret_cast(tEngine); auto &lightManager = engine->getLightManager(); return reinterpret_cast(&lightManager); } EMSCRIPTEN_KEEPALIVE TCamera *Engine_createCamera(TEngine *tEngine) { auto *engine = reinterpret_cast(tEngine); utils::Entity entity = utils::EntityManager::get().create(); auto *camera = engine->createCamera(entity); return reinterpret_cast(camera); } EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine *tEngine, EntityId entityId) { auto *engine = reinterpret_cast(tEngine); auto entity = utils::Entity::import(entityId); if (entity.isNull()) { return std::nullptr_t(); } auto *camera = engine->getCameraComponent(entity); return reinterpret_cast(camera); } EMSCRIPTEN_KEEPALIVE void Engine_setTransform(TEngine *tEngine, EntityId entity, double4x4 transform) { auto *engine = reinterpret_cast(tEngine); auto &transformManager = engine->getTransformManager(); auto transformInstance = transformManager.getInstance(utils::Entity::import(entity)); if (!transformInstance.isValid()) { Log("Transform instance not valid"); } transformManager.setTransform(transformInstance, convert_double4x4_to_mat4(transform)); } EMSCRIPTEN_KEEPALIVE TMaterial *Engine_buildMaterial(TEngine *tEngine, const uint8_t *materialData, size_t length) { auto *engine = reinterpret_cast(tEngine); auto *material = Material::Builder() .package(materialData, length) .build(*engine); return reinterpret_cast(material); } EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterial(TEngine *tEngine, TMaterial *tMaterial) { auto *engine = reinterpret_cast(tEngine); auto *material = reinterpret_cast(tMaterial); engine->destroy(material); } EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialInstance(TEngine *tEngine, TMaterialInstance *tMaterialInstance) { auto *engine = reinterpret_cast(tEngine); auto *mi = reinterpret_cast(tMaterialInstance); engine->destroy(mi); } EMSCRIPTEN_KEEPALIVE void Engine_destroyTexture(TEngine *tEngine, TTexture *tTexture) { auto *engine = reinterpret_cast(tEngine); auto *texture = reinterpret_cast(tTexture); engine->destroy(texture); } EMSCRIPTEN_KEEPALIVE TFence *Engine_createFence(TEngine *tEngine) { auto *engine = reinterpret_cast(tEngine); auto *fence = engine->createFence(); return reinterpret_cast(fence); } EMSCRIPTEN_KEEPALIVE void Engine_destroyFence(TEngine *tEngine, TFence *tFence) { auto *engine = reinterpret_cast(tEngine); auto *fence = reinterpret_cast(tFence); Fence::waitAndDestroy(fence); } EMSCRIPTEN_KEEPALIVE void Engine_flushAndWait(TEngine *tEngine) { auto *engine = reinterpret_cast(tEngine); #ifdef __EMSCRIPTEN__ engine->execute(); emscripten_webgl_commit_frame(); #else engine->flushAndWait(); #endif } EMSCRIPTEN_KEEPALIVE TScene *Engine_createScene(TEngine *tEngine) { auto *engine = reinterpret_cast(tEngine); auto *scene = engine->createScene(); return reinterpret_cast(scene); } EMSCRIPTEN_KEEPALIVE TSkybox *Engine_buildSkybox(TEngine *tEngine, uint8_t *ktxData, size_t length, void (*onTextureUploadComplete)()) { auto *engine = reinterpret_cast(tEngine); auto copy = new std::vector(ktxData, ktxData + length); image::Ktx1Bundle *skyboxBundle = new image::Ktx1Bundle(static_cast(copy->data()), static_cast(length)); std::vector *callbackData = new std::vector{ reinterpret_cast(onTextureUploadComplete), reinterpret_cast(skyboxBundle), reinterpret_cast(copy)}; auto *texture = ktxreader::Ktx1Reader::createTexture( engine, *skyboxBundle, false, [](void *userdata) { std::vector* vec = (std::vector*)userdata; void *callbackPtr = vec->at(0); image::Ktx1Bundle *skyboxBundle = reinterpret_cast(vec->at(1)); std::vector *copy = reinterpret_cast*>(vec->at(2)); delete vec; if (callbackPtr) { void (*callback)(void) = (void (*)(void))callbackPtr; callback(); } delete skyboxBundle; delete copy; }, (void *)callbackData); auto *skybox = filament::Skybox::Builder() .environment(texture) .build(*engine); return reinterpret_cast(skybox); } EMSCRIPTEN_KEEPALIVE TIndirectLight *Engine_buildIndirectLight(TEngine *tEngine, uint8_t *ktxData, size_t length, float intensity, void (*onTextureUploadComplete)()) { auto *engine = reinterpret_cast(tEngine); auto copy = new std::vector(ktxData, ktxData + length); image::Ktx1Bundle *iblBundle = new image::Ktx1Bundle(static_cast(copy->data()), static_cast(length)); filament::math::float3 harmonics[9]; iblBundle->getSphericalHarmonics(harmonics); std::vector *callbackData = new std::vector{ reinterpret_cast(onTextureUploadComplete), reinterpret_cast(iblBundle), reinterpret_cast(copy)}; auto *texture = ktxreader::Ktx1Reader::createTexture( engine, *iblBundle, false, [](void *userdata) { std::vector* vec = (std::vector*)userdata; void *callbackPtr = vec->at(0); image::Ktx1Bundle *iblBundle = reinterpret_cast(vec->at(1)); std::vector *copy = reinterpret_cast*>(vec->at(2)); delete vec; if (callbackPtr) { void (*callback)(void) = (void (*)(void))callbackPtr; callback(); } delete iblBundle; delete copy; }, (void *)callbackData); auto *indirectLight = filament::IndirectLight::Builder() .reflections(texture) .irradiance(3, harmonics) .intensity(intensity) .build(*engine); return reinterpret_cast(indirectLight); } EMSCRIPTEN_KEEPALIVE void Engine_destroySkybox(TEngine *tEngine, TSkybox *tSkybox) { auto *engine = reinterpret_cast(tEngine); auto *skybox = reinterpret_cast(tSkybox); if(skybox->getTexture()) { engine->destroy(skybox->getTexture()); } engine->destroy(skybox); } EMSCRIPTEN_KEEPALIVE void Engine_destroyIndirectLight(TEngine *tEngine, TIndirectLight *tIndirectLight) { auto *engine = reinterpret_cast(tEngine); auto *indirectLight = reinterpret_cast(tIndirectLight); if(indirectLight->getReflectionsTexture()) { engine->destroy(indirectLight->getReflectionsTexture()); } if(indirectLight->getIrradianceTexture()) { engine->destroy(indirectLight->getIrradianceTexture()); } engine->destroy(indirectLight); } #ifdef __cplusplus } } #endif