From 4355d9c83fb89334bac6dafce0230e86f138788b Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Thu, 26 Sep 2024 16:51:14 +0800 Subject: [PATCH] more camera work --- thermion_dart/ffigen/native.yaml | 2 +- .../src/viewer/src/ffi/src/camera_ffi.dart | 12 ++++++++++- .../viewer/src/ffi/src/thermion_dart.g.dart | 13 ++++++++++++ .../src/ffi/src/thermion_viewer_ffi.dart | 19 ++++++++++++++++++ .../src/viewer/src/thermion_viewer_base.dart | 11 ++++++++++ .../src/viewer/src/thermion_viewer_stub.dart | 12 +++++++++++ thermion_dart/lib/src/viewer/viewer.dart | 2 +- thermion_dart/native/include/SceneManager.hpp | 8 +++++++- .../native/include/ThermionDartApi.h | 2 ++ thermion_dart/native/src/FilamentViewer.cpp | 3 ++- thermion_dart/native/src/SceneManager.cpp | 20 +++++++++++++++++-- thermion_dart/native/src/ThermionDartApi.cpp | 10 ++++++++++ thermion_dart/test/camera_tests.dart | 7 ++++++- thermion_dart/test/helpers.dart | 2 +- 14 files changed, 114 insertions(+), 9 deletions(-) diff --git a/thermion_dart/ffigen/native.yaml b/thermion_dart/ffigen/native.yaml index f95f8bd6..97d42410 100644 --- a/thermion_dart/ffigen/native.yaml +++ b/thermion_dart/ffigen/native.yaml @@ -1,4 +1,4 @@ -output: '../lib/thermion_dart/viewer/ffi/src/thermion_dart.g.dart' +output: '../lib/src/viewer/src/ffi/src/thermion_dart.g.dart' headers: entry-points: - '../native/include/ThermionDartRenderThreadApi.h' diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/camera_ffi.dart b/thermion_dart/lib/src/viewer/src/ffi/src/camera_ffi.dart index ef727d2d..457c5615 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/camera_ffi.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/camera_ffi.dart @@ -3,11 +3,11 @@ import 'dart:ffi'; import 'package:vector_math/vector_math_64.dart'; import '../../../../utils/matrix.dart'; -import '../../shared_types/camera.dart'; import '../../thermion_viewer_base.dart'; import 'thermion_dart.g.dart'; class ThermionFFICamera extends Camera { + final Pointer camera; final Pointer engine; late ThermionEntity _entity; @@ -51,4 +51,14 @@ class ThermionFFICamera extends Camera { Future setModelMatrix(Matrix4 matrix) async { Camera_setModelMatrix(camera, matrix4ToDouble4x4(matrix)); } + + @override + bool operator ==(Object other) => + identical(this, other) || + other is ThermionFFICamera && + runtimeType == other.runtimeType && + camera == other.camera; + + @override + int get hashCode => camera.hashCode; } diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart index e7b30929..6429cd52 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart @@ -970,6 +970,19 @@ external void SceneManager_setCamera( ffi.Pointer camera, ); +@ffi.Native)>(isLeaf: true) +external int SceneManager_getCameraCount( + ffi.Pointer sceneManager, +); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Size)>(isLeaf: true) +external ffi.Pointer SceneManager_getCameraAt( + ffi.Pointer sceneManager, + int index, +); + @ffi.Native< ffi.Int Function(ffi.Pointer, EntityId, ffi.Pointer)>(isLeaf: true) 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 d99c5c03..21daa4a6 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 @@ -2205,6 +2205,25 @@ class ThermionViewerFFI extends ThermionViewer { _hooks.remove(hook); } } + + /// + /// + /// + int getCameraCount() { + return SceneManager_getCameraCount(_sceneManager!); + } + + /// + /// Returns the camera specified by the given index. Note that the camera at + /// index 0 is always the main camera; this cannot be destroyed. + /// + Camera getCameraAt(int index) { + final camera = SceneManager_getCameraAt(_sceneManager!, index); + if (camera == nullptr) { + throw Exception("No camera at index $index"); + } + return ThermionFFICamera(camera, Viewer_getEngine(_viewer!)); + } } class ThermionFFITexture extends ThermionTexture { 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 02b957d3..0e6ad543 100644 --- a/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart +++ b/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart @@ -979,4 +979,15 @@ abstract class ThermionViewer { /// /// Future unregisterRequestFrameHook(Future Function() hook); + + /// + /// + /// + int getCameraCount(); + + /// + /// Returns the camera specified by the given index. Note that the camera at + /// index 0 is always the main camera; this cannot be destroyed. + /// + Camera getCameraAt(int index); } diff --git a/thermion_dart/lib/src/viewer/src/thermion_viewer_stub.dart b/thermion_dart/lib/src/viewer/src/thermion_viewer_stub.dart index 8e52e3fc..e5376f6a 100644 --- a/thermion_dart/lib/src/viewer/src/thermion_viewer_stub.dart +++ b/thermion_dart/lib/src/viewer/src/thermion_viewer_stub.dart @@ -995,6 +995,18 @@ class ThermionViewerStub extends ThermionViewer { // TODO: implement unregisterRequestFrameHook throw UnimplementedError(); } + + @override + Camera getCameraAt(int index) { + // TODO: implement getCameraAt + throw UnimplementedError(); + } + + @override + int getCameraCount() { + // TODO: implement getCameraCount + throw UnimplementedError(); + } } diff --git a/thermion_dart/lib/src/viewer/viewer.dart b/thermion_dart/lib/src/viewer/viewer.dart index 60065e59..f5ede7db 100644 --- a/thermion_dart/lib/src/viewer/viewer.dart +++ b/thermion_dart/lib/src/viewer/viewer.dart @@ -1,7 +1,7 @@ library thermion_viewer; -export 'src/shared_types/shared_types.dart'; export 'src/thermion_viewer_base.dart'; export 'src/thermion_viewer_stub.dart' if (dart.library.io) 'src/ffi/thermion_viewer_ffi.dart' if (dart.library.js_interop) 'src/web_wasm/thermion_viewer_web_wasm.dart'; +export 'src/shared_types/shared_types.dart'; \ No newline at end of file diff --git a/thermion_dart/native/include/SceneManager.hpp b/thermion_dart/native/include/SceneManager.hpp index 7f4d79ae..0ad2a748 100644 --- a/thermion_dart/native/include/SceneManager.hpp +++ b/thermion_dart/native/include/SceneManager.hpp @@ -50,7 +50,8 @@ namespace thermion_filament const ResourceLoaderWrapperImpl *const loader, Engine *engine, Scene *scene, - const char *uberArchivePath); + const char *uberArchivePath, + Camera* mainCamera); ~SceneManager(); enum LAYERS { @@ -305,12 +306,17 @@ namespace thermion_filament void setCamera(Camera* camera); + size_t getCameraCount(); + + Camera* getCameraAt(size_t index); + private: gltfio::AssetLoader *_assetLoader = nullptr; const ResourceLoaderWrapperImpl *const _resourceLoaderWrapper; Engine *_engine = nullptr; Scene *_scene = nullptr; View* _view = nullptr; + Camera* _mainCamera; gltfio::MaterialProvider *_ubershaderProvider = nullptr; gltfio::MaterialProvider *_unlitMaterialProvider = nullptr; diff --git a/thermion_dart/native/include/ThermionDartApi.h b/thermion_dart/native/include/ThermionDartApi.h index 1ef8d712..7b47ed31 100644 --- a/thermion_dart/native/include/ThermionDartApi.h +++ b/thermion_dart/native/include/ThermionDartApi.h @@ -245,6 +245,8 @@ extern "C" EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_createCamera(TSceneManager *sceneManager); EMSCRIPTEN_KEEPALIVE void SceneManager_destroyCamera(TSceneManager *sceneManager, TCamera* camera); EMSCRIPTEN_KEEPALIVE void SceneManager_setCamera(TSceneManager *sceneManager, TCamera* camera); + EMSCRIPTEN_KEEPALIVE size_t SceneManager_getCameraCount(TSceneManager *sceneManager); + EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_getCameraAt(TSceneManager *sceneManager, size_t index); EMSCRIPTEN_KEEPALIVE int hide_mesh(TSceneManager *sceneManager, EntityId entity, const char *meshName); EMSCRIPTEN_KEEPALIVE int reveal_mesh(TSceneManager *sceneManager, EntityId entity, const char *meshName); EMSCRIPTEN_KEEPALIVE void set_post_processing(TViewer *viewer, bool enabled); diff --git a/thermion_dart/native/src/FilamentViewer.cpp b/thermion_dart/native/src/FilamentViewer.cpp index 98d886b8..3e8a423a 100644 --- a/thermion_dart/native/src/FilamentViewer.cpp +++ b/thermion_dart/native/src/FilamentViewer.cpp @@ -201,7 +201,8 @@ namespace thermion_filament _resourceLoaderWrapper, _engine, _scene, - uberArchivePath); + uberArchivePath, + _mainCamera); } void FilamentViewer::setAntiAliasing(bool msaa, bool fxaa, bool taa) diff --git a/thermion_dart/native/src/SceneManager.cpp b/thermion_dart/native/src/SceneManager.cpp index 9ccb0f6e..83c9e1e0 100644 --- a/thermion_dart/native/src/SceneManager.cpp +++ b/thermion_dart/native/src/SceneManager.cpp @@ -52,11 +52,13 @@ namespace thermion_filament const ResourceLoaderWrapperImpl *const resourceLoaderWrapper, Engine *engine, Scene *scene, - const char *uberArchivePath) + const char *uberArchivePath, + Camera *mainCamera) : _view(view), _resourceLoaderWrapper(resourceLoaderWrapper), _engine(engine), - _scene(scene) + _scene(scene), + _mainCamera(mainCamera) { _stbDecoder = createStbProvider(_engine); @@ -2662,6 +2664,20 @@ EntityId SceneManager::createGeometry( void SceneManager::setCamera(Camera* camera) { _view->setCamera(camera); } + + size_t SceneManager::getCameraCount() { + return _cameras.size() + 1; + } + + Camera* SceneManager::getCameraAt(size_t index) { + if(index == 0) { + return _mainCamera; + } + if(index - 1 > _cameras.size() - 1) { + return nullptr; + } + return _cameras[index-1]; + } } // namespace thermion_filament diff --git a/thermion_dart/native/src/ThermionDartApi.cpp b/thermion_dart/native/src/ThermionDartApi.cpp index 10c2b7f9..d24a2334 100644 --- a/thermion_dart/native/src/ThermionDartApi.cpp +++ b/thermion_dart/native/src/ThermionDartApi.cpp @@ -1119,4 +1119,14 @@ EMSCRIPTEN_KEEPALIVE void SceneManager_setCamera(TSceneManager* tSceneManager, T auto * camera = reinterpret_cast(tCamera); sceneManager->setCamera(camera); } + +EMSCRIPTEN_KEEPALIVE size_t SceneManager_getCameraCount(TSceneManager *tSceneManager) { + auto * sceneManager = reinterpret_cast(tSceneManager); + return sceneManager->getCameraCount(); +} +EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_getCameraAt(TSceneManager *tSceneManager, size_t index) { + auto * sceneManager = reinterpret_cast(tSceneManager); + auto * camera = sceneManager->getCameraAt(index); + return reinterpret_cast(camera); +} } diff --git a/thermion_dart/test/camera_tests.dart b/thermion_dart/test/camera_tests.dart index 7c78419c..75e340d9 100644 --- a/thermion_dart/test/camera_tests.dart +++ b/thermion_dart/test/camera_tests.dart @@ -128,7 +128,7 @@ void main() async { expect(modelMatrix.getColumn(3).w, 1.0); await viewer.setTransform(parent, Matrix4.translation(Vector3(0, 1, 0))); - modelMatrix = await viewer.getCameraModelMatrix(); + modelMatrix = await viewer.getCameraModelMatrix(); expect(modelMatrix.getColumn(3).x, 1.0); expect(modelMatrix.getColumn(3).y, 1.0); expect(modelMatrix.getColumn(3).z, 0.0); @@ -150,6 +150,11 @@ void main() async { final mainCamera = await viewer.getMainCamera(); await viewer.setActiveCamera(mainCamera); await testHelper.capture(viewer, "create_camera_back_to_main"); + + expect(viewer.getCameraCount(), 2); + expect(viewer.getCameraAt(0), await viewer.getMainCamera()); + expect(viewer.getCameraAt(1), newCamera); + await expectLater(() => viewer.getCameraAt(2), throwsA(isA())); }); }); } diff --git a/thermion_dart/test/helpers.dart b/thermion_dart/test/helpers.dart index f0ead246..056d34b4 100644 --- a/thermion_dart/test/helpers.dart +++ b/thermion_dart/test/helpers.dart @@ -72,7 +72,7 @@ class TestHelper { final packageUri = findPackageRoot('thermion_dart'); testDir = Directory("${packageUri.toFilePath()}/test").path; - var outDir = Directory("$testDir/output/${dir}"); + outDir = Directory("$testDir/output/${dir}"); // outDir.deleteSync(recursive: true); outDir.createSync(); }