#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 *tViewer) { auto *viewer = reinterpret_cast(tViewer); delete 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 Viewer_getMainCamera(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); } }