From e6bdcb687a2a42ace6773c0a59cd516a23a77cb6 Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Thu, 20 Mar 2025 18:48:04 +0800 Subject: [PATCH] refactoring --- .../lib/src/filament/src/camera.dart | 5 + .../lib/src/filament/src/filament_app.dart | 15 +- .../viewer/src/ffi/src/ffi_filament_app.dart | 139 +++- .../viewer/src/ffi/src/thermion_dart.g.dart | 716 ++++++++++-------- .../src/ffi/src/thermion_viewer_ffi.dart | 77 +- .../src/viewer/src/thermion_viewer_base.dart | 17 +- thermion_dart/native/include/ThreadPool.hpp | 79 -- .../native/include/c_api/TGltfAssetLoader.h | 10 +- .../include/c_api/TGltfResourceLoader.h | 21 + .../native/include/c_api/TSceneAsset.h | 13 +- .../c_api/ThermionDartRenderThreadApi.h | 11 +- .../native/include/scene/GltfSceneAsset.hpp | 2 +- .../native/src/c_api/TGltfAssetLoader.cpp | 37 +- .../native/src/c_api/TGltfResourceLoader.cpp | 75 ++ .../native/src/c_api/TSceneAsset.cpp | 52 +- .../src/c_api/ThermionDartRenderThreadApi.cpp | 52 +- 16 files changed, 780 insertions(+), 541 deletions(-) delete mode 100644 thermion_dart/native/include/ThreadPool.hpp create mode 100644 thermion_dart/native/include/c_api/TGltfResourceLoader.h create mode 100644 thermion_dart/native/src/c_api/TGltfResourceLoader.cpp diff --git a/thermion_dart/lib/src/filament/src/camera.dart b/thermion_dart/lib/src/filament/src/camera.dart index 225b7427..0f2cd414 100644 --- a/thermion_dart/lib/src/filament/src/camera.dart +++ b/thermion_dart/lib/src/filament/src/camera.dart @@ -5,6 +5,11 @@ enum Projection { Perspective, Orthographic } abstract class Camera { + Future 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); diff --git a/thermion_dart/lib/src/filament/src/filament_app.dart b/thermion_dart/lib/src/filament/src/filament_app.dart index db57c45c..7e027a5d 100644 --- a/thermion_dart/lib/src/filament/src/filament_app.dart +++ b/thermion_dart/lib/src/filament/src/filament_app.dart @@ -6,7 +6,7 @@ class FilamentConfig { final Backend backend; final T? renderCallback; final U? renderCallbackOwner; - final U resourceLoader; + final Future Function(String) resourceLoader; final U? platform; final U? driver; final U? sharedContext; @@ -32,7 +32,6 @@ abstract class FilamentApp { 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 { 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 { /// /// Future setClearColor(double r, double g, double b, double a); + + /// + /// + /// + Future loadGlbFromBuffer(Uint8List data, T animationManager, + {int numInstances = 1, + bool keepData = false, + int priority = 4, + int layer = 0, + bool loadResourcesAsync = false, + String? relativeResourcePath}); } diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_filament_app.dart b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_filament_app.dart index 4a918dc1..b9c6db89 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_filament_app.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_filament_app.dart @@ -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> { class FFIFilamentApp extends FilamentApp { final Pointer engine; final Pointer gltfAssetLoader; - final Pointer gltfResourceLoader; final Pointer renderer; final Pointer transformManager; final Pointer lightManager; @@ -36,29 +37,35 @@ class FFIFilamentApp extends FilamentApp { final Pointer renderTicker; final Pointer nameComponentManager; + final Future 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 _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 { config.disableHandleUseAfterFreeCheck, cb)); - final gltfResourceLoader = await withPointerCallback( - (cb) => GltfResourceLoader_createRenderThread(engine, cb)); final gltfAssetLoader = await withPointerCallback( (cb) => GltfAssetLoader_createRenderThread(engine, nullptr, cb)); final renderer = await withPointerCallback( @@ -95,14 +100,14 @@ class FFIFilamentApp extends FilamentApp { FilamentApp.instance = FFIFilamentApp( engine, gltfAssetLoader, - gltfResourceLoader, renderer, transformManager, lightManager, renderableManager, ubershaderMaterialProvider, renderTicker, - nameComponentManager); + nameComponentManager, + config.resourceLoader); } final _views = >{}; @@ -220,7 +225,7 @@ class FFIFilamentApp extends FilamentApp { TextureFormat textureFormat = TextureFormat.RGBA16F, int? importedTextureHandle}) async { var bitmask = flags.fold(0, (a, b) => a | b.value); - + final texturePtr = await withPointerCallback((cb) { Texture_buildRenderThread( engine, @@ -238,7 +243,7 @@ class FFIFilamentApp extends FilamentApp { throw Exception("Failed to create texture"); } return FFITexture( - engine!, + engine, texturePtr, ); } @@ -256,24 +261,24 @@ class FFIFilamentApp extends FilamentApp { 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 { /// Future createMaterial(Uint8List data) async { var ptr = await withPointerCallback((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 { Future setClearColor(double r, double g, double b, double a) async { Renderer_setClearOptions(renderer, r, g, b, a, 0, true, false); } + + /// + /// + /// + Future 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( + (cb) => GltfResourceLoader_createRenderThread(engine, + relativeResourcePath?.toNativeUtf8().cast() ?? nullptr, cb)); + + var asset = await withPointerCallback((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 = []; + + for (int i = 0; i < resourceUriCount; i++) { + final resourceUriDart = resourceUris[i].cast().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()); + } +} + +class FinalizableUint8List implements Finalizable { + final Pointer name; + final Uint8List data; + + FinalizableUint8List(this.name, this.data); } 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 4fbadd1a..aec23598 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 @@ -430,6 +430,240 @@ external void FilamentAsset_getEntities( ffi.Pointer out, ); +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer)>(isLeaf: true) +external ffi.Pointer GltfAssetLoader_create( + ffi.Pointer tEngine, + ffi.Pointer tMaterialProvider, +); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Size, + ffi.Uint8)>(isLeaf: true) +external ffi.Pointer GltfAssetLoader_load( + ffi.Pointer tEngine, + ffi.Pointer tAssetLoader, + ffi.Pointer data, + int length, + int numInstances, +); + +@ffi.Native< + ffi.Pointer Function(ffi.Pointer, + ffi.Pointer)>(isLeaf: true) +external ffi.Pointer GltfAssetLoader_getMaterialInstance( + ffi.Pointer tRenderableManager, + ffi.Pointer tAsset, +); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer)>(isLeaf: true) +external ffi.Pointer GltfAssetLoader_getMaterialProvider( + ffi.Pointer tAssetLoader, +); + +@ffi.Native)>(isLeaf: true) +external TViewport View_getViewport( + ffi.Pointer view, +); + +@ffi.Native, ffi.Uint32, ffi.Uint32)>( + isLeaf: true) +external void View_setViewport( + ffi.Pointer view, + int width, + int height, +); + +@ffi.Native, ffi.Pointer)>( + isLeaf: true) +external void View_setRenderTarget( + ffi.Pointer view, + ffi.Pointer renderTarget, +); + +@ffi.Native, ffi.Bool)>(isLeaf: true) +external void View_setFrustumCullingEnabled( + ffi.Pointer view, + bool enabled, +); + +@ffi.Native Function(ffi.Pointer)>( + isLeaf: true) +external ffi.Pointer View_getRenderTarget( + ffi.Pointer tView, +); + +@ffi.Native, ffi.Bool)>(isLeaf: true) +external void View_setPostProcessing( + ffi.Pointer tView, + bool enabled, +); + +@ffi.Native, ffi.Bool)>(isLeaf: true) +external void View_setShadowsEnabled( + ffi.Pointer tView, + bool enabled, +); + +@ffi.Native, ffi.Int)>(isLeaf: true) +external void View_setShadowType( + ffi.Pointer tView, + int shadowType, +); + +@ffi.Native, ffi.Float, ffi.Float)>( + isLeaf: true) +external void View_setSoftShadowOptions( + ffi.Pointer tView, + double penumbraScale, + double penumbraRatioScale, +); + +@ffi.Native, ffi.Bool, ffi.Float)>( + isLeaf: true) +external void View_setBloom( + ffi.Pointer tView, + bool enabled, + double strength, +); + +@ffi.Native, ffi.UnsignedInt)>( + symbol: "View_setRenderQuality", isLeaf: true) +external void _View_setRenderQuality( + ffi.Pointer tView, + int qualityLevel, +); + +void View_setRenderQuality( + ffi.Pointer tView, + TQualityLevel qualityLevel, +) => + _View_setRenderQuality( + tView, + qualityLevel.value, + ); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.UnsignedInt)>(symbol: "View_setToneMapping", isLeaf: true) +external void _View_setToneMapping( + ffi.Pointer tView, + ffi.Pointer tEngine, + int toneMapping, +); + +void View_setToneMapping( + ffi.Pointer tView, + ffi.Pointer tEngine, + TToneMapping toneMapping, +) => + _View_setToneMapping( + tView, + tEngine, + toneMapping.value, + ); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Bool, ffi.Bool, ffi.Bool)>(isLeaf: true) +external void View_setAntiAliasing( + ffi.Pointer tView, + bool msaa, + bool fxaa, + bool taa, +); + +@ffi.Native, ffi.Int, ffi.Bool)>( + isLeaf: true) +external void View_setLayerEnabled( + ffi.Pointer tView, + int layer, + bool visible, +); + +@ffi.Native, ffi.Pointer)>( + isLeaf: true) +external void View_setCamera( + ffi.Pointer tView, + ffi.Pointer tCamera, +); + +@ffi.Native Function(ffi.Pointer)>(isLeaf: true) +external ffi.Pointer View_getScene( + ffi.Pointer tView, +); + +@ffi.Native Function(ffi.Pointer)>(isLeaf: true) +external ffi.Pointer View_getCamera( + ffi.Pointer tView, +); + +@ffi.Native, ffi.Bool)>(isLeaf: true) +external void View_setStencilBufferEnabled( + ffi.Pointer tView, + bool enabled, +); + +@ffi.Native)>(isLeaf: true) +external bool View_isStencilBufferEnabled( + ffi.Pointer tView, +); + +@ffi.Native, ffi.Bool)>(isLeaf: true) +external void View_setDitheringEnabled( + ffi.Pointer tView, + bool enabled, +); + +@ffi.Native)>(isLeaf: true) +external bool View_isDitheringEnabled( + ffi.Pointer tView, +); + +@ffi.Native, ffi.Pointer)>( + isLeaf: true) +external void View_setScene( + ffi.Pointer tView, + ffi.Pointer tScene, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Uint32, ffi.Uint32, ffi.Uint32, + PickCallback)>(isLeaf: true) +external void View_pick( + ffi.Pointer tView, + int requestId, + int x, + int y, + PickCallback callback, +); + +@ffi.Native Function()>(isLeaf: true) +external ffi.Pointer NameComponentManager_create(); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, EntityId)>(isLeaf: true) +external ffi.Pointer NameComponentManager_getName( + ffi.Pointer tNameComponentManager, + int entity, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Pointer)>(isLeaf: true) +external void IndirectLight_setRotation( + ffi.Pointer tIndirectLight, + ffi.Pointer rotation, +); + @ffi.Native< ffi.Pointer Function( ffi.Pointer, @@ -802,246 +1036,6 @@ external void TextureSampler_destroy( ffi.Pointer sampler, ); -@ffi.Native< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer)>(isLeaf: true) -external ffi.Pointer GltfAssetLoader_create( - ffi.Pointer tEngine, - ffi.Pointer tMaterialProvider, -); - -@ffi.Native Function(ffi.Pointer)>( - isLeaf: true) -external ffi.Pointer GltfResourceLoader_create( - ffi.Pointer tEngine, -); - -@ffi.Native< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Size, - ffi.Uint8)>(isLeaf: true) -external ffi.Pointer GltfAssetLoader_load( - ffi.Pointer tAssetLoader, - ffi.Pointer tResourceLoader, - ffi.Pointer data, - int length, - int numInstances, -); - -@ffi.Native< - ffi.Pointer Function(ffi.Pointer, - ffi.Pointer)>(isLeaf: true) -external ffi.Pointer GltfAssetLoader_getMaterialInstance( - ffi.Pointer tRenderableManager, - ffi.Pointer tAsset, -); - -@ffi.Native< - ffi.Pointer Function( - ffi.Pointer)>(isLeaf: true) -external ffi.Pointer GltfAssetLoader_getMaterialProvider( - ffi.Pointer tAssetLoader, -); - -@ffi.Native)>(isLeaf: true) -external TViewport View_getViewport( - ffi.Pointer view, -); - -@ffi.Native, ffi.Uint32, ffi.Uint32)>( - isLeaf: true) -external void View_setViewport( - ffi.Pointer view, - int width, - int height, -); - -@ffi.Native, ffi.Pointer)>( - isLeaf: true) -external void View_setRenderTarget( - ffi.Pointer view, - ffi.Pointer renderTarget, -); - -@ffi.Native, ffi.Bool)>(isLeaf: true) -external void View_setFrustumCullingEnabled( - ffi.Pointer view, - bool enabled, -); - -@ffi.Native Function(ffi.Pointer)>( - isLeaf: true) -external ffi.Pointer View_getRenderTarget( - ffi.Pointer tView, -); - -@ffi.Native, ffi.Bool)>(isLeaf: true) -external void View_setPostProcessing( - ffi.Pointer tView, - bool enabled, -); - -@ffi.Native, ffi.Bool)>(isLeaf: true) -external void View_setShadowsEnabled( - ffi.Pointer tView, - bool enabled, -); - -@ffi.Native, ffi.Int)>(isLeaf: true) -external void View_setShadowType( - ffi.Pointer tView, - int shadowType, -); - -@ffi.Native, ffi.Float, ffi.Float)>( - isLeaf: true) -external void View_setSoftShadowOptions( - ffi.Pointer tView, - double penumbraScale, - double penumbraRatioScale, -); - -@ffi.Native, ffi.Bool, ffi.Float)>( - isLeaf: true) -external void View_setBloom( - ffi.Pointer tView, - bool enabled, - double strength, -); - -@ffi.Native, ffi.UnsignedInt)>( - symbol: "View_setRenderQuality", isLeaf: true) -external void _View_setRenderQuality( - ffi.Pointer tView, - int qualityLevel, -); - -void View_setRenderQuality( - ffi.Pointer tView, - TQualityLevel qualityLevel, -) => - _View_setRenderQuality( - tView, - qualityLevel.value, - ); - -@ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Pointer, - ffi.UnsignedInt)>(symbol: "View_setToneMapping", isLeaf: true) -external void _View_setToneMapping( - ffi.Pointer tView, - ffi.Pointer tEngine, - int toneMapping, -); - -void View_setToneMapping( - ffi.Pointer tView, - ffi.Pointer tEngine, - TToneMapping toneMapping, -) => - _View_setToneMapping( - tView, - tEngine, - toneMapping.value, - ); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, ffi.Bool, ffi.Bool, ffi.Bool)>(isLeaf: true) -external void View_setAntiAliasing( - ffi.Pointer tView, - bool msaa, - bool fxaa, - bool taa, -); - -@ffi.Native, ffi.Int, ffi.Bool)>( - isLeaf: true) -external void View_setLayerEnabled( - ffi.Pointer tView, - int layer, - bool visible, -); - -@ffi.Native, ffi.Pointer)>( - isLeaf: true) -external void View_setCamera( - ffi.Pointer tView, - ffi.Pointer tCamera, -); - -@ffi.Native Function(ffi.Pointer)>(isLeaf: true) -external ffi.Pointer View_getScene( - ffi.Pointer tView, -); - -@ffi.Native Function(ffi.Pointer)>(isLeaf: true) -external ffi.Pointer View_getCamera( - ffi.Pointer tView, -); - -@ffi.Native, ffi.Bool)>(isLeaf: true) -external void View_setStencilBufferEnabled( - ffi.Pointer tView, - bool enabled, -); - -@ffi.Native)>(isLeaf: true) -external bool View_isStencilBufferEnabled( - ffi.Pointer tView, -); - -@ffi.Native, ffi.Bool)>(isLeaf: true) -external void View_setDitheringEnabled( - ffi.Pointer tView, - bool enabled, -); - -@ffi.Native)>(isLeaf: true) -external bool View_isDitheringEnabled( - ffi.Pointer tView, -); - -@ffi.Native, ffi.Pointer)>( - isLeaf: true) -external void View_setScene( - ffi.Pointer tView, - ffi.Pointer tScene, -); - -@ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Uint32, ffi.Uint32, ffi.Uint32, - PickCallback)>(isLeaf: true) -external void View_pick( - ffi.Pointer tView, - int requestId, - int x, - int y, - PickCallback callback, -); - -@ffi.Native Function()>(isLeaf: true) -external ffi.Pointer NameComponentManager_create(); - -@ffi.Native< - ffi.Pointer Function( - ffi.Pointer, EntityId)>(isLeaf: true) -external ffi.Pointer NameComponentManager_getName( - ffi.Pointer tNameComponentManager, - int entity, -); - -@ffi.Native< - ffi.Void Function( - ffi.Pointer, ffi.Pointer)>(isLeaf: true) -external void IndirectLight_setRotation( - ffi.Pointer tIndirectLight, - ffi.Pointer rotation, -); - @ffi.Native< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.UnsignedInt)>(symbol: "Gizmo_create", isLeaf: true) @@ -1999,9 +1993,8 @@ external void SceneAsset_destroyRenderThread( @ffi.Native< ffi.Void Function( - ffi.Pointer, - ffi.Pointer, ffi.Pointer, + ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Size, @@ -2011,9 +2004,8 @@ external void SceneAsset_destroyRenderThread( .NativeFunction)>>)>( isLeaf: true) external void SceneAsset_loadGlbRenderThread( - ffi.Pointer tAssetLoader, - ffi.Pointer tResourceLoader, ffi.Pointer tEngine, + ffi.Pointer tAssetLoader, ffi.Pointer tNameComponentManager, ffi.Pointer data, int length, @@ -2600,22 +2592,60 @@ external void GltfAssetLoader_createRenderThread( @ffi.Native< ffi.Void Function( ffi.Pointer, + ffi.Pointer, ffi.Pointer< ffi.NativeFunction< ffi.Void Function( ffi.Pointer)>>)>(isLeaf: true) external void GltfResourceLoader_createRenderThread( ffi.Pointer tEngine, + ffi.Pointer relativeResourcePath, ffi.Pointer< ffi .NativeFunction)>> callback, ); +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer>)>(isLeaf: true) +external void GltfResourceLoader_destroyRenderThread( + ffi.Pointer tEngine, + ffi.Pointer tResourceLoader, + ffi.Pointer> callback, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer>)>( + isLeaf: true) +external void GltfResourceLoader_loadResourcesRenderThread( + ffi.Pointer tGltfResourceLoader, + ffi.Pointer tFilamentAsset, + ffi.Pointer> callback, +); + @ffi.Native< ffi.Void Function( - ffi.Pointer, ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Size, + ffi.Pointer>)>(isLeaf: true) +external void GltfResourceLoader_addResourceDataRenderThread( + ffi.Pointer tGltfResourceLoader, + ffi.Pointer uri, + ffi.Pointer data, + int length, + ffi.Pointer> callback, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, ffi.Pointer, ffi.Size, ffi.Uint8, @@ -2623,8 +2653,8 @@ external void GltfResourceLoader_createRenderThread( ffi.NativeFunction< ffi.Void Function(ffi.Pointer)>>)>(isLeaf: true) external void GltfAssetLoader_loadRenderThread( + ffi.Pointer tEngine, ffi.Pointer tAssetLoader, - ffi.Pointer tResourceLoader, ffi.Pointer data, int length, int numInstances, @@ -2642,6 +2672,48 @@ external void Scene_addFilamentAssetRenderThread( ffi.Pointer> callback, ); +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer)>(isLeaf: true) +external ffi.Pointer GltfResourceLoader_create( + ffi.Pointer tEngine, + ffi.Pointer relativeResourcePath, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Pointer)>(isLeaf: true) +external void GltfResourceLoader_destroy( + ffi.Pointer tEngine, + ffi.Pointer tGltfResourceLoader, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, + ffi.Pointer)>(isLeaf: true) +external void GltfResourceLoader_asyncBeginLoad( + ffi.Pointer tGltfResourceLoader, + ffi.Pointer tFilamentAsset, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer, ffi.Size)>(isLeaf: true) +external void GltfResourceLoader_addResourceData( + ffi.Pointer tGltfResourceLoader, + ffi.Pointer uri, + ffi.Pointer data, + int length, +); + +@ffi.Native< + ffi.Bool Function(ffi.Pointer, + ffi.Pointer)>(isLeaf: true) +external bool GltfResourceLoader_loadResources( + ffi.Pointer tGltfResourceLoader, + ffi.Pointer tFilamentAsset, +); + @ffi.Native< ffi.Void Function(ffi.Pointer, EntityId, ffi.Int, ffi.Pointer)>(isLeaf: true) @@ -2987,17 +3059,15 @@ external ffi.Pointer SceneAsset_createGeometry( @ffi.Native< ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, ffi.Pointer, + ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Size, ffi.Size)>(isLeaf: true) external ffi.Pointer SceneAsset_loadGlb( - ffi.Pointer tAssetLoader, - ffi.Pointer tResourceLoader, ffi.Pointer tEngine, + ffi.Pointer tAssetLoader, ffi.Pointer tNameComponentManager, ffi.Pointer data, int length, @@ -3023,6 +3093,24 @@ external ffi.Pointer SceneAsset_loadGltf( int numInstances, ); +@ffi.Native)>(isLeaf: true) +external int SceneAsset_getResourceUriCount( + ffi.Pointer tSceneAsset, +); + +@ffi.Native< + ffi.Pointer> Function( + ffi.Pointer)>(isLeaf: true) +external ffi.Pointer> SceneAsset_getResourceUris( + ffi.Pointer tSceneAsset, +); + +@ffi.Native Function(ffi.Pointer)>( + isLeaf: true) +external ffi.Pointer SceneAsset_getFilamentAsset( + ffi.Pointer tSceneAsset, +); + @ffi.Native< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(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>; +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>; -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), diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart index 54c94030..ba8cd099 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart @@ -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 animationManager; - late final Future Function(String path) loadAsset; + late final Future 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((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((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 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((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 loadGltf(String path, String relativeResourcePath, - {bool keepData = false}) async { - throw UnimplementedError(); - // final pathPtr = path.toNativeUtf8(allocator: allocator).cast(); - // final relativeResourcePathPtr = - // relativeResourcePath.toNativeUtf8(allocator: allocator).cast(); - // var assetPtr = await withPointerCallback((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; } /// diff --git a/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart b/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart index 545b1b37..b2bb1442 100644 --- a/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart +++ b/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart @@ -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 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 loadGltf(String path, String relativeResourcePath, - {bool keepData = false}); + bool loadResourcesAsync = false, + String relativeResourcePath}); /// /// Destroys [asset] and all underlying resources diff --git a/thermion_dart/native/include/ThreadPool.hpp b/thermion_dart/native/include/ThreadPool.hpp deleted file mode 100644 index eb4bc07b..00000000 --- a/thermion_dart/native/include/ThreadPool.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * This file is licensed under the zlib/libpng license, included in this - * distribution in the file COPYING. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef _THREADPOOL_HPP -#define _THREADPOOL_HPP - -namespace thermion { - -class ThreadPool { - std::vector pool; - bool stop; - - std::mutex access; - std::condition_variable cond; - std::deque> tasks; - -public: - explicit ThreadPool(int nr = 1) : stop(false) { - while(nr-->0) { - add_worker(); - } - } - ~ThreadPool() { - stop = true; - for(std::thread &t : pool) { - t.join(); - } - pool.clear(); - } - - template - auto add_task(std::packaged_task& pt) -> std::future { - std::unique_lock lock(access); - - auto ret = pt.get_future(); - tasks.push_back([pt=std::make_shared>(std::move(pt))]{ (*pt)();}); - - cond.notify_one(); - - return ret; - } - -private: - void add_worker() { - std::thread t([this]() { - while(!stop || tasks.size() > 0) { - std::function task; - { - std::unique_lock lock(access); - if(tasks.empty()) { - cond.wait_for(lock, std::chrono::duration(5)); - continue; - } - task = std::move(tasks.front()); - tasks.pop_front(); - } - task(); - } - }); - pool.push_back(std::move(t)); - } -}; - -} - -#endif//_THREADPOOL_HPP - -// vim: syntax=cpp11 \ No newline at end of file diff --git a/thermion_dart/native/include/c_api/TGltfAssetLoader.h b/thermion_dart/native/include/c_api/TGltfAssetLoader.h index 89ee54d5..810f21c1 100644 --- a/thermion_dart/native/include/c_api/TGltfAssetLoader.h +++ b/thermion_dart/native/include/c_api/TGltfAssetLoader.h @@ -1,10 +1,7 @@ -#ifndef _T_GLTF_ASSET_LOADER_H -#define _T_GLTF_ASSET_LOADER_H +#pragma once #include "APIExport.h" #include "APIBoundaryTypes.h" -#include "TMaterialInstance.h" -#include "TTexture.h" #ifdef __cplusplus extern "C" @@ -12,10 +9,10 @@ extern "C" #endif EMSCRIPTEN_KEEPALIVE TGltfAssetLoader *GltfAssetLoader_create(TEngine *tEngine, TMaterialProvider *tMaterialProvider); -EMSCRIPTEN_KEEPALIVE TGltfResourceLoader *GltfResourceLoader_create(TEngine *tEngine); + EMSCRIPTEN_KEEPALIVE TFilamentAsset *GltfAssetLoader_load( + TEngine *tEngine, TGltfAssetLoader *tAssetLoader, - TGltfResourceLoader *tResourceLoader, uint8_t *data, size_t length, uint8_t numInstances @@ -27,4 +24,3 @@ EMSCRIPTEN_KEEPALIVE TMaterialProvider *GltfAssetLoader_getMaterialProvider(TGlt } #endif -#endif \ No newline at end of file diff --git a/thermion_dart/native/include/c_api/TGltfResourceLoader.h b/thermion_dart/native/include/c_api/TGltfResourceLoader.h new file mode 100644 index 00000000..51056f7b --- /dev/null +++ b/thermion_dart/native/include/c_api/TGltfResourceLoader.h @@ -0,0 +1,21 @@ +#pragma once + +#include "APIExport.h" +#include "APIBoundaryTypes.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +EMSCRIPTEN_KEEPALIVE TGltfResourceLoader *GltfResourceLoader_create(TEngine *tEngine, const char *relativeResourcePath); +EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_destroy(TEngine *tEngine, TGltfResourceLoader *tGltfResourceLoader); +EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_asyncBeginLoad(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset); +EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_addResourceData(TGltfResourceLoader *tGltfResourceLoader, const char *uri, uint8_t *data, size_t length); +EMSCRIPTEN_KEEPALIVE bool GltfResourceLoader_loadResources(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset); + + +#ifdef __cplusplus +} +#endif + diff --git a/thermion_dart/native/include/c_api/TSceneAsset.h b/thermion_dart/native/include/c_api/TSceneAsset.h index 185c9636..45b8aa6c 100644 --- a/thermion_dart/native/include/c_api/TSceneAsset.h +++ b/thermion_dart/native/include/c_api/TSceneAsset.h @@ -24,9 +24,8 @@ extern "C" ); EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_loadGlb( - TGltfAssetLoader *tAssetLoader, - TGltfResourceLoader *tResourceLoader, TEngine *tEngine, + TGltfAssetLoader *tAssetLoader, TNameComponentManager *tNameComponentManager, uint8_t *data, size_t length, @@ -43,6 +42,16 @@ extern "C" size_t numInstances ); + EMSCRIPTEN_KEEPALIVE int32_t SceneAsset_getResourceUriCount( + TSceneAsset *tSceneAsset + ); + + EMSCRIPTEN_KEEPALIVE const char* const* SceneAsset_getResourceUris( + TSceneAsset *tSceneAsset + ); + + EMSCRIPTEN_KEEPALIVE TFilamentAsset *SceneAsset_getFilamentAsset(TSceneAsset *tSceneAsset); + EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_createGrid(TEngine *tEngine, TMaterial * tMaterial); EMSCRIPTEN_KEEPALIVE void SceneAsset_destroy(TSceneAsset *tSceneAsset); diff --git a/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h b/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h index 79264ea0..a9e8bf51 100644 --- a/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h +++ b/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h @@ -85,9 +85,8 @@ namespace thermion EMSCRIPTEN_KEEPALIVE void SceneAsset_destroyRenderThread(TSceneAsset *tSceneAsset, void (*onComplete)()); EMSCRIPTEN_KEEPALIVE void SceneAsset_loadGlbRenderThread( - TGltfAssetLoader *tAssetLoader, - TGltfResourceLoader *tResourceLoader, TEngine *tEngine, + TGltfAssetLoader *tAssetLoader, TNameComponentManager *tNameComponentManager, uint8_t *data, size_t length, @@ -250,10 +249,14 @@ namespace thermion EMSCRIPTEN_KEEPALIVE void AnimationManager_resetToRestPoseRenderThread(TAnimationManager *tAnimationManager, EntityId entityId, void (*callback)()); EMSCRIPTEN_KEEPALIVE void GltfAssetLoader_createRenderThread(TEngine *tEngine, TMaterialProvider *tMaterialProvider, void (*callback)(TGltfAssetLoader *)); - EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_createRenderThread(TEngine *tEngine, void (*callback)(TGltfResourceLoader *)); + EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_createRenderThread(TEngine *tEngine, const char* relativeResourcePath, void (*callback)(TGltfResourceLoader *)); + EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_destroyRenderThread(TEngine *tEngine, TGltfResourceLoader *tResourceLoader, void (*callback)()); + EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_loadResourcesRenderThread(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset, void (*callback)(bool)); + EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_addResourceDataRenderThread(TGltfResourceLoader *tGltfResourceLoader, const char *uri, uint8_t *data, size_t length, void (*callback)()); + EMSCRIPTEN_KEEPALIVE void GltfAssetLoader_loadRenderThread( + TEngine *tEngine, TGltfAssetLoader *tAssetLoader, - TGltfResourceLoader *tResourceLoader, uint8_t *data, size_t length, uint8_t numInstances, diff --git a/thermion_dart/native/include/scene/GltfSceneAsset.hpp b/thermion_dart/native/include/scene/GltfSceneAsset.hpp index c22f61f2..eea3a5bc 100644 --- a/thermion_dart/native/include/scene/GltfSceneAsset.hpp +++ b/thermion_dart/native/include/scene/GltfSceneAsset.hpp @@ -41,7 +41,7 @@ namespace thermion _materialInstances(materialInstances), _materialInstanceCount(materialInstanceCount) { - TRACE("Created GltfSceneAsset with %d reserved instances", asset->getAssetInstanceCount()); + TRACE("Created GltfSceneAsset from FilamentAsset %d with %d reserved instances", asset, asset->getAssetInstanceCount()); } ~GltfSceneAsset(); diff --git a/thermion_dart/native/src/c_api/TGltfAssetLoader.cpp b/thermion_dart/native/src/c_api/TGltfAssetLoader.cpp index e44dddf9..57e8cbd3 100644 --- a/thermion_dart/native/src/c_api/TGltfAssetLoader.cpp +++ b/thermion_dart/native/src/c_api/TGltfAssetLoader.cpp @@ -33,18 +33,6 @@ namespace thermion #endif -EMSCRIPTEN_KEEPALIVE TGltfResourceLoader *GltfResourceLoader_create(TEngine *tEngine) { - auto *engine = reinterpret_cast(tEngine); - auto *gltfResourceLoader = new gltfio::ResourceLoader({.engine = engine, - .normalizeSkinningWeights = true}); - auto stbDecoder = gltfio::createStbProvider(engine); - auto ktxDecoder = gltfio::createKtx2Provider(engine); - gltfResourceLoader->addTextureProvider("image/ktx2", ktxDecoder); - gltfResourceLoader->addTextureProvider("image/png", stbDecoder); - gltfResourceLoader->addTextureProvider("image/jpeg", stbDecoder); - - return reinterpret_cast(gltfResourceLoader); -} EMSCRIPTEN_KEEPALIVE TGltfAssetLoader *GltfAssetLoader_create(TEngine *tEngine, TMaterialProvider *tMaterialProvider) { auto *engine = reinterpret_cast(tEngine); @@ -66,18 +54,23 @@ EMSCRIPTEN_KEEPALIVE TGltfAssetLoader *GltfAssetLoader_create(TEngine *tEngine, } EMSCRIPTEN_KEEPALIVE TFilamentAsset *GltfAssetLoader_load( + TEngine *tEngine, TGltfAssetLoader *tAssetLoader, - TGltfResourceLoader *tGltfResourceLoader, uint8_t *data, size_t length, uint8_t numInstances) { + auto *engine = reinterpret_cast(tEngine); auto *assetLoader = reinterpret_cast(tAssetLoader); - auto *resourceLoader = reinterpret_cast(tGltfResourceLoader); - std::vector instances(numInstances); + gltfio::FilamentAsset *asset; - gltfio::FilamentAsset *asset = assetLoader->createInstancedAsset((const uint8_t *)data, length, instances.data(), numInstances); + if(numInstances > 1) { + std::vector instances(numInstances); + asset = assetLoader->createInstancedAsset((const uint8_t *)data, length, instances.data(), numInstances); + } else { + asset = assetLoader->createAsset((const uint8_t *)data, length); + } if (!asset) { @@ -85,11 +78,15 @@ EMSCRIPTEN_KEEPALIVE TFilamentAsset *GltfAssetLoader_load( return std::nullptr_t(); } - if (!resourceLoader->loadResources(asset)) - { - Log("Unknown error loading glb asset"); - return std::nullptr_t(); + const char *const *const resourceUris = asset->getResourceUris(); + const size_t resourceUriCount = asset->getResourceUriCount(); + + Log("glTF asset : %d resource URIs, %d instances", resourceUriCount, numInstances); + + for(int i = 0; i < resourceUriCount; i++) { + Log("%s", resourceUris[i]); } + return reinterpret_cast(asset); } diff --git a/thermion_dart/native/src/c_api/TGltfResourceLoader.cpp b/thermion_dart/native/src/c_api/TGltfResourceLoader.cpp new file mode 100644 index 00000000..d3eaa96a --- /dev/null +++ b/thermion_dart/native/src/c_api/TGltfResourceLoader.cpp @@ -0,0 +1,75 @@ +#include "c_api/TGltfResourceLoader.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "Log.hpp" + +#ifdef __cplusplus +namespace thermion +{ + extern "C" + { + using namespace filament; + +#endif + +EMSCRIPTEN_KEEPALIVE TGltfResourceLoader *GltfResourceLoader_create(TEngine *tEngine, const char *relativeResourcePath) { + auto *engine = reinterpret_cast(tEngine); + auto *gltfResourceLoader = new gltfio::ResourceLoader({ + .engine = engine, + .gltfPath = relativeResourcePath + }); + auto stbDecoder = gltfio::createStbProvider(engine); + auto ktxDecoder = gltfio::createKtx2Provider(engine); + gltfResourceLoader->addTextureProvider("image/ktx2", ktxDecoder); + gltfResourceLoader->addTextureProvider("image/png", stbDecoder); + gltfResourceLoader->addTextureProvider("image/jpeg", stbDecoder); + + return reinterpret_cast(gltfResourceLoader); +} + +EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_destroy(TEngine *tEngine, TGltfResourceLoader *tGltfResourceLoader) { + auto *gltfResourceLoader = reinterpret_cast(tGltfResourceLoader); + delete gltfResourceLoader; +} + +EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_addResourceData(TGltfResourceLoader *tGltfResourceLoader, const char *uri, uint8_t *data, size_t length) { + TRACE("Adding data (length %d) for glTF resource URI %s", length, uri); + auto *gltfResourceLoader = reinterpret_cast(tGltfResourceLoader); + for(int i = 0; i < 8; i++) { + std::cout << static_cast(data[i]) << " "; + } + std::cout << std::endl; + gltfResourceLoader->addResourceData(uri, { data, length}); +} + +EMSCRIPTEN_KEEPALIVE bool GltfResourceLoader_loadResources(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset) { + auto *gltfResourceLoader = reinterpret_cast(tGltfResourceLoader); + auto *filamentAsset = reinterpret_cast(tFilamentAsset); + return gltfResourceLoader->loadResources(filamentAsset); +} + +#ifdef __cplusplus + } +} +#endif diff --git a/thermion_dart/native/src/c_api/TSceneAsset.cpp b/thermion_dart/native/src/c_api/TSceneAsset.cpp index cc0890ff..9926989d 100644 --- a/thermion_dart/native/src/c_api/TSceneAsset.cpp +++ b/thermion_dart/native/src/c_api/TSceneAsset.cpp @@ -67,9 +67,8 @@ extern "C" } EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_loadGlb( - TGltfAssetLoader *tAssetLoader, - TGltfResourceLoader *tResourceLoader, TEngine *tEngine, + TGltfAssetLoader *tAssetLoader, TNameComponentManager *tNameComponentManager, uint8_t *data, size_t length, @@ -77,20 +76,61 @@ extern "C" ) { auto *engine = reinterpret_cast(tEngine); auto *nameComponentManager = reinterpret_cast(tNameComponentManager); - auto *tFilamentAsset = GltfAssetLoader_load(tAssetLoader, tResourceLoader, data, length, numInstances); + auto *tFilamentAsset = GltfAssetLoader_load(tEngine, tAssetLoader, data, length, numInstances); auto *filamentAsset = reinterpret_cast(tFilamentAsset); + auto *assetLoader = reinterpret_cast(tAssetLoader); - auto *resourceLoader = reinterpret_cast(tResourceLoader); auto *sceneAsset = new GltfSceneAsset( filamentAsset, assetLoader, engine, nameComponentManager ); - return reinterpret_cast(sceneAsset); - + + return reinterpret_cast(sceneAsset); } + + EMSCRIPTEN_KEEPALIVE int32_t SceneAsset_getResourceUriCount( + TSceneAsset *tSceneAsset + ) { + auto sceneAsset = reinterpret_cast(tSceneAsset); + if(sceneAsset->getType() != SceneAsset::SceneAssetType::Gltf) { + Log("Error - not a gltf asset"); + return -1; + } + auto gltfAsset = reinterpret_cast(tSceneAsset); + auto *filamentAsset = gltfAsset->getAsset(); + return filamentAsset->getResourceUriCount(); + } + + EMSCRIPTEN_KEEPALIVE const char* const* SceneAsset_getResourceUris( + TSceneAsset *tSceneAsset + ) { + auto sceneAsset = reinterpret_cast(tSceneAsset); + if(sceneAsset->getType() != SceneAsset::SceneAssetType::Gltf) { + Log("Error - not a gltf asset"); + return nullptr; + } + auto gltfAsset = reinterpret_cast(tSceneAsset); + auto *filamentAsset = gltfAsset->getAsset(); + return filamentAsset->getResourceUris(); + } + + EMSCRIPTEN_KEEPALIVE TFilamentAsset *SceneAsset_getFilamentAsset(TSceneAsset *tSceneAsset) { + auto sceneAsset = reinterpret_cast(tSceneAsset); + if(sceneAsset->getType() != SceneAsset::SceneAssetType::Gltf) { + Log("Error - not a gltf asset"); + return nullptr; + } + + auto gltfAsset = reinterpret_cast(tSceneAsset); + auto *filamentAsset = gltfAsset->getAsset(); + TRACE("SceneAsset %d FilamentAsset %d", sceneAsset, filamentAsset); + return reinterpret_cast(filamentAsset); + } + + EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_createGrid(TEngine *tEngine, TMaterial* tMaterial) { auto *engine = reinterpret_cast(tEngine); auto *material = reinterpret_cast(tMaterial); diff --git a/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp b/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp index 77eab3fa..4a9ce676 100644 --- a/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp +++ b/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp @@ -9,6 +9,7 @@ #include "c_api/TAnimationManager.h" #include "c_api/TEngine.h" #include "c_api/TGltfAssetLoader.h" +#include "c_api/TGltfResourceLoader.h" #include "c_api/TRenderer.h" #include "c_api/TRenderTicker.h" #include "c_api/TRenderTarget.h" @@ -18,12 +19,9 @@ #include "c_api/TView.h" #include "c_api/ThermionDartRenderThreadApi.h" - #include "rendering/RenderLoop.hpp" #include "Log.hpp" -#include "ThreadPool.hpp" - using namespace thermion; using namespace std::chrono_literals; #include @@ -360,9 +358,8 @@ extern "C" } EMSCRIPTEN_KEEPALIVE void SceneAsset_loadGlbRenderThread( - TGltfAssetLoader *tAssetLoader, - TGltfResourceLoader *tResourceLoader, TEngine *tEngine, + TGltfAssetLoader *tAssetLoader, TNameComponentManager *tNameComponentManager, uint8_t *data, size_t length, @@ -372,7 +369,7 @@ extern "C" std::packaged_task lambda( [=] { - auto sceneAsset = SceneAsset_loadGlb(tAssetLoader, tResourceLoader, tEngine, tNameComponentManager, data, length, numInstances); + auto sceneAsset = SceneAsset_loadGlb(tEngine, tAssetLoader, tNameComponentManager, data, length, numInstances); callback(sceneAsset); }); auto fut = _rl->add_task(lambda); @@ -875,19 +872,54 @@ extern "C" auto fut = _rl->add_task(lambda); } - EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_createRenderThread(TEngine *tEngine, void (*callback)(TGltfResourceLoader *)) { + EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_createRenderThread(TEngine *tEngine, const char* relativeResourcePath, void (*callback)(TGltfResourceLoader *)) { std::packaged_task lambda( [=]() mutable { - auto loader = GltfResourceLoader_create(tEngine); + auto loader = GltfResourceLoader_create(tEngine, relativeResourcePath); callback(loader); }); auto fut = _rl->add_task(lambda); } + + EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_destroyRenderThread(TEngine *tEngine, TGltfResourceLoader *tResourceLoader, void (*callback)()) { + std::packaged_task lambda( + [=]() mutable + { + GltfResourceLoader_destroy(tEngine, tResourceLoader); + callback(); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_loadResourcesRenderThread(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset, void (*callback)(bool)) { + std::packaged_task lambda( + [=]() mutable + { + auto result = GltfResourceLoader_loadResources(tGltfResourceLoader, tFilamentAsset); + callback(result); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_addResourceDataRenderThread( + TGltfResourceLoader *tGltfResourceLoader, + const char *uri, + uint8_t *data, + size_t length, + void (*callback)()) { + std::packaged_task lambda( + [=]() mutable + { + GltfResourceLoader_addResourceData(tGltfResourceLoader, uri, data, length); + callback(); + }); + auto fut = _rl->add_task(lambda); + } EMSCRIPTEN_KEEPALIVE void GltfAssetLoader_loadRenderThread( + TEngine *tEngine, TGltfAssetLoader *tAssetLoader, - TGltfResourceLoader *tResourceLoader, uint8_t *data, size_t length, uint8_t numInstances, @@ -896,7 +928,7 @@ extern "C" std::packaged_task lambda( [=]() mutable { - auto loader = GltfAssetLoader_load(tAssetLoader, tResourceLoader, data, length, numInstances); + auto loader = GltfAssetLoader_load(tEngine, tAssetLoader, data, length, numInstances); callback(loader); }); auto fut = _rl->add_task(lambda);