fix instancing so that gltf assets always fill the first instance slot

This commit is contained in:
Nick Fisher
2025-03-28 13:06:36 +08:00
parent a79e1a86f8
commit ecb8d8672a
13 changed files with 206 additions and 186 deletions

View File

@@ -749,16 +749,16 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
(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));
var filamentAsset = await withPointerCallback<TFilamentAsset>((cb) =>
GltfAssetLoader_loadRenderThread(engine, gltfAssetLoader, data.address,
data.length, numInstances, cb));
if (asset == nullptr) {
if (filamentAsset == nullptr) {
throw Exception("An error occurred loading the asset");
}
var resourceUris = SceneAsset_getResourceUris(asset);
var resourceUriCount = SceneAsset_getResourceUriCount(asset);
var resourceUris = FilamentAsset_getResourceUris(filamentAsset);
var resourceUriCount = FilamentAsset_getResourceUriCount(filamentAsset);
final resources = <FinalizableUint8List>[];
for (int i = 0; i < resourceUriCount; i++) {
@@ -782,10 +782,6 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
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));
@@ -794,6 +790,10 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
}
}
final asset = await withPointerCallback<TSceneAsset>((cb) =>
SceneAsset_createFromFilamentAssetRenderThread(
engine, gltfAssetLoader, nameComponentManager, filamentAsset, cb));
await withVoidCallback((cb) =>
GltfResourceLoader_destroyRenderThread(engine, gltfResourceLoader, cb));
return FFIAsset(asset, this, animationManager.cast<TAnimationManager>());

View File

@@ -473,6 +473,18 @@ external ffi.Pointer<TMaterialProvider> GltfAssetLoader_getMaterialProvider(
ffi.Pointer<TGltfAssetLoader> tAssetLoader,
);
@ffi.Native<ffi.Int32 Function(ffi.Pointer<TFilamentAsset>)>(isLeaf: true)
external int FilamentAsset_getResourceUriCount(
ffi.Pointer<TFilamentAsset> tFilamentAsset,
);
@ffi.Native<
ffi.Pointer<ffi.Pointer<ffi.Char>> Function(
ffi.Pointer<TFilamentAsset>)>(isLeaf: true)
external ffi.Pointer<ffi.Pointer<ffi.Char>> FilamentAsset_getResourceUris(
ffi.Pointer<TFilamentAsset> tFilamentAsset,
);
@ffi.Native<TViewport Function(ffi.Pointer<TView>)>(isLeaf: true)
external TViewport View_getViewport(
ffi.Pointer<TView> view,
@@ -2111,22 +2123,18 @@ external void SceneAsset_destroyRenderThread(
ffi.Pointer<TEngine>,
ffi.Pointer<TGltfAssetLoader>,
ffi.Pointer<TNameComponentManager>,
ffi.Pointer<ffi.Uint8>,
ffi.Size,
ffi.Size,
ffi.Pointer<TFilamentAsset>,
ffi.Pointer<
ffi
.NativeFunction<ffi.Void Function(ffi.Pointer<TSceneAsset>)>>)>(
isLeaf: true)
external void SceneAsset_loadGlbRenderThread(
external void SceneAsset_createFromFilamentAssetRenderThread(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TGltfAssetLoader> tAssetLoader,
ffi.Pointer<TNameComponentManager> tNameComponentManager,
ffi.Pointer<ffi.Uint8> data,
int length,
int numInstances,
ffi.Pointer<TFilamentAsset> tFilamentAsset,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<TSceneAsset>)>>
callback,
onComplete,
);
@ffi.Native<
@@ -3234,47 +3242,12 @@ external ffi.Pointer<TSceneAsset> SceneAsset_createGeometry(
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<TFilamentAsset>)>(isLeaf: true)
external ffi.Pointer<TSceneAsset> SceneAsset_createFromFilamentAsset(
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TGltfAssetLoader> tAssetLoader,
ffi.Pointer<TNameComponentManager> tNameComponentManager,
ffi.Pointer<ffi.Uint8> data,
int length,
int numInstances,
);
@ffi.Native<
ffi.Pointer<TSceneAsset> Function(
ffi.Pointer<TGltfAssetLoader>,
ffi.Pointer<TGltfResourceLoader>,
ffi.Pointer<TEngine>,
ffi.Pointer<TNameComponentManager>,
ffi.Pointer<ffi.Uint8>,
ffi.Size,
ffi.Size)>(isLeaf: true)
external ffi.Pointer<TSceneAsset> SceneAsset_loadGltf(
ffi.Pointer<TGltfAssetLoader> tAssetLoader,
ffi.Pointer<TGltfResourceLoader> tResourceLoader,
ffi.Pointer<TEngine> tEngine,
ffi.Pointer<TNameComponentManager> tNameComponentManager,
ffi.Pointer<ffi.Uint8> data,
int length,
int numInstances,
);
@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.Pointer<TFilamentAsset> tFilamentAsset,
);
@ffi.Native<ffi.Pointer<TFilamentAsset> Function(ffi.Pointer<TSceneAsset>)>(

View File

@@ -20,6 +20,14 @@ EMSCRIPTEN_KEEPALIVE TFilamentAsset *GltfAssetLoader_load(
EMSCRIPTEN_KEEPALIVE TMaterialInstance *GltfAssetLoader_getMaterialInstance(TRenderableManager *tRenderableManager, TFilamentAsset *tAsset);
EMSCRIPTEN_KEEPALIVE TMaterialProvider *GltfAssetLoader_getMaterialProvider(TGltfAssetLoader *tAssetLoader);
EMSCRIPTEN_KEEPALIVE int32_t FilamentAsset_getResourceUriCount(
TFilamentAsset *tFilamentAsset
);
EMSCRIPTEN_KEEPALIVE const char* const* FilamentAsset_getResourceUris(
TFilamentAsset *tFilamentAsset
);
#ifdef __cplusplus
}
#endif

View File

@@ -22,38 +22,14 @@ extern "C"
TMaterialInstance **materialInstances,
int materialInstanceCount
);
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_loadGlb(
EMSCRIPTEN_KEEPALIVE TSceneAsset * SceneAsset_createFromFilamentAsset(
TEngine *tEngine,
TGltfAssetLoader *tAssetLoader,
TNameComponentManager *tNameComponentManager,
const uint8_t *data,
size_t length,
size_t numInstances
TFilamentAsset *tFilamentAsset
);
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_loadGltf(
TGltfAssetLoader *tAssetLoader,
TGltfResourceLoader *tResourceLoader,
TEngine *tEngine,
TNameComponentManager *tNameComponentManager,
const uint8_t *data,
size_t length,
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);
EMSCRIPTEN_KEEPALIVE void SceneAsset_addToScene(TSceneAsset *tSceneAsset, TScene *tScene);
EMSCRIPTEN_KEEPALIVE void SceneAsset_removeFromScene(TSceneAsset *tSceneAsset, TScene *tScene);
@@ -68,8 +44,7 @@ extern "C"
EMSCRIPTEN_KEEPALIVE size_t SceneAsset_getInstanceCount(TSceneAsset *tSceneAsset);
EMSCRIPTEN_KEEPALIVE TSceneAsset * SceneAsset_createInstance(TSceneAsset *asset, TMaterialInstance **materialInstances, int materialInstanceCount);
EMSCRIPTEN_KEEPALIVE Aabb3 SceneAsset_getBoundingBox(TSceneAsset *asset);
EMSCRIPTEN_KEEPALIVE Aabb3 SceneAsset_getBoundingBox(TSceneAsset *asset);
#ifdef __cplusplus
}
#endif

View File

@@ -92,14 +92,12 @@ namespace thermion
FilamentRenderCallback make_render_callback_fn_pointer(FilamentRenderCallback);
EMSCRIPTEN_KEEPALIVE void SceneAsset_destroyRenderThread(TSceneAsset *tSceneAsset, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void SceneAsset_loadGlbRenderThread(
EMSCRIPTEN_KEEPALIVE void SceneAsset_createFromFilamentAssetRenderThread(
TEngine *tEngine,
TGltfAssetLoader *tAssetLoader,
TNameComponentManager *tNameComponentManager,
uint8_t *data,
size_t length,
size_t numInstances,
void (*callback)(TSceneAsset *)
TFilamentAsset *tFilamentAsset,
void (*onComplete)(TSceneAsset *)
);
EMSCRIPTEN_KEEPALIVE void SceneAsset_createInstanceRenderThread(TSceneAsset *asset, TMaterialInstance **tMaterialInstances, int materialInstanceCount, void (*callback)(TSceneAsset *));
EMSCRIPTEN_KEEPALIVE void SceneAsset_createGeometryRenderThread(

View File

@@ -27,6 +27,7 @@ namespace thermion
class GltfSceneAsset : public SceneAsset
{
public:
GltfSceneAsset(
gltfio::FilamentAsset *asset,
gltfio::AssetLoader *assetLoader,
@@ -34,25 +35,13 @@ namespace thermion
utils::NameComponentManager* ncm,
MaterialInstance **materialInstances = nullptr,
size_t materialInstanceCount = 0,
int instanceIndex = -1) : _asset(asset),
_assetLoader(assetLoader),
_engine(engine),
_ncm(ncm),
_materialInstances(materialInstances),
_materialInstanceCount(materialInstanceCount)
{
TRACE("Created GltfSceneAsset from FilamentAsset %d with %d reserved instances", asset, asset->getAssetInstanceCount());
}
int instanceIndex = 0);
~GltfSceneAsset();
SceneAsset *createInstance(MaterialInstance **materialInstances = nullptr, size_t materialInstanceCount = 0) override;
void destroyInstance(SceneAsset *asset) override {
auto it = std::remove_if(_instances.begin(), _instances.end(), [=](auto &sceneAsset)
{ return sceneAsset.get() == asset; });
_instances.erase(it, _instances.end());
};
void destroyInstance(SceneAsset *asset) override;
SceneAssetType getType() override
{

View File

@@ -3,7 +3,6 @@
#include <memory>
#include <filament/Scene.h>
#include <gltfio/FilamentAsset.h>
#include <math.h>
#include <utils/Entity.h>

View File

@@ -4,6 +4,7 @@
#include "c_api/TGizmo.h"
#include "c_api/TSceneAsset.h"
#include "c_api/TGltfAssetLoader.h"
#include "scene/Gizmo.hpp"
#include "scene/GltfSceneAsset.hpp"
#include "resources/translation_gizmo_glb.h"
@@ -20,56 +21,59 @@ namespace thermion
EMSCRIPTEN_KEEPALIVE TGizmo *Gizmo_create(
TEngine *tEngine,
TGltfAssetLoader *assetLoader,
TGltfAssetLoader *tAssetLoader,
TGltfResourceLoader *tGltfResourceLoader,
TNameComponentManager *tNameComponentManager,
TView *tView,
TMaterial *tMaterial,
TGizmoType tGizmoType) {
TGizmoType tGizmoType)
{
auto *engine = reinterpret_cast<Engine *>(tEngine);
auto *view = reinterpret_cast<View *>(tView);
auto *material = reinterpret_cast<Material *>(tMaterial);
auto *gltfResourceLoader = reinterpret_cast<gltfio::ResourceLoader *>(tGltfResourceLoader);
TSceneAsset *sceneAsset;
const uint8_t *data;
size_t size;
switch (tGizmoType)
{
case GIZMO_TYPE_TRANSLATION:
{
{
TRACE("Building translation gizmo");
sceneAsset = SceneAsset_loadGlb(
tEngine,
assetLoader,
tNameComponentManager,
TRANSLATION_GIZMO_GLB_TRANSLATION_GIZMO_DATA,
TRANSLATION_GIZMO_GLB_TRANSLATION_GIZMO_SIZE,
3
);
data = TRANSLATION_GIZMO_GLB_TRANSLATION_GIZMO_DATA;
size = TRANSLATION_GIZMO_GLB_TRANSLATION_GIZMO_SIZE;
break;
}
case GIZMO_TYPE_ROTATION:
{
TRACE("Building rotation gizmo");
sceneAsset = SceneAsset_loadGlb(
tEngine,
assetLoader,
tNameComponentManager,
ROTATION_GIZMO_GLB_ROTATION_GIZMO_DATA,
ROTATION_GIZMO_GLB_ROTATION_GIZMO_SIZE,
3
);
break;
}
}
case GIZMO_TYPE_ROTATION:
{
TRACE("Building rotation gizmo");
data = ROTATION_GIZMO_GLB_ROTATION_GIZMO_DATA;
size = ROTATION_GIZMO_GLB_ROTATION_GIZMO_SIZE;
break;
}
}
auto *tFilamentAsset = GltfAssetLoader_load(
tEngine,
tAssetLoader,
data,
size,
3);
auto *filamentAsset = reinterpret_cast<gltfio::FilamentAsset *>(tFilamentAsset);
auto *sceneAsset = SceneAsset_createFromFilamentAsset(
tEngine,
tAssetLoader,
tNameComponentManager,
tFilamentAsset);
auto *gltfSceneAsset = reinterpret_cast<GltfSceneAsset *>(sceneAsset);
auto *filamentAsset = gltfSceneAsset->getAsset();
gltfResourceLoader->loadResources(filamentAsset);
auto *gizmo = new Gizmo(
gltfSceneAsset,
engine,
view,
material
);
gltfSceneAsset,
engine,
view,
material);
return reinterpret_cast<TGizmo *>(gizmo);
}

View File

@@ -114,6 +114,20 @@ EMSCRIPTEN_KEEPALIVE TMaterialProvider *GltfAssetLoader_getMaterialProvider(TGlt
return reinterpret_cast<TMaterialProvider *>(&materialProvider);
}
EMSCRIPTEN_KEEPALIVE int32_t FilamentAsset_getResourceUriCount(
TFilamentAsset *tFilamentAsset
) {
auto *filamentAsset = reinterpret_cast<gltfio::FilamentAsset *>(tFilamentAsset);
return filamentAsset->getResourceUriCount();
}
EMSCRIPTEN_KEEPALIVE const char* const* FilamentAsset_getResourceUris(
TFilamentAsset *tFilamentAsset
) {
auto *filamentAsset = reinterpret_cast<gltfio::FilamentAsset *>(tFilamentAsset);
return filamentAsset->getResourceUris();
}
#ifdef __cplusplus
}
}

View File

@@ -66,17 +66,14 @@ extern "C"
}
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_loadGlb(
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_createFromFilamentAsset(
TEngine *tEngine,
TGltfAssetLoader *tAssetLoader,
TNameComponentManager *tNameComponentManager,
const uint8_t *data,
size_t length,
size_t numInstances
TFilamentAsset *tFilamentAsset
) {
auto *engine = reinterpret_cast<filament::Engine *>(tEngine);
auto *nameComponentManager = reinterpret_cast<utils::NameComponentManager *>(tNameComponentManager);
auto *tFilamentAsset = GltfAssetLoader_load(tEngine, tAssetLoader, data, length, numInstances);
auto *filamentAsset = reinterpret_cast<filament::gltfio::FilamentAsset *>(tFilamentAsset);
auto *assetLoader = reinterpret_cast<filament::gltfio::AssetLoader *>(tAssetLoader);
@@ -89,33 +86,6 @@ extern "C"
return reinterpret_cast<TSceneAsset *>(sceneAsset);
}
EMSCRIPTEN_KEEPALIVE int32_t SceneAsset_getResourceUriCount(
TSceneAsset *tSceneAsset
) {
auto sceneAsset = reinterpret_cast<SceneAsset *>(tSceneAsset);
if(sceneAsset->getType() != SceneAsset::SceneAssetType::Gltf) {
Log("Error - not a gltf asset");
return -1;
}
auto gltfAsset = reinterpret_cast<GltfSceneAsset *>(tSceneAsset);
auto *filamentAsset = gltfAsset->getAsset();
return filamentAsset->getResourceUriCount();
}
EMSCRIPTEN_KEEPALIVE const char* const* SceneAsset_getResourceUris(
TSceneAsset *tSceneAsset
) {
auto sceneAsset = reinterpret_cast<SceneAsset *>(tSceneAsset);
if(sceneAsset->getType() != SceneAsset::SceneAssetType::Gltf) {
Log("Error - not a gltf asset");
return nullptr;
}
auto gltfAsset = reinterpret_cast<GltfSceneAsset *>(tSceneAsset);
auto *filamentAsset = gltfAsset->getAsset();
return filamentAsset->getResourceUris();
}
EMSCRIPTEN_KEEPALIVE TFilamentAsset *SceneAsset_getFilamentAsset(TSceneAsset *tSceneAsset) {
auto sceneAsset = reinterpret_cast<SceneAsset *>(tSceneAsset);
@@ -130,7 +100,6 @@ extern "C"
return reinterpret_cast<TFilamentAsset *>(filamentAsset);
}
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_createGrid(TEngine *tEngine, TMaterial* tMaterial) {
auto *engine = reinterpret_cast<filament::Engine *>(tEngine);
auto *material = reinterpret_cast<filament::Material *>(tMaterial);
@@ -234,6 +203,11 @@ extern "C"
return reinterpret_cast<TSceneAsset*>(instance);
}
EMSCRIPTEN_KEEPALIVE size_t SceneAsset_getInstanceCount(TSceneAsset *tSceneAsset) {
auto *asset = reinterpret_cast<SceneAsset*>(tSceneAsset);
return asset->getInstanceCount();
}
EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneAsset_createInstance(TSceneAsset *tSceneAsset, TMaterialInstance **tMaterialInstances, int materialInstanceCount)
{
auto *materialInstances = reinterpret_cast<MaterialInstance **>(tMaterialInstances);

View File

@@ -415,23 +415,6 @@ extern "C"
auto fut = _renderThread->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void SceneAsset_loadGlbRenderThread(
TEngine *tEngine,
TGltfAssetLoader *tAssetLoader,
TNameComponentManager *tNameComponentManager,
uint8_t *data,
size_t length,
size_t numInstances,
void (*callback)(TSceneAsset *)
) {
std::packaged_task<void()> lambda(
[=]
{
auto sceneAsset = SceneAsset_loadGlb(tEngine, tAssetLoader, tNameComponentManager, data, length, numInstances);
callback(sceneAsset);
});
auto fut = _renderThread->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void SceneAsset_createGeometryRenderThread(
TEngine *tEngine,
@@ -457,6 +440,22 @@ extern "C"
auto fut = _renderThread->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void SceneAsset_createFromFilamentAssetRenderThread(
TEngine *tEngine,
TGltfAssetLoader *tAssetLoader,
TNameComponentManager *tNameComponentManager,
TFilamentAsset *tFilamentAsset,
void (*onComplete)(TSceneAsset *)
) {
std::packaged_task<void()> lambda(
[=]
{
auto sceneAsset = SceneAsset_createFromFilamentAsset(tEngine, tAssetLoader, tNameComponentManager, tFilamentAsset);
onComplete(sceneAsset);
});
auto fut = _renderThread->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void SceneAsset_createInstanceRenderThread(
TSceneAsset *asset, TMaterialInstance **tMaterialInstances,
int materialInstanceCount,

View File

@@ -3,9 +3,49 @@
#include "scene/GltfSceneAssetInstance.hpp"
#include "gltfio/FilamentInstance.h"
#include "Log.hpp"
#include <memory>
#include <vector>
#include <filament/Engine.h>
#include <filament/RenderableManager.h>
#include <filament/VertexBuffer.h>
#include <filament/IndexBuffer.h>
#include <gltfio/AssetLoader.h>
#include <gltfio/FilamentAsset.h>
#include <gltfio/MaterialProvider.h>
#include <utils/NameComponentManager.h>
#include "scene/GltfSceneAssetInstance.hpp"
#include "components/AnimationComponentManager.hpp"
#include "components/CollisionComponentManager.hpp"
#include "scene/SceneAsset.hpp"
namespace thermion
{
GltfSceneAsset::GltfSceneAsset(
gltfio::FilamentAsset *asset,
gltfio::AssetLoader *assetLoader,
Engine *engine,
utils::NameComponentManager* ncm,
MaterialInstance **materialInstances,
size_t materialInstanceCount,
int instanceIndex) : _asset(asset),
_assetLoader(assetLoader),
_engine(engine),
_ncm(ncm),
_materialInstances(materialInstances),
_materialInstanceCount(materialInstanceCount)
{
createInstance();
TRACE("Created GltfSceneAsset from FilamentAsset %d with %d reserved instances", asset, asset->getAssetInstanceCount());
}
GltfSceneAsset::~GltfSceneAsset()
{
_instances.clear();
@@ -14,6 +54,13 @@ namespace thermion
TRACE("Destroyed");
}
void GltfSceneAsset::destroyInstance(SceneAsset *asset) {
auto it = std::remove_if(_instances.begin(), _instances.end(), [=](auto &sceneAsset)
{ return sceneAsset.get() == asset; });
_instances.erase(it, _instances.end());
};
SceneAsset *GltfSceneAsset::createInstance(MaterialInstance **materialInstances, size_t materialInstanceCount)
{
auto instanceNumber = _instances.size();

View File

@@ -0,0 +1,40 @@
@Timeout(const Duration(seconds: 600))
import 'package:test/test.dart';
import 'package:vector_math/vector_math_64.dart';
import 'helpers.dart';
void main() async {
final testHelper = TestHelper("instancing");
await testHelper.setup();
test('gltf assets always create one instance', () async {
await testHelper.withViewer((viewer) async {
var asset =
await viewer.loadGltf("file://${testHelper.testDir}/assets/cube.glb");
expect(await asset.getInstanceCount(), 1);
});
});
test('create gltf instance', () async {
await testHelper.withViewer((viewer) async {
await viewer
.loadIbl("file://${testHelper.testDir}/assets/default_env_ibl.ktx");
await viewer.loadSkybox(
"file://${testHelper.testDir}/assets/default_env_skybox.ktx");
await viewer.setPostProcessing(true);
await viewer.setAntiAliasing(false, true, false);
var asset = await viewer.loadGltf(
"file://${testHelper.testDir}/assets/cube.glb",
numInstances: 2);
await testHelper.capture(viewer.view, "gltf");
var instance = await asset.createInstance();
await viewer.addToScene(instance);
print(instance.entity);
print(await instance.getChildEntities());
await instance.setTransform(Matrix4.translation(Vector3(1, 0, 0)));
await testHelper.capture(viewer.view, "gltf_with_instance");
});
});
}