internal: store bounding box with SceneAsset rather than recalculating from renderables

This commit is contained in:
Nick Fisher
2025-01-07 12:02:44 +08:00
parent 124eed0264
commit 0e5253f7b3
12 changed files with 78 additions and 25 deletions

View File

@@ -4,9 +4,9 @@ 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/ffi_material.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';
import 'package:thermion_dart/thermion_dart.dart'; import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart' as v64;
class FFIAsset extends ThermionAsset { class FFIAsset extends ThermionAsset {
/// ///
/// ///
/// ///
@@ -236,16 +236,25 @@ class FFIAsset extends ThermionAsset {
FFIAsset? boundingBoxAsset; FFIAsset? boundingBoxAsset;
Future<Aabb3> getBoundingBox() async { Future<v64.Aabb3> getBoundingBox() async {
late ThermionEntity targetEntity; final entities = <ThermionEntity>[];
if (RenderableManager_isRenderable(renderableManager, entity)) { if (RenderableManager_isRenderable(renderableManager, entity)) {
targetEntity = entity; entities.add(entity);
} else { } else {
targetEntity = (await getChildEntities()).first; entities.addAll(await getChildEntities());
} }
final aabb3 =
SceneManager_getRenderableBoundingBox(sceneManager, targetEntity); var boundingBox = v64.Aabb3();
return 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 @override
Future<void> setBoundingBoxVisibility(bool visible) async { Future<void> setBoundingBoxVisibility(bool visible) async {
if (boundingBoxAsset == null) { if (boundingBoxAsset == null) {
final boundingBox = await getBoundingBox(); final boundingBox = await SceneAsset_getBoundingBox(pointer!);
final min = [ final min = [
boundingBox.centerX - boundingBox.halfExtentX, boundingBox.centerX - boundingBox.halfExtentX,
boundingBox.centerY - boundingBox.halfExtentY, boundingBox.centerY - boundingBox.halfExtentY,

View File

@@ -1718,7 +1718,7 @@ external void SceneManager_destroyLightsRenderThread(
); );
@ffi.Native< @ffi.Native<
EntityId Function( ffi.Void Function(
ffi.Pointer<TSceneManager>, ffi.Pointer<TSceneManager>,
ffi.Uint8, ffi.Uint8,
ffi.Float, ffi.Float,
@@ -1738,7 +1738,7 @@ external void SceneManager_destroyLightsRenderThread(
ffi.Bool, ffi.Bool,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>>)>( ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>>)>(
isLeaf: true) isLeaf: true)
external int SceneManager_addLightRenderThread( external void SceneManager_addLightRenderThread(
ffi.Pointer<TSceneManager> tSceneManager, ffi.Pointer<TSceneManager> tSceneManager,
int type, int type,
double colour, double colour,
@@ -2383,6 +2383,11 @@ external ffi.Pointer<TSceneAsset> SceneAsset_createInstance(
int materialInstanceCount, int materialInstanceCount,
); );
@ffi.Native<Aabb3 Function(ffi.Pointer<TSceneAsset>)>(isLeaf: true)
external Aabb3 SceneAsset_getBoundingBox(
ffi.Pointer<TSceneAsset> asset,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TAnimationManager>, EntityId)>( @ffi.Native<ffi.Void Function(ffi.Pointer<TAnimationManager>, EntityId)>(
isLeaf: true) isLeaf: true)
external void AnimationManager_addAnimationComponent( external void AnimationManager_addAnimationComponent(

View File

@@ -21,6 +21,7 @@ extern "C"
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_getInstance(TSceneAsset *tSceneAsset, int index); EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_getInstance(TSceneAsset *tSceneAsset, int index);
EMSCRIPTEN_KEEPALIVE size_t SceneAsset_getInstanceCount(TSceneAsset *tSceneAsset); EMSCRIPTEN_KEEPALIVE size_t SceneAsset_getInstanceCount(TSceneAsset *tSceneAsset);
EMSCRIPTEN_KEEPALIVE TSceneAsset * SceneAsset_createInstance(TSceneAsset *asset, TMaterialInstance **materialInstances, int materialInstanceCount); EMSCRIPTEN_KEEPALIVE TSceneAsset * SceneAsset_createInstance(TSceneAsset *asset, TMaterialInstance **materialInstances, int materialInstanceCount);
EMSCRIPTEN_KEEPALIVE Aabb3 SceneAsset_getBoundingBox(TSceneAsset *asset);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -122,6 +122,10 @@ namespace thermion
return Entity(); // not currently implemented return Entity(); // not currently implemented
} }
const filament::Aabb getBoundingBox() const override {
return _boundingBox;
}
static std::unique_ptr<GeometrySceneAsset> create( static std::unique_ptr<GeometrySceneAsset> create(
float *vertices, uint32_t numVertices, float *vertices, uint32_t numVertices,
float *normals, uint32_t numNormals, float *normals, uint32_t numNormals,
@@ -136,7 +140,7 @@ namespace thermion
VertexBuffer *_vertexBuffer = nullptr; VertexBuffer *_vertexBuffer = nullptr;
IndexBuffer *_indexBuffer = nullptr; IndexBuffer *_indexBuffer = nullptr;
std::vector<MaterialInstance*> _materialInstances; std::vector<MaterialInstance*> _materialInstances;
Box _boundingBox; Aabb _boundingBox;
GeometrySceneAsset *_instanceOwner = std::nullptr_t(); GeometrySceneAsset *_instanceOwner = std::nullptr_t();
utils::Entity _entity; utils::Entity _entity;
RenderableManager::PrimitiveType _primitiveType; RenderableManager::PrimitiveType _primitiveType;

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <utils/Entity.h> #include <utils/Entity.h>
#include <filament/Box.h>
#include <filament/Engine.h> #include <filament/Engine.h>
#include <filament/Material.h> #include <filament/Material.h>
#include <filament/MaterialInstance.h> #include <filament/MaterialInstance.h>
@@ -145,6 +146,10 @@ namespace thermion
math::mat4f getRotationForAxis(Gizmo::Axis axis); math::mat4f getRotationForAxis(Gizmo::Axis axis);
const filament::Aabb getBoundingBox() const override {
return _boundingBox;
}
private: private:
SceneAsset *_source; SceneAsset *_source;
Engine *_engine; Engine *_engine;
@@ -161,6 +166,8 @@ namespace thermion
std::vector<utils::Entity> _entities; std::vector<utils::Entity> _entities;
std::vector<MaterialInstance *> _materialInstances; std::vector<MaterialInstance *> _materialInstances;
filament::Aabb _boundingBox;
GizmoPickResultType getPickResult(utils::Entity entity) GizmoPickResultType getPickResult(utils::Entity entity)
{ {
if (entity.isNull()) if (entity.isNull())

View File

@@ -167,6 +167,10 @@ namespace thermion
return entities[0]; return entities[0];
} }
const filament::Aabb getBoundingBox() const override {
return _asset->getBoundingBox();
}
private: private:
gltfio::FilamentAsset *_asset; gltfio::FilamentAsset *_asset;
gltfio::AssetLoader *_assetLoader; gltfio::AssetLoader *_assetLoader;

View File

@@ -159,7 +159,9 @@ namespace thermion
} }
} }
const filament::Aabb getBoundingBox() const override {
return _instance->getBoundingBox();
}
private: private:
filament::Engine *_engine; filament::Engine *_engine;

View File

@@ -48,6 +48,10 @@ public:
const Entity* getChildEntities() override; const Entity* getChildEntities() override;
Entity findEntityByName(const char* name) override; Entity findEntityByName(const char* name) override;
const filament::Aabb getBoundingBox() const override {
return filament::Aabb();
}
private: private:
Engine& _engine; Engine& _engine;
utils::Entity _gridEntity; utils::Entity _gridEntity;

View File

@@ -2,10 +2,12 @@
#include <memory> #include <memory>
#include <utils/Entity.h>
#include <gltfio/FilamentAsset.h>
#include <filament/Scene.h> #include <filament/Scene.h>
#include <gltfio/FilamentAsset.h>
#include <math.h>
#include <utils/Entity.h>
#include "CustomGeometry.hpp" #include "CustomGeometry.hpp"
#include "Log.hpp" #include "Log.hpp"
@@ -51,6 +53,8 @@ class SceneAsset {
virtual void setPriority(RenderableManager& rm, int mask) = 0; virtual void setPriority(RenderableManager& rm, int mask) = 0;
virtual void setLayer(RenderableManager& rm, int layer) = 0; virtual void setLayer(RenderableManager& rm, int layer) = 0;
virtual const filament::Aabb getBoundingBox() const = 0;
}; };

View File

@@ -101,6 +101,12 @@ extern "C"
return reinterpret_cast<TSceneAsset *>(instance); return reinterpret_cast<TSceneAsset *>(instance);
} }
EMSCRIPTEN_KEEPALIVE Aabb3 SceneAsset_getBoundingBox(TSceneAsset *tSceneAsset) {
auto *asset = reinterpret_cast<SceneAsset*>(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 #ifdef __cplusplus
} }

View File

@@ -31,7 +31,6 @@ namespace thermion
_vertexBuffer(vertexBuffer), _vertexBuffer(vertexBuffer),
_indexBuffer(indexBuffer), _indexBuffer(indexBuffer),
_primitiveType(primitiveType), _primitiveType(primitiveType),
_boundingBox(boundingBox),
_instanceOwner(instanceOwner) _instanceOwner(instanceOwner)
{ {
_materialInstances.insert(_materialInstances.begin(), materialInstances, materialInstances + materialInstanceCount); _materialInstances.insert(_materialInstances.begin(), materialInstances, materialInstances + materialInstanceCount);
@@ -39,11 +38,15 @@ namespace thermion
_entity = utils::EntityManager::get().create(); _entity = utils::EntityManager::get().create();
RenderableManager::Builder builder(1); RenderableManager::Builder builder(1);
builder.boundingBox(_boundingBox) builder.boundingBox(boundingBox)
.geometry(0, _primitiveType, _vertexBuffer, _indexBuffer) .geometry(0, _primitiveType, _vertexBuffer, _indexBuffer)
.culling(true) .culling(true)
.receiveShadows(true) .receiveShadows(true)
.castShadows(true); .castShadows(true);
_boundingBox.min = boundingBox.getMin();
_boundingBox.max = boundingBox.getMax();
for (int i = 0; i < materialInstanceCount; i++) for (int i = 0; i < materialInstanceCount; i++)
{ {
builder.material(i, materialInstances[i]); builder.material(i, materialInstances[i]);
@@ -83,7 +86,7 @@ namespace thermion
materialInstances, materialInstances,
materialInstanceCount, materialInstanceCount,
_primitiveType, _primitiveType,
_boundingBox, filament::Box().set(_boundingBox.min, _boundingBox.max),
this); this);
auto *raw = instance.get(); auto *raw = instance.get();
_instances.push_back(std::move(instance)); _instances.push_back(std::move(instance));

View File

@@ -26,7 +26,10 @@ namespace thermion
} }
TRACE("Creating instance %d", instanceNumber); TRACE("Creating instance %d", instanceNumber);
auto instance = _asset->getAssetInstances()[instanceNumber]; auto instance = _asset->getAssetInstances()[instanceNumber];
instance->recomputeBoundingBoxes(); 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(); instance->getAnimator()->updateBoneMatrices();
auto& rm = _engine->getRenderableManager(); auto& rm = _engine->getRenderableManager();