diff --git a/thermion_dart/lib/src/filament/src/implementation/ffi_filament_app.dart b/thermion_dart/lib/src/filament/src/implementation/ffi_filament_app.dart index c15ff593..3aa88700 100644 --- a/thermion_dart/lib/src/filament/src/implementation/ffi_filament_app.dart +++ b/thermion_dart/lib/src/filament/src/implementation/ffi_filament_app.dart @@ -890,7 +890,7 @@ class FFIFilamentApp extends FilamentApp { /// Future loadGltfFromBuffer( Uint8List data, Pointer animationManager, - {int numInstances = 1, + {int initialInstances = 1, bool keepData = false, int priority = 4, int layer = 0, @@ -914,7 +914,7 @@ class FFIFilamentApp extends FilamentApp { var filamentAsset = await withPointerCallback((cb) => GltfAssetLoader_loadRenderThread(engine, gltfAssetLoader, - data.address, data.length, numInstances, cb)); + data.address, data.length, initialInstances, cb)); if (filamentAsset == nullptr) { throw Exception("An error occurred loading the asset"); diff --git a/thermion_dart/lib/src/filament/src/interface/asset.dart b/thermion_dart/lib/src/filament/src/interface/asset.dart index dfdf86b3..596109a2 100644 --- a/thermion_dart/lib/src/filament/src/interface/asset.dart +++ b/thermion_dart/lib/src/filament/src/interface/asset.dart @@ -6,7 +6,6 @@ import 'package:thermion_dart/src/filament/src/interface/scene.dart'; import 'package:thermion_dart/thermion_dart.dart'; export 'geometry.dart'; -export 'gltf.dart'; /// /// A high-level interface for a renderable object diff --git a/thermion_dart/lib/src/filament/src/interface/filament_app.dart b/thermion_dart/lib/src/filament/src/interface/filament_app.dart index 5e9d8365..c2bf2e48 100644 --- a/thermion_dart/lib/src/filament/src/interface/filament_app.dart +++ b/thermion_dart/lib/src/filament/src/interface/filament_app.dart @@ -291,11 +291,11 @@ abstract class FilamentApp { Future setClearOptions(double r, double g, double b, double a, {int clearStencil = 0, bool discard = false, bool clear = true}); - /// + /// See [FilamentViewerFFI.loadGltf] for details. /// /// Future loadGltfFromBuffer(Uint8List data, T animationManager, - {int numInstances = 1, + {int initialInstances = 1, bool keepData = false, int priority = 4, int layer = 0, diff --git a/thermion_dart/lib/src/filament/src/interface/gltf.dart b/thermion_dart/lib/src/filament/src/interface/gltf.dart deleted file mode 100644 index 1189c38e..00000000 --- a/thermion_dart/lib/src/filament/src/interface/gltf.dart +++ /dev/null @@ -1,6 +0,0 @@ -class GLTF { - final String uri; - final int numInstances; - - GLTF(this.uri, this.numInstances); -} 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 d43d3c40..c81bba43 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 @@ -457,7 +457,7 @@ class ThermionViewerFFI extends ThermionViewer { Future loadGltf( String path, { bool addToScene = true, - int numInstances = 1, + int initialInstances = 1, bool keepData = false, String? resourceUri, bool loadAsync = false, @@ -475,7 +475,7 @@ class ThermionViewerFFI extends ThermionViewer { return loadGltfFromBuffer( data, addToScene: addToScene, - numInstances: numInstances, + initialInstances: initialInstances, keepData: keepData, resourceUri: resourceUri, loadResourcesAsync: loadAsync, @@ -489,7 +489,7 @@ class ThermionViewerFFI extends ThermionViewer { Future loadGltfFromBuffer( Uint8List data, { bool addToScene = true, - int numInstances = 1, + int initialInstances = 1, bool keepData = false, int priority = 4, int layer = 0, @@ -499,7 +499,7 @@ class ThermionViewerFFI extends ThermionViewer { var asset = await FilamentApp.instance!.loadGltfFromBuffer( data, animationManager, - numInstances: numInstances, + initialInstances: initialInstances, keepData: keepData, priority: priority, layer: layer, 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 02fafb09..97f9ca47 100644 --- a/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart +++ b/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart @@ -151,37 +151,38 @@ abstract class ThermionViewer { /// If [addToScene] is [true], all renderable entities (including lights) /// in the asset will be added to the scene. /// - /// If you want to dynamically create instances of this asset after it is - /// instantiated, pass [kee] - - /// Alternatively, specifying [numInstances] will pre-allocate the specified - /// number of instances. This is more efficient than dynamically instantating at a later time. - /// You can then retrieve the created instances with [getInstances]. - /// - /// If [keepData] is false and [numInstances] is 1, - /// the source glTF data will be released and [createInstance] - /// will throw an exception. + /// The [initialInstances] argument determines the number of + /// instances created when the asset is first instantiated. If [keepData] is + /// false, no further instances will be able to be created. + /// + /// If [keepData] is true, additional instances can be created by calling + /// [createInstance] on the returned asset. + /// + /// Creating instances at asset load time is more efficient than dynamically + /// instantating at a later time. /// + /// Instances can be retrieved with [getInstances]. + /// + /// If [loadResourcesAsync] is true, resources (textures, materials, etc) will + /// be loaded asynchronously. Some material/texture pop-in is expected. /// Future loadGltf(String uri, {bool addToScene = true, - int numInstances = 1, + int initialInstances = 1, bool keepData = false, String? resourceUri, bool loadAsync = false}); /// - /// Load the .glb asset from the specified buffer, adding all entities to the scene. - /// Specify [numInstances] to create multiple instances (this is more efficient than dynamically instantating at a later time). You can then retrieve the created instances with [getInstances]. - /// If you want to be able to call [createInstance] at a later time, you must pass true for [keepData]. - /// If [keepData] is false, the source glTF data will be released and [createInstance] will throw an exception. - /// If [loadResourcesAsync] is true, resources (textures, materials, etc) will - /// be loaded asynchronously (so expect some material/texture pop-in); + /// Loads a gltf asset from the specified buffer (which contains the contents + /// of a .glb file). + /// + /// See the [loadGltf] method for documentation on arguments. /// /// Future loadGltfFromBuffer(Uint8List data, {String? resourceUri, - int numInstances = 1, + int initialInstances = 1, bool keepData = false, int priority = 4, int layer = 0, diff --git a/thermion_dart/native/include/scene/GltfSceneAsset.hpp b/thermion_dart/native/include/scene/GltfSceneAsset.hpp index e6dccdae..169ce9e6 100644 --- a/thermion_dart/native/include/scene/GltfSceneAsset.hpp +++ b/thermion_dart/native/include/scene/GltfSceneAsset.hpp @@ -33,8 +33,7 @@ namespace thermion Engine *engine, utils::NameComponentManager* ncm, MaterialInstance **materialInstances = nullptr, - size_t materialInstanceCount = 0, - int instanceIndex = 0); + size_t materialInstanceCount = 0); ~GltfSceneAsset(); diff --git a/thermion_dart/native/src/scene/GltfSceneAsset.cpp b/thermion_dart/native/src/scene/GltfSceneAsset.cpp index 8e1a5a06..78f59bee 100644 --- a/thermion_dart/native/src/scene/GltfSceneAsset.cpp +++ b/thermion_dart/native/src/scene/GltfSceneAsset.cpp @@ -33,15 +33,16 @@ namespace thermion Engine *engine, utils::NameComponentManager* ncm, MaterialInstance **materialInstances, - size_t materialInstanceCount, - int instanceIndex) : _asset(asset), + size_t materialInstanceCount) : _asset(asset), _assetLoader(assetLoader), _engine(engine), _ncm(ncm), _materialInstances(materialInstances), _materialInstanceCount(materialInstanceCount) { - createInstance(); + for(int i = 0; i < asset->getAssetInstanceCount(); i++) { + createInstance(); + } TRACE("Created GltfSceneAsset from FilamentAsset %d with %d reserved instances", asset, asset->getAssetInstanceCount()); } diff --git a/thermion_dart/test/instancing_tests.dart b/thermion_dart/test/instancing_tests.dart index a31dfc11..c1ab6d4b 100644 --- a/thermion_dart/test/instancing_tests.dart +++ b/thermion_dart/test/instancing_tests.dart @@ -56,11 +56,20 @@ void main() async { }, bg: kRed); }); - test('gltf assets always create one instance', () async { + test('gltf assets are created with initialInstances instances', () async { await testHelper.withViewer((viewer) async { - var asset = - await viewer.loadGltf("file://${testHelper.testDir}/assets/cube.glb"); + var asset = await viewer.loadGltf( + "file://${testHelper.testDir}/assets/cube.glb", + initialInstances: 1); expect(await asset.getInstanceCount(), 1); + + asset = await viewer.loadGltf( + "file://${testHelper.testDir}/assets/cube.glb", + initialInstances: 2); + expect(await asset.getInstanceCount(), 2); + + await expectLater(asset.createInstance(), throwsA(isA())); + }); }); @@ -77,11 +86,12 @@ void main() async { var asset = await viewer.loadGltf( "file://${testHelper.testDir}/assets/cube.glb", addToScene: false, - numInstances: 2, keepData: true); + initialInstances: 2, + keepData: true); var defaultInstance = await asset.getInstance(0); await viewer.addToScene(defaultInstance); await testHelper.capture(viewer.view, "gltf_without_instance"); - + var instance = await asset.createInstance(); await instance.setTransform(Matrix4.translation(Vector3(1, 0, 0))); await testHelper.capture(viewer.view, "gltf_instance_created"); @@ -91,13 +101,12 @@ void main() async { await testHelper.capture(viewer.view, "gltf_instance_remove_from_scene"); // above, we pre-allocated two instances and have used all of them - // calling createInstance now will still create another instance, but will be slower than allocating. + // calling createInstance now will still create another instance, but + // will be slower than specifying initialInstances on load. var instance2 = await asset.createInstance(); await instance2.setTransform(Matrix4.translation(Vector3(-1, 0, 0))); await viewer.addToScene(instance2); await testHelper.capture(viewer.view, "gltf_instance2_add_to_scene"); - - }, addSkybox: true); });