diff --git a/thermion_dart/lib/src/bindings/src/thermion_dart_ffi.g.dart b/thermion_dart/lib/src/bindings/src/thermion_dart_ffi.g.dart index ae8360cd..a816ffcd 100644 --- a/thermion_dart/lib/src/bindings/src/thermion_dart_ffi.g.dart +++ b/thermion_dart/lib/src/bindings/src/thermion_dart_ffi.g.dart @@ -636,7 +636,6 @@ external bool Texture_loadImage( int level, ); - @ffi.Native< ffi.Bool Function( ffi.Pointer, @@ -651,7 +650,6 @@ external bool Texture_loadImage( ffi.Uint32, ffi.Uint32, ffi.Uint32, - ffi.Uint32, ffi.Uint32)>(isLeaf: true) external bool Texture_setImage( ffi.Pointer tEngine, @@ -664,7 +662,6 @@ external bool Texture_setImage( int z_offset, int width, int height, - int channels, int depth, int bufferFormat, int pixelDataType, @@ -1618,6 +1615,11 @@ external int EntityManager_createEntity( ffi.Pointer tEntityManager, ); +@ffi.Native)>(isLeaf: true) +external void Fence_waitAndDestroy( + ffi.Pointer tFence, +); + @ffi.Native(isLeaf: true) external void RenderThread_create(); @@ -1941,6 +1943,14 @@ external void Engine_createFenceRenderThread( onComplete, ); +@ffi.Native, ffi.Uint32, VoidCallback)>( + isLeaf: true) +external void Fence_waitAndDestroyRenderThread( + ffi.Pointer tFence, + int requestId, + VoidCallback onComplete, +); + @ffi.Native< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Uint32, VoidCallback)>(isLeaf: true) @@ -2507,7 +2517,6 @@ external void Texture_loadImageRenderThread( ffi.Pointer> onComplete, ); - @ffi.Native< ffi.Void Function( ffi.Pointer, @@ -2945,6 +2954,17 @@ external bool GltfResourceLoader_loadResources( ffi.Pointer tFilamentAsset, ); +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Double, ffi.Double, ffi.Double, + ffi.Double)>(isLeaf: true) +external void Skybox_setColor( + ffi.Pointer tSkybox, + double r, + double g, + double b, + double a, +); + @ffi.Native< ffi.Bool Function(ffi.Pointer, EntityId, ffi.Int, ffi.Pointer)>(isLeaf: true) diff --git a/thermion_dart/lib/src/bindings/src/thermion_dart_js_interop.g.dart b/thermion_dart/lib/src/bindings/src/thermion_dart_js_interop.g.dart index 65c3205e..c0d5a554 100644 --- a/thermion_dart/lib/src/bindings/src/thermion_dart_js_interop.g.dart +++ b/thermion_dart/lib/src/bindings/src/thermion_dart_js_interop.g.dart @@ -1956,6 +1956,13 @@ extension type NativeLibrary(JSObject _) implements JSObject { Pointer tGltfResourceLoader, Pointer tFilamentAsset, ); + external void _Skybox_setColor( + Pointer tSkybox, + double r, + double g, + double b, + double a, + ); external int _RenderableManager_setMaterialInstanceAt( Pointer tRenderableManager, EntityId entityId, @@ -5509,6 +5516,17 @@ bool GltfResourceLoader_loadResources( return result == 1; } +void Skybox_setColor( + self.Pointer tSkybox, + double r, + double g, + double b, + double a, +) { + final result = _lib._Skybox_setColor(tSkybox.cast(), r, g, b, a); + return result; +} + bool RenderableManager_setMaterialInstanceAt( self.Pointer tRenderableManager, DartEntityId entityId, diff --git a/thermion_dart/lib/src/filament/src/implementation/ffi_filament_app.dart b/thermion_dart/lib/src/filament/src/implementation/ffi_filament_app.dart index d9474c45..f51c0bfc 100644 --- a/thermion_dart/lib/src/filament/src/implementation/ffi_filament_app.dart +++ b/thermion_dart/lib/src/filament/src/implementation/ffi_filament_app.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:thermion_dart/src/filament/src/implementation/ffi_camera.dart'; +import 'package:thermion_dart/src/filament/src/implementation/ffi_skybox.dart'; import 'package:thermion_dart/src/filament/src/interface/scene.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_asset.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_gizmo.dart'; @@ -10,6 +11,7 @@ import 'package:thermion_dart/src/filament/src/implementation/ffi_scene.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_swapchain.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_texture.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_view.dart'; +import 'package:thermion_dart/src/filament/src/interface/skybox.dart'; import 'package:thermion_dart/src/utils/src/matrix.dart'; import 'package:thermion_dart/thermion_dart.dart'; import 'package:logging/logging.dart'; @@ -1207,5 +1209,17 @@ class FFIFilamentApp extends FilamentApp { Vector3(bb.halfExtentX, bb.halfExtentY, bb.halfExtentZ)); } - + /// Builds an (empty) [Skybox] instance. This will not be attached to any scene until + /// [setSkybox] is called. + /// + Future buildSkybox({Texture? texture = null}) async { + final ptr = await withPointerCallback((cb) { + Engine_buildSkyboxRenderThread( + engine, + (texture as FFITexture?)?.pointer ?? nullptr, + cb, + ); + }); + return FFISkybox(ptr); + } } diff --git a/thermion_dart/lib/src/filament/src/implementation/ffi_scene.dart b/thermion_dart/lib/src/filament/src/implementation/ffi_scene.dart index e5b14153..88055f4c 100644 --- a/thermion_dart/lib/src/filament/src/implementation/ffi_scene.dart +++ b/thermion_dart/lib/src/filament/src/implementation/ffi_scene.dart @@ -1,6 +1,8 @@ import 'package:thermion_dart/src/filament/src/implementation/ffi_asset.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_indirect_light.dart'; +import 'package:thermion_dart/src/filament/src/implementation/ffi_skybox.dart'; import 'package:thermion_dart/src/filament/src/interface/scene.dart'; +import 'package:thermion_dart/src/filament/src/interface/skybox.dart'; import 'package:thermion_dart/thermion_dart.dart'; import 'package:logging/logging.dart'; @@ -153,4 +155,11 @@ class FFIScene extends Scene { Future getIndirectLight() async { return _indirectLight; } + + /// + /// + /// + Future setSkybox(Skybox skybox) async { + Scene_setSkybox(scene, (skybox as FFISkybox).pointer); + } } diff --git a/thermion_dart/lib/src/filament/src/implementation/ffi_skybox.dart b/thermion_dart/lib/src/filament/src/implementation/ffi_skybox.dart new file mode 100644 index 00000000..97d3291a --- /dev/null +++ b/thermion_dart/lib/src/filament/src/implementation/ffi_skybox.dart @@ -0,0 +1,26 @@ +import 'package:thermion_dart/src/filament/src/implementation/ffi_filament_app.dart'; +import 'package:thermion_dart/src/filament/src/interface/skybox.dart'; +import 'package:thermion_dart/thermion_dart.dart'; + +class FFISkybox extends Skybox { + final Pointer pointer; + + FFISkybox(this.pointer); + + @override + Future setColor(double r, double g, double b, double a) async { + Skybox_setColor(pointer, r, g, b, a); + } + + @override + Future destroy() async { + await withVoidCallback( + (requestId, cb) => Engine_destroySkyboxRenderThread( + (FilamentApp.instance as FFIFilamentApp).engine, + pointer, + requestId, + cb, + ), + ); + } +} diff --git a/thermion_dart/lib/src/filament/src/interface/filament_app.dart b/thermion_dart/lib/src/filament/src/interface/filament_app.dart index 45452d14..3e0f37ac 100644 --- a/thermion_dart/lib/src/filament/src/interface/filament_app.dart +++ b/thermion_dart/lib/src/filament/src/interface/filament_app.dart @@ -1,4 +1,5 @@ import 'package:thermion_dart/src/filament/src/interface/scene.dart'; +import 'package:thermion_dart/src/filament/src/interface/skybox.dart'; import 'package:thermion_dart/thermion_dart.dart'; class FilamentConfig { @@ -344,19 +345,23 @@ abstract class FilamentApp { Future getWorldTransform(ThermionEntity entity); /// Sets the render priority for [entity]. - /// [priority] should be be between 0 and 7, with 0 meaning highest priority + /// [priority] should be be between 0 and 7, with 0 meaning highest priority /// (rendered first) and 7 meaning lowest priority (rendered last). /// Future setPriority(ThermionEntity entity, int priority); - /// Gets the number of primitives for [entity] (which is assumed to be + /// Gets the number of primitives for [entity] (which is assumed to be /// have a renderable component attached) /// Future getPrimitiveCount(ThermionEntity entity); - /// Gets the bounding box for [entity] (which is assumed to be + /// Gets the bounding box for [entity] (which is assumed to be /// have a renderable component attached). /// Future getBoundingBox(ThermionEntity entity); + /// Builds a [Skybox] instance. This will not be attached to any scene until + /// [setSkybox] is called. + /// + Future buildSkybox({Texture? texture = null}); } diff --git a/thermion_dart/lib/src/filament/src/interface/scene.dart b/thermion_dart/lib/src/filament/src/interface/scene.dart index 04e3ed27..35319632 100644 --- a/thermion_dart/lib/src/filament/src/interface/scene.dart +++ b/thermion_dart/lib/src/filament/src/interface/scene.dart @@ -1,3 +1,4 @@ +import 'package:thermion_dart/src/filament/src/interface/skybox.dart'; import 'package:thermion_dart/thermion_dart.dart'; abstract class Scene { @@ -49,4 +50,11 @@ abstract class Scene { Future getIndirectLight() { throw UnimplementedError(); } + + /// + /// + /// + Future setSkybox(Skybox skybox) { + throw UnimplementedError(); + } } diff --git a/thermion_dart/lib/src/filament/src/interface/skybox.dart b/thermion_dart/lib/src/filament/src/interface/skybox.dart new file mode 100644 index 00000000..a59ed9d5 --- /dev/null +++ b/thermion_dart/lib/src/filament/src/interface/skybox.dart @@ -0,0 +1,11 @@ +abstract class Skybox { + /// + /// + /// + Future setColor(double r, double g, double b, double a); + + /// + /// + /// + Future destroy(); +} diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart index 147b2e8e..54d040ff 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:thermion_dart/src/filament/src/implementation/background_image.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_indirect_light.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_ktx1_bundle.dart'; +import 'package:thermion_dart/src/filament/src/implementation/ffi_skybox.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_swapchain.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_texture.dart'; import '../../../../filament/src/implementation/ffi_asset.dart'; @@ -229,13 +230,10 @@ class ThermionViewerFFI extends ThermionViewer { /// @override Future setBackgroundColor(double r, double g, double b, double a) async { - // we don't want to use the Renderer clearColor, because this only applies - // to clearing the swapchain. Even if this Viewer is rendered into the - // swapchain, we don't necessarily (?) want to set the clear color, - // because that will affect other views. - // We therefore use the background image as the color; - _backgroundImage ??= await BackgroundImage.create(this, scene); - await _backgroundImage!.setBackgroundColor(r, g, b, a); + await removeSkybox(); + _skybox = await FilamentApp.instance!.buildSkybox() as FFISkybox; + await scene.setSkybox(_skybox!); + await _skybox!.setColor(r, g, b, a); } /// @@ -252,7 +250,7 @@ class ThermionViewerFFI extends ThermionViewer { Future? _skyboxTextureUploadComplete; FFITexture? _skyboxTexture; - Pointer? _skybox; + FFISkybox? _skybox; /// /// @@ -271,10 +269,11 @@ class ThermionViewerFFI extends ThermionViewer { _skyboxTexture = await bundle.createTexture() as FFITexture; - _skybox = await withPointerCallback((cb) { - Engine_buildSkyboxRenderThread(app.engine, _skyboxTexture!.pointer, cb); - }); - Scene_setSkybox(scene.scene, _skybox!); + _skybox = await FilamentApp.instance!.buildSkybox(texture: _skyboxTexture) + as FFISkybox; + + await scene.setSkybox(_skybox!); + completer.complete(); }).then((_) async { _skyboxTextureUploadComplete = null; @@ -364,16 +363,7 @@ class ThermionViewerFFI extends ThermionViewer { _skyboxTextureUploadComplete = null; } - if (_skybox != null) { - await withVoidCallback( - (requestId, cb) => Engine_destroySkyboxRenderThread( - app.engine, - _skybox!, - requestId, - cb, - ), - ); - } + await _skybox?.destroy(); _skybox = null; _skyboxTexture = null; } diff --git a/thermion_dart/native/include/c_api/TSkybox.h b/thermion_dart/native/include/c_api/TSkybox.h new file mode 100644 index 00000000..cf68c2c8 --- /dev/null +++ b/thermion_dart/native/include/c_api/TSkybox.h @@ -0,0 +1,16 @@ +#pragma once + +#include "APIExport.h" +#include "APIBoundaryTypes.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +EMSCRIPTEN_KEEPALIVE void Skybox_setColor(TSkybox* tSkybox, double r, double g, double b, double a); + +#ifdef __cplusplus +} +#endif + diff --git a/thermion_dart/native/src/c_api/TSkybox.cpp b/thermion_dart/native/src/c_api/TSkybox.cpp new file mode 100644 index 00000000..0847eeab --- /dev/null +++ b/thermion_dart/native/src/c_api/TSkybox.cpp @@ -0,0 +1,30 @@ +#ifdef __EMSCRIPTEN__ +#include +#endif + +#include "c_api/TSkybox.h" + +#include +#include + +#include "Log.hpp" + +#ifdef __cplusplus +namespace thermion +{ + extern "C" + { + using namespace filament; +#endif + + EMSCRIPTEN_KEEPALIVE void Skybox_setColor(TSkybox *tSkybox, double r, double g, double b, double a) + { + auto *skybox = reinterpret_cast(tSkybox); + skybox->setColor(filament::math::float4 { static_cast(r), static_cast(g), static_cast(b), static_cast(a) } ); + } + + +#ifdef __cplusplus + } +} +#endif