From cbff4cd8057843f550681b38f36603175aa8134a Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Thu, 20 Mar 2025 11:07:16 +0800 Subject: [PATCH] refactoring --- .../lib/src/filament/src/filament_app.dart | 8 +- .../lib/src/viewer/src/ffi/src/callbacks.dart | 4 +- .../viewer/src/ffi/src/ffi_filament_app.dart | 9 +++ .../src/ffi/src/thermion_viewer_ffi.dart | 52 +++---------- .../src/viewer/src/thermion_viewer_base.dart | 4 +- .../native/src/scene/GltfSceneAsset.cpp | 1 + thermion_dart/test/asset_tests.dart | 74 ++++++++++++++++--- thermion_dart/test/light_tests.dart | 40 +++------- 8 files changed, 108 insertions(+), 84 deletions(-) diff --git a/thermion_dart/lib/src/filament/src/filament_app.dart b/thermion_dart/lib/src/filament/src/filament_app.dart index 0ff24665..db57c45c 100644 --- a/thermion_dart/lib/src/filament/src/filament_app.dart +++ b/thermion_dart/lib/src/filament/src/filament_app.dart @@ -70,6 +70,11 @@ abstract class FilamentApp { /// Future destroy(); + /// + /// + /// + Future destroyAsset(covariant ThermionAsset asset); + /// /// /// @@ -227,7 +232,8 @@ abstract class FilamentApp { /// /// /// - Future capture(covariant View view, {bool captureRenderTarget = false}); + Future capture(covariant View view, + {bool captureRenderTarget = false}); /// /// diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/callbacks.dart b/thermion_dart/lib/src/viewer/src/ffi/src/callbacks.dart index 18a7ef77..ea169f42 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/callbacks.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/callbacks.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:ffi'; import 'package:ffi/ffi.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart'; export 'package:ffi/ffi.dart'; export 'dart:ffi'; export 'thermion_dart.g.dart'; @@ -18,8 +19,9 @@ Future withVoidCallback2(Function() func) async { void Function() callback = () { func.call(); completer.complete(); - }; + }; final nativeCallable = NativeCallable.listener(callback); + RenderLoop_addTask(nativeCallable.nativeFunction); await completer.future; nativeCallable.close(); } diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_filament_app.dart b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_filament_app.dart index f22c43bb..4a918dc1 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_filament_app.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_filament_app.dart @@ -3,6 +3,7 @@ import 'dart:typed_data'; import 'package:thermion_dart/src/filament/src/engine.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_material.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_render_target.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_swapchain.dart'; @@ -187,6 +188,14 @@ class FFIFilamentApp extends FilamentApp { Engine_destroy(engine); } + /// + /// + /// + Future destroyAsset(covariant FFIAsset asset) async { + await withVoidCallback( + (cb) => SceneAsset_destroyRenderThread(asset.asset, cb)); + } + /// /// /// 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 4565bb0f..54c94030 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 @@ -234,7 +234,7 @@ class ThermionViewerFFI extends ThermionViewer { } Pointer? indirectLight; - + Pointer? skybox; /// @@ -279,47 +279,13 @@ class ThermionViewerFFI extends ThermionViewer { @override Future removeIbl() async { if (indirectLight != null) { + Scene_setIndirectLight(scene.scene, nullptr); await withVoidCallback((cb) => Engine_destroyIndirectLightRenderThread( app.engine, indirectLight!, cb)); indirectLight = null; } } - @override - Future addLight( - LightType type, - double colour, - double intensity, - double posX, - double posY, - double posZ, - double dirX, - double dirY, - double dirZ, - {double falloffRadius = 1.0, - double spotLightConeInner = pi / 8, - double spotLightConeOuter = pi / 4, - double sunAngularRadius = 0.545, - double sunHaloSize = 10.0, - double sunHaloFallof = 80.0, - bool castShadows = true}) async { - DirectLight directLight = DirectLight( - type: type, - color: colour, - intensity: intensity, - position: Vector3(posX, posY, posZ), - direction: Vector3(dirX, dirY, dirZ)..normalize(), - falloffRadius: falloffRadius, - spotLightConeInner: spotLightConeInner, - spotLightConeOuter: spotLightConeOuter, - sunAngularRadius: sunAngularRadius, - sunHaloSize: sunHaloSize, - sunHaloFallof: sunHaloFallof, - castShadows: castShadows); - - return addDirectLight(directLight); - } - final _lights = {}; /// @@ -347,7 +313,7 @@ class ThermionViewerFFI extends ThermionViewer { // LightManager_setSunHaloFalloff(app.lightManager, entity, directLight.spotLightConeInner, directLight.spotLightConeOuter); LightManager_setShadowCaster( app.lightManager, entity, directLight.castShadows); - + Scene_addEntity(scene.scene, entity); _lights.add(entity); @@ -453,9 +419,7 @@ class ThermionViewerFFI extends ThermionViewer { @override Future destroyAsset(covariant FFIAsset asset) async { await scene.remove(asset); - - await withVoidCallback( - (cb) => SceneAsset_destroyRenderThread(asset.asset, cb)); + await FilamentApp.instance!.destroyAsset(asset); // if (asset.boundingBoxAsset != null) { // await asset.setBoundingBoxVisibility(false); @@ -790,4 +754,12 @@ class ThermionViewerFFI extends ThermionViewer { // gizmoEntities.toSet() // ..add(SceneAsset_getEntity(gizmo.cast()))); } + + Future addToScene(covariant FFIAsset asset) async { + await scene.add(asset); + } + + Future removeFromScene(covariant FFIAsset asset) async { + await scene.remove(asset); + } } diff --git a/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart b/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart index 932f2986..545b1b37 100644 --- a/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart +++ b/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart @@ -17,7 +17,6 @@ import 'dart:async'; /// using the methods directly via FilamentApp.instance; /// abstract class ThermionViewer { - Future get initialized; /// @@ -294,4 +293,7 @@ abstract class ThermionViewer { /// /// int getCameraCount(); + + Future addToScene(covariant ThermionAsset asset); + Future removeFromScene(covariant ThermionAsset asset); } diff --git a/thermion_dart/native/src/scene/GltfSceneAsset.cpp b/thermion_dart/native/src/scene/GltfSceneAsset.cpp index 5023001b..d78b360a 100644 --- a/thermion_dart/native/src/scene/GltfSceneAsset.cpp +++ b/thermion_dart/native/src/scene/GltfSceneAsset.cpp @@ -11,6 +11,7 @@ namespace thermion _instances.clear(); _asset->releaseSourceData(); _assetLoader->destroyAsset(_asset); + TRACE("Destroyed"); } SceneAsset *GltfSceneAsset::createInstance(MaterialInstance **materialInstances, size_t materialInstanceCount) diff --git a/thermion_dart/test/asset_tests.dart b/thermion_dart/test/asset_tests.dart index 3c8a8339..3dfb57d5 100644 --- a/thermion_dart/test/asset_tests.dart +++ b/thermion_dart/test/asset_tests.dart @@ -1,21 +1,73 @@ +@Timeout(const Duration(seconds: 600)) import 'package:test/test.dart'; +import 'package:vector_math/vector_math_64.dart'; import 'helpers.dart'; void main() async { - final testHelper = TestHelper("lights"); + final testHelper = TestHelper("assets"); + await testHelper.setup(); group("assets", () { - test('add/clear asset', () async { + // test('load/clear skybox', () async { + // await testHelper.withViewer((viewer) async { + // final camera = await viewer.getActiveCamera(); + // print(await camera.getModelMatrix()); + // print(await camera.getViewMatrix()); + // print(await camera.getProjectionMatrix()); + // await camera.lookAt(Vector3(0, 0, 10), + // focus: Vector3.zero(), up: Vector3(0, 1, 0)); + // await viewer.loadSkybox( + // "file://${testHelper.testDir}/assets/default_env_skybox.ktx"); + // await testHelper.capture(viewer.view, "load_skybox"); + // await viewer.removeSkybox(); + // await testHelper.capture(viewer.view, "remove_skybox"); + // }); + // }); + + test('load/remove ibl', () async { await testHelper.withViewer((viewer) async { - var asset = await viewer.loadGlb("file://${testHelper.testDir}/assets/cube.glb"); - await testHelper.capture(viewer, "asset_loaded"); - await viewer.destroyAssets(); - await viewer.destroyLights(); - await viewer.removeSkybox(); + var asset = await viewer + .loadGlb("file://${testHelper.testDir}/assets/cube.glb"); + await viewer + .loadIbl("file://${testHelper.testDir}/assets/default_env_ibl.ktx"); + await testHelper.capture(viewer.view, "ibl_loaded"); await viewer.removeIbl(); - await testHelper.capture(viewer, "assets_cleared"); - asset = await viewer.loadGlb("file://${testHelper.testDir}/assets/cube.glb"); - await testHelper.capture(viewer, "asset_reloaded"); - }, bg: kRed); + await testHelper.capture(viewer.view, "ibl_removed"); + }, cameraPosition: Vector3(0, 0, 5)); }); + + // test('add/remove asset from scene ', () async { + // await testHelper.withViewer((viewer) async { + // var asset = await viewer + // .loadGlb("file://${testHelper.testDir}/assets/cube.glb"); + // await viewer + // .loadIbl("file://${testHelper.testDir}/assets/default_env_ibl.ktx"); + // await testHelper.capture(viewer.view, "asset_added"); + // await viewer.removeFromScene(asset); + // await testHelper.capture(viewer.view, "asset_removed"); + // }, cameraPosition: Vector3(0, 0, 5)); + // }); + + // test('destroy assets', () async { + // await testHelper.withViewer((viewer) async { + // var asset = await viewer + // .loadGlb("file://${testHelper.testDir}/assets/cube.glb"); + // await viewer + // .loadIbl("file://${testHelper.testDir}/assets/default_env_ibl.ktx"); + // await testHelper.capture(viewer.view, "assets_present"); + // await viewer.destroyAssets(); + // await testHelper.capture(viewer.view, "assets_destroyed"); + // }, cameraPosition: Vector3(0, 0, 5)); + // }); + + + + + // await viewer.destroyLights(); + // await viewer.removeSkybox(); + // await viewer.removeIbl(); + + // asset = await viewer + // .loadGlb("file://${testHelper.testDir}/assets/cube.glb"); + // await testHelper.capture(viewer.view, "asset_reloaded"); }); } diff --git a/thermion_dart/test/light_tests.dart b/thermion_dart/test/light_tests.dart index 9b98fb30..1f55ee64 100644 --- a/thermion_dart/test/light_tests.dart +++ b/thermion_dart/test/light_tests.dart @@ -1,46 +1,26 @@ -import 'package:thermion_dart/thermion_dart.dart'; +import 'package:thermion_dart/src/filament/src/light_options.dart'; import 'package:test/test.dart'; -import 'package:vector_math/vector_math_64.dart'; import 'helpers.dart'; void main() async { final testHelper = TestHelper("lights"); + await testHelper.setup(); group("lights", () { - test('add/clear point lights', () async { + test('add/clear point light', () async { await testHelper.withViewer((viewer) async { await viewer.loadGlb("file://${testHelper.testDir}/assets/cube.glb"); var light = await viewer.addDirectLight( - DirectLight.point(intensity: 10000000000, falloffRadius: 10)); - await viewer.setLightPosition(light, 0, 10, 0); - await testHelper.capture(viewer, "add_point_light"); - await viewer.destroyLights(); - await testHelper.capture(viewer, "remove_lights"); + DirectLight.point(intensity: 1000000, falloffRadius: 10)); + await viewer.setLightPosition(light, 1, 2, 2); + await testHelper.capture(viewer.view, "add_point_light"); + await viewer.setLightPosition(light, -1, 2, 2); + await testHelper.capture(viewer.view, "move_point_light"); + await viewer.removeLight(light); + await testHelper.capture(viewer.view, "remove_point_light"); }); }); - test('add/remove IBL', () async { - await testHelper.withViewer((viewer) async { - await viewer.loadGlb("file://${testHelper.testDir}/assets/cube.glb"); - await viewer - .loadIbl("file://${testHelper.testDir}/assets/default_env_ibl.ktx"); - await testHelper.capture(viewer, "load_ibl"); - await viewer.removeIbl(); - await testHelper.capture(viewer, "remove_ibl"); - }); - }); - - test('add/remove skybox', () async { - await testHelper.withViewer((viewer) async { - await viewer.loadGlb("file://${testHelper.testDir}/assets/cube.glb"); - - await viewer - .loadSkybox("file://${testHelper.testDir}/assets/default_env_skybox.ktx"); - await testHelper.capture(viewer, "load_skybox"); - await viewer.removeSkybox(); - await testHelper.capture(viewer, "remove_skybox"); - }); - }); }); }