refactoring

This commit is contained in:
Nick Fisher
2025-03-20 18:48:04 +08:00
parent cbff4cd805
commit e6bdcb687a
16 changed files with 780 additions and 541 deletions

View File

@@ -5,6 +5,11 @@ enum Projection { Perspective, Orthographic }
abstract class Camera {
Future<Vector3> getPosition() async {
final modelMatrix = await getModelMatrix();
return modelMatrix.getTranslation();
}
Future lookAt(Vector3 position, {Vector3? focus, Vector3? up}) async {
focus ??= Vector3.zero();
up ??= Vector3(0, 1, 0);

View File

@@ -6,7 +6,7 @@ class FilamentConfig<T, U> {
final Backend backend;
final T? renderCallback;
final U? renderCallbackOwner;
final U resourceLoader;
final Future<Uint8List> Function(String) resourceLoader;
final U? platform;
final U? driver;
final U? sharedContext;
@@ -32,7 +32,6 @@ abstract class FilamentApp<T> {
final T engine;
final T gltfAssetLoader;
final T gltfResourceLoader;
final T renderer;
final T transformManager;
final T lightManager;
@@ -42,7 +41,6 @@ abstract class FilamentApp<T> {
FilamentApp(
{required this.engine,
required this.gltfAssetLoader,
required this.gltfResourceLoader,
required this.renderer,
required this.transformManager,
required this.lightManager,
@@ -239,4 +237,15 @@ abstract class FilamentApp<T> {
///
///
Future setClearColor(double r, double g, double b, double a);
///
///
///
Future<ThermionAsset> loadGlbFromBuffer(Uint8List data, T animationManager,
{int numInstances = 1,
bool keepData = false,
int priority = 4,
int layer = 0,
bool loadResourcesAsync = false,
String? relativeResourcePath});
}

View File

@@ -1,6 +1,8 @@
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:path/path.dart';
import 'package:thermion_dart/src/filament/src/engine.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart';
@@ -27,7 +29,6 @@ class FFIFilamentConfig extends FilamentConfig<RenderCallback, Pointer<Void>> {
class FFIFilamentApp extends FilamentApp<Pointer> {
final Pointer<TEngine> engine;
final Pointer<TGltfAssetLoader> gltfAssetLoader;
final Pointer<TGltfResourceLoader> gltfResourceLoader;
final Pointer<TRenderer> renderer;
final Pointer<TTransformManager> transformManager;
final Pointer<TLightManager> lightManager;
@@ -36,29 +37,35 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
final Pointer<TRenderTicker> renderTicker;
final Pointer<TNameComponentManager> nameComponentManager;
final Future<Uint8List> Function(String uri) resourceLoader;
FFIFilamentApp(
this.engine,
this.gltfAssetLoader,
this.gltfResourceLoader,
this.renderer,
this.transformManager,
this.lightManager,
this.renderableManager,
this.ubershaderMaterialProvider,
this.renderTicker,
this.nameComponentManager)
this.nameComponentManager,
this.resourceLoader)
: super(
engine: engine,
gltfAssetLoader: gltfAssetLoader,
gltfResourceLoader: gltfResourceLoader,
renderer: renderer,
transformManager: transformManager,
lightManager: lightManager,
renderableManager: renderableManager,
ubershaderMaterialProvider: ubershaderMaterialProvider) {}
static Future<Uint8List> _defaultResourceLoader(String path) {
print("Loading file $path");
return File(path).readAsBytes();
}
static Future create({FFIFilamentConfig? config}) async {
config ??= FFIFilamentConfig(resourceLoader: nullptr);
config ??= FFIFilamentConfig(resourceLoader: _defaultResourceLoader);
if (FilamentApp.instance != null) {
await FilamentApp.instance!.destroy();
}
@@ -75,8 +82,6 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
config.disableHandleUseAfterFreeCheck,
cb));
final gltfResourceLoader = await withPointerCallback<TGltfResourceLoader>(
(cb) => GltfResourceLoader_createRenderThread(engine, cb));
final gltfAssetLoader = await withPointerCallback<TGltfAssetLoader>(
(cb) => GltfAssetLoader_createRenderThread(engine, nullptr, cb));
final renderer = await withPointerCallback<TRenderer>(
@@ -95,14 +100,14 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
FilamentApp.instance = FFIFilamentApp(
engine,
gltfAssetLoader,
gltfResourceLoader,
renderer,
transformManager,
lightManager,
renderableManager,
ubershaderMaterialProvider,
renderTicker,
nameComponentManager);
nameComponentManager,
config.resourceLoader);
}
final _views = <FFISwapChain, List<FFIView>>{};
@@ -220,7 +225,7 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
TextureFormat textureFormat = TextureFormat.RGBA16F,
int? importedTextureHandle}) async {
var bitmask = flags.fold(0, (a, b) => a | b.value);
final texturePtr = await withPointerCallback<TTexture>((cb) {
Texture_buildRenderThread(
engine,
@@ -238,7 +243,7 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
throw Exception("Failed to create texture");
}
return FFITexture(
engine!,
engine,
texturePtr,
);
}
@@ -256,24 +261,24 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
TextureCompareMode compareMode = TextureCompareMode.NONE,
TextureCompareFunc compareFunc = TextureCompareFunc.LESS_EQUAL}) async {
final samplerPtr = TextureSampler_create();
// TextureSampler_setMinFilter(
// samplerPtr, TSamplerMinFilter.values[minFilter.index]);
// TextureSampler_setMagFilter(
// samplerPtr, TSamplerMagFilter.values[magFilter.index]);
// TextureSampler_setWrapModeS(
// samplerPtr, TSamplerWrapMode.values[wrapS.index]);
// TextureSampler_setWrapModeT(
// samplerPtr, TSamplerWrapMode.values[wrapT.index]);
// TextureSampler_setWrapModeR(
// samplerPtr, TSamplerWrapMode.values[wrapR.index]);
// if (anisotropy > 0) {
// TextureSampler_setAnisotropy(samplerPtr, anisotropy);
// }
TextureSampler_setMinFilter(
samplerPtr, TSamplerMinFilter.values[minFilter.index]);
TextureSampler_setMagFilter(
samplerPtr, TSamplerMagFilter.values[magFilter.index]);
TextureSampler_setWrapModeS(
samplerPtr, TSamplerWrapMode.values[wrapS.index]);
TextureSampler_setWrapModeT(
samplerPtr, TSamplerWrapMode.values[wrapT.index]);
TextureSampler_setWrapModeR(
samplerPtr, TSamplerWrapMode.values[wrapR.index]);
if (anisotropy > 0) {
TextureSampler_setAnisotropy(samplerPtr, anisotropy);
}
// TextureSampler_setCompareMode(
// samplerPtr,
// TSamplerCompareMode.values[compareMode.index],
// TSamplerCompareFunc.values[compareFunc.index]);
TextureSampler_setCompareMode(
samplerPtr,
TSamplerCompareMode.values[compareMode.index],
TSamplerCompareFunc.values[compareFunc.index]);
return FFITextureSampler(samplerPtr);
}
@@ -307,7 +312,7 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
///
Future<Material> createMaterial(Uint8List data) async {
var ptr = await withPointerCallback<TMaterial>((cb) {
Engine_buildMaterialRenderThread(engine!, data.address, data.length, cb);
Engine_buildMaterialRenderThread(engine, data.address, data.length, cb);
});
return FFIMaterial(ptr, this);
}
@@ -614,4 +619,80 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
Future setClearColor(double r, double g, double b, double a) async {
Renderer_setClearOptions(renderer, r, g, b, a, 0, true, false);
}
///
///
///
Future<ThermionAsset> loadGlbFromBuffer(
Uint8List data, Pointer animationManager,
{int numInstances = 1,
bool keepData = false,
int priority = 4,
int layer = 0,
String? relativeResourcePath,
bool loadResourcesAsync = false}) async {
if (relativeResourcePath != null && !relativeResourcePath!.endsWith("/")) {
relativeResourcePath = "$relativeResourcePath/";
}
var gltfResourceLoader = await withPointerCallback<TGltfResourceLoader>(
(cb) => GltfResourceLoader_createRenderThread(engine,
relativeResourcePath?.toNativeUtf8().cast<Char>() ?? nullptr, cb));
var asset = await withPointerCallback<TSceneAsset>((cb) =>
SceneAsset_loadGlbRenderThread(engine, gltfAssetLoader,
nameComponentManager, data.address, data.length, numInstances, cb));
if (asset == nullptr) {
throw Exception("An error occurred loading the asset");
}
var resourceUris = SceneAsset_getResourceUris(asset);
var resourceUriCount = SceneAsset_getResourceUriCount(asset);
final resources = <FinalizableUint8List>[];
for (int i = 0; i < resourceUriCount; i++) {
final resourceUriDart = resourceUris[i].cast<Utf8>().toDartString();
final resourceData = await resourceLoader(relativeResourcePath == null
? resourceUriDart
: "$relativeResourcePath/$resourceUriDart");
resources.add(FinalizableUint8List(resourceUris[i], resourceData));
await withVoidCallback((cb) =>
GltfResourceLoader_addResourceDataRenderThread(
gltfResourceLoader,
resourceUris[i],
resourceData.address,
resourceData.lengthInBytes,
cb));
}
if (loadResourcesAsync) {
// GltfResourceLoader_asyncBeginLoad(gltfResourceLoader)
throw UnimplementedError(
"TODO"); // need to use a NativeFinalizer to ensure the pointer is still valid until resource loader has finished
} else {
final filamentAsset = SceneAsset_getFilamentAsset(asset);
if (filamentAsset == nullptr) {
throw Exception();
}
final result = await withBoolCallback((cb) =>
GltfResourceLoader_loadResourcesRenderThread(
gltfResourceLoader, filamentAsset, cb));
if (!result) {
throw Exception("Failed to load resources");
}
}
await withVoidCallback((cb) =>
GltfResourceLoader_destroyRenderThread(engine, gltfResourceLoader, cb));
return FFIAsset(asset, this, animationManager.cast<TAnimationManager>());
}
}
class FinalizableUint8List implements Finalizable {
final Pointer name;
final Uint8List data;
FinalizableUint8List(this.name, this.data);
}

View File

@@ -430,6 +430,240 @@ external void FilamentAsset_getEntities(
ffi.Pointer<EntityId> out,
);
@ffi.Native<
ffi.Pointer<TGltfAssetLoader> Function(
ffi.Pointer<TEngine>, ffi.Pointer<TMaterialProvider>)>(isLeaf: true)
external ffi.Pointer<TGltfAssetLoader> GltfAssetLoader_create(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TMaterialProvider> tMaterialProvider,
);
@ffi.Native<
ffi.Pointer<TFilamentAsset> Function(
ffi.Pointer<TEngine>,
ffi.Pointer<TGltfAssetLoader>,
ffi.Pointer<ffi.Uint8>,
ffi.Size,
ffi.Uint8)>(isLeaf: true)
external ffi.Pointer<TFilamentAsset> GltfAssetLoader_load(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TGltfAssetLoader> tAssetLoader,
ffi.Pointer<ffi.Uint8> data,
int length,
int numInstances,
);
@ffi.Native<
ffi.Pointer<TMaterialInstance> Function(ffi.Pointer<TRenderableManager>,
ffi.Pointer<TFilamentAsset>)>(isLeaf: true)
external ffi.Pointer<TMaterialInstance> GltfAssetLoader_getMaterialInstance(
ffi.Pointer<TRenderableManager> tRenderableManager,
ffi.Pointer<TFilamentAsset> tAsset,
);
@ffi.Native<
ffi.Pointer<TMaterialProvider> Function(
ffi.Pointer<TGltfAssetLoader>)>(isLeaf: true)
external ffi.Pointer<TMaterialProvider> GltfAssetLoader_getMaterialProvider(
ffi.Pointer<TGltfAssetLoader> tAssetLoader,
);
@ffi.Native<TViewport Function(ffi.Pointer<TView>)>(isLeaf: true)
external TViewport View_getViewport(
ffi.Pointer<TView> view,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Uint32, ffi.Uint32)>(
isLeaf: true)
external void View_setViewport(
ffi.Pointer<TView> view,
int width,
int height,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Pointer<TRenderTarget>)>(
isLeaf: true)
external void View_setRenderTarget(
ffi.Pointer<TView> view,
ffi.Pointer<TRenderTarget> renderTarget,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Bool)>(isLeaf: true)
external void View_setFrustumCullingEnabled(
ffi.Pointer<TView> view,
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,
bool enabled,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Bool)>(isLeaf: true)
external void View_setShadowsEnabled(
ffi.Pointer<TView> tView,
bool enabled,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Int)>(isLeaf: true)
external void View_setShadowType(
ffi.Pointer<TView> tView,
int shadowType,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Float, ffi.Float)>(
isLeaf: true)
external void View_setSoftShadowOptions(
ffi.Pointer<TView> tView,
double penumbraScale,
double penumbraRatioScale,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Bool, ffi.Float)>(
isLeaf: true)
external void View_setBloom(
ffi.Pointer<TView> tView,
bool enabled,
double strength,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.UnsignedInt)>(
symbol: "View_setRenderQuality", isLeaf: true)
external void _View_setRenderQuality(
ffi.Pointer<TView> tView,
int qualityLevel,
);
void View_setRenderQuality(
ffi.Pointer<TView> tView,
TQualityLevel qualityLevel,
) =>
_View_setRenderQuality(
tView,
qualityLevel.value,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TView>, ffi.Pointer<TEngine>,
ffi.UnsignedInt)>(symbol: "View_setToneMapping", isLeaf: true)
external void _View_setToneMapping(
ffi.Pointer<TView> tView,
ffi.Pointer<TEngine> tEngine,
int toneMapping,
);
void View_setToneMapping(
ffi.Pointer<TView> tView,
ffi.Pointer<TEngine> tEngine,
TToneMapping toneMapping,
) =>
_View_setToneMapping(
tView,
tEngine,
toneMapping.value,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TView>, ffi.Bool, ffi.Bool, ffi.Bool)>(isLeaf: true)
external void View_setAntiAliasing(
ffi.Pointer<TView> tView,
bool msaa,
bool fxaa,
bool taa,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Int, ffi.Bool)>(
isLeaf: true)
external void View_setLayerEnabled(
ffi.Pointer<TView> tView,
int layer,
bool visible,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Pointer<TCamera>)>(
isLeaf: true)
external void View_setCamera(
ffi.Pointer<TView> tView,
ffi.Pointer<TCamera> tCamera,
);
@ffi.Native<ffi.Pointer<TScene> Function(ffi.Pointer<TView>)>(isLeaf: true)
external ffi.Pointer<TScene> View_getScene(
ffi.Pointer<TView> tView,
);
@ffi.Native<ffi.Pointer<TCamera> Function(ffi.Pointer<TView>)>(isLeaf: true)
external ffi.Pointer<TCamera> View_getCamera(
ffi.Pointer<TView> tView,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Bool)>(isLeaf: true)
external void View_setStencilBufferEnabled(
ffi.Pointer<TView> tView,
bool enabled,
);
@ffi.Native<ffi.Bool Function(ffi.Pointer<TView>)>(isLeaf: true)
external bool View_isStencilBufferEnabled(
ffi.Pointer<TView> tView,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Bool)>(isLeaf: true)
external void View_setDitheringEnabled(
ffi.Pointer<TView> tView,
bool enabled,
);
@ffi.Native<ffi.Bool Function(ffi.Pointer<TView>)>(isLeaf: true)
external bool View_isDitheringEnabled(
ffi.Pointer<TView> tView,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Pointer<TScene>)>(
isLeaf: true)
external void View_setScene(
ffi.Pointer<TView> tView,
ffi.Pointer<TScene> tScene,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TView>, ffi.Uint32, ffi.Uint32, ffi.Uint32,
PickCallback)>(isLeaf: true)
external void View_pick(
ffi.Pointer<TView> tView,
int requestId,
int x,
int y,
PickCallback callback,
);
@ffi.Native<ffi.Pointer<TNameComponentManager> Function()>(isLeaf: true)
external ffi.Pointer<TNameComponentManager> NameComponentManager_create();
@ffi.Native<
ffi.Pointer<ffi.Char> Function(
ffi.Pointer<TNameComponentManager>, EntityId)>(isLeaf: true)
external ffi.Pointer<ffi.Char> NameComponentManager_getName(
ffi.Pointer<TNameComponentManager> tNameComponentManager,
int entity,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TIndirectLight>, ffi.Pointer<ffi.Double>)>(isLeaf: true)
external void IndirectLight_setRotation(
ffi.Pointer<TIndirectLight> tIndirectLight,
ffi.Pointer<ffi.Double> rotation,
);
@ffi.Native<
ffi.Pointer<TTexture> Function(
ffi.Pointer<TEngine>,
@@ -802,246 +1036,6 @@ external void TextureSampler_destroy(
ffi.Pointer<TTextureSampler> sampler,
);
@ffi.Native<
ffi.Pointer<TGltfAssetLoader> Function(
ffi.Pointer<TEngine>, ffi.Pointer<TMaterialProvider>)>(isLeaf: true)
external ffi.Pointer<TGltfAssetLoader> GltfAssetLoader_create(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TMaterialProvider> tMaterialProvider,
);
@ffi.Native<ffi.Pointer<TGltfResourceLoader> Function(ffi.Pointer<TEngine>)>(
isLeaf: true)
external ffi.Pointer<TGltfResourceLoader> GltfResourceLoader_create(
ffi.Pointer<TEngine> tEngine,
);
@ffi.Native<
ffi.Pointer<TFilamentAsset> Function(
ffi.Pointer<TGltfAssetLoader>,
ffi.Pointer<TGltfResourceLoader>,
ffi.Pointer<ffi.Uint8>,
ffi.Size,
ffi.Uint8)>(isLeaf: true)
external ffi.Pointer<TFilamentAsset> GltfAssetLoader_load(
ffi.Pointer<TGltfAssetLoader> tAssetLoader,
ffi.Pointer<TGltfResourceLoader> tResourceLoader,
ffi.Pointer<ffi.Uint8> data,
int length,
int numInstances,
);
@ffi.Native<
ffi.Pointer<TMaterialInstance> Function(ffi.Pointer<TRenderableManager>,
ffi.Pointer<TFilamentAsset>)>(isLeaf: true)
external ffi.Pointer<TMaterialInstance> GltfAssetLoader_getMaterialInstance(
ffi.Pointer<TRenderableManager> tRenderableManager,
ffi.Pointer<TFilamentAsset> tAsset,
);
@ffi.Native<
ffi.Pointer<TMaterialProvider> Function(
ffi.Pointer<TGltfAssetLoader>)>(isLeaf: true)
external ffi.Pointer<TMaterialProvider> GltfAssetLoader_getMaterialProvider(
ffi.Pointer<TGltfAssetLoader> tAssetLoader,
);
@ffi.Native<TViewport Function(ffi.Pointer<TView>)>(isLeaf: true)
external TViewport View_getViewport(
ffi.Pointer<TView> view,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Uint32, ffi.Uint32)>(
isLeaf: true)
external void View_setViewport(
ffi.Pointer<TView> view,
int width,
int height,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Pointer<TRenderTarget>)>(
isLeaf: true)
external void View_setRenderTarget(
ffi.Pointer<TView> view,
ffi.Pointer<TRenderTarget> renderTarget,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Bool)>(isLeaf: true)
external void View_setFrustumCullingEnabled(
ffi.Pointer<TView> view,
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,
bool enabled,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Bool)>(isLeaf: true)
external void View_setShadowsEnabled(
ffi.Pointer<TView> tView,
bool enabled,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Int)>(isLeaf: true)
external void View_setShadowType(
ffi.Pointer<TView> tView,
int shadowType,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Float, ffi.Float)>(
isLeaf: true)
external void View_setSoftShadowOptions(
ffi.Pointer<TView> tView,
double penumbraScale,
double penumbraRatioScale,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Bool, ffi.Float)>(
isLeaf: true)
external void View_setBloom(
ffi.Pointer<TView> tView,
bool enabled,
double strength,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.UnsignedInt)>(
symbol: "View_setRenderQuality", isLeaf: true)
external void _View_setRenderQuality(
ffi.Pointer<TView> tView,
int qualityLevel,
);
void View_setRenderQuality(
ffi.Pointer<TView> tView,
TQualityLevel qualityLevel,
) =>
_View_setRenderQuality(
tView,
qualityLevel.value,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TView>, ffi.Pointer<TEngine>,
ffi.UnsignedInt)>(symbol: "View_setToneMapping", isLeaf: true)
external void _View_setToneMapping(
ffi.Pointer<TView> tView,
ffi.Pointer<TEngine> tEngine,
int toneMapping,
);
void View_setToneMapping(
ffi.Pointer<TView> tView,
ffi.Pointer<TEngine> tEngine,
TToneMapping toneMapping,
) =>
_View_setToneMapping(
tView,
tEngine,
toneMapping.value,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TView>, ffi.Bool, ffi.Bool, ffi.Bool)>(isLeaf: true)
external void View_setAntiAliasing(
ffi.Pointer<TView> tView,
bool msaa,
bool fxaa,
bool taa,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Int, ffi.Bool)>(
isLeaf: true)
external void View_setLayerEnabled(
ffi.Pointer<TView> tView,
int layer,
bool visible,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Pointer<TCamera>)>(
isLeaf: true)
external void View_setCamera(
ffi.Pointer<TView> tView,
ffi.Pointer<TCamera> tCamera,
);
@ffi.Native<ffi.Pointer<TScene> Function(ffi.Pointer<TView>)>(isLeaf: true)
external ffi.Pointer<TScene> View_getScene(
ffi.Pointer<TView> tView,
);
@ffi.Native<ffi.Pointer<TCamera> Function(ffi.Pointer<TView>)>(isLeaf: true)
external ffi.Pointer<TCamera> View_getCamera(
ffi.Pointer<TView> tView,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Bool)>(isLeaf: true)
external void View_setStencilBufferEnabled(
ffi.Pointer<TView> tView,
bool enabled,
);
@ffi.Native<ffi.Bool Function(ffi.Pointer<TView>)>(isLeaf: true)
external bool View_isStencilBufferEnabled(
ffi.Pointer<TView> tView,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Bool)>(isLeaf: true)
external void View_setDitheringEnabled(
ffi.Pointer<TView> tView,
bool enabled,
);
@ffi.Native<ffi.Bool Function(ffi.Pointer<TView>)>(isLeaf: true)
external bool View_isDitheringEnabled(
ffi.Pointer<TView> tView,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Pointer<TScene>)>(
isLeaf: true)
external void View_setScene(
ffi.Pointer<TView> tView,
ffi.Pointer<TScene> tScene,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TView>, ffi.Uint32, ffi.Uint32, ffi.Uint32,
PickCallback)>(isLeaf: true)
external void View_pick(
ffi.Pointer<TView> tView,
int requestId,
int x,
int y,
PickCallback callback,
);
@ffi.Native<ffi.Pointer<TNameComponentManager> Function()>(isLeaf: true)
external ffi.Pointer<TNameComponentManager> NameComponentManager_create();
@ffi.Native<
ffi.Pointer<ffi.Char> Function(
ffi.Pointer<TNameComponentManager>, EntityId)>(isLeaf: true)
external ffi.Pointer<ffi.Char> NameComponentManager_getName(
ffi.Pointer<TNameComponentManager> tNameComponentManager,
int entity,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TIndirectLight>, ffi.Pointer<ffi.Double>)>(isLeaf: true)
external void IndirectLight_setRotation(
ffi.Pointer<TIndirectLight> tIndirectLight,
ffi.Pointer<ffi.Double> rotation,
);
@ffi.Native<
ffi.Pointer<TGizmo> Function(ffi.Pointer<TEngine>, ffi.Pointer<TView>,
ffi.UnsignedInt)>(symbol: "Gizmo_create", isLeaf: true)
@@ -1999,9 +1993,8 @@ external void SceneAsset_destroyRenderThread(
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TGltfAssetLoader>,
ffi.Pointer<TGltfResourceLoader>,
ffi.Pointer<TEngine>,
ffi.Pointer<TGltfAssetLoader>,
ffi.Pointer<TNameComponentManager>,
ffi.Pointer<ffi.Uint8>,
ffi.Size,
@@ -2011,9 +2004,8 @@ external void SceneAsset_destroyRenderThread(
.NativeFunction<ffi.Void Function(ffi.Pointer<TSceneAsset>)>>)>(
isLeaf: true)
external void SceneAsset_loadGlbRenderThread(
ffi.Pointer<TGltfAssetLoader> tAssetLoader,
ffi.Pointer<TGltfResourceLoader> tResourceLoader,
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TGltfAssetLoader> tAssetLoader,
ffi.Pointer<TNameComponentManager> tNameComponentManager,
ffi.Pointer<ffi.Uint8> data,
int length,
@@ -2600,22 +2592,60 @@ external void GltfAssetLoader_createRenderThread(
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TEngine>,
ffi.Pointer<ffi.Char>,
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(
ffi.Pointer<TGltfResourceLoader>)>>)>(isLeaf: true)
external void GltfResourceLoader_createRenderThread(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<ffi.Char> relativeResourcePath,
ffi.Pointer<
ffi
.NativeFunction<ffi.Void Function(ffi.Pointer<TGltfResourceLoader>)>>
callback,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TEngine>, ffi.Pointer<TGltfResourceLoader>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void GltfResourceLoader_destroyRenderThread(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TGltfResourceLoader> tResourceLoader,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TGltfResourceLoader>,
ffi.Pointer<TFilamentAsset>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>>)>(
isLeaf: true)
external void GltfResourceLoader_loadResourcesRenderThread(
ffi.Pointer<TGltfResourceLoader> tGltfResourceLoader,
ffi.Pointer<TFilamentAsset> tFilamentAsset,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>> callback,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TGltfAssetLoader>,
ffi.Pointer<TGltfResourceLoader>,
ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.Uint8>,
ffi.Size,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void GltfResourceLoader_addResourceDataRenderThread(
ffi.Pointer<TGltfResourceLoader> tGltfResourceLoader,
ffi.Pointer<ffi.Char> uri,
ffi.Pointer<ffi.Uint8> data,
int length,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TEngine>,
ffi.Pointer<TGltfAssetLoader>,
ffi.Pointer<ffi.Uint8>,
ffi.Size,
ffi.Uint8,
@@ -2623,8 +2653,8 @@ external void GltfResourceLoader_createRenderThread(
ffi.NativeFunction<
ffi.Void Function(ffi.Pointer<TFilamentAsset>)>>)>(isLeaf: true)
external void GltfAssetLoader_loadRenderThread(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TGltfAssetLoader> tAssetLoader,
ffi.Pointer<TGltfResourceLoader> tResourceLoader,
ffi.Pointer<ffi.Uint8> data,
int length,
int numInstances,
@@ -2642,6 +2672,48 @@ external void Scene_addFilamentAssetRenderThread(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
ffi.Pointer<TGltfResourceLoader> Function(
ffi.Pointer<TEngine>, ffi.Pointer<ffi.Char>)>(isLeaf: true)
external ffi.Pointer<TGltfResourceLoader> GltfResourceLoader_create(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<ffi.Char> relativeResourcePath,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TEngine>, ffi.Pointer<TGltfResourceLoader>)>(isLeaf: true)
external void GltfResourceLoader_destroy(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TGltfResourceLoader> tGltfResourceLoader,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TGltfResourceLoader>,
ffi.Pointer<TFilamentAsset>)>(isLeaf: true)
external void GltfResourceLoader_asyncBeginLoad(
ffi.Pointer<TGltfResourceLoader> tGltfResourceLoader,
ffi.Pointer<TFilamentAsset> tFilamentAsset,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TGltfResourceLoader>, ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.Uint8>, ffi.Size)>(isLeaf: true)
external void GltfResourceLoader_addResourceData(
ffi.Pointer<TGltfResourceLoader> tGltfResourceLoader,
ffi.Pointer<ffi.Char> uri,
ffi.Pointer<ffi.Uint8> data,
int length,
);
@ffi.Native<
ffi.Bool Function(ffi.Pointer<TGltfResourceLoader>,
ffi.Pointer<TFilamentAsset>)>(isLeaf: true)
external bool GltfResourceLoader_loadResources(
ffi.Pointer<TGltfResourceLoader> tGltfResourceLoader,
ffi.Pointer<TFilamentAsset> tFilamentAsset,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TRenderableManager>, EntityId, ffi.Int,
ffi.Pointer<TMaterialInstance>)>(isLeaf: true)
@@ -2987,17 +3059,15 @@ external ffi.Pointer<TSceneAsset> SceneAsset_createGeometry(
@ffi.Native<
ffi.Pointer<TSceneAsset> Function(
ffi.Pointer<TGltfAssetLoader>,
ffi.Pointer<TGltfResourceLoader>,
ffi.Pointer<TEngine>,
ffi.Pointer<TGltfAssetLoader>,
ffi.Pointer<TNameComponentManager>,
ffi.Pointer<ffi.Uint8>,
ffi.Size,
ffi.Size)>(isLeaf: true)
external ffi.Pointer<TSceneAsset> SceneAsset_loadGlb(
ffi.Pointer<TGltfAssetLoader> tAssetLoader,
ffi.Pointer<TGltfResourceLoader> tResourceLoader,
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TGltfAssetLoader> tAssetLoader,
ffi.Pointer<TNameComponentManager> tNameComponentManager,
ffi.Pointer<ffi.Uint8> data,
int length,
@@ -3023,6 +3093,24 @@ external ffi.Pointer<TSceneAsset> SceneAsset_loadGltf(
int numInstances,
);
@ffi.Native<ffi.Int32 Function(ffi.Pointer<TSceneAsset>)>(isLeaf: true)
external int SceneAsset_getResourceUriCount(
ffi.Pointer<TSceneAsset> tSceneAsset,
);
@ffi.Native<
ffi.Pointer<ffi.Pointer<ffi.Char>> Function(
ffi.Pointer<TSceneAsset>)>(isLeaf: true)
external ffi.Pointer<ffi.Pointer<ffi.Char>> SceneAsset_getResourceUris(
ffi.Pointer<TSceneAsset> tSceneAsset,
);
@ffi.Native<ffi.Pointer<TFilamentAsset> Function(ffi.Pointer<TSceneAsset>)>(
isLeaf: true)
external ffi.Pointer<TFilamentAsset> SceneAsset_getFilamentAsset(
ffi.Pointer<TSceneAsset> tSceneAsset,
);
@ffi.Native<
ffi.Pointer<TSceneAsset> Function(
ffi.Pointer<TEngine>, ffi.Pointer<TMaterial>)>(isLeaf: true)
@@ -3815,6 +3903,70 @@ enum TLightType {
typedef EntityId = ffi.Int32;
typedef DartEntityId = int;
final class TViewport extends ffi.Struct {
@ffi.Int32()
external int left;
@ffi.Int32()
external int bottom;
@ffi.Uint32()
external int width;
@ffi.Uint32()
external int height;
}
enum TToneMapping {
ACES(0),
FILMIC(1),
LINEAR(2);
final int value;
const TToneMapping(this.value);
static TToneMapping fromValue(int value) => switch (value) {
0 => ACES,
1 => FILMIC,
2 => LINEAR,
_ => throw ArgumentError("Unknown value for TToneMapping: $value"),
};
}
enum TQualityLevel {
LOW(0),
MEDIUM(1),
HIGH(2),
ULTRA(3);
final int value;
const TQualityLevel(this.value);
static TQualityLevel fromValue(int value) => switch (value) {
0 => LOW,
1 => MEDIUM,
2 => HIGH,
3 => ULTRA,
_ => throw ArgumentError("Unknown value for TQualityLevel: $value"),
};
}
typedef PickCallback = ffi.Pointer<ffi.NativeFunction<PickCallbackFunction>>;
typedef PickCallbackFunction = ffi.Void Function(
ffi.Uint32 requestId,
EntityId entityId,
ffi.Float depth,
ffi.Float fragX,
ffi.Float fragY,
ffi.Float fragZ);
typedef DartPickCallbackFunction = void Function(
int requestId,
DartEntityId entityId,
double depth,
double fragX,
double fragY,
double fragZ);
enum TTextureSamplerType {
SAMPLER_2D(0),
SAMPLER_2D_ARRAY(1),
@@ -4258,70 +4410,6 @@ enum TSamplerCompareMode {
};
}
final class TViewport extends ffi.Struct {
@ffi.Int32()
external int left;
@ffi.Int32()
external int bottom;
@ffi.Uint32()
external int width;
@ffi.Uint32()
external int height;
}
enum TToneMapping {
ACES(0),
FILMIC(1),
LINEAR(2);
final int value;
const TToneMapping(this.value);
static TToneMapping fromValue(int value) => switch (value) {
0 => ACES,
1 => FILMIC,
2 => LINEAR,
_ => throw ArgumentError("Unknown value for TToneMapping: $value"),
};
}
enum TQualityLevel {
LOW(0),
MEDIUM(1),
HIGH(2),
ULTRA(3);
final int value;
const TQualityLevel(this.value);
static TQualityLevel fromValue(int value) => switch (value) {
0 => LOW,
1 => MEDIUM,
2 => HIGH,
3 => ULTRA,
_ => throw ArgumentError("Unknown value for TQualityLevel: $value"),
};
}
typedef PickCallback = ffi.Pointer<ffi.NativeFunction<PickCallbackFunction>>;
typedef PickCallbackFunction = ffi.Void Function(
ffi.Uint32 requestId,
EntityId entityId,
ffi.Float depth,
ffi.Float fragX,
ffi.Float fragY,
ffi.Float fragZ);
typedef DartPickCallbackFunction = void Function(
int requestId,
DartEntityId entityId,
double depth,
double fragX,
double fragY,
double fragZ);
enum TGizmoAxis {
X(0),
Y(1),

View File

@@ -1,6 +1,5 @@
import 'dart:async';
import 'dart:io';
import 'dart:math';
import 'dart:typed_data';
import 'package:thermion_dart/src/filament/src/light_options.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/background_image.dart';
@@ -39,12 +38,12 @@ class ThermionViewerFFI extends ThermionViewer {
late final FFIView view;
late final FFIScene scene;
late final Pointer<TAnimationManager> animationManager;
late final Future<Uint8List> Function(String path) loadAsset;
late final Future<Uint8List> Function(String path) loadAssetFromUri;
///
///
///
ThermionViewerFFI({required this.loadAsset, this.renderTarget}) {
ThermionViewerFFI({required this.loadAssetFromUri, this.renderTarget}) {
if (FilamentApp.instance == null) {
throw Exception("FilamentApp has not been created");
}
@@ -191,7 +190,7 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future setBackgroundImage(String path, {bool fillHeight = false}) async {
final imageData = await loadAsset(path);
final imageData = await loadAssetFromUri(path);
_backgroundImage ??= await BackgroundImage.create(this, scene);
await _backgroundImage!.setImage(imageData);
}
@@ -224,7 +223,7 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future loadSkybox(String skyboxPath) async {
var data = await loadAsset(skyboxPath);
var data = await loadAssetFromUri(skyboxPath);
skybox = await withPointerCallback<TSkybox>((cb) {
Engine_buildSkyboxRenderThread(
@@ -242,7 +241,7 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future loadIbl(String lightingPath, {double intensity = 30000}) async {
var data = await loadAsset(lightingPath);
var data = await loadAssetFromUri(lightingPath);
indirectLight = await withPointerCallback<TIndirectLight>((cb) {
Engine_buildIndirectLightRenderThread(
app.engine, data.address, data.length, intensity, cb, nullptr);
@@ -313,7 +312,7 @@ class ThermionViewerFFI extends ThermionViewer {
// LightManager_setSunHaloFalloff(app.lightManager, entity, directLight.spotLightConeInner, directLight.spotLightConeOuter);
LightManager_setShadowCaster(
app.lightManager, entity, directLight.castShadows);
Scene_addEntity(scene.scene, entity);
_lights.add(entity);
@@ -349,11 +348,11 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future<ThermionAsset> loadGlb(String path,
{int numInstances = 1, bool keepData = false}) async {
final data = await loadAsset(path);
{int numInstances = 1, bool keepData = false, String? relativeResourcePath}) async {
final data = await loadAssetFromUri(path);
return loadGlbFromBuffer(data,
numInstances: numInstances, keepData: keepData);
numInstances: numInstances, keepData: keepData, relativeResourcePath: relativeResourcePath);
}
///
@@ -365,52 +364,22 @@ class ThermionViewerFFI extends ThermionViewer {
bool keepData = false,
int priority = 4,
int layer = 0,
bool loadResourcesAsync = false}) async {
var asset = await withPointerCallback<TSceneAsset>((cb) =>
SceneAsset_loadGlbRenderThread(
app.gltfAssetLoader,
app.gltfResourceLoader,
app.engine,
app.nameComponentManager,
data.address,
data.length,
numInstances,
cb));
bool loadResourcesAsync = false,
String? relativeResourcePath}) async {
var asset = await FilamentApp.instance!.loadGlbFromBuffer(data, animationManager,
numInstances: numInstances,
keepData: keepData,
priority: priority,
layer: layer,
loadResourcesAsync: loadResourcesAsync,
relativeResourcePath:relativeResourcePath
) as FFIAsset;
_assets.add(asset);
if (asset == nullptr) {
throw Exception("An error occurred loading the asset");
}
await scene.add(asset);
var thermionAsset = FFIAsset(asset, app, animationManager);
_assets.add(thermionAsset);
await scene.add(thermionAsset);
return thermionAsset;
}
///
///
///
@override
Future<ThermionAsset> loadGltf(String path, String relativeResourcePath,
{bool keepData = false}) async {
throw UnimplementedError();
// final pathPtr = path.toNativeUtf8(allocator: allocator).cast<Char>();
// final relativeResourcePathPtr =
// relativeResourcePath.toNativeUtf8(allocator: allocator).cast<Char>();
// var assetPtr = await withPointerCallback<TSceneAsset>((callback) =>
// SceneManager_loadGltfRenderThread(_sceneManager!, pathPtr,
// relativeResourcePathPtr, keepData, callback));
// allocator.free(pathPtr);
// allocator.free(relativeResourcePathPtr);
// if (assetPtr == nullptr) {
// throw Exception("An error occurred loading the asset at $path");
// }
// return FFIAsset(
// assetPtr, _sceneManager!, app.engine!, _unlitMaterialProvider!, this);
return asset;
}
///

View File

@@ -129,7 +129,9 @@ abstract class ThermionViewer {
/// If [keepData] is false, the source glTF data will be released and [createInstance] will throw an exception.
///
Future<ThermionAsset> loadGlb(String path,
{int numInstances = 1, bool keepData = false});
{int numInstances = 1,
bool keepData = false,
String relativeResourcePath});
///
/// Load the .glb asset from the specified buffer, adding all entities to the scene.
@@ -145,17 +147,8 @@ abstract class ThermionViewer {
bool keepData = false,
int priority = 4,
int layer = 0,
bool loadResourcesAsync = false});
///
/// Load the .gltf asset at the given path, adding all entities to the scene.
/// [relativeResourcePath] is the folder path where the glTF resources are stored;
/// this is usually the parent directory of the .gltf file itself.
///
/// See [loadGlb] for an explanation of [keepData].
///
Future<ThermionAsset> loadGltf(String path, String relativeResourcePath,
{bool keepData = false});
bool loadResourcesAsync = false,
String relativeResourcePath});
///
/// Destroys [asset] and all underlying resources