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 01afe50b..e7b5c5b2 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 @@ -83,8 +83,15 @@ class ThermionViewerFFI extends ThermionViewer { this._sharedContext = sharedContext ?? nullptr; _onPickResultCallable = NativeCallable< - Void Function(EntityId entityId, Int x, Int y, - Pointer view, Float depth, Float fragX, Float fragY, Float fragZ)>.listener(_onPickResult); + Void Function( + EntityId entityId, + Int x, + Int y, + Pointer view, + Float depth, + Float fragX, + Float fragY, + Float fragZ)>.listener(_onPickResult); _initialize(); } @@ -300,7 +307,7 @@ class ThermionViewerFFI extends ThermionViewer { return; } _disposing = true; - + await setRendering(false); await clearEntities(); await clearLights(); @@ -1509,17 +1516,38 @@ class ThermionViewerFFI extends ThermionViewer { } void _onPickResult( - ThermionEntity entityId, int x, int y, Pointer viewPtr, double depth, double fragX, double fragY, double fragZ) async { + ThermionEntity entityId, + int x, + int y, + Pointer viewPtr, + double depth, + double fragX, + double fragY, + double fragZ) async { final view = FFIView(viewPtr, _viewer!); final viewport = await view.getViewport(); - _pickResultController - .add((entity: entityId, x: x, y: (viewport.height - y), depth: depth, fragX: fragX, fragY: viewport.height - fragY, fragZ: fragZ )); + _pickResultController.add(( + entity: entityId, + x: x, + y: (viewport.height - y), + depth: depth, + fragX: fragX, + fragY: viewport.height - fragY, + fragZ: fragZ + )); } late NativeCallable< - Void Function(EntityId entityId, Int x, Int y, Pointer view, Float depth, Float fragX, Float fragY, Float fragZ)> - _onPickResultCallable; + Void Function( + EntityId entityId, + Int x, + Int y, + Pointer view, + Float depth, + Float fragX, + Float fragY, + Float fragZ)> _onPickResultCallable; /// /// @@ -1750,6 +1778,7 @@ class ThermionViewerFFI extends ThermionViewer { throw Exception("Viewer must not be null"); } + var entity = await withIntCallback((callback) => SceneManager_createGeometryRenderThread( _sceneManager!, @@ -1835,6 +1864,18 @@ class ThermionViewerFFI extends ThermionViewer { set_priority(_sceneManager!, entityId, priority); } + /// + /// + /// + @override + Future getRenderableBoundingBox(ThermionEntity entityId) async { + final result = + SceneManager_getRenderableBoundingBox(_sceneManager!, entityId); + return v64.Aabb3.centerAndHalfExtents( + Vector3(result.centerX, result.centerY, result.centerZ), + Vector3(result.halfExtentX, result.halfExtentY, result.halfExtentZ)); + } + /// /// /// @@ -2051,9 +2092,11 @@ class ThermionViewerFFI extends ThermionViewer { /// /// /// - Future createUnlitFixedSizeMaterialInstance() async { + Future + createUnlitFixedSizeMaterialInstance() async { var instance = await withPointerCallback((cb) { - SceneManager_createUnlitFixedSizeMaterialInstanceRenderThread(_sceneManager!, cb); + SceneManager_createUnlitFixedSizeMaterialInstanceRenderThread( + _sceneManager!, cb); }); if (instance == nullptr) { throw Exception("Failed to create material instance"); @@ -2205,6 +2248,12 @@ class ThermionFFIMaterialInstance extends MaterialInstance { MaterialInstance_setDepthWrite(this._pointer, enabled); } + @override + Future setParameterFloat4(String name, double x, double y, double z, double w) async { + MaterialInstance_setParameterFloat4( + _pointer, name.toNativeUtf8().cast(), x, y, z, w); + } + @override Future setParameterFloat2(String name, double x, double y) async { MaterialInstance_setParameterFloat2( @@ -2216,6 +2265,14 @@ class ThermionFFIMaterialInstance extends MaterialInstance { MaterialInstance_setParameterFloat( _pointer, name.toNativeUtf8().cast(), value); } + + @override + Future setParameterInt(String name, int value) async { + MaterialInstance_setParameterInt( + _pointer, name.toNativeUtf8().cast(), value); + } + + } class FFIRenderTarget extends RenderTarget { diff --git a/thermion_dart/lib/src/viewer/src/shared_types/material.dart b/thermion_dart/lib/src/viewer/src/shared_types/material.dart index 0f58907b..efd2455e 100644 --- a/thermion_dart/lib/src/viewer/src/shared_types/material.dart +++ b/thermion_dart/lib/src/viewer/src/shared_types/material.dart @@ -1,8 +1,11 @@ abstract class MaterialInstance { Future setDepthWriteEnabled(bool enabled); + Future setDepthCullingEnabled(bool enabled); + Future setParameterFloat4(String name, double x, double y, double z, double w); Future setParameterFloat2(String name, double x, double y); Future setParameterFloat(String name, double x); + Future setParameterInt(String name, int value); } enum AlphaMode { OPAQUE, MASK, BLEND } 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 6fd1a27c..f1490f0b 100644 --- a/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart +++ b/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart @@ -790,6 +790,11 @@ abstract class ThermionViewer { /// void onDispose(Future Function() callback); + /// + /// Gets the 3D axis aligned bounding box for the given entity. + /// + Future getRenderableBoundingBox(ThermionEntity entity); + /// /// Gets the 2D bounding box (in viewport coordinates) for the given entity. /// diff --git a/thermion_dart/test/geometry_tests.dart b/thermion_dart/test/geometry_tests.dart index baa4c172..ee2b7707 100644 --- a/thermion_dart/test/geometry_tests.dart +++ b/thermion_dart/test/geometry_tests.dart @@ -20,10 +20,13 @@ void main() async { await viewer .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8)); await viewer.setBackgroundColor(1.0, 1.0, 1.0, 1.0); - await viewer + final cube = await viewer .createGeometry(GeometryHelper.cube(normals: false, uvs: false)); await testHelper.capture(viewer, "geometry_cube_no_uv_no_normal"); + await viewer.removeEntity(cube); + await testHelper.capture(viewer, "geometry_cube_removed"); + await viewer.dispose(); }); test('create cube (no normals)', () async { @@ -179,5 +182,16 @@ void main() async { .createGeometry(GeometryHelper.sphere(normals: false, uvs: false)); await testHelper.capture(viewer, "geometry_sphere_no_normals"); }); + + test('create geometry instance', () async { + var viewer = await testHelper.createViewer( + cameraPosition: Vector3(0, 0, 6), bg: kRed); + final cube = await viewer + .createGeometry(GeometryHelper.sphere(normals: false, uvs: false)); + await viewer.setTransform(cube, Matrix4.translation(Vector3(2, 1, 1))); + final cube2 = await viewer.createInstance(cube); + await viewer.setTransform(cube2, Matrix4.translation(Vector3(-2, 1, 1))); + await testHelper.capture(viewer, "geometry_instance"); + }); }); } diff --git a/thermion_dart/test/material_tests.dart b/thermion_dart/test/material_tests.dart index ffc49a0f..fa95d051 100644 --- a/thermion_dart/test/material_tests.dart +++ b/thermion_dart/test/material_tests.dart @@ -23,8 +23,10 @@ void main() async { var cube = await viewer.createGeometry(GeometryHelper.cube(), materialInstance: materialInstance); - await viewer.setMaterialPropertyFloat4( - cube, "baseColorFactor", 0, 0.0, 1.0, 0.0, 1.0); + await materialInstance.setParameterFloat4( + "baseColorFactor", 0.0, 1.0, 0.0, 1.0); + await materialInstance.setParameterInt( + "baseColorIndex", -1); await testHelper.capture(viewer, "unlit_material_base_color");