refactoring

This commit is contained in:
Nick Fisher
2025-03-20 11:07:16 +08:00
parent a8a2f14b34
commit cbff4cd805
8 changed files with 108 additions and 84 deletions

View File

@@ -70,6 +70,11 @@ abstract class FilamentApp<T> {
///
Future destroy();
///
///
///
Future destroyAsset(covariant ThermionAsset asset);
///
///
///
@@ -227,7 +232,8 @@ abstract class FilamentApp<T> {
///
///
///
Future<Uint8List> capture(covariant View view, {bool captureRenderTarget = false});
Future<Uint8List> capture(covariant View view,
{bool captureRenderTarget = false});
///
///

View File

@@ -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<void> withVoidCallback2(Function() func) async {
void Function() callback = () {
func.call();
completer.complete();
};
};
final nativeCallable = NativeCallable<Void Function()>.listener(callback);
RenderLoop_addTask(nativeCallable.nativeFunction);
await completer.future;
nativeCallable.close();
}

View File

@@ -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<Pointer> {
Engine_destroy(engine);
}
///
///
///
Future destroyAsset(covariant FFIAsset asset) async {
await withVoidCallback(
(cb) => SceneAsset_destroyRenderThread(asset.asset, cb));
}
///
///
///

View File

@@ -234,7 +234,7 @@ class ThermionViewerFFI extends ThermionViewer {
}
Pointer<TIndirectLight>? indirectLight;
Pointer<TSkybox>? 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<ThermionEntity> 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 = <ThermionEntity>{};
///
@@ -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<TSceneAsset>())));
}
Future addToScene(covariant FFIAsset asset) async {
await scene.add(asset);
}
Future removeFromScene(covariant FFIAsset asset) async {
await scene.remove(asset);
}
}

View File

@@ -17,7 +17,6 @@ import 'dart:async';
/// using the methods directly via FilamentApp.instance;
///
abstract class ThermionViewer {
Future<bool> get initialized;
///
@@ -294,4 +293,7 @@ abstract class ThermionViewer {
///
///
int getCameraCount();
Future addToScene(covariant ThermionAsset asset);
Future removeFromScene(covariant ThermionAsset asset);
}

View File

@@ -11,6 +11,7 @@ namespace thermion
_instances.clear();
_asset->releaseSourceData();
_assetLoader->destroyAsset(_asset);
TRACE("Destroyed");
}
SceneAsset *GltfSceneAsset::createInstance(MaterialInstance **materialInstances, size_t materialInstanceCount)

View File

@@ -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");
});
}

View File

@@ -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");
});
});
});
}