diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_camera.dart b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_camera.dart index fc065746..b02c86e6 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_camera.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_camera.dart @@ -5,7 +5,7 @@ import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart'; import 'package:thermion_dart/src/filament/src/layers.dart'; import 'package:thermion_dart/thermion_dart.dart'; -import 'package:vector_math/vector_math_64.dart'; + import '../../../../utils/src/matrix.dart'; class FFICamera extends Camera { diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_filament_app.dart b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_filament_app.dart index 8585d01d..0f8b5670 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_filament_app.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_filament_app.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:typed_data'; +import 'package:thermion_dart/src/filament/src/engine.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_material.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_render_target.dart'; @@ -14,12 +15,12 @@ typedef RenderCallback = Pointer)>>; class FFIFilamentConfig extends FilamentConfig> { FFIFilamentConfig( - {required super.backend, - required super.resourceLoader, - required super.driver, - required super.platform, - required super.sharedContext, - required super.uberArchivePath}); + {required super.resourceLoader, + super.backend = Backend.DEFAULT, + super.driver = null, + super.platform = null, + super.sharedContext = null, + super.uberArchivePath = null}); } class FFIFilamentApp extends FilamentApp { @@ -55,7 +56,8 @@ class FFIFilamentApp extends FilamentApp { renderableManager: renderableManager, ubershaderMaterialProvider: ubershaderMaterialProvider) {} - static Future create(FFIFilamentConfig config) async { + static Future create({FFIFilamentConfig? config}) async { + config ??= FFIFilamentConfig(resourceLoader: nullptr); if (FilamentApp.instance != null) { await FilamentApp.instance!.destroy(); } @@ -65,7 +67,7 @@ class FFIFilamentApp extends FilamentApp { final engine = await withPointerCallback((cb) => Engine_createRenderThread( - TBackend.values[config.backend.index].index, + TBackend.values[config!.backend.index].index, config.platform ?? nullptr, config.sharedContext ?? nullptr, config.stereoscopicEyeCount, @@ -79,15 +81,13 @@ class FFIFilamentApp extends FilamentApp { final renderer = await withPointerCallback( (cb) => Engine_createRendererRenderThread(engine, cb)); final ubershaderMaterialProvider = - await withPointerCallback( - (cb) => GltfAssetLoader_getMaterialProvider(gltfAssetLoader)); + GltfAssetLoader_getMaterialProvider(gltfAssetLoader); final transformManager = Engine_getTransformManager(engine); final lightManager = Engine_getLightManager(engine); final renderableManager = Engine_getRenderableManager(engine); - final renderTicker = await withPointerCallback( - (cb) => RenderTicker_create(renderer)); + final renderTicker = RenderTicker_create(renderer); final nameComponentManager = NameComponentManager_create(); @@ -210,7 +210,8 @@ class FFIFilamentApp extends FilamentApp { TextureSamplerType textureSamplerType = TextureSamplerType.SAMPLER_2D, TextureFormat textureFormat = TextureFormat.RGBA16F, int? importedTextureHandle}) async { - var bitmask = flags.fold(0, (a, b) => a | b.index); + var bitmask = flags.fold(0, (a, b) => a | b.value); + print("bitmask $bitmask"); final texturePtr = await withPointerCallback((cb) { Texture_buildRenderThread( engine, @@ -218,8 +219,8 @@ class FFIFilamentApp extends FilamentApp { height, depth, levels, - importedTextureHandle ?? 0, bitmask, + importedTextureHandle ?? 0, TTextureSamplerType.values[textureSamplerType.index], TTextureFormat.values[textureFormat.index], cb); @@ -404,7 +405,7 @@ class FFIFilamentApp extends FilamentApp { FFIMaterial? _gridMaterial; Future get gridMaterial async { - _gridMaterial ??= FFIMaterial(Material_createGridMaterial(), this); + _gridMaterial ??= FFIMaterial(Material_createGridMaterial(engine), this); return _gridMaterial!; } @@ -425,8 +426,8 @@ class FFIFilamentApp extends FilamentApp { /// @override Future render() async { - await withVoidCallback((cb) => - RenderTicker_renderRenderThread(renderTicker, 0, cb)); + await withVoidCallback( + (cb) => RenderTicker_renderRenderThread(renderTicker, 0, cb)); } /// @@ -436,6 +437,10 @@ class FFIFilamentApp extends FilamentApp { Future register( covariant FFISwapChain swapChain, covariant FFIView view) async { _viewMappings[view] = swapChain; + if (!_views.containsKey(swapChain)) { + _views[swapChain] = []; + } + _views[swapChain]!.add(view); } final _hooks = []; @@ -531,9 +536,12 @@ class FFIFilamentApp extends FilamentApp { Material? _imageMaterial; + /// + /// + /// @override Future createImageMaterialInstance() async { - _imageMaterial ??= FFIMaterial(Material_createImageMaterial(), + _imageMaterial ??= FFIMaterial(Material_createImageMaterial(engine), FilamentApp.instance! as FFIFilamentApp); var instance = await _imageMaterial!.createInstance() as FFIMaterialInstance; diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_material.dart b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_material.dart index 71ac18da..4f240a9a 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_material.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_material.dart @@ -4,7 +4,6 @@ import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_texture.dart'; import 'package:thermion_dart/thermion_dart.dart'; -import 'package:vector_math/vector_math_64.dart'; class FFIMaterial extends Material { final FFIFilamentApp app; diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_swapchain.dart b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_swapchain.dart index a7a036d0..aff2ca66 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_swapchain.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_swapchain.dart @@ -1,5 +1,3 @@ -import 'dart:ffi'; - import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart'; import 'package:thermion_dart/thermion_dart.dart'; diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_view.dart b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_view.dart index 197fdbfc..d76b5746 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_view.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_view.dart @@ -107,7 +107,7 @@ class FFIView extends View { } Future setScene(covariant FFIScene scene) async { - await withVoidCallback((cb) => View_setScene(view, scene.scene)); + View_setScene(view, scene.scene); } @override diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart index 636efadc..8ed8f10a 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart @@ -25,11 +25,15 @@ external ffi.Pointer Material_createInstance( ffi.Pointer tMaterial, ); -@ffi.Native Function()>(isLeaf: true) -external ffi.Pointer Material_createImageMaterial(); +@ffi.Native Function(ffi.Pointer)>(isLeaf: true) +external ffi.Pointer Material_createImageMaterial( + ffi.Pointer tEngine, +); -@ffi.Native Function()>(isLeaf: true) -external ffi.Pointer Material_createGridMaterial(); +@ffi.Native Function(ffi.Pointer)>(isLeaf: true) +external ffi.Pointer Material_createGridMaterial( + ffi.Pointer tEngine, +); @ffi.Native, ffi.Pointer)>( isLeaf: true) @@ -1491,9 +1495,11 @@ external void RenderLoop_create(); @ffi.Native(isLeaf: true) external void RenderLoop_destroy(); -@ffi.Native)>(isLeaf: true) +@ffi.Native< + ffi.Void Function( + ffi.Pointer>)>(isLeaf: true) external void RenderLoop_requestAnimationFrame( - ffi.Pointer onComplete, + ffi.Pointer> onComplete, ); @ffi.Native< @@ -3847,7 +3853,7 @@ enum TGizmoType { }; } -sealed class TPrimitiveType { +abstract class TPrimitiveType { /// !< points static const PRIMITIVETYPE_POINTS = 0; @@ -4265,7 +4271,7 @@ enum TTextureFormat { } /// ! Pixel Data Format -sealed class TPixelDataFormat { +abstract class TPixelDataFormat { /// !< One Red channel, float static const PIXELDATAFORMAT_R = 0; @@ -4299,7 +4305,7 @@ sealed class TPixelDataFormat { static const PIXELDATAFORMAT_ALPHA = 11; } -sealed class TPixelDataType { +abstract class TPixelDataType { /// !< unsigned byte static const PIXELDATATYPE_UBYTE = 0; 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 84a8787d..dd04e707 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 @@ -95,6 +95,7 @@ class ThermionViewerFFI extends ThermionViewer { _cameras.add(camera); await view.setCamera(camera); + if (renderTarget != null) { await view.setRenderTarget(renderTarget); } @@ -149,14 +150,12 @@ class ThermionViewerFFI extends ThermionViewer { } final _onDispose = []; - bool _disposing = false; /// /// /// @override Future dispose() async { - _disposing = true; await setRendering(false); await destroyAssets(); await destroyLights(); @@ -166,7 +165,6 @@ class ThermionViewerFFI extends ThermionViewer { } _onDispose.clear(); - _disposing = false; } /// diff --git a/thermion_dart/native/include/RenderTicker.hpp b/thermion_dart/native/include/RenderTicker.hpp index a92584db..4280eab0 100644 --- a/thermion_dart/native/include/RenderTicker.hpp +++ b/thermion_dart/native/include/RenderTicker.hpp @@ -25,10 +25,6 @@ namespace thermion { - typedef std::chrono::time_point time_point_t; - - using namespace std::chrono; - class RenderTicker { diff --git a/thermion_dart/native/include/c_api/TMaterialInstance.h b/thermion_dart/native/include/c_api/TMaterialInstance.h index 14e4cedf..0ff40a61 100644 --- a/thermion_dart/native/include/c_api/TMaterialInstance.h +++ b/thermion_dart/native/include/c_api/TMaterialInstance.h @@ -68,8 +68,8 @@ extern "C" }; EMSCRIPTEN_KEEPALIVE TMaterialInstance *Material_createInstance(TMaterial *tMaterial); - EMSCRIPTEN_KEEPALIVE TMaterial *Material_createImageMaterial(); - EMSCRIPTEN_KEEPALIVE TMaterial *Material_createGridMaterial(); + EMSCRIPTEN_KEEPALIVE TMaterial *Material_createImageMaterial(TEngine *tEngine); + EMSCRIPTEN_KEEPALIVE TMaterial *Material_createGridMaterial(TEngine *tEngine); EMSCRIPTEN_KEEPALIVE bool Material_hasParameter(TMaterial *tMaterial, const char *propertyName); EMSCRIPTEN_KEEPALIVE bool MaterialInstance_isStencilWriteEnabled(TMaterialInstance *materialInstance); EMSCRIPTEN_KEEPALIVE void MaterialInstance_setStencilWrite(TMaterialInstance *materialInstance, bool enabled); diff --git a/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h b/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h index f8cc283d..7aeaf875 100644 --- a/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h +++ b/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h @@ -16,7 +16,7 @@ namespace thermion EMSCRIPTEN_KEEPALIVE void RenderLoop_create(); EMSCRIPTEN_KEEPALIVE void RenderLoop_destroy(); - EMSCRIPTEN_KEEPALIVE void RenderLoop_requestAnimationFrame(void (*onComplete)); + EMSCRIPTEN_KEEPALIVE void RenderLoop_requestAnimationFrame(void (*onComplete)()); EMSCRIPTEN_KEEPALIVE void RenderTicker_renderRenderThread(TRenderTicker *tRenderTicker, uint64_t frameTimeInNanos, void (*onComplete)()); // EMSCRIPTEN_KEEPALIVE void RenderLoop_addTask(TRenderLoop* tRenderLoop, void (*task)()); @@ -52,6 +52,7 @@ namespace thermion TTextureFormat format, void (*onComplete)(TTexture*) ); + EMSCRIPTEN_KEEPALIVE void Engine_destroyTextureRenderThread(TEngine *engine, TTexture* tTexture, void (*onComplete)()); EMSCRIPTEN_KEEPALIVE void Engine_createFenceRenderThread(TEngine *tEngine, void (*onComplete)(TFence*)); EMSCRIPTEN_KEEPALIVE void Engine_destroyFenceRenderThread(TEngine *tEngine, TFence *tFence, void (*onComplete)()); @@ -175,18 +176,6 @@ namespace thermion EMSCRIPTEN_KEEPALIVE void Image_getHeightRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t)); EMSCRIPTEN_KEEPALIVE void Image_getChannelsRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t)); - // Texture methods - EMSCRIPTEN_KEEPALIVE void Texture_buildRenderThread(TEngine *engine, - uint32_t width, - uint32_t height, - uint32_t depth, - uint8_t levels, - uint16_t tUsage, - intptr_t import, - TTextureSamplerType sampler, - TTextureFormat format, - void (*onComplete)(TTexture *) - ); EMSCRIPTEN_KEEPALIVE void Texture_loadImageRenderThread( TEngine *tEngine, @@ -292,8 +281,6 @@ namespace thermion void (*onComplete)() ); - EMSCRIPTEN_KEEPALIVE void AnimationManager_updateBoneMatricesRenderThread(TSceneManager *sceneManager, - EntityId asset, void (*callback)(bool)); EMSCRIPTEN_KEEPALIVE void AnimationManager_setBoneTransformRenderThread( TAnimationManager *tAnimationManager, EntityId asset, diff --git a/thermion_dart/native/include/scene/Gizmo.hpp b/thermion_dart/native/include/scene/Gizmo.hpp index f4e500de..9ad8b8d2 100644 --- a/thermion_dart/native/include/scene/Gizmo.hpp +++ b/thermion_dart/native/include/scene/Gizmo.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include #include #include diff --git a/thermion_dart/native/include/scene/GridOverlay.hpp b/thermion_dart/native/include/scene/GridOverlay.hpp index da070d4e..c53266a1 100644 --- a/thermion_dart/native/include/scene/GridOverlay.hpp +++ b/thermion_dart/native/include/scene/GridOverlay.hpp @@ -37,10 +37,6 @@ public: void addAllEntities(Scene* scene) override; void removeAllEntities(Scene* scene) override; - void setPriority(RenderableManager& rm, int priority) override; - void setLayer(RenderableManager& rm, int layer) override; - - size_t getInstanceCount() override { return _instances.size(); } SceneAsset* getInstanceByEntity(utils::Entity entity) override; SceneAsset* getInstanceAt(size_t index) override; diff --git a/thermion_dart/native/src/GridOverlay.cpp b/thermion_dart/native/src/GridOverlay.cpp index 0b133f47..fd23f61b 100644 --- a/thermion_dart/native/src/GridOverlay.cpp +++ b/thermion_dart/native/src/GridOverlay.cpp @@ -227,23 +227,7 @@ namespace thermion scene->remove(_gridEntity); // scene->remove(_sphereEntity); } - - void GridOverlay::setPriority(RenderableManager &rm, int priority) - { - auto gridInstance = rm.getInstance(_gridEntity); - rm.setPriority(gridInstance, priority); - // auto sphereInstance = rm.getInstance(_sphereEntity); - // rm.setPriority(sphereInstance, priority); - } - - void GridOverlay::setLayer(RenderableManager &rm, int layer) - { - auto gridInstance = rm.getInstance(_gridEntity); - rm.setLayerMask(gridInstance, 0xFF, 1u << (uint8_t)layer); - // auto sphereInstance = rm.getInstance(_sphereEntity); - // rm.setLayerMask(sphereInstance, 0xFF, 1u << (uint8_t)layer); - } - + SceneAsset *GridOverlay::getInstanceByEntity(utils::Entity entity) { for (auto &instance : _instances) diff --git a/thermion_dart/native/src/RenderTicker.cpp b/thermion_dart/native/src/RenderTicker.cpp index 259fdfcd..438db81a 100644 --- a/thermion_dart/native/src/RenderTicker.cpp +++ b/thermion_dart/native/src/RenderTicker.cpp @@ -42,7 +42,6 @@ namespace thermion using namespace filament; using namespace filament::math; using namespace utils; - using namespace std::chrono; using std::string; diff --git a/thermion_dart/native/src/c_api/TCamera.cpp b/thermion_dart/native/src/c_api/TCamera.cpp index 774d0f10..df69ab14 100644 --- a/thermion_dart/native/src/c_api/TCamera.cpp +++ b/thermion_dart/native/src/c_api/TCamera.cpp @@ -1,12 +1,13 @@ +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include + #include -#include "c_api/ThermionDartApi.h" #include "c_api/TCamera.h" #include "Log.hpp" #include "MathUtils.hpp" @@ -32,8 +33,8 @@ namespace thermion EMSCRIPTEN_KEEPALIVE void Camera_getFrustum(TCamera *tCamera, double *out) { auto *camera = reinterpret_cast(tCamera); - auto &frustum = camera->getFrustum(); - auto planes = frustum.getPlanes(); + auto frustum = camera->getFrustum(); + auto planes = frustum.getNormalizedPlanes(); for(int i = 0; i < 6; i++) { for(int j = 0; j < 4; j++) { out[(i*4) + j] = planes[i][j]; @@ -41,18 +42,30 @@ namespace thermion } } + EMSCRIPTEN_KEEPALIVE void Camera_setLensProjection(TCamera *tCamera, double near, double far, double aspect, double focalLength) { + auto *camera = reinterpret_cast(tCamera); + camera->setLensProjection(near, far, aspect, focalLength); + } + + EMSCRIPTEN_KEEPALIVE void Camera_setModelMatrix(TCamera *tCamera, double4x4 tModelMatrix) { + auto *camera = reinterpret_cast(tCamera); + auto modelMatrix = convert_double4x4_to_mat4(tModelMatrix); + camera->setModelMatrix(modelMatrix); + } + + EMSCRIPTEN_KEEPALIVE void Camera_setCustomProjectionWithCulling(TCamera *tCamera, double4x4 projectionMatrix, double near, double far) { auto *camera = reinterpret_cast(tCamera); camera->setCustomProjection(convert_double4x4_to_mat4(projectionMatrix), near, far); } - EMSCRIPTEN_KEEPALIVE double Camera_getFocusDistance(TCamera *camera) { + EMSCRIPTEN_KEEPALIVE double Camera_getFocusDistance(TCamera *tCamera) { auto *camera = reinterpret_cast(tCamera); return camera->getFocusDistance(); } - EMSCRIPTEN_KEEPALIVE void Camera_setFocusDistance(TCamera *camera, float distance) { + EMSCRIPTEN_KEEPALIVE void Camera_setFocusDistance(TCamera *tCamera, float distance) { auto *camera = reinterpret_cast(tCamera); return camera->setFocusDistance(distance); } @@ -93,16 +106,16 @@ namespace thermion return camera->getCullingFar(); } - EMSCRIPTEN_KEEPALIVE void Camera_setProjection(TCamera *const tCamera, Projection projection, double left, double right, + EMSCRIPTEN_KEEPALIVE void Camera_setProjection(TCamera *const tCamera, TProjection projection, double left, double right, double bottom, double top, double near, double far) { auto *camera = reinterpret_cast(tCamera); filament::Camera::Projection filamentProjection; switch(projection) { - case Projection::Orthographic: + case TProjection::Orthographic: filamentProjection = filament::Camera::Projection::ORTHO; - case Projection::Perspective: + case TProjection::Perspective: filamentProjection = filament::Camera::Projection::PERSPECTIVE; } camera->setProjection(filamentProjection, left, right, bottom, top, near, far); diff --git a/thermion_dart/native/src/c_api/TEngine.cpp b/thermion_dart/native/src/c_api/TEngine.cpp index e5049500..b53f2129 100644 --- a/thermion_dart/native/src/c_api/TEngine.cpp +++ b/thermion_dart/native/src/c_api/TEngine.cpp @@ -47,15 +47,21 @@ namespace thermion EMSCRIPTEN_KEEPALIVE TEngine *Engine_create( TBackend backend, - void* platform, - void* sharedContext, + void* tPlatform, + void* tSharedContext, uint8_t stereoscopicEyeCount, bool disableHandleUseAfterFreeCheck) { filament::Engine::Config config; config.stereoscopicEyeCount = stereoscopicEyeCount; config.disableHandleUseAfterFreeCheck = disableHandleUseAfterFreeCheck; - auto *engine = filament::Engine::create(static_cast(backend), platform, sharedContext, &config); + auto *platform = reinterpret_cast(tPlatform); + auto *engine = filament::Engine::create( + static_cast(backend), + platform, + tSharedContext, + &config + ); return reinterpret_cast(engine); } diff --git a/thermion_dart/native/src/c_api/TLightManager.cpp b/thermion_dart/native/src/c_api/TLightManager.cpp index 0dd6eb34..7b9783a7 100644 --- a/thermion_dart/native/src/c_api/TLightManager.cpp +++ b/thermion_dart/native/src/c_api/TLightManager.cpp @@ -46,12 +46,13 @@ EMSCRIPTEN_KEEPALIVE int LightManager_createLight(TEngine *tEngine, TLightManage } filament::LightManager::Builder builder(lightType); - auto entity = utils::EntityManager::create(); - auto result = builder.build(*engine, utils::Entity::import(entity)); + auto &em = utils::EntityManager::get(); + auto entity = em.create(); + auto result = builder.build(*engine, entity); if(result != filament::LightManager::Builder::Result::Success) { Log("Failed to create light"); } - return entity; + return utils::Entity::smuggle(entity); } EMSCRIPTEN_KEEPALIVE void LightManager_destroyLight(TLightManager *tLightManager, EntityId entity) { diff --git a/thermion_dart/native/src/c_api/TMaterialInstance.cpp b/thermion_dart/native/src/c_api/TMaterialInstance.cpp index d9f98661..ea36ebd3 100644 --- a/thermion_dart/native/src/c_api/TMaterialInstance.cpp +++ b/thermion_dart/native/src/c_api/TMaterialInstance.cpp @@ -2,12 +2,16 @@ #include #include + #include #include #include #include "Log.hpp" -#include "materials/image.h" + +#include "material/image.h" +#include "material/grid.h" + #include "c_api/TMaterialInstance.h" #ifdef __cplusplus @@ -26,7 +30,7 @@ namespace thermion EMSCRIPTEN_KEEPALIVE TMaterial *Material_createImageMaterial(TEngine *tEngine) { auto *engine = reinterpret_cast(tEngine); - auto *material = Material::Builder() + auto *material = filament::Material::Builder() .package(IMAGE_IMAGE_DATA, IMAGE_IMAGE_SIZE) .build(*engine); @@ -35,10 +39,9 @@ namespace thermion EMSCRIPTEN_KEEPALIVE TMaterial *Material_createGridMaterial(TEngine *tEngine) { auto *engine = reinterpret_cast(tEngine); - auto *material = Material::Builder() - .package(GRID_GRID_DATA, GRID_GRID_SIZE) - .build(*engine); - + auto *material = filament::Material::Builder() + .package(GRID_GRID_DATA, GRID_GRID_SIZE) + .build(*engine); return reinterpret_cast(material); } diff --git a/thermion_dart/native/src/c_api/TRenderableManager.cpp b/thermion_dart/native/src/c_api/TRenderableManager.cpp index d09df6f4..2d173461 100644 --- a/thermion_dart/native/src/c_api/TRenderableManager.cpp +++ b/thermion_dart/native/src/c_api/TRenderableManager.cpp @@ -121,7 +121,7 @@ namespace thermion if (!renderableInstance.isValid()) { return Aabb3 { }; } - auto box = renderableManager.getAxisAlignedBoundingBox(renderableInstance); + auto box = renderableManager->getAxisAlignedBoundingBox(renderableInstance); return Aabb3{box.center.x, box.center.y, box.center.z, box.halfExtent.x, box.halfExtent.y, box.halfExtent.z}; } diff --git a/thermion_dart/native/src/c_api/TTexture.cpp b/thermion_dart/native/src/c_api/TTexture.cpp index 05e88fb8..ea388cd9 100644 --- a/thermion_dart/native/src/c_api/TTexture.cpp +++ b/thermion_dart/native/src/c_api/TTexture.cpp @@ -1,7 +1,6 @@ +#include #include -#include "c_api/TTexture.h" - #include #include #include @@ -15,6 +14,8 @@ #include #include +#include "c_api/TTexture.h" + #include "Log.hpp" #ifdef __cplusplus @@ -227,7 +228,7 @@ namespace thermion auto *engine = reinterpret_cast<::filament::Engine *>(tEngine); auto format = convertToFilamentFormat(tFormat); auto samplerType = static_cast<::filament::Texture::Sampler>(static_cast(tSamplerType)); - auto usage = static_cast<::filament::Texture::Usage>(tUsage); + auto usage = static_cast(tUsage); if ((usage & TextureUsage::UPLOADABLE) == TextureUsage::UPLOADABLE) { TRACE("UPLOADABLE"); diff --git a/thermion_dart/native/src/rendering/RenderLoop.cpp b/thermion_dart/native/src/rendering/RenderLoop.cpp index 385cb75c..a0e309b9 100644 --- a/thermion_dart/native/src/rendering/RenderLoop.cpp +++ b/thermion_dart/native/src/rendering/RenderLoop.cpp @@ -1,4 +1,4 @@ -#include "RenderLoop.hpp" +#include "rendering/RenderLoop.hpp" #include #include diff --git a/thermion_dart/native/src/scene/SceneManager.cpp b/thermion_dart/native/src/scene/SceneManager.cpp index 6e4637e0..32aaca46 100644 --- a/thermion_dart/native/src/scene/SceneManager.cpp +++ b/thermion_dart/native/src/scene/SceneManager.cpp @@ -1,970 +1,970 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "material/FileMaterialProvider.hpp" -#include "material/UnlitMaterialProvider.hpp" -#include "material/unlit.h" -#include "material/gizmo.h" - -#include "StreamBufferAdapter.hpp" - -#include "Log.hpp" - -#include "scene/SceneManager.hpp" -#include "scene/CustomGeometry.hpp" -#include "scene/GeometrySceneAsset.hpp" -#include "scene/GltfSceneAsset.hpp" -#include "scene/Gizmo.hpp" -#include "scene/SceneAsset.hpp" -#include "scene/GeometrySceneAssetBuilder.hpp" -#include "TextureProjection.hpp" - -#include "resources/translation_gizmo_glb.h" -#include "resources/rotation_gizmo_glb.h" - -extern "C" -{ -#include "material/image.h" -#include "material/unlit_fixed_size.h" -} - -namespace thermion -{ - - using namespace std::chrono; - using namespace image; - using namespace utils; - using namespace filament; - using namespace filament::gltfio; - using std::unique_ptr; - - SceneManager::SceneManager(const ResourceLoaderWrapperImpl *const resourceLoaderWrapper, - Engine *engine, - Scene *scene, - const char *uberArchivePath, - Camera *mainCamera) - : _resourceLoaderWrapper(resourceLoaderWrapper), - _engine(engine), - _scene(scene), - _mainCamera(mainCamera) - { - - _stbDecoder = createStbProvider(_engine); - _ktxDecoder = createKtx2Provider(_engine); - - _gltfResourceLoader = new ResourceLoader({.engine = _engine, - .normalizeSkinningWeights = true}); - if (uberArchivePath) - { - auto uberdata = resourceLoaderWrapper->load(uberArchivePath); - if (!uberdata.data) - { - Log("Failed to load ubershader material. This is fatal."); - } - _ubershaderProvider = gltfio::createUbershaderProvider(_engine, uberdata.data, uberdata.size); - resourceLoaderWrapper->free(uberdata); - } - else - { - _ubershaderProvider = gltfio::createUbershaderProvider( - _engine, UBERARCHIVE_DEFAULT_DATA, UBERARCHIVE_DEFAULT_SIZE); - } - - _unlitMaterialProvider = new UnlitMaterialProvider(_engine, UNLIT_PACKAGE, UNLIT_UNLIT_SIZE); - - utils::EntityManager &em = utils::EntityManager::get(); - - _ncm = new NameComponentManager(em); - - _assetLoader = AssetLoader::create({_engine, _ubershaderProvider, _ncm, &em}); - - _gltfResourceLoader->addTextureProvider("image/ktx2", _ktxDecoder); - _gltfResourceLoader->addTextureProvider("image/png", _stbDecoder); - _gltfResourceLoader->addTextureProvider("image/jpeg", _stbDecoder); - - auto &tm = _engine->getTransformManager(); - - _collisionComponentManager = std::make_unique(tm); - - _animationManager = std::make_unique(_engine, _scene); - - _unlitFixedSizeMaterial = - Material::Builder() - .package(UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_DATA, UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE) - .build(*_engine); - - _gizmoMaterial = - Material::Builder() - .package(GIZMO_GIZMO_DATA, GIZMO_GIZMO_SIZE) - .build(*_engine); - } - - SceneManager::~SceneManager() - { - TRACE("Destroying cameras"); - for (auto camera : _cameras) - { - auto entity = camera->getEntity(); - _engine->destroyCameraComponent(entity); - _engine->getEntityManager().destroy(entity); - } - TRACE("Cameras destroyed"); - - destroyAll(); - TRACE("Destroyed all assets"); - - _engine->destroy(_unlitFixedSizeMaterial); - _engine->destroy(_gizmoMaterial); - TRACE("Destroyed materials"); - _cameras.clear(); - - _grid = nullptr; - - _gltfResourceLoader->asyncCancelLoad(); - _ubershaderProvider->destroyMaterials(); - - _animationManager = std::nullptr_t(); - _collisionComponentManager = std::nullptr_t(); - delete _ncm; - - delete _gltfResourceLoader; - delete _stbDecoder; - delete _ktxDecoder; - delete _ubershaderProvider; - TRACE("Destroying asset loader"); - AssetLoader::destroy(&_assetLoader); - TRACE("Destroyed asset loader"); - } - - SceneAsset *SceneManager::createGrid(Material *material) - { - if (!_grid) - { - if (!material) - { - material = Material::Builder() - .package(GRID_PACKAGE, GRID_GRID_SIZE) - .build(*_engine); - } - - _grid = std::make_unique(*_engine, material); - } - return _grid.get(); - } - - bool SceneManager::isGridEntity(utils::Entity entity) - { - if (!_grid) - { - TRACE("No grid"); - return false; - } - if (entity == _grid->getEntity()) - { - TRACE("%d is a grid entity.", entity); - return true; - } - for (int i = 0; i < _grid->getChildEntityCount(); i++) - { - if (entity == _grid->getChildEntities()[i]) - { - TRACE("%d is a child entity of grid.", entity); - return true; - } - } - return false; - } - - Gizmo *SceneManager::createGizmo(View *view, Scene *scene, GizmoType type) - { - TRACE("Creating gizmo type %d", type); - Gizmo *raw; - switch (type) - { - case GizmoType::TRANSLATION: - if (!_translationGizmoGlb) - { - TRACE("Translation gizmo source not found, loading"); - _translationGizmoGlb = loadGlbFromBuffer(TRANSLATION_GIZMO_GLB_TRANSLATION_GIZMO_DATA, TRANSLATION_GIZMO_GLB_TRANSLATION_GIZMO_SIZE, 100, true, 4, 0, false, false); - } - raw = new Gizmo(_translationGizmoGlb, _engine, view, scene, _unlitFixedSizeMaterial); - TRACE("Built translation gizmo"); - break; - case GizmoType::ROTATION: - if (!_rotationGizmoGlb) - { - TRACE("Rotation gizmo source not found, loading"); - _rotationGizmoGlb = loadGlbFromBuffer(ROTATION_GIZMO_GLB_ROTATION_GIZMO_DATA, ROTATION_GIZMO_GLB_ROTATION_GIZMO_SIZE, 100, true, 4, 0, false, false); - } - raw = new Gizmo(_rotationGizmoGlb, _engine, view, scene, _unlitFixedSizeMaterial); - TRACE("Built rotation gizmo"); - break; - } - - _sceneAssets.push_back(std::unique_ptr(raw)); - return raw; - } - - int SceneManager::getInstanceCount(EntityId entityId) - { - auto entity = utils::Entity::import(entityId); - for (auto &asset : _sceneAssets) - { - if (asset->getEntity() == entity) - { - return asset->getInstanceCount(); - } - } - return -1; - } - - void SceneManager::getInstances(EntityId entityId, EntityId *out) - { - auto entity = utils::Entity::import(entityId); - for (auto &asset : _sceneAssets) - { - if (asset->getEntity() == entity) - { - for (int i = 0; i < asset->getInstanceCount(); i++) - { - out[i] = Entity::smuggle(asset->getInstanceAt(i)->getEntity()); - } - return; - } - } - } - - SceneAsset *SceneManager::loadGltf(const char *uri, - const char *relativeResourcePath, - int numInstances, - bool keepData) - { - if (numInstances < 1) - { - return std::nullptr_t(); - } - - ResourceBuffer rbuf = _resourceLoaderWrapper->load(uri); - - std::vector instances(numInstances); - - FilamentAsset *asset = _assetLoader->createInstancedAsset((uint8_t *)rbuf.data, rbuf.size, instances.data(), numInstances); - - if (!asset) - { - Log("Unable to load glTF asset at %d", uri); - return std::nullptr_t(); - } - - const char *const *const resourceUris = asset->getResourceUris(); - const size_t resourceUriCount = asset->getResourceUriCount(); - - std::vector resourceBuffers; - - for (size_t i = 0; i < resourceUriCount; i++) - { - std::string uri = std::string(relativeResourcePath) + std::string("/") + std::string(resourceUris[i]); - ResourceBuffer buf = _resourceLoaderWrapper->load(uri.c_str()); - - resourceBuffers.push_back(buf); - - ResourceLoader::BufferDescriptor b(buf.data, buf.size); - _gltfResourceLoader->addResourceData(resourceUris[i], std::move(b)); - } - -#ifdef __EMSCRIPTEN__ - if (!_gltfResourceLoader->asyncBeginLoad(asset)) - { - Log("Unknown error loading glTF asset"); - _resourceLoaderWrapper->free(rbuf); - for (auto &rb : resourceBuffers) - { - _resourceLoaderWrapper->free(rb); - } - return 0; - } - while (_gltfResourceLoader->asyncGetLoadProgress() < 1.0f) - { - _gltfResourceLoader->asyncUpdateLoad(); - } -#else - // load resources synchronously - if (!_gltfResourceLoader->loadResources(asset)) - { - Log("Unknown error loading glTF asset"); - _resourceLoaderWrapper->free(rbuf); - for (auto &rb : resourceBuffers) - { - _resourceLoaderWrapper->free(rb); - } - return std::nullptr_t(); - } -#endif - - auto sceneAsset = std::make_unique( - asset, - _assetLoader, - _engine, - _ncm); - auto filamentInstance = asset->getInstance(); - size_t entityCount = filamentInstance->getEntityCount(); - - _scene->addEntities(filamentInstance->getEntities(), entityCount); - - for (auto &rb : resourceBuffers) - { - _resourceLoaderWrapper->free(rb); - } - _resourceLoaderWrapper->free(rbuf); - - auto lights = asset->getLightEntities(); - _scene->addEntities(lights, asset->getLightEntityCount()); - - sceneAsset->createInstance(); - - auto entityId = Entity::smuggle(sceneAsset->getEntity()); - - auto *raw = sceneAsset.get(); - - _sceneAssets.push_back(std::move(sceneAsset)); - - Log("Loaded glTF asset from uri: %s", uri); - - return raw; - } - - void SceneManager::setVisibilityLayer(EntityId entityId, int layer) - { - utils::Entity entity = utils::Entity::import(entityId); - for (auto &asset : _sceneAssets) - { - if (asset->getEntity() == entity) - { - asset->setLayer(_engine->getRenderableManager(), layer); - } - } - } - - SceneAsset *SceneManager::loadGlbFromBuffer(const uint8_t *data, size_t length, int numInstances, bool keepData, int priority, int layer, bool loadResourcesAsync, bool addToScene) - { - auto &rm = _engine->getRenderableManager(); - - std::vector instances(numInstances); - - FilamentAsset *asset = _assetLoader->createInstancedAsset((const uint8_t *)data, length, instances.data(), numInstances); - - Log("Created glTF asset with %d instances.", numInstances); - - if (!asset) - { - Log("Unknown error loading GLB asset."); - return std::nullptr_t(); - } -#ifdef __EMSCRIPTEN__ - if (!_gltfResourceLoader->asyncBeginLoad(asset)) - { - Log("Unknown error loading glb asset"); - return 0; - } - while (_gltfResourceLoader->asyncGetLoadProgress() < 1.0f) - { - _gltfResourceLoader->asyncUpdateLoad(); - } -#else - if (loadResourcesAsync) - { - if (!_gltfResourceLoader->asyncBeginLoad(asset)) - { - Log("Unknown error loading glb asset"); - return 0; - } - } - else - { - if (!_gltfResourceLoader->loadResources(asset)) - { - Log("Unknown error loading glb asset"); - return 0; - } - } -#endif - - auto sceneAsset = std::make_unique( - asset, - _assetLoader, - _engine, - _ncm); - - auto sceneAssetInstance = sceneAsset->createInstance(); - if (addToScene) - { - sceneAssetInstance->addAllEntities(_scene); - } - sceneAssetInstance->setPriority(_engine->getRenderableManager(), priority); - sceneAssetInstance->setLayer(_engine->getRenderableManager(), layer); - - auto *raw = sceneAsset.get(); - - _sceneAssets.push_back(std::move(sceneAsset)); - - return raw; - } - - SceneAsset *SceneManager::createInstance(SceneAsset *asset, MaterialInstance **materialInstances, size_t materialInstanceCount) - { - std::lock_guard lock(_mutex); - - auto instance = asset->createInstance(materialInstances, materialInstanceCount); - if (instance) - { - instance->addAllEntities(_scene); - } - else - { - Log("Failed to create instance"); - } - return instance; - } - - SceneAsset *SceneManager::loadGlb(const char *uri, int numInstances, bool keepData) - { - ResourceBuffer rbuf = _resourceLoaderWrapper->load(uri); - auto entity = loadGlbFromBuffer((const uint8_t *)rbuf.data, rbuf.size, numInstances, keepData); - _resourceLoaderWrapper->free(rbuf); - return entity; - } - - bool SceneManager::removeFromScene(EntityId entityId) - { - _scene->remove(Entity::import(entityId)); - return true; - } - - bool SceneManager::addToScene(EntityId entityId) - { - _scene->addEntity(Entity::import(entityId)); - return true; - } - - void SceneManager::destroyAll() - { - - destroyLights(); - destroyAssets(); - std::lock_guard lock(_mutex); - - for (auto *materialInstance : _materialInstances) - { - _engine->destroy(materialInstance); - } - _materialInstances.clear(); - } - - void SceneManager::destroy(SceneAsset *asset) - { - - std::lock_guard lock(_mutex); - - auto entity = asset->getEntity(); - _collisionComponentManager->removeComponent(entity); - _animationManager->removeAnimationComponent(utils::Entity::smuggle(entity)); - for (int i = 0; i < asset->getChildEntityCount(); i++) - { - auto childEntity = asset->getChildEntities()[i]; - _collisionComponentManager->removeComponent(childEntity); - _animationManager->removeAnimationComponent(utils::Entity::smuggle(childEntity)); - } - asset->removeAllEntities(_scene); - if (asset->isInstance()) - { - asset->destroyInstance(asset); - } - else - { - auto it = std::remove_if(_sceneAssets.begin(), _sceneAssets.end(), [=](auto &sceneAsset) - { return sceneAsset.get() == asset; }); - _sceneAssets.erase(it, _sceneAssets.end()); - } - } - - 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(); - - // LightManager::ShadowOptions shadowOptions; - // shadowOptions.stable = true; - - 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)) - // .shadowOptions(shadowOptions) - .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(); - } - - - void SceneManager::addCollisionComponent(EntityId entityId, void (*onCollisionCallback)(const EntityId entityId1, const EntityId entityId2), bool affectsTransform) - { - std::lock_guard lock(_mutex); - utils::Entity entity = utils::Entity::import(entityId); - for (auto &asset : _sceneAssets) - { - auto *instance = reinterpret_cast(asset->getInstanceByEntity(entity)); - if (instance) - { - auto collisionInstance = _collisionComponentManager->addComponent(instance->getInstance()->getRoot()); - _collisionComponentManager->elementAt<0>(collisionInstance) = instance->getInstance()->getBoundingBox(); - _collisionComponentManager->elementAt<1>(collisionInstance) = onCollisionCallback; - _collisionComponentManager->elementAt<2>(collisionInstance) = affectsTransform; - return; - } - } - } - - void SceneManager::removeCollisionComponent(EntityId entityId) - { - std::lock_guard lock(_mutex); - utils::Entity entity = utils::Entity::import(entityId); - _collisionComponentManager->removeComponent(entity); - } - - void SceneManager::testCollisions(EntityId entityId) - { - utils::Entity entity = utils::Entity::import(entityId); - for (auto &asset : _sceneAssets) - { - auto *instance = reinterpret_cast(asset->getInstanceByEntity(entity)); - if (instance) - { - const auto &tm = _engine->getTransformManager(); - auto transformInstance = tm.getInstance(entity); - auto worldTransform = tm.getWorldTransform(transformInstance); - auto aabb = instance->getInstance()->getBoundingBox(); - aabb = aabb.transform(worldTransform); - _collisionComponentManager->collides(entity, aabb); - } - } - } - - void SceneManager::update() - { - _animationManager->update(); - _updateTransforms(); - } - - void SceneManager::_updateTransforms() - { - std::lock_guard lock(_mutex); - - // auto &tm = _engine->getTransformManager(); - // tm.openLocalTransformTransaction(); - - // for (const auto &[entityId, transformUpdate] : _transformUpdates) - // { - // const auto &pos = _instances.find(entityId); - - // bool isCollidable = true; - // Entity entity; - // filament::TransformManager::Instance transformInstance; - // filament::math::mat4f transform; - // Aabb boundingBox; - // if (pos == _instances.end()) - // { - // isCollidable = false; - // entity = Entity::import(entityId); - // } - // else - // { - // const auto *instance = pos->second; - // entity = instance->getRoot(); - // boundingBox = instance->getBoundingBox(); - // } - - // transformInstance = tm.getInstance(entity); - // transform = tm.getTransform(transformInstance); - - // if (isCollidable) - // { - // auto transformedBB = boundingBox.transform(transform); - - // auto collisionAxes = _collisionComponentManager->collides(entity, transformedBB); - - // if (collisionAxes.size() == 1) - // { - // // auto globalAxis = collisionAxes[0]; - // // globalAxis *= norm(relativeTranslation); - // // auto newRelativeTranslation = relativeTranslation + globalAxis; - // // translation -= relativeTranslation; - // // translation += newRelativeTranslation; - // // transform = composeMatrix(translation, rotation, scale); - // } - // else if (collisionAxes.size() > 1) - // { - // // translation -= relativeTranslation; - // // transform = composeMatrix(translation, rotation, scale); - // } - // } - // tm.setTransform(transformInstance, transformUpdate); - // } - // tm.commitLocalTransformTransaction(); - // _transformUpdates.clear(); - } - - void SceneManager::queueRelativePositionUpdateFromViewportVector(View *view, EntityId entityId, float viewportCoordX, float viewportCoordY) - { - // Get the camera and viewport - const auto &camera = view->getCamera(); - const auto &vp = view->getViewport(); - - // Convert viewport coordinates to NDC space - float ndcX = (2.0f * viewportCoordX) / vp.width - 1.0f; - float ndcY = 1.0f - (2.0f * viewportCoordY) / vp.height; - - // Get the current position of the entity - auto &tm = _engine->getTransformManager(); - auto entity = Entity::import(entityId); - auto transformInstance = tm.getInstance(entity); - auto currentTransform = tm.getTransform(transformInstance); - - // get entity model origin in camera space - auto entityPositionInCameraSpace = camera.getViewMatrix() * currentTransform * filament::math::float4{0.0f, 0.0f, 0.0f, 1.0f}; - // get entity model origin in clip space - auto entityPositionInClipSpace = camera.getProjectionMatrix() * entityPositionInCameraSpace; - auto entityPositionInNdcSpace = entityPositionInClipSpace / entityPositionInClipSpace.w; - - // Viewport coords in NDC space (use entity position in camera space Z to project onto near plane) - math::float4 ndcNearPlanePos = {ndcX, ndcY, -1.0f, 1.0f}; - math::float4 ndcFarPlanePos = {ndcX, ndcY, 0.99f, 1.0f}; - math::float4 ndcEntityPlanePos = {ndcX, ndcY, entityPositionInNdcSpace.z, 1.0f}; - - // Get viewport coords in clip space - math::float4 nearPlaneInClipSpace = Camera::inverseProjection(camera.getProjectionMatrix()) * ndcNearPlanePos; - auto nearPlaneInCameraSpace = nearPlaneInClipSpace / nearPlaneInClipSpace.w; - math::float4 farPlaneInClipSpace = Camera::inverseProjection(camera.getProjectionMatrix()) * ndcFarPlanePos; - auto farPlaneInCameraSpace = farPlaneInClipSpace / farPlaneInClipSpace.w; - math::float4 entityPlaneInClipSpace = Camera::inverseProjection(camera.getProjectionMatrix()) * ndcEntityPlanePos; - auto entityPlaneInCameraSpace = entityPlaneInClipSpace / entityPlaneInClipSpace.w; - auto entityPlaneInWorldSpace = camera.getModelMatrix() * entityPlaneInCameraSpace; - } - - void SceneManager::queueTransformUpdates(EntityId *entities, math::mat4 *transforms, int numEntities) - { - std::lock_guard lock(_mutex); - - for (int i = 0; i < numEntities; i++) - { - auto entity = entities[i]; - const auto &pos = _transformUpdates.find(entity); - if (pos == _transformUpdates.end()) - { - _transformUpdates.emplace(entity, transforms[i]); - } - auto curr = _transformUpdates[entity]; - _transformUpdates[entity] = curr; - } - } - - Aabb3 SceneManager::getRenderableBoundingBox(EntityId entityId) - { - auto &rm = _engine->getRenderableManager(); - auto instance = rm.getInstance(Entity::import(entityId)); - if (!instance.isValid()) - { - return Aabb3{}; - } - auto box = rm.getAxisAlignedBoundingBox(instance); - return Aabb3{box.center.x, box.center.y, box.center.z, box.halfExtent.x, box.halfExtent.y, box.halfExtent.z}; - } - - Aabb2 SceneManager::getScreenSpaceBoundingBox(View *view, EntityId entityId) - { - const auto &camera = view->getCamera(); - const auto &viewport = view->getViewport(); - - auto &tcm = _engine->getTransformManager(); - auto &rcm = _engine->getRenderableManager(); - - // Get the projection and view matrices - math::mat4 projMatrix = camera.getProjectionMatrix(); - math::mat4 viewMatrix = camera.getViewMatrix(); - math::mat4 vpMatrix = projMatrix * viewMatrix; - - auto entity = Entity::import(entityId); - - auto renderable = rcm.getInstance(entity); - auto worldTransform = tcm.getWorldTransform(tcm.getInstance(entity)); - - // Get the axis-aligned bounding box in model space - Box aabb = rcm.getAxisAlignedBoundingBox(renderable); - - auto min = aabb.getMin(); - auto max = aabb.getMax(); - - // Transform the 8 corners of the AABB to clip space - std::array corners = { - worldTransform * math::float4(min.x, min.y, min.z, 1.0f), - worldTransform * math::float4(max.x, min.y, min.z, 1.0f), - worldTransform * math::float4(min.x, max.y, min.z, 1.0f), - worldTransform * math::float4(max.x, max.y, min.z, 1.0f), - worldTransform * math::float4(min.x, min.y, max.z, 1.0f), - worldTransform * math::float4(max.x, min.y, max.z, 1.0f), - worldTransform * math::float4(min.x, max.y, max.z, 1.0f), - worldTransform * math::float4(max.x, max.y, max.z, 1.0f)}; - - // Project corners to clip space and convert to viewport space - float minX = std::numeric_limits::max(); - float minY = std::numeric_limits::max(); - float maxX = std::numeric_limits::lowest(); - float maxY = std::numeric_limits::lowest(); - - for (const auto &corner : corners) - { - - math::float4 clipSpace = vpMatrix * corner; - - // Check if the point is behind the camera - if (clipSpace.w <= 0) - { - continue; // Skip this point - } - - // Perform perspective division - math::float3 ndcSpace = clipSpace.xyz / clipSpace.w; - - // Clamp NDC coordinates to [-1, 1] range - ndcSpace.x = std::max(-1.0f, std::min(1.0f, ndcSpace.x)); - ndcSpace.y = std::max(-1.0f, std::min(1.0f, ndcSpace.y)); - - // Convert NDC to viewport space - float viewportX = (ndcSpace.x * 0.5f + 0.5f) * viewport.width; - float viewportY = (1.0f - (ndcSpace.y * 0.5f + 0.5f)) * viewport.height; // Flip Y-axis - - minX = std::min(minX, viewportX); - minY = std::min(minY, viewportY); - maxX = std::max(maxX, viewportX); - maxY = std::max(maxY, viewportY); - } - - return Aabb2{minX, minY, maxX, maxY}; - } - - static filament::gltfio::MaterialKey getDefaultUnlitMaterialConfig(int numUvs) - { - filament::gltfio::MaterialKey config; - memset(&config, 0, sizeof(config)); - - config.unlit = false; - config.doubleSided = false; - config.useSpecularGlossiness = false; - config.alphaMode = filament::gltfio::AlphaMode::OPAQUE; - config.hasBaseColorTexture = numUvs > 0; - config.baseColorUV = 0; - config.hasVertexColors = false; - - return config; - } - - SceneAsset *SceneManager::createGeometry( - float *vertices, - uint32_t numVertices, - float *normals, - uint32_t numNormals, - float *uvs, - uint32_t numUvs, - uint16_t *indices, - uint32_t numIndices, - filament::RenderableManager::PrimitiveType primitiveType, - filament::MaterialInstance **materialInstances, - size_t materialInstanceCount, - bool keepData) - { - utils::Entity entity; - - auto builder = GeometrySceneAssetBuilder(_engine) - .vertices(vertices, numVertices) - .indices(indices, numIndices) - .primitiveType(primitiveType); - - if (normals) - { - builder.normals(normals, numNormals); - } - - if (uvs) - { - builder.uvs(uvs, numUvs); - } - - builder.materials(materialInstances, materialInstanceCount); - - auto sceneAsset = builder.build(); - - if (!sceneAsset) - { - Log("Failed to create geometry"); - return std::nullptr_t(); - } - - sceneAsset->addAllEntities(_scene); - auto *raw = sceneAsset.get(); - _sceneAssets.push_back(std::move(sceneAsset)); - return raw; - } - - void SceneManager::destroy(filament::MaterialInstance *instance) - { - auto it = std::find(_materialInstances.begin(), _materialInstances.end(), instance); - if (it != _materialInstances.end()) - { - _materialInstances.erase(it); - } - _engine->destroy(instance); - } - - MaterialInstance *SceneManager::createUnlitFixedSizeMaterialInstance() - { - auto instance = _unlitFixedSizeMaterial->createInstance(); - instance->setParameter("scale", 1.0f); - return instance; - } - - MaterialInstance *SceneManager::createUnlitMaterialInstance() - { - UvMap uvmap; - auto instance = _unlitMaterialProvider->createMaterialInstance(nullptr, &uvmap); - instance->setParameter("baseColorFactor", filament::math::float4{1.0f, 1.0f, 1.0f, 1.0f}); - instance->setParameter("baseColorIndex", -1); - instance->setParameter("uvScale", filament::math::float2{1.0f, 1.0f}); - _materialInstances.push_back(instance); - return instance; - } - - Camera *SceneManager::createCamera() - { - auto entity = EntityManager::get().create(); - auto camera = _engine->createCamera(entity); - _cameras.push_back(camera); - return camera; - } - - void SceneManager::destroyCamera(Camera *camera) - { - auto entity = camera->getEntity(); - _engine->destroyCameraComponent(entity); - _engine->getEntityManager().destroy(entity); - auto it = std::find(_cameras.begin(), _cameras.end(), camera); - if (it != _cameras.end()) - { - _cameras.erase(it); - } - } - - size_t SceneManager::getCameraCount() - { - return _cameras.size() + 1; - } - - Camera *SceneManager::getCameraAt(size_t index) - { - if (index == 0) - { - return _mainCamera; - } - if (index - 1 > _cameras.size() - 1) - { - return nullptr; - } - return _cameras[index - 1]; - } - - -} // namespace thermion +// #include +// #include +// #include +// #include +// #include +// #include +// #include + +// #include +// #include +// #include +// #include +// #include +// #include + +// #include + +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include + +// #include "material/FileMaterialProvider.hpp" +// #include "material/UnlitMaterialProvider.hpp" +// #include "material/unlit.h" +// #include "material/gizmo.h" + +// #include "StreamBufferAdapter.hpp" + +// #include "Log.hpp" + +// #include "scene/SceneManager.hpp" +// #include "scene/CustomGeometry.hpp" +// #include "scene/GeometrySceneAsset.hpp" +// #include "scene/GltfSceneAsset.hpp" +// #include "scene/Gizmo.hpp" +// #include "scene/SceneAsset.hpp" +// #include "scene/GeometrySceneAssetBuilder.hpp" +// #include "TextureProjection.hpp" + +// #include "resources/translation_gizmo_glb.h" +// #include "resources/rotation_gizmo_glb.h" + +// extern "C" +// { +// #include "material/image.h" +// #include "material/unlit_fixed_size.h" +// } + +// namespace thermion +// { + +// using namespace std::chrono; +// using namespace image; +// using namespace utils; +// using namespace filament; +// using namespace filament::gltfio; +// using std::unique_ptr; + +// SceneManager::SceneManager(const ResourceLoaderWrapperImpl *const resourceLoaderWrapper, +// Engine *engine, +// Scene *scene, +// const char *uberArchivePath, +// Camera *mainCamera) +// : _resourceLoaderWrapper(resourceLoaderWrapper), +// _engine(engine), +// _scene(scene), +// _mainCamera(mainCamera) +// { + +// _stbDecoder = createStbProvider(_engine); +// _ktxDecoder = createKtx2Provider(_engine); + +// _gltfResourceLoader = new ResourceLoader({.engine = _engine, +// .normalizeSkinningWeights = true}); +// if (uberArchivePath) +// { +// auto uberdata = resourceLoaderWrapper->load(uberArchivePath); +// if (!uberdata.data) +// { +// Log("Failed to load ubershader material. This is fatal."); +// } +// _ubershaderProvider = gltfio::createUbershaderProvider(_engine, uberdata.data, uberdata.size); +// resourceLoaderWrapper->free(uberdata); +// } +// else +// { +// _ubershaderProvider = gltfio::createUbershaderProvider( +// _engine, UBERARCHIVE_DEFAULT_DATA, UBERARCHIVE_DEFAULT_SIZE); +// } + +// _unlitMaterialProvider = new UnlitMaterialProvider(_engine, UNLIT_PACKAGE, UNLIT_UNLIT_SIZE); + +// utils::EntityManager &em = utils::EntityManager::get(); + +// _ncm = new NameComponentManager(em); + +// _assetLoader = AssetLoader::create({_engine, _ubershaderProvider, _ncm, &em}); + +// _gltfResourceLoader->addTextureProvider("image/ktx2", _ktxDecoder); +// _gltfResourceLoader->addTextureProvider("image/png", _stbDecoder); +// _gltfResourceLoader->addTextureProvider("image/jpeg", _stbDecoder); + +// auto &tm = _engine->getTransformManager(); + +// _collisionComponentManager = std::make_unique(tm); + +// _animationManager = std::make_unique(_engine, _scene); + +// _unlitFixedSizeMaterial = +// Material::Builder() +// .package(UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_DATA, UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE) +// .build(*_engine); + +// _gizmoMaterial = +// Material::Builder() +// .package(GIZMO_GIZMO_DATA, GIZMO_GIZMO_SIZE) +// .build(*_engine); +// } + +// SceneManager::~SceneManager() +// { +// TRACE("Destroying cameras"); +// for (auto camera : _cameras) +// { +// auto entity = camera->getEntity(); +// _engine->destroyCameraComponent(entity); +// _engine->getEntityManager().destroy(entity); +// } +// TRACE("Cameras destroyed"); + +// destroyAll(); +// TRACE("Destroyed all assets"); + +// _engine->destroy(_unlitFixedSizeMaterial); +// _engine->destroy(_gizmoMaterial); +// TRACE("Destroyed materials"); +// _cameras.clear(); + +// _grid = nullptr; + +// _gltfResourceLoader->asyncCancelLoad(); +// _ubershaderProvider->destroyMaterials(); + +// _animationManager = std::nullptr_t(); +// _collisionComponentManager = std::nullptr_t(); +// delete _ncm; + +// delete _gltfResourceLoader; +// delete _stbDecoder; +// delete _ktxDecoder; +// delete _ubershaderProvider; +// TRACE("Destroying asset loader"); +// AssetLoader::destroy(&_assetLoader); +// TRACE("Destroyed asset loader"); +// } + +// SceneAsset *SceneManager::createGrid(Material *material) +// { +// if (!_grid) +// { +// if (!material) +// { +// material = Material::Builder() +// .package(GRID_PACKAGE, GRID_GRID_SIZE) +// .build(*_engine); +// } + +// _grid = std::make_unique(*_engine, material); +// } +// return _grid.get(); +// } + +// bool SceneManager::isGridEntity(utils::Entity entity) +// { +// if (!_grid) +// { +// TRACE("No grid"); +// return false; +// } +// if (entity == _grid->getEntity()) +// { +// TRACE("%d is a grid entity.", entity); +// return true; +// } +// for (int i = 0; i < _grid->getChildEntityCount(); i++) +// { +// if (entity == _grid->getChildEntities()[i]) +// { +// TRACE("%d is a child entity of grid.", entity); +// return true; +// } +// } +// return false; +// } + +// Gizmo *SceneManager::createGizmo(View *view, Scene *scene, GizmoType type) +// { +// TRACE("Creating gizmo type %d", type); +// Gizmo *raw; +// switch (type) +// { +// case GizmoType::TRANSLATION: +// if (!_translationGizmoGlb) +// { +// TRACE("Translation gizmo source not found, loading"); +// _translationGizmoGlb = loadGlbFromBuffer(TRANSLATION_GIZMO_GLB_TRANSLATION_GIZMO_DATA, TRANSLATION_GIZMO_GLB_TRANSLATION_GIZMO_SIZE, 100, true, 4, 0, false, false); +// } +// raw = new Gizmo(_translationGizmoGlb, _engine, view, scene, _unlitFixedSizeMaterial); +// TRACE("Built translation gizmo"); +// break; +// case GizmoType::ROTATION: +// if (!_rotationGizmoGlb) +// { +// TRACE("Rotation gizmo source not found, loading"); +// _rotationGizmoGlb = loadGlbFromBuffer(ROTATION_GIZMO_GLB_ROTATION_GIZMO_DATA, ROTATION_GIZMO_GLB_ROTATION_GIZMO_SIZE, 100, true, 4, 0, false, false); +// } +// raw = new Gizmo(_rotationGizmoGlb, _engine, view, scene, _unlitFixedSizeMaterial); +// TRACE("Built rotation gizmo"); +// break; +// } + +// _sceneAssets.push_back(std::unique_ptr(raw)); +// return raw; +// } + +// int SceneManager::getInstanceCount(EntityId entityId) +// { +// auto entity = utils::Entity::import(entityId); +// for (auto &asset : _sceneAssets) +// { +// if (asset->getEntity() == entity) +// { +// return asset->getInstanceCount(); +// } +// } +// return -1; +// } + +// void SceneManager::getInstances(EntityId entityId, EntityId *out) +// { +// auto entity = utils::Entity::import(entityId); +// for (auto &asset : _sceneAssets) +// { +// if (asset->getEntity() == entity) +// { +// for (int i = 0; i < asset->getInstanceCount(); i++) +// { +// out[i] = Entity::smuggle(asset->getInstanceAt(i)->getEntity()); +// } +// return; +// } +// } +// } + +// SceneAsset *SceneManager::loadGltf(const char *uri, +// const char *relativeResourcePath, +// int numInstances, +// bool keepData) +// { +// if (numInstances < 1) +// { +// return std::nullptr_t(); +// } + +// ResourceBuffer rbuf = _resourceLoaderWrapper->load(uri); + +// std::vector instances(numInstances); + +// FilamentAsset *asset = _assetLoader->createInstancedAsset((uint8_t *)rbuf.data, rbuf.size, instances.data(), numInstances); + +// if (!asset) +// { +// Log("Unable to load glTF asset at %d", uri); +// return std::nullptr_t(); +// } + +// const char *const *const resourceUris = asset->getResourceUris(); +// const size_t resourceUriCount = asset->getResourceUriCount(); + +// std::vector resourceBuffers; + +// for (size_t i = 0; i < resourceUriCount; i++) +// { +// std::string uri = std::string(relativeResourcePath) + std::string("/") + std::string(resourceUris[i]); +// ResourceBuffer buf = _resourceLoaderWrapper->load(uri.c_str()); + +// resourceBuffers.push_back(buf); + +// ResourceLoader::BufferDescriptor b(buf.data, buf.size); +// _gltfResourceLoader->addResourceData(resourceUris[i], std::move(b)); +// } + +// #ifdef __EMSCRIPTEN__ +// if (!_gltfResourceLoader->asyncBeginLoad(asset)) +// { +// Log("Unknown error loading glTF asset"); +// _resourceLoaderWrapper->free(rbuf); +// for (auto &rb : resourceBuffers) +// { +// _resourceLoaderWrapper->free(rb); +// } +// return 0; +// } +// while (_gltfResourceLoader->asyncGetLoadProgress() < 1.0f) +// { +// _gltfResourceLoader->asyncUpdateLoad(); +// } +// #else +// // load resources synchronously +// if (!_gltfResourceLoader->loadResources(asset)) +// { +// Log("Unknown error loading glTF asset"); +// _resourceLoaderWrapper->free(rbuf); +// for (auto &rb : resourceBuffers) +// { +// _resourceLoaderWrapper->free(rb); +// } +// return std::nullptr_t(); +// } +// #endif + +// auto sceneAsset = std::make_unique( +// asset, +// _assetLoader, +// _engine, +// _ncm); +// auto filamentInstance = asset->getInstance(); +// size_t entityCount = filamentInstance->getEntityCount(); + +// _scene->addEntities(filamentInstance->getEntities(), entityCount); + +// for (auto &rb : resourceBuffers) +// { +// _resourceLoaderWrapper->free(rb); +// } +// _resourceLoaderWrapper->free(rbuf); + +// auto lights = asset->getLightEntities(); +// _scene->addEntities(lights, asset->getLightEntityCount()); + +// sceneAsset->createInstance(); + +// auto entityId = Entity::smuggle(sceneAsset->getEntity()); + +// auto *raw = sceneAsset.get(); + +// _sceneAssets.push_back(std::move(sceneAsset)); + +// Log("Loaded glTF asset from uri: %s", uri); + +// return raw; +// } + +// void SceneManager::setVisibilityLayer(EntityId entityId, int layer) +// { +// utils::Entity entity = utils::Entity::import(entityId); +// for (auto &asset : _sceneAssets) +// { +// if (asset->getEntity() == entity) +// { +// asset->setLayer(_engine->getRenderableManager(), layer); +// } +// } +// } + +// SceneAsset *SceneManager::loadGlbFromBuffer(const uint8_t *data, size_t length, int numInstances, bool keepData, int priority, int layer, bool loadResourcesAsync, bool addToScene) +// { +// auto &rm = _engine->getRenderableManager(); + +// std::vector instances(numInstances); + +// FilamentAsset *asset = _assetLoader->createInstancedAsset((const uint8_t *)data, length, instances.data(), numInstances); + +// Log("Created glTF asset with %d instances.", numInstances); + +// if (!asset) +// { +// Log("Unknown error loading GLB asset."); +// return std::nullptr_t(); +// } +// #ifdef __EMSCRIPTEN__ +// if (!_gltfResourceLoader->asyncBeginLoad(asset)) +// { +// Log("Unknown error loading glb asset"); +// return 0; +// } +// while (_gltfResourceLoader->asyncGetLoadProgress() < 1.0f) +// { +// _gltfResourceLoader->asyncUpdateLoad(); +// } +// #else +// if (loadResourcesAsync) +// { +// if (!_gltfResourceLoader->asyncBeginLoad(asset)) +// { +// Log("Unknown error loading glb asset"); +// return 0; +// } +// } +// else +// { +// if (!_gltfResourceLoader->loadResources(asset)) +// { +// Log("Unknown error loading glb asset"); +// return 0; +// } +// } +// #endif + +// auto sceneAsset = std::make_unique( +// asset, +// _assetLoader, +// _engine, +// _ncm); + +// auto sceneAssetInstance = sceneAsset->createInstance(); +// if (addToScene) +// { +// sceneAssetInstance->addAllEntities(_scene); +// } +// sceneAssetInstance->setPriority(_engine->getRenderableManager(), priority); +// sceneAssetInstance->setLayer(_engine->getRenderableManager(), layer); + +// auto *raw = sceneAsset.get(); + +// _sceneAssets.push_back(std::move(sceneAsset)); + +// return raw; +// } + +// SceneAsset *SceneManager::createInstance(SceneAsset *asset, MaterialInstance **materialInstances, size_t materialInstanceCount) +// { +// std::lock_guard lock(_mutex); + +// auto instance = asset->createInstance(materialInstances, materialInstanceCount); +// if (instance) +// { +// instance->addAllEntities(_scene); +// } +// else +// { +// Log("Failed to create instance"); +// } +// return instance; +// } + +// SceneAsset *SceneManager::loadGlb(const char *uri, int numInstances, bool keepData) +// { +// ResourceBuffer rbuf = _resourceLoaderWrapper->load(uri); +// auto entity = loadGlbFromBuffer((const uint8_t *)rbuf.data, rbuf.size, numInstances, keepData); +// _resourceLoaderWrapper->free(rbuf); +// return entity; +// } + +// bool SceneManager::removeFromScene(EntityId entityId) +// { +// _scene->remove(Entity::import(entityId)); +// return true; +// } + +// bool SceneManager::addToScene(EntityId entityId) +// { +// _scene->addEntity(Entity::import(entityId)); +// return true; +// } + +// void SceneManager::destroyAll() +// { + +// destroyLights(); +// destroyAssets(); +// std::lock_guard lock(_mutex); + +// for (auto *materialInstance : _materialInstances) +// { +// _engine->destroy(materialInstance); +// } +// _materialInstances.clear(); +// } + +// void SceneManager::destroy(SceneAsset *asset) +// { + +// std::lock_guard lock(_mutex); + +// auto entity = asset->getEntity(); +// _collisionComponentManager->removeComponent(entity); +// _animationManager->removeAnimationComponent(utils::Entity::smuggle(entity)); +// for (int i = 0; i < asset->getChildEntityCount(); i++) +// { +// auto childEntity = asset->getChildEntities()[i]; +// _collisionComponentManager->removeComponent(childEntity); +// _animationManager->removeAnimationComponent(utils::Entity::smuggle(childEntity)); +// } +// asset->removeAllEntities(_scene); +// if (asset->isInstance()) +// { +// asset->destroyInstance(asset); +// } +// else +// { +// auto it = std::remove_if(_sceneAssets.begin(), _sceneAssets.end(), [=](auto &sceneAsset) +// { return sceneAsset.get() == asset; }); +// _sceneAssets.erase(it, _sceneAssets.end()); +// } +// } + +// 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(); + +// // LightManager::ShadowOptions shadowOptions; +// // shadowOptions.stable = true; + +// 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)) +// // .shadowOptions(shadowOptions) +// .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(); +// } + + +// void SceneManager::addCollisionComponent(EntityId entityId, void (*onCollisionCallback)(const EntityId entityId1, const EntityId entityId2), bool affectsTransform) +// { +// std::lock_guard lock(_mutex); +// utils::Entity entity = utils::Entity::import(entityId); +// for (auto &asset : _sceneAssets) +// { +// auto *instance = reinterpret_cast(asset->getInstanceByEntity(entity)); +// if (instance) +// { +// auto collisionInstance = _collisionComponentManager->addComponent(instance->getInstance()->getRoot()); +// _collisionComponentManager->elementAt<0>(collisionInstance) = instance->getInstance()->getBoundingBox(); +// _collisionComponentManager->elementAt<1>(collisionInstance) = onCollisionCallback; +// _collisionComponentManager->elementAt<2>(collisionInstance) = affectsTransform; +// return; +// } +// } +// } + +// void SceneManager::removeCollisionComponent(EntityId entityId) +// { +// std::lock_guard lock(_mutex); +// utils::Entity entity = utils::Entity::import(entityId); +// _collisionComponentManager->removeComponent(entity); +// } + +// void SceneManager::testCollisions(EntityId entityId) +// { +// utils::Entity entity = utils::Entity::import(entityId); +// for (auto &asset : _sceneAssets) +// { +// auto *instance = reinterpret_cast(asset->getInstanceByEntity(entity)); +// if (instance) +// { +// const auto &tm = _engine->getTransformManager(); +// auto transformInstance = tm.getInstance(entity); +// auto worldTransform = tm.getWorldTransform(transformInstance); +// auto aabb = instance->getInstance()->getBoundingBox(); +// aabb = aabb.transform(worldTransform); +// _collisionComponentManager->collides(entity, aabb); +// } +// } +// } + +// void SceneManager::update() +// { +// _animationManager->update(); +// _updateTransforms(); +// } + +// void SceneManager::_updateTransforms() +// { +// std::lock_guard lock(_mutex); + +// // auto &tm = _engine->getTransformManager(); +// // tm.openLocalTransformTransaction(); + +// // for (const auto &[entityId, transformUpdate] : _transformUpdates) +// // { +// // const auto &pos = _instances.find(entityId); + +// // bool isCollidable = true; +// // Entity entity; +// // filament::TransformManager::Instance transformInstance; +// // filament::math::mat4f transform; +// // Aabb boundingBox; +// // if (pos == _instances.end()) +// // { +// // isCollidable = false; +// // entity = Entity::import(entityId); +// // } +// // else +// // { +// // const auto *instance = pos->second; +// // entity = instance->getRoot(); +// // boundingBox = instance->getBoundingBox(); +// // } + +// // transformInstance = tm.getInstance(entity); +// // transform = tm.getTransform(transformInstance); + +// // if (isCollidable) +// // { +// // auto transformedBB = boundingBox.transform(transform); + +// // auto collisionAxes = _collisionComponentManager->collides(entity, transformedBB); + +// // if (collisionAxes.size() == 1) +// // { +// // // auto globalAxis = collisionAxes[0]; +// // // globalAxis *= norm(relativeTranslation); +// // // auto newRelativeTranslation = relativeTranslation + globalAxis; +// // // translation -= relativeTranslation; +// // // translation += newRelativeTranslation; +// // // transform = composeMatrix(translation, rotation, scale); +// // } +// // else if (collisionAxes.size() > 1) +// // { +// // // translation -= relativeTranslation; +// // // transform = composeMatrix(translation, rotation, scale); +// // } +// // } +// // tm.setTransform(transformInstance, transformUpdate); +// // } +// // tm.commitLocalTransformTransaction(); +// // _transformUpdates.clear(); +// } + +// void SceneManager::queueRelativePositionUpdateFromViewportVector(View *view, EntityId entityId, float viewportCoordX, float viewportCoordY) +// { +// // Get the camera and viewport +// const auto &camera = view->getCamera(); +// const auto &vp = view->getViewport(); + +// // Convert viewport coordinates to NDC space +// float ndcX = (2.0f * viewportCoordX) / vp.width - 1.0f; +// float ndcY = 1.0f - (2.0f * viewportCoordY) / vp.height; + +// // Get the current position of the entity +// auto &tm = _engine->getTransformManager(); +// auto entity = Entity::import(entityId); +// auto transformInstance = tm.getInstance(entity); +// auto currentTransform = tm.getTransform(transformInstance); + +// // get entity model origin in camera space +// auto entityPositionInCameraSpace = camera.getViewMatrix() * currentTransform * filament::math::float4{0.0f, 0.0f, 0.0f, 1.0f}; +// // get entity model origin in clip space +// auto entityPositionInClipSpace = camera.getProjectionMatrix() * entityPositionInCameraSpace; +// auto entityPositionInNdcSpace = entityPositionInClipSpace / entityPositionInClipSpace.w; + +// // Viewport coords in NDC space (use entity position in camera space Z to project onto near plane) +// math::float4 ndcNearPlanePos = {ndcX, ndcY, -1.0f, 1.0f}; +// math::float4 ndcFarPlanePos = {ndcX, ndcY, 0.99f, 1.0f}; +// math::float4 ndcEntityPlanePos = {ndcX, ndcY, entityPositionInNdcSpace.z, 1.0f}; + +// // Get viewport coords in clip space +// math::float4 nearPlaneInClipSpace = Camera::inverseProjection(camera.getProjectionMatrix()) * ndcNearPlanePos; +// auto nearPlaneInCameraSpace = nearPlaneInClipSpace / nearPlaneInClipSpace.w; +// math::float4 farPlaneInClipSpace = Camera::inverseProjection(camera.getProjectionMatrix()) * ndcFarPlanePos; +// auto farPlaneInCameraSpace = farPlaneInClipSpace / farPlaneInClipSpace.w; +// math::float4 entityPlaneInClipSpace = Camera::inverseProjection(camera.getProjectionMatrix()) * ndcEntityPlanePos; +// auto entityPlaneInCameraSpace = entityPlaneInClipSpace / entityPlaneInClipSpace.w; +// auto entityPlaneInWorldSpace = camera.getModelMatrix() * entityPlaneInCameraSpace; +// } + +// void SceneManager::queueTransformUpdates(EntityId *entities, math::mat4 *transforms, int numEntities) +// { +// std::lock_guard lock(_mutex); + +// for (int i = 0; i < numEntities; i++) +// { +// auto entity = entities[i]; +// const auto &pos = _transformUpdates.find(entity); +// if (pos == _transformUpdates.end()) +// { +// _transformUpdates.emplace(entity, transforms[i]); +// } +// auto curr = _transformUpdates[entity]; +// _transformUpdates[entity] = curr; +// } +// } + +// Aabb3 SceneManager::getRenderableBoundingBox(EntityId entityId) +// { +// auto &rm = _engine->getRenderableManager(); +// auto instance = rm.getInstance(Entity::import(entityId)); +// if (!instance.isValid()) +// { +// return Aabb3{}; +// } +// auto box = rm.getAxisAlignedBoundingBox(instance); +// return Aabb3{box.center.x, box.center.y, box.center.z, box.halfExtent.x, box.halfExtent.y, box.halfExtent.z}; +// } + +// Aabb2 SceneManager::getScreenSpaceBoundingBox(View *view, EntityId entityId) +// { +// const auto &camera = view->getCamera(); +// const auto &viewport = view->getViewport(); + +// auto &tcm = _engine->getTransformManager(); +// auto &rcm = _engine->getRenderableManager(); + +// // Get the projection and view matrices +// math::mat4 projMatrix = camera.getProjectionMatrix(); +// math::mat4 viewMatrix = camera.getViewMatrix(); +// math::mat4 vpMatrix = projMatrix * viewMatrix; + +// auto entity = Entity::import(entityId); + +// auto renderable = rcm.getInstance(entity); +// auto worldTransform = tcm.getWorldTransform(tcm.getInstance(entity)); + +// // Get the axis-aligned bounding box in model space +// Box aabb = rcm.getAxisAlignedBoundingBox(renderable); + +// auto min = aabb.getMin(); +// auto max = aabb.getMax(); + +// // Transform the 8 corners of the AABB to clip space +// std::array corners = { +// worldTransform * math::float4(min.x, min.y, min.z, 1.0f), +// worldTransform * math::float4(max.x, min.y, min.z, 1.0f), +// worldTransform * math::float4(min.x, max.y, min.z, 1.0f), +// worldTransform * math::float4(max.x, max.y, min.z, 1.0f), +// worldTransform * math::float4(min.x, min.y, max.z, 1.0f), +// worldTransform * math::float4(max.x, min.y, max.z, 1.0f), +// worldTransform * math::float4(min.x, max.y, max.z, 1.0f), +// worldTransform * math::float4(max.x, max.y, max.z, 1.0f)}; + +// // Project corners to clip space and convert to viewport space +// float minX = std::numeric_limits::max(); +// float minY = std::numeric_limits::max(); +// float maxX = std::numeric_limits::lowest(); +// float maxY = std::numeric_limits::lowest(); + +// for (const auto &corner : corners) +// { + +// math::float4 clipSpace = vpMatrix * corner; + +// // Check if the point is behind the camera +// if (clipSpace.w <= 0) +// { +// continue; // Skip this point +// } + +// // Perform perspective division +// math::float3 ndcSpace = clipSpace.xyz / clipSpace.w; + +// // Clamp NDC coordinates to [-1, 1] range +// ndcSpace.x = std::max(-1.0f, std::min(1.0f, ndcSpace.x)); +// ndcSpace.y = std::max(-1.0f, std::min(1.0f, ndcSpace.y)); + +// // Convert NDC to viewport space +// float viewportX = (ndcSpace.x * 0.5f + 0.5f) * viewport.width; +// float viewportY = (1.0f - (ndcSpace.y * 0.5f + 0.5f)) * viewport.height; // Flip Y-axis + +// minX = std::min(minX, viewportX); +// minY = std::min(minY, viewportY); +// maxX = std::max(maxX, viewportX); +// maxY = std::max(maxY, viewportY); +// } + +// return Aabb2{minX, minY, maxX, maxY}; +// } + +// static filament::gltfio::MaterialKey getDefaultUnlitMaterialConfig(int numUvs) +// { +// filament::gltfio::MaterialKey config; +// memset(&config, 0, sizeof(config)); + +// config.unlit = false; +// config.doubleSided = false; +// config.useSpecularGlossiness = false; +// config.alphaMode = filament::gltfio::AlphaMode::OPAQUE; +// config.hasBaseColorTexture = numUvs > 0; +// config.baseColorUV = 0; +// config.hasVertexColors = false; + +// return config; +// } + +// SceneAsset *SceneManager::createGeometry( +// float *vertices, +// uint32_t numVertices, +// float *normals, +// uint32_t numNormals, +// float *uvs, +// uint32_t numUvs, +// uint16_t *indices, +// uint32_t numIndices, +// filament::RenderableManager::PrimitiveType primitiveType, +// filament::MaterialInstance **materialInstances, +// size_t materialInstanceCount, +// bool keepData) +// { +// utils::Entity entity; + +// auto builder = GeometrySceneAssetBuilder(_engine) +// .vertices(vertices, numVertices) +// .indices(indices, numIndices) +// .primitiveType(primitiveType); + +// if (normals) +// { +// builder.normals(normals, numNormals); +// } + +// if (uvs) +// { +// builder.uvs(uvs, numUvs); +// } + +// builder.materials(materialInstances, materialInstanceCount); + +// auto sceneAsset = builder.build(); + +// if (!sceneAsset) +// { +// Log("Failed to create geometry"); +// return std::nullptr_t(); +// } + +// sceneAsset->addAllEntities(_scene); +// auto *raw = sceneAsset.get(); +// _sceneAssets.push_back(std::move(sceneAsset)); +// return raw; +// } + +// void SceneManager::destroy(filament::MaterialInstance *instance) +// { +// auto it = std::find(_materialInstances.begin(), _materialInstances.end(), instance); +// if (it != _materialInstances.end()) +// { +// _materialInstances.erase(it); +// } +// _engine->destroy(instance); +// } + +// MaterialInstance *SceneManager::createUnlitFixedSizeMaterialInstance() +// { +// auto instance = _unlitFixedSizeMaterial->createInstance(); +// instance->setParameter("scale", 1.0f); +// return instance; +// } + +// MaterialInstance *SceneManager::createUnlitMaterialInstance() +// { +// UvMap uvmap; +// auto instance = _unlitMaterialProvider->createMaterialInstance(nullptr, &uvmap); +// instance->setParameter("baseColorFactor", filament::math::float4{1.0f, 1.0f, 1.0f, 1.0f}); +// instance->setParameter("baseColorIndex", -1); +// instance->setParameter("uvScale", filament::math::float2{1.0f, 1.0f}); +// _materialInstances.push_back(instance); +// return instance; +// } + +// Camera *SceneManager::createCamera() +// { +// auto entity = EntityManager::get().create(); +// auto camera = _engine->createCamera(entity); +// _cameras.push_back(camera); +// return camera; +// } + +// void SceneManager::destroyCamera(Camera *camera) +// { +// auto entity = camera->getEntity(); +// _engine->destroyCameraComponent(entity); +// _engine->getEntityManager().destroy(entity); +// auto it = std::find(_cameras.begin(), _cameras.end(), camera); +// if (it != _cameras.end()) +// { +// _cameras.erase(it); +// } +// } + +// size_t SceneManager::getCameraCount() +// { +// return _cameras.size() + 1; +// } + +// Camera *SceneManager::getCameraAt(size_t index) +// { +// if (index == 0) +// { +// return _mainCamera; +// } +// if (index - 1 > _cameras.size() - 1) +// { +// return nullptr; +// } +// return _cameras[index - 1]; +// } + + +// } // namespace thermion diff --git a/thermion_flutter/thermion_flutter/macos/Classes/ThermionTexture.swift b/thermion_flutter/thermion_flutter/macos/Classes/ThermionTexture.swift deleted file mode 100644 index 15ec0fdc..00000000 --- a/thermion_flutter/thermion_flutter/macos/Classes/ThermionTexture.swift +++ /dev/null @@ -1,201 +0,0 @@ -import Foundation -import GLKit - -@objc public class ThermionTextureSwift : NSObject { - - public var pixelBuffer: CVPixelBuffer? - - var pixelBufferAttrs = [ - kCVPixelBufferPixelFormatTypeKey: NSNumber(value: kCVPixelFormatType_32ABGR ), - kCVPixelBufferIOSurfacePropertiesKey: [:] as CFDictionary - ] as [CFString : Any] as CFDictionary - - @objc public var cvMetalTextureCache:CVMetalTextureCache? - @objc public var metalDevice:MTLDevice? - - @objc public var cvMetalTexture:CVMetalTexture? - @objc public var metalTexture:MTLTexture? - @objc public var metalTextureAddress:Int = -1 - - @objc override public init() { - - } - - @objc public init(width:Int64, height:Int64, isDepth:Bool) { - if(self.metalDevice == nil) { - self.metalDevice = MTLCreateSystemDefaultDevice()! - } - - if isDepth { - // Create a proper depth texture without IOSurface backing - let textureDescriptor = MTLTextureDescriptor.texture2DDescriptor( - pixelFormat: .depth32Float, - width: Int(width), - height: Int(height), - mipmapped: false) - textureDescriptor.usage = [.renderTarget, .shaderRead] - textureDescriptor.storageMode = .private // Best performance for GPU-only access - - metalTexture = metalDevice?.makeTexture(descriptor: textureDescriptor) - let metalTexturePtr = Unmanaged.passRetained(metalTexture!).toOpaque() - metalTextureAddress = Int(bitPattern: metalTexturePtr) - return - } - - let pixelFormat: MTLPixelFormat = isDepth ? .depth32Float : .bgra8Unorm - let cvPixelFormat = isDepth ? kCVPixelFormatType_DepthFloat32 : kCVPixelFormatType_32BGRA - - - if(CVPixelBufferCreate(kCFAllocatorDefault, Int(width), Int(height), - kCVPixelFormatType_32BGRA, pixelBufferAttrs, &pixelBuffer) != kCVReturnSuccess) { - print("Error allocating pixel buffer") - metalTextureAddress = -1; - return - } - - if self.cvMetalTextureCache == nil { - let cacheCreationResult = CVMetalTextureCacheCreate( - kCFAllocatorDefault, - nil, - self.metalDevice!, - nil, - &self.cvMetalTextureCache) - if(cacheCreationResult != kCVReturnSuccess) { - print("Error creating Metal texture cache") - metalTextureAddress = -1 - return - } - } - let cvret = CVMetalTextureCacheCreateTextureFromImage( - kCFAllocatorDefault, - self.cvMetalTextureCache!, - pixelBuffer!, nil, - MTLPixelFormat.bgra8Unorm, - Int(width), Int(height), - 0, - &cvMetalTexture) - if(cvret != kCVReturnSuccess) { - print("Error creating texture from image") - metalTextureAddress = -1 - return - } - metalTexture = CVMetalTextureGetTexture(cvMetalTexture!) - let metalTexturePtr = Unmanaged.passRetained(metalTexture!).toOpaque() - metalTextureAddress = Int(bitPattern:metalTexturePtr) - } - - @objc public func destroyTexture() { - CVMetalTextureCacheFlush(self.cvMetalTextureCache!, 0) - self.metalTexture = nil - self.cvMetalTexture = nil - self.pixelBuffer = nil - self.metalDevice = nil - self.cvMetalTextureCache = nil - } - - @objc public func fillColor() { - CVPixelBufferLockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0)) - let bufferWidth = Int(CVPixelBufferGetWidth(pixelBuffer!)) - let bufferHeight = Int(CVPixelBufferGetHeight(pixelBuffer!)) - let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer!) - - guard let baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer!) else { - return - } - - for row in 0.. NSData? { - guard let texture = self.metalTexture else { - print("Metal texture is not available") - return nil - } - - let width = texture.width - let height = texture.height - - // Check what type of texture we're dealing with - let isDepthTexture = texture.pixelFormat == .depth32Float || - texture.pixelFormat == .depth16Unorm - print("Using texture pixel format : \(texture.pixelFormat) isDepthTexture \(isDepthTexture) (depth32Float \(MTLPixelFormat.depth32Float)) (depth16Unorm \(MTLPixelFormat.depth16Unorm))") - // Determine bytes per pixel based on format - let bytesPerPixel = isDepthTexture ? - (texture.pixelFormat == .depth32Float ? 4 : 2) : 4 - let bytesPerRow = width * bytesPerPixel - let byteCount = bytesPerRow * height - - // Create a staging buffer that is CPU-accessible - guard let stagingBuffer = self.metalDevice?.makeBuffer( - length: byteCount, - options: .storageModeShared) else { - print("Failed to create staging buffer") - return nil - } - - // Create command buffer and encoder for copying - guard let cmdQueue = self.metalDevice?.makeCommandQueue(), - let cmdBuffer = cmdQueue.makeCommandBuffer(), - let blitEncoder = cmdBuffer.makeBlitCommandEncoder() else { - print("Failed to create command objects") - return nil - } - - // Copy from texture to buffer - blitEncoder.copy( - from: texture, - sourceSlice: 0, - sourceLevel: 0, - sourceOrigin: MTLOrigin(x: 0, y: 0, z: 0), - sourceSize: MTLSize(width: width, height: height, depth: 1), - to: stagingBuffer, - destinationOffset: 0, - destinationBytesPerRow: bytesPerRow, - destinationBytesPerImage: byteCount - ) - - blitEncoder.endEncoding() - cmdBuffer.commit() - cmdBuffer.waitUntilCompleted() - - // Now the data is in the staging buffer, accessible to CPU - if isDepthTexture { - // For depth textures, just return the raw data - return NSData(bytes: stagingBuffer.contents(), length: byteCount) - } else { - // For color textures, do the BGRA to RGBA swizzling - let bytes = stagingBuffer.contents().bindMemory(to: UInt8.self, capacity: byteCount) - let data = NSMutableData(bytes: bytes, length: byteCount) - - let mutableBytes = data.mutableBytes.bindMemory(to: UInt8.self, capacity: byteCount) - for i in stride(from: 0, to: byteCount, by: 4) { - let blue = mutableBytes[i] - let red = mutableBytes[i+2] - mutableBytes[i] = red - mutableBytes[i+2] = blue - } - - return data - } -} - -}