diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_asset.dart b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_asset.dart index 4e71f0ed..041df325 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_asset.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_asset.dart @@ -4,40 +4,40 @@ import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_material.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart'; import 'package:thermion_dart/thermion_dart.dart'; +import 'package:vector_math/vector_math_64.dart' as v64; class FFIAsset extends ThermionAsset { - /// /// /// final Pointer pointer; - + /// /// /// final Pointer sceneManager; - + /// /// /// Pointer get renderableManager => Engine_getRenderableManager(engine); - + /// /// /// final Pointer engine; - + /// /// /// FFIAsset? _highlight; - + /// /// /// final Pointer _unlitMaterialProvider; - + /// /// /// @@ -47,7 +47,7 @@ class FFIAsset extends ThermionAsset { /// /// late final ThermionEntity entity; - + /// /// /// @@ -236,16 +236,25 @@ class FFIAsset extends ThermionAsset { FFIAsset? boundingBoxAsset; - Future getBoundingBox() async { - late ThermionEntity targetEntity; + Future getBoundingBox() async { + final entities = []; if (RenderableManager_isRenderable(renderableManager, entity)) { - targetEntity = entity; + entities.add(entity); } else { - targetEntity = (await getChildEntities()).first; + entities.addAll(await getChildEntities()); } - final aabb3 = - SceneManager_getRenderableBoundingBox(sceneManager, targetEntity); - return aabb3; + + var boundingBox = v64.Aabb3(); + + for (final entity in entities) { + final aabb3 = SceneManager_getRenderableBoundingBox(sceneManager, entity); + final entityBB = v64.Aabb3.centerAndHalfExtents( + v64.Vector3(aabb3.centerX, aabb3.centerY, aabb3.centerZ), + v64.Vector3(aabb3.halfExtentX, aabb3.halfExtentY, aabb3.halfExtentZ), + ); + boundingBox.hull(entityBB); + } + return boundingBox; } /// @@ -254,7 +263,8 @@ class FFIAsset extends ThermionAsset { @override Future setBoundingBoxVisibility(bool visible) async { if (boundingBoxAsset == null) { - final boundingBox = await getBoundingBox(); + final boundingBox = await SceneAsset_getBoundingBox(pointer!); + final min = [ boundingBox.centerX - boundingBox.halfExtentX, boundingBox.centerY - boundingBox.halfExtentY, 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 73a7dfbc..5b49e076 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 @@ -1718,7 +1718,7 @@ external void SceneManager_destroyLightsRenderThread( ); @ffi.Native< - EntityId Function( + ffi.Void Function( ffi.Pointer, ffi.Uint8, ffi.Float, @@ -1738,7 +1738,7 @@ external void SceneManager_destroyLightsRenderThread( ffi.Bool, ffi.Pointer>)>( isLeaf: true) -external int SceneManager_addLightRenderThread( +external void SceneManager_addLightRenderThread( ffi.Pointer tSceneManager, int type, double colour, @@ -2383,6 +2383,11 @@ external ffi.Pointer SceneAsset_createInstance( int materialInstanceCount, ); +@ffi.Native)>(isLeaf: true) +external Aabb3 SceneAsset_getBoundingBox( + ffi.Pointer asset, +); + @ffi.Native, EntityId)>( isLeaf: true) external void AnimationManager_addAnimationComponent( diff --git a/thermion_dart/native/include/c_api/TSceneAsset.h b/thermion_dart/native/include/c_api/TSceneAsset.h index d6e33d3f..f51e91ff 100644 --- a/thermion_dart/native/include/c_api/TSceneAsset.h +++ b/thermion_dart/native/include/c_api/TSceneAsset.h @@ -21,6 +21,7 @@ extern "C" EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_getInstance(TSceneAsset *tSceneAsset, int index); EMSCRIPTEN_KEEPALIVE size_t SceneAsset_getInstanceCount(TSceneAsset *tSceneAsset); EMSCRIPTEN_KEEPALIVE TSceneAsset * SceneAsset_createInstance(TSceneAsset *asset, TMaterialInstance **materialInstances, int materialInstanceCount); + EMSCRIPTEN_KEEPALIVE Aabb3 SceneAsset_getBoundingBox(TSceneAsset *asset); #ifdef __cplusplus } diff --git a/thermion_dart/native/include/scene/GeometrySceneAsset.hpp b/thermion_dart/native/include/scene/GeometrySceneAsset.hpp index 1cd85181..02d42a8e 100644 --- a/thermion_dart/native/include/scene/GeometrySceneAsset.hpp +++ b/thermion_dart/native/include/scene/GeometrySceneAsset.hpp @@ -122,6 +122,10 @@ namespace thermion return Entity(); // not currently implemented } + const filament::Aabb getBoundingBox() const override { + return _boundingBox; + } + static std::unique_ptr create( float *vertices, uint32_t numVertices, float *normals, uint32_t numNormals, @@ -136,7 +140,7 @@ namespace thermion VertexBuffer *_vertexBuffer = nullptr; IndexBuffer *_indexBuffer = nullptr; std::vector _materialInstances; - Box _boundingBox; + Aabb _boundingBox; GeometrySceneAsset *_instanceOwner = std::nullptr_t(); utils::Entity _entity; RenderableManager::PrimitiveType _primitiveType; diff --git a/thermion_dart/native/include/scene/Gizmo.hpp b/thermion_dart/native/include/scene/Gizmo.hpp index abf99c7f..2c229b44 100644 --- a/thermion_dart/native/include/scene/Gizmo.hpp +++ b/thermion_dart/native/include/scene/Gizmo.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -145,6 +146,10 @@ namespace thermion math::mat4f getRotationForAxis(Gizmo::Axis axis); + const filament::Aabb getBoundingBox() const override { + return _boundingBox; + } + private: SceneAsset *_source; Engine *_engine; @@ -161,6 +166,8 @@ namespace thermion std::vector _entities; std::vector _materialInstances; + filament::Aabb _boundingBox; + GizmoPickResultType getPickResult(utils::Entity entity) { if (entity.isNull()) diff --git a/thermion_dart/native/include/scene/GltfSceneAsset.hpp b/thermion_dart/native/include/scene/GltfSceneAsset.hpp index 947c3d34..17f684e5 100644 --- a/thermion_dart/native/include/scene/GltfSceneAsset.hpp +++ b/thermion_dart/native/include/scene/GltfSceneAsset.hpp @@ -167,6 +167,10 @@ namespace thermion return entities[0]; } + const filament::Aabb getBoundingBox() const override { + return _asset->getBoundingBox(); + } + private: gltfio::FilamentAsset *_asset; gltfio::AssetLoader *_assetLoader; diff --git a/thermion_dart/native/include/scene/GltfSceneAssetInstance.hpp b/thermion_dart/native/include/scene/GltfSceneAssetInstance.hpp index 36b527af..78157e73 100644 --- a/thermion_dart/native/include/scene/GltfSceneAssetInstance.hpp +++ b/thermion_dart/native/include/scene/GltfSceneAssetInstance.hpp @@ -159,7 +159,9 @@ namespace thermion } } - + const filament::Aabb getBoundingBox() const override { + return _instance->getBoundingBox(); + } private: filament::Engine *_engine; diff --git a/thermion_dart/native/include/scene/GridOverlay.hpp b/thermion_dart/native/include/scene/GridOverlay.hpp index b51cd813..da070d4e 100644 --- a/thermion_dart/native/include/scene/GridOverlay.hpp +++ b/thermion_dart/native/include/scene/GridOverlay.hpp @@ -48,6 +48,10 @@ public: const Entity* getChildEntities() override; Entity findEntityByName(const char* name) override; + const filament::Aabb getBoundingBox() const override { + return filament::Aabb(); + } + private: Engine& _engine; utils::Entity _gridEntity; diff --git a/thermion_dart/native/include/scene/SceneAsset.hpp b/thermion_dart/native/include/scene/SceneAsset.hpp index 418cc002..3f8822b5 100644 --- a/thermion_dart/native/include/scene/SceneAsset.hpp +++ b/thermion_dart/native/include/scene/SceneAsset.hpp @@ -2,10 +2,12 @@ #include -#include -#include #include +#include +#include +#include + #include "CustomGeometry.hpp" #include "Log.hpp" @@ -51,6 +53,8 @@ class SceneAsset { virtual void setPriority(RenderableManager& rm, int mask) = 0; virtual void setLayer(RenderableManager& rm, int layer) = 0; + virtual const filament::Aabb getBoundingBox() const = 0; + }; diff --git a/thermion_dart/native/src/c_api/TSceneAsset.cpp b/thermion_dart/native/src/c_api/TSceneAsset.cpp index e018baef..0fee7ec0 100644 --- a/thermion_dart/native/src/c_api/TSceneAsset.cpp +++ b/thermion_dart/native/src/c_api/TSceneAsset.cpp @@ -101,6 +101,12 @@ extern "C" return reinterpret_cast(instance); } + EMSCRIPTEN_KEEPALIVE Aabb3 SceneAsset_getBoundingBox(TSceneAsset *tSceneAsset) { + auto *asset = reinterpret_cast(tSceneAsset); + auto box = asset->getBoundingBox(); + return Aabb3{box.center().x, box.center().y, box.center().z, box.extent().x, box.extent().y, box.extent().z}; + } + #ifdef __cplusplus } diff --git a/thermion_dart/native/src/scene/GeometrySceneAsset.cpp b/thermion_dart/native/src/scene/GeometrySceneAsset.cpp index d8a75d06..c4dd7b7c 100644 --- a/thermion_dart/native/src/scene/GeometrySceneAsset.cpp +++ b/thermion_dart/native/src/scene/GeometrySceneAsset.cpp @@ -31,7 +31,6 @@ namespace thermion _vertexBuffer(vertexBuffer), _indexBuffer(indexBuffer), _primitiveType(primitiveType), - _boundingBox(boundingBox), _instanceOwner(instanceOwner) { _materialInstances.insert(_materialInstances.begin(), materialInstances, materialInstances + materialInstanceCount); @@ -39,11 +38,15 @@ namespace thermion _entity = utils::EntityManager::get().create(); RenderableManager::Builder builder(1); - builder.boundingBox(_boundingBox) + builder.boundingBox(boundingBox) .geometry(0, _primitiveType, _vertexBuffer, _indexBuffer) .culling(true) .receiveShadows(true) .castShadows(true); + + _boundingBox.min = boundingBox.getMin(); + _boundingBox.max = boundingBox.getMax(); + for (int i = 0; i < materialInstanceCount; i++) { builder.material(i, materialInstances[i]); @@ -83,7 +86,7 @@ namespace thermion materialInstances, materialInstanceCount, _primitiveType, - _boundingBox, + filament::Box().set(_boundingBox.min, _boundingBox.max), this); auto *raw = instance.get(); _instances.push_back(std::move(instance)); diff --git a/thermion_dart/native/src/scene/GltfSceneAsset.cpp b/thermion_dart/native/src/scene/GltfSceneAsset.cpp index 33127738..5023001b 100644 --- a/thermion_dart/native/src/scene/GltfSceneAsset.cpp +++ b/thermion_dart/native/src/scene/GltfSceneAsset.cpp @@ -26,7 +26,10 @@ namespace thermion } TRACE("Creating instance %d", instanceNumber); auto instance = _asset->getAssetInstances()[instanceNumber]; + instance->recomputeBoundingBoxes(); + auto bb = instance->getBoundingBox(); + TRACE("Instance bounding box center (%f,%f,%f), extent (%f,%f,%f)", bb.center().x, bb.center().y, bb.center().z, bb.extent().x,bb.extent().y,bb.extent().z); instance->getAnimator()->updateBoneMatrices(); auto& rm = _engine->getRenderableManager();