From baf86d1ade11b42fb101dd2bacf59b28fa707df4 Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Sat, 4 Jan 2025 14:43:37 +0800 Subject: [PATCH] refactor!: move light methods from FilamentViewer to SceneManager/TLightManager and rename clearLights/clearAssets to destroyLights/destroyAssets --- .../src/ffi/src/thermion_viewer_ffi.dart | 24 ++-- .../src/viewer/src/thermion_viewer_base.dart | 4 +- .../src/viewer/src/thermion_viewer_stub.dart | 16 +-- .../src/thermion_viewer_dart_bridge.dart | 10 +- .../src/web_js/src/thermion_viewer_js.dart | 12 +- .../web_js/src/thermion_viewer_js_shim.dart | 12 +- .../native/include/FilamentViewer.hpp | 23 +--- .../native/include/c_api/APIBoundaryTypes.h | 4 + .../native/include/c_api/TLightManager.h | 17 +++ .../native/include/c_api/TSceneAsset.h | 1 + .../native/include/c_api/TSceneManager.h | 28 ++++- .../native/include/c_api/ThermionDartApi.h | 23 +--- .../native/include/scene/SceneManager.hpp | 46 ++++++- thermion_dart/native/src/FilamentViewer.cpp | 115 +----------------- .../native/src/c_api/TLightManager.cpp | 33 +++++ .../native/src/c_api/TSceneManager.cpp | 82 ++++++++++--- .../native/src/c_api/ThermionDartApi.cpp | 48 +------- .../native/src/scene/SceneManager.cpp | 87 +++++++++++-- thermion_dart/test/asset_tests.dart | 18 +++ thermion_dart/test/light_tests.dart | 22 ++++ .../src/widgets/src/lights/light_slider.dart | 2 +- 21 files changed, 355 insertions(+), 272 deletions(-) create mode 100644 thermion_dart/native/include/c_api/TLightManager.h create mode 100644 thermion_dart/native/src/c_api/TLightManager.cpp create mode 100644 thermion_dart/test/asset_tests.dart create mode 100644 thermion_dart/test/light_tests.dart diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart index 730e3e1f..00cb2dd8 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart @@ -29,6 +29,7 @@ class ThermionViewerFFI extends ThermionViewer { Pointer? _unlitMaterialProvider; Pointer? _ubershaderMaterialProvider; Pointer? _transformManager; + Pointer? _lightManager; Pointer? _renderableManager; Pointer? _viewer; Pointer? _animationManager; @@ -197,6 +198,7 @@ class ThermionViewerFFI extends ThermionViewer { SceneManager_getUbershaderMaterialProvider(_sceneManager!); _engine = Viewer_getEngine(_viewer!); _transformManager = Engine_getTransformManager(_engine!); + _lightManager = Engine_getLightManager(_engine!); _animationManager = SceneManager_getAnimationManager(_sceneManager!); _nameComponentManager = SceneManager_getNameComponentManager(_sceneManager!); @@ -284,11 +286,11 @@ class ThermionViewerFFI extends ThermionViewer { } _disposing = true; await setRendering(false); - await clearEntities(); + await destroyAssets(); for (final mInstance in _materialInstances) { await mInstance.dispose(); } - await clearLights(); + await destroyLights(); Viewer_destroyOnRenderThread(_viewer!); _sceneManager = null; @@ -450,8 +452,8 @@ class ThermionViewerFFI extends ThermionViewer { /// @override Future addDirectLight(DirectLight directLight) async { - var entity = add_light( - _viewer!, + var entity = SceneManager_addLight( + _sceneManager!, directLight.type.index, directLight.color, directLight.intensity, @@ -480,15 +482,15 @@ class ThermionViewerFFI extends ThermionViewer { /// @override Future removeLight(ThermionEntity entity) async { - remove_light(_viewer!, entity); + SceneManager_removeLight(_sceneManager!, entity); } /// /// /// @override - Future clearLights() async { - clear_lights(_viewer!); + Future destroyLights() async { + SceneManager_destroyLights(_sceneManager!); } /// @@ -987,7 +989,7 @@ class ThermionViewerFFI extends ThermionViewer { /// /// @override - Future clearEntities() async { + Future destroyAssets() async { await withVoidCallback((callback) { SceneManager_destroyAllRenderThread(_sceneManager!, callback); }); @@ -1314,7 +1316,7 @@ class ThermionViewerFFI extends ThermionViewer { @override Future setLightPosition( ThermionEntity lightEntity, double x, double y, double z) async { - set_light_position(_viewer!, lightEntity, x, y, z); + LightManager_setPosition(_lightManager!, lightEntity, x, y, z); } /// @@ -1324,8 +1326,8 @@ class ThermionViewerFFI extends ThermionViewer { Future setLightDirection( ThermionEntity lightEntity, Vector3 direction) async { direction.normalize(); - set_light_direction( - _viewer!, lightEntity, direction.x, direction.y, direction.z); + LightManager_setPosition( + _lightManager!, lightEntity, direction.x, direction.y, direction.z); } /// diff --git a/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart b/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart index b3f2b169..19f34a65 100644 --- a/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart +++ b/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart @@ -206,7 +206,7 @@ abstract class ThermionViewer { /// /// Remove all lights (excluding IBL) from the scene. /// - Future clearLights(); + Future destroyLights(); /// /// Load the .glb asset at the given path, adding all entities to the scene. @@ -386,7 +386,7 @@ abstract class ThermionViewer { /// Removes/destroys all renderable entities from the scene (including cameras). /// All [ThermionEntity] handles will no longer be valid after this method is called; ensure you immediately discard all references to all entities once this method is complete. /// - Future clearEntities(); + Future destroyAssets(); /// /// Schedules the glTF animation at [index] in [asset] to start playing on the next frame. diff --git a/thermion_dart/lib/src/viewer/src/thermion_viewer_stub.dart b/thermion_dart/lib/src/viewer/src/thermion_viewer_stub.dart index babdd17b..ebc01fc6 100644 --- a/thermion_dart/lib/src/viewer/src/thermion_viewer_stub.dart +++ b/thermion_dart/lib/src/viewer/src/thermion_viewer_stub.dart @@ -55,14 +55,14 @@ class ThermionViewerStub extends ThermionViewer { } @override - Future clearEntities() { - // TODO: implement clearEntities + Future destroyAssets() { + // TODO: implement destroyAssets throw UnimplementedError(); } @override - Future clearLights() { - // TODO: implement clearLights + Future destroyLights() { + // TODO: implement destroyLights throw UnimplementedError(); } @@ -1008,8 +1008,8 @@ class ThermionViewerStub extends ThermionViewer { } @override - Future removeEntity(ThermionAsset asset) { - // TODO: implement removeEntity + Future removeAsset(ThermionAsset asset) { + // TODO: implement removeAsset throw UnimplementedError(); } @@ -1074,8 +1074,8 @@ class ThermionViewerStub extends ThermionViewer { } @override - Future removeEntityFromScene(ThermionEntity entity) { - // TODO: implement removeEntityFromScene + Future removeAssetFromScene(ThermionEntity entity) { + // TODO: implement removeAssetFromScene throw UnimplementedError(); } diff --git a/thermion_dart/lib/src/viewer/src/web_js/src/thermion_viewer_dart_bridge.dart b/thermion_dart/lib/src/viewer/src/web_js/src/thermion_viewer_dart_bridge.dart index 656017da..0a25e7bb 100644 --- a/thermion_dart/lib/src/viewer/src/web_js/src/thermion_viewer_dart_bridge.dart +++ b/thermion_dart/lib/src/viewer/src/web_js/src/thermion_viewer_dart_bridge.dart @@ -131,7 +131,7 @@ // JSPromise removeLight(ThermionEntity light) => viewer.removeLight(light).toJS; // @JSExport() -// JSPromise clearLights() => viewer.clearLights().toJS; +// JSPromise destroyLights() => viewer.destroyLights().toJS; // @JSExport() // JSPromise loadGlb(String path, {int numInstances = 1}) { @@ -319,12 +319,12 @@ // } // @JSExport() -// JSPromise removeEntity(ThermionEntity entity) => -// viewer.removeEntity(entity).toJS; +// JSPromise removeAsset(ThermionEntity entity) => +// viewer.removeAsset(entity).toJS; // @JSExport() -// JSPromise clearEntities() { -// return viewer.clearEntities().toJS; +// JSPromise destroyAssets() { +// return viewer.destroyAssets().toJS; // } // @JSExport() diff --git a/thermion_dart/lib/src/viewer/src/web_js/src/thermion_viewer_js.dart b/thermion_dart/lib/src/viewer/src/web_js/src/thermion_viewer_js.dart index 48357131..b9380135 100644 --- a/thermion_dart/lib/src/viewer/src/web_js/src/thermion_viewer_js.dart +++ b/thermion_dart/lib/src/viewer/src/web_js/src/thermion_viewer_js.dart @@ -161,8 +161,8 @@ // } // @override -// Future clearLights() async { -// await _shim.clearLights().toDart; +// Future destroyLights() async { +// await _shim.destroyLights().toDart; // } // @override @@ -339,13 +339,13 @@ // } // @override -// Future removeEntity(ThermionEntity entity) async { -// await _shim.removeEntity(entity).toDart; +// Future removeAsset(ThermionEntity entity) async { +// await _shim.removeAsset(entity).toDart; // } // @override -// Future clearEntities() async { -// await _shim.clearEntities().toDart; +// Future destroyAssets() async { +// await _shim.destroyAssets().toDart; // } // @override diff --git a/thermion_dart/lib/src/viewer/src/web_js/src/thermion_viewer_js_shim.dart b/thermion_dart/lib/src/viewer/src/web_js/src/thermion_viewer_js_shim.dart index 3dd9e74c..30ee6bb5 100644 --- a/thermion_dart/lib/src/viewer/src/web_js/src/thermion_viewer_js_shim.dart +++ b/thermion_dart/lib/src/viewer/src/web_js/src/thermion_viewer_js_shim.dart @@ -81,8 +81,8 @@ extension type ThermionViewerJSShim(JSObject _) implements JSObject { @JS('removeLight') external JSPromise removeLight(ThermionEntity light); - @JS('clearLights') - external JSPromise clearLights(); + @JS('destroyLights') + external JSPromise destroyLights(); @JS('loadGlb') external JSPromise loadGlb(String path, int numInstances); @@ -164,11 +164,11 @@ extension type ThermionViewerJSShim(JSObject _) implements JSObject { JSNumber fadeOutInSecs, JSNumber maxDelta); - @JS('removeEntity') - external JSPromise removeEntity(ThermionEntity entity); + @JS('removeAsset') + external JSPromise removeAsset(ThermionEntity entity); - @JS('clearEntities') - external JSPromise clearEntities(); + @JS('destroyAssets') + external JSPromise destroyAssets(); @JS('zoomBegin') external JSPromise zoomBegin(); diff --git a/thermion_dart/native/include/FilamentViewer.hpp b/thermion_dart/native/include/FilamentViewer.hpp index 1812166b..b8179bd3 100644 --- a/thermion_dart/native/include/FilamentViewer.hpp +++ b/thermion_dart/native/include/FilamentViewer.hpp @@ -99,27 +99,7 @@ namespace thermion return _engine; } - EntityId addLight( - LightManager::Type t, - float colour, - float intensity, - float posX, - float posY, - float posZ, - float dirX, - float dirY, - float dirZ, - float falloffRadius, - float spotLightConeInner, - float spotLightConeOuter, - float sunAngularRadius, - float sunHaloSize, - float sunHaloFallof, - bool shadows); - void setLightPosition(EntityId entityId, float x, float y, float z); - void setLightDirection(EntityId entityId, float x, float y, float z); - void removeLight(EntityId entityId); - void clearLights(); + void capture(View* view, uint8_t *out, bool useFence, SwapChain* swapChain, void (*onComplete)()); void capture(View* view, uint8_t *out, bool useFence, SwapChain* swapChain, RenderTarget* renderTarget, void (*onComplete)()); @@ -152,7 +132,6 @@ namespace thermion std::mutex _renderMutex; // mutex to ensure thread safety when removing assets - std::vector _lights; Texture *_skyboxTexture = nullptr; Skybox *_skybox = nullptr; Texture *_iblTexture = nullptr; diff --git a/thermion_dart/native/include/c_api/APIBoundaryTypes.h b/thermion_dart/native/include/c_api/APIBoundaryTypes.h index 8073f9f2..fe955556 100644 --- a/thermion_dart/native/include/c_api/APIBoundaryTypes.h +++ b/thermion_dart/native/include/c_api/APIBoundaryTypes.h @@ -7,12 +7,15 @@ extern "C" #include +#include "APIExport.h" + typedef int32_t EntityId; typedef struct TCamera TCamera; typedef struct TEngine TEngine; typedef struct TEntityManager TEntityManager; typedef struct TViewer TViewer; typedef struct TSceneManager TSceneManager; + typedef struct TLightManager TLightManager; typedef struct TRenderTarget TRenderTarget; typedef struct TSwapChain TSwapChain; typedef struct TView TView; @@ -91,6 +94,7 @@ extern "C" } ; typedef struct TMaterialKey TMaterialKey; + typedef struct { double x; double y; diff --git a/thermion_dart/native/include/c_api/TLightManager.h b/thermion_dart/native/include/c_api/TLightManager.h new file mode 100644 index 00000000..9018eacc --- /dev/null +++ b/thermion_dart/native/include/c_api/TLightManager.h @@ -0,0 +1,17 @@ +#pragma once + +#include "APIBoundaryTypes.h" +#include "APIExport.h" +#include "TMaterialInstance.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + EMSCRIPTEN_KEEPALIVE void LightManager_setPosition(TLightManager *tLightManager, EntityId light, double x, double y, double z); + EMSCRIPTEN_KEEPALIVE void LightManager_setDirection(TLightManager *tLightManager, EntityId light, double x, double y, double z); + +#ifdef __cplusplus +} +#endif diff --git a/thermion_dart/native/include/c_api/TSceneAsset.h b/thermion_dart/native/include/c_api/TSceneAsset.h index e75a2a54..d6e33d3f 100644 --- a/thermion_dart/native/include/c_api/TSceneAsset.h +++ b/thermion_dart/native/include/c_api/TSceneAsset.h @@ -2,6 +2,7 @@ #pragma once #include + #include "APIExport.h" #include "APIBoundaryTypes.h" diff --git a/thermion_dart/native/include/c_api/TSceneManager.h b/thermion_dart/native/include/c_api/TSceneManager.h index 49e6fd9a..09a1033f 100644 --- a/thermion_dart/native/include/c_api/TSceneManager.h +++ b/thermion_dart/native/include/c_api/TSceneManager.h @@ -51,13 +51,35 @@ extern "C" EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_loadGlbFromBuffer(TSceneManager *tSceneManager, const uint8_t *const, size_t length, int numInstances, bool keepData, int priority, int layer, bool loadResourcesAsync); EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_loadGlb(TSceneManager *sceneManager, const char *assetPath, int numInstances, bool keepData); EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_loadGltf(TSceneManager *sceneManager, const char *assetPath, const char *relativePath, bool keepData); + + EMSCRIPTEN_KEEPALIVE EntityId SceneManager_addLight( + TSceneManager *tSceneManager, + uint8_t type, + float colour, + float intensity, + float posX, + float posY, + float posZ, + float dirX, + float dirY, + float dirZ, + float falloffRadius, + float spotLightConeInner, + float spotLightConeOuter, + float sunAngularRadius, + float sunHaloSize, + float sunHaloFallof, + bool shadows); + EMSCRIPTEN_KEEPALIVE void SceneManager_removeLight(TSceneManager *tSceneManager, EntityId entityId); + EMSCRIPTEN_KEEPALIVE void SceneManager_destroyLights(TSceneManager *tSceneManager); + EMSCRIPTEN_KEEPALIVE void SceneManager_destroyAsset(TSceneManager *tSceneManager, TSceneAsset *sceneAsset); + EMSCRIPTEN_KEEPALIVE void SceneManager_destroyAssets(TSceneManager *tSceneManager); + EMSCRIPTEN_KEEPALIVE void SceneManager_destroyAll(TSceneManager *tSceneManager); + EMSCRIPTEN_KEEPALIVE TAnimationManager *SceneManager_getAnimationManager(TSceneManager *tSceneManager); - EMSCRIPTEN_KEEPALIVE void *SceneManager_destroyAll(TSceneManager *tSceneManager); - EMSCRIPTEN_KEEPALIVE void *SceneManager_destroyAsset(TSceneManager *tSceneManager, TSceneAsset *sceneAsset); EMSCRIPTEN_KEEPALIVE TNameComponentManager *SceneManager_getNameComponentManager(TSceneManager *tSceneManager); - EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_createGrid(TSceneManager *tSceneManager, TMaterial *tMaterial); EMSCRIPTEN_KEEPALIVE bool SceneManager_isGridEntity(TSceneManager *tSceneManager, EntityId entityId); diff --git a/thermion_dart/native/include/c_api/ThermionDartApi.h b/thermion_dart/native/include/c_api/ThermionDartApi.h index 6af44438..7ddf592a 100644 --- a/thermion_dart/native/include/c_api/ThermionDartApi.h +++ b/thermion_dart/native/include/c_api/ThermionDartApi.h @@ -48,6 +48,7 @@ extern "C" EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine* tEngine, EntityId entityId); EMSCRIPTEN_KEEPALIVE TTransformManager *Engine_getTransformManager(TEngine *engine); EMSCRIPTEN_KEEPALIVE TRenderableManager *Engine_getRenderableManager(TEngine *engine); + EMSCRIPTEN_KEEPALIVE TLightManager *Engine_getLightManager(TEngine *engine); EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine *engine, EntityId entity); EMSCRIPTEN_KEEPALIVE TEntityManager *Engine_getEntityManager(TEngine *engine); @@ -65,28 +66,6 @@ extern "C" EMSCRIPTEN_KEEPALIVE void rotate_ibl(TViewer *viewer, float *rotationMatrix); EMSCRIPTEN_KEEPALIVE void remove_skybox(TViewer *viewer); EMSCRIPTEN_KEEPALIVE void remove_ibl(TViewer *viewer); - EMSCRIPTEN_KEEPALIVE EntityId add_light( - TViewer *viewer, - uint8_t type, - float colour, - float intensity, - float posX, - float posY, - float posZ, - float dirX, - float dirY, - float dirZ, - float falloffRadius, - float spotLightConeInner, - float spotLightConeOuter, - float sunAngularRadius, - float sunHaloSize, - float sunHaloFallof, - bool shadows); - EMSCRIPTEN_KEEPALIVE void remove_light(TViewer *viewer, EntityId entityId); - EMSCRIPTEN_KEEPALIVE void clear_lights(TViewer *viewer); - EMSCRIPTEN_KEEPALIVE void set_light_position(TViewer *viewer, EntityId light, float x, float y, float z); - EMSCRIPTEN_KEEPALIVE void set_light_direction(TViewer *viewer, EntityId light, float x, float y, float z); EMSCRIPTEN_KEEPALIVE EntityId get_main_camera(TViewer *viewer); diff --git a/thermion_dart/native/include/scene/SceneManager.hpp b/thermion_dart/native/include/scene/SceneManager.hpp index 809d2ed8..22b7d616 100644 --- a/thermion_dart/native/include/scene/SceneManager.hpp +++ b/thermion_dart/native/include/scene/SceneManager.hpp @@ -6,8 +6,11 @@ #include #include -#include #include +#include +#include +#include +#include #include #include @@ -15,8 +18,6 @@ #include #include -#include -#include #include #include "tsl/robin_map.h" @@ -92,6 +93,30 @@ namespace thermion /// @return SceneAsset* loadGlbFromBuffer(const uint8_t *data, size_t length, int numInstances = 1, bool keepData = false, int priority = 4, int layer = 0, bool loadResourcesAsync = false, bool addToScene = true); + /// @brief Destroys all assets and instances. + /// + utils::Entity addLight( + filament::LightManager::Type t, + float colour, + float intensity, + float posX, + float posY, + float posZ, + float dirX, + float dirY, + float dirZ, + float falloffRadius, + float spotLightConeInner, + float spotLightConeOuter, + float sunAngularRadius, + float sunHaloSize, + float sunHaloFallof, + bool shadows); + + /// @brief Removes/destroys the light. + /// + void removeLight(utils::Entity entity); + /// /// Creates an instance of the given entity. /// This may return an instance from a pool of inactive instances; see [remove] for more information. @@ -106,10 +131,18 @@ namespace thermion /// @param entity void destroy(SceneAsset* entity); - /// @brief Destroys all assets, scenes, materials, etc. + /// @brief Destroys all lights. /// - void destroyAll(); - + void destroyLights(); + + /// @brief Destroys all assets and instances. + /// + void destroyAssets(); + + /// @brief Destroys all assets/instances, scenes, materials, etc. + /// + void destroyAll(); + /// @brief /// @param entityId void transformToUnitCube(EntityId entityId); @@ -336,6 +369,7 @@ namespace thermion tsl::robin_map _transformUpdates; std::set _textures; std::vector _cameras; + std::vector _lights; std::vector> _sceneAssets; std::vector> _gizmos; diff --git a/thermion_dart/native/src/FilamentViewer.cpp b/thermion_dart/native/src/FilamentViewer.cpp index 97220004..64a30c74 100644 --- a/thermion_dart/native/src/FilamentViewer.cpp +++ b/thermion_dart/native/src/FilamentViewer.cpp @@ -52,7 +52,6 @@ #include #include -#include #include #include @@ -99,12 +98,6 @@ #include "TimeIt.hpp" #include "UnprojectTexture.hpp" -namespace filament -{ - class IndirectLight; - class LightManager; -} // namespace filament - namespace thermion { @@ -191,107 +184,6 @@ namespace thermion _renderer->setFrameRateOptions(fro); } - EntityId FilamentViewer::addLight( - LightManager::Type t, - float colour, - float intensity, - float posX, - float posY, - float posZ, - float dirX, - float dirY, - float dirZ, - float falloffRadius, - float spotLightConeInner, - float spotLightConeOuter, - float sunAngularRadius, - float sunHaloSize, - float sunHaloFallof, - bool shadows) - { - auto light = EntityManager::get().create(); - - auto result = LightManager::Builder(t) - .color(Color::cct(colour)) - .intensity(intensity) - .falloff(falloffRadius) - .spotLightCone(spotLightConeInner, spotLightConeOuter) - .sunAngularRadius(sunAngularRadius) - .sunHaloSize(sunHaloSize) - .sunHaloFalloff(sunHaloFallof) - .position(filament::math::float3(posX, posY, posZ)) - .direction(filament::math::float3(dirX, dirY, dirZ)) - .castShadows(shadows) - .build(*_engine, light); - if (result != LightManager::Builder::Result::Success) - { - Log("ERROR : failed to create light"); - } - else - { - _scene->addEntity(light); - _lights.push_back(light); - } - - return Entity::smuggle(light); - } - - void FilamentViewer::setLightPosition(EntityId entityId, float x, float y, float z) - { - auto light = Entity::import(entityId); - - if (light.isNull()) - { - Log("Light not found for entity %d", entityId); - return; - } - - auto &lm = _engine->getLightManager(); - - auto instance = lm.getInstance(light); - - lm.setPosition(instance, filament::math::float3{x, y, z}); - } - - void FilamentViewer::setLightDirection(EntityId entityId, float x, float y, float z) - { - auto light = Entity::import(entityId); - - if (light.isNull()) - { - Log("Light not found for entity %d", entityId); - return; - } - - auto &lm = _engine->getLightManager(); - - auto instance = lm.getInstance(light); - - lm.setDirection(instance, filament::math::float3{x, y, z}); - } - - void FilamentViewer::removeLight(EntityId entityId) - { - auto entity = utils::Entity::import(entityId); - if (entity.isNull()) - { - Log("Error: light entity not found under ID %d", entityId); - } - else - { - auto removed = remove(_lights.begin(), _lights.end(), entity); - _scene->remove(entity); - EntityManager::get().destroy(1, &entity); - } - } - - void FilamentViewer::clearLights() - { - _scene->removeEntities(_lights.data(), _lights.size()); - EntityManager::get().destroy(_lights.size(), _lights.data()); - _lights.clear(); - } - static bool endsWith(std::string path, std::string ending) { return path.compare(path.length() - ending.length(), ending.length(), ending) == 0; @@ -630,7 +522,8 @@ namespace thermion FilamentViewer::~FilamentViewer() { - clearLights(); + + _sceneManager->destroyAll(); for (auto view : _views) { @@ -952,7 +845,7 @@ namespace thermion _iblTexture->setImage(*_engine, 0, std::move(pbd)); - _indirectLight = IndirectLight::Builder() + _indirectLight = filament::IndirectLight::Builder() .reflections(_iblTexture) .intensity(intensity) .build(*_engine); @@ -995,7 +888,7 @@ namespace thermion delete rb; delete vec; }, callbackData); - _indirectLight = IndirectLight::Builder() + _indirectLight = filament::IndirectLight::Builder() .reflections(_iblTexture) .irradiance(3, harmonics) .intensity(intensity) diff --git a/thermion_dart/native/src/c_api/TLightManager.cpp b/thermion_dart/native/src/c_api/TLightManager.cpp new file mode 100644 index 00000000..7225b0e3 --- /dev/null +++ b/thermion_dart/native/src/c_api/TLightManager.cpp @@ -0,0 +1,33 @@ + +#include + +#include + +#include "c_api/APIExport.h" +#include "Log.hpp" + +extern "C" +{ + +#include "c_api/TLightManager.h" + + EMSCRIPTEN_KEEPALIVE void LightManager_setPosition(TLightManager *tLightManager, EntityId light, double x, double y, double z) { + auto lightManager = reinterpret_cast(tLightManager); + auto instance = lightManager->getInstance(utils::Entity::import(light)); + if(!instance.isValid()) { + Log("Warning: invalid light instance"); + return; + } + lightManager->setPosition(instance, filament::math::float3 { x, y, z }); + } + + EMSCRIPTEN_KEEPALIVE void LightManager_setDirection(TLightManager *tLightManager, EntityId light, double x, double y, double z) { + auto lightManager = reinterpret_cast(tLightManager); + auto instance = lightManager->getInstance(utils::Entity::import(light)); + if(!instance.isValid()) { + Log("Warning: invalid light instance"); + return; + } + lightManager->setPosition(instance, filament::math::float3 { x, y, z }); + } +} \ No newline at end of file diff --git a/thermion_dart/native/src/c_api/TSceneManager.cpp b/thermion_dart/native/src/c_api/TSceneManager.cpp index 3da8abc0..118bb8e1 100644 --- a/thermion_dart/native/src/c_api/TSceneManager.cpp +++ b/thermion_dart/native/src/c_api/TSceneManager.cpp @@ -12,22 +12,24 @@ extern "C" #include "c_api/TSceneManager.h" - EMSCRIPTEN_KEEPALIVE TScene *SceneManager_getScene(TSceneManager *tSceneManager) { + EMSCRIPTEN_KEEPALIVE TScene *SceneManager_getScene(TSceneManager *tSceneManager) + { auto sceneManager = reinterpret_cast(tSceneManager); - return reinterpret_cast(sceneManager->getScene()); + return reinterpret_cast(sceneManager->getScene()); } - - EMSCRIPTEN_KEEPALIVE TMaterialProvider *SceneManager_getUnlitMaterialProvider(TSceneManager *tSceneManager) { + EMSCRIPTEN_KEEPALIVE TMaterialProvider *SceneManager_getUnlitMaterialProvider(TSceneManager *tSceneManager) + { auto sceneManager = reinterpret_cast(tSceneManager); auto provider = sceneManager->getUnlitMaterialProvider(); - return reinterpret_cast(provider); + return reinterpret_cast(provider); } - EMSCRIPTEN_KEEPALIVE TMaterialProvider *SceneManager_getUbershaderMaterialProvider(TSceneManager *tSceneManager) { + EMSCRIPTEN_KEEPALIVE TMaterialProvider *SceneManager_getUbershaderMaterialProvider(TSceneManager *tSceneManager) + { auto sceneManager = reinterpret_cast(tSceneManager); auto provider = sceneManager->getUbershaderMaterialProvider(); - return reinterpret_cast(provider); + return reinterpret_cast(provider); } EMSCRIPTEN_KEEPALIVE TGizmo *SceneManager_createGizmo(TSceneManager *tSceneManager, TView *tView, TScene *tScene, TGizmoType tGizmoType) @@ -46,7 +48,7 @@ extern "C" return reinterpret_cast(asset); } - EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_loadGltf(TSceneManager *tSceneManager, + EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_loadGltf(TSceneManager *tSceneManager, const char *assetPath, const char *relativeResourcePath, bool keepData) @@ -56,7 +58,6 @@ extern "C" return reinterpret_cast(asset); } - EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_loadGlbFromBuffer(TSceneManager *tSceneManager, const uint8_t *const data, size_t length, int numInstances, bool keepData, int priority, int layer, bool loadResourcesAsync) { auto *sceneManager = reinterpret_cast(tSceneManager); @@ -164,7 +165,6 @@ extern "C" ((SceneManager *)sceneManager)->destroy(reinterpret_cast(instance)); } - EMSCRIPTEN_KEEPALIVE int SceneManager_removeFromScene(TSceneManager *sceneManager, EntityId entityId) { return ((SceneManager *)sceneManager)->removeFromScene(entityId); @@ -187,36 +187,78 @@ extern "C" return reinterpret_cast(animationManager); } - EMSCRIPTEN_KEEPALIVE void *SceneManager_destroyAll(TSceneManager *tSceneManager) + EMSCRIPTEN_KEEPALIVE EntityId SceneManager_addLight( + TSceneManager *tSceneManager, + uint8_t type, + float colour, + float intensity, + float posX, + float posY, + float posZ, + float dirX, + float dirY, + float dirZ, + float falloffRadius, + float spotLightConeInner, + float spotLightConeOuter, + float sunAngularRadius, + float sunHaloSize, + float sunHaloFallof, + bool shadows) + { + auto *sceneManager = reinterpret_cast(tSceneManager); + auto entity = sceneManager->addLight( + (LightManager::Type)type, colour, intensity, posX, posY, posZ, dirX, dirY, dirZ, falloffRadius, spotLightConeInner, spotLightConeOuter, sunAngularRadius, sunHaloSize, sunHaloFallof, shadows); + } + + EMSCRIPTEN_KEEPALIVE void SceneManager_removeLight(TSceneManager *tSceneManager, EntityId entityId) + { + auto *sceneManager = reinterpret_cast(tSceneManager); + sceneManager->removeLight(utils::Entity::import(entityId)); + } + + EMSCRIPTEN_KEEPALIVE void SceneManager_destroyAll(TSceneManager *tSceneManager) { auto *sceneManager = reinterpret_cast(tSceneManager); sceneManager->destroyAll(); - return nullptr; } - EMSCRIPTEN_KEEPALIVE void *SceneManager_destroyAsset(TSceneManager *tSceneManager, TSceneAsset *tSceneAsset) + EMSCRIPTEN_KEEPALIVE void SceneManager_destroyAsset(TSceneManager *tSceneManager, TSceneAsset *tSceneAsset) { auto *sceneManager = reinterpret_cast(tSceneManager); auto *sceneAsset = reinterpret_cast(tSceneAsset); sceneManager->destroy(sceneAsset); - return nullptr; } - EMSCRIPTEN_KEEPALIVE TNameComponentManager *SceneManager_getNameComponentManager(TSceneManager *tSceneManager) { + EMSCRIPTEN_KEEPALIVE void SceneManager_destroyLights(TSceneManager *tSceneManager) + { auto *sceneManager = reinterpret_cast(tSceneManager); - return reinterpret_cast(sceneManager->getNameComponentManager()); + sceneManager->destroyLights(); } - EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_createGrid(TSceneManager *tSceneManager, TMaterial *tMaterial) { + EMSCRIPTEN_KEEPALIVE void SceneManager_destroyAssets(TSceneManager *tSceneManager) + { + auto *sceneManager = reinterpret_cast(tSceneManager); + sceneManager->destroyAssets(); + } + + EMSCRIPTEN_KEEPALIVE TNameComponentManager *SceneManager_getNameComponentManager(TSceneManager *tSceneManager) + { + auto *sceneManager = reinterpret_cast(tSceneManager); + return reinterpret_cast(sceneManager->getNameComponentManager()); + } + + EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_createGrid(TSceneManager *tSceneManager, TMaterial *tMaterial) + { auto *sceneManager = reinterpret_cast(tSceneManager); auto *material = reinterpret_cast(tMaterial); auto *grid = sceneManager->createGrid(material); - return reinterpret_cast(grid); + return reinterpret_cast(grid); } - EMSCRIPTEN_KEEPALIVE bool SceneManager_isGridEntity(TSceneManager *tSceneManager, EntityId entityId) { + EMSCRIPTEN_KEEPALIVE bool SceneManager_isGridEntity(TSceneManager *tSceneManager, EntityId entityId) + { auto *sceneManager = reinterpret_cast(tSceneManager); return sceneManager->isGridEntity(utils::Entity::import(entityId)); } - } \ No newline at end of file diff --git a/thermion_dart/native/src/c_api/ThermionDartApi.cpp b/thermion_dart/native/src/c_api/ThermionDartApi.cpp index 00012ea0..931da94b 100644 --- a/thermion_dart/native/src/c_api/ThermionDartApi.cpp +++ b/thermion_dart/native/src/c_api/ThermionDartApi.cpp @@ -113,48 +113,6 @@ extern "C" ((FilamentViewer *)viewer)->removeIbl(); } - EMSCRIPTEN_KEEPALIVE EntityId add_light( - TViewer *viewer, - uint8_t type, - float colour, - float intensity, - float posX, - float posY, - float posZ, - float dirX, - float dirY, - float dirZ, - float falloffRadius, - float spotLightConeInner, - float spotLightConeOuter, - float sunAngularRadius, - float sunHaloSize, - float sunHaloFallof, - bool shadows) - { - return ((FilamentViewer *)viewer)->addLight((LightManager::Type)type, colour, intensity, posX, posY, posZ, dirX, dirY, dirZ, falloffRadius, spotLightConeInner, spotLightConeOuter, sunAngularRadius, sunHaloSize, sunHaloFallof, shadows); - } - - EMSCRIPTEN_KEEPALIVE void set_light_position(TViewer *viewer, int32_t entityId, float x, float y, float z) - { - ((FilamentViewer *)viewer)->setLightPosition(entityId, x, y, z); - } - - EMSCRIPTEN_KEEPALIVE void set_light_direction(TViewer *viewer, int32_t entityId, float x, float y, float z) - { - ((FilamentViewer *)viewer)->setLightDirection(entityId, x, y, z); - } - - EMSCRIPTEN_KEEPALIVE void remove_light(TViewer *viewer, int32_t entityId) - { - ((FilamentViewer *)viewer)->removeLight(entityId); - } - - EMSCRIPTEN_KEEPALIVE void clear_lights(TViewer *viewer) - { - ((FilamentViewer *)viewer)->clearLights(); - } - EMSCRIPTEN_KEEPALIVE int get_instance_count(TSceneManager *sceneManager, EntityId entityId) { return ((SceneManager *)sceneManager)->getInstanceCount(entityId); @@ -489,6 +447,12 @@ extern "C" 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); diff --git a/thermion_dart/native/src/scene/SceneManager.cpp b/thermion_dart/native/src/scene/SceneManager.cpp index 6a128177..f4c48fc6 100644 --- a/thermion_dart/native/src/scene/SceneManager.cpp +++ b/thermion_dart/native/src/scene/SceneManager.cpp @@ -465,15 +465,11 @@ namespace thermion void SceneManager::destroyAll() { + + destroyLights(); + destroyAssets(); std::lock_guard lock(_mutex); - for (auto &asset : _sceneAssets) - { - asset->removeAllEntities(_scene); - } - - _sceneAssets.clear(); - for (auto *texture : _textures) { _engine->destroy(texture); @@ -515,6 +511,83 @@ namespace thermion } } + utils::Entity SceneManager::addLight( + LightManager::Type t, + float colour, + float intensity, + float posX, + float posY, + float posZ, + float dirX, + float dirY, + float dirZ, + float falloffRadius, + float spotLightConeInner, + float spotLightConeOuter, + float sunAngularRadius, + float sunHaloSize, + float sunHaloFallof, + bool shadows) + { + auto light = EntityManager::get().create(); + + auto result = LightManager::Builder(t) + .color(Color::cct(colour)) + .intensity(intensity) + .falloff(falloffRadius) + .spotLightCone(spotLightConeInner, spotLightConeOuter) + .sunAngularRadius(sunAngularRadius) + .sunHaloSize(sunHaloSize) + .sunHaloFalloff(sunHaloFallof) + .position(filament::math::float3(posX, posY, posZ)) + .direction(filament::math::float3(dirX, dirY, dirZ)) + .castShadows(shadows) + .build(*_engine, light); + if (result != LightManager::Builder::Result::Success) + { + Log("ERROR : failed to create light"); + } + else + { + _scene->addEntity(light); + _lights.push_back(light); + TRACE("Created light"); + } + + return light; + } + + void SceneManager::removeLight(utils::Entity entity) + { + auto removed = remove(_lights.begin(), _lights.end(), entity); + _scene->remove(entity); + EntityManager::get().destroy(1, &entity); + } + + void SceneManager::destroyLights() + { + std::lock_guard lock(_mutex); + + _scene->removeEntities(_lights.data(), _lights.size()); + EntityManager::get().destroy(_lights.size(), _lights.data()); + _lights.clear(); + } + + void SceneManager::destroyAssets() + { + std::lock_guard lock(_mutex); + + for (auto &asset : _sceneAssets) + { + asset->removeAllEntities(_scene); + for(int i = 0; i < asset->getInstanceCount(); i++) { + asset->getInstanceAt(i)->removeAllEntities(_scene); + } + } + + _sceneAssets.clear(); + } + Texture *SceneManager::createTexture(const uint8_t *data, size_t length, const char *name) { diff --git a/thermion_dart/test/asset_tests.dart b/thermion_dart/test/asset_tests.dart new file mode 100644 index 00000000..cda5dbd4 --- /dev/null +++ b/thermion_dart/test/asset_tests.dart @@ -0,0 +1,18 @@ +import 'package:thermion_dart/thermion_dart.dart'; +import 'package:test/test.dart'; +import 'package:vector_math/vector_math_64.dart'; +import 'helpers.dart'; + +void main() async { + final testHelper = TestHelper("lights"); + group("assets", () { + test('add/clear asset', () async { + await testHelper.withViewer((viewer) async { + var asset = await viewer.loadGlb("file://${testHelper.testDir}/assets/cube.glb"); + await testHelper.capture(viewer, "asset_loaded"); + await viewer.destroyAssets(); + await testHelper.capture(viewer, "assets_cleared"); + }, bg: kRed); + }); + }); +} diff --git a/thermion_dart/test/light_tests.dart b/thermion_dart/test/light_tests.dart new file mode 100644 index 00000000..c46b0085 --- /dev/null +++ b/thermion_dart/test/light_tests.dart @@ -0,0 +1,22 @@ +import 'package:thermion_dart/thermion_dart.dart'; +import 'package:test/test.dart'; +import 'package:vector_math/vector_math_64.dart'; +import 'helpers.dart'; + +void main() async { + final testHelper = TestHelper("lights"); + group("lights", () { + test('add/clear point lights', () async { + await testHelper.withViewer((viewer) async { + await viewer.loadGlb("file://${testHelper.testDir}/assets/cube.glb"); + + var light = await viewer.addDirectLight( + DirectLight.point(intensity: 10000000000, falloffRadius: 10)); + await viewer.setLightPosition(light, 0, 10, 0); + await testHelper.capture(viewer, "add_point_light"); + await viewer.destroyLights(); + await testHelper.capture(viewer, "remove_lights"); + }); + }); + }); +} diff --git a/thermion_flutter/thermion_flutter/lib/src/widgets/src/lights/light_slider.dart b/thermion_flutter/thermion_flutter/lib/src/widgets/src/lights/light_slider.dart index 10ca8d82..f29409f0 100644 --- a/thermion_flutter/thermion_flutter/lib/src/widgets/src/lights/light_slider.dart +++ b/thermion_flutter/thermion_flutter/lib/src/widgets/src/lights/light_slider.dart @@ -31,7 +31,7 @@ // } // Future _set() async { -// await widget.controller.clearLights(); +// await widget.controller.destroyLights(); // if (widget.options.iblPath != null) { // _light = await widget.controller.loadIbl(widget.options.iblPath!,