419 lines
15 KiB
C++
419 lines
15 KiB
C++
#ifdef _WIN32
|
|
#include "ThermionWin32.h"
|
|
#endif
|
|
|
|
#include <thread>
|
|
#include <functional>
|
|
|
|
#ifdef __EMSCRIPTEN__
|
|
#include <emscripten/emscripten.h>
|
|
#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<TViewer *>(viewer);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer *viewer)
|
|
{
|
|
auto *engine = reinterpret_cast<FilamentViewer *>(viewer)->getEngine();
|
|
return reinterpret_cast<TEngine *>(engine);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE TRenderTarget *Viewer_createRenderTarget(TViewer *tViewer, intptr_t texture, uint32_t width, uint32_t height)
|
|
{
|
|
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
|
auto renderTarget = viewer->createRenderTarget(texture, width, height);
|
|
return reinterpret_cast<TRenderTarget *>(renderTarget);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTarget(TViewer *tViewer, TRenderTarget *tRenderTarget)
|
|
{
|
|
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
|
auto renderTarget = reinterpret_cast<RenderTarget *>(tRenderTarget);
|
|
viewer->destroyRenderTarget(renderTarget);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE void Viewer_destroy(TViewer *tViewer)
|
|
{
|
|
auto *viewer = reinterpret_cast<FilamentViewer*>(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<FilamentViewer *>(tViewer);
|
|
auto *view = reinterpret_cast<View *>(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<filament::Camera *>(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<filament::Camera *>(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<filament::Camera *>(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<TCamera *>(filamentCamera);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE double4x4 get_camera_model_matrix(TCamera *camera)
|
|
{
|
|
const auto &mat = reinterpret_cast<filament::Camera *>(camera)->getModelMatrix();
|
|
return convert_mat4_to_double4x4(mat);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE double4x4 get_camera_view_matrix(TCamera *camera)
|
|
{
|
|
const auto &mat = reinterpret_cast<filament::Camera *>(camera)->getViewMatrix();
|
|
return convert_mat4_to_double4x4(mat);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE double4x4 get_camera_projection_matrix(TCamera *camera)
|
|
{
|
|
const auto &mat = reinterpret_cast<filament::Camera *>(camera)->getProjectionMatrix();
|
|
return convert_mat4_to_double4x4(mat);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE double4x4 get_camera_culling_projection_matrix(TCamera *camera)
|
|
{
|
|
const auto &mat = reinterpret_cast<filament::Camera *>(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<filament::Camera *>(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<filament::Camera *>(camera);
|
|
cam->setLensProjection(focalLength, aspect, near, far);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE void Camera_setModelMatrix(TCamera *camera, double4x4 matrix)
|
|
{
|
|
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
|
cam->setModelMatrix(convert_double4x4_to_mat4(matrix));
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE double get_camera_near(TCamera *camera)
|
|
{
|
|
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
|
return cam->getNear();
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE double get_camera_culling_far(TCamera *camera)
|
|
{
|
|
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
|
return cam->getCullingFar();
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE const double *const get_camera_frustum(TCamera *camera)
|
|
{
|
|
|
|
const auto frustum = reinterpret_cast<filament::Camera *>(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<filament::Camera *>(camera);
|
|
cam->setFocusDistance(distance);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE void set_camera_exposure(TCamera *camera, float aperture, float shutterSpeed, float sensitivity)
|
|
{
|
|
auto *cam = reinterpret_cast<filament::Camera *>(camera);
|
|
cam->setExposure(aperture, shutterSpeed, sensitivity);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE void set_camera_model_matrix(TCamera *camera, double4x4 matrix)
|
|
{
|
|
auto *cam = reinterpret_cast<filament::Camera *>(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<FilamentViewer *>(tViewer);
|
|
viewer->render(0);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE void Viewer_setViewRenderable(TViewer *tViewer, TSwapChain *tSwapChain, TView *tView, bool renderable)
|
|
{
|
|
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
|
auto swapChain = reinterpret_cast<SwapChain *>(tSwapChain);
|
|
auto *view = reinterpret_cast<View *>(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<SwapChain *>(tSwapChain);
|
|
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
|
auto *view = reinterpret_cast<View *>(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<SwapChain *>(tSwapChain);
|
|
auto renderTarget = reinterpret_cast<RenderTarget *>(tRenderTarget);
|
|
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
|
auto *view = reinterpret_cast<View *>(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<FilamentViewer *>(tViewer);
|
|
auto swapChain = reinterpret_cast<SwapChain *>(tSwapChain);
|
|
viewer->destroySwapChain(swapChain);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createHeadlessSwapChain(TViewer *tViewer, uint32_t width, uint32_t height)
|
|
{
|
|
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
|
auto swapChain = viewer->createSwapChain(width, height);
|
|
return reinterpret_cast<TSwapChain *>(swapChain);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createSwapChain(TViewer *tViewer, const void *const window)
|
|
{
|
|
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
|
auto swapChain = viewer->createSwapChain(window);
|
|
return reinterpret_cast<TSwapChain *>(swapChain);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_getSwapChainAt(TViewer *tViewer, int index)
|
|
{
|
|
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
|
auto swapChain = viewer->getSwapChainAt(index);
|
|
return reinterpret_cast<TSwapChain *>(swapChain);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE TView *Viewer_createView(TViewer *tViewer)
|
|
{
|
|
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
|
auto view = viewer->createView();
|
|
return reinterpret_cast<TView *>(view);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE TView *Viewer_getViewAt(TViewer *tViewer, int32_t index)
|
|
{
|
|
auto viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
|
auto view = viewer->getViewAt(index);
|
|
return reinterpret_cast<TView *>(view);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE TSceneManager *Viewer_getSceneManager(TViewer *tViewer)
|
|
{
|
|
auto *viewer = reinterpret_cast<FilamentViewer *>(tViewer);
|
|
auto *sceneManager = viewer->getSceneManager();
|
|
return reinterpret_cast<TSceneManager *>(sceneManager);
|
|
}
|
|
|
|
EMSCRIPTEN_KEEPALIVE void queue_position_update_from_viewport_coords(TSceneManager *sceneManager, TView *tView, EntityId entity, float viewportX, float viewportY)
|
|
{
|
|
auto *view = reinterpret_cast<View *>(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<View *>(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<View *>(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);
|
|
}
|
|
|
|
|
|
}
|