From 7f11250b791e7b57d4b2c3865b72149ad97a7d82 Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Fri, 27 Sep 2024 23:16:01 +0800 Subject: [PATCH] refactor!: refactor to support multiple Views/Render Targets --- thermion_dart/ffigen/native.yaml | 4 + .../viewer/src/ffi/src/thermion_dart.g.dart | 377 ++++++----- .../src/ffi/src/thermion_viewer_ffi.dart | 219 +++---- .../lib/src/viewer/src/shared_types/view.dart | 6 + .../src/viewer/src/thermion_viewer_base.dart | 71 +-- .../src/viewer/src/thermion_viewer_stub.dart | 32 +- .../web_wasm/src/thermion_viewer_wasm.dart | 20 - .../native/include/APIBoundaryTypes.h | 2 + .../native/include/FilamentViewer.hpp | 51 +- thermion_dart/native/include/Gizmo.hpp | 9 +- thermion_dart/native/include/SceneManager.hpp | 18 +- thermion_dart/native/include/TGizmo.h | 15 + thermion_dart/native/include/TView.h | 79 +++ .../native/include/ThermionDartApi.h | 47 +- .../include/ThermionDartRenderThreadApi.h | 8 +- thermion_dart/native/src/FilamentViewer.cpp | 601 ++++++------------ thermion_dart/native/src/Gizmo.cpp | 8 +- thermion_dart/native/src/SceneManager.cpp | 38 +- thermion_dart/native/src/TGizmo.cpp | 29 + thermion_dart/native/src/TView.cpp | 142 +++++ thermion_dart/native/src/ThermionDartApi.cpp | 539 ++++++++-------- .../src/ThermionDartRenderThreadApi.cpp | 71 +-- thermion_dart/test/helpers.dart | 32 +- thermion_dart/test/view_tests.dart | 21 + .../lib/thermion_flutter_ffi.dart | 2 +- 25 files changed, 1137 insertions(+), 1304 deletions(-) create mode 100644 thermion_dart/lib/src/viewer/src/shared_types/view.dart create mode 100644 thermion_dart/native/include/TGizmo.h create mode 100644 thermion_dart/native/include/TView.h create mode 100644 thermion_dart/native/src/TGizmo.cpp create mode 100644 thermion_dart/native/src/TView.cpp create mode 100644 thermion_dart/test/view_tests.dart diff --git a/thermion_dart/ffigen/native.yaml b/thermion_dart/ffigen/native.yaml index 97d42410..085fd90a 100644 --- a/thermion_dart/ffigen/native.yaml +++ b/thermion_dart/ffigen/native.yaml @@ -3,10 +3,14 @@ headers: entry-points: - '../native/include/ThermionDartRenderThreadApi.h' - '../native/include/ThermionDartApi.h' + - '../native/include/TView.h' + - '../native/include/TGizmo.h' - '../native/include/ResourceBuffer.h' include-directives: - '../native/include/ThermionDartRenderThreadApi.h' - '../native/include/ThermionDartApi.h' + - '../native/include/TView.h' + - '../native/include/TGizmo.h' - '../native/include/ResourceBuffer.h' - '../native/include/APIBoundaryTypes.h' ffi-native: 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 7b19b3ca..dcb1bb21 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 @@ -45,14 +45,6 @@ external void Viewer_destroyRenderTarget( ffi.Pointer tRenderTarget, ); -@ffi.Native< - ffi.Void Function( - ffi.Pointer, ffi.Pointer)>(isLeaf: true) -external void Viewer_setRenderTarget( - ffi.Pointer viewer, - ffi.Pointer tRenderTarget, -); - @ffi.Native< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Uint32, ffi.Uint32)>(isLeaf: true) @@ -73,6 +65,7 @@ external void Viewer_destroySwapChain( @ffi.Native< ffi.Bool Function( ffi.Pointer, + ffi.Pointer, ffi.Pointer, ffi.Uint64, ffi.Pointer, @@ -83,6 +76,7 @@ external void Viewer_destroySwapChain( ffi.Pointer)>(isLeaf: true) external bool Viewer_render( ffi.Pointer viewer, + ffi.Pointer view, ffi.Pointer swapChain, int frameTimeInNanos, ffi.Pointer pixelBuffer, @@ -97,11 +91,13 @@ external bool Viewer_render( @ffi.Native< ffi.Void Function( ffi.Pointer, + ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>(isLeaf: true) external void Viewer_capture( ffi.Pointer viewer, + ffi.Pointer view, ffi.Pointer swapChain, ffi.Pointer pixelBuffer, ffi.Pointer> callback, @@ -110,18 +106,39 @@ external void Viewer_capture( @ffi.Native< ffi.Void Function( ffi.Pointer, + ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>(isLeaf: true) external void Viewer_captureRenderTarget( ffi.Pointer viewer, + ffi.Pointer view, ffi.Pointer swapChain, ffi.Pointer renderTarget, ffi.Pointer pixelBuffer, 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)>(isLeaf: true) external ffi.Pointer Viewer_getEngine( ffi.Pointer viewer, @@ -177,12 +194,6 @@ external void set_background_color( double a, ); -@ffi.Native, ffi.Int)>(isLeaf: true) -external void set_tone_mapping( - ffi.Pointer viewer, - int toneMapping, -); - @ffi.Native, ffi.Float)>(isLeaf: true) external void set_bloom( ffi.Pointer viewer, @@ -360,25 +371,11 @@ external void get_instances( ffi.Pointer out, ); -@ffi.Native)>(isLeaf: true) -external void set_main_camera( - ffi.Pointer viewer, -); - @ffi.Native)>(isLeaf: true) external int get_main_camera( ffi.Pointer viewer, ); -@ffi.Native< - ffi.Bool Function( - ffi.Pointer, EntityId, ffi.Pointer)>(isLeaf: true) -external bool set_camera( - ffi.Pointer viewer, - int entity, - ffi.Pointer nodeName, -); - @ffi.Native, ffi.Bool)>(isLeaf: true) external void set_view_frustum_culling( ffi.Pointer viewer, @@ -391,57 +388,6 @@ external void set_frame_interval( double interval, ); -@ffi.Native, ffi.Uint32, ffi.Uint32)>( - isLeaf: true) -external void update_viewport( - ffi.Pointer viewer, - int width, - int height, -); - -@ffi.Native)>(isLeaf: true) -external void scroll_begin( - ffi.Pointer viewer, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, ffi.Float, ffi.Float, ffi.Float)>(isLeaf: true) -external void scroll_update( - ffi.Pointer viewer, - double x, - double y, - double z, -); - -@ffi.Native)>(isLeaf: true) -external void scroll_end( - ffi.Pointer viewer, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, ffi.Float, ffi.Float, ffi.Bool)>(isLeaf: true) -external void grab_begin( - ffi.Pointer viewer, - double x, - double y, - bool pan, -); - -@ffi.Native, ffi.Float, ffi.Float)>( - isLeaf: true) -external void grab_update( - ffi.Pointer viewer, - double x, - double y, -); - -@ffi.Native)>(isLeaf: true) -external void grab_end( - ffi.Pointer viewer, -); - @ffi.Native< ffi.Void Function(ffi.Pointer, EntityId, ffi.Pointer, ffi.Pointer, ffi.Int)>(isLeaf: true) @@ -699,6 +645,29 @@ external void SceneManager_queueTransformUpdates( int numEntities, ); +@ffi.Native< + ffi.Pointer Function(ffi.Pointer, EntityId, + ffi.Pointer)>(isLeaf: true) +external ffi.Pointer SceneManager_findCameraByName( + ffi.Pointer tSceneManager, + int entity, + ffi.Pointer name, +); + +@ffi.Native, EntityId, ffi.Int)>( + isLeaf: true) +external void SceneManager_setVisibilityLayer( + ffi.Pointer tSceneManager, + int entity, + int layer, +); + +@ffi.Native Function(ffi.Pointer)>( + isLeaf: true) +external ffi.Pointer SceneManager_getGizmo( + ffi.Pointer tSceneManager, +); + @ffi.Native, EntityId)>( isLeaf: true) external bool update_bone_matrices( @@ -778,10 +747,11 @@ external void queue_relative_position_update_world_axis( ); @ffi.Native< - ffi.Void Function(ffi.Pointer, EntityId, ffi.Float, - ffi.Float)>(isLeaf: true) + 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, @@ -942,17 +912,6 @@ external void set_camera_focus_distance( double focusDistance, ); -@ffi.Native< - ffi.Void Function(ffi.Pointer, _ManipulatorMode, ffi.Double, - ffi.Double, ffi.Double)>(isLeaf: true) -external void set_camera_manipulator_options( - ffi.Pointer viewer, - int mode, - double orbitSpeedX, - double orbitSpeedY, - double zoomSpeed, -); - @ffi.Native< ffi.Void Function( ffi.Pointer, double4x4, ffi.Double, ffi.Double)>(isLeaf: true) @@ -1005,14 +964,6 @@ external void SceneManager_destroyCamera( ffi.Pointer camera, ); -@ffi.Native< - ffi.Void Function( - ffi.Pointer, ffi.Pointer)>(isLeaf: true) -external void SceneManager_setCamera( - ffi.Pointer sceneManager, - ffi.Pointer camera, -); - @ffi.Native)>(isLeaf: true) external int SceneManager_getCameraCount( ffi.Pointer sceneManager, @@ -1026,12 +977,6 @@ external ffi.Pointer SceneManager_getCameraAt( int index, ); -@ffi.Native Function(ffi.Pointer)>( - isLeaf: true) -external ffi.Pointer SceneManager_getActiveCamera( - ffi.Pointer sceneManager, -); - @ffi.Native< ffi.Int Function(ffi.Pointer, EntityId, ffi.Pointer)>(isLeaf: true) @@ -1050,45 +995,10 @@ external int reveal_mesh( ffi.Pointer meshName, ); -@ffi.Native, ffi.Bool)>(isLeaf: true) -external void set_post_processing( - ffi.Pointer viewer, - bool enabled, -); - -@ffi.Native, ffi.Bool)>(isLeaf: true) -external void set_shadows_enabled( - ffi.Pointer viewer, - bool enabled, -); - -@ffi.Native, ffi.Int)>(isLeaf: true) -external void set_shadow_type( - ffi.Pointer viewer, - int shadowType, -); - -@ffi.Native, ffi.Float, ffi.Float)>( - isLeaf: true) -external void set_soft_shadow_options( - ffi.Pointer viewer, - double penumbraScale, - double penumbraRatioScale, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, ffi.Bool, ffi.Bool, ffi.Bool)>(isLeaf: true) -external void set_antialiasing( - ffi.Pointer viewer, - bool msaa, - bool fxaa, - bool taa, -); - @ffi.Native< ffi.Void Function( ffi.Pointer, + ffi.Pointer, ffi.Int, ffi.Int, ffi.Pointer< @@ -1097,6 +1007,7 @@ external void set_antialiasing( EntityId entityId, ffi.Int x, ffi.Int y)>>)>(isLeaf: true) external void filament_pick( ffi.Pointer viewer, + ffi.Pointer tView, int x, int y, ffi.Pointer< @@ -1273,15 +1184,19 @@ external void get_gizmo( ffi.Pointer out, ); -@ffi.Native, EntityId)>(isLeaf: true) +@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, @@ -1289,6 +1204,7 @@ external Aabb2 get_bounding_box( 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, @@ -1296,41 +1212,6 @@ external void get_bounding_box_to_out( ffi.Pointer maxY, ); -@ffi.Native, ffi.Int, ffi.Bool)>( - isLeaf: true) -external void set_layer_visibility( - ffi.Pointer sceneManager, - int layer, - bool visible, -); - -@ffi.Native, EntityId, ffi.Int)>( - isLeaf: true) -external void set_visibility_layer( - ffi.Pointer sceneManager, - int entity, - int layer, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, - ffi.Int, - ffi.Int, - ffi.Pointer< - ffi.NativeFunction< - ffi.Void Function( - EntityId entityId, ffi.Int x, ffi.Int y)>>)>(isLeaf: true) -external void pick_gizmo( - ffi.Pointer sceneManager, - int x, - int y, - ffi.Pointer< - ffi.NativeFunction< - ffi.Void Function(EntityId entityId, ffi.Int x, ffi.Int y)>> - callback, -); - @ffi.Native, ffi.Bool)>( isLeaf: true) external void set_gizmo_visibility( @@ -1537,21 +1418,25 @@ external void Viewer_destroySwapChainRenderThread( ffi.Pointer> onComplete, ); -@ffi.Native, ffi.Pointer)>( - isLeaf: true) +@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.Pointer>)>(isLeaf: true) external void Viewer_captureRenderThread( ffi.Pointer viewer, + ffi.Pointer view, ffi.Pointer swapChain, ffi.Pointer out, ffi.Pointer> onComplete, @@ -1560,12 +1445,14 @@ external void Viewer_captureRenderThread( @ffi.Native< ffi.Void Function( ffi.Pointer, + ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>(isLeaf: true) external void Viewer_captureRenderTargetRenderThread( ffi.Pointer viewer, + ffi.Pointer view, ffi.Pointer swapChain, ffi.Pointer renderTarget, ffi.Pointer out, @@ -1749,17 +1636,6 @@ external void clear_entities_render_thread( ffi.Pointer> callback, ); -@ffi.Native< - ffi.Void Function(ffi.Pointer, EntityId, ffi.Pointer, - ffi.Pointer>)>( - isLeaf: true) -external void set_camera_render_thread( - ffi.Pointer viewer, - int asset, - ffi.Pointer nodeName, - ffi.Pointer> callback, -); - @ffi.Native< ffi.Void Function(ffi.Pointer, EntityId, ffi.Pointer, ffi.Pointer, ffi.Int)>(isLeaf: true) @@ -1956,6 +1832,119 @@ external void unproject_texture_render_thread( ffi.Pointer> callback, ); +@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, ffi.Uint32, ffi.Uint32)>( + isLeaf: true) +external void View_updateViewport( + ffi.Pointer tView, + int width, + int height, +); + +@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.Float)>(isLeaf: true) +external void View_setBloom( + ffi.Pointer tView, + double strength, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Pointer, ffi.Int)>(isLeaf: true) +external void View_setToneMapping( + ffi.Pointer tView, + ffi.Pointer tEngine, + int toneMapping, +); + +@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_getCamera( + ffi.Pointer tView, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Int, + ffi.Int, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function( + EntityId entityId, ffi.Int x, ffi.Int y)>>)>(isLeaf: true) +external void Gizmo_pick( + ffi.Pointer tGizmo, + ffi.Pointer tView, + int x, + int y, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(EntityId entityId, ffi.Int x, ffi.Int y)>> + callback, +); + final class TCamera extends ffi.Opaque {} final class TMaterialInstance extends ffi.Opaque {} @@ -1972,6 +1961,10 @@ final class TRenderTarget extends ffi.Opaque {} final class TSwapChain extends ffi.Opaque {} +final class TView extends ffi.Opaque {} + +final class TGizmo extends ffi.Opaque {} + final class TMaterialKey extends ffi.Struct { @ffi.Bool() external bool doubleSided; @@ -2197,8 +2190,6 @@ typedef DartLoadFilamentResourceIntoOutPointerFunction = void Function( /// - setting up a render loop typedef EntityId = ffi.Int32; typedef DartEntityId = int; -typedef _ManipulatorMode = ffi.Int32; -typedef Dart_ManipulatorMode = 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 6038e54d..f93da411 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 @@ -10,6 +10,7 @@ import '../../../../entities/gizmo.dart'; import '../../../../utils/matrix.dart'; import '../../events.dart'; import '../../shared_types/camera.dart'; +import '../../shared_types/view.dart'; import '../../thermion_viewer_base.dart'; import 'package:logging/logging.dart'; @@ -111,12 +112,28 @@ class ThermionViewerFFI extends ThermionViewer { /// /// Future setRenderTarget(FFIRenderTarget renderTarget) async { - Viewer_setRenderTarget(_viewer!, renderTarget.renderTarget); + final view = (await getViewAt(0)) as FFIView; + View_setRenderTarget(view.view, renderTarget.renderTarget); } + /// + /// + /// + Future createView() async { + var view = Viewer_createView(_viewer!); + if (view == nullptr) { + throw Exception("Failed to create view"); + } + return FFIView(view, _viewer!); + } + + /// + /// + /// Future updateViewportAndCameraProjection(double width, double height) async { viewportDimensions = (width * pixelRatio, height * pixelRatio); - update_viewport(_viewer!, width.toInt(), height.toInt()); + var mainView = FFIView(Viewer_getViewAt(_viewer!, 0), _viewer!); + mainView.updateViewport(width.toInt(), height.toInt()); final cameraCount = await getCameraCount(); @@ -176,8 +193,6 @@ class ThermionViewerFFI extends ThermionViewer { _sceneManager = Viewer_getSceneManager(_viewer!); - await setCameraManipulatorOptions(zoomSpeed: 1.0); - final gizmoEntities = allocator(4); get_gizmo(_sceneManager!, gizmoEntities); _gizmo = Gizmo(gizmoEntities[0], gizmoEntities[1], gizmoEntities[2], @@ -210,7 +225,8 @@ class ThermionViewerFFI extends ThermionViewer { /// @override Future render(FFISwapChain swapChain) async { - Viewer_renderRenderThread(_viewer!, swapChain.swapChain); + final view = (await getViewAt(0)) as FFIView; + Viewer_renderRenderThread(_viewer!, view.view, swapChain.swapChain); } /// @@ -223,13 +239,14 @@ class ThermionViewerFFI extends ThermionViewer { this.viewportDimensions.$2.toInt() * 4; final out = Uint8List(length); + final view = (await getViewAt(0)) as FFIView; await withVoidCallback((cb) { if (renderTarget != null) { - Viewer_captureRenderTargetRenderThread( - _viewer!, swapChain.swapChain, renderTarget.renderTarget, out.address, cb); + Viewer_captureRenderTargetRenderThread(_viewer!, view.view, + swapChain.swapChain, renderTarget.renderTarget, out.address, cb); } else { Viewer_captureRenderThread( - _viewer!, swapChain.swapChain, out.address, cb); + _viewer!, view.view, swapChain.swapChain, out.address, cb); } }); return out; @@ -569,54 +586,6 @@ class ThermionViewerFFI extends ThermionViewer { return entity; } - /// - /// - /// - @override - Future panStart(double x, double y) async { - grab_begin(_viewer!, x * pixelRatio, y * pixelRatio, true); - } - - /// - /// - /// - @override - Future panUpdate(double x, double y) async { - grab_update(_viewer!, x * pixelRatio, y * pixelRatio); - } - - /// - /// - /// - @override - Future panEnd() async { - grab_end(_viewer!); - } - - /// - /// - /// - @override - Future rotateStart(double x, double y) async { - grab_begin(_viewer!, x * pixelRatio, y * pixelRatio, false); - } - - /// - /// - /// - @override - Future rotateUpdate(double x, double y) async { - grab_update(_viewer!, x * pixelRatio, y * pixelRatio); - } - - /// - /// - /// - @override - Future rotateEnd() async { - grab_end(_viewer!); - } - /// /// /// @@ -1072,33 +1041,6 @@ class ThermionViewerFFI extends ThermionViewer { }); } - /// - /// - /// - /// - /// - /// - @override - Future zoomBegin() async { - scroll_begin(_viewer!); - } - - /// - /// - /// - @override - Future zoomUpdate(double x, double y, double z) async { - scroll_update(_viewer!, x, y, z); - } - - /// - /// - /// - @override - Future zoomEnd() async { - scroll_end(_viewer!); - } - /// /// /// @@ -1167,7 +1109,8 @@ class ThermionViewerFFI extends ThermionViewer { /// @override Future setMainCamera() async { - set_main_camera(_viewer!); + final view = (await getViewAt(0)) as FFIView; + Viewer_setMainCamera(_viewer!, view.view); } /// @@ -1198,11 +1141,14 @@ class ThermionViewerFFI extends ThermionViewer { Future setCamera(ThermionEntity entity, String? name) async { var cameraNamePtr = name?.toNativeUtf8(allocator: allocator).cast() ?? nullptr; - var result = set_camera(_viewer!, entity, cameraNamePtr); - allocator.free(cameraNamePtr); - if (!result) { + final camera = + SceneManager_findCameraByName(_sceneManager!, entity, cameraNamePtr); + if (camera == nullptr) { throw Exception("Failed to set camera"); } + final view = (await getViewAt(0)) as FFIView; + View_setCamera(view.view, camera); + allocator.free(cameraNamePtr); } /// @@ -1218,7 +1164,8 @@ class ThermionViewerFFI extends ThermionViewer { /// @override Future setPostProcessing(bool enabled) async { - set_post_processing_render_thread(_viewer!, enabled); + final view = await getViewAt(0) as FFIView; + View_setPostProcessing(view.view, enabled); } /// @@ -1226,14 +1173,16 @@ class ThermionViewerFFI extends ThermionViewer { /// @override Future setShadowsEnabled(bool enabled) async { - set_shadows_enabled(_viewer!, enabled); + final view = await getViewAt(0) as FFIView; + View_setShadowsEnabled(view.view, enabled); } /// /// /// Future setShadowType(ShadowType shadowType) async { - set_shadow_type(_viewer!, shadowType.index); + final view = await getViewAt(0) as FFIView; + View_setShadowType(view.view, shadowType.index); } /// @@ -1241,7 +1190,8 @@ class ThermionViewerFFI extends ThermionViewer { /// Future setSoftShadowOptions( double penumbraScale, double penumbraRatioScale) async { - set_soft_shadow_options(_viewer!, penumbraScale, penumbraRatioScale); + final view = await getViewAt(0) as FFIView; + View_setSoftShadowOptions(view.view, penumbraScale, penumbraRatioScale); } /// @@ -1249,7 +1199,8 @@ class ThermionViewerFFI extends ThermionViewer { /// @override Future setAntiAliasing(bool msaa, bool fxaa, bool taa) async { - set_antialiasing(_viewer!, msaa, fxaa, taa); + final view = await getViewAt(0) as FFIView; + View_setAntiAliasing(view.view, msaa, fxaa, taa); } /// @@ -1257,7 +1208,8 @@ class ThermionViewerFFI extends ThermionViewer { /// @override Future setBloom(double bloom) async { - set_bloom_render_thread(_viewer!, bloom); + final view = await getViewAt(0) as FFIView; + View_setBloom(view.view, bloom); } /// @@ -1489,7 +1441,9 @@ class ThermionViewerFFI extends ThermionViewer { /// Future queuePositionUpdateFromViewportCoords( ThermionEntity entity, double x, double y) async { - queue_position_update_from_viewport_coords(_sceneManager!, entity, x, y); + final view = (await getViewAt(0)) as FFIView; + queue_position_update_from_viewport_coords( + _sceneManager!, view.view, entity, x, y); } /// @@ -1566,8 +1520,9 @@ class ThermionViewerFFI extends ThermionViewer { void pick(int x, int y) async { x = (x * pixelRatio).ceil(); y = (viewportDimensions.$2 - (y * pixelRatio)).ceil(); - - filament_pick(_viewer!, x, y, _onPickResultCallable.nativeFunction); + final view = (await getViewAt(0)) as FFIView; + filament_pick( + _viewer!, view.view, x, y, _onPickResultCallable.nativeFunction); } /// @@ -1577,7 +1532,10 @@ class ThermionViewerFFI extends ThermionViewer { void pickGizmo(int x, int y) async { x = (x * pixelRatio).ceil(); y = (viewportDimensions.$2 - (y * pixelRatio)).ceil(); - pick_gizmo(_sceneManager!, x, y, _onGizmoPickResultCallable.nativeFunction); + final view = (await getViewAt(0)) as FFIView; + final gizmo = SceneManager_getGizmo(_sceneManager!); + Gizmo_pick( + gizmo, view.view, x, y, _onGizmoPickResultCallable.nativeFunction); } /// @@ -1658,27 +1616,6 @@ class ThermionViewerFFI extends ThermionViewer { return rotationMatrix; } - ManipulatorMode _cameraMode = ManipulatorMode.ORBIT; - - /// - /// - /// - @override - Future setCameraManipulatorOptions( - {ManipulatorMode? mode, - double orbitSpeedX = 0.01, - double orbitSpeedY = 0.01, - double zoomSpeed = 0.01}) async { - if (mode != null) { - _cameraMode = mode; - } - if (_cameraMode != ManipulatorMode.ORBIT) { - throw Exception("Manipulator mode $mode not yet implemented"); - } - set_camera_manipulator_options( - _viewer!, _cameraMode.index, orbitSpeedX, orbitSpeedX, zoomSpeed); - } - /// /// /// @@ -1908,7 +1845,8 @@ class ThermionViewerFFI extends ThermionViewer { /// @override Future getViewportBoundingBox(ThermionEntity entityId) async { - final result = get_bounding_box(_sceneManager!, entityId); + final view = (await getViewAt(0)) as FFIView; + final result = get_bounding_box(_sceneManager!, view.view, entityId); return v64.Aabb2.minMax(v64.Vector2(result.minX, result.minY), v64.Vector2(result.maxX, result.maxY)); } @@ -1916,17 +1854,16 @@ class ThermionViewerFFI extends ThermionViewer { /// /// /// - Future setLayerVisibility(int layer, bool visible) { - set_layer_visibility(_sceneManager!, layer, visible); - return Future.value(); + Future setLayerVisibility(int layer, bool visible) async { + final view = (await getViewAt(0)) as FFIView; + View_setLayerEnabled(view.view, layer, visible); } /// /// /// - Future setVisibilityLayer(ThermionEntity entity, int layer) { - set_visibility_layer(_sceneManager!, entity, layer); - return Future.value(); + Future setVisibilityLayer(ThermionEntity entity, int layer) async { + SceneManager_setVisibilityLayer(_sceneManager!, entity, layer); } /// @@ -2171,14 +2108,16 @@ class ThermionViewerFFI extends ThermionViewer { /// /// Future setActiveCamera(ThermionFFICamera camera) async { - SceneManager_setCamera(_sceneManager!, camera.camera); + final view = (await getViewAt(0)) as FFIView; + View_setCamera(view.view, camera.camera); } /// /// /// Future getActiveCamera() async { - final ptr = SceneManager_getActiveCamera(_sceneManager!); + final view = (await getViewAt(0)) as FFIView; + final ptr = View_getCamera(view.view); return ThermionFFICamera(ptr, Viewer_getEngine(_viewer!)); } @@ -2216,6 +2155,15 @@ class ThermionViewerFFI extends ThermionViewer { } return ThermionFFICamera(camera, Viewer_getEngine(_viewer!)); } + + @override + Future getViewAt(int index) async { + var view = Viewer_getViewAt(_viewer!, index); + if (view == nullptr) { + throw Exception("Failed to get view"); + } + return FFIView(view, _viewer!); + } } class ThermionFFITexture extends ThermionTexture { @@ -2270,3 +2218,20 @@ class FFISwapChain extends SwapChain { }); } } + +class FFIView extends View { + final Pointer view; + final Pointer viewer; + + FFIView(this.view, this.viewer); + + @override + Future updateViewport(int width, int height) async { + View_updateViewport(view, width, height); + } + + @override + Future setRenderTarget(covariant FFIRenderTarget renderTarget) async { + View_setRenderTarget(view, renderTarget.renderTarget); + } +} diff --git a/thermion_dart/lib/src/viewer/src/shared_types/view.dart b/thermion_dart/lib/src/viewer/src/shared_types/view.dart new file mode 100644 index 00000000..478a7710 --- /dev/null +++ b/thermion_dart/lib/src/viewer/src/shared_types/view.dart @@ -0,0 +1,6 @@ +import 'package:thermion_dart/thermion_dart.dart'; + +abstract class View { + Future updateViewport(int width, int height); + Future setRenderTarget(covariant RenderTarget renderTarget); +} 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 b0fec8ba..c19fc395 100644 --- a/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart +++ b/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart @@ -11,6 +11,7 @@ import 'dart:async'; import 'package:animation_tools_dart/animation_tools_dart.dart'; import 'shared_types/swap_chain.dart'; +import 'shared_types/view.dart'; const double kNear = 0.05; const double kFar = 1000.0; @@ -72,7 +73,8 @@ abstract class ThermionViewer { /// /// Render a single frame and copy the pixel buffer to [out]. /// - Future capture(covariant SwapChain swapChain, { covariant RenderTarget? renderTarget }); + Future capture(covariant SwapChain swapChain, + {covariant RenderTarget? renderTarget}); /// /// @@ -82,13 +84,23 @@ abstract class ThermionViewer { /// /// /// - Future createRenderTarget(int width, int height, int textureHandle); + Future createRenderTarget( + int width, int height, int textureHandle); /// /// /// Future setRenderTarget(covariant RenderTarget renderTarget); + /// + /// + /// + Future createView(); + + /// + /// + /// + Future getViewAt(int index); /// /// Sets the framerate for continuous rendering when [setRendering] is enabled. @@ -246,36 +258,6 @@ abstract class ThermionViewer { Future loadGltf(String path, String relativeResourcePath, {bool keepData = false}); - /// - /// Called by `FilamentGestureDetector`. You probably don't want to call this yourself. - /// - Future panStart(double x, double y); - - /// - /// Called by `FilamentGestureDetector`. You probably don't want to call this yourself. - /// - Future panUpdate(double x, double y); - - /// - /// Called by `FilamentGestureDetector`. You probably don't want to call this yourself. - /// - Future panEnd(); - - /// - /// Called by `FilamentGestureDetector`. You probably don't want to call this yourself. - /// - Future rotateStart(double x, double y); - - /// - /// Called by `FilamentGestureDetector`. You probably don't want to call this yourself. - /// - Future rotateUpdate(double x, double y); - - /// - /// Called by `FilamentGestureDetector`. You probably don't want to call this yourself. - /// - Future rotateEnd(); - /// /// Set the weights for all morph targets in [entity] to [weights]. /// Note that [weights] must contain values for ALL morph targets, but no exception will be thrown if you don't do so (you'll just get incorrect results). @@ -418,20 +400,6 @@ abstract class ThermionViewer { /// Future clearEntities(); - /// - /// Called by `FilamentGestureDetector`. You probably don't want to call this yourself. - /// - Future zoomBegin(); - - /// - /// Called by `FilamentGestureDetector`. You probably don't want to call this yourself. - /// - Future zoomUpdate(double x, double y, double z); - - /// - /// Called by `FilamentGestureDetector`. You probably don't want to call this yourself. - /// - Future zoomEnd(); /// /// Schedules the glTF animation at [index] in [entity] to start playing on the next frame. @@ -746,17 +714,6 @@ abstract class ThermionViewer { /// String? getNameForEntity(ThermionEntity entity); - /// - /// Sets the options for manipulating the camera via the viewport. - /// ManipulatorMode.FREE_FLIGHT and ManipulatorMode.MAP are currently unsupported and will throw an exception. - /// - @Deprecated("Use InputHandler instead") - Future setCameraManipulatorOptions( - {ManipulatorMode mode = ManipulatorMode.ORBIT, - double orbitSpeedX = 0.01, - double orbitSpeedY = 0.01, - double zoomSpeed = 0.01}); - /// /// Returns all child entities under [parent]. /// 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 e0ce4fca..771379b4 100644 --- a/thermion_dart/lib/src/viewer/src/thermion_viewer_stub.dart +++ b/thermion_dart/lib/src/viewer/src/thermion_viewer_stub.dart @@ -2,6 +2,7 @@ import 'dart:math'; import 'dart:typed_data'; import 'package:thermion_dart/src/viewer/src/shared_types/swap_chain.dart'; +import 'package:thermion_dart/src/viewer/src/shared_types/view.dart'; import 'package:thermion_dart/thermion_dart.dart'; import 'package:vector_math/vector_math_64.dart'; import 'dart:async'; @@ -385,12 +386,7 @@ class ThermionViewerStub extends ThermionViewer { throw UnimplementedError(); } - @override - Future render() { - // TODO: implement render - throw UnimplementedError(); - } - + @override // TODO: implement rendering bool get rendering => throw UnimplementedError(); @@ -1032,6 +1028,30 @@ class ThermionViewerStub extends ThermionViewer { // TODO: implement setRenderTarget throw UnimplementedError(); } + + @override + Future capture(covariant SwapChain swapChain, {covariant RenderTarget? renderTarget}) { + // TODO: implement capture + throw UnimplementedError(); + } + + @override + Future createView() { + // TODO: implement createView + throw UnimplementedError(); + } + + @override + Future getViewAt(int index) { + // TODO: implement getViewAt + throw UnimplementedError(); + } + + @override + Future render(covariant SwapChain swapChain) { + // TODO: implement render + 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 a99e3951..3a524515 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 @@ -1803,26 +1803,6 @@ class ThermionViewerWasm implements ThermionViewer { null); } - @override - Future setCameraManipulatorOptions( - {ManipulatorMode mode = ManipulatorMode.ORBIT, - double orbitSpeedX = 0.01, - double orbitSpeedY = 0.01, - double zoomSpeed = 0.01}) async { - _module!.ccall( - "set_camera_manipulator_options", - "void", - ["void*".toJS, "int".toJS, "double".toJS, "double".toJS, "double".toJS] - .toJS, - [ - _viewer!, - mode.index.toJS, - orbitSpeedX.toJS, - orbitSpeedY.toJS, - zoomSpeed.toJS - ].toJS, - null); - } @override Future setCameraModelMatrix(List matrix) async { diff --git a/thermion_dart/native/include/APIBoundaryTypes.h b/thermion_dart/native/include/APIBoundaryTypes.h index f96c25b6..a2a87b9a 100644 --- a/thermion_dart/native/include/APIBoundaryTypes.h +++ b/thermion_dart/native/include/APIBoundaryTypes.h @@ -17,6 +17,8 @@ extern "C" typedef struct TSceneManager TSceneManager; typedef struct TRenderTarget TRenderTarget; typedef struct TSwapChain TSwapChain; + typedef struct TView TView; + typedef struct TGizmo TGizmo; struct TMaterialKey { bool doubleSided = 1; diff --git a/thermion_dart/native/include/FilamentViewer.hpp b/thermion_dart/native/include/FilamentViewer.hpp index dd98ae89..f7ec467d 100644 --- a/thermion_dart/native/include/FilamentViewer.hpp +++ b/thermion_dart/native/include/FilamentViewer.hpp @@ -61,8 +61,9 @@ namespace thermion_filament FilamentViewer(const void *context, const ResourceLoaderWrapperImpl *const resourceLoaderWrapper, void *const platform = nullptr, const char *uberArchivePath = nullptr); ~FilamentViewer(); - void setToneMapping(ToneMapping toneMapping); - void setBloom(float strength); + View* createView(); + View* getViewAt(int index); + void loadSkybox(const char *const skyboxUri); void removeSkybox(); @@ -74,17 +75,16 @@ namespace thermion_filament void removeEntity(EntityId asset); void clearEntities(); - void updateViewport(uint32_t width, uint32_t height); bool render( uint64_t frameTimeInNanos, + View* view, SwapChain* swapChain, void *pixelBuffer, void (*callback)(void *buf, size_t size, void *data), void *data); void setFrameInterval(float interval); - bool setCamera(EntityId asset, const char *nodeName); - void setMainCamera(); + void setMainCamera(View *view); EntityId getMainCamera(); Camera* getCamera(EntityId entity); @@ -96,25 +96,15 @@ namespace thermion_filament RenderTarget* createRenderTarget(intptr_t textureId, uint32_t width, uint32_t height); void destroyRenderTarget(RenderTarget* renderTarget); - void setRenderTarget(RenderTarget* renderTarget); Renderer *getRenderer(); void setBackgroundColor(const float r, const float g, const float b, const float a); - void setBackgroundImage(const char *resourcePath, bool fillHeight); + void setBackgroundImage(const char *resourcePath, bool fillHeight, uint32_t width, uint32_t height); void clearBackgroundImage(); - void setBackgroundImagePosition(float x, float y, bool clamp); - - void setViewFrustumCulling(bool enabled); - - void setCameraManipulatorOptions(filament::camutils::Mode mode, double orbitSpeedX, double orbitSpeedY, double zoomSpeed); - void grabBegin(float x, float y, bool pan); - void grabUpdate(float x, float y); - void grabEnd(); - void scrollBegin(); - void scrollUpdate(float x, float y, float delta); - void scrollEnd(); - void pick(uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y)); + void setBackgroundImagePosition(float x, float y, bool clamp, uint32_t width, uint32_t height); + + void pick(View *view, uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y)); Engine* getEngine() { return _engine; } @@ -140,16 +130,9 @@ namespace thermion_filament void setLightDirection(EntityId entityId, float x, float y, float z); void removeLight(EntityId entityId); void clearLights(); - void setPostProcessing(bool enabled); - void capture(uint8_t *out, bool useFence, SwapChain* swapChain, void (*onComplete)()); - void capture(uint8_t *out, bool useFence, SwapChain* swapChain, RenderTarget* renderTarget, void (*onComplete)()); - - void setAntiAliasing(bool msaaEnabled, bool fxaaEnabled, bool taaEnabled); - void setDepthOfField(); - void setShadowsEnabled(bool enabled); - void setShadowType(ShadowType shadowType); - void setSoftShadowOptions( float penumbraScale, float penumbraRatioScale); + 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() { @@ -162,13 +145,13 @@ namespace thermion_filament const ResourceLoaderWrapperImpl *const _resourceLoaderWrapper; void* _context = nullptr; Scene *_scene = nullptr; - View *_view = nullptr; Engine *_engine = nullptr; thermion_filament::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 @@ -183,16 +166,6 @@ namespace thermion_filament // Camera properties Camera *_mainCamera = nullptr; // the default camera added to every scene. If you want the *active* camera, access via View. - Manipulator *_manipulator = nullptr; - filament::camutils::Mode _manipulatorMode = filament::camutils::Mode::ORBIT; - double _orbitSpeedX = 0.01; - double _orbitSpeedY = 0.01; - double _zoomSpeed = 0.01; - - void _createManipulator(); - - ColorGrading *colorGrading = nullptr; - // background image properties uint32_t _imageHeight = 0; uint32_t _imageWidth = 0; diff --git a/thermion_dart/native/include/Gizmo.hpp b/thermion_dart/native/include/Gizmo.hpp index 1358106b..9f244cc4 100644 --- a/thermion_dart/native/include/Gizmo.hpp +++ b/thermion_dart/native/include/Gizmo.hpp @@ -58,7 +58,7 @@ class Gizmo { }; public: - Gizmo(Engine& engine, View *view, Scene *scene); + Gizmo(Engine& engine, Scene *scene); ~Gizmo(); Entity x() { @@ -73,15 +73,12 @@ class Gizmo { Entity center() { return _entities[3]; }; - View* view() { - return _view; - } bool isActive() { return _isActive; } - void pick(uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y)); + void pick(View* view, uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y)); bool isGizmoEntity(Entity entity); void setVisibility(bool visible); @@ -90,9 +87,7 @@ class Gizmo { void highlight(Entity entity); void unhighlight(); Engine &_engine; - View *_view; Scene *_scene; - filament::Camera *_camera; utils::Entity _entities[7] = { utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity(), utils::Entity() }; Material* _material; MaterialInstance* _materialInstances[7]; diff --git a/thermion_dart/native/include/SceneManager.hpp b/thermion_dart/native/include/SceneManager.hpp index d955d17a..a29c2ed1 100644 --- a/thermion_dart/native/include/SceneManager.hpp +++ b/thermion_dart/native/include/SceneManager.hpp @@ -46,7 +46,7 @@ namespace thermion_filament class SceneManager { public: - SceneManager(View* view, + SceneManager( const ResourceLoaderWrapperImpl *const loader, Engine *engine, Scene *scene, @@ -111,9 +111,9 @@ namespace thermion_filament void setRotation(EntityId e, float rads, float x, float y, float z, float w); void queueTransformUpdates(EntityId* entities, math::mat4* transforms, int numEntities); - void queueRelativePositionUpdateWorldAxis(EntityId entity, float viewportCoordX, float viewportCoordY, float x, float y, float z); - void queueRelativePositionUpdateFromViewportVector(EntityId entityId, float viewportCoordX, float viewportCoordY); + void queueRelativePositionUpdateFromViewportVector(View* view, EntityId entityId, float viewportCoordX, float viewportCoordY); + const utils::Entity *getCameraEntities(EntityId e); size_t getCameraEntityCount(EntityId e); const utils::Entity *getLightEntities(EntityId e) noexcept; @@ -231,12 +231,7 @@ namespace thermion_filament /// @param out a pointer large enough to store four floats (the min/max coordinates of the bounding box) /// @return /// - Aabb2 getBoundingBox(EntityId entity); - - /// - /// Toggles the visibility of the given layer. - /// - void setLayerVisibility(SceneManager::LAYERS layer, bool enabled); + Aabb2 getBoundingBox(View* view, EntityId entity); /// /// Creates an entity with the specified geometry/material/normals and adds to the scene. @@ -308,20 +303,15 @@ namespace thermion_filament void destroyCamera(Camera* camera); - void setCamera(Camera* camera); - size_t getCameraCount(); Camera* getCameraAt(size_t index); - Camera* getActiveCamera(); - private: gltfio::AssetLoader *_assetLoader = nullptr; const ResourceLoaderWrapperImpl *const _resourceLoaderWrapper; Engine *_engine = nullptr; Scene *_scene = nullptr; - View* _view = nullptr; Camera* _mainCamera; gltfio::MaterialProvider *_ubershaderProvider = nullptr; diff --git a/thermion_dart/native/include/TGizmo.h b/thermion_dart/native/include/TGizmo.h new file mode 100644 index 00000000..c7cac630 --- /dev/null +++ b/thermion_dart/native/include/TGizmo.h @@ -0,0 +1,15 @@ +#pragma once + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ThermionDartApi.h" + +EMSCRIPTEN_KEEPALIVE void Gizmo_pick(TGizmo *tGizmo, TView *tView, int x, int y, void (*callback)(EntityId entityId, int x, int y)); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/thermion_dart/native/include/TView.h b/thermion_dart/native/include/TView.h new file mode 100644 index 00000000..aa287122 --- /dev/null +++ b/thermion_dart/native/include/TView.h @@ -0,0 +1,79 @@ +#ifndef _FLUTTER_FILAMENT_API_H +#define _FLUTTER_FILAMENT_API_H + +#ifdef _WIN32 +#ifdef IS_DLL +#define EMSCRIPTEN_KEEPALIVE __declspec(dllimport) +#else +#define EMSCRIPTEN_KEEPALIVE __declspec(dllexport) +#endif +#else +#ifndef EMSCRIPTEN_KEEPALIVE +#define EMSCRIPTEN_KEEPALIVE __attribute__((visibility("default"))) +#endif +#endif + +// we copy the LLVM here rather than including, +// because on Windows it's difficult to pin the exact location which confuses dart ffigen + +#ifndef __STDBOOL_H +#define __STDBOOL_H + +#define __bool_true_false_are_defined 1 + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ > 201710L +/* FIXME: We should be issuing a deprecation warning here, but cannot yet due + * to system headers which include this header file unconditionally. + */ +#elif !defined(__cplusplus) +#define bool _Bool +#define true 1 +#define false 0 +#elif defined(__GNUC__) && !defined(__STRICT_ANSI__) +/* Define _Bool as a GNU extension. */ +#define _Bool bool +#if defined(__cplusplus) && __cplusplus < 201103L +/* For C++98, define bool, false, true as a GNU extension. */ +#define bool bool +#define false false +#define true true +#endif +#endif + +#endif /* __STDBOOL_H */ + +#if defined(__APPLE__) || defined(__EMSCRIPTEN__) +#include +#endif + +#include "APIBoundaryTypes.h" +#include "ResourceBuffer.hpp" + +#ifdef __cplusplus +extern "C" +{ +#endif + +// View +EMSCRIPTEN_KEEPALIVE void View_updateViewport(TView *view, uint32_t width, uint32_t height); +EMSCRIPTEN_KEEPALIVE void View_setRenderTarget(TView *view, TRenderTarget *renderTarget); +EMSCRIPTEN_KEEPALIVE void View_setFrustumCullingEnabled(TView *view, bool enabled); +EMSCRIPTEN_KEEPALIVE void View_updateViewport(TView* tView, uint32_t width, uint32_t height); +EMSCRIPTEN_KEEPALIVE void View_setRenderTarget(TView* tView, TRenderTarget* tRenderTarget); +EMSCRIPTEN_KEEPALIVE void View_setFrustumCullingEnabled(TView* tView, bool enabled); +EMSCRIPTEN_KEEPALIVE void View_setPostProcessing(TView* tView, bool enabled); +EMSCRIPTEN_KEEPALIVE void View_setShadowsEnabled(TView* tView, bool enabled); +EMSCRIPTEN_KEEPALIVE void View_setShadowType(TView* tView, int shadowType); +EMSCRIPTEN_KEEPALIVE void View_setSoftShadowOptions(TView* tView, float penumbraScale, float penumbraRatioScale); +EMSCRIPTEN_KEEPALIVE void View_setBloom(TView* tView, float strength); +EMSCRIPTEN_KEEPALIVE void View_setToneMapping(TView* tView, TEngine* tEngine, int toneMapping); +EMSCRIPTEN_KEEPALIVE void View_setAntiAliasing(TView *tView, bool msaa, bool fxaa, bool taa); +EMSCRIPTEN_KEEPALIVE void View_setLayerEnabled(TView *tView, int layer, bool visible); +EMSCRIPTEN_KEEPALIVE void View_setCamera(TView *tView, TCamera *tCamera); +EMSCRIPTEN_KEEPALIVE TCamera* View_getCamera(TView *tView); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/thermion_dart/native/include/ThermionDartApi.h b/thermion_dart/native/include/ThermionDartApi.h index 0886fe40..5c3ad0bb 100644 --- a/thermion_dart/native/include/ThermionDartApi.h +++ b/thermion_dart/native/include/ThermionDartApi.h @@ -59,11 +59,11 @@ extern "C" EMSCRIPTEN_KEEPALIVE TSceneManager *Viewer_getSceneManager(TViewer *viewer); EMSCRIPTEN_KEEPALIVE TRenderTarget* Viewer_createRenderTarget(TViewer *viewer, intptr_t texture, uint32_t width, uint32_t height); EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTarget(TViewer *viewer, TRenderTarget* tRenderTarget); - EMSCRIPTEN_KEEPALIVE void Viewer_setRenderTarget(TViewer *viewer, TRenderTarget* tRenderTarget); EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createSwapChain(TViewer *viewer, const void *const window, uint32_t width, uint32_t height); EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChain(TViewer *viewer, TSwapChain* swapChain); EMSCRIPTEN_KEEPALIVE bool Viewer_render( TViewer *viewer, + TView *view, TSwapChain *swapChain, uint64_t frameTimeInNanos, void *pixelBuffer, @@ -71,16 +71,20 @@ extern "C" void *data); EMSCRIPTEN_KEEPALIVE void Viewer_capture( TViewer *viewer, + TView *view, TSwapChain *swapChain, uint8_t *pixelBuffer, void (*callback)(void)); EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTarget( TViewer *viewer, + TView *view, TSwapChain *swapChain, TRenderTarget *renderTarget, uint8_t *pixelBuffer, 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); // Engine EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer* viewer); @@ -92,7 +96,7 @@ extern "C" 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 void set_tone_mapping(TViewer *viewer, int toneMapping); + EMSCRIPTEN_KEEPALIVE void set_bloom(TViewer *viewer, float strength); EMSCRIPTEN_KEEPALIVE void load_skybox(TViewer *viewer, const char *skyboxPath); EMSCRIPTEN_KEEPALIVE void load_ibl(TViewer *viewer, const char *iblPath, float intensity); @@ -128,20 +132,12 @@ extern "C" EMSCRIPTEN_KEEPALIVE EntityId create_instance(TSceneManager *sceneManager, EntityId id); EMSCRIPTEN_KEEPALIVE int get_instance_count(TSceneManager *sceneManager, EntityId entityId); EMSCRIPTEN_KEEPALIVE void get_instances(TSceneManager *sceneManager, EntityId entityId, EntityId *out); - EMSCRIPTEN_KEEPALIVE void set_main_camera(TViewer *viewer); + EMSCRIPTEN_KEEPALIVE EntityId get_main_camera(TViewer *viewer); - EMSCRIPTEN_KEEPALIVE bool set_camera(TViewer *viewer, EntityId entity, const char *nodeName); EMSCRIPTEN_KEEPALIVE void set_view_frustum_culling(TViewer *viewer, bool enabled); - EMSCRIPTEN_KEEPALIVE void set_frame_interval(TViewer *viewer, float interval); - EMSCRIPTEN_KEEPALIVE void update_viewport(TViewer *viewer, uint32_t width, uint32_t height); - EMSCRIPTEN_KEEPALIVE void scroll_begin(TViewer *viewer); - EMSCRIPTEN_KEEPALIVE void scroll_update(TViewer *viewer, float x, float y, float z); - EMSCRIPTEN_KEEPALIVE void scroll_end(TViewer *viewer); - EMSCRIPTEN_KEEPALIVE void grab_begin(TViewer *viewer, float x, float y, bool pan); - EMSCRIPTEN_KEEPALIVE void grab_update(TViewer *viewer, float x, float y); - EMSCRIPTEN_KEEPALIVE void grab_end(TViewer *viewer); + EMSCRIPTEN_KEEPALIVE void apply_weights( TSceneManager *sceneManager, EntityId entity, @@ -213,6 +209,9 @@ extern "C" EMSCRIPTEN_KEEPALIVE bool SceneManager_setTransform(TSceneManager *sceneManager, EntityId entityId, const double *const transform); EMSCRIPTEN_KEEPALIVE void SceneManager_queueTransformUpdates(TSceneManager *sceneManager, EntityId* entities, const double* const transforms, int numEntities); + EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_findCameraByName(TSceneManager* tSceneManager, EntityId entity, const char* name); + EMSCRIPTEN_KEEPALIVE void SceneManager_setVisibilityLayer(TSceneManager *tSceneManager, EntityId entity, int layer); + EMSCRIPTEN_KEEPALIVE TGizmo* SceneManager_getGizmo(TSceneManager *tSceneManager); EMSCRIPTEN_KEEPALIVE bool update_bone_matrices(TSceneManager *sceneManager, EntityId entityId); EMSCRIPTEN_KEEPALIVE void get_morph_target_name(TSceneManager *sceneManager, EntityId assetEntity, EntityId childEntity, char *const outPtr, int index); @@ -223,7 +222,7 @@ extern "C" EMSCRIPTEN_KEEPALIVE void transform_to_unit_cube(TSceneManager *sceneManager, EntityId asset); 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, EntityId entity, float viewportX, float viewportY); + EMSCRIPTEN_KEEPALIVE void queue_position_update_from_viewport_coords(TSceneManager *sceneManager, TView *view, EntityId entity, float viewportX, float viewportY); EMSCRIPTEN_KEEPALIVE void set_position(TSceneManager *sceneManager, EntityId entity, float x, float y, float z); EMSCRIPTEN_KEEPALIVE void set_rotation(TSceneManager *sceneManager, EntityId entity, float rads, float x, float y, float z, float w); @@ -252,7 +251,6 @@ extern "C" EMSCRIPTEN_KEEPALIVE double get_camera_culling_far(TCamera *camera); EMSCRIPTEN_KEEPALIVE float get_camera_fov(TCamera *camera, bool horizontal); EMSCRIPTEN_KEEPALIVE void set_camera_focus_distance(TCamera *camera, float focusDistance); - EMSCRIPTEN_KEEPALIVE void set_camera_manipulator_options(TViewer *viewer, _ManipulatorMode mode, double orbitSpeedX, double orbitSpeedY, double zoomSpeed); EMSCRIPTEN_KEEPALIVE void Camera_setCustomProjectionWithCulling(TCamera* camera, double4x4 projectionMatrix, double near, double far); EMSCRIPTEN_KEEPALIVE void Camera_setModelMatrix(TCamera* camera, double4x4 modelMatrix); @@ -264,22 +262,15 @@ extern "C" EMSCRIPTEN_KEEPALIVE TEntityManager *Engine_getEntityManager(TEngine *engine); // SceneManager - EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_createCamera(TSceneManager *sceneManager); EMSCRIPTEN_KEEPALIVE void SceneManager_destroyCamera(TSceneManager *sceneManager, TCamera* camera); - EMSCRIPTEN_KEEPALIVE void SceneManager_setCamera(TSceneManager *sceneManager, TCamera* camera); EMSCRIPTEN_KEEPALIVE size_t SceneManager_getCameraCount(TSceneManager *sceneManager); EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_getCameraAt(TSceneManager *sceneManager, size_t index); - EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_getActiveCamera(TSceneManager *sceneManager); EMSCRIPTEN_KEEPALIVE int hide_mesh(TSceneManager *sceneManager, EntityId entity, const char *meshName); EMSCRIPTEN_KEEPALIVE int reveal_mesh(TSceneManager *sceneManager, EntityId entity, const char *meshName); - EMSCRIPTEN_KEEPALIVE void set_post_processing(TViewer *viewer, bool enabled); - EMSCRIPTEN_KEEPALIVE void set_shadows_enabled(TViewer *viewer, bool enabled); - EMSCRIPTEN_KEEPALIVE void set_shadow_type(TViewer *viewer, int shadowType); - EMSCRIPTEN_KEEPALIVE void set_soft_shadow_options(TViewer *viewer, float penumbraScale, float penumbraRatioScale); - EMSCRIPTEN_KEEPALIVE void set_antialiasing(TViewer *viewer, bool msaa, bool fxaa, bool taa); - EMSCRIPTEN_KEEPALIVE void filament_pick(TViewer *viewer, int x, int y, void (*callback)(EntityId entityId, int x, int y)); + + EMSCRIPTEN_KEEPALIVE void filament_pick(TViewer *viewer, TView* tView, int x, int y, void (*callback)(EntityId entityId, int x, int y)); EMSCRIPTEN_KEEPALIVE const char *get_name_for_entity(TSceneManager *sceneManager, const EntityId entityId); EMSCRIPTEN_KEEPALIVE EntityId find_child_entity_by_name(TSceneManager *sceneManager, const EntityId parent, const char *name); EMSCRIPTEN_KEEPALIVE int get_entity_count(TSceneManager *sceneManager, const EntityId target, bool renderableOnly); @@ -312,11 +303,9 @@ extern "C" EMSCRIPTEN_KEEPALIVE void test_collisions(TSceneManager *sceneManager, EntityId entity); EMSCRIPTEN_KEEPALIVE void set_priority(TSceneManager *sceneManager, EntityId entityId, int priority); EMSCRIPTEN_KEEPALIVE void get_gizmo(TSceneManager *sceneManager, EntityId *out); - EMSCRIPTEN_KEEPALIVE Aabb2 get_bounding_box(TSceneManager *sceneManager, EntityId entity); - EMSCRIPTEN_KEEPALIVE void get_bounding_box_to_out(TSceneManager *sceneManager, EntityId entity, float *minX, float *minY, float *maxX, float *maxY); - EMSCRIPTEN_KEEPALIVE void set_layer_visibility(TSceneManager *sceneManager, int layer, bool visible); - EMSCRIPTEN_KEEPALIVE void set_visibility_layer(TSceneManager *sceneManager, EntityId entity, int layer); - EMSCRIPTEN_KEEPALIVE void pick_gizmo(TSceneManager *sceneManager, int x, int y, void (*callback)(EntityId entityId, int x, int y)); + 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); + EMSCRIPTEN_KEEPALIVE void set_gizmo_visibility(TSceneManager *sceneManager, bool visible); EMSCRIPTEN_KEEPALIVE void set_stencil_highlight(TSceneManager *sceneManager, EntityId entity, float r, float g, float b); EMSCRIPTEN_KEEPALIVE void remove_stencil_highlight(TSceneManager *sceneManager, EntityId entity); diff --git a/thermion_dart/native/include/ThermionDartRenderThreadApi.h b/thermion_dart/native/include/ThermionDartRenderThreadApi.h index 8b882f0f..6794ef41 100644 --- a/thermion_dart/native/include/ThermionDartRenderThreadApi.h +++ b/thermion_dart/native/include/ThermionDartRenderThreadApi.h @@ -27,9 +27,9 @@ extern "C" void (*callback)(TViewer *viewer)); EMSCRIPTEN_KEEPALIVE void Viewer_createSwapChainRenderThread(TViewer *viewer, void *const surface, 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, TSwapChain* swapChain); - EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderThread(TViewer *viewer, TSwapChain* swapChain, uint8_t* out, void (*onComplete)()); - EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTargetRenderThread(TViewer *viewer, TSwapChain* swapChain, TRenderTarget* renderTarget, uint8_t* out, 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, void (*onComplete)()); + EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTargetRenderThread(TViewer *viewer, TView* view, TSwapChain* swapChain, TRenderTarget* renderTarget, uint8_t* out, void (*onComplete)()); EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer_render_thread(TViewer *viewer); @@ -52,7 +52,7 @@ extern "C" EMSCRIPTEN_KEEPALIVE void create_instance_render_thread(TSceneManager *sceneManager, EntityId entityId, void (*callback)(EntityId)); EMSCRIPTEN_KEEPALIVE void remove_entity_render_thread(TViewer *viewer, EntityId asset, void (*callback)()); EMSCRIPTEN_KEEPALIVE void clear_entities_render_thread(TViewer *viewer, void (*callback)()); - EMSCRIPTEN_KEEPALIVE void set_camera_render_thread(TViewer *viewer, EntityId asset, const char *nodeName, void (*callback)(bool)); + EMSCRIPTEN_KEEPALIVE void apply_weights_render_thread( TSceneManager *sceneManager, EntityId asset, diff --git a/thermion_dart/native/src/FilamentViewer.cpp b/thermion_dart/native/src/FilamentViewer.cpp index 564427a6..510eb025 100644 --- a/thermion_dart/native/src/FilamentViewer.cpp +++ b/thermion_dart/native/src/FilamentViewer.cpp @@ -164,31 +164,7 @@ namespace thermion_filament _mainCamera = _engine->createCamera(camera); - _view = _engine->createView(); - _view->setBlendMode(filament::View::BlendMode::TRANSLUCENT); - _view->setStencilBufferEnabled(true); - - setToneMapping(ToneMapping::ACES); - - // there's a glitch on certain iGPUs where nothing will render when postprocessing is enabled and bloom is disabled - // set bloom to a small value here - setBloom(0.01); - - _view->setAmbientOcclusionOptions({.enabled = false}); - _view->setDynamicResolutionOptions({.enabled = false}); - -#if defined(_WIN32) - _view->setStereoscopicOptions({.enabled = true}); -#endif - - _view->setDithering(filament::Dithering::NONE); - setAntiAliasing(false, false, false); - _view->setShadowingEnabled(false); - _view->setScreenSpaceRefractionEnabled(false); - setPostProcessing(false); - - _view->setScene(_scene); - _view->setCamera(_mainCamera); + createView(); const float aperture = _mainCamera->getAperture(); const float shutterSpeed = _mainCamera->getShutterSpeed(); @@ -197,7 +173,6 @@ namespace thermion_filament EntityManager &em = EntityManager::get(); _sceneManager = new SceneManager( - _view, _resourceLoaderWrapper, _engine, _scene, @@ -205,80 +180,6 @@ namespace thermion_filament _mainCamera); } - void FilamentViewer::setAntiAliasing(bool msaa, bool fxaa, bool taa) - { - View::MultiSampleAntiAliasingOptions multiSampleAntiAliasingOptions; - multiSampleAntiAliasingOptions.enabled = msaa; - - _view->setMultiSampleAntiAliasingOptions(multiSampleAntiAliasingOptions); - TemporalAntiAliasingOptions taaOpts; - taaOpts.enabled = taa; - _view->setTemporalAntiAliasingOptions(taaOpts); - _view->setAntiAliasing(fxaa ? AntiAliasing::FXAA : AntiAliasing::NONE); - } - - void FilamentViewer::setPostProcessing(bool enabled) - { - _view->setPostProcessingEnabled(enabled); - } - - void FilamentViewer::setShadowsEnabled(bool enabled) - { - _view->setShadowingEnabled(enabled); - } - - void FilamentViewer::setShadowType(ShadowType shadowType) - { - _view->setShadowType(shadowType); - } - - void FilamentViewer::setSoftShadowOptions(float penumbraScale, float penumbraRatioScale) - { - SoftShadowOptions opts; - opts.penumbraRatioScale = penumbraRatioScale; - opts.penumbraScale = penumbraScale; - _view->setSoftShadowOptions(opts); - } - - void FilamentViewer::setBloom(float strength) - { -#ifndef __EMSCRIPTEN__ - decltype(_view->getBloomOptions()) opts; - opts.enabled = true; - opts.strength = strength; - _view->setBloomOptions(opts); -#endif - } - - void FilamentViewer::setToneMapping(ToneMapping toneMapping) - { - - ToneMapper *tm; - switch (toneMapping) - { - case ToneMapping::ACES: - Log("Setting tone mapping to ACES"); - tm = new ACESToneMapper(); - break; - case ToneMapping::LINEAR: - Log("Setting tone mapping to Linear"); - tm = new LinearToneMapper(); - break; - case ToneMapping::FILMIC: - Log("Setting tone mapping to Filmic"); - tm = new FilmicToneMapper(); - break; - default: - Log("ERROR: Unsupported tone mapping"); - return; - } - - auto newColorGrading = ColorGrading::Builder().toneMapper(tm).build(*_engine); - _view->setColorGrading(newColorGrading); - _engine->destroy(colorGrading); - delete tm; - } - void FilamentViewer::setFrameInterval(float frameInterval) { _frameInterval = frameInterval; @@ -307,7 +208,7 @@ namespace thermion_filament bool shadows) { auto light = EntityManager::get().create(); - + auto result = LightManager::Builder(t) .color(Color::cct(colour)) .intensity(intensity) @@ -333,36 +234,38 @@ namespace thermion_filament return Entity::smuggle(light); } - void FilamentViewer::setLightPosition(EntityId entityId, float x, float y, float z) { + void FilamentViewer::setLightPosition(EntityId entityId, float x, float y, float z) + { auto light = Entity::import(entityId); - if(light.isNull()) { + if (light.isNull()) + { Log("Light not found for entity %d", entityId); return; } - auto& lm = _engine->getLightManager(); + auto &lm = _engine->getLightManager(); auto instance = lm.getInstance(light); - lm.setPosition(instance, filament::math::float3 { x, y, z }); - + lm.setPosition(instance, filament::math::float3{x, y, z}); } - void FilamentViewer::setLightDirection(EntityId entityId, float x, float y, float z) { + void FilamentViewer::setLightDirection(EntityId entityId, float x, float y, float z) + { auto light = Entity::import(entityId); - if(light.isNull()) { + if (light.isNull()) + { Log("Light not found for entity %d", entityId); return; } - auto& lm = _engine->getLightManager(); + auto &lm = _engine->getLightManager(); auto instance = lm.getInstance(light); - lm.setDirection(instance, filament::math::float3 { x, y, z }); - + lm.setDirection(instance, filament::math::float3{x, y, z}); } void FilamentViewer::removeLight(EntityId entityId) @@ -608,7 +511,7 @@ namespace thermion_filament } } - void FilamentViewer::setBackgroundImage(const char *resourcePath, bool fillHeight) + void FilamentViewer::setBackgroundImage(const char *resourcePath, bool fillHeight, uint32_t width, uint32_t height) { std::lock_guard lock(_imageMutex); @@ -624,9 +527,7 @@ namespace thermion_filament // This currently just anchors the image at the bottom left of the viewport at its original size // TODO - implement stretch/etc - const Viewport &vp = _view->getViewport(); - - float xScale = float(vp.width) / float(_imageWidth); + float xScale = float(width) / float(_imageWidth); float yScale; if (fillHeight) @@ -635,7 +536,7 @@ namespace thermion_filament } else { - yScale = float(vp.height) / float(_imageHeight); + yScale = float(height) / float(_imageHeight); } _imageScale = mat4f{xScale, 0.0f, 0.0f, 0.0f, 0.0f, yScale, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; @@ -643,7 +544,6 @@ namespace thermion_filament _imageMaterial->setDefaultParameter("transform", _imageScale); _imageMaterial->setDefaultParameter("image", _imageTexture, _imageSampler); _imageMaterial->setDefaultParameter("showImage", 1); - } /// @@ -652,7 +552,7 @@ namespace thermion_filament /// are positioned at a max/min of -1/1 respectively /// (i.e. you cannot set a position where the left/top or right/bottom sides would be "inside" the screen coordinate space). /// - void FilamentViewer::setBackgroundImagePosition(float x, float y, bool clamp = false) + void FilamentViewer::setBackgroundImagePosition(float x, float y, bool clamp = false, uint32_t width = 0, uint32_t height = 0) { std::lock_guard lock(_imageMutex); @@ -678,8 +578,8 @@ namespace thermion_filament { Log("Clamping background image translation"); // first, clamp x/y - auto xScale = float(_imageWidth) / _view->getViewport().width; - auto yScale = float(_imageHeight) / _view->getViewport().height; + auto xScale = float(_imageWidth) / width; + auto yScale = float(_imageHeight) / height; float xMin = 0; float xMax = 0; @@ -720,31 +620,30 @@ namespace thermion_filament // i.e. translating the image right by 0.5 units means translating the UV coordinates left by 0.5 units. x = -x; y = -y; - Log("x %f y %f", x, y); - - Log("imageScale %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f ", _imageScale[0][0], _imageScale[0][1], _imageScale[0][2], _imageScale[0][3], - _imageScale[1][0], _imageScale[1][1], _imageScale[1][2], _imageScale[1][3], - _imageScale[2][0], _imageScale[2][1], _imageScale[2][2], _imageScale[2][3], - _imageScale[3][0], _imageScale[3][1], _imageScale[3][2], _imageScale[3][3]); auto transform = math::mat4f::translation(filament::math::float3(x, y, 0.0f)) * _imageScale; - Log("transform %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f ", transform[0][0], transform[0][1], transform[0][2], transform[0][3], - transform[1][0], transform[1][1], transform[1][2], transform[1][3], - transform[2][0], transform[2][1], transform[2][2], transform[2][3], - transform[3][0], transform[3][1], transform[3][2], transform[3][3]); _imageMaterial->setDefaultParameter("transform", transform); } FilamentViewer::~FilamentViewer() { clearLights(); - for(auto swapChain : _swapChains) { + + for (auto view : _views) + { + _engine->destroy(view); + } + + _views.clear(); + + for (auto swapChain : _swapChains) + { _engine->destroy(swapChain); } _swapChains.clear(); - + if (!_imageEntity.isNull()) { _engine->destroy(_imageEntity); @@ -756,7 +655,6 @@ namespace thermion_filament delete _sceneManager; _engine->destroyCameraComponent(_mainCamera->getEntity()); _mainCamera = nullptr; - _engine->destroy(_view); _engine->destroy(_scene); _engine->destroy(_renderer); Engine::destroy(&_engine); @@ -765,10 +663,10 @@ namespace thermion_filament Renderer *FilamentViewer::getRenderer() { return _renderer; } - SwapChain* FilamentViewer::createSwapChain(const void *window, uint32_t width, uint32_t height) + SwapChain *FilamentViewer::createSwapChain(const void *window, uint32_t width, uint32_t height) { std::lock_guard lock(_renderMutex); - SwapChain* swapChain; + SwapChain *swapChain; #if TARGET_OS_IPHONE swapChain = _engine->createSwapChain((void *)window, filament::backend::SWAP_CHAIN_CONFIG_TRANSPARENT | filament::backend::SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER); #else @@ -787,58 +685,58 @@ namespace thermion_filament return swapChain; } - RenderTarget* FilamentViewer::createRenderTarget(intptr_t texture, uint32_t width, uint32_t height) + RenderTarget *FilamentViewer::createRenderTarget(intptr_t texture, uint32_t width, uint32_t height) { // Create filament textures and render targets (note the color buffer has the import call) auto rtColor = filament::Texture::Builder() - .width(width) - .height(height) - .levels(1) - .usage(filament::Texture::Usage::COLOR_ATTACHMENT | filament::Texture::Usage::SAMPLEABLE) - .format(filament::Texture::InternalFormat::RGBA8) - .import(texture) - .build(*_engine); + .width(width) + .height(height) + .levels(1) + .usage(filament::Texture::Usage::COLOR_ATTACHMENT | filament::Texture::Usage::SAMPLEABLE) + .format(filament::Texture::InternalFormat::RGBA8) + .import(texture) + .build(*_engine); auto rtDepth = filament::Texture::Builder() - .width(width) - .height(height) - .levels(1) - .usage(filament::Texture::Usage::DEPTH_ATTACHMENT | filament::Texture::Usage::SAMPLEABLE) - .format(filament::Texture::InternalFormat::DEPTH32F) - .build(*_engine); + .width(width) + .height(height) + .levels(1) + .usage(filament::Texture::Usage::DEPTH_ATTACHMENT | filament::Texture::Usage::SAMPLEABLE) + .format(filament::Texture::InternalFormat::DEPTH32F) + .build(*_engine); auto rt = filament::RenderTarget::Builder() - .texture(RenderTarget::AttachmentPoint::COLOR, rtColor) - .texture(RenderTarget::AttachmentPoint::DEPTH, rtDepth) - .build(*_engine); - return rt; + .texture(RenderTarget::AttachmentPoint::COLOR, rtColor) + .texture(RenderTarget::AttachmentPoint::DEPTH, rtDepth) + .build(*_engine); + return rt; } - void FilamentViewer::destroyRenderTarget(RenderTarget* renderTarget) { + void FilamentViewer::destroyRenderTarget(RenderTarget *renderTarget) + { std::lock_guard lock(_renderMutex); auto rtDepth = renderTarget->getTexture(RenderTarget::AttachmentPoint::DEPTH); - if(rtDepth) { + if (rtDepth) + { _engine->destroy(rtDepth); } auto rtColor = renderTarget->getTexture(RenderTarget::AttachmentPoint::COLOR); - if(rtColor) { + if (rtColor) + { _engine->destroy(rtColor); } - _engine->destroy(renderTarget); + _engine->destroy(renderTarget); auto it = std::find(_renderTargets.begin(), _renderTargets.end(), renderTarget); - if(it != _renderTargets.end()) { + if (it != _renderTargets.end()) + { _renderTargets.erase(it); } } - void FilamentViewer::setRenderTarget(RenderTarget *renderTarget) { - std::lock_guard lock(_renderMutex); - _view->setRenderTarget(renderTarget); - } - void FilamentViewer::destroySwapChain(SwapChain *swapChain) { std::lock_guard lock(_renderMutex); auto it = std::find(_swapChains.begin(), _swapChains.end(), swapChain); - if(it != _swapChains.end()) { + if (it != _swapChains.end()) + { _swapChains.erase(it); } _engine->destroy(swapChain); @@ -850,9 +748,55 @@ namespace thermion_filament #endif } + /// + /// + /// + View *FilamentViewer::createView() + { + auto *view = _engine->createView(); + view->setLayerEnabled(SceneManager::LAYERS::DEFAULT_ASSETS, true); + view->setLayerEnabled(SceneManager::LAYERS::BACKGROUND, true); // skybox + image + view->setLayerEnabled(SceneManager::LAYERS::OVERLAY, false); // world grid + gizmo + view->setBlendMode(filament::View::BlendMode::TRANSLUCENT); + view->setStencilBufferEnabled(true); + view->setAmbientOcclusionOptions({.enabled = false}); + view->setDynamicResolutionOptions({.enabled = false}); +#if defined(_WIN32) + view->setStereoscopicOptions({.enabled = true}); +#endif + + // there's a glitch on certain iGPUs where nothing will render when postprocessing is enabled and bloom is disabled + // set bloom to a small value here + view->setBloomOptions({.strength = 0.01}); + view->setDithering(filament::Dithering::NONE); + view->setShadowingEnabled(false); + view->setScreenSpaceRefractionEnabled(false); + view->setPostProcessingEnabled(false); + view->setScene(_scene); + view->setCamera(_mainCamera); + + _views.push_back(view); + return view; + } + + /// + /// + /// + View *FilamentViewer::getViewAt(int32_t index) + { + Log("Getting view at %d", index); + if (index < _views.size()) + { + return _views[index]; + } + return nullptr; + } + + /// @brief + /// + /// void FilamentViewer::clearEntities() { - _view->setCamera(_mainCamera); _sceneManager->destroyAll(); } @@ -867,9 +811,9 @@ namespace thermion_filament /// /// /// - void FilamentViewer::setMainCamera() + void FilamentViewer::setMainCamera(View *view) { - _view->setCamera(_mainCamera); + view->setCamera(_mainCamera); } /// @@ -880,73 +824,6 @@ namespace thermion_filament return Entity::smuggle(_mainCamera->getEntity()); } - /// - /// Sets the active camera to the GLTF camera node specified by [name] (or if null, the first camera found under that node). - /// N.B. Blender will generally export a three-node hierarchy - - /// Camera1->Camera_Orientation->Camera2. The correct name will be the Camera_Orientation. - /// - bool FilamentViewer::setCamera(EntityId entityId, const char *cameraName) - { - - auto asset = _sceneManager->getAssetByEntityId(entityId); - if (!asset) - { - Log("Failed to find asset under entity id %d.", entityId); - return false; - } - size_t count = asset->getCameraEntityCount(); - if (count == 0) - { - Log("No cameras found attached to specified entity."); - return false; - } - - const utils::Entity *cameras = asset->getCameraEntities(); - - utils::Entity target; - - if (!cameraName) - { - target = cameras[0]; - const char *name = asset->getName(target); - Log("No camera specified, using first camera node found (%s)", name); - } - else - { - for (int j = 0; j < count; j++) - { - const char *name = asset->getName(cameras[j]); - if (strcmp(name, cameraName) == 0) - { - target = cameras[j]; - break; - } - } - } - if (target.isNull()) - { - Log("Unable to locate camera under name %s ", cameraName); - return false; - } - - Camera *camera = _engine->getCameraComponent(target); - if (!camera) - { - Log("Failed to retrieve camera component for target"); - return false; - } - _view->setCamera(camera); - - const Viewport &vp = _view->getViewport(); - const double aspect = (double)vp.width / vp.height; - - camera->setScaling({1.0 / aspect, 1.0}); - - Log("Successfully set view camera to target"); - - return true; - } - void FilamentViewer::loadSkybox(const char *const skyboxPath) { @@ -990,8 +867,8 @@ namespace thermion_filament callbackData); _skybox = filament::Skybox::Builder() - .environment(_skyboxTexture) - .build(*_engine); + .environment(_skyboxTexture) + .build(*_engine); _skybox->setLayerMask(0xFF, 1u << SceneManager::LAYERS::BACKGROUND); @@ -1046,13 +923,25 @@ namespace thermion_filament .build(*_engine); // Create a copy of the cubemap data - float *pixelData = new float[18] { - r, g, b, - r, g, b, - r, g, b, - r, g, b, - r, g, b, - r, g, b, + float *pixelData = new float[18]{ + r, + g, + b, + r, + g, + b, + r, + g, + b, + r, + g, + b, + r, + g, + b, + r, + g, + b, }; Texture::PixelBufferDescriptor::Callback freeCallback = [](void *buf, size_t, void *data) @@ -1126,13 +1015,14 @@ namespace thermion_filament bool FilamentViewer::render( uint64_t frameTimeInNanos, - SwapChain* swapChain, + View *view, + SwapChain *swapChain, void *pixelBuffer, void (*callback)(void *buf, size_t size, void *data), void *data) { - if (!_view || !swapChain) + if (!view || !swapChain) { return false; } @@ -1155,15 +1045,6 @@ namespace thermion_filament _cumulativeAnimationUpdateTime += tmr.elapsed(); - // if a manipulator is active, update the active camera orientation - if (_manipulator) - { - math::double3 eye, target, upward; - Camera &cam = _view->getCamera(); - _manipulator->getLookAt(&eye, &target, &upward); - cam.lookAt(eye, target, upward); - } - // Render the scene, unless the renderer wants to skip the frame. bool beginFrame = _renderer->beginFrame(swapChain, frameTimeInNanos); if (!beginFrame) @@ -1174,7 +1055,7 @@ namespace thermion_filament if (beginFrame) { - _renderer->render(_view); + _renderer->render(view); _frameCount++; @@ -1186,21 +1067,24 @@ namespace thermion_filament return beginFrame; } - class CaptureCallbackHandler : public filament::backend::CallbackHandler { - void post(void* user, Callback callback) { - callback(user); - } + class CaptureCallbackHandler : public filament::backend::CallbackHandler + { + void post(void *user, Callback callback) + { + callback(user); + } }; - void FilamentViewer::capture(uint8_t *out, bool useFence, SwapChain* swapChain, void (*onComplete)()) + void FilamentViewer::capture(View *view, uint8_t *out, bool useFence, SwapChain *swapChain, void (*onComplete)()) { - if(!swapChain) { + if (!swapChain) + { Log("NO SWAPCHAIN"); return; } - Viewport const &vp = _view->getViewport(); + Viewport const &vp = view->getViewport(); size_t pixelBufferSize = vp.width * vp.height * 4; auto *pixelBuffer = new uint8_t[pixelBufferSize]; auto callback = [](void *buf, size_t size, void *data) @@ -1211,15 +1095,17 @@ namespace thermion_filament memcpy(out, buf, size); delete frameCallbackData; - if(callbackPtr) { + if (callbackPtr) + { void (*callback)(void) = (void (*)(void))callbackPtr; callback(); } }; // Create a fence - Fence* fence = nullptr; - if(useFence) { + Fence *fence = nullptr; + if (useFence) + { fence = _engine->createFence(); } @@ -1232,7 +1118,7 @@ namespace thermion_filament Texture::Format::RGBA, Texture::Type::UBYTE, dispatcher, callback, userData); _renderer->beginFrame(swapChain, 0); - _renderer->render(_view); + _renderer->render(view); _renderer->readPixels(0, 0, vp.width, vp.height, std::move(pbd)); _renderer->endFrame(); @@ -1240,20 +1126,22 @@ namespace thermion_filament _engine->execute(); emscripten_webgl_commit_frame(); #endif - if(fence) { - Fence::waitAndDestroy(fence); - } + if (fence) + { + Fence::waitAndDestroy(fence); + } } - void FilamentViewer::capture(uint8_t *out, bool useFence, SwapChain* swapChain, RenderTarget* renderTarget, void (*onComplete)()) + void FilamentViewer::capture(View *view, uint8_t *out, bool useFence, SwapChain *swapChain, RenderTarget *renderTarget, void (*onComplete)()) { - if(!renderTarget) { + if (!renderTarget) + { Log("NO SWAPCHAIN"); return; } - Viewport const &vp = _view->getViewport(); + Viewport const &vp = view->getViewport(); size_t pixelBufferSize = vp.width * vp.height * 4; auto *pixelBuffer = new uint8_t[pixelBufferSize]; auto callback = [](void *buf, size_t size, void *data) @@ -1264,15 +1152,17 @@ namespace thermion_filament memcpy(out, buf, size); delete frameCallbackData; - if(callbackPtr) { + if (callbackPtr) + { void (*callback)(void) = (void (*)(void))callbackPtr; callback(); } }; // Create a fence - Fence* fence = nullptr; - if(useFence) { + Fence *fence = nullptr; + if (useFence) + { fence = _engine->createFence(); } @@ -1285,7 +1175,7 @@ namespace thermion_filament Texture::Format::RGBA, Texture::Type::UBYTE, dispatcher, callback, userData); _renderer->beginFrame(swapChain, 0); - _renderer->render(_view); + _renderer->render(view); _renderer->readPixels(renderTarget, 0, 0, vp.width, vp.height, std::move(pbd)); _renderer->endFrame(); @@ -1293,138 +1183,22 @@ namespace thermion_filament _engine->execute(); emscripten_webgl_commit_frame(); #endif - if(fence) { - Fence::waitAndDestroy(fence); - } + if (fence) + { + Fence::waitAndDestroy(fence); + } } - Camera* FilamentViewer::getCamera(EntityId entity) { + Camera *FilamentViewer::getCamera(EntityId entity) + { return _engine->getCameraComponent(Entity::import(entity)); } - void FilamentViewer::updateViewport( - uint32_t width, uint32_t height) - { - _view->setViewport({0, 0, width, height}); - } - - void FilamentViewer::setViewFrustumCulling(bool enabled) - { - _view->setFrustumCullingEnabled(enabled); - } - - void FilamentViewer::_createManipulator() - { - Camera &cam = _view->getCamera(); - - math::double3 home = cam.getPosition(); - math::double3 up = cam.getUpVector(); - auto fv = cam.getForwardVector(); - math::double3 target = home + fv; - Viewport const &vp = _view->getViewport(); - - _manipulator = Manipulator::Builder() - .viewport(vp.width, vp.height) - .upVector(up.x, up.y, up.z) - .zoomSpeed(_zoomSpeed) - .targetPosition(target[0], target[1], target[2]) - // only applicable to Mode::ORBIT - .orbitHomePosition(home[0], home[1], home[2]) - .orbitSpeed(_orbitSpeedX, _orbitSpeedY) - // only applicable to Mode::FREE_FLIGHT - .flightStartPosition(home[0], home[1], home[2]) - .build(_manipulatorMode); - } - - void FilamentViewer::setCameraManipulatorOptions(filament::camutils::Mode mode, double orbitSpeedX, double orbitSpeedY, double zoomSpeed) - { - _manipulatorMode = mode; - _orbitSpeedX = orbitSpeedX; - _orbitSpeedY = orbitSpeedY; - _zoomSpeed = zoomSpeed; - } - - void FilamentViewer::grabBegin(float x, float y, bool pan) - { - if (!_view || !_mainCamera) - { - Log("View not ready, ignoring grab"); - return; - } - if (!_manipulator) - { - _createManipulator(); - } - _manipulator->grabBegin(x, y, pan); - } - - void FilamentViewer::grabUpdate(float x, float y) - { - if (!_view ) - { - Log("View not ready, ignoring grab"); - return; - } - - if (_manipulator) - { - _manipulator->grabUpdate(x, y); - } - else - { - Log("Error - trying to use a manipulator when one is not available. Ensure you call grabBegin before grabUpdate/grabEnd"); - } - } - - void FilamentViewer::grabEnd() - { - if (!_view || !_mainCamera ) - { - Log("View not ready, ignoring grab"); - return; - } - if (_manipulator) - { - _manipulator->grabEnd(); - } - else - { - Log("Error - trying to use a manipulator when one is not available. Ensure you call grabBegin before grabUpdate/grabEnd"); - } - delete _manipulator; - _manipulator = nullptr; - } - - void FilamentViewer::scrollBegin() - { - if (!_manipulator) - { - _createManipulator(); - } - } - - void FilamentViewer::scrollUpdate(float x, float y, float delta) - { - if (_manipulator) - { - _manipulator->scroll(int(x), int(y), delta); - } - else - { - Log("Error - trying to use a manipulator when one is not available. Ensure you call grabBegin before grabUpdate/grabEnd"); - } - } - - void FilamentViewer::scrollEnd() - { - delete _manipulator; - _manipulator = nullptr; - } - - void FilamentViewer::pick(uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y)) + void FilamentViewer::pick(View *view, uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y)) { - _view->pick(x, y, [=](filament::View::PickingQueryResult const &result) { + view->pick(x, y, [=](filament::View::PickingQueryResult const &result) + { if(_sceneManager->gizmo->isGizmoEntity(result.renderable)) { Log("Gizmo entity, ignoring"); @@ -1438,24 +1212,23 @@ namespace thermion_filament if (nonPickableEntities.find(result.renderable) == nonPickableEntities.end()) { callback(Entity::smuggle(result.renderable), x, y); - } - }); + } }); } - void FilamentViewer::unprojectTexture(EntityId entityId, uint8_t* input, uint32_t inputWidth, uint32_t inputHeight, uint8_t* out, uint32_t outWidth, uint32_t outHeight) { - const auto * geometry = _sceneManager->getGeometry(entityId); - if(!geometry->uvs) { - Log("No UVS"); - return; + void FilamentViewer::unprojectTexture(EntityId entityId, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight) + { + const auto *geometry = _sceneManager->getGeometry(entityId); + if (!geometry->uvs) + { + Log("No UVS"); + return; } - - UnprojectTexture unproject(geometry, _view->getCamera(), _engine); + + // UnprojectTexture unproject(geometry, _view->getCamera(), _engine); // TODO - check that input dimensions match viewport? - - unproject.unproject(utils::Entity::import(entityId), input, out, inputWidth, inputHeight, outWidth, outHeight); + + // unproject.unproject(utils::Entity::import(entityId), input, out, inputWidth, inputHeight, outWidth, outHeight); } - - } // namespace thermion_filament diff --git a/thermion_dart/native/src/Gizmo.cpp b/thermion_dart/native/src/Gizmo.cpp index 7041c629..d136498a 100644 --- a/thermion_dart/native/src/Gizmo.cpp +++ b/thermion_dart/native/src/Gizmo.cpp @@ -14,12 +14,10 @@ namespace thermion_filament { using namespace filament::gltfio; -Gizmo::Gizmo(Engine &engine, View* view, Scene* scene) : _engine(engine) +Gizmo::Gizmo(Engine &engine, Scene* scene) : _engine(engine) { _scene = scene; - _view = view; - _camera = &(_view->getCamera()); auto &entityManager = EntityManager::get(); @@ -326,10 +324,10 @@ void Gizmo::unhighlight() { } } -void Gizmo::pick(uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y)) +void Gizmo::pick(View *view, uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y)) { auto handler = new Gizmo::PickCallbackHandler(this, callback); - _view->pick(x, y, [=](filament::View::PickingQueryResult const &result) { + view->pick(x, y, [=](filament::View::PickingQueryResult const &result) { handler->handle(result); }); } diff --git a/thermion_dart/native/src/SceneManager.cpp b/thermion_dart/native/src/SceneManager.cpp index 261a5655..b5cf75ad 100644 --- a/thermion_dart/native/src/SceneManager.cpp +++ b/thermion_dart/native/src/SceneManager.cpp @@ -48,13 +48,12 @@ namespace thermion_filament using namespace filament::gltfio; using std::unique_ptr; - SceneManager::SceneManager(View *view, - const ResourceLoaderWrapperImpl *const resourceLoaderWrapper, + SceneManager::SceneManager(const ResourceLoaderWrapperImpl *const resourceLoaderWrapper, Engine *engine, Scene *scene, const char *uberArchivePath, Camera *mainCamera) - : _view(view), + : _resourceLoaderWrapper(resourceLoaderWrapper), _engine(engine), _scene(scene), @@ -99,21 +98,16 @@ namespace thermion_filament _collisionComponentManager = new CollisionComponentManager(tm); _animationComponentManager = new AnimationComponentManager(tm, _engine->getRenderableManager()); - gizmo = new Gizmo(*_engine, _view, _scene); + gizmo = new Gizmo(*_engine, _scene); _gridOverlay = new GridOverlay(*_engine); _scene->addEntity(_gridOverlay->sphere()); _scene->addEntity(_gridOverlay->grid()); - _view->setLayerEnabled(SceneManager::LAYERS::DEFAULT_ASSETS, true); - _view->setLayerEnabled(SceneManager::LAYERS::BACKGROUND, true); // skybox + image - _view->setLayerEnabled(SceneManager::LAYERS::OVERLAY, false); // world grid + gizmo } SceneManager::~SceneManager() { - _view->setScene(nullptr); - _view->setCamera(nullptr); for(auto camera : _cameras) { auto entity = camera->getEntity(); _engine->destroyCameraComponent(entity); @@ -1894,11 +1888,11 @@ namespace thermion_filament tm.setTransform(transformInstance, newTransform); } - void SceneManager::queueRelativePositionUpdateFromViewportVector(EntityId entityId, float viewportCoordX, float viewportCoordY) + void SceneManager::queueRelativePositionUpdateFromViewportVector(View* view, EntityId entityId, float viewportCoordX, float viewportCoordY) { // Get the camera and viewport - const auto &camera = _view->getCamera(); - const auto &vp = _view->getViewport(); + const auto &camera = view->getCamera(); + const auto &vp = view->getViewport(); // Convert viewport coordinates to NDC space float ndcX = (2.0f * viewportCoordX) / vp.width - 1.0f; @@ -2170,10 +2164,10 @@ namespace thermion_filament rm.setPriority(renderableInstance, priority); } - Aabb2 SceneManager::getBoundingBox(EntityId entityId) + Aabb2 SceneManager::getBoundingBox(View *view, EntityId entityId) { - const auto &camera = _view->getCamera(); - const auto &viewport = _view->getViewport(); + const auto &camera = view->getCamera(); + const auto &viewport = view->getViewport(); auto &tcm = _engine->getTransformManager(); auto &rcm = _engine->getRenderableManager(); @@ -2242,11 +2236,6 @@ namespace thermion_filament return Aabb2{minX, minY, maxX, maxY}; } - void SceneManager::setLayerVisibility(LAYERS layer, bool enabled) - { - _view->setLayerEnabled(layer, enabled); - } - void SceneManager::removeStencilHighlight(EntityId entityId) { std::lock_guard lock(_stencilMutex); @@ -2491,10 +2480,6 @@ EntityId SceneManager::createGeometry( } } - void SceneManager::setCamera(Camera* camera) { - _view->setCamera(camera); - } - size_t SceneManager::getCameraCount() { return _cameras.size() + 1; } @@ -2508,11 +2493,6 @@ EntityId SceneManager::createGeometry( } return _cameras[index-1]; } - - Camera* SceneManager::getActiveCamera() { - auto& camera = _view->getCamera(); - return &camera; - } } // namespace thermion_filament diff --git a/thermion_dart/native/src/TGizmo.cpp b/thermion_dart/native/src/TGizmo.cpp new file mode 100644 index 00000000..8142caf5 --- /dev/null +++ b/thermion_dart/native/src/TGizmo.cpp @@ -0,0 +1,29 @@ +#ifdef _WIN32 +#pragma comment(lib, "Shlwapi.lib") +#pragma comment(lib, "opengl32.lib") +#endif + +#include "ResourceBuffer.hpp" +#include "FilamentViewer.hpp" +#include "filament/LightManager.h" +#include "Log.hpp" +#include "ThreadPool.hpp" + +#include +#include + +#ifdef __EMSCRIPTEN__ +#include +#endif + +using namespace thermion_filament; + +extern "C" +{ + EMSCRIPTEN_KEEPALIVE void Gizmo_pick(TGizmo *tGizmo, TView *tView, int x, int y, void (*callback)(EntityId entityId, int x, int y)) + { + auto *gizmo = reinterpret_cast(tGizmo); + auto *view = reinterpret_cast(tView); + gizmo->pick(view, x, y, callback); + } +} \ No newline at end of file diff --git a/thermion_dart/native/src/TView.cpp b/thermion_dart/native/src/TView.cpp new file mode 100644 index 00000000..826d2c91 --- /dev/null +++ b/thermion_dart/native/src/TView.cpp @@ -0,0 +1,142 @@ +#ifdef _WIN32 +#pragma comment(lib, "Shlwapi.lib") +#pragma comment(lib, "opengl32.lib") +#endif + +#include "ResourceBuffer.hpp" +#include "FilamentViewer.hpp" +#include "filament/LightManager.h" +#include "Log.hpp" +#include "ThreadPool.hpp" + +#include +#include + +#ifdef __EMSCRIPTEN__ +#include +#endif + +using namespace thermion_filament; + +extern "C" +{ + +#include "ThermionDartApi.h" + + EMSCRIPTEN_KEEPALIVE void View_updateViewport(TView *tView, uint32_t width, uint32_t height) + { + auto view = reinterpret_cast(tView); + view->setViewport({0, 0, width, height}); + } + + EMSCRIPTEN_KEEPALIVE void View_setRenderTarget(TView *tView, TRenderTarget *tRenderTarget) + { + auto view = reinterpret_cast(tView); + auto renderTarget = reinterpret_cast(tRenderTarget); + view->setRenderTarget(renderTarget); + } + + EMSCRIPTEN_KEEPALIVE void View_setFrustumCullingEnabled(TView *tView, bool enabled) + { + auto view = reinterpret_cast(tView); + view->setFrustumCullingEnabled(enabled); + } + + EMSCRIPTEN_KEEPALIVE void View_setPostProcessing(TView *tView, bool enabled) + { + auto view = reinterpret_cast(tView); + view->setPostProcessingEnabled(enabled); + } + + EMSCRIPTEN_KEEPALIVE void View_setShadowsEnabled(TView *tView, bool enabled) + { + auto view = reinterpret_cast(tView); + view->setShadowingEnabled(enabled); + } + + EMSCRIPTEN_KEEPALIVE void View_setShadowType(TView *tView, ShadowType shadowType) + { + auto view = reinterpret_cast(tView); + view->setShadowType(shadowType); + } + + EMSCRIPTEN_KEEPALIVE void View_setSoftShadowOptions(TView *tView, float penumbraScale, float penumbraRatioScale) + { + auto view = reinterpret_cast(tView); + SoftShadowOptions opts; + opts.penumbraRatioScale = penumbraRatioScale; + opts.penumbraScale = penumbraScale; + view->setSoftShadowOptions(opts); + } + + EMSCRIPTEN_KEEPALIVE void View_setBloom(TView *tView, float strength) + { + auto view = reinterpret_cast(tView); +#ifndef __EMSCRIPTEN__ + decltype(view->getBloomOptions()) opts; + opts.enabled = true; + opts.strength = strength; + view->setBloomOptions(opts); +#endif + } + + EMSCRIPTEN_KEEPALIVE void View_setToneMapping(TView *tView, TEngine *tEngine, int toneMapping) + { + auto view = reinterpret_cast(tView); + auto engine = reinterpret_cast(tEngine); + + ToneMapper *tm; + switch (toneMapping) + { + case ToneMapping::ACES: + Log("Setting tone mapping to ACES"); + tm = new ACESToneMapper(); + break; + case ToneMapping::LINEAR: + Log("Setting tone mapping to Linear"); + tm = new LinearToneMapper(); + break; + case ToneMapping::FILMIC: + Log("Setting tone mapping to Filmic"); + tm = new FilmicToneMapper(); + break; + default: + Log("ERROR: Unsupported tone mapping"); + return; + } + auto newColorGrading = ColorGrading::Builder().toneMapper(tm).build(*engine); + auto oldColorGrading = view->getColorGrading(); + view->setColorGrading(newColorGrading); + + if (oldColorGrading) + { + engine->destroy(oldColorGrading); + } + delete tm; + } + + void View_setAntiAliasing(TView *tView, bool msaa, bool fxaa, bool taa) + { + auto view = reinterpret_cast(tView); + View::MultiSampleAntiAliasingOptions multiSampleAntiAliasingOptions; + multiSampleAntiAliasingOptions.enabled = msaa; + + view->setMultiSampleAntiAliasingOptions(multiSampleAntiAliasingOptions); + TemporalAntiAliasingOptions taaOpts; + taaOpts.enabled = taa; + view->setTemporalAntiAliasingOptions(taaOpts); + view->setAntiAliasing(fxaa ? AntiAliasing::FXAA : AntiAliasing::NONE); + } + + EMSCRIPTEN_KEEPALIVE void View_setLayerEnabled(TView* tView, int layer, bool enabled) { + auto view = reinterpret_cast(tView); + view->setLayerEnabled(layer, enabled); + } + + EMSCRIPTEN_KEEPALIVE void View_setCamera(TView *tView, TCamera *tCamera) { + auto view = reinterpret_cast(tView); + auto *camera = reinterpret_cast(tCamera); + view->setCamera(camera); + } + +} \ No newline at end of file diff --git a/thermion_dart/native/src/ThermionDartApi.cpp b/thermion_dart/native/src/ThermionDartApi.cpp index 135921ac..716d3078 100644 --- a/thermion_dart/native/src/ThermionDartApi.cpp +++ b/thermion_dart/native/src/ThermionDartApi.cpp @@ -48,32 +48,28 @@ extern "C" { const auto *loaderImpl = new ResourceLoaderWrapperImpl((ResourceLoaderWrapper *)loader); auto viewer = new FilamentViewer(context, loaderImpl, platform, uberArchivePath); - return reinterpret_cast(viewer); + return reinterpret_cast(viewer); } - EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer* viewer) { - auto* engine = reinterpret_cast(viewer)->getEngine(); - return reinterpret_cast(engine); + EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer *viewer) + { + auto *engine = reinterpret_cast(viewer)->getEngine(); + return reinterpret_cast(engine); } - EMSCRIPTEN_KEEPALIVE TRenderTarget* Viewer_createRenderTarget(TViewer *tViewer, intptr_t texture, uint32_t width, uint32_t height) + EMSCRIPTEN_KEEPALIVE TRenderTarget *Viewer_createRenderTarget(TViewer *tViewer, intptr_t texture, uint32_t width, uint32_t height) { auto viewer = reinterpret_cast(tViewer); auto renderTarget = viewer->createRenderTarget(texture, width, height); - return reinterpret_cast(renderTarget); + return reinterpret_cast(renderTarget); } - EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTarget(TViewer *tViewer, TRenderTarget* tRenderTarget) { + EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTarget(TViewer *tViewer, TRenderTarget *tRenderTarget) + { auto viewer = reinterpret_cast(tViewer); - auto renderTarget = reinterpret_cast(tRenderTarget); + auto renderTarget = reinterpret_cast(tRenderTarget); viewer->destroyRenderTarget(renderTarget); } - - EMSCRIPTEN_KEEPALIVE void Viewer_setRenderTarget(TViewer *tViewer, TRenderTarget* tRenderTarget) { - auto viewer = reinterpret_cast(tViewer); - auto renderTarget = reinterpret_cast(tRenderTarget); - viewer->setRenderTarget(renderTarget); - } EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer(TViewer *viewer) { @@ -92,23 +88,14 @@ extern "C" EMSCRIPTEN_KEEPALIVE void set_background_image(TViewer *viewer, const char *path, bool fillHeight) { - ((FilamentViewer *)viewer)->setBackgroundImage(path, 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); + ((FilamentViewer *)viewer)->setBackgroundImagePosition(x, y, clamp, 100, 100); } - EMSCRIPTEN_KEEPALIVE void set_tone_mapping(TViewer *viewer, int toneMapping) - { - ((FilamentViewer *)viewer)->setToneMapping((ToneMapping)toneMapping); - } - - EMSCRIPTEN_KEEPALIVE void set_bloom(TViewer *viewer, float strength) - { - ((FilamentViewer *)viewer)->setBloom(strength); - } EMSCRIPTEN_KEEPALIVE void load_skybox(TViewer *viewer, const char *skyboxPath) { @@ -221,9 +208,11 @@ extern "C" return ((SceneManager *)sceneManager)->loadGltf(assetPath, relativePath, keepData); } - EMSCRIPTEN_KEEPALIVE void set_main_camera(TViewer *viewer) + EMSCRIPTEN_KEEPALIVE void Viewer_setMainCamera(TViewer *tViewer, TView *tView) { - return ((FilamentViewer *)viewer)->setMainCamera(); + auto *viewer = reinterpret_cast(tViewer); + auto *view = reinterpret_cast(tView); + viewer->setMainCamera(view); } EMSCRIPTEN_KEEPALIVE EntityId get_main_camera(TViewer *viewer) @@ -231,11 +220,6 @@ extern "C" return ((FilamentViewer *)viewer)->getMainCamera(); } - EMSCRIPTEN_KEEPALIVE bool set_camera(TViewer *viewer, EntityId asset, const char *nodeName) - { - return ((FilamentViewer *)viewer)->setCamera(asset, nodeName); - } - EMSCRIPTEN_KEEPALIVE float get_camera_fov(TCamera *camera, bool horizontal) { auto cam = reinterpret_cast(camera); @@ -334,15 +318,7 @@ extern "C" return array; } - EMSCRIPTEN_KEEPALIVE void set_camera_manipulator_options(TViewer *viewer, _ManipulatorMode mode, double orbitSpeedX, double orbitSpeedY, double zoomSpeed) - { - ((FilamentViewer *)viewer)->setCameraManipulatorOptions((filament::camutils::Mode)mode, orbitSpeedX, orbitSpeedY, zoomSpeed); - } - - EMSCRIPTEN_KEEPALIVE void set_view_frustum_culling(TViewer *viewer, bool enabled) - { - ((FilamentViewer *)viewer)->setViewFrustumCulling(enabled); - } + EMSCRIPTEN_KEEPALIVE void set_camera_focus_distance(TCamera *camera, float distance) { @@ -365,20 +341,23 @@ extern "C" EMSCRIPTEN_KEEPALIVE bool Viewer_render( TViewer *tViewer, + TView *tView, TSwapChain *tSwapChain, uint64_t frameTimeInNanos, void *pixelBuffer, void (*callback)(void *buf, size_t size, void *data), void *data) { - auto swapChain = reinterpret_cast(tSwapChain); - auto viewer = reinterpret_cast(tViewer); - return viewer->render(frameTimeInNanos, swapChain, pixelBuffer, callback, data); + auto swapChain = reinterpret_cast(tSwapChain); + auto viewer = reinterpret_cast(tViewer); + auto *view = reinterpret_cast(tView); + return viewer->render(frameTimeInNanos, view, swapChain, pixelBuffer, callback, data); } EMSCRIPTEN_KEEPALIVE void Viewer_capture( TViewer *tViewer, - TSwapChain* tSwapChain, + TView *tView, + TSwapChain *tSwapChain, uint8_t *pixelBuffer, void (*callback)(void)) { @@ -387,14 +366,16 @@ extern "C" #else bool useFence = false; #endif - auto swapChain = reinterpret_cast(tSwapChain); - auto viewer = reinterpret_cast(tViewer); - viewer->capture(pixelBuffer, useFence, swapChain, callback); + 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, - TSwapChain* tSwapChain, + TView *tView, + TSwapChain *tSwapChain, TRenderTarget *tRenderTarget, uint8_t *pixelBuffer, void (*callback)(void)) @@ -404,10 +385,11 @@ extern "C" #else bool useFence = false; #endif - auto swapChain = reinterpret_cast(tSwapChain); - auto renderTarget = reinterpret_cast(tRenderTarget); - auto viewer = reinterpret_cast(tViewer); - viewer->capture(pixelBuffer, useFence, swapChain, renderTarget, callback); + 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( @@ -417,59 +399,41 @@ extern "C" ((FilamentViewer *)viewer)->setFrameInterval(frameInterval); } - EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChain(TViewer *tViewer, TSwapChain* tSwapChain) + EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChain(TViewer *tViewer, TSwapChain *tSwapChain) { - auto viewer = reinterpret_cast(tViewer); - auto swapChain = reinterpret_cast(tSwapChain); + auto viewer = reinterpret_cast(tViewer); + auto swapChain = reinterpret_cast(tSwapChain); viewer->destroySwapChain(swapChain); } - EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createSwapChain(TViewer *tViewer, const void *const window, uint32_t width, uint32_t height) { - auto viewer = reinterpret_cast(tViewer); + EMSCRIPTEN_KEEPALIVE TSwapChain *Viewer_createSwapChain(TViewer *tViewer, const void *const window, uint32_t width, uint32_t height) + { + auto viewer = reinterpret_cast(tViewer); auto swapChain = viewer->createSwapChain(window, width, height); - return reinterpret_cast(swapChain); + return reinterpret_cast(swapChain); } - EMSCRIPTEN_KEEPALIVE void update_viewport(TViewer *viewer, uint32_t width, uint32_t height) + EMSCRIPTEN_KEEPALIVE TView *Viewer_createView(TViewer *tViewer) { - return ((FilamentViewer *)viewer)->updateViewport(width, height); + auto viewer = reinterpret_cast(tViewer); + auto view = viewer->createView(); + return reinterpret_cast(view); } - EMSCRIPTEN_KEEPALIVE void scroll_update(TViewer *viewer, float x, float y, float delta) + EMSCRIPTEN_KEEPALIVE TView *Viewer_getViewAt(TViewer *tViewer, int32_t index) { - ((FilamentViewer *)viewer)->scrollUpdate(x, y, delta); + auto viewer = reinterpret_cast(tViewer); + auto view = viewer->getViewAt(index); + return reinterpret_cast(view); } - EMSCRIPTEN_KEEPALIVE void scroll_begin(TViewer *viewer) - { - ((FilamentViewer *)viewer)->scrollBegin(); - } + - EMSCRIPTEN_KEEPALIVE void scroll_end(TViewer *viewer) + EMSCRIPTEN_KEEPALIVE TSceneManager *Viewer_getSceneManager(TViewer *tViewer) { - ((FilamentViewer *)viewer)->scrollEnd(); - } - - EMSCRIPTEN_KEEPALIVE void grab_begin(TViewer *viewer, float x, float y, bool pan) - { - ((FilamentViewer *)viewer)->grabBegin(x, y, pan); - } - - EMSCRIPTEN_KEEPALIVE void grab_update(TViewer *viewer, float x, float y) - { - ((FilamentViewer *)viewer)->grabUpdate(x, y); - } - - EMSCRIPTEN_KEEPALIVE void grab_end(TViewer *viewer) - { - ((FilamentViewer *)viewer)->grabEnd(); - } - - EMSCRIPTEN_KEEPALIVE TSceneManager* Viewer_getSceneManager(TViewer *tViewer) - { - auto * viewer = reinterpret_cast(tViewer); - auto * sceneManager = viewer->getSceneManager(); - return reinterpret_cast(sceneManager); + auto *viewer = reinterpret_cast(tViewer); + auto *sceneManager = viewer->getSceneManager(); + return reinterpret_cast(sceneManager); } EMSCRIPTEN_KEEPALIVE void apply_weights( @@ -529,31 +493,6 @@ extern "C" ((SceneManager *)sceneManager)->addBoneAnimation(asset, skinIndex, boneIndex, frameData, numFrames, frameLengthInMs, fadeOutInSecs, fadeInInSecs, maxDelta); } - EMSCRIPTEN_KEEPALIVE void set_post_processing(TViewer *viewer, bool enabled) - { - ((FilamentViewer *)viewer)->setPostProcessing(enabled); - } - - EMSCRIPTEN_KEEPALIVE void set_shadows_enabled(TViewer *viewer, bool enabled) - { - ((FilamentViewer *)viewer)->setShadowsEnabled(enabled); - } - - EMSCRIPTEN_KEEPALIVE void set_shadow_type(TViewer *viewer, int shadowType) - { - ((FilamentViewer *)viewer)->setShadowType((ShadowType)shadowType); - } - - EMSCRIPTEN_KEEPALIVE void set_soft_shadow_options(TViewer *viewer, float penumbraScale, float penumbraRatioScale) - { - ((FilamentViewer *)viewer)->setSoftShadowOptions(penumbraScale, penumbraRatioScale); - } - - EMSCRIPTEN_KEEPALIVE void set_antialiasing(TViewer *viewer, bool msaa, bool fxaa, bool taa) - { - ((FilamentViewer *)viewer)->setAntiAliasing(msaa, fxaa, taa); - } - EMSCRIPTEN_KEEPALIVE EntityId get_bone(TSceneManager *sceneManager, EntityId entityId, int skinIndex, @@ -737,6 +676,17 @@ extern "C" } } + EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_getCameraByName(TSceneManager *tSceneManager, EntityId entityId, const char* name) { + auto *sceneManager = reinterpret_cast(tSceneManager); + return nullptr; + } + + EMSCRIPTEN_KEEPALIVE TGizmo* SceneManager_getGizmo(TSceneManager *tSceneManager) { + auto *sceneManager = reinterpret_cast(tSceneManager); + auto *gizmo = sceneManager->gizmo; + return reinterpret_cast(gizmo); + } + EMSCRIPTEN_KEEPALIVE bool SceneManager_setTransform(TSceneManager *sceneManager, EntityId entityId, const double *const transform) { auto matrix = math::mat4( @@ -757,25 +707,27 @@ extern "C" return ((SceneManager *)sceneManager)->setTransform(entityId, matrix); } - EMSCRIPTEN_KEEPALIVE void SceneManager_queueTransformUpdates(TSceneManager *tSceneManager, EntityId* entities, const double* const transforms, int numEntities) { - auto * sceneManager = reinterpret_cast(tSceneManager); + EMSCRIPTEN_KEEPALIVE void SceneManager_queueTransformUpdates(TSceneManager *tSceneManager, EntityId *entities, const double *const transforms, int numEntities) + { + auto *sceneManager = reinterpret_cast(tSceneManager); math::mat4 matrices[numEntities]; - for(int i = 0; i < numEntities; i++) { - matrices[i] = math::mat4( - transforms[i * 16], transforms[i*16+1], transforms[i*16+2], - transforms[i*16+3], - transforms[i*16+4], - transforms[i*16+5], - transforms[i*16+6], - transforms[i*16+7], - transforms[i*16+8], - transforms[i*16+9], - transforms[i*16+10], - transforms[i*16+11], - transforms[i*16+12], - transforms[i*16+13], - transforms[i*16+14], - transforms[i*16+15]); + for (int i = 0; i < numEntities; i++) + { + matrices[i] = math::mat4( + transforms[i * 16], transforms[i * 16 + 1], transforms[i * 16 + 2], + transforms[i * 16 + 3], + transforms[i * 16 + 4], + transforms[i * 16 + 5], + transforms[i * 16 + 6], + transforms[i * 16 + 7], + transforms[i * 16 + 8], + transforms[i * 16 + 9], + transforms[i * 16 + 10], + transforms[i * 16 + 11], + transforms[i * 16 + 12], + transforms[i * 16 + 13], + transforms[i * 16 + 14], + transforms[i * 16 + 15]); } sceneManager->queueTransformUpdates(entities, matrices, numEntities); } @@ -833,9 +785,10 @@ extern "C" ((SceneManager *)sceneManager)->setScale(asset, scale); } - EMSCRIPTEN_KEEPALIVE void queue_position_update_from_viewport_coords(TSceneManager *sceneManager, EntityId entity, float viewportX, float viewportY) + EMSCRIPTEN_KEEPALIVE void queue_position_update_from_viewport_coords(TSceneManager *sceneManager, TView *tView, EntityId entity, float viewportX, float viewportY) { - ((SceneManager *)sceneManager)->queueRelativePositionUpdateFromViewportVector(entity, viewportX, viewportY); + auto *view = reinterpret_cast(tView); + ((SceneManager *)sceneManager)->queueRelativePositionUpdateFromViewportVector(view, entity, viewportX, viewportY); } EMSCRIPTEN_KEEPALIVE void stop_animation(TSceneManager *sceneManager, EntityId asset, int index) @@ -853,9 +806,11 @@ extern "C" return ((SceneManager *)sceneManager)->reveal(asset, meshName); } - EMSCRIPTEN_KEEPALIVE void filament_pick(TViewer *viewer, int x, int y, void (*callback)(EntityId entityId, int x, int y)) + EMSCRIPTEN_KEEPALIVE void filament_pick(TViewer *tViewer, TView* tView, int x, int y, void (*callback)(EntityId entityId, int x, int y)) { - ((FilamentViewer *)viewer)->pick(static_cast(x), static_cast(y), callback); + auto *viewer = reinterpret_cast(tViewer); + auto *view = reinterpret_cast(tView); + ((FilamentViewer *)viewer)->pick(view, static_cast(x), static_cast(y), callback); } EMSCRIPTEN_KEEPALIVE const char *get_name_for_entity(TSceneManager *sceneManager, const EntityId entityId) @@ -965,28 +920,26 @@ extern "C" out[3] = Entity::smuggle(gizmo->center()); } - EMSCRIPTEN_KEEPALIVE Aabb2 get_bounding_box(TSceneManager *sceneManager, EntityId entity) + EMSCRIPTEN_KEEPALIVE Aabb2 get_bounding_box(TSceneManager *sceneManager, TView *tView, EntityId entity) { - return ((SceneManager *)sceneManager)->getBoundingBox(entity); + auto view = reinterpret_cast(tView); + return ((SceneManager *)sceneManager)->getBoundingBox(view, entity); } - EMSCRIPTEN_KEEPALIVE void get_bounding_box_to_out(TSceneManager *sceneManager, EntityId entity, float *minX, float *minY, float *maxX, float *maxY) + EMSCRIPTEN_KEEPALIVE void get_bounding_box_to_out(TSceneManager *sceneManager, TView *tView, EntityId entity, float *minX, float *minY, float *maxX, float *maxY) { - auto box = ((SceneManager *)sceneManager)->getBoundingBox(entity); + auto view = reinterpret_cast(tView); + auto box = ((SceneManager *)sceneManager)->getBoundingBox(view, entity); *minX = box.minX; *minY = box.minY; *maxX = box.maxX; *maxY = box.maxY; } - EMSCRIPTEN_KEEPALIVE void set_visibility_layer(TSceneManager *sceneManager, EntityId entity, int layer) { - ((SceneManager*)sceneManager)->setVisibilityLayer(entity, layer); - } - - - EMSCRIPTEN_KEEPALIVE void set_layer_visibility(TSceneManager *sceneManager, int layer, bool visible) + EMSCRIPTEN_KEEPALIVE void SceneManager_setVisibilityLayer(TSceneManager *tSceneManager, EntityId entity, int layer) { - ((SceneManager *)sceneManager)->setLayerVisibility((SceneManager::LAYERS)layer, visible); + auto *sceneManager = reinterpret_cast(tSceneManager); + sceneManager->setVisibilityLayer(entity, layer); } EMSCRIPTEN_KEEPALIVE void thermion_flutter_free(void *ptr) @@ -994,11 +947,6 @@ extern "C" free(ptr); } - EMSCRIPTEN_KEEPALIVE void pick_gizmo(TSceneManager *sceneManager, int x, int y, void (*callback)(EntityId entityId, int x, int y)) - { - ((SceneManager *)sceneManager)->gizmo->pick(x, y, callback); - } - EMSCRIPTEN_KEEPALIVE void set_gizmo_visibility(TSceneManager *sceneManager, bool visible) { ((SceneManager *)sceneManager)->gizmo->setVisibility(visible); @@ -1019,9 +967,10 @@ extern "C" ((SceneManager *)sceneManager)->setMaterialProperty(entity, materialIndex, property, value); } - EMSCRIPTEN_KEEPALIVE TMaterialInstance* get_material_instance_at(TSceneManager *sceneManager, EntityId entity, int materialIndex) { + EMSCRIPTEN_KEEPALIVE TMaterialInstance *get_material_instance_at(TSceneManager *sceneManager, EntityId entity, int materialIndex) + { auto instance = ((SceneManager *)sceneManager)->getMaterialInstanceAt(entity, materialIndex); - return reinterpret_cast(instance); + return reinterpret_cast(instance); } EMSCRIPTEN_KEEPALIVE void set_material_property_int(TSceneManager *sceneManager, EntityId entity, int materialIndex, const char *property, int32_t value) @@ -1030,7 +979,7 @@ extern "C" } EMSCRIPTEN_KEEPALIVE void set_material_property_float4(TSceneManager *sceneManager, EntityId entity, int materialIndex, const char *property, double4 value) - { + { filament::math::float4 filamentValue; filamentValue.x = static_cast(value.x); filamentValue.y = static_cast(value.y); @@ -1039,7 +988,7 @@ extern "C" ((SceneManager *)sceneManager)->setMaterialProperty(entity, materialIndex, property, filamentValue); } - EMSCRIPTEN_KEEPALIVE void unproject_texture(TViewer *viewer, EntityId entity, uint8_t* input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight) + EMSCRIPTEN_KEEPALIVE void unproject_texture(TViewer *viewer, EntityId entity, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight) { ((FilamentViewer *)viewer)->unprojectTexture(entity, input, inputWidth, inputHeight, out, outWidth, outHeight); } @@ -1059,146 +1008,154 @@ extern "C" ((SceneManager *)sceneManager)->destroyTexture(reinterpret_cast(texture)); } + EMSCRIPTEN_KEEPALIVE TMaterialInstance *create_material_instance(TSceneManager *sceneManager, TMaterialKey materialConfig) + { - EMSCRIPTEN_KEEPALIVE TMaterialInstance* create_material_instance(TSceneManager *sceneManager, TMaterialKey materialConfig) -{ + filament::gltfio::MaterialKey config; + memset(&config, 0, sizeof(MaterialKey)); - filament::gltfio::MaterialKey config; - memset(&config, 0, sizeof(MaterialKey)); - - // Set and log each field - config.unlit = materialConfig.unlit; - config.doubleSided = materialConfig.doubleSided; - config.useSpecularGlossiness = materialConfig.useSpecularGlossiness; - config.alphaMode = static_cast(materialConfig.alphaMode); - config.hasBaseColorTexture = materialConfig.hasBaseColorTexture; - config.hasClearCoat = materialConfig.hasClearCoat; - config.hasClearCoatNormalTexture = materialConfig.hasClearCoatNormalTexture; - config.hasClearCoatRoughnessTexture = materialConfig.hasClearCoatRoughnessTexture; - config.hasEmissiveTexture = materialConfig.hasEmissiveTexture; - config.hasIOR = materialConfig.hasIOR; - config.hasMetallicRoughnessTexture = materialConfig.hasMetallicRoughnessTexture; - config.hasNormalTexture = materialConfig.hasNormalTexture; - config.hasOcclusionTexture = materialConfig.hasOcclusionTexture; - config.hasSheen = materialConfig.hasSheen; - config.hasSheenColorTexture = materialConfig.hasSheenColorTexture; - config.hasSheenRoughnessTexture = materialConfig.hasSheenRoughnessTexture; - config.hasTextureTransforms = materialConfig.hasTextureTransforms; - config.hasTransmission = materialConfig.hasTransmission; - config.hasTransmissionTexture = materialConfig.hasTransmissionTexture; - config.hasVolume = materialConfig.hasVolume; - config.hasVolumeThicknessTexture = materialConfig.hasVolumeThicknessTexture; - config.baseColorUV = materialConfig.baseColorUV; - config.hasVertexColors = materialConfig.hasVertexColors; - auto materialInstance = ((SceneManager *)sceneManager)->createUbershaderMaterialInstance(config); - return reinterpret_cast(materialInstance); -} - -EMSCRIPTEN_KEEPALIVE TMaterialInstance *create_unlit_material_instance(TSceneManager *sceneManager) { - auto * instance = ((SceneManager*)sceneManager)->createUnlitMaterialInstance(); - return reinterpret_cast(instance); -} - -EMSCRIPTEN_KEEPALIVE void destroy_material_instance(TSceneManager *sceneManager, TMaterialInstance *instance) { - ((SceneManager *)sceneManager)->destroy(reinterpret_cast(instance)); -} - -EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthWrite(TMaterialInstance* materialInstance, bool enabled) { - reinterpret_cast(materialInstance)->setDepthWrite(enabled); -} - -EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthCulling(TMaterialInstance* materialInstance, bool enabled) { - reinterpret_cast(materialInstance)->setDepthCulling(enabled); -} - -EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat2(TMaterialInstance* materialInstance, const char* propertyName, double x, double y) { - filament::math::float2 data { static_cast(x), static_cast(y) }; - reinterpret_cast(materialInstance)->setParameter(propertyName, data); -} - -EMSCRIPTEN_KEEPALIVE void Camera_setCustomProjectionWithCulling(TCamera* tCamera, double4x4 projectionMatrix, double near, double far) { - auto * camera = reinterpret_cast(tCamera); - camera->setCustomProjection(convert_double4x4_to_mat4(projectionMatrix), near, far); -} - -EMSCRIPTEN_KEEPALIVE double4x4 Camera_getModelMatrix(TCamera* tCamera) { - auto * camera = reinterpret_cast(tCamera); - return convert_mat4_to_double4x4(camera->getModelMatrix()); -} - -EMSCRIPTEN_KEEPALIVE double4x4 Camera_getViewMatrix(TCamera *const tCamera) { - auto * camera = reinterpret_cast(tCamera); - return convert_mat4_to_double4x4(camera->getViewMatrix()); -} - -EMSCRIPTEN_KEEPALIVE EntityId Camera_getEntity(TCamera* tCamera) { - auto * camera = reinterpret_cast(tCamera); - return Entity::smuggle(camera->getEntity()); -} - -EMSCRIPTEN_KEEPALIVE double Camera_getFocalLength(TCamera *const tCamera) { - auto * camera = reinterpret_cast(tCamera); - return camera->getFocalLength(); -} - -EMSCRIPTEN_KEEPALIVE double Camera_getNear(TCamera *const tCamera) { - auto * camera = reinterpret_cast(tCamera); - return camera->getNear(); -} - -EMSCRIPTEN_KEEPALIVE double Camera_getCullingFar(TCamera *const tCamera) { - auto * camera = reinterpret_cast(tCamera); - return camera->getCullingFar(); -} - -EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine* tEngine, EntityId entityId) { - auto * engine = reinterpret_cast(tEngine); - auto * camera = engine->getCameraComponent(utils::Entity::import(entityId)); - return reinterpret_cast(camera); -} - -EMSCRIPTEN_KEEPALIVE void Engine_setTransform(TEngine* tEngine, EntityId entity, double4x4 transform) { - auto * engine = reinterpret_cast(tEngine); - auto& transformManager = engine->getTransformManager(); - - auto transformInstance = transformManager.getInstance(utils::Entity::import(entity)); - if(!transformInstance.isValid()) { - Log("Transform instance not valid"); + // Set and log each field + config.unlit = materialConfig.unlit; + config.doubleSided = materialConfig.doubleSided; + config.useSpecularGlossiness = materialConfig.useSpecularGlossiness; + config.alphaMode = static_cast(materialConfig.alphaMode); + config.hasBaseColorTexture = materialConfig.hasBaseColorTexture; + config.hasClearCoat = materialConfig.hasClearCoat; + config.hasClearCoatNormalTexture = materialConfig.hasClearCoatNormalTexture; + config.hasClearCoatRoughnessTexture = materialConfig.hasClearCoatRoughnessTexture; + config.hasEmissiveTexture = materialConfig.hasEmissiveTexture; + config.hasIOR = materialConfig.hasIOR; + config.hasMetallicRoughnessTexture = materialConfig.hasMetallicRoughnessTexture; + config.hasNormalTexture = materialConfig.hasNormalTexture; + config.hasOcclusionTexture = materialConfig.hasOcclusionTexture; + config.hasSheen = materialConfig.hasSheen; + config.hasSheenColorTexture = materialConfig.hasSheenColorTexture; + config.hasSheenRoughnessTexture = materialConfig.hasSheenRoughnessTexture; + config.hasTextureTransforms = materialConfig.hasTextureTransforms; + config.hasTransmission = materialConfig.hasTransmission; + config.hasTransmissionTexture = materialConfig.hasTransmissionTexture; + config.hasVolume = materialConfig.hasVolume; + config.hasVolumeThicknessTexture = materialConfig.hasVolumeThicknessTexture; + config.baseColorUV = materialConfig.baseColorUV; + config.hasVertexColors = materialConfig.hasVertexColors; + auto materialInstance = ((SceneManager *)sceneManager)->createUbershaderMaterialInstance(config); + return reinterpret_cast(materialInstance); } - transformManager.setTransform(transformInstance, convert_double4x4_to_mat4(transform)); -} -EMSCRIPTEN_KEEPALIVE TCamera *SceneManager_createCamera(TSceneManager* tSceneManager) { - auto * sceneManager = reinterpret_cast(tSceneManager); - return reinterpret_cast(sceneManager->createCamera()); -} + EMSCRIPTEN_KEEPALIVE TMaterialInstance *create_unlit_material_instance(TSceneManager *sceneManager) + { + auto *instance = ((SceneManager *)sceneManager)->createUnlitMaterialInstance(); + return reinterpret_cast(instance); + } -EMSCRIPTEN_KEEPALIVE void SceneManager_destroyCamera(TSceneManager* tSceneManager, TCamera* tCamera) { - auto * sceneManager = reinterpret_cast(tSceneManager); - auto * camera = reinterpret_cast(tCamera); - sceneManager->destroyCamera(camera); -} + EMSCRIPTEN_KEEPALIVE void destroy_material_instance(TSceneManager *sceneManager, TMaterialInstance *instance) + { + ((SceneManager *)sceneManager)->destroy(reinterpret_cast(instance)); + } -EMSCRIPTEN_KEEPALIVE void SceneManager_setCamera(TSceneManager* tSceneManager, TCamera* tCamera) { - auto * sceneManager = reinterpret_cast(tSceneManager); - auto * camera = reinterpret_cast(tCamera); - sceneManager->setCamera(camera); -} + EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthWrite(TMaterialInstance *materialInstance, bool enabled) + { + reinterpret_cast(materialInstance)->setDepthWrite(enabled); + } -EMSCRIPTEN_KEEPALIVE size_t SceneManager_getCameraCount(TSceneManager *tSceneManager) { - auto * sceneManager = reinterpret_cast(tSceneManager); - return sceneManager->getCameraCount(); -} -EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_getCameraAt(TSceneManager *tSceneManager, size_t index) { - auto * sceneManager = reinterpret_cast(tSceneManager); - auto * camera = sceneManager->getCameraAt(index); - return reinterpret_cast(camera); -} + EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthCulling(TMaterialInstance *materialInstance, bool enabled) + { + reinterpret_cast(materialInstance)->setDepthCulling(enabled); + } + + EMSCRIPTEN_KEEPALIVE void MaterialInstance_setParameterFloat2(TMaterialInstance *materialInstance, const char *propertyName, double x, double y) + { + filament::math::float2 data{static_cast(x), static_cast(y)}; + reinterpret_cast(materialInstance)->setParameter(propertyName, data); + } + + EMSCRIPTEN_KEEPALIVE void Camera_setCustomProjectionWithCulling(TCamera *tCamera, double4x4 projectionMatrix, double near, double far) + { + auto *camera = reinterpret_cast(tCamera); + camera->setCustomProjection(convert_double4x4_to_mat4(projectionMatrix), near, far); + } + + EMSCRIPTEN_KEEPALIVE double4x4 Camera_getModelMatrix(TCamera *tCamera) + { + auto *camera = reinterpret_cast(tCamera); + return convert_mat4_to_double4x4(camera->getModelMatrix()); + } + + EMSCRIPTEN_KEEPALIVE double4x4 Camera_getViewMatrix(TCamera *const tCamera) + { + auto *camera = reinterpret_cast(tCamera); + return convert_mat4_to_double4x4(camera->getViewMatrix()); + } + + EMSCRIPTEN_KEEPALIVE EntityId Camera_getEntity(TCamera *tCamera) + { + auto *camera = reinterpret_cast(tCamera); + return Entity::smuggle(camera->getEntity()); + } + + EMSCRIPTEN_KEEPALIVE double Camera_getFocalLength(TCamera *const tCamera) + { + auto *camera = reinterpret_cast(tCamera); + return camera->getFocalLength(); + } + + EMSCRIPTEN_KEEPALIVE double Camera_getNear(TCamera *const tCamera) + { + auto *camera = reinterpret_cast(tCamera); + return camera->getNear(); + } + + EMSCRIPTEN_KEEPALIVE double Camera_getCullingFar(TCamera *const tCamera) + { + auto *camera = reinterpret_cast(tCamera); + return camera->getCullingFar(); + } + + EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine *tEngine, EntityId entityId) + { + auto *engine = reinterpret_cast(tEngine); + auto *camera = engine->getCameraComponent(utils::Entity::import(entityId)); + return reinterpret_cast(camera); + } + + EMSCRIPTEN_KEEPALIVE void Engine_setTransform(TEngine *tEngine, EntityId entity, double4x4 transform) + { + auto *engine = reinterpret_cast(tEngine); + auto &transformManager = engine->getTransformManager(); + + auto transformInstance = transformManager.getInstance(utils::Entity::import(entity)); + if (!transformInstance.isValid()) + { + Log("Transform instance not valid"); + } + transformManager.setTransform(transformInstance, convert_double4x4_to_mat4(transform)); + } + + EMSCRIPTEN_KEEPALIVE TCamera *SceneManager_createCamera(TSceneManager *tSceneManager) + { + auto *sceneManager = reinterpret_cast(tSceneManager); + return reinterpret_cast(sceneManager->createCamera()); + } + + EMSCRIPTEN_KEEPALIVE void SceneManager_destroyCamera(TSceneManager *tSceneManager, TCamera *tCamera) + { + auto *sceneManager = reinterpret_cast(tSceneManager); + auto *camera = reinterpret_cast(tCamera); + sceneManager->destroyCamera(camera); + } + + EMSCRIPTEN_KEEPALIVE size_t SceneManager_getCameraCount(TSceneManager *tSceneManager) + { + auto *sceneManager = reinterpret_cast(tSceneManager); + return sceneManager->getCameraCount(); + } + + EMSCRIPTEN_KEEPALIVE TCamera *SceneManager_getCameraAt(TSceneManager *tSceneManager, size_t index) + { + auto *sceneManager = reinterpret_cast(tSceneManager); + auto *camera = sceneManager->getCameraAt(index); + return reinterpret_cast(camera); + } -EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_getActiveCamera(TSceneManager *tSceneManager) { - auto * sceneManager = reinterpret_cast(tSceneManager); - auto * camera = sceneManager->getActiveCamera(); - return reinterpret_cast(camera); -} } diff --git a/thermion_dart/native/src/ThermionDartRenderThreadApi.cpp b/thermion_dart/native/src/ThermionDartRenderThreadApi.cpp index f9fcf49c..aca06e59 100644 --- a/thermion_dart/native/src/ThermionDartRenderThreadApi.cpp +++ b/thermion_dart/native/src/ThermionDartRenderThreadApi.cpp @@ -82,9 +82,10 @@ public: } } - void requestFrame(SwapChain* swapChain, void (*callback)()) + void requestFrame(TView* tView, TSwapChain* tSwapChain, void (*callback)()) { - this->target = swapChain; + this->target = tSwapChain; + this->view = tView; this->_requestFrameRenderCallback = callback; } @@ -93,7 +94,7 @@ public: std::unique_lock lock(_mutex); if (target) { - doRender(target); + doRender(view, target); this->_requestFrameRenderCallback(); target = nullptr; @@ -176,7 +177,7 @@ public: fut.wait(); } - bool doRender(SwapChain *swapChain) + bool doRender(TView* tView, TSwapChain *tSwapChain) { #ifdef __EMSCRIPTEN__ if (emscripten_is_webgl_context_lost(_context) == EM_TRUE) @@ -187,8 +188,7 @@ public: return; } #endif - TSwapChain *tSwapChain = reinterpret_cast(swapChain); - auto rendered = Viewer_render(_viewer, tSwapChain, 0, nullptr, nullptr, nullptr); + auto rendered = Viewer_render(_viewer, tView, tSwapChain, 0, nullptr, nullptr, nullptr); if (_renderCallback) { _renderCallback(_renderCallbackOwner); @@ -218,7 +218,8 @@ public: } public: - SwapChain* target; + TSwapChain *target; + TView *view; private: void(*_requestFrameRenderCallback)() = nullptr; @@ -306,7 +307,7 @@ extern "C" } - EMSCRIPTEN_KEEPALIVE void Viewer_requestFrameRenderThread(TViewer *viewer, TSwapChain* tSwapChain, void(*onComplete)()) + EMSCRIPTEN_KEEPALIVE void Viewer_requestFrameRenderThread(TViewer *viewer, TView* view, TSwapChain* tSwapChain, void(*onComplete)()) { if (!_rl) { @@ -314,7 +315,7 @@ extern "C" } else { - _rl->requestFrame(reinterpret_cast(tSwapChain), onComplete); + _rl->requestFrame(view, tSwapChain, onComplete); } } @@ -327,24 +328,24 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void Viewer_renderRenderThread(TViewer *viewer, TSwapChain *tSwapChain) + EMSCRIPTEN_KEEPALIVE void Viewer_renderRenderThread(TViewer *viewer, TView *tView, TSwapChain *tSwapChain) { std::packaged_task lambda([=]() mutable - { _rl->doRender(reinterpret_cast(tSwapChain)); }); + { _rl->doRender(tView, tSwapChain); }); auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderThread(TViewer *viewer, TSwapChain *tSwapChain, uint8_t *pixelBuffer, void (*onComplete)()) + EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderThread(TViewer *viewer, TView *view, TSwapChain *tSwapChain, uint8_t *pixelBuffer, void (*onComplete)()) { std::packaged_task lambda([=]() mutable - { Viewer_capture(viewer, tSwapChain, pixelBuffer, onComplete); }); + { Viewer_capture(viewer, view, tSwapChain, pixelBuffer, onComplete); }); auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTargetRenderThread(TViewer *viewer, TSwapChain *tSwapChain, TRenderTarget* tRenderTarget, uint8_t *pixelBuffer, void (*onComplete)()) + EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTargetRenderThread(TViewer *viewer, TView *view, TSwapChain *tSwapChain, TRenderTarget* tRenderTarget, uint8_t *pixelBuffer, void (*onComplete)()) { std::packaged_task lambda([=]() mutable - { Viewer_captureRenderTarget(viewer, tSwapChain, tRenderTarget, pixelBuffer, onComplete); }); + { Viewer_captureRenderTarget(viewer, view, tSwapChain, tRenderTarget, pixelBuffer, onComplete); }); auto fut = _rl->add_task(lambda); } @@ -449,20 +450,7 @@ extern "C" { set_background_image_position(viewer, x, y, clamp); }); auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void set_tone_mapping_render_thread(TViewer *viewer, - int toneMapping) - { - std::packaged_task lambda( - [=] - { set_tone_mapping(viewer, toneMapping); }); - auto fut = _rl->add_task(lambda); - } - EMSCRIPTEN_KEEPALIVE void set_bloom_render_thread(TViewer *viewer, float strength) - { - std::packaged_task lambda([=] - { set_bloom(viewer, strength); }); - auto fut = _rl->add_task(lambda); - } + EMSCRIPTEN_KEEPALIVE void load_skybox_render_thread(TViewer *viewer, const char *skyboxPath, void (*onComplete)()) @@ -530,22 +518,6 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void set_camera_render_thread(TViewer *viewer, EntityId asset, - const char *nodeName, void (*callback)(bool)) - { - std::packaged_task lambda( - [=] - { - auto success = set_camera(viewer, asset, nodeName); -#ifdef __EMSCRIPTEN__ - MAIN_THREAD_EM_ASM({ moduleArg.dartFilamentResolveCallback($0, $1); }, callback, success); -#else - callback(success); -#endif - return success; - }); - auto fut = _rl->add_task(lambda); - } EMSCRIPTEN_KEEPALIVE void get_morph_target_name_render_thread(TSceneManager *sceneManager, EntityId assetEntity, @@ -637,15 +609,6 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void set_post_processing_render_thread(TViewer *viewer, - bool enabled) - { - std::packaged_task lambda( - [=] - { set_post_processing(viewer, enabled); }); - auto fut = _rl->add_task(lambda); - } - EMSCRIPTEN_KEEPALIVE void get_name_for_entity_render_thread(TSceneManager *sceneManager, const EntityId entityId, void (*callback)(const char *)) { diff --git a/thermion_dart/test/helpers.dart b/thermion_dart/test/helpers.dart index a413e241..6ea6e697 100644 --- a/thermion_dart/test/helpers.dart +++ b/thermion_dart/test/helpers.dart @@ -79,10 +79,11 @@ class TestHelper { outDir.createSync(); } - Future capture(ThermionViewer viewer, String outputFilename) async { + Future capture(ThermionViewer viewer, String outputFilename, { SwapChain? swapChain, RenderTarget? renderTarget}) async { await Future.delayed(Duration(milliseconds: 10)); var outPath = p.join(outDir.path, "$outputFilename.bmp"); - var pixelBuffer = await viewer.capture(swapChain); //, renderTarget: renderTarget); + var pixelBuffer = + await viewer.capture(swapChain ?? this.swapChain, renderTarget: renderTarget); await savePixelBufferToBmp( pixelBuffer, viewer.viewportDimensions.$1.toInt(), @@ -91,17 +92,21 @@ class TestHelper { return pixelBuffer; } + Future createTexture(int width, int height) async { + final packageUri = findPackageRoot('thermion_dart'); + final lib = ThermionDartTexture1(DynamicLibrary.open( + '${packageUri.toFilePath()}/native/lib/macos/swift/libthermion_swift.dylib')); + final object = ThermionDartTexture.new1(lib); + object.initWithWidth_height_(width, height); + return object.metalTextureAddress; + } + Future createViewer( {img.Color? bg, Vector3? cameraPosition, viewportDimensions = (width: 500, height: 500)}) async { - final packageUri = findPackageRoot('thermion_dart'); - - final lib = ThermionDartTexture1(DynamicLibrary.open( - '${packageUri.toFilePath()}/native/lib/macos/swift/libthermion_swift.dylib')); - final object = ThermionDartTexture.new1(lib); - object.initWithWidth_height_( - viewportDimensions.width, viewportDimensions.height); + final texture = + await createTexture(viewportDimensions.width, viewportDimensions.height); final resourceLoader = calloc(1); var loadToOut = NativeCallable< @@ -118,11 +123,10 @@ class TestHelper { await viewer.initialized; swapChain = await viewer.createSwapChain( viewportDimensions.width, viewportDimensions.height); - renderTarget = await viewer.createRenderTarget( - viewportDimensions.width, - viewportDimensions.height, - object.metalTextureAddress); - await viewer.setRenderTarget(renderTarget as FFIRenderTarget); + renderTarget = await viewer.createRenderTarget(viewportDimensions.width, + viewportDimensions.height, texture); + + // await viewer.setRenderTarget(renderTarget as FFIRenderTarget); await viewer.updateViewportAndCameraProjection( viewportDimensions.width.toDouble(), viewportDimensions.height.toDouble()); diff --git a/thermion_dart/test/view_tests.dart b/thermion_dart/test/view_tests.dart new file mode 100644 index 00000000..5252e196 --- /dev/null +++ b/thermion_dart/test/view_tests.dart @@ -0,0 +1,21 @@ +import 'package:test/test.dart'; +import 'helpers.dart'; + +void main() async { + final testHelper = TestHelper("view"); + + group('view tests', () { + test('create view', () async { + var viewer = await testHelper.createViewer(); + final renderTarget = await viewer.createRenderTarget( + 200, 400, await testHelper.createTexture(200, 400)); + final view = await viewer.createView(); + + await view.updateViewport(200, 400); + await view.setRenderTarget(renderTarget); + await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0); + await testHelper.capture(viewer, "create_view_with_render_target", renderTarget: renderTarget); + await viewer.dispose(); + }); + }); +} diff --git a/thermion_flutter/thermion_flutter_ffi/lib/thermion_flutter_ffi.dart b/thermion_flutter/thermion_flutter_ffi/lib/thermion_flutter_ffi.dart index 3c9d97c2..232789b4 100644 --- a/thermion_flutter/thermion_flutter_ffi/lib/thermion_flutter_ffi.dart +++ b/thermion_flutter/thermion_flutter_ffi/lib/thermion_flutter_ffi.dart @@ -240,7 +240,7 @@ class ThermionFlutterFFI extends ThermionFlutterPlatform { if (newTexture.hardwareTextureId != null) { // ignore: unused_local_variable var renderTarget = await _viewer!.createRenderTarget( - width.toDouble(), height.toDouble(), newTexture.hardwareTextureId!); + width, height, newTexture.hardwareTextureId!); } await _viewer! .updateViewportAndCameraProjection(width.toDouble(), height.toDouble());