feat: remove bounding box from SceneAsset and create renderable wireframe bounding box in ThermionAsset
This commit is contained in:
@@ -16,9 +16,10 @@ class FFIAsset extends ThermionAsset {
|
||||
final bool isInstance;
|
||||
|
||||
late final ThermionEntity entity;
|
||||
final ThermionViewer viewer;
|
||||
|
||||
FFIAsset(
|
||||
this.pointer, this.sceneManager, this.engine, this._unlitMaterialProvider,
|
||||
FFIAsset(this.pointer, this.sceneManager, this.engine,
|
||||
this._unlitMaterialProvider, this.viewer,
|
||||
{this.isInstance = false}) {
|
||||
entity = SceneAsset_getEntity(pointer);
|
||||
}
|
||||
@@ -41,7 +42,8 @@ class FFIAsset extends ThermionAsset {
|
||||
if (instance == nullptr) {
|
||||
throw Exception("No instance available at index $index");
|
||||
}
|
||||
return FFIAsset(instance, sceneManager, engine, _unlitMaterialProvider);
|
||||
return FFIAsset(
|
||||
instance, sceneManager, engine, _unlitMaterialProvider, viewer);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -71,7 +73,8 @@ class FFIAsset extends ThermionAsset {
|
||||
if (created == FILAMENT_ASSET_ERROR) {
|
||||
throw Exception("Failed to create instance");
|
||||
}
|
||||
return FFIAsset(created, sceneManager, engine, _unlitMaterialProvider);
|
||||
return FFIAsset(
|
||||
created, sceneManager, engine, _unlitMaterialProvider, viewer);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -90,7 +93,7 @@ class FFIAsset extends ThermionAsset {
|
||||
var count = await getInstanceCount();
|
||||
final result = List<ThermionAsset>.generate(count, (i) {
|
||||
return FFIAsset(SceneAsset_getInstance(pointer, i), sceneManager, engine,
|
||||
_unlitMaterialProvider);
|
||||
_unlitMaterialProvider, viewer);
|
||||
});
|
||||
|
||||
return result;
|
||||
@@ -184,4 +187,100 @@ class FFIAsset extends ThermionAsset {
|
||||
SceneManager_removeFromScene(sceneManager, child);
|
||||
}
|
||||
}
|
||||
|
||||
ThermionAsset? _boundingBoxAsset;
|
||||
|
||||
Aabb3 getBoundingBox() {
|
||||
final aabb3 = SceneManager_getRenderableBoundingBox(sceneManager, entity);
|
||||
return aabb3;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setBoundingBoxVisibility(bool visible) async {
|
||||
if (_boundingBoxAsset == null) {
|
||||
final boundingBox = await getBoundingBox();
|
||||
final min = [
|
||||
boundingBox.centerX - boundingBox.halfExtentX,
|
||||
boundingBox.centerY - boundingBox.halfExtentY,
|
||||
boundingBox.centerZ - boundingBox.halfExtentZ
|
||||
];
|
||||
final max = [
|
||||
boundingBox.centerX + boundingBox.halfExtentX,
|
||||
boundingBox.centerY + boundingBox.halfExtentY,
|
||||
boundingBox.centerZ + boundingBox.halfExtentZ
|
||||
];
|
||||
|
||||
// Create vertices for the bounding box wireframe
|
||||
// 8 vertices for a cube
|
||||
final vertices = Float32List(8 * 3);
|
||||
|
||||
// Bottom vertices
|
||||
vertices[0] = min[0];
|
||||
vertices[1] = min[1];
|
||||
vertices[2] = min[2]; // v0
|
||||
vertices[3] = max[0];
|
||||
vertices[4] = min[1];
|
||||
vertices[5] = min[2]; // v1
|
||||
vertices[6] = max[0];
|
||||
vertices[7] = min[1];
|
||||
vertices[8] = max[2]; // v2
|
||||
vertices[9] = min[0];
|
||||
vertices[10] = min[1];
|
||||
vertices[11] = max[2]; // v3
|
||||
|
||||
// Top vertices
|
||||
vertices[12] = min[0];
|
||||
vertices[13] = max[1];
|
||||
vertices[14] = min[2]; // v4
|
||||
vertices[15] = max[0];
|
||||
vertices[16] = max[1];
|
||||
vertices[17] = min[2]; // v5
|
||||
vertices[18] = max[0];
|
||||
vertices[19] = max[1];
|
||||
vertices[20] = max[2]; // v6
|
||||
vertices[21] = min[0];
|
||||
vertices[22] = max[1];
|
||||
vertices[23] = max[2]; // v7
|
||||
|
||||
// Indices for lines (24 indices for 12 lines)
|
||||
final indices = [
|
||||
// Bottom face
|
||||
0, 1, 1, 2, 2, 3, 3, 0,
|
||||
// Top face
|
||||
4, 5, 5, 6, 6, 7, 7, 4,
|
||||
// Vertical edges
|
||||
0, 4, 1, 5, 2, 6, 3, 7
|
||||
];
|
||||
|
||||
// Create unlit material instance for the wireframe
|
||||
final materialInstancePtr =
|
||||
await withPointerCallback<TMaterialInstance>((cb) {
|
||||
final key = Struct.create<TMaterialKey>();
|
||||
MaterialProvider_createMaterialInstanceRenderThread(
|
||||
_unlitMaterialProvider, key.address, cb);
|
||||
});
|
||||
|
||||
final material = FFIMaterialInstance(materialInstancePtr, sceneManager);
|
||||
await material.setParameterFloat4(
|
||||
"baseColorFactor", 1.0, 1.0, 0.0, 1.0); // Yellow wireframe
|
||||
|
||||
// Create geometry for the bounding box
|
||||
final geometry = Geometry(
|
||||
vertices,
|
||||
indices,
|
||||
primitiveType: PrimitiveType.LINES,
|
||||
);
|
||||
|
||||
_boundingBoxAsset = await viewer.createGeometry(
|
||||
geometry,
|
||||
materialInstances: [material],
|
||||
keepData: false,
|
||||
);
|
||||
}
|
||||
if (visible) {
|
||||
await _boundingBoxAsset!.addToScene();
|
||||
} else {
|
||||
await _boundingBoxAsset!.removeFromScene();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ class FFIGizmo extends FFIAsset implements GizmoAsset {
|
||||
super.sceneManager,
|
||||
super.renderableManager,
|
||||
super.unlitMaterialProvider,
|
||||
super.viewer,
|
||||
this.gizmoEntities) {
|
||||
_nativeCallback =
|
||||
NativeCallable<GizmoPickCallbackFunction>.listener(_onPickResult);
|
||||
|
||||
@@ -230,6 +230,22 @@ external void MaterialInstance_setStencilWriteMask(
|
||||
int mask,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Void Function(ffi.Pointer<TMaterialInstance>, ffi.UnsignedInt)>(
|
||||
symbol: "MaterialInstance_setTransparencyMode", isLeaf: true)
|
||||
external void _MaterialInstance_setTransparencyMode(
|
||||
ffi.Pointer<TMaterialInstance> materialInstance,
|
||||
int transparencyMode,
|
||||
);
|
||||
|
||||
void MaterialInstance_setTransparencyMode(
|
||||
ffi.Pointer<TMaterialInstance> materialInstance,
|
||||
TTransparencyMode transparencyMode,
|
||||
) =>
|
||||
_MaterialInstance_setTransparencyMode(
|
||||
materialInstance,
|
||||
transparencyMode.value,
|
||||
);
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Pointer<TViewer> Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
|
||||
ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Char>)>(isLeaf: true)
|
||||
@@ -741,6 +757,12 @@ external void View_setFrustumCullingEnabled(
|
||||
bool enabled,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Pointer<TRenderTarget> Function(ffi.Pointer<TView>)>(
|
||||
isLeaf: true)
|
||||
external ffi.Pointer<TRenderTarget> View_getRenderTarget(
|
||||
ffi.Pointer<TView> tView,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Bool)>(isLeaf: true)
|
||||
external void View_setPostProcessing(
|
||||
ffi.Pointer<TView> tView,
|
||||
@@ -1310,6 +1332,15 @@ external void Viewer_createRenderTargetRenderThread(
|
||||
onComplete,
|
||||
);
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Void Function(ffi.Pointer<TViewer>, ffi.Pointer<TRenderTarget>,
|
||||
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
|
||||
external void Viewer_destroyRenderTargetRenderThread(
|
||||
ffi.Pointer<TViewer> viewer,
|
||||
ffi.Pointer<TRenderTarget> tRenderTarget,
|
||||
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
|
||||
);
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Void Function(
|
||||
ffi.Pointer<TEngine>,
|
||||
@@ -2730,6 +2761,30 @@ enum TCullingMode {
|
||||
};
|
||||
}
|
||||
|
||||
enum TTransparencyMode {
|
||||
/// ! the transparent object is drawn honoring the raster state
|
||||
DEFAULT(0),
|
||||
|
||||
/// the transparent object is first drawn in the depth buffer,
|
||||
/// then in the color buffer, honoring the culling mode, but ignoring the depth test function
|
||||
TWO_PASSES_ONE_SIDE(1),
|
||||
|
||||
/// the transparent object is drawn twice in the color buffer,
|
||||
/// first with back faces only, then with front faces; the culling
|
||||
/// mode is ignored. Can be combined with two-sided lighting
|
||||
TWO_PASSES_TWO_SIDES(2);
|
||||
|
||||
final int value;
|
||||
const TTransparencyMode(this.value);
|
||||
|
||||
static TTransparencyMode fromValue(int value) => switch (value) {
|
||||
0 => DEFAULT,
|
||||
1 => TWO_PASSES_ONE_SIDE,
|
||||
2 => TWO_PASSES_TWO_SIDES,
|
||||
_ => throw ArgumentError("Unknown value for TTransparencyMode: $value"),
|
||||
};
|
||||
}
|
||||
|
||||
typedef EntityId = ffi.Int32;
|
||||
typedef DartEntityId = int;
|
||||
|
||||
|
||||
@@ -511,7 +511,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
}
|
||||
|
||||
var thermionAsset =
|
||||
FFIAsset(asset, _sceneManager!, _engine!, _unlitMaterialProvider!);
|
||||
FFIAsset(asset, _sceneManager!, _engine!, _unlitMaterialProvider!, this);
|
||||
|
||||
return thermionAsset;
|
||||
}
|
||||
@@ -551,7 +551,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
throw Exception("An error occurred loading GLB from buffer");
|
||||
}
|
||||
return FFIAsset(
|
||||
assetPtr, _sceneManager!, _engine!, _unlitMaterialProvider!);
|
||||
assetPtr, _sceneManager!, _engine!, _unlitMaterialProvider!, this);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -573,7 +573,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
}
|
||||
|
||||
return FFIAsset(
|
||||
assetPtr, _sceneManager!, _engine!, _unlitMaterialProvider!);
|
||||
assetPtr, _sceneManager!, _engine!, _unlitMaterialProvider!, this);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -1642,7 +1642,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
}
|
||||
|
||||
var asset =
|
||||
FFIAsset(assetPtr, _sceneManager!, _engine!, _unlitMaterialProvider!);
|
||||
FFIAsset(assetPtr, _sceneManager!, _engine!, _unlitMaterialProvider!, this);
|
||||
|
||||
return asset;
|
||||
}
|
||||
@@ -1760,7 +1760,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
_sceneManager!, material.pointer, cb);
|
||||
}
|
||||
});
|
||||
_grid = FFIAsset(ptr, _sceneManager!, _engine!, _unlitMaterialProvider!);
|
||||
_grid = FFIAsset(ptr, _sceneManager!, _engine!, _unlitMaterialProvider!, this);
|
||||
}
|
||||
await _grid!.addToScene();
|
||||
await setLayerVisibility(VisibilityLayers.OVERLAY, true);
|
||||
@@ -2093,6 +2093,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
_sceneManager!,
|
||||
_engine!,
|
||||
nullptr,
|
||||
this,
|
||||
gizmoEntities.toSet()
|
||||
..add(SceneAsset_getEntity(gizmo.cast<TSceneAsset>())));
|
||||
}
|
||||
|
||||
@@ -12,9 +12,8 @@ export 'light_options.dart';
|
||||
typedef ThermionEntity = int;
|
||||
|
||||
abstract class ThermionAsset {
|
||||
|
||||
ThermionEntity get entity;
|
||||
|
||||
|
||||
Future<List<ThermionEntity>> getChildEntities();
|
||||
|
||||
///
|
||||
@@ -28,6 +27,11 @@ abstract class ThermionAsset {
|
||||
///
|
||||
Future removeStencilHighlight();
|
||||
|
||||
///
|
||||
/// When visible is [true], renders the bounding box.
|
||||
///
|
||||
Future setBoundingBoxVisibility(bool visible);
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user