From 77fe40848b23ce57fcb04c84d115c94b76575a32 Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Tue, 18 Mar 2025 16:26:47 +0800 Subject: [PATCH] refactoring --- .../src/viewer/src/ffi/src/ffi_camera.dart | 15 +- .../viewer/src/ffi/src/ffi_filament_app.dart | 150 ++ .../viewer/src/ffi/src/ffi_render_target.dart | 15 +- .../lib/src/viewer/src/ffi/src/ffi_scene.dart | 19 + .../src/viewer/src/ffi/src/ffi_swapchain.dart | 3 +- .../lib/src/viewer/src/ffi/src/ffi_view.dart | 32 +- .../viewer/src/ffi/src/thermion_dart.g.dart | 1788 ++++++++--------- .../src/ffi/src/thermion_viewer_ffi.dart | 285 +-- .../lib/src/viewer/src/filament/filament.dart | 78 + .../src/viewer/src/shared_types/config.dart | 0 .../src/viewer/src/shared_types/engine.dart | 28 + .../src/viewer/src/shared_types/entity.dart | 3 + .../src/viewer/src/shared_types/layers.dart | 18 + .../src/shared_types/render_target.dart | 1 + .../src/viewer/src/shared_types/scene.dart | 4 + .../src/viewer/src/thermion_viewer_base.dart | 59 +- .../src/viewer/src/thermion_viewer_stub.dart | 102 +- .../src/web_wasm/src/material_instance.dart | 50 + .../web_wasm/src/thermion_viewer_wasm.dart | 4 +- .../native/include/FilamentViewer.hpp | 176 -- thermion_dart/native/include/RenderTicker.hpp | 48 + .../native/include/c_api/APIBoundaryTypes.h | 7 +- thermion_dart/native/include/c_api/TEngine.h | 3 +- .../native/include/c_api/TGltfAssetLoader.h | 1 + .../native/include/c_api/TIndirectLight.h | 19 + .../native/include/c_api/TRenderTarget.h | 5 + .../native/include/c_api/TRenderTicker.h | 17 + .../native/include/c_api/TRenderer.h | 7 + .../native/include/c_api/ThermionDartApi.h | 85 - .../c_api/ThermionDartRenderThreadApi.h | 55 +- .../native/include/rendering/RenderLoop.hpp | 87 + thermion_dart/native/src/RenderTicker.cpp | 103 + thermion_dart/native/src/c_api/TEngine.cpp | 27 +- .../native/src/c_api/TGltfAssetLoader.cpp | 6 + .../native/src/c_api/TIndirectLight.cpp | 41 + .../native/src/c_api/TRenderTarget.cpp | 10 + .../native/src/c_api/TRenderTicker.cpp | 38 + thermion_dart/native/src/c_api/TRenderer.cpp | 16 + .../native/src/c_api/ThermionDartApi.cpp | 415 ---- .../src/c_api/ThermionDartRenderThreadApi.cpp | 339 +--- .../native/src/rendering/RenderLoop.cpp | 83 + 41 files changed, 1900 insertions(+), 2342 deletions(-) create mode 100644 thermion_dart/lib/src/viewer/src/ffi/src/ffi_filament_app.dart create mode 100644 thermion_dart/lib/src/viewer/src/ffi/src/ffi_scene.dart create mode 100644 thermion_dart/lib/src/viewer/src/filament/filament.dart create mode 100644 thermion_dart/lib/src/viewer/src/shared_types/config.dart create mode 100644 thermion_dart/lib/src/viewer/src/shared_types/engine.dart create mode 100644 thermion_dart/lib/src/viewer/src/shared_types/layers.dart create mode 100644 thermion_dart/lib/src/viewer/src/shared_types/scene.dart delete mode 100644 thermion_dart/native/include/FilamentViewer.hpp create mode 100644 thermion_dart/native/include/RenderTicker.hpp create mode 100644 thermion_dart/native/include/c_api/TIndirectLight.h create mode 100644 thermion_dart/native/include/c_api/TRenderTicker.h delete mode 100644 thermion_dart/native/include/c_api/ThermionDartApi.h create mode 100644 thermion_dart/native/include/rendering/RenderLoop.hpp create mode 100644 thermion_dart/native/src/RenderTicker.cpp create mode 100644 thermion_dart/native/src/c_api/TIndirectLight.cpp create mode 100644 thermion_dart/native/src/c_api/TRenderTicker.cpp delete mode 100644 thermion_dart/native/src/c_api/ThermionDartApi.cpp create mode 100644 thermion_dart/native/src/rendering/RenderLoop.cpp 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 38c91a56..a93f4eea 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 @@ -1,5 +1,7 @@ import 'dart:ffi'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart'; +import 'package:thermion_dart/src/viewer/src/shared_types/layers.dart'; import 'package:vector_math/vector_math_64.dart'; import '../../../../utils/src/matrix.dart'; @@ -8,11 +10,10 @@ import 'thermion_dart.g.dart' as g; class FFICamera extends Camera { final Pointer camera; - final Pointer engine; - final Pointer transformManager; + final FFIFilamentApp app; late ThermionEntity _entity; - FFICamera(this.camera, this.engine, this.transformManager) { + FFICamera(this.camera, this.app) { _entity = g.Camera_getEntity(camera); } @@ -30,7 +31,8 @@ class FFICamera extends Camera { @override Future setTransform(Matrix4 transform) async { var entity = g.Camera_getEntity(camera); - g.TransformManager_setTransform(transformManager, entity, matrix4ToDouble4x4(transform)); + g.TransformManager_setTransform( + app.transformManager, entity, matrix4ToDouble4x4(transform)); } @override @@ -84,9 +86,8 @@ class FFICamera extends Camera { @override Future setProjection(Projection projection, double left, double right, - double bottom, double top, double near, double far) async { + double bottom, double top, double near, double far) async { var pType = g.Projection.values[projection.index]; - g.Camera_setProjection(camera, pType, left, - right, bottom, top, near, far); + g.Camera_setProjection(camera, pType, left, right, bottom, top, near, far); } } 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 new file mode 100644 index 00000000..6ff9339a --- /dev/null +++ b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_filament_app.dart @@ -0,0 +1,150 @@ +import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_render_target.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_swapchain.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_texture.dart'; +import 'package:thermion_dart/src/viewer/src/filament/filament.dart'; +import 'package:thermion_dart/thermion_dart.dart'; + +typedef RenderCallback = Pointer)>>; + +class FFIFilamentConfig extends FilamentConfig> { + FFIFilamentConfig( + {required super.backend, + required super.resourceLoader, + required super.uberArchivePath}); +} + +class FFIFilamentApp extends FilamentApp { + static FFIFilamentApp? _instance; + + final Pointer engine; + final Pointer gltfAssetLoader; + final Pointer gltfResourceLoader; + final Pointer renderer; + final Pointer transformManager; + final Pointer lightManager; + final Pointer renderableManager; + final Pointer ubershaderMaterialProvider; + final Pointer renderTicker; + + FFIFilamentApp( + this.engine, + this.gltfAssetLoader, + this.gltfResourceLoader, + this.renderer, + this.transformManager, + this.lightManager, + this.renderableManager, + this.ubershaderMaterialProvider, + this.renderTicker) + : super( + engine: engine, + gltfAssetLoader: gltfAssetLoader, + gltfResourceLoader: gltfResourceLoader, + renderer: renderer, + transformManager: transformManager, + lightManager: lightManager, + renderableManager: renderableManager, + ubershaderMaterialProvider: ubershaderMaterialProvider); + + Future create(FFIFilamentConfig config) async { + if (_instance == null) { + RenderLoop_destroy(); + RenderLoop_create(); + + final engine = await withPointerCallback((cb) => + Engine_createRenderThread( + TBackend.values[config.backend.index].index, + config.platform ?? nullptr, + config.sharedContext ?? nullptr, + config.stereoscopicEyeCount, + config.disableHandleUseAfterFreeCheck, + cb)); + + final gltfResourceLoader = await withPointerCallback( + (cb) => GltfResourceLoader_createRenderThread(engine, cb)); + final gltfAssetLoader = await withPointerCallback( + (cb) => GltfAssetLoader_createRenderThread(engine, nullptr, cb)); + final renderer = await withPointerCallback( + (cb) => Engine_createRendererRenderThread(engine, cb)); + final ubershaderMaterialProvider = + await withPointerCallback( + (cb) => 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()); + + _instance = FFIFilamentApp( + engine, + gltfAssetLoader, + gltfResourceLoader, + renderer, + transformManager, + lightManager, + renderableManager, + ubershaderMaterialProvider); + } + return _instance!; + } + + @override + Future createHeadlessSwapChain(int width, int height, + {bool hasStencilBuffer = false}) async { + var flags = TSWAP_CHAIN_CONFIG_TRANSPARENT | TSWAP_CHAIN_CONFIG_READABLE; + if (hasStencilBuffer) { + flags |= TSWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER; + } + final swapChain = await withPointerCallback((cb) => + Engine_createHeadlessSwapChainRenderThread( + this.engine, width, height, flags, cb)); + return FFISwapChain(swapChain); + } + + /// + /// + /// + @override + Future createSwapChain(Pointer window, + {bool hasStencilBuffer = false}) async { + var flags = TSWAP_CHAIN_CONFIG_TRANSPARENT | TSWAP_CHAIN_CONFIG_READABLE; + if (hasStencilBuffer) { + flags |= TSWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER; + } + final swapChain = await withPointerCallback((cb) => + Engine_createSwapChainRenderThread( + this.engine, window.cast(), flags, cb)); + return FFISwapChain(swapChain); + } + + /// + /// + /// + Future destroySwapChain(SwapChain swapChain) async { + await withVoidCallback((callback) { + Engine_destroySwapChainRenderThread( + engine, (swapChain as FFISwapChain).swapChain, callback); + }); + } + + @override + Future destroy() { + throw UnimplementedError(); + } + + /// + /// + /// + Future createRenderTarget(int width, int height, + {covariant FFITexture? color, covariant FFITexture? depth}) async { + final renderTarget = await withPointerCallback((cb) { + RenderTarget_createRenderThread(engine, width, height, + color?.pointer ?? nullptr, depth?.pointer ?? nullptr, cb); + }); + + return FFIRenderTarget(renderTarget, this); + } +} diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_render_target.dart b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_render_target.dart index 28d69723..ab5c3ffb 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_render_target.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_render_target.dart @@ -1,25 +1,30 @@ import 'dart:ffi'; 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'; class FFIRenderTarget extends RenderTarget { final Pointer renderTarget; - final Pointer viewer; - final Pointer engine; + final FFIFilamentApp app; - FFIRenderTarget(this.renderTarget, this.viewer, this.engine); + FFIRenderTarget(this.renderTarget, this.app); @override Future getColorTexture() async { final ptr = RenderTarget_getColorTexture(renderTarget); - return FFITexture(engine, ptr); + return FFITexture(app.engine, ptr); } @override Future getDepthTexture() async { final ptr = RenderTarget_getDepthTexture(renderTarget); - return FFITexture(engine, ptr); + return FFITexture(app.engine, ptr); + } + + @override + Future destroy() async { + await withVoidCallback((cb) => RenderTarget_destroy(app.engine, renderTarget)); } } diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_scene.dart b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_scene.dart new file mode 100644 index 00000000..ae07af69 --- /dev/null +++ b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_scene.dart @@ -0,0 +1,19 @@ +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_render_target.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_swapchain.dart'; +import 'package:thermion_dart/src/viewer/src/shared_types/scene.dart'; +import 'package:thermion_dart/src/viewer/src/shared_types/shared_types.dart'; +import 'callbacks.dart'; +import 'ffi_camera.dart'; + +class FFIScene extends Scene { + final Pointer scene; + final FFIFilamentApp app; + + FFIRenderTarget? renderTarget; + + FFIScene(this.scene, this.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 9ad32369..a7a036d0 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 @@ -5,7 +5,6 @@ import 'package:thermion_dart/thermion_dart.dart'; class FFISwapChain extends SwapChain { final Pointer swapChain; - final Pointer viewer; - FFISwapChain(this.swapChain, this.viewer); + FFISwapChain(this.swapChain); } 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 55d142e8..20aabdac 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 @@ -1,26 +1,22 @@ -import 'dart:ffi'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_render_target.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_scene.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_swapchain.dart'; -import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart'; +import 'package:thermion_dart/src/viewer/src/shared_types/scene.dart'; import 'package:thermion_dart/src/viewer/src/shared_types/shared_types.dart'; import 'callbacks.dart'; import 'ffi_camera.dart'; -import 'thermion_viewer_ffi.dart'; class FFIView extends View { final Pointer view; - final Pointer viewer; - final Pointer engine; + final FFIFilamentApp app; + FFIRenderTarget? renderTarget; - FFIView(this.view, this.viewer, this.engine) { + FFIView(this.view, this.app) { final renderTargetPtr = View_getRenderTarget(view); if (renderTargetPtr != nullptr) { - renderTarget = FFIRenderTarget( - renderTargetPtr, - viewer, - engine - ); + renderTarget = FFIRenderTarget(renderTargetPtr, app); } } @@ -56,10 +52,9 @@ class FFIView extends View { @override Future getCamera() async { - final engine = Viewer_getEngine(viewer); - final transformManager = Engine_getTransformManager(engine); + final transformManager = Engine_getTransformManager(app.engine); final cameraPtr = View_getCamera(view); - return FFICamera(cameraPtr, engine, transformManager); + return FFICamera(cameraPtr, app.engine, transformManager); } @override @@ -73,7 +68,7 @@ class FFIView extends View { } Future setRenderable(bool renderable, FFISwapChain swapChain) async { - Viewer_setViewRenderable(viewer, swapChain.swapChain, view, renderable); + throw UnimplementedError(); } @override @@ -90,8 +85,7 @@ class FFIView extends View { @override Future setToneMapper(ToneMapper mapper) async { - final engine = await Viewer_getEngine(viewer); - View_setToneMappingRenderThread(view, engine, mapper.index); + View_setToneMappingRenderThread(view, app.engine, mapper.index); } Future setStencilBufferEnabled(bool enabled) async { @@ -114,4 +108,8 @@ class FFIView extends View { Future setRenderQuality(QualityLevel quality) async { View_setRenderQuality(view, TQualityLevel.values[quality.index]); } + + Future setScene(covariant FFIScene scene) async { + await withVoidCallback((cb) => View_setScene(view, scene.scene)); + } } 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 c178c87c..16cab229 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 @@ -389,524 +389,65 @@ external void LightManager_setShadowCaster( bool enabled, ); -@ffi.Native< - ffi.Pointer Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer, ffi.Pointer)>(isLeaf: true) -external ffi.Pointer Viewer_create( - ffi.Pointer context, - ffi.Pointer loader, - ffi.Pointer platform, - ffi.Pointer uberArchivePath, -); - -@ffi.Native Function(ffi.Pointer)>(isLeaf: true) -external ffi.Pointer Viewer_getRenderer( - ffi.Pointer tViewer, -); - -@ffi.Native)>(isLeaf: true) -external void Viewer_destroy( - ffi.Pointer viewer, -); - -@ffi.Native Function(ffi.Pointer)>( - isLeaf: true) -external ffi.Pointer Viewer_getSceneManager( - ffi.Pointer viewer, +@ffi.Native)>(isLeaf: true) +external int FilamentAsset_getEntityCount( + ffi.Pointer filamentAsset, ); @ffi.Native< - ffi.Pointer Function(ffi.Pointer, ffi.IntPtr, - ffi.IntPtr, ffi.Uint32, ffi.Uint32)>(isLeaf: true) -external ffi.Pointer Viewer_createRenderTarget( - ffi.Pointer viewer, - int colorTextureId, - int depthTextureId, + ffi.Void Function( + ffi.Pointer, ffi.Pointer)>(isLeaf: true) +external void FilamentAsset_getEntities( + ffi.Pointer filamentAsset, + ffi.Pointer out, +); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, + ffi.Uint32, + ffi.Uint32, + ffi.Uint32, + ffi.Uint8, + ffi.Uint16, + ffi.IntPtr, + ffi.UnsignedInt, + ffi.UnsignedInt)>(symbol: "Texture_build", isLeaf: true) +external ffi.Pointer _Texture_build( + ffi.Pointer engine, int width, int height, + int depth, + int levels, + int tUsage, + int import1, + int sampler, + int format, ); -@ffi.Native< - ffi.Void Function( - ffi.Pointer, ffi.Pointer)>(isLeaf: true) -external void Viewer_destroyRenderTarget( - ffi.Pointer viewer, - ffi.Pointer tRenderTarget, -); - -@ffi.Native< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer)>(isLeaf: true) -external ffi.Pointer Viewer_createSwapChain( - ffi.Pointer viewer, - ffi.Pointer window, -); - -@ffi.Native< - ffi.Pointer Function( - ffi.Pointer, ffi.Uint32, ffi.Uint32)>(isLeaf: true) -external ffi.Pointer Viewer_createHeadlessSwapChain( - ffi.Pointer viewer, +ffi.Pointer Texture_build( + ffi.Pointer engine, int width, int height, -); - -@ffi.Native, ffi.Pointer)>( - isLeaf: true) -external void Viewer_destroySwapChain( - ffi.Pointer viewer, - ffi.Pointer swapChain, -); - -@ffi.Native)>(isLeaf: true) -external void Viewer_render( - ffi.Pointer viewer, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Bool, - ffi.Pointer>)>(isLeaf: true) -external void Viewer_capture( - ffi.Pointer viewer, - ffi.Pointer view, - ffi.Pointer swapChain, - ffi.Pointer pixelBuffer, - bool useFence, - ffi.Pointer> callback, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Bool, - ffi.Pointer>)>(isLeaf: true) -external void Viewer_captureRenderTarget( - ffi.Pointer viewer, - ffi.Pointer view, - ffi.Pointer swapChain, - ffi.Pointer renderTarget, - ffi.Pointer pixelBuffer, - bool useFence, - ffi.Pointer> callback, -); - -@ffi.Native Function(ffi.Pointer)>(isLeaf: true) -external ffi.Pointer Viewer_createView( - ffi.Pointer viewer, -); - -@ffi.Native Function(ffi.Pointer, ffi.Int)>( - isLeaf: true) -external ffi.Pointer Viewer_getViewAt( - ffi.Pointer viewer, - int index, -); - -@ffi.Native, ffi.Pointer)>( - isLeaf: true) -external void Viewer_setMainCamera( - ffi.Pointer tViewer, - ffi.Pointer tView, -); - -@ffi.Native Function(ffi.Pointer, ffi.Int)>( - isLeaf: true) -external ffi.Pointer Viewer_getSwapChainAt( - ffi.Pointer tViewer, - int index, -); - -@ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer, ffi.Bool)>(isLeaf: true) -external void Viewer_setViewRenderable( - ffi.Pointer viewer, - ffi.Pointer swapChain, - ffi.Pointer view, - bool renderable, -); - -@ffi.Native Function(ffi.Pointer)>(isLeaf: true) -external ffi.Pointer Viewer_getEngine( - ffi.Pointer viewer, -); - -@ffi.Native)>(isLeaf: true) -external void clear_background_image( - ffi.Pointer viewer, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, ffi.Pointer, ffi.Bool)>(isLeaf: true) -external void set_background_image( - ffi.Pointer viewer, - ffi.Pointer path, - bool fillHeight, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, ffi.Float, ffi.Float, ffi.Bool)>(isLeaf: true) -external void set_background_image_position( - ffi.Pointer viewer, - double x, - double y, - bool clamp, -); - -@ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Float, ffi.Float, ffi.Float, - ffi.Float)>(isLeaf: true) -external void set_background_color( - ffi.Pointer viewer, - double r, - double g, - double b, - double a, -); - -@ffi.Native)>(isLeaf: true) -external int Viewer_getMainCamera( - ffi.Pointer viewer, -); - -@ffi.Native, ffi.Pointer)>( - isLeaf: true) -external void Viewer_loadSkybox( - ffi.Pointer viewer, - ffi.Pointer skyboxPath, -); - -@ffi.Native)>(isLeaf: true) -external void Viewer_removeSkybox( - ffi.Pointer viewer, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, ffi.Pointer, ffi.Float)>(isLeaf: true) -external void Viewer_loadIbl( - ffi.Pointer viewer, - ffi.Pointer iblPath, - double intensity, -); - -@ffi.Native)>(isLeaf: true) -external void Viewer_removeIbl( - ffi.Pointer viewer, -); - -@ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Float, ffi.Float, ffi.Float, - ffi.Float)>(isLeaf: true) -external void create_ibl( - ffi.Pointer viewer, - double r, - double g, - double b, - double intensity, -); - -@ffi.Native, ffi.Pointer)>( - isLeaf: true) -external void rotate_ibl( - ffi.Pointer viewer, - ffi.Pointer rotationMatrix, -); - -@ffi.Native, ffi.Float)>(isLeaf: true) -external void set_frame_interval( - ffi.Pointer viewer, - double interval, -); - -@ffi.Native< - ffi.Void Function(ffi.Pointer, EntityId, ffi.Float, - ffi.Float, ffi.Float, ffi.Float, ffi.Float)>(isLeaf: true) -external void queue_relative_position_update_world_axis( - ffi.Pointer sceneManager, - int entity, - double viewportX, - double viewportY, - double x, - double y, - double z, -); - -@ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Pointer, EntityId, - ffi.Float, ffi.Float)>(isLeaf: true) -external void queue_position_update_from_viewport_coords( - ffi.Pointer sceneManager, - ffi.Pointer view, - int entity, - double viewportX, - double viewportY, -); - -@ffi.Native(isLeaf: true) -external void ios_dummy(); - -@ffi.Native)>(isLeaf: true) -external void thermion_flutter_free( - ffi.Pointer ptr, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, - EntityId, - ffi.Pointer< - ffi.NativeFunction< - ffi.Void Function(EntityId entityId1, EntityId entityId2)>>, - ffi.Bool)>(isLeaf: true) -external void add_collision_component( - ffi.Pointer sceneManager, - int entityId, - ffi.Pointer< - ffi.NativeFunction< - ffi.Void Function(EntityId entityId1, EntityId entityId2)>> - callback, - bool affectsCollidingTransform, -); - -@ffi.Native, EntityId)>( - isLeaf: true) -external void remove_collision_component( - ffi.Pointer sceneManager, - int entityId, -); - -@ffi.Native, EntityId)>( - isLeaf: true) -external void test_collisions( - ffi.Pointer sceneManager, - int entity, -); - -@ffi.Native< - Aabb2 Function( - ffi.Pointer, ffi.Pointer, EntityId)>(isLeaf: true) -external Aabb2 get_bounding_box( - ffi.Pointer sceneManager, - ffi.Pointer view, - int entity, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - EntityId, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>(isLeaf: true) -external void get_bounding_box_to_out( - ffi.Pointer sceneManager, - ffi.Pointer view, - int entity, - ffi.Pointer minX, - ffi.Pointer minY, - ffi.Pointer maxX, - ffi.Pointer maxY, -); - -@ffi.Native)>(isLeaf: true) -external TViewport View_getViewport( - ffi.Pointer view, -); - -@ffi.Native, ffi.Uint32, ffi.Uint32)>( - isLeaf: true) -external void View_setViewport( - ffi.Pointer view, - int width, - int height, -); - -@ffi.Native, ffi.Pointer)>( - isLeaf: true) -external void View_setRenderTarget( - ffi.Pointer view, - ffi.Pointer renderTarget, -); - -@ffi.Native, ffi.Bool)>(isLeaf: true) -external void View_setFrustumCullingEnabled( - ffi.Pointer view, - bool enabled, -); - -@ffi.Native Function(ffi.Pointer)>( - isLeaf: true) -external ffi.Pointer View_getRenderTarget( - ffi.Pointer tView, -); - -@ffi.Native, ffi.Bool)>(isLeaf: true) -external void View_setPostProcessing( - ffi.Pointer tView, - bool enabled, -); - -@ffi.Native, ffi.Bool)>(isLeaf: true) -external void View_setShadowsEnabled( - ffi.Pointer tView, - bool enabled, -); - -@ffi.Native, ffi.Int)>(isLeaf: true) -external void View_setShadowType( - ffi.Pointer tView, - int shadowType, -); - -@ffi.Native, ffi.Float, ffi.Float)>( - isLeaf: true) -external void View_setSoftShadowOptions( - ffi.Pointer tView, - double penumbraScale, - double penumbraRatioScale, -); - -@ffi.Native, ffi.Bool, ffi.Float)>( - isLeaf: true) -external void View_setBloom( - ffi.Pointer tView, - bool enabled, - double strength, -); - -@ffi.Native, ffi.UnsignedInt)>( - symbol: "View_setRenderQuality", isLeaf: true) -external void _View_setRenderQuality( - ffi.Pointer tView, - int qualityLevel, -); - -void View_setRenderQuality( - ffi.Pointer tView, - TQualityLevel qualityLevel, + int depth, + int levels, + int tUsage, + int import1, + TTextureSamplerType sampler, + TTextureFormat format, ) => - _View_setRenderQuality( - tView, - qualityLevel.value, + _Texture_build( + engine, + width, + height, + depth, + levels, + tUsage, + import1, + sampler.value, + format.value, ); -@ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Pointer, - ffi.UnsignedInt)>(symbol: "View_setToneMapping", isLeaf: true) -external void _View_setToneMapping( - ffi.Pointer tView, - ffi.Pointer tEngine, - int toneMapping, -); - -void View_setToneMapping( - ffi.Pointer tView, - ffi.Pointer tEngine, - ToneMapping toneMapping, -) => - _View_setToneMapping( - tView, - tEngine, - toneMapping.value, - ); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, ffi.Bool, ffi.Bool, ffi.Bool)>(isLeaf: true) -external void View_setAntiAliasing( - ffi.Pointer tView, - bool msaa, - bool fxaa, - bool taa, -); - -@ffi.Native, ffi.Int, ffi.Bool)>( - isLeaf: true) -external void View_setLayerEnabled( - ffi.Pointer tView, - int layer, - bool visible, -); - -@ffi.Native, ffi.Pointer)>( - isLeaf: true) -external void View_setCamera( - ffi.Pointer tView, - ffi.Pointer tCamera, -); - -@ffi.Native Function(ffi.Pointer)>(isLeaf: true) -external ffi.Pointer View_getScene( - ffi.Pointer tView, -); - -@ffi.Native Function(ffi.Pointer)>(isLeaf: true) -external ffi.Pointer View_getCamera( - ffi.Pointer tView, -); - -@ffi.Native, ffi.Bool)>(isLeaf: true) -external void View_setStencilBufferEnabled( - ffi.Pointer tView, - bool enabled, -); - -@ffi.Native)>(isLeaf: true) -external bool View_isStencilBufferEnabled( - ffi.Pointer tView, -); - -@ffi.Native, ffi.Bool)>(isLeaf: true) -external void View_setDitheringEnabled( - ffi.Pointer tView, - bool enabled, -); - -@ffi.Native)>(isLeaf: true) -external bool View_isDitheringEnabled( - ffi.Pointer tView, -); - -@ffi.Native, ffi.Pointer)>( - isLeaf: true) -external void View_setScene( - ffi.Pointer tView, - ffi.Pointer tScene, -); - -@ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Uint32, ffi.Uint32, ffi.Uint32, - PickCallback)>(isLeaf: true) -external void View_pick( - ffi.Pointer tView, - int requestId, - int x, - int y, - PickCallback callback, -); - -@ffi.Native< - ffi.Pointer Function( - ffi.Pointer, EntityId)>(isLeaf: true) -external ffi.Pointer NameComponentManager_getName( - ffi.Pointer tNameComponentManager, - int entity, -); - @ffi.Native< ffi.Bool Function( ffi.Pointer, @@ -1001,6 +542,22 @@ external int Texture_getDepth( int level, ); +@ffi.Native, ffi.Uint32)>( + symbol: "Texture_getUsage", isLeaf: true) +external int _Texture_getUsage( + ffi.Pointer tTexture, + int level, +); + +TTextureUsage Texture_getUsage( + ffi.Pointer tTexture, + int level, +) => + TTextureUsage.fromValue(_Texture_getUsage( + tTexture, + level, + )); + @ffi.Native< ffi.Pointer Function( ffi.Uint32, ffi.Uint32, ffi.Uint32)>(isLeaf: true) @@ -1217,6 +774,235 @@ external void TextureSampler_destroy( ffi.Pointer sampler, ); +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer)>(isLeaf: true) +external ffi.Pointer GltfAssetLoader_create( + ffi.Pointer tEngine, + ffi.Pointer tMaterialProvider, +); + +@ffi.Native Function(ffi.Pointer)>( + isLeaf: true) +external ffi.Pointer GltfResourceLoader_create( + ffi.Pointer tEngine, +); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Size, + ffi.Uint8)>(isLeaf: true) +external ffi.Pointer GltfAssetLoader_load( + ffi.Pointer tAssetLoader, + ffi.Pointer tResourceLoader, + ffi.Pointer data, + int length, + int numInstances, +); + +@ffi.Native< + ffi.Pointer Function(ffi.Pointer, + ffi.Pointer)>(isLeaf: true) +external ffi.Pointer GltfAssetLoader_getMaterialInstance( + ffi.Pointer tRenderableManager, + ffi.Pointer tAsset, +); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer)>(isLeaf: true) +external ffi.Pointer GltfAssetLoader_getMaterialProvider( + ffi.Pointer tAssetLoader, +); + +@ffi.Native)>(isLeaf: true) +external TViewport View_getViewport( + ffi.Pointer view, +); + +@ffi.Native, ffi.Uint32, ffi.Uint32)>( + isLeaf: true) +external void View_setViewport( + ffi.Pointer view, + int width, + int height, +); + +@ffi.Native, ffi.Pointer)>( + isLeaf: true) +external void View_setRenderTarget( + ffi.Pointer view, + ffi.Pointer renderTarget, +); + +@ffi.Native, ffi.Bool)>(isLeaf: true) +external void View_setFrustumCullingEnabled( + ffi.Pointer view, + bool enabled, +); + +@ffi.Native Function(ffi.Pointer)>( + isLeaf: true) +external ffi.Pointer View_getRenderTarget( + ffi.Pointer tView, +); + +@ffi.Native, ffi.Bool)>(isLeaf: true) +external void View_setPostProcessing( + ffi.Pointer tView, + bool enabled, +); + +@ffi.Native, ffi.Bool)>(isLeaf: true) +external void View_setShadowsEnabled( + ffi.Pointer tView, + bool enabled, +); + +@ffi.Native, ffi.Int)>(isLeaf: true) +external void View_setShadowType( + ffi.Pointer tView, + int shadowType, +); + +@ffi.Native, ffi.Float, ffi.Float)>( + isLeaf: true) +external void View_setSoftShadowOptions( + ffi.Pointer tView, + double penumbraScale, + double penumbraRatioScale, +); + +@ffi.Native, ffi.Bool, ffi.Float)>( + isLeaf: true) +external void View_setBloom( + ffi.Pointer tView, + bool enabled, + double strength, +); + +@ffi.Native, ffi.UnsignedInt)>( + symbol: "View_setRenderQuality", isLeaf: true) +external void _View_setRenderQuality( + ffi.Pointer tView, + int qualityLevel, +); + +void View_setRenderQuality( + ffi.Pointer tView, + TQualityLevel qualityLevel, +) => + _View_setRenderQuality( + tView, + qualityLevel.value, + ); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.UnsignedInt)>(symbol: "View_setToneMapping", isLeaf: true) +external void _View_setToneMapping( + ffi.Pointer tView, + ffi.Pointer tEngine, + int toneMapping, +); + +void View_setToneMapping( + ffi.Pointer tView, + ffi.Pointer tEngine, + ToneMapping toneMapping, +) => + _View_setToneMapping( + tView, + tEngine, + toneMapping.value, + ); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Bool, ffi.Bool, ffi.Bool)>(isLeaf: true) +external void View_setAntiAliasing( + ffi.Pointer tView, + bool msaa, + bool fxaa, + bool taa, +); + +@ffi.Native, ffi.Int, ffi.Bool)>( + isLeaf: true) +external void View_setLayerEnabled( + ffi.Pointer tView, + int layer, + bool visible, +); + +@ffi.Native, ffi.Pointer)>( + isLeaf: true) +external void View_setCamera( + ffi.Pointer tView, + ffi.Pointer tCamera, +); + +@ffi.Native Function(ffi.Pointer)>(isLeaf: true) +external ffi.Pointer View_getScene( + ffi.Pointer tView, +); + +@ffi.Native Function(ffi.Pointer)>(isLeaf: true) +external ffi.Pointer View_getCamera( + ffi.Pointer tView, +); + +@ffi.Native, ffi.Bool)>(isLeaf: true) +external void View_setStencilBufferEnabled( + ffi.Pointer tView, + bool enabled, +); + +@ffi.Native)>(isLeaf: true) +external bool View_isStencilBufferEnabled( + ffi.Pointer tView, +); + +@ffi.Native, ffi.Bool)>(isLeaf: true) +external void View_setDitheringEnabled( + ffi.Pointer tView, + bool enabled, +); + +@ffi.Native)>(isLeaf: true) +external bool View_isDitheringEnabled( + ffi.Pointer tView, +); + +@ffi.Native, ffi.Pointer)>( + isLeaf: true) +external void View_setScene( + ffi.Pointer tView, + ffi.Pointer tScene, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Uint32, ffi.Uint32, ffi.Uint32, + PickCallback)>(isLeaf: true) +external void View_pick( + ffi.Pointer tView, + int requestId, + int x, + int y, + PickCallback callback, +); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, EntityId)>(isLeaf: true) +external ffi.Pointer NameComponentManager_getName( + ffi.Pointer tNameComponentManager, + int entity, +); + @ffi.Native< ffi.Void Function(ffi.Pointer, ffi.Uint32, ffi.Uint32, GizmoPickCallback)>(isLeaf: true) @@ -1256,6 +1042,25 @@ external ffi.Pointer MaterialProvider_createMaterialInstance( ffi.Pointer key, ); +@ffi.Native< + ffi.Pointer Function(ffi.Pointer, ffi.Uint32, + ffi.Uint32, ffi.Pointer, ffi.Pointer)>(isLeaf: true) +external ffi.Pointer RenderTarget_create( + ffi.Pointer tEngine, + int width, + int height, + ffi.Pointer color, + ffi.Pointer depth, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Pointer)>(isLeaf: true) +external void RenderTarget_destroy( + ffi.Pointer tEngine, + ffi.Pointer tRenderTarget, +); + @ffi.Native, EntityId)>(isLeaf: true) external void Scene_addEntity( ffi.Pointer tScene, @@ -1271,164 +1076,150 @@ external void Scene_setSkybox( @ffi.Native< ffi.Void Function( - ffi.Pointer, ffi.Float, ffi.Float, ffi.Float)>(isLeaf: true) -external void set_camera_exposure( - ffi.Pointer camera, + ffi.Pointer, ffi.Pointer)>(isLeaf: true) +external void Scene_setIndirectLight( + ffi.Pointer tScene, + ffi.Pointer tIndirectLight, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Pointer)>(isLeaf: true) +external void Scene_addFilamentAsset( + ffi.Pointer tScene, + ffi.Pointer asset, +); + +@ffi.Native< + ffi.Int Function( + ffi.Pointer, ffi.Float, ffi.Float, ffi.Float)>(isLeaf: true) +external int set_camera_exposure( + ffi.Pointer camera, double aperture, double shutterSpeed, double sensitivity, ); -@ffi.Native, double4x4)>(isLeaf: true) -external void set_camera_model_matrix( - ffi.Pointer camera, - double4x4 matrix, +@ffi.Native, ffi.Int)>(isLeaf: true) +external int set_camera_model_matrix( + ffi.Pointer camera, + int matrix, ); -@ffi.Native)>(isLeaf: true) -external double4x4 get_camera_model_matrix( - ffi.Pointer camera, -); +@ffi.Native(symbol: "double4x4") +external int double4x41; -@ffi.Native)>(isLeaf: true) -external double4x4 get_camera_view_matrix( - ffi.Pointer camera, -); - -@ffi.Native)>(isLeaf: true) -external double4x4 get_camera_projection_matrix( - ffi.Pointer camera, -); - -@ffi.Native)>(isLeaf: true) -external double4x4 get_camera_culling_projection_matrix( - ffi.Pointer camera, -); - -@ffi.Native Function(ffi.Pointer)>( - isLeaf: true) -external ffi.Pointer get_camera_frustum( - ffi.Pointer camera, +@ffi.Native Function(ffi.Pointer)>(isLeaf: true) +external ffi.Pointer get_camera_frustum( + ffi.Pointer camera, ); @ffi.Native< - ffi.Void Function( - ffi.Pointer, double4x4, ffi.Double, ffi.Double)>(isLeaf: true) -external void set_camera_projection_matrix( - ffi.Pointer camera, - double4x4 matrix, + ffi.Int Function( + ffi.Pointer, ffi.Int, ffi.Double, ffi.Double)>(isLeaf: true) +external int set_camera_projection_matrix( + ffi.Pointer camera, + int matrix, double near, double far, ); @ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Double, ffi.Double, ffi.Double, - ffi.Double, ffi.Bool)>(isLeaf: true) -external void set_camera_projection_from_fov( - ffi.Pointer camera, + ffi.Int Function(ffi.Pointer, ffi.Double, ffi.Double, ffi.Double, + ffi.Double, ffi.Int)>(isLeaf: true) +external int set_camera_projection_from_fov( + ffi.Pointer camera, double fovInDegrees, double aspect, double near, double far, - bool horizontal, + int horizontal, ); -@ffi.Native)>(isLeaf: true) -external double get_camera_focal_length( - ffi.Pointer camera, +@ffi.Native)>(isLeaf: true) +external int get_camera_focal_length( + ffi.Pointer camera, ); -@ffi.Native)>(isLeaf: true) -external double Camera_getFocalLength( - ffi.Pointer camera, +@ffi.Native)>(isLeaf: true) +external int Camera_getFocalLength( + ffi.Pointer camera, ); -@ffi.Native)>(isLeaf: true) -external double Camera_getNear( - ffi.Pointer camera, +@ffi.Native)>(isLeaf: true) +external int Camera_getNear( + ffi.Pointer camera, ); -@ffi.Native)>(isLeaf: true) -external double Camera_getCullingFar( - ffi.Pointer camera, +@ffi.Native)>(isLeaf: true) +external int Camera_getCullingFar( + ffi.Pointer camera, ); -@ffi.Native)>(isLeaf: true) -external double4x4 Camera_getViewMatrix( - ffi.Pointer camera, -); - -@ffi.Native)>(isLeaf: true) -external double4x4 Camera_getModelMatrix( - ffi.Pointer camera, -); - -@ffi.Native, double3, double3, double3)>( +@ffi.Native, ffi.Int, ffi.Int, ffi.Int)>( isLeaf: true) -external void Camera_lookAt( - ffi.Pointer camera, - double3 eye, - double3 focus, - double3 up, +external int Camera_lookAt( + ffi.Pointer camera, + int eye, + int focus, + int up, ); -@ffi.Native)>(isLeaf: true) -external double get_camera_near( - ffi.Pointer camera, +@ffi.Native)>(isLeaf: true) +external int get_camera_near( + ffi.Pointer camera, ); -@ffi.Native)>(isLeaf: true) -external double get_camera_culling_far( - ffi.Pointer camera, +@ffi.Native)>(isLeaf: true) +external int get_camera_culling_far( + ffi.Pointer camera, ); -@ffi.Native, ffi.Bool)>(isLeaf: true) -external double get_camera_fov( - ffi.Pointer camera, - bool horizontal, +@ffi.Native, ffi.Int)>(isLeaf: true) +external int get_camera_fov( + ffi.Pointer camera, + int horizontal, ); -@ffi.Native, ffi.Float)>(isLeaf: true) -external void set_camera_focus_distance( - ffi.Pointer camera, +@ffi.Native, ffi.Float)>(isLeaf: true) +external int set_camera_focus_distance( + ffi.Pointer camera, double focusDistance, ); @ffi.Native< - ffi.Void Function( - ffi.Pointer, double4x4, ffi.Double, ffi.Double)>(isLeaf: true) -external void Camera_setCustomProjectionWithCulling( - ffi.Pointer camera, - double4x4 projectionMatrix, + ffi.Int Function( + ffi.Pointer, ffi.Int, ffi.Double, ffi.Double)>(isLeaf: true) +external int Camera_setCustomProjectionWithCulling( + ffi.Pointer camera, + int projectionMatrix, double near, double far, ); -@ffi.Native, double4x4)>(isLeaf: true) -external void Camera_setModelMatrix( - ffi.Pointer camera, - double4x4 modelMatrix, +@ffi.Native, ffi.Int)>(isLeaf: true) +external int Camera_setModelMatrix( + ffi.Pointer camera, + int modelMatrix, ); @ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Double, ffi.Double, ffi.Double, + ffi.Int Function(ffi.Pointer, ffi.Double, ffi.Double, ffi.Double, ffi.Double)>(isLeaf: true) -external void Camera_setLensProjection( - ffi.Pointer camera, +external int Camera_setLensProjection( + ffi.Pointer camera, double near, double far, double aspect, double focalLength, ); -@ffi.Native)>(isLeaf: true) -external int Camera_getEntity( - ffi.Pointer camera, -); +@ffi.Native(symbol: "EntityId") +external int EntityId1; @ffi.Native< - ffi.Void Function( - ffi.Pointer, + ffi.Int Function( + ffi.Pointer, ffi.UnsignedInt, ffi.Double, ffi.Double, @@ -1436,8 +1227,8 @@ external int Camera_getEntity( ffi.Double, ffi.Double, ffi.Double)>(symbol: "Camera_setProjection", isLeaf: true) -external void _Camera_setProjection( - ffi.Pointer tCamera, +external int _Camera_setProjection( + ffi.Pointer tCamera, int projection, double left, double right, @@ -1447,8 +1238,8 @@ external void _Camera_setProjection( double far, ); -void Camera_setProjection( - ffi.Pointer tCamera, +int Camera_setProjection( + ffi.Pointer tCamera, Projection projection, double left, double right, @@ -1581,224 +1372,71 @@ external void Renderer_readPixels( ffi.Pointer out, ); +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Float, ffi.Float, ffi.Uint8, + ffi.Uint8)>(isLeaf: true) +external void Renderer_setFrameInterval( + ffi.Pointer tRenderer, + double headRoomRatio, + double scaleRate, + int history, + int interval, +); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer)>(isLeaf: true) +external ffi.Pointer RenderTicker_create( + ffi.Pointer tRenderer, + ffi.Pointer tSceneManager, +); + +@ffi.Native, ffi.Uint64)>( + isLeaf: true) +external void RenderTicker_render( + ffi.Pointer tRenderTicker, + int frameTimeInNanos, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer>, ffi.Uint8)>(isLeaf: true) +external void RenderTicker_setRenderable( + ffi.Pointer tFilamentRender, + ffi.Pointer swapChain, + ffi.Pointer> views, + int numViews, +); + @ffi.Native(isLeaf: true) external void RenderLoop_create(); @ffi.Native(isLeaf: true) external void RenderLoop_destroy(); -@ffi.Native< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer renderCallbackOwner)>>, - ffi.Pointer, - ffi.Pointer< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer viewer)>>)>(isLeaf: true) -external void Viewer_createOnRenderThread( - ffi.Pointer context, - ffi.Pointer platform, - ffi.Pointer uberArchivePath, - ffi.Pointer loader, - ffi.Pointer< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer renderCallbackOwner)>> - renderCallback, - ffi.Pointer renderCallbackOwner, - ffi.Pointer< - ffi.NativeFunction viewer)>> - callback, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer< - ffi - .NativeFunction tView)>>)>( +@ffi.Native, ffi.Uint64)>( isLeaf: true) -external void Viewer_createViewRenderThread( - ffi.Pointer viewer, - ffi.Pointer tView)>> - onComplete, -); - -@ffi.Native)>(isLeaf: true) -external void Viewer_destroyOnRenderThread( - ffi.Pointer viewer, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer< - ffi - .NativeFunction)>>)>( - isLeaf: true) -external void Viewer_createSwapChainRenderThread( - ffi.Pointer viewer, - ffi.Pointer surface, - ffi.Pointer)>> - onComplete, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, - ffi.Uint32, - ffi.Uint32, - ffi.Pointer< - ffi - .NativeFunction)>>)>( - isLeaf: true) -external void Viewer_createHeadlessSwapChainRenderThread( - ffi.Pointer viewer, - int width, - int height, - ffi.Pointer)>> - onComplete, -); - -@ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer>)>(isLeaf: true) -external void Viewer_destroySwapChainRenderThread( - ffi.Pointer viewer, - ffi.Pointer swapChain, - ffi.Pointer> onComplete, -); - -@ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>(isLeaf: true) -external void Viewer_renderRenderThread( - ffi.Pointer viewer, - ffi.Pointer view, - ffi.Pointer swapChain, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Bool, - ffi.Pointer>)>(isLeaf: true) -external void Viewer_captureRenderThread( - ffi.Pointer viewer, - ffi.Pointer view, - ffi.Pointer swapChain, - ffi.Pointer out, - bool useFence, - ffi.Pointer> onComplete, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Bool, - ffi.Pointer>)>(isLeaf: true) -external void Viewer_captureRenderTargetRenderThread( - ffi.Pointer viewer, - ffi.Pointer view, - ffi.Pointer swapChain, - ffi.Pointer renderTarget, - ffi.Pointer out, - bool useFence, - ffi.Pointer> onComplete, -); - -@ffi.Native< - ffi.Void Function(ffi.Pointer, - ffi.Pointer>)>(isLeaf: true) -external void Viewer_requestFrameRenderThread( - ffi.Pointer viewer, - ffi.Pointer> onComplete, -); - -@ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Float, - ffi.Pointer>)>(isLeaf: true) -external void Viewer_loadIblRenderThread( - ffi.Pointer viewer, - ffi.Pointer iblPath, - double intensity, - ffi.Pointer> onComplete, -); - -@ffi.Native< - ffi.Void Function(ffi.Pointer, - ffi.Pointer>)>(isLeaf: true) -external void Viewer_removeIblRenderThread( - ffi.Pointer viewer, - ffi.Pointer> onComplete, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, - ffi.IntPtr, - ffi.IntPtr, - ffi.Uint32, - ffi.Uint32, - ffi.Pointer< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer)>>)>(isLeaf: true) -external void Viewer_createRenderTargetRenderThread( - ffi.Pointer viewer, - int colorTexture, - int depthTexture, - int width, - int height, - ffi.Pointer)>> - onComplete, -); - -@ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer>)>(isLeaf: true) -external void Viewer_destroyRenderTargetRenderThread( - ffi.Pointer viewer, - ffi.Pointer tRenderTarget, - ffi.Pointer> onComplete, -); - -@ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer>)>(isLeaf: true) -external void Viewer_loadSkyboxRenderThread( - ffi.Pointer viewer, - ffi.Pointer skyboxPath, - ffi.Pointer> onComplete, -); - -@ffi.Native< - ffi.Void Function(ffi.Pointer, - ffi.Pointer>)>(isLeaf: true) -external void Viewer_removeSkyboxRenderThread( - ffi.Pointer viewer, - ffi.Pointer> onComplete, +external void RenderTicker_renderRenderThread( + ffi.Pointer tRenderTicker, + int frameTimeInNanos, ); @ffi.Native< ffi.Void Function( ffi.Int, + ffi.Pointer, + ffi.Pointer, + ffi.Uint8, + ffi.Bool, ffi.Pointer< ffi.NativeFunction)>>)>( isLeaf: true) external void Engine_createRenderThread( int backend, + ffi.Pointer platform, + ffi.Pointer sharedContext, + int stereoscopicEyeCount, + bool disableHandleUseAfterFreeCheck, ffi.Pointer)>> onComplete, ); @@ -1893,6 +1531,15 @@ external void Engine_buildMaterialRenderThread( onComplete, ); +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer>)>(isLeaf: true) +external void Engine_destroySwapChainRenderThread( + ffi.Pointer tEngine, + ffi.Pointer tSwapChain, + ffi.Pointer> onComplete, +); + @ffi.Native< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer>)>(isLeaf: true) @@ -1902,6 +1549,24 @@ external void Engine_destroyMaterialRenderThread( ffi.Pointer> onComplete, ); +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer>)>(isLeaf: true) +external void Engine_destroySkyboxRenderThread( + ffi.Pointer tEngine, + ffi.Pointer tSkybox, + ffi.Pointer> onComplete, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer>)>(isLeaf: true) +external void Engine_destroyIndirectLightRenderThread( + ffi.Pointer tEngine, + ffi.Pointer tIndirectLight, + ffi.Pointer> onComplete, +); + @ffi.Native< ffi.Void Function( ffi.Pointer, @@ -1909,40 +1574,48 @@ external void Engine_destroyMaterialRenderThread( ffi.Uint32, ffi.Uint32, ffi.Uint8, + ffi.Uint16, + ffi.IntPtr, ffi.UnsignedInt, ffi.UnsignedInt, ffi.Pointer< ffi.NativeFunction)>>)>( - symbol: "Engine_buildTextureRenderThread", isLeaf: true) -external void _Engine_buildTextureRenderThread( + symbol: "Texture_buildRenderThread", isLeaf: true) +external void _Texture_buildRenderThread( ffi.Pointer engine, int width, int height, int depth, int levels, + int tUsage, + int import1, int sampler, int format, ffi.Pointer)>> onComplete, ); -void Engine_buildTextureRenderThread( +void Texture_buildRenderThread( ffi.Pointer engine, int width, int height, int depth, int levels, + int tUsage, + int import1, TTextureSamplerType sampler, TTextureFormat format, ffi.Pointer)>> onComplete, ) => - _Engine_buildTextureRenderThread( + _Texture_buildRenderThread( engine, width, height, depth, levels, + tUsage, + import1, sampler.value, format.value, onComplete, @@ -2003,6 +1676,26 @@ external void Engine_buildSkyboxRenderThread( ffi.Pointer> onTextureUploadComplete, ); +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Size, + ffi.Float, + ffi.Pointer< + ffi.NativeFunction)>>, + ffi.Pointer>)>(isLeaf: true) +external void Engine_buildIndirectLightRenderThread( + ffi.Pointer tEngine, + ffi.Pointer iblData, + int length, + double intensity, + ffi.Pointer< + ffi.NativeFunction)>> + onComplete, + ffi.Pointer> onTextureUploadComplete, +); + @ffi.Native< ffi.Void Function( ffi.Pointer, @@ -2131,57 +1824,6 @@ external FilamentRenderCallback make_render_callback_fn_pointer( FilamentRenderCallback arg0, ); -@ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Bool, - ffi.Pointer>)>(isLeaf: true) -external void set_rendering_render_thread( - ffi.Pointer viewer, - bool rendering, - ffi.Pointer> onComplete, -); - -@ffi.Native, ffi.Float)>(isLeaf: true) -external void set_frame_interval_render_thread( - ffi.Pointer viewer, - double frameInterval, -); - -@ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Float, ffi.Float, ffi.Float, - ffi.Float)>(isLeaf: true) -external void set_background_color_render_thread( - ffi.Pointer viewer, - double r, - double g, - double b, - double a, -); - -@ffi.Native)>(isLeaf: true) -external void clear_background_image_render_thread( - ffi.Pointer viewer, -); - -@ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Bool, - ffi.Pointer>)>(isLeaf: true) -external void set_background_image_render_thread( - ffi.Pointer viewer, - ffi.Pointer path, - bool fillHeight, - ffi.Pointer> onComplete, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, ffi.Float, ffi.Float, ffi.Bool)>(isLeaf: true) -external void set_background_image_position_render_thread( - ffi.Pointer viewer, - double x, - double y, - bool clamp, -); - @ffi.Native< ffi.Void Function( ffi.Pointer, @@ -2738,6 +2380,26 @@ external void RenderTarget_getColorTextureRenderThread( onComplete, ); +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Uint32, + ffi.Uint32, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer)>>)>(isLeaf: true) +external void RenderTarget_createRenderThread( + ffi.Pointer tEngine, + int width, + int height, + ffi.Pointer color, + ffi.Pointer depth, + ffi.Pointer)>> + onComplete, +); + @ffi.Native< ffi.Void Function( ffi.Pointer< @@ -2997,12 +2659,6 @@ external void set_bone_transform_render_thread( ffi.Pointer> callback, ); -@ffi.Native, ffi.Bool)>(isLeaf: true) -external void set_post_processing_render_thread( - ffi.Pointer viewer, - bool enabled, -); - @ffi.Native< ffi.Void Function(ffi.Pointer, EntityId, ffi.Pointer>)>(isLeaf: true) @@ -3012,6 +2668,102 @@ external void reset_to_rest_pose_render_thread( ffi.Pointer> callback, ); +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer)>>)>(isLeaf: true) +external void GltfAssetLoader_createRenderThread( + ffi.Pointer tEngine, + ffi.Pointer tMaterialProvider, + ffi.Pointer< + ffi.NativeFunction)>> + callback, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer)>>)>(isLeaf: true) +external void GltfResourceLoader_createRenderThread( + ffi.Pointer tEngine, + ffi.Pointer< + ffi + .NativeFunction)>> + callback, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Size, + ffi.Uint8, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer)>>)>(isLeaf: true) +external void GltfAssetLoader_loadRenderThread( + ffi.Pointer tAssetLoader, + ffi.Pointer tResourceLoader, + ffi.Pointer data, + int length, + int numInstances, + ffi.Pointer< + ffi.NativeFunction)>> + callback, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer>)>(isLeaf: true) +external void Scene_addFilamentAssetRenderThread( + ffi.Pointer tScene, + ffi.Pointer tAsset, + ffi.Pointer> callback, +); + +@ffi.Native)>(isLeaf: true) +external double4x4 get_camera_model_matrix( + ffi.Pointer camera, +); + +@ffi.Native)>(isLeaf: true) +external double4x4 get_camera_view_matrix( + ffi.Pointer camera, +); + +@ffi.Native)>(isLeaf: true) +external double4x4 get_camera_projection_matrix( + ffi.Pointer camera, +); + +@ffi.Native)>(isLeaf: true) +external double4x4 get_camera_culling_projection_matrix( + ffi.Pointer camera, +); + +@ffi.Native)>(isLeaf: true) +external double4x4 Camera_getViewMatrix( + ffi.Pointer camera, +); + +@ffi.Native)>(isLeaf: true) +external double4x4 Camera_getModelMatrix( + ffi.Pointer camera, +); + +@ffi.Native)>(isLeaf: true) +external int Camera_getEntity( + ffi.Pointer camera, +); + @ffi.Native< ffi.Pointer Function( ffi.Pointer, @@ -3430,17 +3182,34 @@ external bool RenderableManager_getFogEnabled( int entityId, ); -@ffi.Native Function(ffi.UnsignedInt)>( - symbol: "Engine_create", isLeaf: true) +@ffi.Native< + ffi.Pointer Function( + ffi.UnsignedInt, + ffi.Pointer, + ffi.Pointer, + ffi.Uint8, + ffi.Bool)>(symbol: "Engine_create", isLeaf: true) external ffi.Pointer _Engine_create( int backend, + ffi.Pointer platform, + ffi.Pointer sharedContext, + int stereoscopicEyeCount, + bool disableHandleUseAfterFreeCheck, ); ffi.Pointer Engine_create( TBackend backend, + ffi.Pointer platform, + ffi.Pointer sharedContext, + int stereoscopicEyeCount, + bool disableHandleUseAfterFreeCheck, ) => _Engine_create( backend.value, + platform, + sharedContext, + stereoscopicEyeCount, + disableHandleUseAfterFreeCheck, ); @ffi.Native Function(ffi.Pointer)>(isLeaf: true) @@ -3467,6 +3236,13 @@ external ffi.Pointer Engine_createHeadlessSwapChain( int flags, ); +@ffi.Native, ffi.Pointer)>( + isLeaf: true) +external void Engine_destroySwapChain( + ffi.Pointer tEngine, + ffi.Pointer tSwapChain, +); + @ffi.Native Function(ffi.Pointer)>(isLeaf: true) external ffi.Pointer Engine_createCamera( ffi.Pointer tEngine, @@ -3508,44 +3284,6 @@ external ffi.Pointer Engine_getEntityManager( ffi.Pointer engine, ); -@ffi.Native< - ffi.Pointer Function( - ffi.Pointer, - ffi.Uint32, - ffi.Uint32, - ffi.Uint32, - ffi.Uint8, - ffi.UnsignedInt, - ffi.UnsignedInt)>(symbol: "Engine_buildTexture", isLeaf: true) -external ffi.Pointer _Engine_buildTexture( - ffi.Pointer engine, - int width, - int height, - int depth, - int levels, - int sampler, - int format, -); - -ffi.Pointer Engine_buildTexture( - ffi.Pointer engine, - int width, - int height, - int depth, - int levels, - TTextureSamplerType sampler, - TTextureFormat format, -) => - _Engine_buildTexture( - engine, - width, - height, - depth, - levels, - sampler.value, - format.value, - ); - @ffi.Native, ffi.Pointer)>( isLeaf: true) external void Engine_destroyTexture( @@ -3604,6 +3342,36 @@ external ffi.Pointer Engine_buildSkybox( ffi.Pointer> onTextureUploadComplete, ); +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Size, + ffi.Float, + ffi.Pointer>)>(isLeaf: true) +external ffi.Pointer Engine_buildIndirectLight( + ffi.Pointer tEngine, + ffi.Pointer ktxData, + int length, + double intensity, + ffi.Pointer> onTextureUploadComplete, +); + +@ffi.Native, ffi.Pointer)>( + isLeaf: true) +external void Engine_destroySkybox( + ffi.Pointer tEngine, + ffi.Pointer tSkybox, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Pointer)>(isLeaf: true) +external void Engine_destroyIndirectLight( + ffi.Pointer tEngine, + ffi.Pointer tIndirectLight, +); + @ffi.Native< ffi.Pointer Function( ffi.Pointer, @@ -3963,6 +3731,8 @@ final class TScene extends ffi.Opaque {} final class TSkybox extends ffi.Opaque {} +final class TIndirectLight extends ffi.Opaque {} + final class TTransformManager extends ffi.Opaque {} final class TAnimationManager extends ffi.Opaque {} @@ -3989,6 +3759,12 @@ final class TTextureSampler extends ffi.Opaque {} final class TLinearImage extends ffi.Opaque {} +final class TGltfAssetLoader extends ffi.Opaque {} + +final class TGltfResourceLoader extends ffi.Opaque {} + +final class TFilamentAsset extends ffi.Opaque {} + final class TMaterialKey extends ffi.Struct { @ffi.Bool() external bool doubleSided; @@ -4128,6 +3904,14 @@ final class double3 extends ffi.Struct { external double z; } +final class double3x3 extends ffi.Struct { + external double3 col1; + + external double3 col2; + + external double3 col3; +} + final class double4 extends ffi.Struct { @ffi.Double() external double x; @@ -4350,70 +4134,6 @@ enum TTransparencyMode { typedef EntityId = ffi.Int32; typedef DartEntityId = int; -final class TViewport extends ffi.Struct { - @ffi.Int32() - external int left; - - @ffi.Int32() - external int bottom; - - @ffi.Uint32() - external int width; - - @ffi.Uint32() - external int height; -} - -enum ToneMapping { - ACES(0), - FILMIC(1), - LINEAR(2); - - final int value; - const ToneMapping(this.value); - - static ToneMapping fromValue(int value) => switch (value) { - 0 => ACES, - 1 => FILMIC, - 2 => LINEAR, - _ => throw ArgumentError("Unknown value for ToneMapping: $value"), - }; -} - -enum TQualityLevel { - LOW(0), - MEDIUM(1), - HIGH(2), - ULTRA(3); - - final int value; - const TQualityLevel(this.value); - - static TQualityLevel fromValue(int value) => switch (value) { - 0 => LOW, - 1 => MEDIUM, - 2 => HIGH, - 3 => ULTRA, - _ => throw ArgumentError("Unknown value for TQualityLevel: $value"), - }; -} - -typedef PickCallback = ffi.Pointer>; -typedef PickCallbackFunction = ffi.Void Function( - ffi.Uint32 requestId, - EntityId entityId, - ffi.Float depth, - ffi.Float fragX, - ffi.Float fragY, - ffi.Float fragZ); -typedef DartPickCallbackFunction = void Function( - int requestId, - DartEntityId entityId, - double depth, - double fragX, - double fragY, - double fragZ); - enum TTextureSamplerType { SAMPLER_2D(0), SAMPLER_2D_ARRAY(1), @@ -4738,6 +4458,58 @@ abstract class TPixelDataType { static const PIXELDATATYPE_UINT_2_10_10_10_REV = 11; } +enum TTextureUsage { + TEXTURE_USAGE_NONE(0), + + /// !< Texture can be used as a color attachment + TEXTURE_USAGE_COLOR_ATTACHMENT(1), + + /// !< Texture can be used as a depth attachment + TEXTURE_USAGE_DEPTH_ATTACHMENT(2), + + /// !< Texture can be used as a stencil attachment + TEXTURE_USAGE_STENCIL_ATTACHMENT(4), + + /// !< Data can be uploaded into this texture (default) + TEXTURE_USAGE_UPLOADABLE(8), + + /// !< Texture can be sampled (default) + TEXTURE_USAGE_SAMPLEABLE(16), + + /// !< Texture can be used as a subpass input + TEXTURE_USAGE_SUBPASS_INPUT(32), + + /// !< Texture can be used the source of a blit() + TEXTURE_USAGE_BLIT_SRC(64), + + /// !< Texture can be used the destination of a blit() + TEXTURE_USAGE_BLIT_DST(128), + + /// !< Texture can be used the destination of a blit() + TEXTURE_USAGE_PROTECTED(256), + + /// !< Default texture usage + TEXTURE_USAGE_DEFAULT(24); + + final int value; + const TTextureUsage(this.value); + + static TTextureUsage fromValue(int value) => switch (value) { + 0 => TEXTURE_USAGE_NONE, + 1 => TEXTURE_USAGE_COLOR_ATTACHMENT, + 2 => TEXTURE_USAGE_DEPTH_ATTACHMENT, + 4 => TEXTURE_USAGE_STENCIL_ATTACHMENT, + 8 => TEXTURE_USAGE_UPLOADABLE, + 16 => TEXTURE_USAGE_SAMPLEABLE, + 32 => TEXTURE_USAGE_SUBPASS_INPUT, + 64 => TEXTURE_USAGE_BLIT_SRC, + 128 => TEXTURE_USAGE_BLIT_DST, + 256 => TEXTURE_USAGE_PROTECTED, + 24 => TEXTURE_USAGE_DEFAULT, + _ => throw ArgumentError("Unknown value for TTextureUsage: $value"), + }; +} + enum TSamplerWrapMode { WRAP_CLAMP_TO_EDGE(0), WRAP_REPEAT(1), @@ -4805,6 +4577,70 @@ enum TSamplerCompareMode { }; } +final class TViewport extends ffi.Struct { + @ffi.Int32() + external int left; + + @ffi.Int32() + external int bottom; + + @ffi.Uint32() + external int width; + + @ffi.Uint32() + external int height; +} + +enum ToneMapping { + ACES(0), + FILMIC(1), + LINEAR(2); + + final int value; + const ToneMapping(this.value); + + static ToneMapping fromValue(int value) => switch (value) { + 0 => ACES, + 1 => FILMIC, + 2 => LINEAR, + _ => throw ArgumentError("Unknown value for ToneMapping: $value"), + }; +} + +enum TQualityLevel { + LOW(0), + MEDIUM(1), + HIGH(2), + ULTRA(3); + + final int value; + const TQualityLevel(this.value); + + static TQualityLevel fromValue(int value) => switch (value) { + 0 => LOW, + 1 => MEDIUM, + 2 => HIGH, + 3 => ULTRA, + _ => throw ArgumentError("Unknown value for TQualityLevel: $value"), + }; +} + +typedef PickCallback = ffi.Pointer>; +typedef PickCallbackFunction = ffi.Void Function( + ffi.Uint32 requestId, + EntityId entityId, + ffi.Float depth, + ffi.Float fragX, + ffi.Float fragY, + ffi.Float fragZ); +typedef DartPickCallbackFunction = void Function( + int requestId, + DartEntityId entityId, + double depth, + double fragX, + double fragY, + double fragZ); + enum TGizmoAxis { X(0), Y(1), @@ -4863,6 +4699,8 @@ enum Projection { }; } +typedef TRenderTicker = ffi.Int; +typedef DartTRenderTicker = int; typedef FilamentRenderCallback = ffi.Pointer>; typedef FilamentRenderCallbackFunction = ffi.Void Function( 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 fd5b9625..a8bc6fe3 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 @@ -4,11 +4,16 @@ import 'dart:math'; import 'dart:typed_data'; import 'package:animation_tools_dart/animation_tools_dart.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_gizmo.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'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_scene.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_swapchain.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_texture.dart'; +import 'package:thermion_dart/src/viewer/src/filament/filament.dart'; +import 'package:thermion_dart/src/viewer/src/shared_types/config.dart'; +import 'package:thermion_dart/src/viewer/src/shared_types/layers.dart'; import 'package:vector_math/vector_math_64.dart'; import 'package:vector_math/vector_math_64.dart' as v64; import '../../../../utils/src/matrix.dart'; @@ -19,84 +24,24 @@ import 'callbacks.dart'; import 'ffi_camera.dart'; import 'ffi_view.dart'; -class FFIBindings { - final Pointer sceneManager; - final Pointer engine; - final Pointer unlitMaterialProvider; - final Pointer ubershaderMaterialProvider; - final Pointer transformManager; - final Pointer lightManager; - final Pointer renderableManager; - final Pointer viewer; - final Pointer animationManager; - final Pointer nameComponentManager; - final Pointer renderer; - - FFIBindings( - {required this.renderer, - required this.sceneManager, - required this.engine, - required this.unlitMaterialProvider, - required this.ubershaderMaterialProvider, - required this.transformManager, - required this.lightManager, - required this.renderableManager, - required this.viewer, - required this.animationManager, - required this.nameComponentManager}); -} - -// ignore: constant_identifier_names -const ThermionEntity FILAMENT_ASSET_ERROR = 0; - -typedef RenderCallback = Pointer)>>; - +/// +/// +/// class ThermionViewerFFI extends ThermionViewer { final _logger = Logger("ThermionViewerFFI"); - Pointer? _sceneManager; - Pointer? _engine; - Pointer? _unlitMaterialProvider; - Pointer? _ubershaderMaterialProvider; - Pointer? _transformManager; - Pointer? _lightManager; - Pointer? _renderableManager; - Pointer? _viewer; - Pointer? _animationManager; - Pointer? _nameComponentManager; - - late FFIBindings bindings; - final String? uberArchivePath; - final _initialized = Completer(); Future get initialized => _initialized.future; - final Pointer resourceLoader; - - var _driver = nullptr.cast(); - - late final RenderCallback _renderCallback; - var _renderCallbackOwner = nullptr.cast(); - - var _sharedContext = nullptr.cast(); - late NativeCallable _onPickResultCallable; - /// - /// - /// - ThermionViewerFFI( - {RenderCallback? renderCallback, - Pointer? renderCallbackOwner, - required this.resourceLoader, - Pointer? driver, - Pointer? sharedContext, - this.uberArchivePath}) { - this._renderCallbackOwner = renderCallbackOwner ?? nullptr; - this._renderCallback = renderCallback ?? nullptr; - this._driver = driver ?? nullptr; - this._sharedContext = sharedContext ?? nullptr; + late final FFIFilamentApp app; + late final FFIRenderTarget? renderTarget; + /// + /// + /// + ThermionViewerFFI(this.app, {this.renderTarget}) { _onPickResultCallable = NativeCallable.listener(_onPickResult); @@ -107,49 +52,21 @@ class ThermionViewerFFI extends ThermionViewer { /// /// Future createRenderTarget(int width, int height, - {int? colorTextureHandle, int? depthTextureHandle}) async { + {covariant FFITexture? color, covariant FFITexture? depth}) async { final renderTarget = await withPointerCallback((cb) { - Viewer_createRenderTargetRenderThread(_viewer!, colorTextureHandle ?? 0, - depthTextureHandle ?? 0, width, height, cb); + RenderTarget_createRenderThread(app.engine, width, height, + color?.pointer ?? nullptr, depth?.pointer ?? nullptr, cb); }); - return FFIRenderTarget(renderTarget, _viewer!, _engine!); - } - - /// - /// - /// - @override - Future destroyRenderTarget(FFIRenderTarget renderTarget) async { - if (_disposing || _viewer == null) { - _logger.info( - "Viewer is being (or has been) disposed; this will clean up all render targets."); - } else { - await withVoidCallback((cb) { - Viewer_destroyRenderTargetRenderThread( - _viewer!, renderTarget.renderTarget, cb); - }); - } - } - - /// - /// - /// - Future createView() async { - var view = await withPointerCallback((cb) { - Viewer_createViewRenderThread(_viewer!, cb); - }); - if (view == nullptr) { - throw Exception("Failed to create view"); - } - return FFIView(view, _viewer!, _engine!); + return FFIRenderTarget(renderTarget, app); } /// /// /// Future setViewportAndCameraProjection(double width, double height) async { - var mainView = FFIView(Viewer_getViewAt(_viewer!, 0), _viewer!, _engine!); + var mainView = + FFIView(Viewer_getViewAt(_viewer!, 0), _viewer!, app.engine!); mainView.setViewport(width.toInt(), height.toInt()); final cameraCount = await getCameraCount(); @@ -175,86 +92,25 @@ class ThermionViewerFFI extends ThermionViewer { } } - /// - /// - /// - Future createHeadlessSwapChain(int width, int height) async { - var swapChain = await withPointerCallback((callback) { - return Viewer_createHeadlessSwapChainRenderThread( - _viewer!, width, height, callback); - }); - return FFISwapChain(swapChain, _viewer!); - } - - /// - /// - /// - Future createSwapChain(int surface) async { - var swapChain = await withPointerCallback((callback) { - return Viewer_createSwapChainRenderThread( - _viewer!, Pointer.fromAddress(surface), callback); - }); - return FFISwapChain(swapChain, _viewer!); - } - - /// - /// - /// - Future destroySwapChain(SwapChain swapChain) async { - if (_viewer != null) { - await withVoidCallback((callback) { - Viewer_destroySwapChainRenderThread( - _viewer!, (swapChain as FFISwapChain).swapChain, callback); - }); - } - } + late final FFIView view; + late final FFIScene scene; + late final FFICamera camera; Future _initialize() async { _logger.info("Initializing ThermionViewerFFI"); - - Viewer_destroyOnRenderThread(nullptr); - - RenderLoop_destroy(); - RenderLoop_create(); - - final uberarchivePtr = - uberArchivePath?.toNativeUtf8(allocator: allocator).cast() ?? - nullptr; - _viewer = await withPointerCallback( - (Pointer)>> callback) { - Viewer_createOnRenderThread(_sharedContext, _driver, uberarchivePtr, - resourceLoader, _renderCallback, _renderCallbackOwner, callback); - }); - - allocator.free(uberarchivePtr); - if (_viewer!.address == 0) { - throw Exception("Failed to create viewer. Check logs for details"); + view = FFIView( + await withPointerCallback( + (cb) => Engine_createViewRenderThread(app.engine, cb)), + app); + scene = FFIScene(Engine_createScene(app.engine), app); + await view.setScene(scene); + camera = FFICamera( + await withPointerCallback( + (cb) => Engine_createCameraRenderThread(app.engine, cb)), + app); + if (renderTarget != null) { + await view.setRenderTarget(renderTarget); } - - _sceneManager = Viewer_getSceneManager(_viewer!); - _unlitMaterialProvider = - SceneManager_getUnlitMaterialProvider(_sceneManager!); - _ubershaderMaterialProvider = - SceneManager_getUbershaderMaterialProvider(_sceneManager!); - _engine = Viewer_getEngine(_viewer!); - _transformManager = Engine_getTransformManager(_engine!); - _lightManager = Engine_getLightManager(_engine!); - _animationManager = SceneManager_getAnimationManager(_sceneManager!); - _nameComponentManager = - SceneManager_getNameComponentManager(_sceneManager!); - _renderableManager = Engine_getRenderableManager(_engine!); - bindings = FFIBindings( - sceneManager: _sceneManager!, - engine: _engine!, - unlitMaterialProvider: _unlitMaterialProvider!, - ubershaderMaterialProvider: _ubershaderMaterialProvider!, - transformManager: _transformManager!, - lightManager: _lightManager!, - renderableManager: _renderableManager!, - viewer: _viewer!, - animationManager: _animationManager!, - nameComponentManager: _nameComponentManager!, - renderer: Viewer_getRenderer(_viewer!)); this._initialized.complete(true); } @@ -272,32 +128,24 @@ class ThermionViewerFFI extends ThermionViewer { @override Future setRendering(bool render) async { _rendering = render; - // await withVoidCallback((cb) { - // set_rendering_render_thread(_viewer!, render, cb); - // }); } /// /// /// @override - Future render({FFISwapChain? swapChain}) async { - final view = (await getViewAt(0)) as FFIView; - swapChain ??= FFISwapChain(Viewer_getSwapChainAt(_viewer!, 0), _viewer!); - Viewer_renderRenderThread(_viewer!, view.view, swapChain.swapChain); + Future render() async { + RenderTicker_renderRenderThread(app.renderTicker, 0); + // Viewer_renderRenderThread(_viewer!, view.view, swapChain.swapChain); } /// /// /// @override - Future> capture( - List<({View view, SwapChain? swapChain, RenderTarget? renderTarget})> - targets) async { - var renderer = Viewer_getRenderer(_viewer!); - + Future capture() async { final fence = await withPointerCallback((cb) { - Engine_createFenceRenderThread(_engine!, cb); + Engine_createFenceRenderThread(app.engine!, cb); }); var pixelBuffers = []; @@ -337,11 +185,11 @@ class ThermionViewerFFI extends ThermionViewer { }); await withVoidCallback((cb) { - Engine_flushAndWaitRenderThead(_engine!, cb); + Engine_flushAndWaitRenderThead(app.engine!, cb); }); await withVoidCallback((cb) { - Engine_destroyFenceRenderThread(_engine!, fence, cb); + Engine_destroyFenceRenderThread(app.engine!, fence, cb); }); // await withVoidCallback((cb) { @@ -400,9 +248,6 @@ class ThermionViewerFFI extends ThermionViewer { await mInstance.dispose(); } await destroyLights(); - Viewer_destroyOnRenderThread(_viewer!); - - RenderLoop_destroy(); _sceneManager = null; _viewer = null; @@ -410,7 +255,7 @@ class ThermionViewerFFI extends ThermionViewer { for (final callback in _onDispose) { await callback.call(); } - + await app.destroy(); _onDispose.clear(); _disposing = false; } @@ -635,7 +480,7 @@ class ThermionViewerFFI extends ThermionViewer { } var thermionAsset = FFIAsset( - asset, _sceneManager!, _engine!, _unlitMaterialProvider!, this); + asset, _sceneManager!, app.engine!, _unlitMaterialProvider!, this); return thermionAsset; } @@ -675,7 +520,7 @@ class ThermionViewerFFI extends ThermionViewer { throw Exception("An error occurred loading GLB from buffer"); } return FFIAsset( - assetPtr, _sceneManager!, _engine!, _unlitMaterialProvider!, this); + assetPtr, _sceneManager!, app.engine!, _unlitMaterialProvider!, this); } /// @@ -697,7 +542,7 @@ class ThermionViewerFFI extends ThermionViewer { } return FFIAsset( - assetPtr, _sceneManager!, _engine!, _unlitMaterialProvider!, this); + assetPtr, _sceneManager!, app.engine!, _unlitMaterialProvider!, this); } /// @@ -1780,7 +1625,7 @@ class ThermionViewerFFI extends ThermionViewer { } var asset = FFIAsset( - assetPtr, _sceneManager!, _engine!, _unlitMaterialProvider!, this); + assetPtr, _sceneManager!, app.engine!, _unlitMaterialProvider!, this); return asset; } @@ -1841,7 +1686,7 @@ class ThermionViewerFFI extends ThermionViewer { /// @override Future setPriority(ThermionEntity entityId, int priority) async { - RenderableManager_setPriority(_renderableManager!, entityId, priority); + RenderableManager_setPriority(app.renderableManager, entityId, priority); } /// @@ -1899,7 +1744,7 @@ class ThermionViewerFFI extends ThermionViewer { } }); _grid = FFIAsset( - ptr, _sceneManager!, _engine!, _unlitMaterialProvider!, this); + ptr, _sceneManager!, app.engine!, _unlitMaterialProvider!, this); } await _grid!.addToScene(); await setLayerVisibility(VisibilityLayers.OVERLAY, true); @@ -1929,7 +1774,7 @@ class ThermionViewerFFI extends ThermionViewer { var bitmask = flags.fold(0, (a, b) => a | b.index); final texturePtr = await withPointerCallback((cb) { Texture_buildRenderThread( - _engine!, + app.engine!, width, height, depth, @@ -1944,7 +1789,7 @@ class ThermionViewerFFI extends ThermionViewer { throw Exception("Failed to create texture"); } return FFITexture( - _engine!, + app.engine!, texturePtr, ); } @@ -1958,7 +1803,6 @@ class ThermionViewerFFI extends ThermionViewer { double anisotropy = 0.0, TextureCompareMode compareMode = TextureCompareMode.NONE, TextureCompareFunc compareFunc = TextureCompareFunc.LESS_EQUAL}) async { - return FFITextureSampler(TextureSampler_create()); final samplerPtr = TextureSampler_create(); TextureSampler_setMinFilter( samplerPtr, TSamplerMinFilter.values[minFilter.index]); @@ -2011,9 +1855,10 @@ class ThermionViewerFFI extends ThermionViewer { /// Future createMaterial(Uint8List data) async { var ptr = await withPointerCallback((cb) { - Engine_buildMaterialRenderThread(_engine!, data.address, data.length, cb); + Engine_buildMaterialRenderThread( + app.engine!, data.address, data.length, cb); }); - return FFIMaterial(ptr, _engine!, _sceneManager!); + return FFIMaterial(ptr, app.engine!, _sceneManager!); } /// @@ -2098,7 +1943,7 @@ class ThermionViewerFFI extends ThermionViewer { final materialInstance = await withPointerCallback((cb) { MaterialProvider_createMaterialInstanceRenderThread( - _ubershaderMaterialProvider!, key.address, cb); + app.ubershaderMaterialProvider, key.address, cb); }); if (materialInstance == nullptr) { throw Exception("Failed to create material instance"); @@ -2148,7 +1993,7 @@ class ThermionViewerFFI extends ThermionViewer { Future getMaterialInstanceAt( ThermionEntity entity, int index) async { final instancePtr = RenderableManager_getMaterialInstanceAt( - _renderableManager!, entity, index); + app.renderableManager, entity, index); final instance = FFIMaterialInstance(instancePtr, _sceneManager!); return instance; @@ -2254,7 +2099,7 @@ class ThermionViewerFFI extends ThermionViewer { if (view == nullptr) { throw Exception("Failed to get view"); } - return FFIView(view, _viewer!, _engine!); + return FFIView(view, _viewer!, app.engine!); } @override @@ -2278,7 +2123,7 @@ class ThermionViewerFFI extends ThermionViewer { view, gizmo.cast(), _sceneManager!, - _engine!, + app.engine!, nullptr, this, gizmoEntities.toSet() @@ -2289,14 +2134,15 @@ class ThermionViewerFFI extends ThermionViewer { /// /// Future setCastShadows(ThermionEntity entity, bool castShadows) async { - RenderableManager_setCastShadows(_renderableManager!, entity, castShadows); + RenderableManager_setCastShadows( + app.renderableManager, entity, castShadows); } /// /// /// Future isCastShadowsEnabled(ThermionEntity entity) async { - return RenderableManager_isShadowCaster(_renderableManager!, entity); + return RenderableManager_isShadowCaster(app.renderableManager, entity); } /// @@ -2304,14 +2150,14 @@ class ThermionViewerFFI extends ThermionViewer { /// Future setReceiveShadows(ThermionEntity entity, bool receiveShadows) async { RenderableManager_setReceiveShadows( - _renderableManager!, entity, receiveShadows); + app.renderableManager, entity, receiveShadows); } /// /// /// Future isReceiveShadowsEnabled(ThermionEntity entity) async { - return RenderableManager_isShadowReceiver(_renderableManager!, entity); + return RenderableManager_isShadowReceiver(app.renderableManager, entity); } /// @@ -2319,8 +2165,7 @@ class ThermionViewerFFI extends ThermionViewer { /// Future setClearOptions( Vector4 clearColor, int clearStencil, bool clear, bool discard) async { - final renderer = Viewer_getRenderer(_viewer!); - Renderer_setClearOptions(renderer, clearColor.r, clearColor.g, clearColor.b, - clearColor.a, clearStencil, clear, discard); + Renderer_setClearOptions(app.renderer, clearColor.r, clearColor.g, + clearColor.b, clearColor.a, clearStencil, clear, discard); } } diff --git a/thermion_dart/lib/src/viewer/src/filament/filament.dart b/thermion_dart/lib/src/viewer/src/filament/filament.dart new file mode 100644 index 00000000..a9889e9a --- /dev/null +++ b/thermion_dart/lib/src/viewer/src/filament/filament.dart @@ -0,0 +1,78 @@ +import 'package:thermion_dart/src/viewer/src/shared_types/engine.dart'; +import 'package:thermion_dart/thermion_dart.dart'; + +class FilamentConfig { + final Backend backend; + final T? renderCallback; + final U? renderCallbackOwner; + final U resourceLoader; + final U? platform; + final U? driver; + final U? sharedContext; + final String uberArchivePath; + final int stereoscopicEyeCount; + final bool disableHandleUseAfterFreeCheck; + + FilamentConfig( + {required this.backend, + required this.resourceLoader, + required this.uberArchivePath, + this.renderCallback, + this.renderCallbackOwner, + this.platform, + this.driver, + this.sharedContext, + this.stereoscopicEyeCount = 1, + this.disableHandleUseAfterFreeCheck = false}); +} + +abstract class FilamentApp { + final T engine; + final T gltfAssetLoader; + final T gltfResourceLoader; + final T renderer; + final T transformManager; + final T lightManager; + final T renderableManager; + final T ubershaderMaterialProvider; + + FilamentApp( + {required this.engine, + required this.gltfAssetLoader, + required this.gltfResourceLoader, + required this.renderer, + required this.transformManager, + required this.lightManager, + required this.renderableManager, + required this.ubershaderMaterialProvider + }); + + /// + /// + /// + Future createHeadlessSwapChain(int width, int height, + {bool hasStencilBuffer = false}); + + /// + /// + /// + Future createSwapChain(T handle, {bool hasStencilBuffer = false}); + + /// + /// + /// + Future destroySwapChain(SwapChain swapChain); + + /// + /// + /// + Future destroy(); + + + /// + /// + /// + Future createRenderTarget( + int width, int height, { covariant Texture? color, covariant Texture? depth }); + +} diff --git a/thermion_dart/lib/src/viewer/src/shared_types/config.dart b/thermion_dart/lib/src/viewer/src/shared_types/config.dart new file mode 100644 index 00000000..e69de29b diff --git a/thermion_dart/lib/src/viewer/src/shared_types/engine.dart b/thermion_dart/lib/src/viewer/src/shared_types/engine.dart new file mode 100644 index 00000000..396cd016 --- /dev/null +++ b/thermion_dart/lib/src/viewer/src/shared_types/engine.dart @@ -0,0 +1,28 @@ +enum Backend { + /// !< Automatically selects an appropriate driver for the platform. + DEFAULT(0), + + /// !< Selects the OpenGL/ES driver (default on Android) + OPENGL(1), + + /// !< Selects the Vulkan driver if the platform supports it (default on Linux/Windows) + VULKAN(2), + + /// !< Selects the Metal driver if the platform supports it (default on MacOS/iOS). + METAL(3), + + /// !< Selects the no-op driver for testing purposes. + NOOP(4); + + final int value; + const Backend(this.value); + + static Backend fromValue(int value) => switch (value) { + 0 => DEFAULT, + 1 => OPENGL, + 2 => VULKAN, + 3 => METAL, + 4 => NOOP, + _ => throw ArgumentError("Unknown value for TBackend: $value"), + }; +} \ No newline at end of file diff --git a/thermion_dart/lib/src/viewer/src/shared_types/entity.dart b/thermion_dart/lib/src/viewer/src/shared_types/entity.dart index e69de29b..f9e8b651 100644 --- a/thermion_dart/lib/src/viewer/src/shared_types/entity.dart +++ b/thermion_dart/lib/src/viewer/src/shared_types/entity.dart @@ -0,0 +1,3 @@ +import 'package:thermion_dart/thermion_dart.dart'; + +final ThermionEntity FILAMENT_ENTITY_NULL = 0; \ No newline at end of file diff --git a/thermion_dart/lib/src/viewer/src/shared_types/layers.dart b/thermion_dart/lib/src/viewer/src/shared_types/layers.dart new file mode 100644 index 00000000..0a901f97 --- /dev/null +++ b/thermion_dart/lib/src/viewer/src/shared_types/layers.dart @@ -0,0 +1,18 @@ +const double kNear = 0.05; +const double kFar = 1000.0; +const double kFocalLength = 28.0; + +enum VisibilityLayers { + DEFAULT_ASSET(0), + LAYER_1(1), + LAYER_2(2), + LAYER_3(3), + LAYER_4(4), + LAYER_5(5), + BACKGROUND(6), + OVERLAY(7); + + final int value; + const VisibilityLayers(this.value); +} + diff --git a/thermion_dart/lib/src/viewer/src/shared_types/render_target.dart b/thermion_dart/lib/src/viewer/src/shared_types/render_target.dart index 3a03b11a..ce837f4c 100644 --- a/thermion_dart/lib/src/viewer/src/shared_types/render_target.dart +++ b/thermion_dart/lib/src/viewer/src/shared_types/render_target.dart @@ -3,4 +3,5 @@ import 'package:thermion_dart/thermion_dart.dart'; abstract class RenderTarget { Future getColorTexture(); Future getDepthTexture(); + Future destroy(); } diff --git a/thermion_dart/lib/src/viewer/src/shared_types/scene.dart b/thermion_dart/lib/src/viewer/src/shared_types/scene.dart new file mode 100644 index 00000000..1d8fbda6 --- /dev/null +++ b/thermion_dart/lib/src/viewer/src/shared_types/scene.dart @@ -0,0 +1,4 @@ + +abstract class Scene { + +} 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 ff922596..33c30a0d 100644 --- a/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart +++ b/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart @@ -1,3 +1,5 @@ +import 'package:thermion_dart/src/viewer/src/shared_types/layers.dart'; + import '../../utils/src/gizmo.dart'; import 'shared_types/shared_types.dart'; export 'shared_types/shared_types.dart'; @@ -8,32 +10,12 @@ import 'package:vector_math/vector_math_64.dart'; import 'dart:async'; import 'package:animation_tools_dart/animation_tools_dart.dart'; -const double kNear = 0.05; -const double kFar = 1000.0; -const double kFocalLength = 28.0; - -enum VisibilityLayers { - DEFAULT_ASSET(0), - LAYER_1(1), - LAYER_2(2), - LAYER_3(3), - LAYER_4(4), - LAYER_5(5), - BACKGROUND(6), - OVERLAY(7); - - final int value; - const VisibilityLayers(this.value); -} - -final ThermionEntity FILAMENT_ENTITY_NULL = 0; - +/// +/// A high-level interface for interacting with a 3D scene. +/// This broadly maps to a single scene/view +/// abstract class ThermionViewer { - /// - /// A Future that resolves when the underlying rendering context has been successfully created. - /// - Future get initialized; - + /// /// Whether the controller is currently rendering at [framerate]. /// @@ -47,7 +29,7 @@ abstract class ThermionViewer { /// /// Render a single frame immediately. /// - Future render({covariant SwapChain? swapChain}); + Future render(); /// /// Requests a single frame to be rendered. This is only intended to be used internally. @@ -60,31 +42,6 @@ abstract class ThermionViewer { Future> capture( covariant List<({View view, SwapChain? swapChain, RenderTarget? renderTarget})> targets); - /// - /// - /// - Future createHeadlessSwapChain(int width, int height); - - /// - /// - /// - Future createSwapChain(int handle); - - /// - /// - /// - Future destroySwapChain(covariant SwapChain swapChain); - - /// - /// - /// - Future createRenderTarget( - int width, int height, { int? colorTextureHandle, int? depthTextureHandle }); - - /// - /// - /// - Future destroyRenderTarget(covariant RenderTarget renderTarget); /// /// 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 b25bd826..b16ea582 100644 --- a/thermion_dart/lib/src/viewer/src/thermion_viewer_stub.dart +++ b/thermion_dart/lib/src/viewer/src/thermion_viewer_stub.dart @@ -312,12 +312,6 @@ class ThermionViewerStub extends ThermionViewer { throw UnimplementedError(); } - @override - Future setBloom(double bloom) { - // TODO: implement setBloom - throw UnimplementedError(); - } - @override Future setBoneTransform( ThermionEntity entity, int boneIndex, Matrix4 transform, @@ -768,12 +762,6 @@ class ThermionViewerStub extends ThermionViewer { throw UnimplementedError(); } - @override - Future createRenderTarget(int width, int height, int textureHandle) { - // TODO: implement createRenderTarget - throw UnimplementedError(); - } - @override Future setRenderTarget(covariant RenderTarget renderTarget) { // TODO: implement setRenderTarget @@ -799,13 +787,7 @@ class ThermionViewerStub extends ThermionViewer { // TODO: implement createHeadlessSwapChain throw UnimplementedError(); } - - @override - Future capture({covariant SwapChain? swapChain, covariant View? view, covariant RenderTarget? renderTarget}) { - // TODO: implement capture - throw UnimplementedError(); - } - + @override Future createSwapChain(handle) { // TODO: implement createSwapChain @@ -1089,6 +1071,88 @@ class ThermionViewerStub extends ThermionViewer { // TODO: implement setParent throw UnimplementedError(); } + + @override + Future createImage(int width, int height, int channels) { + // TODO: implement createImage + throw UnimplementedError(); + } + + @override + Future createTexture(int width, int height, {int depth = 1, int levels = 1, TextureSamplerType textureSamplerType = TextureSamplerType.SAMPLER_2D, TextureFormat textureFormat = TextureFormat.RGBA32F}) { + // TODO: implement createTexture + throw UnimplementedError(); + } + + @override + Future createTextureSampler({TextureMinFilter minFilter = TextureMinFilter.LINEAR, TextureMagFilter magFilter = TextureMagFilter.LINEAR, TextureWrapMode wrapS = TextureWrapMode.CLAMP_TO_EDGE, TextureWrapMode wrapT = TextureWrapMode.CLAMP_TO_EDGE, TextureWrapMode wrapR = TextureWrapMode.CLAMP_TO_EDGE, double anisotropy = 0.0, TextureCompareMode compareMode = TextureCompareMode.NONE, TextureCompareFunc compareFunc = TextureCompareFunc.LESS_EQUAL}) { + // TODO: implement createTextureSampler + throw UnimplementedError(); + } + + @override + Future decodeImage(Uint8List data) { + // TODO: implement decodeImage + throw UnimplementedError(); + } + + @override + Future destroyCamera(covariant Camera camera) { + // TODO: implement destroyCamera + throw UnimplementedError(); + } + + @override + Future isCastShadowsEnabled(ThermionEntity entity) { + // TODO: implement isCastShadowsEnabled + throw UnimplementedError(); + } + + @override + Future isReceiveShadowsEnabled(ThermionEntity entity) { + // TODO: implement isReceiveShadowsEnabled + throw UnimplementedError(); + } + + @override + // TODO: implement msPerFrame + double get msPerFrame => throw UnimplementedError(); + + @override + Future setCastShadows(ThermionEntity entity, bool castShadows) { + // TODO: implement setCastShadows + throw UnimplementedError(); + } + + @override + Future setClearOptions(Vector4 clearColor, int clearStencil, bool clear, bool discard) { + // TODO: implement setClearOptions + throw UnimplementedError(); + } + + @override + Future setReceiveShadows(ThermionEntity entity, bool receiveShadows) { + // TODO: implement setReceiveShadows + throw UnimplementedError(); + } + + @override + Future> capture(covariant List<({RenderTarget? renderTarget, SwapChain? swapChain, View view})> targets) { + // TODO: implement capture + throw UnimplementedError(); + } + + @override + Future createRenderTarget(int width, int height, {int? colorTextureHandle, int? depthTextureHandle}) { + // TODO: implement createRenderTarget + throw UnimplementedError(); + } + + @override + Future setBloom(bool enabled, double strength) { + // TODO: implement setBloom + throw UnimplementedError(); + } } diff --git a/thermion_dart/lib/src/viewer/src/web_wasm/src/material_instance.dart b/thermion_dart/lib/src/viewer/src/web_wasm/src/material_instance.dart index af6ac402..685c74d4 100644 --- a/thermion_dart/lib/src/viewer/src/web_wasm/src/material_instance.dart +++ b/thermion_dart/lib/src/viewer/src/web_wasm/src/material_instance.dart @@ -1,3 +1,5 @@ +import 'package:vector_math/vector_math_64.dart'; + import '../../../viewer.dart'; class ThermionWasmMaterialInstance extends MaterialInstance { @@ -94,4 +96,52 @@ class ThermionWasmMaterialInstance extends MaterialInstance { // TODO: implement setStencilWriteEnabled throw UnimplementedError(); } + + @override + Future dispose() { + // TODO: implement dispose + throw UnimplementedError(); + } + + @override + Future setParameterBool(String name, bool value) { + // TODO: implement setParameterBool + throw UnimplementedError(); + } + + @override + Future setParameterFloat3(String name, double x, double y, double z) { + // TODO: implement setParameterFloat3 + throw UnimplementedError(); + } + + @override + Future setParameterFloat3Array(String name, List data) { + // TODO: implement setParameterFloat3Array + throw UnimplementedError(); + } + + @override + Future setParameterTexture(String name, covariant Texture texture, covariant TextureSampler sampler) { + // TODO: implement setParameterTexture + throw UnimplementedError(); + } + + @override + Future setStencilReadMask(int mask) { + // TODO: implement setStencilReadMask + throw UnimplementedError(); + } + + @override + Future setStencilWriteMask(int mask) { + // TODO: implement setStencilWriteMask + throw UnimplementedError(); + } + + @override + Future setTransparencyMode(TransparencyMode mode) { + // TODO: implement setTransparencyMode + throw UnimplementedError(); + } } diff --git a/thermion_dart/lib/src/viewer/src/web_wasm/src/thermion_viewer_wasm.dart b/thermion_dart/lib/src/viewer/src/web_wasm/src/thermion_viewer_wasm.dart index 0779c135..0329028c 100644 --- a/thermion_dart/lib/src/viewer/src/web_wasm/src/thermion_viewer_wasm.dart +++ b/thermion_dart/lib/src/viewer/src/web_wasm/src/thermion_viewer_wasm.dart @@ -121,7 +121,7 @@ // [context!, loader, null, uberArchivePath?.toJS].toJS, // null) as JSNumber; // await createSwapChain(width.ceil(), height.ceil()); -// updateViewportAndCameraProjection(width.ceil(), height.ceil(), 1.0); +// setViewportAndCameraProjection(width.ceil(), height.ceil(), 1.0); // _sceneManager = _module!.ccall("get_scene_manager", "void*", // ["void*".toJS].toJS, [_viewer!].toJS, null) as JSNumber; @@ -177,7 +177,7 @@ // [_viewer!].toJS, null); // } -// void updateViewportAndCameraProjection( +// void setViewportAndCameraProjection( // int width, int height, double scaleFactor) { // if (width == 0 || height == 0) { // throw Exception("Width/height must be greater than zero"); diff --git a/thermion_dart/native/include/FilamentViewer.hpp b/thermion_dart/native/include/FilamentViewer.hpp deleted file mode 100644 index 0ebd8596..00000000 --- a/thermion_dart/native/include/FilamentViewer.hpp +++ /dev/null @@ -1,176 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "ResourceBuffer.hpp" -#include "scene/SceneManager.hpp" -#include "ThreadPool.hpp" - -namespace thermion -{ - - typedef std::chrono::time_point time_point_t; - - using namespace std::chrono; - using namespace gltfio; - using namespace camutils; - - class FilamentViewer - { - - typedef int32_t EntityId; - - public: - FilamentViewer(const void *context, const ResourceLoaderWrapperImpl *const resourceLoaderWrapper, void *const platform = nullptr, const char *uberArchivePath = nullptr); - ~FilamentViewer(); - - View* createView(); - View* getViewAt(int index); - - void loadSkybox(const char *const skyboxUri); - void removeSkybox(); - - void loadIbl(const char *const iblUri, float intensity); - void removeIbl(); - void rotateIbl(const math::mat3f &matrix); - void createIbl(float r, float g, float b, float intensity); - - void render( - uint64_t frameTimeInNanos - ); - void setFrameInterval(float interval); - - void setMainCamera(View *view); - EntityId getMainCamera(); - - float getCameraFov(bool horizontal); - void setCameraFov(double fovDegrees, bool horizontal); - - SwapChain* createSwapChain(const void *surface); - SwapChain* createSwapChain(uint32_t width, uint32_t height); - void destroySwapChain(SwapChain* swapChain); - - RenderTarget* createRenderTarget(intptr_t colorTextureId, intptr_t depthTextureId, uint32_t width, uint32_t height); - void destroyRenderTarget(RenderTarget* renderTarget); - - Renderer *getRenderer(); - - std::map> _renderable; - - void setRenderable(View* view, SwapChain* swapChain, bool renderable); - - void setBackgroundColor(const float r, const float g, const float b, const float a); - void setBackgroundImage(const char *resourcePath, bool fillHeight, uint32_t width, uint32_t height); - void clearBackgroundImage(); - void setBackgroundImagePosition(float x, float y, bool clamp, uint32_t width, uint32_t height); - - Engine* getEngine() { - return _engine; - } - - - - 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)()); - - SceneManager *const getSceneManager() - { - return (SceneManager *const)_sceneManager; - } - - SwapChain* getSwapChainAt(int index) { - if(index < _swapChains.size()) { - return _swapChains[index]; - } - Log("Error: index %d is greater than available swapchains", index); - return nullptr; - } - - private: - const ResourceLoaderWrapperImpl *const _resourceLoaderWrapper; - Scene *_scene = nullptr; - Engine *_engine = nullptr; - thermion::ThreadPool *_tp = nullptr; - Renderer *_renderer = nullptr; - SceneManager *_sceneManager = nullptr; - std::vector _renderTargets; - std::vector _swapChains; - std::vector _views; - - std::mutex _renderMutex; // mutex to ensure thread safety when removing assets - - Texture *_skyboxTexture = nullptr; - Skybox *_skybox = nullptr; - Texture *_iblTexture = nullptr; - IndirectLight *_indirectLight = nullptr; - - float _frameInterval = 1000.0 / 60.0; - - // Camera properties - Camera *_mainCamera = nullptr; // the default camera added to every scene. If you want the *active* camera, access via View. - - // background image properties - uint32_t _imageHeight = 0; - uint32_t _imageWidth = 0; - filament::math::mat4f _imageScale; - Texture *_imageTexture = nullptr; - Texture *_dummyImageTexture = nullptr; - utils::Entity _imageEntity; - VertexBuffer *_imageVb = nullptr; - IndexBuffer *_imageIb = nullptr; - Material *_imageMaterial = nullptr; - TextureSampler _imageSampler; - void loadKtx2Texture(std::string path, ResourceBuffer data); - void loadKtxTexture(std::string path, ResourceBuffer data); - void loadPngTexture(std::string path, ResourceBuffer data); - void loadTextureFromPath(std::string path); - void savePng(void *data, size_t size, int frameNumber); - void createBackgroundImage(); - - - time_point_t _fpsCounterStartTime = std::chrono::high_resolution_clock::now(); - - - std::mutex _imageMutex; - double _cumulativeAnimationUpdateTime = 0; - int _frameCount = 0; - int _skippedFrames = 0; - }; - - struct FrameCallbackData - { - FilamentViewer *viewer; - uint32_t frameNumber; - }; - -} diff --git a/thermion_dart/native/include/RenderTicker.hpp b/thermion_dart/native/include/RenderTicker.hpp new file mode 100644 index 00000000..33676c0c --- /dev/null +++ b/thermion_dart/native/include/RenderTicker.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "scene/SceneManager.hpp" + +namespace thermion +{ + + typedef std::chrono::time_point time_point_t; + + using namespace std::chrono; + + class RenderTicker + { + + public: + RenderTicker(filament::Renderer renderer, thermion::SceneManager sceneManager) : mRenderer(renderer), mSceneManager(sceneManager) { } + ~RenderTicker(); + + void render( + uint64_t frameTimeInNanos + ); + void setRenderable(SwapChain *swapChain, View **view, uint8_t numViews); + + private: + std::mutex mMutex; + Renderer *mRenderer = nullptr; + SceneManager *mSceneManager = nullptr; + std::vector mSwapChains; + std::map> mRenderable; + + }; + + +} diff --git a/thermion_dart/native/include/c_api/APIBoundaryTypes.h b/thermion_dart/native/include/c_api/APIBoundaryTypes.h index 486d9fb8..d2e818ca 100644 --- a/thermion_dart/native/include/c_api/APIBoundaryTypes.h +++ b/thermion_dart/native/include/c_api/APIBoundaryTypes.h @@ -8,7 +8,7 @@ extern "C" #include #include "APIExport.h" - + typedef TRenderTicker TRenderTicker; typedef int32_t EntityId; typedef struct TCamera TCamera; typedef struct TEngine TEngine; @@ -110,6 +110,11 @@ extern "C" double z; } double3; + typedef struct { + double3 col1; + double3 col2; + double3 col3; + } double3x3; typedef struct { double x; diff --git a/thermion_dart/native/include/c_api/TEngine.h b/thermion_dart/native/include/c_api/TEngine.h index 49a89cdd..03ff3300 100644 --- a/thermion_dart/native/include/c_api/TEngine.h +++ b/thermion_dart/native/include/c_api/TEngine.h @@ -21,10 +21,11 @@ enum TBackend { BACKEND_NOOP = 4, //!< Selects the no-op driver for testing purposes. }; -EMSCRIPTEN_KEEPALIVE TEngine *Engine_create(TBackend backend); +EMSCRIPTEN_KEEPALIVE TEngine *Engine_create(TBackend backend, void* platform, void* sharedContext, uint8_t stereoscopicEyeCount, bool disableHandleUseAfterFreeCheck); EMSCRIPTEN_KEEPALIVE TRenderer *Engine_createRenderer(TEngine *tEngine); EMSCRIPTEN_KEEPALIVE TSwapChain *Engine_createSwapChain(TEngine *tEngine, void *window, uint64_t flags); EMSCRIPTEN_KEEPALIVE TSwapChain *Engine_createHeadlessSwapChain(TEngine *tEngine, uint32_t width, uint32_t height, uint64_t flags); +EMSCRIPTEN_KEEPALIVE void Engine_destroySwapChain(TEngine *tEngine, TSwapChain *tSwapChain); EMSCRIPTEN_KEEPALIVE TCamera *Engine_createCamera(TEngine* tEngine); EMSCRIPTEN_KEEPALIVE TView *Engine_createView(TEngine *tEngine); diff --git a/thermion_dart/native/include/c_api/TGltfAssetLoader.h b/thermion_dart/native/include/c_api/TGltfAssetLoader.h index 8a804aa8..51881b57 100644 --- a/thermion_dart/native/include/c_api/TGltfAssetLoader.h +++ b/thermion_dart/native/include/c_api/TGltfAssetLoader.h @@ -23,6 +23,7 @@ EMSCRIPTEN_KEEPALIVE TFilamentAsset *GltfAssetLoader_load( uint8_t numInstances ); EMSCRIPTEN_KEEPALIVE TMaterialInstance *GltfAssetLoader_getMaterialInstance(TRenderableManager *tRenderableManager, TFilamentAsset *tAsset); +EMSCRIPTEN_KEEPALIVE TMaterialProvider *GltfAssetLoader_getMaterialProvider(TGltfAssetLoader *tAssetLoader); #ifdef __cplusplus } diff --git a/thermion_dart/native/include/c_api/TIndirectLight.h b/thermion_dart/native/include/c_api/TIndirectLight.h new file mode 100644 index 00000000..86680383 --- /dev/null +++ b/thermion_dart/native/include/c_api/TIndirectLight.h @@ -0,0 +1,19 @@ +#pragma once + +#include "APIExport.h" +#include "APIBoundaryTypes.h" +#include "TMaterialInstance.h" +#include "TTexture.h" +#include "ResourceBuffer.hpp" +#include "MathUtils.hpp" + +#ifdef __cplusplus +extern "C" +{ +#endif + +EMSCRIPTEN_KEEPALIVE void IndirectLight_setRotation(TIndirectLight TIndirectLight, double3x3 rotation); + +#ifdef __cplusplus +} +#endif diff --git a/thermion_dart/native/include/c_api/TRenderTarget.h b/thermion_dart/native/include/c_api/TRenderTarget.h index 04775929..0e4f3993 100644 --- a/thermion_dart/native/include/c_api/TRenderTarget.h +++ b/thermion_dart/native/include/c_api/TRenderTarget.h @@ -21,6 +21,11 @@ EMSCRIPTEN_KEEPALIVE TRenderTarget *RenderTarget_create( TTexture *depth ); +EMSCRIPTEN_KEEPALIVE void RenderTarget_destroy( + TEngine *tEngine, + TRenderTarget *tRenderTarget +); + #ifdef __cplusplus } #endif diff --git a/thermion_dart/native/include/c_api/TRenderTicker.h b/thermion_dart/native/include/c_api/TRenderTicker.h new file mode 100644 index 00000000..754c5f64 --- /dev/null +++ b/thermion_dart/native/include/c_api/TRenderTicker.h @@ -0,0 +1,17 @@ +#pragma once + +#include "APIExport.h" +#include "APIBoundaryTypes.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + EMSCRIPTEN_KEEPALIVE TRenderTicker *RenderTicker_create(TRenderer *tRenderer, TSceneManager *tSceneManager); + EMSCRIPTEN_KEEPALIVE void RenderTicker_render(TRenderTicker *tRenderTicker, uint64_t frameTimeInNanos); + EMSCRIPTEN_KEEPALIVE void RenderTicker_setRenderable(TRenderTicker *tFilamentRender, TSwapChain *swapChain, TView **views, uint8_t numViews); + +#ifdef __cplusplus +} +#endif diff --git a/thermion_dart/native/include/c_api/TRenderer.h b/thermion_dart/native/include/c_api/TRenderer.h index 32e4dc1d..a84cd5dc 100644 --- a/thermion_dart/native/include/c_api/TRenderer.h +++ b/thermion_dart/native/include/c_api/TRenderer.h @@ -23,6 +23,13 @@ EMSCRIPTEN_KEEPALIVE void Renderer_readPixels( TPixelDataType tPixelDataType, uint8_t *out ); +EMSCRIPTEN_KEEPALIVE void Renderer_setFrameInterval( + TRenderer *tRenderer, + float headRoomRatio, + float scaleRate, + uint8_t history, + uint8_t interval +); diff --git a/thermion_dart/native/include/c_api/ThermionDartApi.h b/thermion_dart/native/include/c_api/ThermionDartApi.h deleted file mode 100644 index 0fa0306c..00000000 --- a/thermion_dart/native/include/c_api/ThermionDartApi.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef _FLUTTER_FILAMENT_API_H -#define _FLUTTER_FILAMENT_API_H - -#include "APIExport.h" -#include "APIBoundaryTypes.h" -#include "TMaterialInstance.h" - -#include "ResourceBuffer.hpp" -#include "MathUtils.hpp" - -#ifdef __cplusplus -extern "C" -{ -#endif - - EMSCRIPTEN_KEEPALIVE TViewer *Viewer_create(const void *const context, const void *const loader, void *const platform, const char *uberArchivePath); - EMSCRIPTEN_KEEPALIVE TRenderer *Viewer_getRenderer(TViewer *tViewer); - - EMSCRIPTEN_KEEPALIVE void Viewer_destroy(TViewer *viewer); - EMSCRIPTEN_KEEPALIVE TSceneManager *Viewer_getSceneManager(TViewer *viewer); - EMSCRIPTEN_KEEPALIVE TRenderTarget* Viewer_createRenderTarget(TViewer *viewer, intptr_t colorTextureId, intptr_t depthTextureId, uint32_t width, uint32_t height); - EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTarget(TViewer *viewer, TRenderTarget* tRenderTarget); - EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createSwapChain(TViewer *viewer, const void *const window); - EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createHeadlessSwapChain(TViewer *viewer, uint32_t width, uint32_t height); - EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChain(TViewer *viewer, TSwapChain* swapChain); - EMSCRIPTEN_KEEPALIVE void Viewer_render( - TViewer *viewer); - EMSCRIPTEN_KEEPALIVE void Viewer_capture( - TViewer *viewer, - TView *view, - TSwapChain *swapChain, - uint8_t *pixelBuffer, - bool useFence, - void (*callback)(void)); - EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTarget( - TViewer *viewer, - TView *view, - TSwapChain *swapChain, - TRenderTarget *renderTarget, - uint8_t *pixelBuffer, - bool useFence, - void (*callback)(void)); - EMSCRIPTEN_KEEPALIVE TView* Viewer_createView(TViewer *viewer); - EMSCRIPTEN_KEEPALIVE TView* Viewer_getViewAt(TViewer *viewer, int index); - EMSCRIPTEN_KEEPALIVE void Viewer_setMainCamera(TViewer *tViewer, TView *tView); - EMSCRIPTEN_KEEPALIVE TSwapChain* Viewer_getSwapChainAt(TViewer *tViewer, int index); - EMSCRIPTEN_KEEPALIVE void Viewer_setViewRenderable(TViewer *viewer, TSwapChain *swapChain, TView* view, bool renderable); - - // Engine - EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer* viewer); - - - EMSCRIPTEN_KEEPALIVE void clear_background_image(TViewer *viewer); - EMSCRIPTEN_KEEPALIVE void set_background_image(TViewer *viewer, const char *path, bool fillHeight); - EMSCRIPTEN_KEEPALIVE void set_background_image_position(TViewer *viewer, float x, float y, bool clamp); - EMSCRIPTEN_KEEPALIVE void set_background_color(TViewer *viewer, const float r, const float g, const float b, const float a); - - EMSCRIPTEN_KEEPALIVE EntityId Viewer_getMainCamera(TViewer *viewer); - EMSCRIPTEN_KEEPALIVE void Viewer_loadSkybox(TViewer *viewer, const char *skyboxPath); - EMSCRIPTEN_KEEPALIVE void Viewer_removeSkybox(TViewer *viewer); - EMSCRIPTEN_KEEPALIVE void Viewer_loadIbl(TViewer *viewer, const char *iblPath, float intensity); - EMSCRIPTEN_KEEPALIVE void Viewer_removeIbl(TViewer *viewer); - EMSCRIPTEN_KEEPALIVE void create_ibl(TViewer *viewer, float r, float g, float b, float intensity); - EMSCRIPTEN_KEEPALIVE void rotate_ibl(TViewer *viewer, float *rotationMatrix); - - - EMSCRIPTEN_KEEPALIVE void set_frame_interval(TViewer *viewer, float interval); - - EMSCRIPTEN_KEEPALIVE void queue_relative_position_update_world_axis(TSceneManager *sceneManager, EntityId entity, float viewportX, float viewportY, float x, float y, float z); - EMSCRIPTEN_KEEPALIVE void queue_position_update_from_viewport_coords(TSceneManager *sceneManager, TView *view, EntityId entity, float viewportX, float viewportY); - - EMSCRIPTEN_KEEPALIVE void ios_dummy(); - EMSCRIPTEN_KEEPALIVE void thermion_flutter_free(void *ptr); - EMSCRIPTEN_KEEPALIVE void add_collision_component(TSceneManager *sceneManager, EntityId entityId, void (*callback)(const EntityId entityId1, const EntityId entityId2), bool affectsCollidingTransform); - EMSCRIPTEN_KEEPALIVE void remove_collision_component(TSceneManager *sceneManager, EntityId entityId); - - EMSCRIPTEN_KEEPALIVE void test_collisions(TSceneManager *sceneManager, EntityId entity); - - EMSCRIPTEN_KEEPALIVE Aabb2 get_bounding_box(TSceneManager *sceneManager, TView *view, EntityId entity); - EMSCRIPTEN_KEEPALIVE void get_bounding_box_to_out(TSceneManager *sceneManager, TView *view, EntityId entity, float *minX, float *minY, float *maxX, float *maxY); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h b/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h index f376b4f6..d020cf01 100644 --- a/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h +++ b/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h @@ -1,7 +1,5 @@ -#ifndef _DART_FILAMENT_FFI_API_H -#define _DART_FILAMENT_FFI_API_H +#pragma once -#include "ThermionDartApi.h" #include "TView.h" #include "TTexture.h" #include "TMaterialProvider.h" @@ -13,49 +11,30 @@ namespace thermion { #endif - /// - /// This header replicates most of the methods in ThermionDartApi.h. - /// It represents the interface for: - /// - invoking those methods that must be called on the main Filament engine thread - /// - setting up a render loop - /// typedef int32_t EntityId; typedef void (*FilamentRenderCallback)(void *const owner); EMSCRIPTEN_KEEPALIVE void RenderLoop_create(); EMSCRIPTEN_KEEPALIVE void RenderLoop_destroy(); - EMSCRIPTEN_KEEPALIVE void Viewer_createOnRenderThread( - void *const context, - void *const platform, - const char *uberArchivePath, - const void *const loader, - void (*renderCallback)(void *const renderCallbackOwner), - void *const renderCallbackOwner, - void (*callback)(TViewer *viewer)); - EMSCRIPTEN_KEEPALIVE void Viewer_createViewRenderThread(TViewer *viewer, void (*onComplete)(TView *tView)); - EMSCRIPTEN_KEEPALIVE void Viewer_destroyOnRenderThread(TViewer *viewer); - EMSCRIPTEN_KEEPALIVE void Viewer_createSwapChainRenderThread(TViewer *viewer, void *const surface, void (*onComplete)(TSwapChain *)); - EMSCRIPTEN_KEEPALIVE void Viewer_createHeadlessSwapChainRenderThread(TViewer *viewer, uint32_t width, uint32_t height, void (*onComplete)(TSwapChain *)); - EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChainRenderThread(TViewer *viewer, TSwapChain *swapChain, void (*onComplete)()); - EMSCRIPTEN_KEEPALIVE void Viewer_renderRenderThread(TViewer *viewer, TView *view, TSwapChain *swapChain); - EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderThread(TViewer *viewer, TView *view, TSwapChain *swapChain, uint8_t *out, bool useFence, void (*onComplete)()); - EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTargetRenderThread(TViewer *viewer, TView *view, TSwapChain *swapChain, TRenderTarget *renderTarget, uint8_t *out, bool useFence, void (*onComplete)()); - EMSCRIPTEN_KEEPALIVE void Viewer_requestFrameRenderThread(TViewer *viewer, void (*onComplete)()); - EMSCRIPTEN_KEEPALIVE void Viewer_loadIblRenderThread(TViewer *viewer, const char *iblPath, float intensity, void (*onComplete)()); - EMSCRIPTEN_KEEPALIVE void Viewer_removeIblRenderThread(TViewer *viewer, void (*onComplete)()); - EMSCRIPTEN_KEEPALIVE void Viewer_createRenderTargetRenderThread(TViewer *viewer, intptr_t colorTexture, intptr_t depthTexture, uint32_t width, uint32_t height, void (*onComplete)(TRenderTarget *)); - EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTargetRenderThread(TViewer *viewer, TRenderTarget *tRenderTarget, void (*onComplete)()); - EMSCRIPTEN_KEEPALIVE void Viewer_loadSkyboxRenderThread(TViewer *viewer, const char *skyboxPath, void (*onComplete)()); - EMSCRIPTEN_KEEPALIVE void Viewer_removeSkyboxRenderThread(TViewer *viewer, void (*onComplete)()); + EMSCRIPTEN_KEEPALIVE void RenderTicker_renderRenderThread(TRenderTicker *tRenderTicker, uint64_t frameTimeInNanos,); + // EMSCRIPTEN_KEEPALIVE void RenderLoop_addTask(TRenderLoop* tRenderLoop, void (*task)()); - EMSCRIPTEN_KEEPALIVE void Engine_createRenderThread(TBackend backend, void (*onComplete)(TEngine *)); + EMSCRIPTEN_KEEPALIVE void Engine_createRenderThread( + TBackend backend, + void* platform, + void* sharedContext, + uint8_t stereoscopicEyeCount, + bool disableHandleUseAfterFreeCheck, + void (*onComplete)(TEngine *) + ); EMSCRIPTEN_KEEPALIVE void Engine_createRendererRenderThread(TEngine *tEngine, void (*onComplete)(TRenderer *)); EMSCRIPTEN_KEEPALIVE void Engine_createSwapChainRenderThread(TEngine *tEngine, void *window, uint64_t flags, void (*onComplete)(TSwapChain *)); EMSCRIPTEN_KEEPALIVE void Engine_createHeadlessSwapChainRenderThread(TEngine *tEngine, uint32_t width, uint32_t height, uint64_t flags, void (*onComplete)(TSwapChain *)); EMSCRIPTEN_KEEPALIVE void Engine_createCameraRenderThread(TEngine* tEngine, void (*onComplete)(TCamera *)); EMSCRIPTEN_KEEPALIVE void Engine_createViewRenderThread(TEngine *tEngine, void (*onComplete)(TView *)); EMSCRIPTEN_KEEPALIVE void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t *materialData, size_t length, void (*onComplete)(TMaterial *)); + EMSCRIPTEN_KEEPALIVE void Engine_destroySwapChainRenderThread(TEngine *tEngine, TSwapChain *tSwapChain, void (*onComplete)()); EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialRenderThread(TEngine *tEngine, TMaterial *tMaterial, void (*onComplete)()); EMSCRIPTEN_KEEPALIVE void Engine_destroySkyboxRenderThread(TEngine *tEngine, TSkybox *tSkybox, void (*onComplete)()); EMSCRIPTEN_KEEPALIVE void Engine_destroyIndirectLightRenderThread(TEngine *tEngine, TIndirectLight *tIndirectLight, void (*onComplete)()); @@ -98,13 +77,6 @@ namespace thermion EMSCRIPTEN_KEEPALIVE void View_setCameraRenderThread(TView *tView, TCamera *tCamera, void (*callback)()); FilamentRenderCallback make_render_callback_fn_pointer(FilamentRenderCallback); - EMSCRIPTEN_KEEPALIVE void set_rendering_render_thread(TViewer *viewer, bool rendering, void (*onComplete)()); - - EMSCRIPTEN_KEEPALIVE void set_frame_interval_render_thread(TViewer *viewer, float frameInterval); - EMSCRIPTEN_KEEPALIVE void set_background_color_render_thread(TViewer *viewer, const float r, const float g, const float b, const float a); - EMSCRIPTEN_KEEPALIVE void clear_background_image_render_thread(TViewer *viewer); - EMSCRIPTEN_KEEPALIVE void set_background_image_render_thread(TViewer *viewer, const char *path, bool fillHeight, void (*onComplete)()); - EMSCRIPTEN_KEEPALIVE void set_background_image_position_render_thread(TViewer *viewer, float x, float y, bool clamp); EMSCRIPTEN_KEEPALIVE void SceneManager_createGridRenderThread(TSceneManager *tSceneManager, TMaterial *tMaterial, void (*callback)(TSceneAsset *)); @@ -323,7 +295,7 @@ namespace thermion int boneIndex, const float *const transform, void (*callback)(bool)); - EMSCRIPTEN_KEEPALIVE void set_post_processing_render_thread(TViewer *viewer, bool enabled); + EMSCRIPTEN_KEEPALIVE void reset_to_rest_pose_render_thread(TSceneManager *sceneManager, EntityId entityId, void (*callback)()); EMSCRIPTEN_KEEPALIVE void GltfAssetLoader_createRenderThread(TEngine *tEngine, TMaterialProvider *tMaterialProvider, void (*callback)(TGltfAssetLoader *)); @@ -345,4 +317,3 @@ namespace thermion } #endif -#endif // _DART_FILAMENT_FFI_API_H diff --git a/thermion_dart/native/include/rendering/RenderLoop.hpp b/thermion_dart/native/include/rendering/RenderLoop.hpp new file mode 100644 index 00000000..0dfc956a --- /dev/null +++ b/thermion_dart/native/include/rendering/RenderLoop.hpp @@ -0,0 +1,87 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "RenderTicker.hpp" + +namespace thermion { + +/** + * @brief A render loop implementation that manages rendering on a separate thread. + * + * This class handles frame rendering requests, viewer creation, and maintains + * a task queue for rendering operations. + */ +class RenderLoop { +public: + /** + * @brief Constructs a new RenderLoop and starts the render thread. + */ + explicit RenderLoop(); + + /** + * @brief Destroys the RenderLoop and stops the render thread. + */ + ~RenderLoop(); + + /** + * @brief Requests a frame to be rendered. + * + * @param callback Callback function to be called after rendering completes + */ + void requestFrame(void (*callback)()); + + /** + * @brief Sets the render ticker used. + */ + void setRenderTicker(RenderTicker *renderTicker) { + mRenderTicker = renderTicker; + } + + /** + * @brief Adds a task to the render thread's task queue. + * + * @param pt The packaged task to be executed + * @return std::future Future for the task result + */ + template + auto add_task(std::packaged_task& pt) -> std::future; + +private: + /** + * @brief Main iteration of the render loop. + */ + void iter(); + + void (*_requestFrameRenderCallback)() = nullptr; + bool _stop = false; + std::mutex _mutex; + std::mutex _taskMutex; + std::condition_variable _cv; + std::deque> _tasks; + std::chrono::high_resolution_clock::time_point _lastFrameTime; + int _frameCount = 0; + float _accumulatedTime = 0.0f; + float _fps = 0.0f; + std::thread* t = nullptr; + RenderTicker* mRenderTicker = nullptr; +}; + +// Template implementation +template +auto RenderLoop::add_task(std::packaged_task& pt) -> std::future { + std::unique_lock lock(_taskMutex); + auto ret = pt.get_future(); + _tasks.push_back([pt = std::make_shared>( + std::move(pt))] + { (*pt)(); }); + _cv.notify_one(); + return ret; +} + +} // namespace thermion \ No newline at end of file diff --git a/thermion_dart/native/src/RenderTicker.cpp b/thermion_dart/native/src/RenderTicker.cpp new file mode 100644 index 00000000..11625aac --- /dev/null +++ b/thermion_dart/native/src/RenderTicker.cpp @@ -0,0 +1,103 @@ +#if __APPLE__ +#include "TargetConditionals.h" +#endif + +#ifdef _WIN32 +#pragma comment(lib, "Ws2_32.lib") +#endif + +#include +#include +#include +#include +#ifdef __EMSCRIPTEN__ +#include +#include +#include +#include +#include +#include +#endif +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Log.hpp" + +#include "RenderTicker.hpp" + +namespace thermion +{ + + using namespace filament; + using namespace filament::math; + using namespace utils; + using namespace std::chrono; + + using std::string; + + static constexpr filament::math::float4 sFullScreenTriangleVertices[3] = { + {-1.0f, -1.0f, 1.0f, 1.0f}, + {3.0f, -1.0f, 1.0f, 1.0f}, + {-1.0f, 3.0f, 1.0f, 1.0f}}; + + static const uint16_t sFullScreenTriangleIndices[3] = {0, 1, 2}; + + void RenderTicker::setRenderable(SwapChain *swapChain, View **views, uint8_t numViews) { + { + + std::lock_guard lock(mMutex); + + auto swapChainViews = mRenderable[swapChain]; + + swapChainViews.clear(); + for(int i = 0; i < numViews; i++) { + swapChainViews.push_back(views[i]); + } + + mRenderable[swapChain] = swapChainViews; + } + + void RenderTicker::render(uint64_t frameTimeInNanos) + { + std::lock_guard lock(mMutex); + + mSceneManager->update(); + + for (auto swapChain : mSwapChains) + { + auto views = mRenderable[swapChain]; + if (views.size() > 0) + { + bool beginFrame = mRenderer->beginFrame(swapChain, frameTimeInNanos); + if (beginFrame) + { + for (auto view : views) + { + mRenderer->render(view); + } + } + mRenderer->endFrame(); + } + } +#ifdef __EMSCRIPTEN__ + _engine->execute(); +#endif + } + + +} // namespace thermion diff --git a/thermion_dart/native/src/c_api/TEngine.cpp b/thermion_dart/native/src/c_api/TEngine.cpp index 34b1e483..9ff4fc82 100644 --- a/thermion_dart/native/src/c_api/TEngine.cpp +++ b/thermion_dart/native/src/c_api/TEngine.cpp @@ -44,9 +44,17 @@ namespace thermion uint64_t TSWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER = filament::backend::SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER; uint64_t TSWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER = filament::backend::SWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER; - EMSCRIPTEN_KEEPALIVE TEngine *Engine_create(TBackend backend) + EMSCRIPTEN_KEEPALIVE TEngine *Engine_create( + TBackend backend, + void* platform, + void* sharedContext, + uint8_t stereoscopicEyeCount, + bool disableHandleUseAfterFreeCheck) { - auto *engine = filament::Engine::create(static_cast(backend)); + filament::Engine::Config config; + config.stereoscopicEyeCount = stereoscopicEyeCount; + config.disableHandleUseAfterFreeCheck = disableHandleUseAfterFreeCheck; + auto *engine = filament::Engine::create(static_cast(backend), platform, sharedContext, &config); return reinterpret_cast(engine); } @@ -71,6 +79,12 @@ namespace thermion return reinterpret_cast(swapChain); } + EMSCRIPTEN_KEEPALIVE void Engine_destroySwapChain(TEngine *tEngine, TSwapChain *tSwapChain) { + auto *engine = reinterpret_cast(tEngine); + auto *swapChain = reinterpret_cast(tSwapChain); + engine->destroy(swapChain); + } + EMSCRIPTEN_KEEPALIVE TView *Engine_createView(TEngine *tEngine) { auto *engine = reinterpret_cast(tEngine); @@ -279,12 +293,21 @@ namespace thermion EMSCRIPTEN_KEEPALIVE void Engine_destroySkybox(TEngine *tEngine, TSkybox *tSkybox) { auto *engine = reinterpret_cast(tEngine); auto *skybox = reinterpret_cast(tSkybox); + if(skybox->getTexture()) { + engine->destroy(skybox->getTexture()); + } engine->destroy(skybox); } EMSCRIPTEN_KEEPALIVE void Engine_destroyIndirectLight(TEngine *tEngine, TIndirectLight *tIndirectLight) { auto *engine = reinterpret_cast(tEngine); auto *indirectLight = reinterpret_cast(tIndirectLight); + if(indirectLight->getReflectionsTexture()) { + engine->destroy(indirectLight->getReflectionsTexture()); + } + if(indirectLight->getIrradianceTexture()) { + engine->destroy(indirectLight->getIrradianceTexture()); + } engine->destroy(indirectLight); } diff --git a/thermion_dart/native/src/c_api/TGltfAssetLoader.cpp b/thermion_dart/native/src/c_api/TGltfAssetLoader.cpp index d9d0055e..c4479937 100644 --- a/thermion_dart/native/src/c_api/TGltfAssetLoader.cpp +++ b/thermion_dart/native/src/c_api/TGltfAssetLoader.cpp @@ -111,6 +111,12 @@ EMSCRIPTEN_KEEPALIVE TMaterialInstance *GltfAssetLoader_getMaterialInstance(TRen return reinterpret_cast(mi); } +EMSCRIPTEN_KEEPALIVE TMaterialProvider *GltfAssetLoader_getMaterialProvider(TGltfAssetLoader *tAssetLoader) { + auto *assetLoader = reinterpret_cast(tAssetLoader); + auto materialProvider = assetLoader->getMaterialProvider(); + return reinterpret_cast(&materialProvider); +} + #ifdef __cplusplus } } diff --git a/thermion_dart/native/src/c_api/TIndirectLight.cpp b/thermion_dart/native/src/c_api/TIndirectLight.cpp new file mode 100644 index 00000000..0e6cb2c0 --- /dev/null +++ b/thermion_dart/native/src/c_api/TIndirectLight.cpp @@ -0,0 +1,41 @@ +#include "c_api/TScene.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "Log.hpp" + +#ifdef __cplusplus +namespace thermion +{ + extern "C" + { + using namespace filament; +#endif + + EMSCRIPTEN_KEEPALIVE void IndirectLight_setRotation(TIndirectLight *tIndirectLight, double3x3 rotation) + { + auto *indirectLight = reinterpret_cast(tIndirectLight); + const filament::math::mat3f fRotation { + filament::math::float3 { rotation.col1.x, rotation.col1.y, rotation.col1.z }, + filament::math::float3 { rotation.col2.x, rotation.col2.y, rotation.col2.z }, + filament::math::float3 { rotation.col3.x, rotation.col3.y, rotation.col3.z }, + }; + indirectLight->setRotation(fRotation); + } + +#ifdef __cplusplus + } +} +#endif diff --git a/thermion_dart/native/src/c_api/TRenderTarget.cpp b/thermion_dart/native/src/c_api/TRenderTarget.cpp index 2f161c56..2bece247 100644 --- a/thermion_dart/native/src/c_api/TRenderTarget.cpp +++ b/thermion_dart/native/src/c_api/TRenderTarget.cpp @@ -34,6 +34,16 @@ namespace thermion return reinterpret_cast(rt); } + EMSCRIPTEN_KEEPALIVE void RenderTarget_destroy( + TEngine *tEngine, + TRenderTarget *tRenderTarget + ) { + auto engine = reinterpret_cast(tEngine); + auto *renderTarget = reinterpret_cast(tRenderTarget); + engine->destroy(renderTarget); + } + + #ifdef __cplusplus } diff --git a/thermion_dart/native/src/c_api/TRenderTicker.cpp b/thermion_dart/native/src/c_api/TRenderTicker.cpp new file mode 100644 index 00000000..a719658d --- /dev/null +++ b/thermion_dart/native/src/c_api/TRenderTicker.cpp @@ -0,0 +1,38 @@ +#ifdef _WIN32 +#include "ThermionWin32.h" +#endif + +#include +#include + +#ifdef __EMSCRIPTEN__ +#include +#endif + +#include "filament/LightManager.h" +#include "Log.hpp" + +using namespace thermion; + +extern "C" +{ +#include "c_api/TRenderTicker.hpp" + +EMSCRIPTEN_KEEPALIVE TRenderTicker *RenderTicker_create(TRenderer *tRenderer, TSceneManager *tSceneManager) { + auto *renderer = reinterpret_cast(tRenderer); + auto *sceneManager = reinterpret_cast(tSceneManager); + auto *renderTicker = new RenderTicker(renderer, sceneManager); + return reinterpret_cast(renderTicker); +} + +EMSCRIPTEN_KEEPALIVE void RenderTicker_render(TRenderTicker *tRenderTicker, uint64_t frameTimeInNanos) { + auto *renderTicker = reinterpret_cast + renderTicker->render(frameTimeInNanos); +} + +EMSCRIPTEN_KEEPALIVE void RenderTicker_setRenderable(TRenderTicker *tRenderTicker, TSwapChain *swapChain, TView **views, uint8_t numViews) { + auto *renderTicker = reinterpret_cast + renderTicker->setRenderable(swapChain, views, numViews); +} + +} diff --git a/thermion_dart/native/src/c_api/TRenderer.cpp b/thermion_dart/native/src/c_api/TRenderer.cpp index c3e99e4f..669afdf8 100644 --- a/thermion_dart/native/src/c_api/TRenderer.cpp +++ b/thermion_dart/native/src/c_api/TRenderer.cpp @@ -61,6 +61,22 @@ EMSCRIPTEN_KEEPALIVE void Renderer_renderStandaloneView(TRenderer *tRenderer, TV renderer->renderStandaloneView(view); } +EMSCRIPTEN_KEEPALIVE void Renderer_setFrameRateOptions( + TRenderer *tRenderer, + float headRoomRatio, + float scaleRate, + uint8_t history, + uint8_t interval +) { + auto *renderer = reinterpret_cast(tRenderer); + filament::Renderer::FrameRateOptions fro; + fro.headRoomRatio = headRoomRatio; + fro.scaleRate = scaleRate; + fro.interval = interval; + fro.interval = interval; + renderer->setFrameRateOptions(fro); +} + class CaptureCallbackHandler : public filament::backend::CallbackHandler { void post(void *user, Callback callback) diff --git a/thermion_dart/native/src/c_api/ThermionDartApi.cpp b/thermion_dart/native/src/c_api/ThermionDartApi.cpp deleted file mode 100644 index f3e9b213..00000000 --- a/thermion_dart/native/src/c_api/ThermionDartApi.cpp +++ /dev/null @@ -1,415 +0,0 @@ -#ifdef _WIN32 -#include "ThermionWin32.h" -#endif - -#include -#include - -#ifdef __EMSCRIPTEN__ -#include -#endif - -#include "filament/LightManager.h" -#include "ResourceBuffer.hpp" -#include "FilamentViewer.hpp" -#include "Log.hpp" -#include "ThreadPool.hpp" - -using namespace thermion; - -extern "C" -{ - -#include "c_api/ThermionDartApi.h" - - EMSCRIPTEN_KEEPALIVE TViewer *Viewer_create(const void *context, const void *const loader, void *const platform, const char *uberArchivePath) - { - const auto *loaderImpl = new ResourceLoaderWrapperImpl((ResourceLoaderWrapper *)loader); - auto viewer = new FilamentViewer(context, loaderImpl, platform, uberArchivePath); - return reinterpret_cast(viewer); - } - - EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer *viewer) - { - auto *engine = reinterpret_cast(viewer)->getEngine(); - return reinterpret_cast(engine); - } - - EMSCRIPTEN_KEEPALIVE TRenderer *Viewer_getRenderer(TViewer *tViewer) { - auto *viewer = reinterpret_cast(tViewer); - return reinterpret_cast(viewer->getRenderer()); - } - - EMSCRIPTEN_KEEPALIVE TRenderTarget *Viewer_createRenderTarget(TViewer *tViewer, intptr_t colorTexture, intptr_t depthTexture, uint32_t width, uint32_t height) - { - auto viewer = reinterpret_cast(tViewer); - auto renderTarget = viewer->createRenderTarget(colorTexture, depthTexture, width, height); - return reinterpret_cast(renderTarget); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTarget(TViewer *tViewer, TRenderTarget *tRenderTarget) - { - auto viewer = reinterpret_cast(tViewer); - auto renderTarget = reinterpret_cast(tRenderTarget); - viewer->destroyRenderTarget(renderTarget); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_destroy(TViewer *tViewer) - { - auto *viewer = reinterpret_cast(tViewer); - delete viewer; - } - - EMSCRIPTEN_KEEPALIVE void set_background_color(TViewer *viewer, const float r, const float g, const float b, const float a) - { - ((FilamentViewer *)viewer)->setBackgroundColor(r, g, b, a); - } - - EMSCRIPTEN_KEEPALIVE void clear_background_image(TViewer *viewer) - { - ((FilamentViewer *)viewer)->clearBackgroundImage(); - } - - EMSCRIPTEN_KEEPALIVE void set_background_image(TViewer *viewer, const char *path, bool fillHeight) - { - ((FilamentViewer *)viewer)->setBackgroundImage(path, fillHeight, 100, 100); - } - - EMSCRIPTEN_KEEPALIVE void set_background_image_position(TViewer *viewer, float x, float y, bool clamp) - { - ((FilamentViewer *)viewer)->setBackgroundImagePosition(x, y, clamp, 100, 100); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_loadSkybox(TViewer *viewer, const char *skyboxPath) - { - ((FilamentViewer *)viewer)->loadSkybox(skyboxPath); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_removeSkybox(TViewer *viewer) - { - ((FilamentViewer *)viewer)->removeSkybox(); - } - - EMSCRIPTEN_KEEPALIVE void create_ibl(TViewer *viewer, float r, float g, float b, float intensity) - { - ((FilamentViewer *)viewer)->createIbl(r, g, b, intensity); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_loadIbl(TViewer *viewer, const char *iblPath, float intensity) - { - ((FilamentViewer *)viewer)->loadIbl(iblPath, intensity); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_removeIbl(TViewer *viewer) - { - ((FilamentViewer *)viewer)->removeIbl(); - } - - EMSCRIPTEN_KEEPALIVE void rotate_ibl(TViewer *viewer, float *rotationMatrix) - { - math::mat3f matrix(rotationMatrix[0], rotationMatrix[1], - rotationMatrix[2], - rotationMatrix[3], - rotationMatrix[4], - rotationMatrix[5], - rotationMatrix[6], - rotationMatrix[7], - rotationMatrix[8]); - - ((FilamentViewer *)viewer)->rotateIbl(matrix); - } - - EMSCRIPTEN_KEEPALIVE int get_instance_count(TSceneManager *sceneManager, EntityId entityId) - { - return ((SceneManager *)sceneManager)->getInstanceCount(entityId); - } - - EMSCRIPTEN_KEEPALIVE void get_instances(TSceneManager *sceneManager, EntityId entityId, EntityId *out) - { - return ((SceneManager *)sceneManager)->getInstances(entityId, out); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_setMainCamera(TViewer *tViewer, TView *tView) - { - auto *viewer = reinterpret_cast(tViewer); - auto *view = reinterpret_cast(tView); - viewer->setMainCamera(view); - } - - EMSCRIPTEN_KEEPALIVE EntityId Viewer_getMainCamera(TViewer *viewer) - { - return ((FilamentViewer *)viewer)->getMainCamera(); - } - - EMSCRIPTEN_KEEPALIVE float get_camera_fov(TCamera *camera, bool horizontal) - { - auto cam = reinterpret_cast(camera); - return cam->getFieldOfViewInDegrees(horizontal ? Camera::Fov::HORIZONTAL : Camera::Fov::VERTICAL); - } - - EMSCRIPTEN_KEEPALIVE double get_camera_focal_length(TCamera *const camera) - { - auto cam = reinterpret_cast(camera); - return cam->getFocalLength(); - } - - EMSCRIPTEN_KEEPALIVE void set_camera_projection_from_fov(TCamera *camera, double fovInDegrees, double aspect, double near, double far, bool horizontal) - { - auto cam = reinterpret_cast(camera); - cam->setProjection(fovInDegrees, aspect, near, far, horizontal ? Camera::Fov::HORIZONTAL : Camera::Fov::VERTICAL); - } - - EMSCRIPTEN_KEEPALIVE double4x4 get_camera_model_matrix(TCamera *camera) - { - const auto &mat = reinterpret_cast(camera)->getModelMatrix(); - return convert_mat4_to_double4x4(mat); - } - - EMSCRIPTEN_KEEPALIVE double4x4 get_camera_view_matrix(TCamera *camera) - { - const auto &mat = reinterpret_cast(camera)->getViewMatrix(); - return convert_mat4_to_double4x4(mat); - } - - EMSCRIPTEN_KEEPALIVE double4x4 get_camera_projection_matrix(TCamera *camera) - { - const auto &mat = reinterpret_cast(camera)->getProjectionMatrix(); - return convert_mat4_to_double4x4(mat); - } - - EMSCRIPTEN_KEEPALIVE double4x4 get_camera_culling_projection_matrix(TCamera *camera) - { - const auto &mat = reinterpret_cast(camera)->getCullingProjectionMatrix(); - return convert_mat4_to_double4x4(mat); - } - - EMSCRIPTEN_KEEPALIVE void set_camera_projection_matrix(TCamera *camera, double4x4 matrix, double near, double far) - { - auto cam = reinterpret_cast(camera); - const auto &mat = convert_double4x4_to_mat4(matrix); - cam->setCustomProjection(mat, near, far); - } - - EMSCRIPTEN_KEEPALIVE void Camera_setLensProjection(TCamera *camera, double near, double far, double aspect, double focalLength) - { - auto cam = reinterpret_cast(camera); - cam->setLensProjection(focalLength, aspect, near, far); - } - - EMSCRIPTEN_KEEPALIVE void Camera_setModelMatrix(TCamera *camera, double4x4 matrix) - { - auto cam = reinterpret_cast(camera); - cam->setModelMatrix(convert_double4x4_to_mat4(matrix)); - } - - EMSCRIPTEN_KEEPALIVE double get_camera_near(TCamera *camera) - { - auto cam = reinterpret_cast(camera); - return cam->getNear(); - } - - EMSCRIPTEN_KEEPALIVE double get_camera_culling_far(TCamera *camera) - { - auto cam = reinterpret_cast(camera); - return cam->getCullingFar(); - } - - EMSCRIPTEN_KEEPALIVE const double *const get_camera_frustum(TCamera *camera) - { - - const auto frustum = reinterpret_cast(camera)->getFrustum(); - - const math::float4 *planes = frustum.getNormalizedPlanes(); - double *array = (double *)calloc(24, sizeof(double)); - for (int i = 0; i < 6; i++) - { - auto plane = planes[i]; - array[i * 4] = double(plane.x); - array[i * 4 + 1] = double(plane.y); - array[i * 4 + 2] = double(plane.z); - array[i * 4 + 3] = double(plane.w); - } - - return array; - } - - EMSCRIPTEN_KEEPALIVE void set_camera_focus_distance(TCamera *camera, float distance) - { - auto *cam = reinterpret_cast(camera); - cam->setFocusDistance(distance); - } - - EMSCRIPTEN_KEEPALIVE void set_camera_exposure(TCamera *camera, float aperture, float shutterSpeed, float sensitivity) - { - auto *cam = reinterpret_cast(camera); - cam->setExposure(aperture, shutterSpeed, sensitivity); - } - - EMSCRIPTEN_KEEPALIVE void set_camera_model_matrix(TCamera *camera, double4x4 matrix) - { - auto *cam = reinterpret_cast(camera); - const filament::math::mat4 &mat = convert_double4x4_to_mat4(matrix); - cam->setModelMatrix(mat); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_render( - TViewer *tViewer) - { - auto viewer = reinterpret_cast(tViewer); - viewer->render(0); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_setViewRenderable(TViewer *tViewer, TSwapChain *tSwapChain, TView *tView, bool renderable) - { - auto viewer = reinterpret_cast(tViewer); - auto swapChain = reinterpret_cast(tSwapChain); - auto *view = reinterpret_cast(tView); - viewer->setRenderable(view, swapChain, renderable); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_capture( - TViewer *tViewer, - TView *tView, - TSwapChain *tSwapChain, - uint8_t *pixelBuffer, - bool useFence, - void (*callback)(void)) - { -#ifdef __EMSCRIPTEN__ - useFence = true; -#endif - auto swapChain = reinterpret_cast(tSwapChain); - auto viewer = reinterpret_cast(tViewer); - auto *view = reinterpret_cast(tView); - viewer->capture(view, pixelBuffer, useFence, swapChain, callback); - }; - - EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTarget( - TViewer *tViewer, - TView *tView, - TSwapChain *tSwapChain, - TRenderTarget *tRenderTarget, - uint8_t *pixelBuffer, - bool useFence, - void (*callback)(void)) - { -#ifdef __EMSCRIPTEN__ - useFence = true; -#endif - auto swapChain = reinterpret_cast(tSwapChain); - auto renderTarget = reinterpret_cast(tRenderTarget); - auto viewer = reinterpret_cast(tViewer); - auto *view = reinterpret_cast(tView); - viewer->capture(view, pixelBuffer, useFence, swapChain, renderTarget, callback); - }; - - EMSCRIPTEN_KEEPALIVE void set_frame_interval( - TViewer *viewer, - float frameInterval) - { - ((FilamentViewer *)viewer)->setFrameInterval(frameInterval); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChain(TViewer *tViewer, TSwapChain *tSwapChain) - { - auto viewer = reinterpret_cast(tViewer); - auto swapChain = reinterpret_cast(tSwapChain); - viewer->destroySwapChain(swapChain); - } - - EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createHeadlessSwapChain(TViewer *tViewer, uint32_t width, uint32_t height) - { - auto viewer = reinterpret_cast(tViewer); - auto swapChain = viewer->createSwapChain(width, height); - return reinterpret_cast(swapChain); - } - - EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createSwapChain(TViewer *tViewer, const void *const window) - { - auto viewer = reinterpret_cast(tViewer); - auto swapChain = viewer->createSwapChain(window); - return reinterpret_cast(swapChain); - } - - EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_getSwapChainAt(TViewer *tViewer, int index) - { - auto viewer = reinterpret_cast(tViewer); - auto swapChain = viewer->getSwapChainAt(index); - return reinterpret_cast(swapChain); - } - - EMSCRIPTEN_KEEPALIVE TView *Viewer_createView(TViewer *tViewer) - { - auto viewer = reinterpret_cast(tViewer); - auto view = viewer->createView(); - return reinterpret_cast(view); - } - - EMSCRIPTEN_KEEPALIVE TView *Viewer_getViewAt(TViewer *tViewer, int32_t index) - { - auto viewer = reinterpret_cast(tViewer); - auto view = viewer->getViewAt(index); - return reinterpret_cast(view); - } - - EMSCRIPTEN_KEEPALIVE TSceneManager *Viewer_getSceneManager(TViewer *tViewer) - { - auto *viewer = reinterpret_cast(tViewer); - auto *sceneManager = viewer->getSceneManager(); - return reinterpret_cast(sceneManager); - } - - EMSCRIPTEN_KEEPALIVE void queue_position_update_from_viewport_coords(TSceneManager *sceneManager, TView *tView, EntityId entity, float viewportX, float viewportY) - { - auto *view = reinterpret_cast(tView); - ((SceneManager *)sceneManager)->queueRelativePositionUpdateFromViewportVector(view, entity, viewportX, viewportY); - } - - EMSCRIPTEN_KEEPALIVE void ios_dummy() - { - Log("Dummy called"); - } - - EMSCRIPTEN_KEEPALIVE void thermion_filament_free(void *ptr) - { - free(ptr); - } - - EMSCRIPTEN_KEEPALIVE void add_collision_component(TSceneManager *sceneManager, EntityId entityId, void (*onCollisionCallback)(const EntityId entityId1, const EntityId entityId2), bool affectsCollidingTransform) - { - ((SceneManager *)sceneManager)->addCollisionComponent(entityId, onCollisionCallback, affectsCollidingTransform); - } - - EMSCRIPTEN_KEEPALIVE void remove_collision_component(TSceneManager *sceneManager, EntityId entityId) - { - ((SceneManager *)sceneManager)->removeCollisionComponent(entityId); - } - - EMSCRIPTEN_KEEPALIVE void test_collisions(TSceneManager *sceneManager, EntityId entity) - { - ((SceneManager *)sceneManager)->testCollisions(entity); - } - - EMSCRIPTEN_KEEPALIVE Aabb2 get_bounding_box(TSceneManager *sceneManager, TView *tView, EntityId entity) - { - auto view = reinterpret_cast(tView); - return ((SceneManager *)sceneManager)->getScreenSpaceBoundingBox(view, entity); - } - - EMSCRIPTEN_KEEPALIVE void get_bounding_box_to_out(TSceneManager *sceneManager, TView *tView, EntityId entity, float *minX, float *minY, float *maxX, float *maxY) - { - auto view = reinterpret_cast(tView); - auto box = ((SceneManager *)sceneManager)->getScreenSpaceBoundingBox(view, entity); - *minX = box.minX; - *minY = box.minY; - *maxX = box.maxX; - *maxY = box.maxY; - } - - EMSCRIPTEN_KEEPALIVE void thermion_flutter_free(void *ptr) - { - free(ptr); - } - - -} diff --git a/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp b/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp index 04a8fa0a..b569322f 100644 --- a/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp +++ b/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp @@ -6,7 +6,6 @@ #include #include "c_api/APIBoundaryTypes.h" - #include "c_api/TAnimationManager.h" #include "c_api/TEngine.h" #include "c_api/TGltfAssetLoader.h" @@ -19,7 +18,8 @@ #include "c_api/TView.h" #include "c_api/ThermionDartRenderThreadApi.h" -#include "FilamentViewer.hpp" +#include "RenderTicker.hpp" +#include "rendering/RenderLoop.hpp" #include "Log.hpp" #include "ThreadPool.hpp" @@ -28,165 +28,6 @@ using namespace thermion; using namespace std::chrono_literals; #include -class RenderLoop -{ -public: - explicit RenderLoop() - { - srand(time(NULL)); - t = new std::thread([this]() - { start(); }); - } - - ~RenderLoop() - { - TRACE("Destroying RenderLoop"); - _stop = true; - _cv.notify_one(); - TRACE("Joining RenderLoop thread.."); - t->join(); - TRACE("RenderLoop destructor complete"); - } - - void start() - { - while (!_stop) - { - iter(); - } - } - - void destroyViewer() { - std::packaged_task lambda([=]() mutable - { - if(viewer) { - Viewer_destroy(viewer); - } - viewer = nullptr; - _renderCallback = nullptr; - _renderCallbackOwner = nullptr; - - }); - auto fut = add_task(lambda); - fut.wait(); - } - - void createViewer( - void *const context, - void *const platform, - const char *uberArchivePath, - const void *const loader, - void (*renderCallback)(void *), - void *const owner, - void (*callback)(TViewer *)) - { - _renderCallback = renderCallback; - _renderCallbackOwner = owner; - std::packaged_task lambda([=]() mutable - { - if(viewer) { - Viewer_destroy(viewer); - } - viewer = Viewer_create(context, loader, platform, uberArchivePath); - callback(viewer); }); - add_task(lambda); - } - - void requestFrame(void (*callback)()) - { - std::unique_lock lock(_mutex); - this->_requestFrameRenderCallback = callback; - _cv.notify_one(); - } - - void iter() - { - { - std::unique_lock lock(_mutex); - if (_requestFrameRenderCallback) - { - doRender(); - lock.unlock(); - this->_requestFrameRenderCallback(); - this->_requestFrameRenderCallback = nullptr; - - // Calculate and print FPS - auto currentTime = std::chrono::high_resolution_clock::now(); - float deltaTime = std::chrono::duration(currentTime - _lastFrameTime).count(); - _lastFrameTime = currentTime; - - _frameCount++; - _accumulatedTime += deltaTime; - - if (_accumulatedTime >= 1.0f) // Update FPS every second - { - _fps = _frameCount / _accumulatedTime; - // std::cout << "FPS: " << _fps << std::endl; - _frameCount = 0; - _accumulatedTime = 0.0f; - } - } - } - std::unique_lock taskLock(_taskMutex); - - if (!_tasks.empty()) - { - auto task = std::move(_tasks.front()); - _tasks.pop_front(); - taskLock.unlock(); - task(); - taskLock.lock(); - } - - _cv.wait_for(taskLock, std::chrono::microseconds(2000), [this] - { return !_tasks.empty() || _stop; }); - } - - void doRender() - { - Viewer_render(viewer); - if (_renderCallback) - { - _renderCallback(_renderCallbackOwner); - } - } - - void setFrameIntervalInMilliseconds(float frameIntervalInMilliseconds) - { - _frameIntervalInMicroseconds = static_cast(1000.0f * frameIntervalInMilliseconds); - } - - template - auto add_task(std::packaged_task &pt) -> std::future - { - std::unique_lock lock(_taskMutex); - auto ret = pt.get_future(); - _tasks.push_back([pt = std::make_shared>( - std::move(pt))] - { (*pt)(); }); - _cv.notify_one(); - return ret; - } - - TViewer *viewer = std::nullptr_t(); - -private: - void (*_requestFrameRenderCallback)() = nullptr; - bool _stop = false; - int _frameIntervalInMicroseconds = 1000000 / 60; - std::mutex _mutex; - std::mutex _taskMutex; - std::condition_variable _cv; - void (*_renderCallback)(void *const) = nullptr; - void *_renderCallbackOwner = nullptr; - std::deque> _tasks; - std::chrono::high_resolution_clock::time_point _lastFrameTime; - int _frameCount = 0; - float _accumulatedTime = 0.0f; - float _fps = 0.0f; - std::thread *t = nullptr; -}; - extern "C" { @@ -205,145 +46,21 @@ extern "C" TRACE("RenderLoop_destroy"); if (_rl) { - _rl->destroyViewer(); _rl = nullptr; } } - EMSCRIPTEN_KEEPALIVE void Viewer_createOnRenderThread( - void *const context, void *const platform, const char *uberArchivePath, - const void *const loader, - void (*renderCallback)(void *const renderCallbackOwner), - void *const renderCallbackOwner, - void (*callback)(TViewer *)) - { - TRACE("Viewer_createOnRenderThread"); - _rl->createViewer( - context, - platform, - uberArchivePath, - loader, - renderCallback, - renderCallbackOwner, - callback - ); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_destroyOnRenderThread(TViewer *viewer) - { - TRACE("Viewer_destroyOnRenderThread"); - if (!_rl) - { - Log("Warning - cannot destroy viewer, no RenderLoop has been created"); - } else { - _rl->destroyViewer(); - } - } - - EMSCRIPTEN_KEEPALIVE void Viewer_createViewRenderThread(TViewer *viewer, void (*onComplete)(TView *tView)) { + + EMSCRIPTEN_KEEPALIVE void RenderTicker_renderRenderThread(TRenderTicker *tRenderTicker, , uint64_t frameTimeInNanos, void (*onComplete)()) { std::packaged_task lambda( [=]() mutable { - auto *view = Viewer_createView(viewer); - onComplete(view); + RenderTicker_render(tRenderTicker, frameTimeInNanos); + onComplete(); }); auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void Viewer_createHeadlessSwapChainRenderThread(TViewer *viewer, - uint32_t width, - uint32_t height, - void (*onComplete)(TSwapChain *)) - { - std::packaged_task lambda( - [=]() mutable - { - auto *swapChain = Viewer_createHeadlessSwapChain(viewer, width, height); - onComplete(swapChain); - }); - auto fut = _rl->add_task(lambda); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_createSwapChainRenderThread(TViewer *viewer, - void *const surface, - void (*onComplete)(TSwapChain *)) - { - std::packaged_task lambda( - [=]() mutable - { - auto *swapChain = Viewer_createSwapChain(viewer, surface); - onComplete(swapChain); - }); - auto fut = _rl->add_task(lambda); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChainRenderThread(TViewer *viewer, TSwapChain *swapChain, void (*onComplete)()) - { - std::packaged_task lambda( - [=]() mutable - { - Viewer_destroySwapChain(viewer, swapChain); - onComplete(); - }); - auto fut = _rl->add_task(lambda); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_requestFrameRenderThread(TViewer *viewer, void (*onComplete)()) - { - if (!_rl) - { - Log("No render loop!"); // PANIC? - } - else - { - _rl->requestFrame(onComplete); - } - } - - EMSCRIPTEN_KEEPALIVE void Viewer_loadIblRenderThread(TViewer *viewer, const char *iblPath, float intensity, void (*onComplete)()) - { - std::packaged_task lambda( - [=]() mutable - { - Viewer_loadIbl(viewer, iblPath, intensity); - onComplete(); - }); - auto fut = _rl->add_task(lambda); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_removeIblRenderThread(TViewer *viewer, void (*onComplete)()) - { - std::packaged_task lambda( - [=]() mutable - { - Viewer_removeIbl(viewer); - onComplete(); - }); - auto fut = _rl->add_task(lambda); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_createRenderTargetRenderThread(TViewer *viewer, intptr_t colorTexture, intptr_t depthTexture, uint32_t width, uint32_t height, void (*onComplete)(TRenderTarget *)) - { - std::packaged_task lambda( - [=]() mutable - { - auto renderTarget = Viewer_createRenderTarget(viewer, colorTexture, depthTexture, width, height); - onComplete(renderTarget); - }); - auto fut = _rl->add_task(lambda); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTargetRenderThread(TViewer *tViewer, TRenderTarget *tRenderTarget, void (*onComplete)()) - { - std::packaged_task lambda( - [=]() mutable - { - Viewer_destroyRenderTarget(tViewer, tRenderTarget); - onComplete(); - }); - auto fut = _rl->add_task(lambda); - } - EMSCRIPTEN_KEEPALIVE void Engine_createRenderThread(TBackend backend, void (*onComplete)(TEngine *)) { std::packaged_task lambda( [=]() mutable @@ -383,6 +100,16 @@ extern "C" }); auto fut = _rl->add_task(lambda); } + + EMSCRIPTEN_KEEPALIVE void Engine_destroySwapChainRenderThread(TEngine *tEngine, TSwapChain *tSwapChain, void (*onComplete)()) { + std::packaged_task lambda( + [=]() mutable + { + Engine_destroySwapChain(tEngine); + onComplete(); + }); + auto fut = _rl->add_task(lambda); + } EMSCRIPTEN_KEEPALIVE void Engine_createCameraRenderThread(TEngine* tEngine, void (*onComplete)(TCamera *)) { std::packaged_task lambda( @@ -446,6 +173,7 @@ extern "C" auto fut = _rl->add_task(lambda); } + EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialRenderThread(TEngine *tEngine, TMaterial *tMaterial, void (*onComplete)()) { std::packaged_task lambda( @@ -592,15 +320,6 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void - set_frame_interval_render_thread(TViewer *viewer, float frameIntervalInMilliseconds) - { - _rl->setFrameIntervalInMilliseconds(frameIntervalInMilliseconds); - std::packaged_task lambda([=]() mutable - { ((FilamentViewer *)viewer)->setFrameInterval(frameIntervalInMilliseconds); }); - auto fut = _rl->add_task(lambda); - } - EMSCRIPTEN_KEEPALIVE void Viewer_renderRenderThread(TViewer *viewer, TView *tView, TSwapChain *tSwapChain) { std::packaged_task lambda([=]() mutable @@ -608,30 +327,6 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderThread(TViewer *viewer, TView *view, TSwapChain *tSwapChain, uint8_t *pixelBuffer, bool useFence, void (*onComplete)()) - { - std::packaged_task lambda([=]() mutable - { Viewer_capture(viewer, view, tSwapChain, pixelBuffer, useFence, onComplete); }); - auto fut = _rl->add_task(lambda); - } - - EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTargetRenderThread(TViewer *viewer, TView *view, TSwapChain *tSwapChain, TRenderTarget *tRenderTarget, uint8_t *pixelBuffer, bool useFence, void (*onComplete)()) - { - std::packaged_task lambda([=]() mutable - { Viewer_captureRenderTarget(viewer, view, tSwapChain, tRenderTarget, pixelBuffer, useFence, onComplete); }); - auto fut = _rl->add_task(lambda); - } - - EMSCRIPTEN_KEEPALIVE void - set_background_color_render_thread(TViewer *viewer, const float r, const float g, - const float b, const float a) - { - std::packaged_task lambda( - [=]() mutable - { set_background_color(viewer, r, g, b, a); }); - auto fut = _rl->add_task(lambda); - } - EMSCRIPTEN_KEEPALIVE void SceneManager_createGridRenderThread(TSceneManager *tSceneManager, TMaterial *tMaterial, void (*callback)(TSceneAsset *)) { std::packaged_task lambda([=]() mutable diff --git a/thermion_dart/native/src/rendering/RenderLoop.cpp b/thermion_dart/native/src/rendering/RenderLoop.cpp new file mode 100644 index 00000000..83f95ff5 --- /dev/null +++ b/thermion_dart/native/src/rendering/RenderLoop.cpp @@ -0,0 +1,83 @@ +#include "RenderLoop.hpp" + +#include +#include +#include + +#include "Log.hpp" + +namespace thermion { + +RenderLoop::RenderLoop() +{ + srand(time(NULL)); + t = new std::thread([this]() { + while (!_stop) { + iter(); + } + }); +} + +RenderLoop::~RenderLoop() +{ + TRACE("Destroying RenderLoop"); + _stop = true; + _cv.notify_one(); + TRACE("Joining RenderLoop thread.."); + t->join(); + delete t; + + TRACE("RenderLoop destructor complete"); +} + +void RenderLoop::requestFrame(void (*callback)()) +{ + std::unique_lock lock(_mutex); + this->_requestFrameRenderCallback = callback; + _cv.notify_one(); +} + +void RenderLoop::iter() +{ + { + std::unique_lock lock(_mutex); + if (_requestFrameRenderCallback) + { + mRenderTicker->render(); + lock.unlock(); + this->_requestFrameRenderCallback(); + this->_requestFrameRenderCallback = nullptr; + + // Calculate and print FPS + auto currentTime = std::chrono::high_resolution_clock::now(); + float deltaTime = std::chrono::duration(currentTime - _lastFrameTime).count(); + _lastFrameTime = currentTime; + + _frameCount++; + _accumulatedTime += deltaTime; + + if (_accumulatedTime >= 1.0f) // Update FPS every second + { + _fps = _frameCount / _accumulatedTime; + _frameCount = 0; + _accumulatedTime = 0.0f; + } + } + } + std::unique_lock taskLock(_taskMutex); + + if (!_tasks.empty()) + { + auto task = std::move(_tasks.front()); + _tasks.pop_front(); + taskLock.unlock(); + task(); + taskLock.lock(); + } + + _cv.wait_for(taskLock, std::chrono::microseconds(2000), [this] + { return !_tasks.empty() || _stop; }); +} + + +} // namespace thermion \ No newline at end of file