#ifdef _WIN32 #include "ThermionWin32.h" #endif #include #include #ifdef __EMSCRIPTEN__ #include #endif #include "filament/LightManager.h" #include "ResourceBuffer.hpp" #include "FilamentViewer.hpp" #include "Log.hpp" #include "ThreadPool.hpp" using namespace thermion; extern "C" { #include "c_api/ThermionDartApi.h" EMSCRIPTEN_KEEPALIVE TViewer *Viewer_create(const void *context, const void *const loader, void *const platform, const char *uberArchivePath) { const auto *loaderImpl = new ResourceLoaderWrapperImpl((ResourceLoaderWrapper *)loader); auto viewer = new FilamentViewer(context, loaderImpl, platform, uberArchivePath); return reinterpret_cast(viewer); } EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer *viewer) { auto *engine = reinterpret_cast(viewer)->getEngine(); return reinterpret_cast(engine); } EMSCRIPTEN_KEEPALIVE TRenderTarget *Viewer_createRenderTarget(TViewer *tViewer, intptr_t texture, uint32_t width, uint32_t height) { auto viewer = reinterpret_cast(tViewer); auto renderTarget = viewer->createRenderTarget(texture, width, height); return reinterpret_cast(renderTarget); } EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTarget(TViewer *tViewer, TRenderTarget *tRenderTarget) { auto viewer = reinterpret_cast(tViewer); auto renderTarget = reinterpret_cast(tRenderTarget); viewer->destroyRenderTarget(renderTarget); } EMSCRIPTEN_KEEPALIVE void Viewer_destroy(TViewer *viewer) { delete ((FilamentViewer *)viewer); } EMSCRIPTEN_KEEPALIVE void set_background_color(TViewer *viewer, const float r, const float g, const float b, const float a) { ((FilamentViewer *)viewer)->setBackgroundColor(r, g, b, a); } EMSCRIPTEN_KEEPALIVE void clear_background_image(TViewer *viewer) { ((FilamentViewer *)viewer)->clearBackgroundImage(); } EMSCRIPTEN_KEEPALIVE void set_background_image(TViewer *viewer, const char *path, bool fillHeight) { ((FilamentViewer *)viewer)->setBackgroundImage(path, fillHeight, 100, 100); } EMSCRIPTEN_KEEPALIVE void set_background_image_position(TViewer *viewer, float x, float y, bool clamp) { ((FilamentViewer *)viewer)->setBackgroundImagePosition(x, y, clamp, 100, 100); } EMSCRIPTEN_KEEPALIVE void Viewer_loadSkybox(TViewer *viewer, const char *skyboxPath) { ((FilamentViewer *)viewer)->loadSkybox(skyboxPath); } EMSCRIPTEN_KEEPALIVE void Viewer_removeSkybox(TViewer *viewer) { ((FilamentViewer *)viewer)->removeSkybox(); } EMSCRIPTEN_KEEPALIVE void create_ibl(TViewer *viewer, float r, float g, float b, float intensity) { ((FilamentViewer *)viewer)->createIbl(r, g, b, intensity); } EMSCRIPTEN_KEEPALIVE void Viewer_loadIbl(TViewer *viewer, const char *iblPath, float intensity) { ((FilamentViewer *)viewer)->loadIbl(iblPath, intensity); } EMSCRIPTEN_KEEPALIVE void Viewer_removeIbl(TViewer *viewer) { ((FilamentViewer *)viewer)->removeIbl(); } EMSCRIPTEN_KEEPALIVE void rotate_ibl(TViewer *viewer, float *rotationMatrix) { math::mat3f matrix(rotationMatrix[0], rotationMatrix[1], rotationMatrix[2], rotationMatrix[3], rotationMatrix[4], rotationMatrix[5], rotationMatrix[6], rotationMatrix[7], rotationMatrix[8]); ((FilamentViewer *)viewer)->rotateIbl(matrix); } EMSCRIPTEN_KEEPALIVE int get_instance_count(TSceneManager *sceneManager, EntityId entityId) { return ((SceneManager *)sceneManager)->getInstanceCount(entityId); } EMSCRIPTEN_KEEPALIVE void get_instances(TSceneManager *sceneManager, EntityId entityId, EntityId *out) { return ((SceneManager *)sceneManager)->getInstances(entityId, out); } EMSCRIPTEN_KEEPALIVE void Viewer_setMainCamera(TViewer *tViewer, TView *tView) { auto *viewer = reinterpret_cast(tViewer); auto *view = reinterpret_cast(tView); viewer->setMainCamera(view); } EMSCRIPTEN_KEEPALIVE EntityId get_main_camera(TViewer *viewer) { return ((FilamentViewer *)viewer)->getMainCamera(); } EMSCRIPTEN_KEEPALIVE float get_camera_fov(TCamera *camera, bool horizontal) { auto cam = reinterpret_cast(camera); return cam->getFieldOfViewInDegrees(horizontal ? Camera::Fov::HORIZONTAL : Camera::Fov::VERTICAL); } EMSCRIPTEN_KEEPALIVE double get_camera_focal_length(TCamera *const camera) { auto cam = reinterpret_cast(camera); return cam->getFocalLength(); } EMSCRIPTEN_KEEPALIVE void set_camera_projection_from_fov(TCamera *camera, double fovInDegrees, double aspect, double near, double far, bool horizontal) { auto cam = reinterpret_cast(camera); cam->setProjection(fovInDegrees, aspect, near, far, horizontal ? Camera::Fov::HORIZONTAL : Camera::Fov::VERTICAL); } EMSCRIPTEN_KEEPALIVE TCamera *get_camera(TViewer *viewer, EntityId entity) { auto filamentCamera = ((FilamentViewer *)viewer)->getCamera(entity); return reinterpret_cast(filamentCamera); } EMSCRIPTEN_KEEPALIVE double4x4 get_camera_model_matrix(TCamera *camera) { const auto &mat = reinterpret_cast(camera)->getModelMatrix(); return convert_mat4_to_double4x4(mat); } EMSCRIPTEN_KEEPALIVE double4x4 get_camera_view_matrix(TCamera *camera) { const auto &mat = reinterpret_cast(camera)->getViewMatrix(); return convert_mat4_to_double4x4(mat); } EMSCRIPTEN_KEEPALIVE double4x4 get_camera_projection_matrix(TCamera *camera) { const auto &mat = reinterpret_cast(camera)->getProjectionMatrix(); return convert_mat4_to_double4x4(mat); } EMSCRIPTEN_KEEPALIVE double4x4 get_camera_culling_projection_matrix(TCamera *camera) { const auto &mat = reinterpret_cast(camera)->getCullingProjectionMatrix(); return convert_mat4_to_double4x4(mat); } EMSCRIPTEN_KEEPALIVE void set_camera_projection_matrix(TCamera *camera, double4x4 matrix, double near, double far) { auto cam = reinterpret_cast(camera); const auto &mat = convert_double4x4_to_mat4(matrix); cam->setCustomProjection(mat, near, far); } EMSCRIPTEN_KEEPALIVE void Camera_setLensProjection(TCamera *camera, double near, double far, double aspect, double focalLength) { auto cam = reinterpret_cast(camera); cam->setLensProjection(focalLength, aspect, near, far); } EMSCRIPTEN_KEEPALIVE void Camera_setModelMatrix(TCamera *camera, double4x4 matrix) { auto cam = reinterpret_cast(camera); cam->setModelMatrix(convert_double4x4_to_mat4(matrix)); } EMSCRIPTEN_KEEPALIVE double get_camera_near(TCamera *camera) { auto cam = reinterpret_cast(camera); return cam->getNear(); } EMSCRIPTEN_KEEPALIVE double get_camera_culling_far(TCamera *camera) { auto cam = reinterpret_cast(camera); return cam->getCullingFar(); } EMSCRIPTEN_KEEPALIVE const double *const get_camera_frustum(TCamera *camera) { const auto frustum = reinterpret_cast(camera)->getFrustum(); const math::float4 *planes = frustum.getNormalizedPlanes(); double *array = (double *)calloc(24, sizeof(double)); for (int i = 0; i < 6; i++) { auto plane = planes[i]; array[i * 4] = double(plane.x); array[i * 4 + 1] = double(plane.y); array[i * 4 + 2] = double(plane.z); array[i * 4 + 3] = double(plane.w); } return array; } EMSCRIPTEN_KEEPALIVE void set_camera_focus_distance(TCamera *camera, float distance) { auto *cam = reinterpret_cast(camera); cam->setFocusDistance(distance); } EMSCRIPTEN_KEEPALIVE void set_camera_exposure(TCamera *camera, float aperture, float shutterSpeed, float sensitivity) { auto *cam = reinterpret_cast(camera); cam->setExposure(aperture, shutterSpeed, sensitivity); } EMSCRIPTEN_KEEPALIVE void set_camera_model_matrix(TCamera *camera, double4x4 matrix) { auto *cam = reinterpret_cast(camera); const filament::math::mat4 &mat = convert_double4x4_to_mat4(matrix); cam->setModelMatrix(mat); } EMSCRIPTEN_KEEPALIVE void Viewer_render( TViewer *tViewer) { auto viewer = reinterpret_cast(tViewer); viewer->render(0); } EMSCRIPTEN_KEEPALIVE void Viewer_setViewRenderable(TViewer *tViewer, TSwapChain *tSwapChain, TView *tView, bool renderable) { auto viewer = reinterpret_cast(tViewer); auto swapChain = reinterpret_cast(tSwapChain); auto *view = reinterpret_cast(tView); viewer->setRenderable(view, swapChain, renderable); } EMSCRIPTEN_KEEPALIVE void Viewer_capture( TViewer *tViewer, TView *tView, TSwapChain *tSwapChain, uint8_t *pixelBuffer, void (*callback)(void)) { #ifdef __EMSCRIPTEN__ bool useFence = true; #else bool useFence = false; #endif auto swapChain = reinterpret_cast(tSwapChain); auto viewer = reinterpret_cast(tViewer); auto *view = reinterpret_cast(tView); viewer->capture(view, pixelBuffer, useFence, swapChain, callback); }; EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTarget( TViewer *tViewer, TView *tView, TSwapChain *tSwapChain, TRenderTarget *tRenderTarget, uint8_t *pixelBuffer, void (*callback)(void)) { #ifdef __EMSCRIPTEN__ bool useFence = true; #else bool useFence = false; #endif auto swapChain = reinterpret_cast(tSwapChain); auto renderTarget = reinterpret_cast(tRenderTarget); auto viewer = reinterpret_cast(tViewer); auto *view = reinterpret_cast(tView); viewer->capture(view, pixelBuffer, useFence, swapChain, renderTarget, callback); }; EMSCRIPTEN_KEEPALIVE void set_frame_interval( TViewer *viewer, float frameInterval) { ((FilamentViewer *)viewer)->setFrameInterval(frameInterval); } EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChain(TViewer *tViewer, TSwapChain *tSwapChain) { auto viewer = reinterpret_cast(tViewer); auto swapChain = reinterpret_cast(tSwapChain); viewer->destroySwapChain(swapChain); } EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createHeadlessSwapChain(TViewer *tViewer, uint32_t width, uint32_t height) { auto viewer = reinterpret_cast(tViewer); auto swapChain = viewer->createSwapChain(width, height); return reinterpret_cast(swapChain); } EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createSwapChain(TViewer *tViewer, const void *const window) { auto viewer = reinterpret_cast(tViewer); auto swapChain = viewer->createSwapChain(window); return reinterpret_cast(swapChain); } EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_getSwapChainAt(TViewer *tViewer, int index) { auto viewer = reinterpret_cast(tViewer); auto swapChain = viewer->getSwapChainAt(index); return reinterpret_cast(swapChain); } EMSCRIPTEN_KEEPALIVE TView *Viewer_createView(TViewer *tViewer) { auto viewer = reinterpret_cast(tViewer); auto view = viewer->createView(); return reinterpret_cast(view); } EMSCRIPTEN_KEEPALIVE TView *Viewer_getViewAt(TViewer *tViewer, int32_t index) { auto viewer = reinterpret_cast(tViewer); auto view = viewer->getViewAt(index); return reinterpret_cast(view); } EMSCRIPTEN_KEEPALIVE TSceneManager *Viewer_getSceneManager(TViewer *tViewer) { auto *viewer = reinterpret_cast(tViewer); auto *sceneManager = viewer->getSceneManager(); return reinterpret_cast(sceneManager); } EMSCRIPTEN_KEEPALIVE void queue_position_update_from_viewport_coords(TSceneManager *sceneManager, TView *tView, EntityId entity, float viewportX, float viewportY) { auto *view = reinterpret_cast(tView); ((SceneManager *)sceneManager)->queueRelativePositionUpdateFromViewportVector(view, entity, viewportX, viewportY); } EMSCRIPTEN_KEEPALIVE void ios_dummy() { Log("Dummy called"); } EMSCRIPTEN_KEEPALIVE void thermion_filament_free(void *ptr) { free(ptr); } EMSCRIPTEN_KEEPALIVE void add_collision_component(TSceneManager *sceneManager, EntityId entityId, void (*onCollisionCallback)(const EntityId entityId1, const EntityId entityId2), bool affectsCollidingTransform) { ((SceneManager *)sceneManager)->addCollisionComponent(entityId, onCollisionCallback, affectsCollidingTransform); } EMSCRIPTEN_KEEPALIVE void remove_collision_component(TSceneManager *sceneManager, EntityId entityId) { ((SceneManager *)sceneManager)->removeCollisionComponent(entityId); } EMSCRIPTEN_KEEPALIVE void test_collisions(TSceneManager *sceneManager, EntityId entity) { ((SceneManager *)sceneManager)->testCollisions(entity); } EMSCRIPTEN_KEEPALIVE Aabb2 get_bounding_box(TSceneManager *sceneManager, TView *tView, EntityId entity) { auto view = reinterpret_cast(tView); return ((SceneManager *)sceneManager)->getScreenSpaceBoundingBox(view, entity); } EMSCRIPTEN_KEEPALIVE void get_bounding_box_to_out(TSceneManager *sceneManager, TView *tView, EntityId entity, float *minX, float *minY, float *maxX, float *maxY) { auto view = reinterpret_cast(tView); auto box = ((SceneManager *)sceneManager)->getScreenSpaceBoundingBox(view, entity); *minX = box.minX; *minY = box.minY; *maxX = box.maxX; *maxY = box.maxY; } EMSCRIPTEN_KEEPALIVE void thermion_flutter_free(void *ptr) { free(ptr); } EMSCRIPTEN_KEEPALIVE void unproject_texture(TViewer *viewer, EntityId entity, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight) { ((FilamentViewer *)viewer)->unprojectTexture(entity, input, inputWidth, inputHeight, out, outWidth, outHeight); } EMSCRIPTEN_KEEPALIVE void *const create_texture(TSceneManager *sceneManager, uint8_t *data, size_t length) { return (void *const)((SceneManager *)sceneManager)->createTexture(data, length, "SOMETEXTURE"); } EMSCRIPTEN_KEEPALIVE void apply_texture_to_material(TSceneManager *sceneManager, EntityId entity, void *const texture, const char *parameterName, int materialIndex) { ((SceneManager *)sceneManager)->applyTexture(entity, reinterpret_cast(texture), parameterName, materialIndex); } EMSCRIPTEN_KEEPALIVE void destroy_texture(TSceneManager *sceneManager, void *const texture) { ((SceneManager *)sceneManager)->destroyTexture(reinterpret_cast(texture)); } 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_getCameraComponent(TEngine *tEngine, EntityId entityId) { auto *engine = reinterpret_cast(tEngine); auto *camera = engine->getCameraComponent(utils::Entity::import(entityId)); 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); } }