refactoring

This commit is contained in:
Nick Fisher
2025-03-19 18:45:42 +08:00
parent 6744c02019
commit a310498c5a
7 changed files with 193 additions and 345 deletions

View File

@@ -14,41 +14,54 @@ class BackgroundImage extends ThermionAsset {
ThermionEntity get entity => asset.entity;
Texture? _backgroundImageTexture;
Texture? texture;
FFITextureSampler? _imageSampler;
FFITextureSampler? sampler;
final MaterialInstance mi;
final FFIScene scene;
BackgroundImage._(
this.asset, this.scene, this._backgroundImageTexture, this._imageSampler);
this.asset, this.scene, this.texture, this.sampler, this.mi);
Future destroy() async {
Scene_removeEntity(scene.scene, entity);
await _backgroundImageTexture!.dispose();
await _imageSampler!.dispose();
await texture!.dispose();
await sampler!.dispose();
await mi.destroy();
}
static Future<BackgroundImage> create(
ThermionViewer viewer, FFIScene scene, Uint8List imageData) async {
final image = await FilamentApp.instance!.decodeImage(imageData);
var backgroundImageTexture = await FilamentApp.instance!
.createTexture(await image.getWidth(), await image.getHeight());
var imageSampler =
await FilamentApp.instance!.createTextureSampler() as FFITextureSampler;
ThermionViewer viewer, FFIScene scene) async {
var imageMaterialInstance =
await FilamentApp.instance!.createImageMaterialInstance();
await imageMaterialInstance.setParameterTexture(
"image", backgroundImageTexture as FFITexture, imageSampler);
var backgroundImage =
await viewer.createGeometry(GeometryHelper.fullscreenQuad());
backgroundImage.setMaterialInstanceAt(imageMaterialInstance);
await scene.add(backgroundImage as FFIAsset);
return BackgroundImage._(
backgroundImage, scene, backgroundImageTexture, imageSampler);
backgroundImage, scene, null, null, imageMaterialInstance);
}
Future setBackgroundColor(double r, double g, double b, double a) async {
await mi.setParameterFloat4("backgroundColor", r, g, b, a);
}
Future setImage(Uint8List imageData) async {
final image = await FilamentApp.instance!.decodeImage(imageData);
texture ??= await FilamentApp.instance!
.createTexture(await image.getWidth(), await image.getHeight());
sampler ??=
await FilamentApp.instance!.createTextureSampler() as FFITextureSampler;
await mi.setParameterTexture(
"image", texture as FFITexture, sampler as FFITextureSampler);
}
///
@@ -263,7 +276,7 @@ class BackgroundImage extends ThermionAsset {
}
@override
Future setTransform(Matrix4 transform, { ThermionEntity? entity }) {
Future setTransform(Matrix4 transform, {ThermionEntity? entity}) {
// TODO: implement setTransform
throw UnimplementedError();
}

View File

@@ -541,10 +541,52 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
///
@override
Future<MaterialInstance> createImageMaterialInstance() async {
_imageMaterial ??= FFIMaterial(Material_createImageMaterial(engine),
FilamentApp.instance! as FFIFilamentApp);
if (_imageMaterial == null) {
var ptr = await withPointerCallback<TMaterial>(
(cb) => Material_createImageMaterialRenderThread(engine, cb));
_imageMaterial =
FFIMaterial(ptr, FilamentApp.instance! as FFIFilamentApp);
}
var instance =
await _imageMaterial!.createInstance() as FFIMaterialInstance;
return instance;
}
///
///
///
Future<Uint8List> capture(covariant FFIView view) async {
final viewport = await view.getViewport();
final swapChain = _viewMappings[view];
final out = Uint8List(viewport.width * viewport.height * 4);
await withBoolCallback((cb) {
Renderer_beginFrameRenderThread(renderer, swapChain!.swapChain, 0, cb);
});
await withVoidCallback((cb) {
Renderer_readPixelsRenderThread(
renderer,
view.view,
view.renderTarget?.renderTarget ?? nullptr,
TPixelDataFormat.PIXELDATAFORMAT_RGBA,
TPixelDataType.PIXELDATATYPE_UBYTE,
out.address,
cb,
);
});
await withVoidCallback((cb) {
Renderer_endFrameRenderThread(renderer, cb);
});
await withVoidCallback((cb) {
Engine_flushAndWaitRenderThead(engine, cb);
});
return out;
}
///
///
///
Future setClearColor(double r, double g, double b, double a) async {
Renderer_setClearOptions(renderer, r, g, b, a, 0, true, false);
}
}

View File

@@ -1907,6 +1907,19 @@ external void Material_createInstanceRenderThread(
onComplete,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TEngine>,
ffi.Pointer<
ffi
.NativeFunction<ffi.Void Function(ffi.Pointer<TMaterial>)>>)>(
isLeaf: true)
external void Material_createImageMaterialRenderThread(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TMaterial>)>>
onComplete,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TView>, ffi.Pointer<TEngine>, ffi.UnsignedInt)>(
@@ -1952,280 +1965,38 @@ external FilamentRenderCallback make_render_callback_fn_pointer(
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
ffi.Pointer<TMaterial>,
ffi.Pointer<
ffi
.NativeFunction<ffi.Void Function(ffi.Pointer<TSceneAsset>)>>)>(
isLeaf: true)
external void SceneManager_createGridRenderThread(
ffi.Pointer<TSceneManager> tSceneManager,
ffi.Pointer<TMaterial> tMaterial,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TSceneAsset>)>>
callback,
);
@ffi.Native<
ffi.Pointer<TGizmo> Function(
ffi.Pointer<TSceneManager>,
ffi.Pointer<TView>,
ffi.Pointer<TScene>,
ffi.UnsignedInt,
ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TGizmo>)>>)>(
symbol: "SceneManager_createGizmoRenderThread", isLeaf: true)
external ffi.Pointer<TGizmo> _SceneManager_createGizmoRenderThread(
ffi.Pointer<TSceneManager> tSceneManager,
ffi.Pointer<TView> tView,
ffi.Pointer<TScene> tScene,
int tGizmoType,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TGizmo>)>>
onComplete,
);
ffi.Pointer<TGizmo> SceneManager_createGizmoRenderThread(
ffi.Pointer<TSceneManager> tSceneManager,
ffi.Pointer<TView> tView,
ffi.Pointer<TScene> tScene,
TGizmoType tGizmoType,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TGizmo>)>>
onComplete,
) =>
_SceneManager_createGizmoRenderThread(
tSceneManager,
tView,
tScene,
tGizmoType.value,
onComplete,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
ffi.Pointer<ffi.Float>,
ffi.Int,
ffi.Pointer<ffi.Float>,
ffi.Int,
ffi.Pointer<ffi.Float>,
ffi.Int,
ffi.Pointer<ffi.Uint16>,
ffi.Int,
ffi.Int,
ffi.Pointer<ffi.Pointer<TMaterialInstance>>,
ffi.Int,
ffi.Bool,
ffi.Pointer<
ffi
.NativeFunction<ffi.Void Function(ffi.Pointer<TSceneAsset>)>>)>(
isLeaf: true)
external void SceneManager_createGeometryRenderThread(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<ffi.Float> vertices,
int numVertices,
ffi.Pointer<ffi.Float> normals,
int numNormals,
ffi.Pointer<ffi.Float> uvs,
int numUvs,
ffi.Pointer<ffi.Uint16> indices,
int numIndices,
int primitiveType,
ffi.Pointer<ffi.Pointer<TMaterialInstance>> materialInstances,
int materialInstanceCount,
bool keepData,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TSceneAsset>)>>
callback,
ffi.Void Function(ffi.Pointer<TSceneAsset>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void SceneAsset_destroyRenderThread(
ffi.Pointer<TSceneAsset> tSceneAsset,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
ffi.Pointer<TGltfAssetLoader>,
ffi.Pointer<TGltfResourceLoader>,
ffi.Pointer<TEngine>,
ffi.Pointer<TNameComponentManager>,
ffi.Pointer<ffi.Uint8>,
ffi.Size,
ffi.Int,
ffi.Bool,
ffi.Int,
ffi.Int,
ffi.Bool,
ffi.Size,
ffi.Pointer<
ffi
.NativeFunction<ffi.Void Function(ffi.Pointer<TSceneAsset>)>>)>(
isLeaf: true)
external void SceneManager_loadGlbFromBufferRenderThread(
ffi.Pointer<TSceneManager> sceneManager,
external void SceneAsset_loadGlbRenderThread(
ffi.Pointer<TGltfAssetLoader> tAssetLoader,
ffi.Pointer<TGltfResourceLoader> tResourceLoader,
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TNameComponentManager> tNameComponentManager,
ffi.Pointer<ffi.Uint8> data,
int length,
int numInstances,
bool keepData,
int priority,
int layer,
bool loadResourcesAsync,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TSceneAsset>)>>
callback,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(
ffi.Pointer<TMaterialInstance>)>>)>(isLeaf: true)
external void SceneManager_createUnlitMaterialInstanceRenderThread(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TMaterialInstance>)>>
callback,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(
ffi.Pointer<TMaterialInstance>)>>)>(isLeaf: true)
external void SceneManager_createUnlitFixedSizeMaterialInstanceRenderThread(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TMaterialInstance>)>>
callback,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
ffi.Pointer<ffi.Char>,
ffi.Int,
ffi.Bool,
ffi.Pointer<
ffi
.NativeFunction<ffi.Void Function(ffi.Pointer<TSceneAsset>)>>)>(
isLeaf: true)
external void SceneManager_loadGlbRenderThread(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<ffi.Char> assetPath,
int numInstances,
bool keepData,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TSceneAsset>)>>
callback,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.Char>,
ffi.Bool,
ffi.Pointer<
ffi
.NativeFunction<ffi.Void Function(ffi.Pointer<TSceneAsset>)>>)>(
isLeaf: true)
external void SceneManager_loadGltfRenderThread(
ffi.Pointer<TSceneManager> sceneManager,
ffi.Pointer<ffi.Char> assetPath,
ffi.Pointer<ffi.Char> relativePath,
bool keepData,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TSceneAsset>)>>
callback,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TSceneManager>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void SceneManager_destroyAllRenderThread(
ffi.Pointer<TSceneManager> tSceneManager,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TSceneManager>, ffi.Pointer<TSceneAsset>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void SceneManager_destroyAssetRenderThread(
ffi.Pointer<TSceneManager> tSceneManager,
ffi.Pointer<TSceneAsset> sceneAsset,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TSceneManager>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void SceneManager_destroyAssetsRenderThread(
ffi.Pointer<TSceneManager> tSceneManager,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TSceneManager>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void SceneManager_destroyLightsRenderThread(
ffi.Pointer<TSceneManager> tSceneManager,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
ffi.Uint8,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Bool,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>>)>(
isLeaf: true)
external void SceneManager_addLightRenderThread(
ffi.Pointer<TSceneManager> tSceneManager,
int type,
double colour,
double intensity,
double posX,
double posY,
double posZ,
double dirX,
double dirY,
double dirZ,
double falloffRadius,
double spotLightConeInner,
double spotLightConeOuter,
double sunAngularRadius,
double sunHaloSize,
double sunHaloFallof,
bool shadows,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>> callback,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TSceneManager>, EntityId,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void SceneManager_removeLightRenderThread(
ffi.Pointer<TSceneManager> tSceneManager,
int entityId,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TCamera>)>>)>(
isLeaf: true)
external void SceneManager_createCameraRenderThread(
ffi.Pointer<TSceneManager> tSceneManager,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TCamera>)>>
callback,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneAsset>,

View File

@@ -129,7 +129,8 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future render() async {
await withVoidCallback((cb) => RenderTicker_renderRenderThread(app.renderTicker, 0, cb));
await withVoidCallback(
(cb) => RenderTicker_renderRenderThread(app.renderTicker, 0, cb));
}
double _msPerFrame = 1000.0 / 60.0;
@@ -191,7 +192,8 @@ class ThermionViewerFFI extends ThermionViewer {
@override
Future setBackgroundImage(String path, {bool fillHeight = false}) async {
final imageData = await loadAsset(path);
_backgroundImage = await BackgroundImage.create(this, scene, imageData);
_backgroundImage ??= await BackgroundImage.create(this, scene);
await _backgroundImage!.setImage(imageData);
}
///
@@ -199,7 +201,13 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future setBackgroundColor(double r, double g, double b, double a) async {
throw UnimplementedError();
// we don't want to use the Renderer clearColor, because this only applies
// to clearing the swapchain. Even if this Viewer is rendered into the
// swapchain, we don't necessarily (?) want to set the clear color,
// because that will affect other views.
// We therefore use the background image as the color;
_backgroundImage ??= await BackgroundImage.create(this, scene);
await _backgroundImage!.setBackgroundColor(r, g, b, a);
}
///
@@ -318,8 +326,8 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future<ThermionEntity> addDirectLight(DirectLight directLight) async {
var entity = LightManager_createLight(app.engine,
app.lightManager, TLightType.values[directLight.type.index]);
var entity = LightManager_createLight(app.engine, app.lightManager,
TLightType.values[directLight.type.index]);
if (entity == FILAMENT_ASSET_ERROR) {
throw Exception("Failed to add light to scene");
}
@@ -391,14 +399,16 @@ class ThermionViewerFFI extends ThermionViewer {
int priority = 4,
int layer = 0,
bool loadResourcesAsync = false}) async {
var asset = SceneAsset_loadGlb(
app.gltfAssetLoader,
app.gltfResourceLoader,
app.engine,
app.nameComponentManager,
data.address,
data.length,
numInstances);
var asset = await withPointerCallback<TSceneAsset>((cb) =>
SceneAsset_loadGlbRenderThread(
app.gltfAssetLoader,
app.gltfResourceLoader,
app.engine,
app.nameComponentManager,
data.address,
data.length,
numInstances,
cb));
if (asset == nullptr) {
throw Exception("An error occurred loading the asset");
@@ -440,7 +450,9 @@ class ThermionViewerFFI extends ThermionViewer {
@override
Future destroyAsset(covariant FFIAsset asset) async {
await scene.remove(asset);
SceneAsset_destroy(asset.asset);
await withVoidCallback((cb) => SceneAsset_destroyRenderThread(asset.asset, cb));
// if (asset.boundingBoxAsset != null) {
// await asset.setBoundingBoxVisibility(false);
// await withVoidCallback((callback) =>
@@ -466,7 +478,7 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future setToneMapping(ToneMapper mapper) async {
view.setToneMapper(mapper);
await view.setToneMapper(mapper);
}
///
@@ -774,4 +786,5 @@ class ThermionViewerFFI extends ThermionViewer {
// gizmoEntities.toSet()
// ..add(SceneAsset_getEntity(gizmo.cast<TSceneAsset>())));
}
}