From e83193ba0df6f6121ffd4e3eccfdf9a421534b7f Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Sat, 21 Sep 2024 11:36:41 +0800 Subject: [PATCH] introduce stronger native typing, camera projection/culling methods, update tests --- .../lib/thermion_dart/utils/matrix.dart | 9 +- .../thermion_dart/viewer/ffi/callbacks.dart | 12 +- .../thermion_dart/viewer/ffi/camera_ffi.dart | 22 ++ .../viewer/ffi/thermion_dart.g.dart | 350 +++++++++--------- .../viewer/ffi/thermion_viewer_ffi.dart | 84 +++-- .../viewer/shared_types/camera.dart | 12 +- .../viewer/thermion_viewer_base.dart | 15 +- .../viewer/thermion_viewer_stub.dart | 19 +- .../native/include/APIBoundaryTypes.h | 2 + .../native/include/FilamentViewer.hpp | 3 + .../native/include/ThermionDartApi.h | 111 +++--- .../include/ThermionDartRenderThreadApi.h | 56 +-- thermion_dart/native/src/ThermionDartApi.cpp | 122 +++--- .../src/ThermionDartRenderThreadApi.cpp | 63 ++-- thermion_dart/test/helpers.dart | 308 ++++++++++++++- thermion_dart/test/integration_test.dart | 25 ++ 16 files changed, 814 insertions(+), 399 deletions(-) create mode 100644 thermion_dart/lib/thermion_dart/viewer/ffi/camera_ffi.dart diff --git a/thermion_dart/lib/thermion_dart/utils/matrix.dart b/thermion_dart/lib/thermion_dart/utils/matrix.dart index 42c5647a..6b8ae389 100644 --- a/thermion_dart/lib/thermion_dart/utils/matrix.dart +++ b/thermion_dart/lib/thermion_dart/utils/matrix.dart @@ -24,14 +24,15 @@ Matrix4 double4x4ToMatrix4(double4x4 mat) { ]); } -double4x4 matrix4ToDouble4x4(Matrix4 mat, double4x4 out) { - +double4x4 matrix4ToDouble4x4(Matrix4 mat) { + final out = Struct.create(); + for (int i = 0; i < 4; i++) { out.col1[i] = mat.storage[i]; out.col2[i] = mat.storage[i + 4]; out.col3[i] = mat.storage[i + 8]; out.col4[i] = mat.storage[i + 12]; } - + return out; -} \ No newline at end of file +} diff --git a/thermion_dart/lib/thermion_dart/viewer/ffi/callbacks.dart b/thermion_dart/lib/thermion_dart/viewer/ffi/callbacks.dart index c3bd3157..e36a430b 100644 --- a/thermion_dart/lib/thermion_dart/viewer/ffi/callbacks.dart +++ b/thermion_dart/lib/thermion_dart/viewer/ffi/callbacks.dart @@ -26,16 +26,16 @@ Future withVoidCallback( nativeCallable.close(); } -Future withVoidPointerCallback( - Function(Pointer)>>) +Future withPointerCallback( + Function(Pointer)>>) func) async { - final completer = Completer>(); + final completer = Completer>(); // ignore: prefer_function_declarations_over_variables - void Function(Pointer) callback = (Pointer ptr) { - completer.complete(ptr); + void Function(Pointer) callback = (Pointer ptr) { + completer.complete(ptr.cast()); }; final nativeCallable = - NativeCallable)>.listener(callback); + NativeCallable)>.listener(callback); func.call(nativeCallable.nativeFunction); var ptr = await completer.future; nativeCallable.close(); diff --git a/thermion_dart/lib/thermion_dart/viewer/ffi/camera_ffi.dart b/thermion_dart/lib/thermion_dart/viewer/ffi/camera_ffi.dart new file mode 100644 index 00000000..d018b8ca --- /dev/null +++ b/thermion_dart/lib/thermion_dart/viewer/ffi/camera_ffi.dart @@ -0,0 +1,22 @@ +import 'dart:ffi'; + +import 'package:thermion_dart/thermion_dart/utils/matrix.dart'; +import 'package:thermion_dart/thermion_dart/viewer/ffi/thermion_dart.g.dart'; +import 'package:thermion_dart/thermion_dart/viewer/shared_types/camera.dart'; +import 'package:vector_math/vector_math_64.dart'; + +class ThermionFFICamera extends Camera { + final Pointer pointer; + + ThermionFFICamera(this.pointer); + + @override + Future setProjectionMatrixWithCulling(Matrix4 projectionMatrix, + double near, double far) async { + Camera_setCustomProjectionWithCulling( + pointer, + matrix4ToDouble4x4(projectionMatrix), + near, + far); + } +} diff --git a/thermion_dart/lib/thermion_dart/viewer/ffi/thermion_dart.g.dart b/thermion_dart/lib/thermion_dart/viewer/ffi/thermion_dart.g.dart index 11d59ae3..e63e4e2b 100644 --- a/thermion_dart/lib/thermion_dart/viewer/ffi/thermion_dart.g.dart +++ b/thermion_dart/lib/thermion_dart/viewer/ffi/thermion_dart.g.dart @@ -17,129 +17,141 @@ external ffi.Pointer make_resource_loader( ); @ffi.Native< - ffi.Pointer Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(isLeaf: true) -external ffi.Pointer create_filament_viewer( +external ffi.Pointer create_filament_viewer( ffi.Pointer context, ffi.Pointer loader, ffi.Pointer platform, ffi.Pointer uberArchivePath, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external void destroy_filament_viewer( - ffi.Pointer viewer, + ffi.Pointer viewer, ); -@ffi.Native Function(ffi.Pointer)>(isLeaf: true) +@ffi.Native Function(ffi.Pointer)>(isLeaf: true) external ffi.Pointer get_scene_manager( - ffi.Pointer viewer, + ffi.Pointer viewer, +); + +@ffi.Native Function(ffi.Pointer)>(isLeaf: true) +external ffi.Pointer Viewer_getEngine( + ffi.Pointer viewer, +); + +@ffi.Native Function(ffi.Pointer, EntityId)>( + isLeaf: true) +external ffi.Pointer Engine_getCameraComponent( + ffi.Pointer tEngine, + int entityId, ); @ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.IntPtr, ffi.Uint32, - ffi.Uint32)>(isLeaf: true) + ffi.Void Function( + ffi.Pointer, ffi.IntPtr, ffi.Uint32, ffi.Uint32)>(isLeaf: true) external void create_render_target( - ffi.Pointer viewer, + ffi.Pointer viewer, int texture, int width, int height, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external void clear_background_image( - ffi.Pointer viewer, + ffi.Pointer viewer, ); @ffi.Native< ffi.Void Function( - ffi.Pointer, ffi.Pointer, ffi.Bool)>(isLeaf: true) + ffi.Pointer, ffi.Pointer, ffi.Bool)>(isLeaf: true) external void set_background_image( - ffi.Pointer viewer, + ffi.Pointer viewer, ffi.Pointer path, bool fillHeight, ); @ffi.Native< ffi.Void Function( - ffi.Pointer, ffi.Float, ffi.Float, ffi.Bool)>(isLeaf: true) + ffi.Pointer, ffi.Float, ffi.Float, ffi.Bool)>(isLeaf: true) external void set_background_image_position( - ffi.Pointer viewer, + ffi.Pointer viewer, double x, double y, bool clamp, ); @ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Float, ffi.Float, ffi.Float, + ffi.Void Function(ffi.Pointer, ffi.Float, ffi.Float, ffi.Float, ffi.Float)>(isLeaf: true) external void set_background_color( - ffi.Pointer viewer, + ffi.Pointer viewer, double r, double g, double b, double a, ); -@ffi.Native, ffi.Int)>(isLeaf: true) +@ffi.Native, ffi.Int)>(isLeaf: true) external void set_tone_mapping( - ffi.Pointer viewer, + ffi.Pointer viewer, int toneMapping, ); -@ffi.Native, ffi.Float)>(isLeaf: true) +@ffi.Native, ffi.Float)>(isLeaf: true) external void set_bloom( - ffi.Pointer viewer, + ffi.Pointer viewer, double strength, ); -@ffi.Native, ffi.Pointer)>( +@ffi.Native, ffi.Pointer)>( isLeaf: true) external void load_skybox( - ffi.Pointer viewer, + ffi.Pointer viewer, ffi.Pointer skyboxPath, ); @ffi.Native< ffi.Void Function( - ffi.Pointer, ffi.Pointer, ffi.Float)>(isLeaf: true) + ffi.Pointer, ffi.Pointer, ffi.Float)>(isLeaf: true) external void load_ibl( - ffi.Pointer viewer, + ffi.Pointer viewer, ffi.Pointer iblPath, double intensity, ); @ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Float, ffi.Float, ffi.Float, + ffi.Void Function(ffi.Pointer, ffi.Float, ffi.Float, ffi.Float, ffi.Float)>(isLeaf: true) external void create_ibl( - ffi.Pointer viewer, + ffi.Pointer viewer, double r, double g, double b, double intensity, ); -@ffi.Native, ffi.Pointer)>( +@ffi.Native, ffi.Pointer)>( isLeaf: true) external void rotate_ibl( - ffi.Pointer viewer, + ffi.Pointer viewer, ffi.Pointer rotationMatrix, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external void remove_skybox( - ffi.Pointer viewer, + ffi.Pointer viewer, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external void remove_ibl( - ffi.Pointer viewer, + ffi.Pointer viewer, ); @ffi.Native< EntityId Function( - ffi.Pointer, + ffi.Pointer, ffi.Uint8, ffi.Float, ffi.Float, @@ -157,7 +169,7 @@ external void remove_ibl( ffi.Float, ffi.Bool)>(isLeaf: true) external int add_light( - ffi.Pointer viewer, + ffi.Pointer viewer, int type, double colour, double intensity, @@ -176,22 +188,22 @@ external int add_light( bool shadows, ); -@ffi.Native, EntityId)>(isLeaf: true) +@ffi.Native, EntityId)>(isLeaf: true) external void remove_light( - ffi.Pointer viewer, + ffi.Pointer viewer, int entityId, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external void clear_lights( - ffi.Pointer viewer, + ffi.Pointer viewer, ); @ffi.Native< - ffi.Void Function(ffi.Pointer, EntityId, ffi.Float, ffi.Float, + ffi.Void Function(ffi.Pointer, EntityId, ffi.Float, ffi.Float, ffi.Float)>(isLeaf: true) external void set_light_position( - ffi.Pointer viewer, + ffi.Pointer viewer, int light, double x, double y, @@ -199,10 +211,10 @@ external void set_light_position( ); @ffi.Native< - ffi.Void Function(ffi.Pointer, EntityId, ffi.Float, ffi.Float, + ffi.Void Function(ffi.Pointer, EntityId, ffi.Float, ffi.Float, ffi.Float)>(isLeaf: true) external void set_light_direction( - ffi.Pointer viewer, + ffi.Pointer viewer, int light, double x, double y, @@ -262,34 +274,34 @@ external void get_instances( ffi.Pointer out, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external void set_main_camera( - ffi.Pointer viewer, + ffi.Pointer viewer, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external int get_main_camera( - ffi.Pointer viewer, + ffi.Pointer viewer, ); @ffi.Native< ffi.Bool Function( - ffi.Pointer, EntityId, ffi.Pointer)>(isLeaf: true) + ffi.Pointer, EntityId, ffi.Pointer)>(isLeaf: true) external bool set_camera( - ffi.Pointer viewer, + ffi.Pointer viewer, int entity, ffi.Pointer nodeName, ); -@ffi.Native, ffi.Bool)>(isLeaf: true) +@ffi.Native, ffi.Bool)>(isLeaf: true) external void set_view_frustum_culling( - ffi.Pointer viewer, + ffi.Pointer viewer, bool enabled, ); @ffi.Native< - ffi.Void Function( - ffi.Pointer, + ffi.Bool Function( + ffi.Pointer, ffi.Uint64, ffi.Pointer, ffi.Pointer< @@ -297,8 +309,8 @@ external void set_view_frustum_culling( ffi.Void Function(ffi.Pointer buf, ffi.Size size, ffi.Pointer data)>>, ffi.Pointer)>(isLeaf: true) -external void render( - ffi.Pointer viewer, +external bool render( + ffi.Pointer viewer, int frameTimeInNanos, ffi.Pointer pixelBuffer, ffi.Pointer< @@ -310,84 +322,84 @@ external void render( ); @ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer>)>(isLeaf: true) external void capture( - ffi.Pointer viewer, + ffi.Pointer viewer, ffi.Pointer pixelBuffer, ffi.Pointer> callback, ); @ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Uint32, + ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Uint32, ffi.Uint32)>(isLeaf: true) external void create_swap_chain( - ffi.Pointer viewer, + ffi.Pointer viewer, ffi.Pointer window, int width, int height, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external void destroy_swap_chain( - ffi.Pointer viewer, + ffi.Pointer viewer, ); -@ffi.Native, ffi.Float)>(isLeaf: true) +@ffi.Native, ffi.Float)>(isLeaf: true) external void set_frame_interval( - ffi.Pointer viewer, + ffi.Pointer viewer, double interval, ); -@ffi.Native, ffi.Uint32, ffi.Uint32)>( +@ffi.Native, ffi.Uint32, ffi.Uint32)>( isLeaf: true) external void update_viewport( - ffi.Pointer viewer, + ffi.Pointer viewer, int width, int height, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external void scroll_begin( - ffi.Pointer viewer, + ffi.Pointer viewer, ); @ffi.Native< ffi.Void Function( - ffi.Pointer, ffi.Float, ffi.Float, ffi.Float)>(isLeaf: true) + ffi.Pointer, ffi.Float, ffi.Float, ffi.Float)>(isLeaf: true) external void scroll_update( - ffi.Pointer viewer, + ffi.Pointer viewer, double x, double y, double z, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external void scroll_end( - ffi.Pointer viewer, + ffi.Pointer viewer, ); @ffi.Native< ffi.Void Function( - ffi.Pointer, ffi.Float, ffi.Float, ffi.Bool)>(isLeaf: true) + ffi.Pointer, ffi.Float, ffi.Float, ffi.Bool)>(isLeaf: true) external void grab_begin( - ffi.Pointer viewer, + ffi.Pointer viewer, double x, double y, bool pan, ); -@ffi.Native, ffi.Float, ffi.Float)>( +@ffi.Native, ffi.Float, ffi.Float)>( isLeaf: true) external void grab_update( - ffi.Pointer viewer, + ffi.Pointer viewer, double x, double y, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external void grab_end( - ffi.Pointer viewer, + ffi.Pointer viewer, ); @ffi.Native< @@ -652,15 +664,15 @@ external int get_morph_target_name_count( int childEntity, ); -@ffi.Native, EntityId)>(isLeaf: true) +@ffi.Native, EntityId)>(isLeaf: true) external void remove_entity( - ffi.Pointer viewer, + ffi.Pointer viewer, int asset, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external void clear_entities( - ffi.Pointer viewer, + ffi.Pointer viewer, ); @ffi.Native< @@ -780,10 +792,10 @@ external void set_camera_model_matrix( double4x4 matrix, ); -@ffi.Native Function(ffi.Pointer, EntityId)>( +@ffi.Native Function(ffi.Pointer, EntityId)>( isLeaf: true) external ffi.Pointer get_camera( - ffi.Pointer viewer, + ffi.Pointer viewer, int entity, ); @@ -874,10 +886,10 @@ external void set_camera_focus_distance( ); @ffi.Native< - ffi.Void Function(ffi.Pointer, _ManipulatorMode, ffi.Double, + ffi.Void Function(ffi.Pointer, _ManipulatorMode, ffi.Double, ffi.Double, ffi.Double)>(isLeaf: true) external void set_camera_manipulator_options( - ffi.Pointer viewer, + ffi.Pointer viewer, int mode, double orbitSpeedX, double orbitSpeedY, @@ -885,16 +897,22 @@ external void set_camera_manipulator_options( ); @ffi.Native< - ffi.Void Function(ffi.Pointer, double4x4, double4x4, ffi.Double, - ffi.Double)>(isLeaf: true) + ffi.Void Function( + ffi.Pointer, double4x4, ffi.Double, ffi.Double)>(isLeaf: true) external void Camera_setCustomProjectionWithCulling( ffi.Pointer camera, double4x4 projectionMatrix, - double4x4 projectionMatrixForCulling, double near, double far, ); +@ffi.Native Function(ffi.Pointer, EntityId)>( + isLeaf: true) +external ffi.Pointer get_camera_component( + ffi.Pointer engine, + int entity, +); + @ffi.Native< ffi.Int Function( ffi.Pointer, EntityId, ffi.Pointer)>(isLeaf: true) @@ -913,37 +931,37 @@ external int reveal_mesh( ffi.Pointer meshName, ); -@ffi.Native, ffi.Bool)>(isLeaf: true) +@ffi.Native, ffi.Bool)>(isLeaf: true) external void set_post_processing( - ffi.Pointer viewer, + ffi.Pointer viewer, bool enabled, ); -@ffi.Native, ffi.Bool)>(isLeaf: true) +@ffi.Native, ffi.Bool)>(isLeaf: true) external void set_shadows_enabled( - ffi.Pointer viewer, + ffi.Pointer viewer, bool enabled, ); -@ffi.Native, ffi.Int)>(isLeaf: true) +@ffi.Native, ffi.Int)>(isLeaf: true) external void set_shadow_type( - ffi.Pointer viewer, + ffi.Pointer viewer, int shadowType, ); -@ffi.Native, ffi.Float, ffi.Float)>( +@ffi.Native, ffi.Float, ffi.Float)>( isLeaf: true) external void set_soft_shadow_options( - ffi.Pointer viewer, + ffi.Pointer viewer, double penumbraScale, double penumbraRatioScale, ); @ffi.Native< ffi.Void Function( - ffi.Pointer, ffi.Bool, ffi.Bool, ffi.Bool)>(isLeaf: true) + ffi.Pointer, ffi.Bool, ffi.Bool, ffi.Bool)>(isLeaf: true) external void set_antialiasing( - ffi.Pointer viewer, + ffi.Pointer viewer, bool msaa, bool fxaa, bool taa, @@ -951,7 +969,7 @@ external void set_antialiasing( @ffi.Native< ffi.Void Function( - ffi.Pointer, + ffi.Pointer, ffi.Int, ffi.Int, ffi.Pointer< @@ -959,7 +977,7 @@ external void set_antialiasing( ffi.Void Function( EntityId entityId, ffi.Int x, ffi.Int y)>>)>(isLeaf: true) external void filament_pick( - ffi.Pointer viewer, + ffi.Pointer viewer, int x, int y, ffi.Pointer< @@ -1012,16 +1030,16 @@ external ffi.Pointer get_entity_name_at( bool renderableOnly, ); -@ffi.Native, ffi.Bool)>(isLeaf: true) +@ffi.Native, ffi.Bool)>(isLeaf: true) external void set_recording( - ffi.Pointer viewer, + ffi.Pointer viewer, bool recording, ); -@ffi.Native, ffi.Pointer)>( +@ffi.Native, ffi.Pointer)>( isLeaf: true) external void set_recording_output_directory( - ffi.Pointer viewer, + ffi.Pointer viewer, ffi.Pointer outputDirectory, ); @@ -1267,7 +1285,7 @@ external void set_material_depth_write( @ffi.Native< ffi.Void Function( - ffi.Pointer, + ffi.Pointer, EntityId, ffi.Pointer, ffi.Uint32, @@ -1276,7 +1294,7 @@ external void set_material_depth_write( ffi.Uint32, ffi.Uint32)>(isLeaf: true) external void unproject_texture( - ffi.Pointer sceneManager, + ffi.Pointer viewer, int entity, ffi.Pointer input, int inputWidth, @@ -1348,8 +1366,7 @@ external void MaterialInstance_setDepthCulling( ffi.Pointer, ffi.Pointer< ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer viewer)>>)>(isLeaf: true) + ffi.Void Function(ffi.Pointer viewer)>>)>(isLeaf: true) external void create_filament_viewer_render_thread( ffi.Pointer context, ffi.Pointer platform, @@ -1361,19 +1378,19 @@ external void create_filament_viewer_render_thread( renderCallback, ffi.Pointer renderCallbackOwner, ffi.Pointer< - ffi.NativeFunction viewer)>> + ffi.NativeFunction viewer)>> callback, ); @ffi.Native< ffi.Void Function( - ffi.Pointer, + ffi.Pointer, ffi.Pointer, ffi.Uint32, ffi.Uint32, ffi.Pointer>)>(isLeaf: true) external void create_swap_chain_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, ffi.Pointer surface, int width, int height, @@ -1381,39 +1398,39 @@ external void create_swap_chain_render_thread( ); @ffi.Native< - ffi.Void Function(ffi.Pointer, + ffi.Void Function(ffi.Pointer, ffi.Pointer>)>(isLeaf: true) external void destroy_swap_chain_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, ffi.Pointer> onComplete, ); @ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.IntPtr, ffi.Uint32, ffi.Uint32, + ffi.Void Function(ffi.Pointer, ffi.IntPtr, ffi.Uint32, ffi.Uint32, ffi.Pointer>)>(isLeaf: true) external void create_render_target_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, int nativeTextureId, int width, int height, ffi.Pointer> onComplete, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external void destroy_filament_viewer_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external void render_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, ); @ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer>)>(isLeaf: true) external void capture_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, ffi.Pointer out, ffi.Pointer> onComplete, ); @@ -1425,46 +1442,46 @@ external FilamentRenderCallback make_render_callback_fn_pointer( ); @ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Bool, + ffi.Void Function(ffi.Pointer, ffi.Bool, ffi.Pointer>)>(isLeaf: true) external void set_rendering_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, bool rendering, ffi.Pointer> onComplete, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external void request_frame_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, ); -@ffi.Native, ffi.Float)>(isLeaf: true) +@ffi.Native, ffi.Float)>(isLeaf: true) external void set_frame_interval_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, double frameInterval, ); @ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Float, ffi.Float, ffi.Float, + ffi.Void Function(ffi.Pointer, ffi.Float, ffi.Float, ffi.Float, ffi.Float)>(isLeaf: true) external void set_background_color_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, double r, double g, double b, double a, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external void clear_background_image_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, ); @ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Bool, + ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Bool, ffi.Pointer>)>(isLeaf: true) external void set_background_image_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, ffi.Pointer path, bool fillHeight, ffi.Pointer> onComplete, @@ -1472,57 +1489,57 @@ external void set_background_image_render_thread( @ffi.Native< ffi.Void Function( - ffi.Pointer, ffi.Float, ffi.Float, ffi.Bool)>(isLeaf: true) + ffi.Pointer, ffi.Float, ffi.Float, ffi.Bool)>(isLeaf: true) external void set_background_image_position_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, double x, double y, bool clamp, ); -@ffi.Native, ffi.Int)>(isLeaf: true) +@ffi.Native, ffi.Int)>(isLeaf: true) external void set_tone_mapping_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, int toneMapping, ); -@ffi.Native, ffi.Float)>(isLeaf: true) +@ffi.Native, ffi.Float)>(isLeaf: true) external void set_bloom_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, double strength, ); @ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer>)>(isLeaf: true) external void load_skybox_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, ffi.Pointer skyboxPath, ffi.Pointer> onComplete, ); @ffi.Native< ffi.Void Function( - ffi.Pointer, ffi.Pointer, ffi.Float)>(isLeaf: true) + ffi.Pointer, ffi.Pointer, ffi.Float)>(isLeaf: true) external void load_ibl_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, ffi.Pointer iblPath, double intensity, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external void remove_skybox_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external void remove_ibl_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, ); @ffi.Native< ffi.Void Function( - ffi.Pointer, + ffi.Pointer, ffi.Uint8, ffi.Float, ffi.Float, @@ -1542,7 +1559,7 @@ external void remove_ibl_render_thread( ffi.Pointer>)>( isLeaf: true) external void add_light_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, int type, double colour, double intensity, @@ -1562,15 +1579,15 @@ external void add_light_render_thread( ffi.Pointer> callback, ); -@ffi.Native, EntityId)>(isLeaf: true) +@ffi.Native, EntityId)>(isLeaf: true) external void remove_light_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, int entityId, ); -@ffi.Native)>(isLeaf: true) +@ffi.Native)>(isLeaf: true) external void clear_lights_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, ); @ffi.Native< @@ -1638,31 +1655,28 @@ external void create_instance_render_thread( ); @ffi.Native< - ffi.Void Function(ffi.Pointer, EntityId, + ffi.Void Function(ffi.Pointer, EntityId, ffi.Pointer>)>(isLeaf: true) external void remove_entity_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, int asset, ffi.Pointer> callback, ); @ffi.Native< - ffi.Void Function(ffi.Pointer, + ffi.Void Function(ffi.Pointer, ffi.Pointer>)>(isLeaf: true) external void clear_entities_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, ffi.Pointer> callback, ); @ffi.Native< - ffi.Void Function( - ffi.Pointer, - EntityId, - ffi.Pointer, + ffi.Void Function(ffi.Pointer, EntityId, ffi.Pointer, ffi.Pointer>)>( isLeaf: true) external void set_camera_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, int asset, ffi.Pointer nodeName, ffi.Pointer> callback, @@ -1794,9 +1808,9 @@ external void set_bone_transform_render_thread( ffi.Pointer> callback, ); -@ffi.Native, ffi.Bool)>(isLeaf: true) +@ffi.Native, ffi.Bool)>(isLeaf: true) external void set_post_processing_render_thread( - ffi.Pointer viewer, + ffi.Pointer viewer, bool enabled, ); @@ -1843,7 +1857,7 @@ external void create_geometry_render_thread( @ffi.Native< ffi.Void Function( - ffi.Pointer, + ffi.Pointer, EntityId, ffi.Pointer, ffi.Uint32, @@ -1853,7 +1867,7 @@ external void create_geometry_render_thread( ffi.Uint32, ffi.Pointer>)>(isLeaf: true) external void unproject_texture_render_thread( - ffi.Pointer sceneManager, + ffi.Pointer viewer, int entity, ffi.Pointer input, int inputWidth, @@ -1868,6 +1882,10 @@ final class TCamera extends ffi.Opaque {} final class TMaterialInstance extends ffi.Opaque {} +final class TEngine extends ffi.Opaque {} + +final class TViewer extends ffi.Opaque {} + final class TMaterialKey extends ffi.Struct { @ffi.Bool() external bool doubleSided; diff --git a/thermion_dart/lib/thermion_dart/viewer/ffi/thermion_viewer_ffi.dart b/thermion_dart/lib/thermion_dart/viewer/ffi/thermion_viewer_ffi.dart index 0afbf003..8eb359fc 100644 --- a/thermion_dart/lib/thermion_dart/viewer/ffi/thermion_viewer_ffi.dart +++ b/thermion_dart/lib/thermion_dart/viewer/ffi/thermion_viewer_ffi.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:ffi'; import 'dart:math'; import 'dart:typed_data'; import 'package:animation_tools_dart/animation_tools_dart.dart'; @@ -8,6 +7,8 @@ import 'package:thermion_dart/thermion_dart/entities/gizmo.dart'; import 'package:thermion_dart/thermion_dart/utils/matrix.dart'; import 'package:thermion_dart/thermion_dart/viewer/events.dart'; import 'package:thermion_dart/thermion_dart/viewer/ffi/callbacks.dart'; +import 'package:thermion_dart/thermion_dart/viewer/ffi/camera_ffi.dart'; +import 'package:thermion_dart/thermion_dart/viewer/shared_types/camera.dart'; import 'package:vector_math/vector_math_64.dart'; import 'package:vector_math/vector_math_64.dart' as v64; import '../thermion_viewer_base.dart'; @@ -25,7 +26,7 @@ class ThermionViewerFFI extends ThermionViewer { Pointer? _sceneManager; - Pointer? _viewer; + Pointer? _viewer; final String? uberArchivePath; @@ -102,7 +103,7 @@ class ThermionViewerFFI extends ThermionViewer { Future updateViewportAndCameraProjection(double width, double height) async { viewportDimensions = (width * pixelRatio, height * pixelRatio); update_viewport(_viewer!, width.toInt(), height.toInt()); - var mainCamera = get_camera(_viewer!, await getMainCamera()); + var mainCamera = await getMainCamera() as ThermionFFICamera; var near = await getCameraCullingNear(); if (near.abs() < 0.000001) { near = kNear; @@ -113,11 +114,12 @@ class ThermionViewerFFI extends ThermionViewer { } var aspect = viewportDimensions.$1 / viewportDimensions.$2; - var focalLength = get_camera_focal_length(mainCamera); + var focalLength = get_camera_focal_length(mainCamera.pointer); if (focalLength.abs() < 0.1) { focalLength = kFocalLength; } - set_camera_lens_projection(mainCamera, near, far, aspect, focalLength); + set_camera_lens_projection( + mainCamera.pointer, near, far, aspect, focalLength); } Future createSwapChain(double width, double height, @@ -141,8 +143,8 @@ class ThermionViewerFFI extends ThermionViewer { final uberarchivePtr = uberArchivePath?.toNativeUtf8(allocator: allocator).cast() ?? nullptr; - var viewer = await withVoidPointerCallback( - (Pointer)>> callback) { + var viewer = await withPointerCallback( + (Pointer)>> callback) { create_filament_viewer_render_thread( _sharedContext, _driver, @@ -1144,8 +1146,25 @@ class ThermionViewerFFI extends ThermionViewer { set_main_camera(_viewer!); } - Future getMainCamera() { - return Future.value(get_main_camera(_viewer!)); + /// + /// + /// + Future getMainCameraEntity() async { + return get_main_camera(_viewer!); + } + + /// + /// + /// + Future getMainCamera() async { + var camera = await getCameraComponent(await getMainCameraEntity()); + return camera!; + } + + Future getCameraComponent(ThermionEntity cameraEntity) async { + var engine = Viewer_getEngine(_viewer!); + var camera = Engine_getCameraComponent(engine, cameraEntity); + return ThermionFFICamera(camera); } /// @@ -1229,8 +1248,8 @@ class ThermionViewerFFI extends ThermionViewer { /// /// Future getCameraFov(bool horizontal) async { - var mainCamera = get_camera(_viewer!, await getMainCamera()); - return get_camera_fov(mainCamera, horizontal); + var mainCamera = await getMainCamera() as ThermionFFICamera; + return get_camera_fov(mainCamera.pointer, horizontal); } /// @@ -1258,8 +1277,8 @@ class ThermionViewerFFI extends ThermionViewer { } Future getCameraNear() async { - var mainCamera = get_camera(_viewer!, await getMainCamera()); - return get_camera_near(mainCamera); + var mainCamera = await getMainCamera() as ThermionFFICamera; + return get_camera_near(mainCamera.pointer); } /// @@ -1267,8 +1286,8 @@ class ThermionViewerFFI extends ThermionViewer { /// @override Future getCameraCullingFar() async { - var mainCamera = get_camera(_viewer!, await getMainCamera()); - return get_camera_culling_far(mainCamera); + var mainCamera = await getMainCamera() as ThermionFFICamera; + return get_camera_culling_far(mainCamera.pointer); } /// @@ -1276,8 +1295,8 @@ class ThermionViewerFFI extends ThermionViewer { /// @override Future setCameraFocusDistance(double focusDistance) async { - var mainCamera = get_camera(_viewer!, await getMainCamera()); - set_camera_focus_distance(mainCamera, focusDistance); + var mainCamera = await getMainCamera() as ThermionFFICamera; + set_camera_focus_distance(mainCamera.pointer, focusDistance); } /// @@ -1312,8 +1331,8 @@ class ThermionViewerFFI extends ThermionViewer { @override Future setCameraExposure( double aperture, double shutterSpeed, double sensitivity) async { - var mainCamera = get_camera(_viewer!, await getMainCamera()); - set_camera_exposure(mainCamera, aperture, shutterSpeed, sensitivity); + var mainCamera = await getMainCamera() as ThermionFFICamera; + set_camera_exposure(mainCamera.pointer, aperture, shutterSpeed, sensitivity); } /// @@ -1341,10 +1360,9 @@ class ThermionViewerFFI extends ThermionViewer { /// @override Future setCameraModelMatrix4(Matrix4 modelMatrix) async { - var mainCamera = get_camera(_viewer!, await getMainCamera()); - final out = Struct.create(); - matrix4ToDouble4x4(modelMatrix, out); - set_camera_model_matrix(mainCamera, out); + var mainCamera = await getMainCamera() as ThermionFFICamera; + final out = matrix4ToDouble4x4(modelMatrix); + set_camera_model_matrix(mainCamera.pointer, out); } /// @@ -1576,8 +1594,8 @@ class ThermionViewerFFI extends ThermionViewer { if (_viewer == null) { throw Exception("No viewer available"); } - var mainCamera = get_camera(_viewer!, await getMainCamera()); - var matrixStruct = get_camera_view_matrix(mainCamera); + var mainCamera = await getMainCamera() as ThermionFFICamera; + var matrixStruct = get_camera_view_matrix(mainCamera.pointer); return double4x4ToMatrix4(matrixStruct); } @@ -1589,8 +1607,8 @@ class ThermionViewerFFI extends ThermionViewer { if (_viewer == null) { throw Exception("No viewer available"); } - var mainCamera = get_camera(_viewer!, await getMainCamera()); - var matrixStruct = get_camera_model_matrix(mainCamera); + var mainCamera = await getMainCamera() as ThermionFFICamera; + var matrixStruct = get_camera_model_matrix(mainCamera.pointer); return double4x4ToMatrix4(matrixStruct); } @@ -1602,8 +1620,8 @@ class ThermionViewerFFI extends ThermionViewer { if (_viewer == null) { throw Exception("No viewer available"); } - var mainCamera = get_camera(_viewer!, await getMainCamera()); - var matrixStruct = get_camera_projection_matrix(mainCamera); + var mainCamera = await getMainCamera() as ThermionFFICamera; + var matrixStruct = get_camera_projection_matrix(mainCamera.pointer); return double4x4ToMatrix4(matrixStruct); } @@ -1615,8 +1633,8 @@ class ThermionViewerFFI extends ThermionViewer { if (_viewer == null) { throw Exception("No viewer available"); } - var mainCamera = get_camera(_viewer!, await getMainCamera()); - var matrixStruct = get_camera_culling_projection_matrix(mainCamera); + var mainCamera = await getMainCamera() as ThermionFFICamera; + var matrixStruct = get_camera_culling_projection_matrix(mainCamera.pointer); return double4x4ToMatrix4(matrixStruct); } @@ -1675,8 +1693,8 @@ class ThermionViewerFFI extends ThermionViewer { if (_viewer == null) { throw Exception("No viewer available"); } - var mainCamera = get_camera(_viewer!, await getMainCamera()); - var arrayPtr = get_camera_frustum(mainCamera); + var mainCamera = await getMainCamera() as ThermionFFICamera; + var arrayPtr = get_camera_frustum(mainCamera.pointer); var doubleList = arrayPtr.asTypedList(24); var frustum = Frustum(); diff --git a/thermion_dart/lib/thermion_dart/viewer/shared_types/camera.dart b/thermion_dart/lib/thermion_dart/viewer/shared_types/camera.dart index 5854c732..d08c4eff 100644 --- a/thermion_dart/lib/thermion_dart/viewer/shared_types/camera.dart +++ b/thermion_dart/lib/thermion_dart/viewer/shared_types/camera.dart @@ -1,6 +1,8 @@ -// abstract class Camera { -// Future setProjectionMatrixWithCulling(Matrix4 projectionMatrix, Matrix4 projectionMatrixForCUlling); -// Future setDepthCullingEnabled(bool enabled); -// } +import 'package:vector_math/vector_math_64.dart'; + +abstract class Camera { + + Future setProjectionMatrixWithCulling(Matrix4 projectionMatrix, double near, double far); + +} -enum AlphaMode { OPAQUE, MASK, BLEND } diff --git a/thermion_dart/lib/thermion_dart/viewer/thermion_viewer_base.dart b/thermion_dart/lib/thermion_dart/viewer/thermion_viewer_base.dart index 5faecd12..01e6be1e 100644 --- a/thermion_dart/lib/thermion_dart/viewer/thermion_viewer_base.dart +++ b/thermion_dart/lib/thermion_dart/viewer/thermion_viewer_base.dart @@ -1,4 +1,5 @@ import 'package:thermion_dart/thermion_dart/viewer/events.dart'; +import 'package:thermion_dart/thermion_dart/viewer/shared_types/camera.dart'; import 'shared_types/shared_types.dart'; export 'shared_types/shared_types.dart'; @@ -444,9 +445,14 @@ abstract class ThermionViewer { Future setMainCamera(); /// - /// Returns the entity associated with the main camera. + /// Returns the entity associated with the main camera. You probably never need this; use getMainCamera instead. /// - Future getMainCamera(); + Future getMainCameraEntity(); + + /// + /// Returns the entity associated with the main camera. You probably never need this; use getMainCamera instead. + /// + Future getMainCamera(); /// /// Sets the horizontal field of view (if [horizontal] is true) or vertical field of view for the currently active camera to [degrees]. @@ -498,7 +504,10 @@ abstract class ThermionViewer { /// /// /// - Future setCameraLensProjection({double near = kNear, double far = kFar, double? aspect, + Future setCameraLensProjection( + {double near = kNear, + double far = kFar, + double? aspect, double focalLength = kFocalLength}); /// diff --git a/thermion_dart/lib/thermion_dart/viewer/thermion_viewer_stub.dart b/thermion_dart/lib/thermion_dart/viewer/thermion_viewer_stub.dart index 273809e0..5f9f2615 100644 --- a/thermion_dart/lib/thermion_dart/viewer/thermion_viewer_stub.dart +++ b/thermion_dart/lib/thermion_dart/viewer/thermion_viewer_stub.dart @@ -4,6 +4,7 @@ import 'dart:typed_data'; import 'package:thermion_dart/thermion_dart/entities/abstract_gizmo.dart'; import 'package:thermion_dart/thermion_dart/thermion_viewer.dart'; import 'package:thermion_dart/thermion_dart/viewer/events.dart'; +import 'package:thermion_dart/thermion_dart/viewer/shared_types/camera.dart'; import 'package:thermion_dart/thermion_dart/viewer/thermion_viewer_base.dart'; import 'package:vector_math/vector_math_64.dart'; import 'dart:async'; @@ -214,12 +215,6 @@ class ThermionViewerStub extends ThermionViewer { throw UnimplementedError(); } - @override - Future getMainCamera() { - // TODO: implement getMainCamera - throw UnimplementedError(); - } - @override Future> getMorphTargetNames( ThermionEntity entity, ThermionEntity childEntity) { @@ -958,6 +953,18 @@ class ThermionViewerStub extends ThermionViewer { // TODO: implement setCameraLensProjection throw UnimplementedError(); } + + @override + Future getMainCameraEntity() { + // TODO: implement getMainCameraEntity + throw UnimplementedError(); + } + + @override + Future getMainCamera() { + // TODO: implement getMainCamera + throw UnimplementedError(); + } } diff --git a/thermion_dart/native/include/APIBoundaryTypes.h b/thermion_dart/native/include/APIBoundaryTypes.h index e4f7d730..61a83cb7 100644 --- a/thermion_dart/native/include/APIBoundaryTypes.h +++ b/thermion_dart/native/include/APIBoundaryTypes.h @@ -11,6 +11,8 @@ extern "C" typedef int32_t _ManipulatorMode; typedef struct TCamera TCamera; typedef struct TMaterialInstance TMaterialInstance; + typedef struct TEngine TEngine; + typedef struct TViewer TViewer; struct TMaterialKey { bool doubleSided = 1; diff --git a/thermion_dart/native/include/FilamentViewer.hpp b/thermion_dart/native/include/FilamentViewer.hpp index a98e99f9..d8ee5058 100644 --- a/thermion_dart/native/include/FilamentViewer.hpp +++ b/thermion_dart/native/include/FilamentViewer.hpp @@ -112,6 +112,9 @@ namespace thermion_filament 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)); + Engine* getEngine() { + return _engine; + } EntityId addLight( LightManager::Type t, diff --git a/thermion_dart/native/include/ThermionDartApi.h b/thermion_dart/native/include/ThermionDartApi.h index 19e33e33..aa619773 100644 --- a/thermion_dart/native/include/ThermionDartApi.h +++ b/thermion_dart/native/include/ThermionDartApi.h @@ -54,24 +54,29 @@ extern "C" { #endif - EMSCRIPTEN_KEEPALIVE const void *create_filament_viewer(const void *const context, const void *const loader, void *const platform, const char *uberArchivePath); - EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer(const void *const viewer); - EMSCRIPTEN_KEEPALIVE void *get_scene_manager(const void *const viewer); - EMSCRIPTEN_KEEPALIVE void create_render_target(const void *const viewer, intptr_t texture, uint32_t width, uint32_t height); - EMSCRIPTEN_KEEPALIVE void clear_background_image(const void *const viewer); - EMSCRIPTEN_KEEPALIVE void set_background_image(const void *const viewer, const char *path, bool fillHeight); - EMSCRIPTEN_KEEPALIVE void set_background_image_position(const void *const viewer, float x, float y, bool clamp); - EMSCRIPTEN_KEEPALIVE void set_background_color(const void *const viewer, const float r, const float g, const float b, const float a); - EMSCRIPTEN_KEEPALIVE void set_tone_mapping(const void *const viewer, int toneMapping); - EMSCRIPTEN_KEEPALIVE void set_bloom(const void *const viewer, float strength); - EMSCRIPTEN_KEEPALIVE void load_skybox(const void *const viewer, const char *skyboxPath); - EMSCRIPTEN_KEEPALIVE void load_ibl(const void *const viewer, const char *iblPath, float intensity); - EMSCRIPTEN_KEEPALIVE void create_ibl(const void *const viewer, float r, float g, float b, float intensity); - EMSCRIPTEN_KEEPALIVE void rotate_ibl(const void *const viewer, float *rotationMatrix); - EMSCRIPTEN_KEEPALIVE void remove_skybox(const void *const viewer); - EMSCRIPTEN_KEEPALIVE void remove_ibl(const void *const viewer); + EMSCRIPTEN_KEEPALIVE TViewer *create_filament_viewer(const void *const context, const void *const loader, void *const platform, const char *uberArchivePath); + EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer(TViewer *viewer); + EMSCRIPTEN_KEEPALIVE void *get_scene_manager(TViewer *viewer); + + // Engine + EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer* viewer); + EMSCRIPTEN_KEEPALIVE TCamera *Engine_getCameraComponent(TEngine* tEngine, EntityId entityId); + + EMSCRIPTEN_KEEPALIVE void create_render_target(TViewer *viewer, intptr_t texture, uint32_t width, uint32_t height); + EMSCRIPTEN_KEEPALIVE void clear_background_image(TViewer *viewer); + EMSCRIPTEN_KEEPALIVE void set_background_image(TViewer *viewer, const char *path, bool fillHeight); + EMSCRIPTEN_KEEPALIVE void set_background_image_position(TViewer *viewer, float x, float y, bool clamp); + EMSCRIPTEN_KEEPALIVE void set_background_color(TViewer *viewer, const float r, const float g, const float b, const float a); + EMSCRIPTEN_KEEPALIVE 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); + EMSCRIPTEN_KEEPALIVE void create_ibl(TViewer *viewer, float r, float g, float b, float intensity); + EMSCRIPTEN_KEEPALIVE void rotate_ibl(TViewer *viewer, float *rotationMatrix); + EMSCRIPTEN_KEEPALIVE void remove_skybox(TViewer *viewer); + EMSCRIPTEN_KEEPALIVE void remove_ibl(TViewer *viewer); EMSCRIPTEN_KEEPALIVE EntityId add_light( - const void *const viewer, + TViewer *viewer, uint8_t type, float colour, float intensity, @@ -88,40 +93,40 @@ extern "C" float sunHaloSize, float sunHaloFallof, bool shadows); - EMSCRIPTEN_KEEPALIVE void remove_light(const void *const viewer, EntityId entityId); - EMSCRIPTEN_KEEPALIVE void clear_lights(const void *const viewer); - EMSCRIPTEN_KEEPALIVE void set_light_position(const void *const viewer, EntityId light, float x, float y, float z); - EMSCRIPTEN_KEEPALIVE void set_light_direction(const void *const viewer, EntityId light, float x, float y, float z); + EMSCRIPTEN_KEEPALIVE void remove_light(TViewer *viewer, EntityId entityId); + EMSCRIPTEN_KEEPALIVE void clear_lights(TViewer *viewer); + EMSCRIPTEN_KEEPALIVE void set_light_position(TViewer *viewer, EntityId light, float x, float y, float z); + EMSCRIPTEN_KEEPALIVE void set_light_direction(TViewer *viewer, EntityId light, float x, float y, float z); EMSCRIPTEN_KEEPALIVE EntityId load_glb(void *sceneManager, const char *assetPath, int numInstances, bool keepData); EMSCRIPTEN_KEEPALIVE EntityId load_glb_from_buffer(void *sceneManager, const void *const data, size_t length, bool keepData, int priority, int layer); EMSCRIPTEN_KEEPALIVE EntityId load_gltf(void *sceneManager, const char *assetPath, const char *relativePath, bool keepData); EMSCRIPTEN_KEEPALIVE EntityId create_instance(void *sceneManager, EntityId id); EMSCRIPTEN_KEEPALIVE int get_instance_count(void *sceneManager, EntityId entityId); EMSCRIPTEN_KEEPALIVE void get_instances(void *sceneManager, EntityId entityId, EntityId *out); - EMSCRIPTEN_KEEPALIVE void set_main_camera(const void *const viewer); - EMSCRIPTEN_KEEPALIVE EntityId get_main_camera(const void *const viewer); - EMSCRIPTEN_KEEPALIVE bool set_camera(const void *const viewer, EntityId entity, const char *nodeName); - EMSCRIPTEN_KEEPALIVE void set_view_frustum_culling(const void *const viewer, bool enabled); + 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 bool render( - const void *const viewer, + TViewer *viewer, uint64_t frameTimeInNanos, void *pixelBuffer, void (*callback)(void *buf, size_t size, void *data), void *data); EMSCRIPTEN_KEEPALIVE void capture( - const void *const viewer, + TViewer *viewer, uint8_t *pixelBuffer, void (*callback)(void)); - EMSCRIPTEN_KEEPALIVE void create_swap_chain(const void *const viewer, const void *const window, uint32_t width, uint32_t height); - EMSCRIPTEN_KEEPALIVE void destroy_swap_chain(const void *const viewer); - EMSCRIPTEN_KEEPALIVE void set_frame_interval(const void *const viewer, float interval); - EMSCRIPTEN_KEEPALIVE void update_viewport(const void *const viewer, uint32_t width, uint32_t height); - EMSCRIPTEN_KEEPALIVE void scroll_begin(const void *const viewer); - EMSCRIPTEN_KEEPALIVE void scroll_update(const void *const viewer, float x, float y, float z); - EMSCRIPTEN_KEEPALIVE void scroll_end(const void *const viewer); - EMSCRIPTEN_KEEPALIVE void grab_begin(const void *const viewer, float x, float y, bool pan); - EMSCRIPTEN_KEEPALIVE void grab_update(const void *const viewer, float x, float y); - EMSCRIPTEN_KEEPALIVE void grab_end(const void *const viewer); + EMSCRIPTEN_KEEPALIVE void create_swap_chain(TViewer *viewer, const void *const window, uint32_t width, uint32_t height); + EMSCRIPTEN_KEEPALIVE void destroy_swap_chain(TViewer *viewer); + 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( void *sceneManager, EntityId entity, @@ -194,8 +199,8 @@ extern "C" EMSCRIPTEN_KEEPALIVE bool update_bone_matrices(void *sceneManager, EntityId entityId); EMSCRIPTEN_KEEPALIVE void get_morph_target_name(void *sceneManager, EntityId assetEntity, EntityId childEntity, char *const outPtr, int index); EMSCRIPTEN_KEEPALIVE int get_morph_target_name_count(void *sceneManager, EntityId assetEntity, EntityId childEntity); - EMSCRIPTEN_KEEPALIVE void remove_entity(const void *const viewer, EntityId asset); - EMSCRIPTEN_KEEPALIVE void clear_entities(const void *const viewer); + EMSCRIPTEN_KEEPALIVE void remove_entity(TViewer *viewer, EntityId asset); + EMSCRIPTEN_KEEPALIVE void clear_entities(TViewer *viewer); EMSCRIPTEN_KEEPALIVE bool set_material_color(void *sceneManager, EntityId entity, const char *meshName, int materialIndex, const float r, const float g, const float b, const float a); EMSCRIPTEN_KEEPALIVE void transform_to_unit_cube(void *sceneManager, EntityId asset); EMSCRIPTEN_KEEPALIVE void queue_position_update(void *sceneManager, EntityId entity, float x, float y, float z, bool relative); @@ -207,10 +212,10 @@ extern "C" EMSCRIPTEN_KEEPALIVE void set_scale(void *sceneManager, EntityId entity, float scale); // Camera methods - EMSCRIPTEN_KEEPALIVE void set_view_frustum_culling(const void *const viewer, bool enabled); + EMSCRIPTEN_KEEPALIVE void set_view_frustum_culling(TViewer *viewer, bool enabled); EMSCRIPTEN_KEEPALIVE void set_camera_exposure(TCamera *camera, float aperture, float shutterSpeed, float sensitivity); EMSCRIPTEN_KEEPALIVE void set_camera_model_matrix(TCamera *camera, double4x4 matrix); - EMSCRIPTEN_KEEPALIVE TCamera *get_camera(const void *const viewer, EntityId entity); + EMSCRIPTEN_KEEPALIVE TCamera *get_camera(TViewer *viewer, EntityId entity); EMSCRIPTEN_KEEPALIVE double get_camera_focal_length(TCamera *const camera); EMSCRIPTEN_KEEPALIVE double4x4 get_camera_model_matrix(TCamera *const camera); EMSCRIPTEN_KEEPALIVE double4x4 get_camera_view_matrix(TCamera *const camera); @@ -224,25 +229,27 @@ extern "C" EMSCRIPTEN_KEEPALIVE float get_camera_fov(TCamera *camera, bool horizontal); EMSCRIPTEN_KEEPALIVE void set_camera_lens_projection(TCamera *camera, double near, double far, double aspect, double focalLength); EMSCRIPTEN_KEEPALIVE void set_camera_focus_distance(TCamera *camera, float focusDistance); - EMSCRIPTEN_KEEPALIVE void set_camera_manipulator_options(const void *const viewer, _ManipulatorMode mode, double orbitSpeedX, double orbitSpeedY, double zoomSpeed); - EMSCRIPTEN_KEEPALIVE void Camera_setCustomProjectionWithCulling(TCamera* camera, double4x4 projectionMatrix, double4x4 projectionMatrixForCulling, double near, double far); + 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 TCamera *get_camera_component(TEngine *engine, EntityId entity); + EMSCRIPTEN_KEEPALIVE int hide_mesh(void *sceneManager, EntityId entity, const char *meshName); EMSCRIPTEN_KEEPALIVE int reveal_mesh(void *sceneManager, EntityId entity, const char *meshName); - EMSCRIPTEN_KEEPALIVE void set_post_processing(void *const viewer, bool enabled); - EMSCRIPTEN_KEEPALIVE void set_shadows_enabled(void *const viewer, bool enabled); - EMSCRIPTEN_KEEPALIVE void set_shadow_type(void *const viewer, int shadowType); - EMSCRIPTEN_KEEPALIVE void set_soft_shadow_options(void *const viewer, float penumbraScale, float penumbraRatioScale); - EMSCRIPTEN_KEEPALIVE void set_antialiasing(void *const viewer, bool msaa, bool fxaa, bool taa); - EMSCRIPTEN_KEEPALIVE void filament_pick(void *const viewer, int x, int y, void (*callback)(EntityId entityId, int x, int y)); + 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 const char *get_name_for_entity(void *const sceneManager, const EntityId entityId); EMSCRIPTEN_KEEPALIVE EntityId find_child_entity_by_name(void *const sceneManager, const EntityId parent, const char *name); EMSCRIPTEN_KEEPALIVE int get_entity_count(void *const sceneManager, const EntityId target, bool renderableOnly); EMSCRIPTEN_KEEPALIVE void get_entities(void *const sceneManager, const EntityId target, bool renderableOnly, EntityId *out); EMSCRIPTEN_KEEPALIVE const char *get_entity_name_at(void *const sceneManager, const EntityId target, int index, bool renderableOnly); - EMSCRIPTEN_KEEPALIVE void set_recording(void *const viewer, bool recording); - EMSCRIPTEN_KEEPALIVE void set_recording_output_directory(void *const viewer, const char *outputDirectory); + EMSCRIPTEN_KEEPALIVE void set_recording(TViewer *viewer, bool recording); + EMSCRIPTEN_KEEPALIVE void set_recording_output_directory(TViewer *viewer, const char *outputDirectory); EMSCRIPTEN_KEEPALIVE void ios_dummy(); EMSCRIPTEN_KEEPALIVE void thermion_flutter_free(void *ptr); EMSCRIPTEN_KEEPALIVE void add_collision_component(void *const sceneManager, EntityId entityId, void (*callback)(const EntityId entityId1, const EntityId entityId2), bool affectsCollidingTransform); @@ -281,7 +288,7 @@ extern "C" EMSCRIPTEN_KEEPALIVE void set_material_property_int(void *const sceneManager, EntityId entity, int materialIndex, const char *property, int value); EMSCRIPTEN_KEEPALIVE void set_material_property_float4(void *const sceneManager, EntityId entity, int materialIndex, const char *property, double4 value); EMSCRIPTEN_KEEPALIVE void set_material_depth_write(void *const sceneManager, EntityId entity, int materialIndex, bool enabled); - EMSCRIPTEN_KEEPALIVE void unproject_texture(void *const sceneManager, 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); EMSCRIPTEN_KEEPALIVE void *const create_texture(void *const sceneManager, uint8_t *data, size_t length); EMSCRIPTEN_KEEPALIVE void destroy_texture(void *const sceneManager, void *const texture); EMSCRIPTEN_KEEPALIVE void apply_texture_to_material(void *const sceneManager, EntityId entity, void *const texture, const char *parameterName, int materialIndex); diff --git a/thermion_dart/native/include/ThermionDartRenderThreadApi.h b/thermion_dart/native/include/ThermionDartRenderThreadApi.h index 33892b52..a11a4b03 100644 --- a/thermion_dart/native/include/ThermionDartRenderThreadApi.h +++ b/thermion_dart/native/include/ThermionDartRenderThreadApi.h @@ -24,29 +24,29 @@ extern "C" const void *const loader, void (*renderCallback)(void *const renderCallbackOwner), void *const renderCallbackOwner, - void (*callback)(void *const viewer)); - EMSCRIPTEN_KEEPALIVE void create_swap_chain_render_thread(void *const viewer, void *const surface, uint32_t width, uint32_t height, void (*onComplete)()); - EMSCRIPTEN_KEEPALIVE void destroy_swap_chain_render_thread(void *const viewer, void (*onComplete)()); - EMSCRIPTEN_KEEPALIVE void create_render_target_render_thread(void *const viewer, intptr_t nativeTextureId, uint32_t width, uint32_t height, void (*onComplete)()); - EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer_render_thread(void *const viewer); - EMSCRIPTEN_KEEPALIVE void render_render_thread(void *const viewer); - EMSCRIPTEN_KEEPALIVE void capture_render_thread(void *const viewer, uint8_t* out, void (*onComplete)()); + void (*callback)(TViewer *viewer)); + EMSCRIPTEN_KEEPALIVE void create_swap_chain_render_thread(TViewer *viewer, void *const surface, uint32_t width, uint32_t height, void (*onComplete)()); + EMSCRIPTEN_KEEPALIVE void destroy_swap_chain_render_thread(TViewer *viewer, void (*onComplete)()); + EMSCRIPTEN_KEEPALIVE void create_render_target_render_thread(TViewer *viewer, intptr_t nativeTextureId, uint32_t width, uint32_t height, void (*onComplete)()); + EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer_render_thread(TViewer *viewer); + EMSCRIPTEN_KEEPALIVE void render_render_thread(TViewer *viewer); + EMSCRIPTEN_KEEPALIVE void capture_render_thread(TViewer *viewer, uint8_t* out, void (*onComplete)()); EMSCRIPTEN_KEEPALIVE FilamentRenderCallback make_render_callback_fn_pointer(FilamentRenderCallback); - EMSCRIPTEN_KEEPALIVE void set_rendering_render_thread(void *const viewer, bool rendering, void(*onComplete)()); - EMSCRIPTEN_KEEPALIVE void request_frame_render_thread(void *const viewer); - EMSCRIPTEN_KEEPALIVE void set_frame_interval_render_thread(void *const viewer, float frameInterval); - EMSCRIPTEN_KEEPALIVE void set_background_color_render_thread(void *const viewer, const float r, const float g, const float b, const float a); - EMSCRIPTEN_KEEPALIVE void clear_background_image_render_thread(void *const viewer); - EMSCRIPTEN_KEEPALIVE void set_background_image_render_thread(void *const viewer, const char *path, bool fillHeight, void (*onComplete)()); - EMSCRIPTEN_KEEPALIVE void set_background_image_position_render_thread(void *const viewer, float x, float y, bool clamp); - EMSCRIPTEN_KEEPALIVE void set_tone_mapping_render_thread(void *const viewer, int toneMapping); - EMSCRIPTEN_KEEPALIVE void set_bloom_render_thread(void *const viewer, float strength); - EMSCRIPTEN_KEEPALIVE void load_skybox_render_thread(void *const viewer, const char *skyboxPath, void (*onComplete)()); - EMSCRIPTEN_KEEPALIVE void load_ibl_render_thread(void *const viewer, const char *iblPath, float intensity); - EMSCRIPTEN_KEEPALIVE void remove_skybox_render_thread(void *const viewer); - EMSCRIPTEN_KEEPALIVE void remove_ibl_render_thread(void *const viewer); + EMSCRIPTEN_KEEPALIVE void set_rendering_render_thread(TViewer *viewer, bool rendering, void(*onComplete)()); + EMSCRIPTEN_KEEPALIVE void request_frame_render_thread(TViewer *viewer); + EMSCRIPTEN_KEEPALIVE void set_frame_interval_render_thread(TViewer *viewer, float frameInterval); + EMSCRIPTEN_KEEPALIVE void set_background_color_render_thread(TViewer *viewer, const float r, const float g, const float b, const float a); + EMSCRIPTEN_KEEPALIVE void clear_background_image_render_thread(TViewer *viewer); + EMSCRIPTEN_KEEPALIVE void set_background_image_render_thread(TViewer *viewer, const char *path, bool fillHeight, void (*onComplete)()); + EMSCRIPTEN_KEEPALIVE void set_background_image_position_render_thread(TViewer *viewer, float x, float y, bool clamp); + EMSCRIPTEN_KEEPALIVE void set_tone_mapping_render_thread(TViewer *viewer, int toneMapping); + EMSCRIPTEN_KEEPALIVE void set_bloom_render_thread(TViewer *viewer, float strength); + EMSCRIPTEN_KEEPALIVE void load_skybox_render_thread(TViewer *viewer, const char *skyboxPath, void (*onComplete)()); + EMSCRIPTEN_KEEPALIVE void load_ibl_render_thread(TViewer *viewer, const char *iblPath, float intensity); + EMSCRIPTEN_KEEPALIVE void remove_skybox_render_thread(TViewer *viewer); + EMSCRIPTEN_KEEPALIVE void remove_ibl_render_thread(TViewer *viewer); EMSCRIPTEN_KEEPALIVE void add_light_render_thread( - void *const viewer, + TViewer *viewer, uint8_t type, float colour, float intensity, @@ -64,15 +64,15 @@ extern "C" float sunHaloFallof, bool shadows, void (*callback)(EntityId)); - EMSCRIPTEN_KEEPALIVE void remove_light_render_thread(void *const viewer, EntityId entityId); - EMSCRIPTEN_KEEPALIVE void clear_lights_render_thread(void *const viewer); + EMSCRIPTEN_KEEPALIVE void remove_light_render_thread(TViewer *viewer, EntityId entityId); + EMSCRIPTEN_KEEPALIVE void clear_lights_render_thread(TViewer *viewer); EMSCRIPTEN_KEEPALIVE void load_glb_render_thread(void *const sceneManager, const char *assetPath, int numInstances, bool keepData, void (*callback)(EntityId)); EMSCRIPTEN_KEEPALIVE void load_glb_from_buffer_render_thread(void *const sceneManager, const uint8_t *const data, size_t length, int numInstances, bool keepData, int priority, int layer, void (*callback)(EntityId)); EMSCRIPTEN_KEEPALIVE void load_gltf_render_thread(void *const sceneManager, const char *assetPath, const char *relativePath, bool keepData, void (*callback)(EntityId)); EMSCRIPTEN_KEEPALIVE void create_instance_render_thread(void *const sceneManager, EntityId entityId, void (*callback)(EntityId)); - EMSCRIPTEN_KEEPALIVE void remove_entity_render_thread(void *const viewer, EntityId asset, void (*callback)()); - EMSCRIPTEN_KEEPALIVE void clear_entities_render_thread(void *const viewer, void (*callback)()); - EMSCRIPTEN_KEEPALIVE void set_camera_render_thread(void *const viewer, EntityId asset, const char *nodeName, void (*callback)(bool)); + 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( void *const sceneManager, EntityId asset, @@ -100,7 +100,7 @@ extern "C" int boneIndex, const float *const transform, void (*callback)(bool)); - EMSCRIPTEN_KEEPALIVE void set_post_processing_render_thread(void *const viewer, bool enabled); + EMSCRIPTEN_KEEPALIVE void set_post_processing_render_thread(TViewer *viewer, bool enabled); EMSCRIPTEN_KEEPALIVE void reset_to_rest_pose_render_thread(void *const sceneManager, EntityId entityId, void(*callback)()); EMSCRIPTEN_KEEPALIVE void create_geometry_render_thread( void *const sceneManager, @@ -116,7 +116,7 @@ extern "C" TMaterialInstance *materialInstance, bool keepData, void (*callback)(EntityId)); - EMSCRIPTEN_KEEPALIVE void unproject_texture_render_thread(void *const sceneManager, EntityId entity, uint8_t* input, uint32_t inputWidth, uint32_t inputHeight, uint8_t* out, uint32_t outWidth, uint32_t outHeight, void(*callback)()); + EMSCRIPTEN_KEEPALIVE void unproject_texture_render_thread(TViewer* viewer, EntityId entity, uint8_t* input, uint32_t inputWidth, uint32_t inputHeight, uint8_t* out, uint32_t outWidth, uint32_t outHeight, void(*callback)()); #ifdef __cplusplus diff --git a/thermion_dart/native/src/ThermionDartApi.cpp b/thermion_dart/native/src/ThermionDartApi.cpp index 0654a054..234230b0 100644 --- a/thermion_dart/native/src/ThermionDartApi.cpp +++ b/thermion_dart/native/src/ThermionDartApi.cpp @@ -44,69 +44,74 @@ extern "C" filament::math::float4{float(d_mat.col4[0]), float(d_mat.col4[1]), float(d_mat.col4[2]), float(d_mat.col4[3])}}; } - EMSCRIPTEN_KEEPALIVE const void *create_filament_viewer(const void *context, const void *const loader, void *const platform, const char *uberArchivePath) + EMSCRIPTEN_KEEPALIVE TViewer *create_filament_viewer(const void *context, const void *const loader, void *const platform, const char *uberArchivePath) { const auto *loaderImpl = new ResourceLoaderWrapperImpl((ResourceLoaderWrapper *)loader); - auto viewer = (const void *)new FilamentViewer(context, loaderImpl, platform, uberArchivePath); - return viewer; + auto viewer = new FilamentViewer(context, loaderImpl, platform, uberArchivePath); + return reinterpret_cast(viewer); } - EMSCRIPTEN_KEEPALIVE void create_render_target(const void *const viewer, intptr_t texture, uint32_t width, uint32_t height) + EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer* viewer) { + auto* engine = reinterpret_cast(viewer)->getEngine(); + return reinterpret_cast(engine); + } + + EMSCRIPTEN_KEEPALIVE void create_render_target(TViewer *viewer, intptr_t texture, uint32_t width, uint32_t height) { ((FilamentViewer *)viewer)->createRenderTarget(texture, width, height); } - EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer(const void *const viewer) + EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer(TViewer *viewer) { delete ((FilamentViewer *)viewer); } - EMSCRIPTEN_KEEPALIVE void set_background_color(const void *const viewer, const float r, const float g, const float b, const float a) + EMSCRIPTEN_KEEPALIVE void set_background_color(TViewer *viewer, const float r, const float g, const float b, const float a) { ((FilamentViewer *)viewer)->setBackgroundColor(r, g, b, a); } - EMSCRIPTEN_KEEPALIVE void clear_background_image(const void *const viewer) + EMSCRIPTEN_KEEPALIVE void clear_background_image(TViewer *viewer) { ((FilamentViewer *)viewer)->clearBackgroundImage(); } - EMSCRIPTEN_KEEPALIVE void set_background_image(const void *const viewer, const char *path, bool fillHeight) + EMSCRIPTEN_KEEPALIVE void set_background_image(TViewer *viewer, const char *path, bool fillHeight) { ((FilamentViewer *)viewer)->setBackgroundImage(path, fillHeight); } - EMSCRIPTEN_KEEPALIVE void set_background_image_position(const void *const viewer, float x, float y, bool clamp) + EMSCRIPTEN_KEEPALIVE void set_background_image_position(TViewer *viewer, float x, float y, bool clamp) { ((FilamentViewer *)viewer)->setBackgroundImagePosition(x, y, clamp); } - EMSCRIPTEN_KEEPALIVE void set_tone_mapping(const void *const viewer, int toneMapping) + EMSCRIPTEN_KEEPALIVE void set_tone_mapping(TViewer *viewer, int toneMapping) { ((FilamentViewer *)viewer)->setToneMapping((ToneMapping)toneMapping); } - EMSCRIPTEN_KEEPALIVE void set_bloom(const void *const viewer, float strength) + EMSCRIPTEN_KEEPALIVE void set_bloom(TViewer *viewer, float strength) { ((FilamentViewer *)viewer)->setBloom(strength); } - EMSCRIPTEN_KEEPALIVE void load_skybox(const void *const viewer, const char *skyboxPath) + EMSCRIPTEN_KEEPALIVE void load_skybox(TViewer *viewer, const char *skyboxPath) { ((FilamentViewer *)viewer)->loadSkybox(skyboxPath); } - EMSCRIPTEN_KEEPALIVE void create_ibl(const void *const viewer, float r, float g, float b, float intensity) + EMSCRIPTEN_KEEPALIVE void create_ibl(TViewer *viewer, float r, float g, float b, float intensity) { ((FilamentViewer *)viewer)->createIbl(r, g, b, intensity); } - EMSCRIPTEN_KEEPALIVE void load_ibl(const void *const viewer, const char *iblPath, float intensity) + EMSCRIPTEN_KEEPALIVE void load_ibl(TViewer *viewer, const char *iblPath, float intensity) { ((FilamentViewer *)viewer)->loadIbl(iblPath, intensity); } - EMSCRIPTEN_KEEPALIVE void rotate_ibl(const void *const viewer, float *rotationMatrix) + EMSCRIPTEN_KEEPALIVE void rotate_ibl(TViewer *viewer, float *rotationMatrix) { math::mat3f matrix(rotationMatrix[0], rotationMatrix[1], rotationMatrix[2], @@ -120,18 +125,18 @@ extern "C" ((FilamentViewer *)viewer)->rotateIbl(matrix); } - EMSCRIPTEN_KEEPALIVE void remove_skybox(const void *const viewer) + EMSCRIPTEN_KEEPALIVE void remove_skybox(TViewer *viewer) { ((FilamentViewer *)viewer)->removeSkybox(); } - EMSCRIPTEN_KEEPALIVE void remove_ibl(const void *const viewer) + EMSCRIPTEN_KEEPALIVE void remove_ibl(TViewer *viewer) { ((FilamentViewer *)viewer)->removeIbl(); } EMSCRIPTEN_KEEPALIVE EntityId add_light( - const void *const viewer, + TViewer *viewer, uint8_t type, float colour, float intensity, @@ -152,22 +157,22 @@ extern "C" return ((FilamentViewer *)viewer)->addLight((LightManager::Type)type, colour, intensity, posX, posY, posZ, dirX, dirY, dirZ, falloffRadius, spotLightConeInner, spotLightConeOuter, sunAngularRadius, sunHaloSize, sunHaloFallof, shadows); } - EMSCRIPTEN_KEEPALIVE void set_light_position(const void *const viewer, int32_t entityId, float x, float y, float z) + EMSCRIPTEN_KEEPALIVE void set_light_position(TViewer *viewer, int32_t entityId, float x, float y, float z) { ((FilamentViewer *)viewer)->setLightPosition(entityId, x, y, z); } - EMSCRIPTEN_KEEPALIVE void set_light_direction(const void *const viewer, int32_t entityId, float x, float y, float z) + EMSCRIPTEN_KEEPALIVE void set_light_direction(TViewer *viewer, int32_t entityId, float x, float y, float z) { ((FilamentViewer *)viewer)->setLightDirection(entityId, x, y, z); } - EMSCRIPTEN_KEEPALIVE void remove_light(const void *const viewer, int32_t entityId) + EMSCRIPTEN_KEEPALIVE void remove_light(TViewer *viewer, int32_t entityId) { ((FilamentViewer *)viewer)->removeLight(entityId); } - EMSCRIPTEN_KEEPALIVE void clear_lights(const void *const viewer) + EMSCRIPTEN_KEEPALIVE void clear_lights(TViewer *viewer) { ((FilamentViewer *)viewer)->clearLights(); } @@ -202,17 +207,17 @@ extern "C" return ((SceneManager *)sceneManager)->loadGltf(assetPath, relativePath, keepData); } - EMSCRIPTEN_KEEPALIVE void set_main_camera(const void *const viewer) + EMSCRIPTEN_KEEPALIVE void set_main_camera(TViewer *viewer) { return ((FilamentViewer *)viewer)->setMainCamera(); } - EMSCRIPTEN_KEEPALIVE EntityId get_main_camera(const void *const viewer) + EMSCRIPTEN_KEEPALIVE EntityId get_main_camera(TViewer *viewer) { return ((FilamentViewer *)viewer)->getMainCamera(); } - EMSCRIPTEN_KEEPALIVE bool set_camera(const void *const viewer, EntityId asset, const char *nodeName) + EMSCRIPTEN_KEEPALIVE bool set_camera(TViewer *viewer, EntityId asset, const char *nodeName) { return ((FilamentViewer *)viewer)->setCamera(asset, nodeName); } @@ -235,7 +240,7 @@ extern "C" cam->setProjection(fovInDegrees, aspect, near, far, horizontal ? Camera::Fov::HORIZONTAL : Camera::Fov::VERTICAL); } - EMSCRIPTEN_KEEPALIVE TCamera *get_camera(const void *const viewer, EntityId entity) + EMSCRIPTEN_KEEPALIVE TCamera *get_camera(TViewer *viewer, EntityId entity) { auto filamentCamera = ((FilamentViewer *)viewer)->getCamera(entity); return reinterpret_cast(filamentCamera); @@ -309,12 +314,12 @@ extern "C" return array; } - EMSCRIPTEN_KEEPALIVE void set_camera_manipulator_options(const void *const viewer, _ManipulatorMode mode, double orbitSpeedX, double orbitSpeedY, double zoomSpeed) + 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(const void *const viewer, bool enabled) + EMSCRIPTEN_KEEPALIVE void set_view_frustum_culling(TViewer *viewer, bool enabled) { ((FilamentViewer *)viewer)->setViewFrustumCulling(enabled); } @@ -339,17 +344,17 @@ extern "C" } EMSCRIPTEN_KEEPALIVE bool render( - const void *const viewer, + TViewer *viewer, uint64_t frameTimeInNanos, void *pixelBuffer, void (*callback)(void *buf, size_t size, void *data), void *data) { - return ((FilamentViewer *)viewer)->render(frameTimeInNanos, pixelBuffer, callback, data); + return ((FilamentViewer *)viewer)->render(frameTimeInNanos, pixelBuffer, callback, data); } EMSCRIPTEN_KEEPALIVE void capture( - const void *const viewer, + TViewer *viewer, uint8_t *pixelBuffer, void (*callback)(void)) { @@ -362,58 +367,58 @@ extern "C" }; EMSCRIPTEN_KEEPALIVE void set_frame_interval( - const void *const viewer, + TViewer *viewer, float frameInterval) { ((FilamentViewer *)viewer)->setFrameInterval(frameInterval); } - EMSCRIPTEN_KEEPALIVE void destroy_swap_chain(const void *const viewer) + EMSCRIPTEN_KEEPALIVE void destroy_swap_chain(TViewer *viewer) { ((FilamentViewer *)viewer)->destroySwapChain(); } - EMSCRIPTEN_KEEPALIVE void create_swap_chain(const void *const viewer, const void *const window, uint32_t width, uint32_t height) + EMSCRIPTEN_KEEPALIVE void create_swap_chain(TViewer *viewer, const void *const window, uint32_t width, uint32_t height) { ((FilamentViewer *)viewer)->createSwapChain(window, width, height); } - EMSCRIPTEN_KEEPALIVE void update_viewport(const void *const viewer, uint32_t width, uint32_t height) + EMSCRIPTEN_KEEPALIVE void update_viewport(TViewer *viewer, uint32_t width, uint32_t height) { return ((FilamentViewer *)viewer)->updateViewport(width, height); } - EMSCRIPTEN_KEEPALIVE void scroll_update(const void *const viewer, float x, float y, float delta) + EMSCRIPTEN_KEEPALIVE void scroll_update(TViewer *viewer, float x, float y, float delta) { ((FilamentViewer *)viewer)->scrollUpdate(x, y, delta); } - EMSCRIPTEN_KEEPALIVE void scroll_begin(const void *const viewer) + EMSCRIPTEN_KEEPALIVE void scroll_begin(TViewer *viewer) { ((FilamentViewer *)viewer)->scrollBegin(); } - EMSCRIPTEN_KEEPALIVE void scroll_end(const void *const viewer) + EMSCRIPTEN_KEEPALIVE void scroll_end(TViewer *viewer) { ((FilamentViewer *)viewer)->scrollEnd(); } - EMSCRIPTEN_KEEPALIVE void grab_begin(const void *const viewer, float x, float y, bool pan) + EMSCRIPTEN_KEEPALIVE void grab_begin(TViewer *viewer, float x, float y, bool pan) { ((FilamentViewer *)viewer)->grabBegin(x, y, pan); } - EMSCRIPTEN_KEEPALIVE void grab_update(const void *const viewer, float x, float y) + EMSCRIPTEN_KEEPALIVE void grab_update(TViewer *viewer, float x, float y) { ((FilamentViewer *)viewer)->grabUpdate(x, y); } - EMSCRIPTEN_KEEPALIVE void grab_end(const void *const viewer) + EMSCRIPTEN_KEEPALIVE void grab_end(TViewer *viewer) { ((FilamentViewer *)viewer)->grabEnd(); } - EMSCRIPTEN_KEEPALIVE void *get_scene_manager(const void *const viewer) + EMSCRIPTEN_KEEPALIVE void *get_scene_manager(TViewer *viewer) { return (void *)((FilamentViewer *)viewer)->getSceneManager(); } @@ -475,27 +480,27 @@ extern "C" ((SceneManager *)sceneManager)->addBoneAnimation(asset, skinIndex, boneIndex, frameData, numFrames, frameLengthInMs, fadeOutInSecs, fadeInInSecs, maxDelta); } - EMSCRIPTEN_KEEPALIVE void set_post_processing(void *const viewer, bool enabled) + EMSCRIPTEN_KEEPALIVE void set_post_processing(TViewer *viewer, bool enabled) { ((FilamentViewer *)viewer)->setPostProcessing(enabled); } - EMSCRIPTEN_KEEPALIVE void set_shadows_enabled(void *const viewer, bool enabled) + EMSCRIPTEN_KEEPALIVE void set_shadows_enabled(TViewer *viewer, bool enabled) { ((FilamentViewer *)viewer)->setShadowsEnabled(enabled); } - EMSCRIPTEN_KEEPALIVE void set_shadow_type(void *const viewer, int shadowType) + EMSCRIPTEN_KEEPALIVE void set_shadow_type(TViewer *viewer, int shadowType) { ((FilamentViewer *)viewer)->setShadowType((ShadowType)shadowType); } - EMSCRIPTEN_KEEPALIVE void set_soft_shadow_options(void *const viewer, float penumbraScale, float penumbraRatioScale) + EMSCRIPTEN_KEEPALIVE void set_soft_shadow_options(TViewer *viewer, float penumbraScale, float penumbraRatioScale) { ((FilamentViewer *)viewer)->setSoftShadowOptions(penumbraScale, penumbraRatioScale); } - EMSCRIPTEN_KEEPALIVE void set_antialiasing(void *const viewer, bool msaa, bool fxaa, bool taa) + EMSCRIPTEN_KEEPALIVE void set_antialiasing(TViewer *viewer, bool msaa, bool fxaa, bool taa) { ((FilamentViewer *)viewer)->setAntiAliasing(msaa, fxaa, taa); } @@ -721,12 +726,12 @@ extern "C" strcpy(outPtr, name.c_str()); } - EMSCRIPTEN_KEEPALIVE void remove_entity(const void *const viewer, EntityId asset) + EMSCRIPTEN_KEEPALIVE void remove_entity(TViewer *viewer, EntityId asset) { ((FilamentViewer *)viewer)->removeEntity(asset); } - EMSCRIPTEN_KEEPALIVE void clear_entities(const void *const viewer) + EMSCRIPTEN_KEEPALIVE void clear_entities(TViewer *viewer) { ((FilamentViewer *)viewer)->clearEntities(); } @@ -791,7 +796,7 @@ extern "C" return ((SceneManager *)sceneManager)->reveal(asset, meshName); } - EMSCRIPTEN_KEEPALIVE void filament_pick(void *const viewer, int x, int y, void (*callback)(EntityId entityId, int x, int y)) + EMSCRIPTEN_KEEPALIVE void filament_pick(TViewer *viewer, int x, int y, void (*callback)(EntityId entityId, int x, int y)) { ((FilamentViewer *)viewer)->pick(static_cast(x), static_cast(y), callback); } @@ -816,12 +821,12 @@ extern "C" return ((SceneManager *)sceneManager)->getEntityNameAt(target, index, renderableOnly); } - EMSCRIPTEN_KEEPALIVE void set_recording(void *const viewer, bool recording) + EMSCRIPTEN_KEEPALIVE void set_recording(TViewer *viewer, bool recording) { ((FilamentViewer *)viewer)->setRecording(recording); } - EMSCRIPTEN_KEEPALIVE void set_recording_output_directory(void *const viewer, const char *outputDirectory) + EMSCRIPTEN_KEEPALIVE void set_recording_output_directory(TViewer *viewer, const char *outputDirectory) { ((FilamentViewer *)viewer)->setRecordingOutputDirectory(outputDirectory); } @@ -987,7 +992,7 @@ extern "C" ((SceneManager *)sceneManager)->setMaterialProperty(entity, materialIndex, property, filamentValue); } - EMSCRIPTEN_KEEPALIVE void unproject_texture(void *const 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); } @@ -1058,7 +1063,14 @@ EMSCRIPTEN_KEEPALIVE void MaterialInstance_setDepthCulling(TMaterialInstance* ma reinterpret_cast(materialInstance)->setDepthCulling(enabled); } -EMSCRIPTEN_KEEPALIVE void Camera_setCustomProjectionWithCulling(TCamera* camera, double4x4 projectionMatrix, double4x4 projectionMatrixForCulling, double near, double far) { - reinterpret_cast(camera)->setCustomProjection(convert_double4x4_to_mat4(projectionMatrix), convert_double4x4_to_mat4(projectionMatrixForCulling), near, far); +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 TCamera *Engine_getCameraComponent(TEngine* tEngine, EntityId entityId) { + auto * engine = reinterpret_cast(tEngine); + auto * camera = engine->getCameraComponent(utils::Entity::import(entityId)); + return reinterpret_cast(camera); } } diff --git a/thermion_dart/native/src/ThermionDartRenderThreadApi.cpp b/thermion_dart/native/src/ThermionDartRenderThreadApi.cpp index ab509990..23a7676a 100644 --- a/thermion_dart/native/src/ThermionDartRenderThreadApi.cpp +++ b/thermion_dart/native/src/ThermionDartRenderThreadApi.cpp @@ -133,7 +133,7 @@ public: const ResourceLoaderWrapper *const loader, void (*renderCallback)(void *), void *const owner, - void (*callback)(void *const)) + void (*callback)(TViewer*)) { _renderCallback = renderCallback; _renderCallbackOwner = owner; @@ -155,7 +155,8 @@ public: _viewer = (FilamentViewer *)create_filament_viewer((void *const)_context, loader, platform, uberArchivePath); MAIN_THREAD_EM_ASM({ moduleArg.dartFilamentResolveCallback($0, $1); }, callback, _viewer); #else - _viewer = (FilamentViewer *)create_filament_viewer(context, loader, platform, uberArchivePath); + auto viewer = (FilamentViewer *)create_filament_viewer(context, loader, platform, uberArchivePath); + _viewer = reinterpret_cast(viewer); callback(_viewer); #endif }); @@ -168,7 +169,7 @@ public: { _render = false; _viewer = nullptr; - destroy_filament_viewer(viewer); }); + destroy_filament_viewer(reinterpret_cast(viewer)); }); auto fut = add_task(lambda); fut.wait(); } @@ -222,7 +223,7 @@ private: void (*_renderCallback)(void *const) = nullptr; void *_renderCallbackOwner = nullptr; std::deque> _tasks; - FilamentViewer *_viewer = nullptr; + TViewer *_viewer = nullptr; std::chrono::high_resolution_clock::time_point _lastFrameTime; int _frameCount = 0; float _accumulatedTime = 0.0f; @@ -246,7 +247,7 @@ extern "C" const void *const loader, void (*renderCallback)(void *const renderCallbackOwner), void *const renderCallbackOwner, - void (*callback)(void *const)) + void (*callback)(TViewer *)) { if (!_rl) @@ -257,14 +258,14 @@ extern "C" renderCallback, renderCallbackOwner, callback); } - EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer_render_thread(void *const viewer) + EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer_render_thread(TViewer *viewer) { _rl->destroyViewer((FilamentViewer *)viewer); delete _rl; _rl = nullptr; } - EMSCRIPTEN_KEEPALIVE void create_swap_chain_render_thread(void *const viewer, + EMSCRIPTEN_KEEPALIVE void create_swap_chain_render_thread(TViewer *viewer, void *const surface, uint32_t width, uint32_t height, @@ -283,7 +284,7 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void destroy_swap_chain_render_thread(void *const viewer, void (*onComplete)()) + EMSCRIPTEN_KEEPALIVE void destroy_swap_chain_render_thread(TViewer *viewer, void (*onComplete)()) { std::packaged_task lambda( [=]() mutable @@ -298,7 +299,7 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void create_render_target_render_thread(void *const viewer, + EMSCRIPTEN_KEEPALIVE void create_render_target_render_thread(TViewer *viewer, intptr_t nativeTextureId, uint32_t width, uint32_t height, @@ -316,7 +317,7 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void request_frame_render_thread(void *const viewer) + EMSCRIPTEN_KEEPALIVE void request_frame_render_thread(TViewer *viewer) { if (!_rl) { @@ -329,7 +330,7 @@ extern "C" } EMSCRIPTEN_KEEPALIVE void - set_frame_interval_render_thread(void *const viewer, float frameIntervalInMilliseconds) + set_frame_interval_render_thread(TViewer *viewer, float frameIntervalInMilliseconds) { _rl->setFrameIntervalInMilliseconds(frameIntervalInMilliseconds); std::packaged_task lambda([=]() mutable @@ -337,14 +338,14 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void render_render_thread(void *const viewer) + EMSCRIPTEN_KEEPALIVE void render_render_thread(TViewer *viewer) { std::packaged_task lambda([=]() mutable { _rl->doRender(); }); auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void capture_render_thread(void *const viewer, uint8_t *pixelBuffer, void (*onComplete)()) + EMSCRIPTEN_KEEPALIVE void capture_render_thread(TViewer *viewer, uint8_t *pixelBuffer, void (*onComplete)()) { std::packaged_task lambda([=]() mutable { capture(viewer, pixelBuffer, onComplete); }); @@ -352,7 +353,7 @@ extern "C" } EMSCRIPTEN_KEEPALIVE void - set_background_color_render_thread(void *const viewer, const float r, const float g, + set_background_color_render_thread(TViewer *viewer, const float r, const float g, const float b, const float a) { std::packaged_task lambda( @@ -420,14 +421,14 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void clear_background_image_render_thread(void *const viewer) + EMSCRIPTEN_KEEPALIVE void clear_background_image_render_thread(TViewer *viewer) { std::packaged_task lambda([=] { clear_background_image(viewer); }); auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void set_background_image_render_thread(void *const viewer, + EMSCRIPTEN_KEEPALIVE void set_background_image_render_thread(TViewer *viewer, const char *path, bool fillHeight, void (*callback)()) { @@ -443,7 +444,7 @@ extern "C" }); auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void set_background_image_position_render_thread(void *const viewer, + EMSCRIPTEN_KEEPALIVE void set_background_image_position_render_thread(TViewer *viewer, float x, float y, bool clamp) { @@ -452,7 +453,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(void *const viewer, + EMSCRIPTEN_KEEPALIVE void set_tone_mapping_render_thread(TViewer *viewer, int toneMapping) { std::packaged_task lambda( @@ -460,13 +461,13 @@ extern "C" { set_tone_mapping(viewer, toneMapping); }); auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void set_bloom_render_thread(void *const viewer, float strength) + 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(void *const viewer, + EMSCRIPTEN_KEEPALIVE void load_skybox_render_thread(TViewer *viewer, const char *skyboxPath, void (*onComplete)()) { @@ -482,7 +483,7 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void load_ibl_render_thread(void *const viewer, const char *iblPath, + EMSCRIPTEN_KEEPALIVE void load_ibl_render_thread(TViewer *viewer, const char *iblPath, float intensity) { std::packaged_task lambda( @@ -490,14 +491,14 @@ extern "C" { load_ibl(viewer, iblPath, intensity); }); auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void remove_skybox_render_thread(void *const viewer) + EMSCRIPTEN_KEEPALIVE void remove_skybox_render_thread(TViewer *viewer) { std::packaged_task lambda([=] { remove_skybox(viewer); }); auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void remove_ibl_render_thread(void *const viewer) + EMSCRIPTEN_KEEPALIVE void remove_ibl_render_thread(TViewer *viewer) { std::packaged_task lambda([=] { remove_ibl(viewer); }); @@ -505,7 +506,7 @@ extern "C" } void add_light_render_thread( - void *const viewer, + TViewer *viewer, uint8_t type, float colour, float intensity, @@ -556,7 +557,7 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void remove_light_render_thread(void *const viewer, + EMSCRIPTEN_KEEPALIVE void remove_light_render_thread(TViewer *viewer, EntityId entityId) { std::packaged_task lambda([=] @@ -564,14 +565,14 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void clear_lights_render_thread(void *const viewer) + EMSCRIPTEN_KEEPALIVE void clear_lights_render_thread(TViewer *viewer) { std::packaged_task lambda([=] { clear_lights(viewer); }); auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void remove_entity_render_thread(void *const viewer, + EMSCRIPTEN_KEEPALIVE void remove_entity_render_thread(TViewer *viewer, EntityId asset, void (*callback)()) { std::packaged_task lambda([=] @@ -586,7 +587,7 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void clear_entities_render_thread(void *const viewer, void (*callback)()) + EMSCRIPTEN_KEEPALIVE void clear_entities_render_thread(TViewer *viewer, void (*callback)()) { std::packaged_task lambda([=] { @@ -600,7 +601,7 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void set_camera_render_thread(void *const viewer, EntityId asset, + EMSCRIPTEN_KEEPALIVE void set_camera_render_thread(TViewer *viewer, EntityId asset, const char *nodeName, void (*callback)(bool)) { std::packaged_task lambda( @@ -707,7 +708,7 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void set_post_processing_render_thread(void *const viewer, + EMSCRIPTEN_KEEPALIVE void set_post_processing_render_thread(TViewer *viewer, bool enabled) { std::packaged_task lambda( @@ -834,7 +835,7 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void unproject_texture_render_thread(void *const viewer, EntityId entity, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight, void (*callback)()) + EMSCRIPTEN_KEEPALIVE void unproject_texture_render_thread(TViewer* viewer, EntityId entity, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight, void (*callback)()) { std::packaged_task lambda( [=] diff --git a/thermion_dart/test/helpers.dart b/thermion_dart/test/helpers.dart index 6b1cb195..76a366e8 100644 --- a/thermion_dart/test/helpers.dart +++ b/thermion_dart/test/helpers.dart @@ -10,8 +10,7 @@ import 'package:thermion_dart/thermion_dart/utils/dart_resources.dart'; import 'package:thermion_dart/thermion_dart/thermion_viewer.dart'; import 'package:thermion_dart/thermion_dart/viewer/ffi/thermion_dart.g.dart'; import 'package:thermion_dart/thermion_dart/viewer/ffi/thermion_viewer_ffi.dart'; - -final viewportDimensions = (width: 500, height: 500); +import 'package:vector_math/vector_math_64.dart'; /// Test files are run in a variety of ways, find this package root in all. /// @@ -107,7 +106,8 @@ Future pixelBufferToBmp( return data; } -Future bmpToPng(Uint8List pixelBuffer, int width, int height) async { +Future pixelsToPng(Uint8List pixelBuffer, int width, int height, + {bool linearToSrgb = false}) async { final image = img.Image(width: width, height: height); for (int y = 0; y < height; y++) { @@ -126,13 +126,23 @@ Future bmpToPng(Uint8List pixelBuffer, int width, int height) async { b = _inverseACESToneMapping(b); } - // Convert from linear to sRGB - final int sRgbR = _linearToSRGB(r); - final int sRgbG = _linearToSRGB(g); - final int sRgbB = _linearToSRGB(b); + if (linearToSrgb) { + // Convert from linear to sRGB - image.setPixel( - x, y, img.ColorUint8(4)..setRgba(sRgbR, sRgbG, sRgbB, 1.0)); + image.setPixel( + x, + y, + img.ColorUint8(4) + ..setRgba( + _linearToSRGB(r), _linearToSRGB(g), _linearToSRGB(b), 1.0)); + } else { + image.setPixel( + x, + y, + img.ColorUint8(4) + ..setRgba((r * 255).toInt(), (g * 255).toInt(), (b * 255).toInt(), + 1.0)); + } } } @@ -163,7 +173,10 @@ int _linearToSRGB(double linearValue) { } } -Future createViewer() async { +Future createViewer( + {img.Color? bg, + Vector3? cameraPosition, + viewportDimensions = (width: 500, height: 500)}) async { final packageUri = findPackageRoot('thermion_dart'); final lib = ThermionDartTexture1(DynamicLibrary.open( @@ -192,5 +205,280 @@ Future createViewer() async { await viewer.updateViewportAndCameraProjection( viewportDimensions.width.toDouble(), viewportDimensions.height.toDouble()); + if (bg != null) { + await viewer.setBackgroundColor( + bg.r.toDouble(), bg.g.toDouble(), bg.b.toDouble(), bg.a.toDouble()); + } + + if (cameraPosition != null) { + await viewer.setCameraPosition( + cameraPosition.x, cameraPosition.y, cameraPosition.z); + } return viewer; } + +Uint8List poissonBlend(List textures, int width, int height) { + final int numTextures = textures.length; + final int size = width * height; + + // Initialize the result + List result = List.generate(size, (_) => Vector4(0, 0, 0, 0)); + List validPixel = List.generate(size, (_) => false); + + // Compute gradients and perform simplified Poisson blending + for (int y = 1; y < height - 1; y++) { + for (int x = 1; x < width - 1; x++) { + int index = y * width + x; + Vector4 gradX = Vector4(0, 0, 0, 0); + Vector4 gradY = Vector4(0, 0, 0, 0); + bool hasValidData = false; + + for (int t = 0; t < numTextures; t++) { + int i = index * 4; + if (textures[t][i] == 0 && + textures[t][i + 1] == 0 && + textures[t][i + 2] == 0 && + textures[t][i + 3] == 0) { + continue; // Skip this texture if the pixel is empty + } + + hasValidData = true; + int iLeft = (y * width + x - 1) * 4; + int iRight = (y * width + x + 1) * 4; + int iUp = ((y - 1) * width + x) * 4; + int iDown = ((y + 1) * width + x) * 4; + + Vector4 gx = Vector4( + (textures[t][iRight] - textures[t][iLeft]) / 2, + (textures[t][iRight + 1] - textures[t][iLeft + 1]) / 2, + (textures[t][iRight + 2] - textures[t][iLeft + 2]) / 2, + (textures[t][iRight + 3] - textures[t][iLeft + 3]) / 2); + + Vector4 gy = Vector4( + (textures[t][iDown] - textures[t][iUp]) / 2, + (textures[t][iDown + 1] - textures[t][iUp + 1]) / 2, + (textures[t][iDown + 2] - textures[t][iUp + 2]) / 2, + (textures[t][iDown + 3] - textures[t][iUp + 3]) / 2); + + // Select the gradient with larger magnitude + double magX = gx.r * gx.r + gx.g * gx.g + gx.b * gx.b + gx.a * gx.a; + double magY = gy.r * gy.r + gy.g * gy.g + gy.b * gy.b + gy.a * gy.a; + + if (magX > + gradX.r * gradX.r + + gradX.g * gradX.g + + gradX.b * gradX.b + + gradX.a * gradX.a) { + gradX = gx; + } + if (magY > + gradY.r * gradY.r + + gradY.g * gradY.g + + gradY.b * gradY.b + + gradY.a * gradY.a) { + gradY = gy; + } + } + + if (hasValidData) { + validPixel[index] = true; + // Simplified Poisson equation solver (Jacobi iteration) + result[index].r = (result[index - 1].r + + result[index + 1].r + + result[index - width].r + + result[index + width].r + + gradX.r - + gradY.r) / + 4; + result[index].g = (result[index - 1].g + + result[index + 1].g + + result[index - width].g + + result[index + width].g + + gradX.g - + gradY.g) / + 4; + result[index].b = (result[index - 1].b + + result[index + 1].b + + result[index - width].b + + result[index + width].b + + gradX.b - + gradY.b) / + 4; + result[index].a = (result[index - 1].a + + result[index + 1].a + + result[index - width].a + + result[index + width].a + + gradX.a - + gradY.a) / + 4; + } + } + } + + // Fill in gaps and normalize + Uint8List finalResult = Uint8List(size * 4); + for (int i = 0; i < size; i++) { + if (validPixel[i]) { + finalResult[i * 4] = (result[i].r.clamp(0, 255)).toInt(); + finalResult[i * 4 + 1] = (result[i].g.clamp(0, 255)).toInt(); + finalResult[i * 4 + 2] = (result[i].b.clamp(0, 255)).toInt(); + finalResult[i * 4 + 3] = (result[i].a.clamp(0, 255)).toInt(); + } else { + // For invalid pixels, try to interpolate from neighbors + List validNeighbors = []; + if (i > width && validPixel[i - width]) validNeighbors.add(i - width); + if (i < size - width && validPixel[i + width]) + validNeighbors.add(i + width); + if (i % width > 0 && validPixel[i - 1]) validNeighbors.add(i - 1); + if (i % width < width - 1 && validPixel[i + 1]) validNeighbors.add(i + 1); + + if (validNeighbors.isNotEmpty) { + double r = 0, g = 0, b = 0, a = 0; + for (int neighbor in validNeighbors) { + r += result[neighbor].r; + g += result[neighbor].g; + b += result[neighbor].b; + a += result[neighbor].a; + } + finalResult[i * 4] = (r / validNeighbors.length).clamp(0, 255).toInt(); + finalResult[i * 4 + 1] = + (g / validNeighbors.length).clamp(0, 255).toInt(); + finalResult[i * 4 + 2] = + (b / validNeighbors.length).clamp(0, 255).toInt(); + finalResult[i * 4 + 3] = + (a / validNeighbors.length).clamp(0, 255).toInt(); + } else { + // If no valid neighbors, set to transparent black + finalResult[i * 4] = 0; + finalResult[i * 4 + 1] = 0; + finalResult[i * 4 + 2] = 0; + finalResult[i * 4 + 3] = 0; + } + } + } + + return finalResult; +} + +Uint8List medianImages(List images) { + if (images.isEmpty) { + return Uint8List(0); + } + + int imageSize = images[0].length; + Uint8List result = Uint8List(imageSize); + int numImages = images.length; + + for (int i = 0; i < imageSize; i++) { + List pixelValues = []; + for (int j = 0; j < numImages; j++) { + pixelValues.add(images[j][i]); + } + + pixelValues.sort(); + int medianIndex = numImages ~/ 2; + result[i] = pixelValues[medianIndex]; + } + + return result; +} + +Uint8List maxIntensityProjection( + List textures, int width, int height) { + final int numTextures = textures.length; + final int size = width * height; + + // Initialize the result with the first texture + Uint8List result = Uint8List.fromList(textures[0]); + + // Iterate through all textures and perform max intensity projection + for (int t = 1; t < numTextures; t++) { + for (int i = 0; i < size * 4; i += 4) { + // Calculate intensity (using luminance formula) + double intensityCurrent = + 0.299 * result[i] + 0.587 * result[i + 1] + 0.114 * result[i + 2]; + double intensityNew = 0.299 * textures[t][i] + + 0.587 * textures[t][i + 1] + + 0.114 * textures[t][i + 2]; + + // If the new texture has higher intensity, use its values + if (intensityNew > intensityCurrent) { + result[i] = textures[t][i]; // R + result[i + 1] = textures[t][i + 1]; // G + result[i + 2] = textures[t][i + 2]; // B + result[i + 3] = textures[t][i + 3]; // A + } + } + } + + return result; +} + +// Helper function to blend MIP result with Poisson blending +Uint8List blendMIPWithPoisson( + Uint8List mipResult, Uint8List poissonResult, double alpha) { + final int size = mipResult.length; + Uint8List blendedResult = Uint8List(size); + + for (int i = 0; i < size; i++) { + blendedResult[i] = (mipResult[i] * (1 - alpha) + poissonResult[i] * alpha) + .round() + .clamp(0, 255); + } + + return blendedResult; +} + +Uint8List pngToPixelBuffer(Uint8List pngData) { + // Decode the PNG image + final image = img.decodePng(pngData); + + if (image == null) { + throw Exception('Failed to decode PNG image'); + } + + // Create a buffer for the raw pixel data + final rawPixels = Uint8List(image.width * image.height * 4); + + // Convert the image to RGBA format + for (int y = 0; y < image.height; y++) { + for (int x = 0; x < image.width; x++) { + final pixel = image.getPixel(x, y); + final i = (y * image.width + x) * 4; + rawPixels[i] = pixel.r.toInt(); // Red + rawPixels[i + 1] = pixel.g.toInt(); // Green + rawPixels[i + 2] = pixel.b.toInt(); // Blue + rawPixels[i + 3] = pixel.a.toInt(); // Alpha + } + } + + return rawPixels; +} + +Uint8List medianBlending(List textures, int width, int height) { + final int numTextures = textures.length; + final int size = width * height; + + Uint8List result = Uint8List(size * 4); + + for (int i = 0; i < size; i++) { + List values = []; + for (int t = 0; t < numTextures; t++) { + if (textures[t][i * 4] != 0 || + textures[t][i * 4 + 1] != 0 || + textures[t][i * 4 + 2] != 0 || + textures[t][i * 4 + 3] != 0) { + values.addAll(textures[t].sublist(i * 4, i * 4 + 4)); + } + } + + if (values.isNotEmpty) { + values.sort(); + result[i] = values[values.length ~/ 2]; + } else { + result[i] = 0; // If no valid data, set to transparent + } + } + + return result; +} diff --git a/thermion_dart/test/integration_test.dart b/thermion_dart/test/integration_test.dart index 83985a5a..f35689ea 100644 --- a/thermion_dart/test/integration_test.dart +++ b/thermion_dart/test/integration_test.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'dart:math'; import 'dart:typed_data'; +import 'package:image/image.dart'; import 'package:thermion_dart/thermion_dart.dart'; import 'package:test/test.dart'; import 'package:animation_tools_dart/animation_tools_dart.dart'; @@ -14,6 +15,9 @@ import 'package:vector_math/vector_math_64.dart'; import 'helpers.dart'; +Color kWhite = ColorFloat32(4)..setRgba(1.0, 1.0, 1.0, 1.0); +Color kRed = ColorFloat32(4)..setRgba(1.0, 0.0, 0.0, 1.0); + void main() async { final packageUri = findPackageRoot('thermion_dart'); testDir = Directory("${packageUri.toFilePath()}/test").path; @@ -98,6 +102,27 @@ void main() async { print(frustum.plane5.normal); print(frustum.plane5.constant); }); + + test('set custom projection/culling matrix', () async { + var viewer = await createViewer(bg:kRed, cameraPosition:Vector3(0,0,4)); + var camera = await viewer.getMainCamera(); + final cube = await viewer.createGeometry(GeometryHelper.cube()); + + + // cube is visible when inside the frustum, cube is visible + var projectionMatrix = + makeOrthographicMatrix(-10.0, 10.0, -10.0, 10.0, 0.05, 10000); + await camera.setProjectionMatrixWithCulling( + projectionMatrix, 0.05, 10000); + await _capture(viewer, "camera_projection_culling_matrix_object_in_frustum"); + + // cube no longer visible when the far plane is moved closer to camera so cube is outside + projectionMatrix = + makeOrthographicMatrix(-10.0, 10.0, -10.0, 10.0, 0.05, 1); + await camera.setProjectionMatrixWithCulling( + projectionMatrix, 0.05, 1); + await _capture(viewer, "camera_projection_culling_matrix_object_outside_frustum"); + }); }); group('background', () {