refactor!: rename removeAsset to destroyAsset

use render thread methods for lights
This commit is contained in:
Nick Fisher
2025-01-04 15:56:05 +08:00
parent 04adbc39e0
commit 4e64c4976f
25 changed files with 1233 additions and 219 deletions

View File

@@ -22,7 +22,7 @@ class _Gizmo {
Future dispose() async {
await transformUpdates.close();
await viewer.removeAsset(_gizmo);
await viewer.destroyAsset(_gizmo);
}
Future hide() async {

View File

@@ -23,7 +23,7 @@
// }
// Future dispose() async {
// await viewer.removeAsset(_translationGizmo);
// await viewer.destroyAsset(_translationGizmo);
// }
// @override

View File

@@ -246,6 +246,28 @@ void MaterialInstance_setTransparencyMode(
transparencyMode.value,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TLightManager>, EntityId, ffi.Double,
ffi.Double, ffi.Double)>(isLeaf: true)
external void LightManager_setPosition(
ffi.Pointer<TLightManager> tLightManager,
int light,
double x,
double y,
double z,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TLightManager>, EntityId, ffi.Double,
ffi.Double, ffi.Double)>(isLeaf: true)
external void LightManager_setDirection(
ffi.Pointer<TLightManager> tLightManager,
int light,
double x,
double y,
double z,
);
@ffi.Native<
ffi.Pointer<TViewer> Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Char>)>(isLeaf: true)
@@ -406,6 +428,12 @@ external ffi.Pointer<TRenderableManager> Engine_getRenderableManager(
ffi.Pointer<TEngine> engine,
);
@ffi.Native<ffi.Pointer<TLightManager> Function(ffi.Pointer<TEngine>)>(
isLeaf: true)
external ffi.Pointer<TLightManager> Engine_getLightManager(
ffi.Pointer<TEngine> engine,
);
@ffi.Native<ffi.Pointer<TEntityManager> Function(ffi.Pointer<TEngine>)>(
isLeaf: true)
external ffi.Pointer<TEntityManager> Engine_getEntityManager(
@@ -465,11 +493,16 @@ external void set_background_color(
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, ffi.Pointer<ffi.Char>)>(
isLeaf: true)
external void load_skybox(
external void Viewer_loadSkybox(
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.Char> skyboxPath,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void Viewer_removeSkybox(
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TViewer>, ffi.Pointer<ffi.Char>, ffi.Float)>(isLeaf: true)
@@ -479,6 +512,11 @@ external void Viewer_loadIbl(
double intensity,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void Viewer_removeIbl(
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TViewer>, ffi.Float, ffi.Float, ffi.Float,
ffi.Float)>(isLeaf: true)
@@ -497,88 +535,6 @@ external void rotate_ibl(
ffi.Pointer<ffi.Float> rotationMatrix,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void remove_skybox(
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void remove_ibl(
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
EntityId Function(
ffi.Pointer<TViewer>,
ffi.Uint8,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Bool)>(isLeaf: true)
external int add_light(
ffi.Pointer<TViewer> viewer,
int type,
double colour,
double intensity,
double posX,
double posY,
double posZ,
double dirX,
double dirY,
double dirZ,
double falloffRadius,
double spotLightConeInner,
double spotLightConeOuter,
double sunAngularRadius,
double sunHaloSize,
double sunHaloFallof,
bool shadows,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>, EntityId)>(isLeaf: true)
external void remove_light(
ffi.Pointer<TViewer> viewer,
int entityId,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void clear_lights(
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TViewer>, EntityId, ffi.Float, ffi.Float,
ffi.Float)>(isLeaf: true)
external void set_light_position(
ffi.Pointer<TViewer> viewer,
int light,
double x,
double y,
double z,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TViewer>, EntityId, ffi.Float, ffi.Float,
ffi.Float)>(isLeaf: true)
external void set_light_direction(
ffi.Pointer<TViewer> viewer,
int light,
double x,
double y,
double z,
);
@ffi.Native<EntityId Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external int get_main_camera(
ffi.Pointer<TViewer> viewer,
@@ -1314,6 +1270,14 @@ external void Viewer_loadIblRenderThread(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TViewer>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void Viewer_removeIblRenderThread(
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TViewer>,
@@ -1341,6 +1305,23 @@ external void Viewer_destroyRenderTargetRenderThread(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TViewer>, ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void Viewer_loadSkyboxRenderThread(
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.Char> skyboxPath,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TViewer>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void Viewer_removeSkyboxRenderThread(
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TEngine>,
@@ -1462,20 +1443,6 @@ external void set_background_image_position_render_thread(
bool clamp,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TViewer>, ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void load_skybox_render_thread(
ffi.Pointer<TViewer> viewer,
ffi.Pointer<ffi.Char> skyboxPath,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
external void remove_skybox_render_thread(
ffi.Pointer<TViewer> viewer,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
@@ -1656,24 +1623,89 @@ external void SceneManager_loadGltfRenderThread(
);
@ffi.Native<
ffi.Pointer<ffi.Void> Function(ffi.Pointer<TSceneManager>,
ffi.Void Function(ffi.Pointer<TSceneManager>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external ffi.Pointer<ffi.Void> SceneManager_destroyAllRenderThread(
external void SceneManager_destroyAllRenderThread(
ffi.Pointer<TSceneManager> tSceneManager,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
ffi.Pointer<ffi.Void> Function(
ffi.Pointer<TSceneManager>,
ffi.Pointer<TSceneAsset>,
ffi.Void Function(ffi.Pointer<TSceneManager>, ffi.Pointer<TSceneAsset>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external ffi.Pointer<ffi.Void> SceneManager_destroyAssetRenderThread(
external void SceneManager_destroyAssetRenderThread(
ffi.Pointer<TSceneManager> tSceneManager,
ffi.Pointer<TSceneAsset> sceneAsset,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TSceneManager>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void SceneManager_destroyAssetsRenderThread(
ffi.Pointer<TSceneManager> tSceneManager,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TSceneManager>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void SceneManager_destroyLightsRenderThread(
ffi.Pointer<TSceneManager> tSceneManager,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
EntityId Function(
ffi.Pointer<TSceneManager>,
ffi.Uint8,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Bool,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>>)>(
isLeaf: true)
external int SceneManager_addLightRenderThread(
ffi.Pointer<TSceneManager> tSceneManager,
int type,
double colour,
double intensity,
double posX,
double posY,
double posZ,
double dirX,
double dirY,
double dirZ,
double falloffRadius,
double spotLightConeInner,
double spotLightConeOuter,
double sunAngularRadius,
double sunHaloSize,
double sunHaloFallof,
bool shadows,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>> callback,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TSceneManager>, EntityId,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
external void SceneManager_removeLightRenderThread(
ffi.Pointer<TSceneManager> tSceneManager,
int entityId,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
);
@ffi.Native<
ffi.Void Function(
ffi.Pointer<TSceneManager>,
@@ -2012,6 +2044,7 @@ external void SceneManager_transformToUnitCube(
ffi.Pointer<TSceneManager>,
ffi.Pointer<ffi.Uint8>,
ffi.Size,
ffi.Int,
ffi.Bool,
ffi.Int,
ffi.Int,
@@ -2020,6 +2053,7 @@ external ffi.Pointer<TSceneAsset> SceneManager_loadGlbFromBuffer(
ffi.Pointer<TSceneManager> tSceneManager,
ffi.Pointer<ffi.Uint8> arg1,
int length,
int numInstances,
bool keepData,
int priority,
int layer,
@@ -2047,26 +2081,81 @@ external ffi.Pointer<TSceneAsset> SceneManager_loadGltf(
);
@ffi.Native<
ffi.Pointer<TAnimationManager> Function(
ffi.Pointer<TSceneManager>)>(isLeaf: true)
external ffi.Pointer<TAnimationManager> SceneManager_getAnimationManager(
EntityId Function(
ffi.Pointer<TSceneManager>,
ffi.Uint8,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Float,
ffi.Bool)>(isLeaf: true)
external int SceneManager_addLight(
ffi.Pointer<TSceneManager> tSceneManager,
int type,
double colour,
double intensity,
double posX,
double posY,
double posZ,
double dirX,
double dirY,
double dirZ,
double falloffRadius,
double spotLightConeInner,
double spotLightConeOuter,
double sunAngularRadius,
double sunHaloSize,
double sunHaloFallof,
bool shadows,
);
@ffi.Native<ffi.Pointer<ffi.Void> Function(ffi.Pointer<TSceneManager>)>(
@ffi.Native<ffi.Void Function(ffi.Pointer<TSceneManager>, EntityId)>(
isLeaf: true)
external ffi.Pointer<ffi.Void> SceneManager_destroyAll(
external void SceneManager_removeLight(
ffi.Pointer<TSceneManager> tSceneManager,
int entityId,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TSceneManager>)>(isLeaf: true)
external void SceneManager_destroyLights(
ffi.Pointer<TSceneManager> tSceneManager,
);
@ffi.Native<
ffi.Pointer<ffi.Void> Function(
ffi.Void Function(
ffi.Pointer<TSceneManager>, ffi.Pointer<TSceneAsset>)>(isLeaf: true)
external ffi.Pointer<ffi.Void> SceneManager_destroyAsset(
external void SceneManager_destroyAsset(
ffi.Pointer<TSceneManager> tSceneManager,
ffi.Pointer<TSceneAsset> sceneAsset,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TSceneManager>)>(isLeaf: true)
external void SceneManager_destroyAssets(
ffi.Pointer<TSceneManager> tSceneManager,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TSceneManager>)>(isLeaf: true)
external void SceneManager_destroyAll(
ffi.Pointer<TSceneManager> tSceneManager,
);
@ffi.Native<
ffi.Pointer<TAnimationManager> Function(
ffi.Pointer<TSceneManager>)>(isLeaf: true)
external ffi.Pointer<TAnimationManager> SceneManager_getAnimationManager(
ffi.Pointer<TSceneManager> tSceneManager,
);
@ffi.Native<
ffi.Pointer<TNameComponentManager> Function(
ffi.Pointer<TSceneManager>)>(isLeaf: true)
@@ -2118,6 +2207,13 @@ external ffi.Pointer<TMaterialInstance> RenderableManager_getMaterialInstanceAt(
int primitiveIndex,
);
@ffi.Native<ffi.Bool Function(ffi.Pointer<TRenderableManager>, EntityId)>(
isLeaf: true)
external bool RenderableManager_isRenderable(
ffi.Pointer<TRenderableManager> tRenderableManager,
int entityId,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TSceneAsset>, ffi.Pointer<TScene>)>(
isLeaf: true)
external void SceneAsset_addToScene(
@@ -2425,6 +2521,8 @@ final class TViewer extends ffi.Opaque {}
final class TSceneManager extends ffi.Opaque {}
final class TLightManager extends ffi.Opaque {}
final class TRenderTarget extends ffi.Opaque {}
final class TSwapChain extends ffi.Opaque {}

View File

@@ -356,7 +356,7 @@ class ThermionViewerFFI extends ThermionViewer {
final pathPtr = skyboxPath.toNativeUtf8(allocator: allocator).cast<Char>();
await withVoidCallback((cb) {
load_skybox_render_thread(_viewer!, pathPtr, cb);
Viewer_loadSkyboxRenderThread(_viewer!, pathPtr, cb);
});
allocator.free(pathPtr);
@@ -401,7 +401,9 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future removeSkybox() async {
remove_skybox_render_thread(_viewer!);
await withVoidCallback((cb) {
Viewer_removeSkyboxRenderThread(_viewer!, cb);
});
}
///
@@ -454,25 +456,27 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future<ThermionEntity> addDirectLight(DirectLight directLight) async {
var entity = SceneManager_addLight(
_sceneManager!,
directLight.type.index,
directLight.color,
directLight.intensity,
directLight.position.x,
directLight.position.y,
directLight.position.z,
directLight.direction.x,
directLight.direction.y,
directLight.direction.z,
directLight.falloffRadius,
directLight.spotLightConeInner,
directLight.spotLightConeOuter,
directLight.sunAngularRadius,
directLight.sunHaloSize,
directLight.sunHaloFallof,
directLight.castShadows,
);
var entity = await withIntCallback((cb) {
SceneManager_addLightRenderThread(
_sceneManager!,
directLight.type.index,
directLight.color,
directLight.intensity,
directLight.position.x,
directLight.position.y,
directLight.position.z,
directLight.direction.x,
directLight.direction.y,
directLight.direction.z,
directLight.falloffRadius,
directLight.spotLightConeInner,
directLight.spotLightConeOuter,
directLight.sunAngularRadius,
directLight.sunHaloSize,
directLight.sunHaloFallof,
directLight.castShadows,
cb);
});
if (entity == FILAMENT_ASSET_ERROR) {
throw Exception("Failed to add light to scene");
}
@@ -484,7 +488,9 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future removeLight(ThermionEntity entity) async {
SceneManager_removeLight(_sceneManager!, entity);
await withVoidCallback((cb) {
SceneManager_removeLightRenderThread(_sceneManager!, entity, cb);
});
}
///
@@ -492,7 +498,9 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future destroyLights() async {
SceneManager_destroyLights(_sceneManager!);
await withVoidCallback((cb) {
SceneManager_destroyLightsRenderThread(_sceneManager!, cb);
});
}
///
@@ -976,7 +984,7 @@ class ThermionViewerFFI extends ThermionViewer {
///
///
@override
Future removeAsset(covariant FFIAsset asset) async {
Future destroyAsset(covariant FFIAsset asset) async {
if (asset.boundingBoxAsset != null) {
await asset.setBoundingBoxVisibility(false);
await withVoidCallback((callback) =>
@@ -993,7 +1001,7 @@ class ThermionViewerFFI extends ThermionViewer {
@override
Future destroyAssets() async {
await withVoidCallback((callback) {
SceneManager_destroyAllRenderThread(_sceneManager!, callback);
SceneManager_destroyAssetsRenderThread(_sceneManager!, callback);
});
}

View File

@@ -377,10 +377,10 @@ abstract class ThermionViewer {
{int skinIndex = 0});
///
/// Removes/destroys the specified entity from the scene.
/// [entity] will no longer be a valid handle after this method is called; ensure you immediately discard all references once this method is complete.
/// Destroys [asset] and all underlying resources
/// (including instances, but excluding any manually created material instances).
///
Future removeAsset(ThermionAsset asset);
Future destroyAsset(ThermionAsset asset);
///
/// Removes/destroys all renderable entities from the scene (including cameras).

View File

@@ -410,13 +410,6 @@ class ThermionViewerStub extends ThermionViewer {
throw UnimplementedError();
}
@override
Future setParent(ThermionEntity child, ThermionEntity parent, { bool preserveScaling = false}) {
// TODO: implement setParent
throw UnimplementedError();
}
@override
Future setPosition(ThermionEntity entity, double x, double y, double z) {
// TODO: implement setPosition
@@ -1008,7 +1001,7 @@ class ThermionViewerStub extends ThermionViewer {
}
@override
Future removeAsset(ThermionAsset asset) {
Future destroyAsset(ThermionAsset asset) {
// TODO: implement removeAsset
throw UnimplementedError();
}
@@ -1102,6 +1095,12 @@ class ThermionViewerStub extends ThermionViewer {
// TODO: implement showGridOverlay
throw UnimplementedError();
}
@override
Future setParent(ThermionEntity child, ThermionEntity? parent, {bool preserveScaling=false}) {
// TODO: implement setParent
throw UnimplementedError();
}
}

View File

@@ -319,8 +319,8 @@
// }
// @JSExport()
// JSPromise removeAsset(ThermionEntity entity) =>
// viewer.removeAsset(entity).toJS;
// JSPromise destroyAsset(ThermionEntity entity) =>
// viewer.destroyAsset(entity).toJS;
// @JSExport()
// JSPromise destroyAssets() {

View File

@@ -339,8 +339,8 @@
// }
// @override
// Future<void> removeAsset(ThermionEntity entity) async {
// await _shim.removeAsset(entity).toDart;
// Future<void> destroyAsset(ThermionEntity entity) async {
// await _shim.destroyAsset(entity).toDart;
// }
// @override

View File

@@ -164,8 +164,8 @@ extension type ThermionViewerJSShim(JSObject _) implements JSObject {
JSNumber fadeOutInSecs,
JSNumber maxDelta);
@JS('removeAsset')
external JSPromise removeAsset(ThermionEntity entity);
@JS('destroyAsset')
external JSPromise destroyAsset(ThermionEntity entity);
@JS('destroyAssets')
external JSPromise destroyAssets();

View File

@@ -225,8 +225,8 @@
// return;
// }
// await setRendering(false);
// await clearEntities();
// await clearLights();
// await destroyAssets();
// await destroyLights();
// _destroyViewer();
// _sceneManager = null;
@@ -1130,13 +1130,13 @@
// }
// @override
// Future clearEntities() async {
// Future destroyAssets() async {
// _module!.ccall(
// "clear_entities", "void", ["void*".toJS].toJS, [_viewer!].toJS, null);
// }
// @override
// Future clearLights() async {
// Future destroyLights() async {
// _module!.ccall(
// "clear_lights", "void", ["void*".toJS].toJS, [_viewer!].toJS, null);
// }
@@ -1585,7 +1585,7 @@
// }
// @override
// Future removeEntity(ThermionEntity entity) async {
// Future destroyAsset(ThermionEntity entity) async {
// _module!.ccall("remove_entity", "void", ["void*".toJS, "int".toJS].toJS,
// [_viewer!, entity.toJS].toJS, null);
// }

View File

@@ -60,14 +60,13 @@ extern "C"
EMSCRIPTEN_KEEPALIVE void set_background_image_position(TViewer *viewer, float x, float y, bool clamp);
EMSCRIPTEN_KEEPALIVE void set_background_color(TViewer *viewer, const float r, const float g, const float b, const float a);
EMSCRIPTEN_KEEPALIVE void load_skybox(TViewer *viewer, const char *skyboxPath);
EMSCRIPTEN_KEEPALIVE void Viewer_loadSkybox(TViewer *viewer, const char *skyboxPath);
EMSCRIPTEN_KEEPALIVE void Viewer_removeSkybox(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE void Viewer_loadIbl(TViewer *viewer, const char *iblPath, float intensity);
EMSCRIPTEN_KEEPALIVE void Viewer_removeIbl(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE void create_ibl(TViewer *viewer, float r, float g, float b, float intensity);
EMSCRIPTEN_KEEPALIVE void rotate_ibl(TViewer *viewer, float *rotationMatrix);
EMSCRIPTEN_KEEPALIVE void remove_skybox(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE EntityId get_main_camera(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE void set_frame_interval(TViewer *viewer, float interval);

View File

@@ -41,11 +41,13 @@ namespace thermion
EMSCRIPTEN_KEEPALIVE void Viewer_removeIblRenderThread(TViewer *viewer, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void Viewer_createRenderTargetRenderThread(TViewer *viewer, intptr_t texture, uint32_t width, uint32_t height, void (*onComplete)(TRenderTarget *));
EMSCRIPTEN_KEEPALIVE void Viewer_destroyRenderTargetRenderThread(TViewer *viewer, TRenderTarget *tRenderTarget, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void Viewer_loadSkyboxRenderThread(TViewer *viewer, const char *skyboxPath, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void Viewer_removeSkyboxRenderThread(TViewer *viewer, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t* materialData, size_t length, void (*onComplete)(TMaterial *));
EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialRenderThread(TEngine *tEngine, TMaterial *tMaterial, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t *materialData, size_t length, void (*onComplete)(TMaterial *));
EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialRenderThread(TEngine *tEngine, TMaterial *tMaterial, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void Material_createInstanceRenderThread(TMaterial *tMaterial, void (*onComplete)(TMaterialInstance*));
EMSCRIPTEN_KEEPALIVE void Material_createInstanceRenderThread(TMaterial *tMaterial, void (*onComplete)(TMaterialInstance *));
EMSCRIPTEN_KEEPALIVE void View_setToneMappingRenderThread(TView *tView, TEngine *tEngine, thermion::ToneMapping toneMapping);
EMSCRIPTEN_KEEPALIVE void View_setBloomRenderThread(TView *tView, double bloom);
@@ -59,18 +61,15 @@ namespace thermion
EMSCRIPTEN_KEEPALIVE void clear_background_image_render_thread(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE void set_background_image_render_thread(TViewer *viewer, const char *path, bool fillHeight, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void set_background_image_position_render_thread(TViewer *viewer, float x, float y, bool clamp);
EMSCRIPTEN_KEEPALIVE void load_skybox_render_thread(TViewer *viewer, const char *skyboxPath, void (*onComplete)());
EMSCRIPTEN_KEEPALIVE void remove_skybox_render_thread(TViewer *viewer);
EMSCRIPTEN_KEEPALIVE void SceneManager_createGridRenderThread(TSceneManager *tSceneManager, TMaterial *tMaterial, void (*callback)(TSceneAsset *));
EMSCRIPTEN_KEEPALIVE TGizmo *SceneManager_createGizmoRenderThread(
TSceneManager *tSceneManager,
TView *tView,
TSceneManager *tSceneManager,
TView *tView,
TScene *tScene,
TGizmoType tGizmoType,
void (*onComplete)(TGizmo*)
);
void (*onComplete)(TGizmo *));
EMSCRIPTEN_KEEPALIVE void SceneManager_createGeometryRenderThread(
TSceneManager *sceneManager,
@@ -92,13 +91,36 @@ namespace thermion
EMSCRIPTEN_KEEPALIVE void SceneManager_createUnlitFixedSizeMaterialInstanceRenderThread(TSceneManager *sceneManager, void (*callback)(TMaterialInstance *));
EMSCRIPTEN_KEEPALIVE void SceneManager_loadGlbRenderThread(TSceneManager *sceneManager, const char *assetPath, int numInstances, bool keepData, void (*callback)(TSceneAsset *));
EMSCRIPTEN_KEEPALIVE void SceneManager_loadGltfRenderThread(TSceneManager *sceneManager, const char *assetPath, const char *relativePath, bool keepData, void (*callback)(TSceneAsset *));
EMSCRIPTEN_KEEPALIVE void *SceneManager_destroyAllRenderThread(TSceneManager *tSceneManager, void (*callback)());
EMSCRIPTEN_KEEPALIVE void *SceneManager_destroyAssetRenderThread(TSceneManager *tSceneManager, TSceneAsset *sceneAsset, void (*callback)());
EMSCRIPTEN_KEEPALIVE void SceneManager_createCameraRenderThread(TSceneManager *tSceneManager, void (*callback)(TCamera*));
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyAllRenderThread(TSceneManager *tSceneManager, void (*callback)());
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyAssetRenderThread(TSceneManager *tSceneManager, TSceneAsset *sceneAsset, void (*callback)());
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyAssetsRenderThread(TSceneManager *tSceneManager, void (*callback)());
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyLightsRenderThread(TSceneManager *tSceneManager, void (*callback)());
EMSCRIPTEN_KEEPALIVE EntityId SceneManager_addLightRenderThread(
TSceneManager *tSceneManager,
uint8_t type,
float colour,
float intensity,
float posX,
float posY,
float posZ,
float dirX,
float dirY,
float dirZ,
float falloffRadius,
float spotLightConeInner,
float spotLightConeOuter,
float sunAngularRadius,
float sunHaloSize,
float sunHaloFallof,
bool shadows,
void (*callback)(EntityId));
EMSCRIPTEN_KEEPALIVE void SceneManager_removeLightRenderThread(TSceneManager *tSceneManager, EntityId entityId, void (*callback)());
EMSCRIPTEN_KEEPALIVE void SceneManager_createCameraRenderThread(TSceneManager *tSceneManager, void (*callback)(TCamera *));
EMSCRIPTEN_KEEPALIVE void SceneAsset_createInstanceRenderThread(TSceneAsset *asset, TMaterialInstance **tMaterialInstances, int materialInstanceCount, void (*callback)(TSceneAsset *));
EMSCRIPTEN_KEEPALIVE void MaterialProvider_createMaterialInstanceRenderThread(TMaterialProvider *tMaterialProvider, TMaterialKey *tKey, void (*callback)(TMaterialInstance*));
EMSCRIPTEN_KEEPALIVE void MaterialProvider_createMaterialInstanceRenderThread(TMaterialProvider *tMaterialProvider, TMaterialKey *tKey, void (*callback)(TMaterialInstance *));
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyMaterialInstanceRenderThread(TSceneManager *tSceneManager, TMaterialInstance *tMaterialInstance, void (*callback)());
EMSCRIPTEN_KEEPALIVE void AnimationManager_updateBoneMatricesRenderThread(

View File

@@ -74,11 +74,16 @@ extern "C"
((FilamentViewer *)viewer)->setBackgroundImagePosition(x, y, clamp, 100, 100);
}
EMSCRIPTEN_KEEPALIVE void load_skybox(TViewer *viewer, const char *skyboxPath)
EMSCRIPTEN_KEEPALIVE void Viewer_loadSkybox(TViewer *viewer, const char *skyboxPath)
{
((FilamentViewer *)viewer)->loadSkybox(skyboxPath);
}
EMSCRIPTEN_KEEPALIVE void Viewer_removeSkybox(TViewer *viewer)
{
((FilamentViewer *)viewer)->removeSkybox();
}
EMSCRIPTEN_KEEPALIVE void create_ibl(TViewer *viewer, float r, float g, float b, float intensity)
{
((FilamentViewer *)viewer)->createIbl(r, g, b, intensity);
@@ -108,12 +113,6 @@ extern "C"
((FilamentViewer *)viewer)->rotateIbl(matrix);
}
EMSCRIPTEN_KEEPALIVE void remove_skybox(TViewer *viewer)
{
((FilamentViewer *)viewer)->removeSkybox();
}
EMSCRIPTEN_KEEPALIVE int get_instance_count(TSceneManager *sceneManager, EntityId entityId)
{
return ((SceneManager *)sceneManager)->getInstanceCount(entityId);

View File

@@ -542,21 +542,24 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void load_skybox_render_thread(TViewer *viewer,
EMSCRIPTEN_KEEPALIVE void Viewer_loadSkyboxRenderThread(TViewer *viewer,
const char *skyboxPath,
void (*onComplete)())
{
std::packaged_task<void()> lambda([=]
{
load_skybox(viewer, skyboxPath);
Viewer_loadSkybox(viewer, skyboxPath);
onComplete(); });
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void remove_skybox_render_thread(TViewer *viewer)
EMSCRIPTEN_KEEPALIVE void Viewer_removeSkyboxRenderThread(TViewer *viewer, void (*onComplete)())
{
std::packaged_task<void()> lambda([=]
{ remove_skybox(viewer); });
{
Viewer_removeSkybox(viewer);
onComplete();
});
auto fut = _rl->add_task(lambda);
}
@@ -591,7 +594,7 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void *SceneManager_destroyAllRenderThread(TSceneManager *tSceneManager, void (*callback)())
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyAllRenderThread(TSceneManager *tSceneManager, void (*callback)())
{
std::packaged_task<void()> lambda(
[=]() mutable
@@ -600,7 +603,6 @@ extern "C"
callback();
});
auto fut = _rl->add_task(lambda);
return nullptr;
}
EMSCRIPTEN_KEEPALIVE TGizmo *SceneManager_createGizmoRenderThread(
@@ -620,7 +622,45 @@ extern "C"
return nullptr;
}
EMSCRIPTEN_KEEPALIVE void *SceneManager_destroyAssetRenderThread(TSceneManager *tSceneManager, TSceneAsset *tSceneAsset, void (*callback)())
EMSCRIPTEN_KEEPALIVE EntityId SceneManager_addLightRenderThread(
TSceneManager *tSceneManager,
uint8_t type,
float colour,
float intensity,
float posX,
float posY,
float posZ,
float dirX,
float dirY,
float dirZ,
float falloffRadius,
float spotLightConeInner,
float spotLightConeOuter,
float sunAngularRadius,
float sunHaloSize,
float sunHaloFallof,
bool shadows,
void (*callback)(EntityId entityId)) {
std::packaged_task<void()> lambda(
[=]() mutable
{
auto light = SceneManager_addLight(tSceneManager, type, colour, intensity, posX, posY, posZ, dirX, dirY, dirZ, falloffRadius, spotLightConeInner, spotLightConeOuter, sunAngularRadius, sunHaloSize, sunHaloFallof, shadows);
callback(light);
});
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void SceneManager_removeLightRenderThread(TSceneManager *tSceneManager, EntityId entityId, void (*callback)()) {
std::packaged_task<void()> lambda(
[=]() mutable
{
SceneManager_removeLight(tSceneManager, entityId);
callback();
});
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyAssetRenderThread(TSceneManager *tSceneManager, TSceneAsset *tSceneAsset, void (*callback)())
{
std::packaged_task<void()> lambda(
[=]() mutable
@@ -629,7 +669,28 @@ extern "C"
callback();
});
auto fut = _rl->add_task(lambda);
return nullptr;
}
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyAssetsRenderThread(TSceneManager *tSceneManager, void (*callback)())
{
std::packaged_task<void()> lambda(
[=]() mutable
{
SceneManager_destroyAssets(tSceneManager);
callback();
});
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void SceneManager_destroyLightsRenderThread(TSceneManager *tSceneManager, void (*callback)())
{
std::packaged_task<void()> lambda(
[=]() mutable
{
SceneManager_destroyLights(tSceneManager);
callback();
});
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void SceneManager_createCameraRenderThread(TSceneManager *tSceneManager, void (*callback)(TCamera *))

View File

@@ -1,6 +1,4 @@
import 'package:thermion_dart/thermion_dart.dart';
import 'package:test/test.dart';
import 'package:vector_math/vector_math_64.dart';
import 'helpers.dart';
void main() async {
@@ -11,7 +9,12 @@ void main() async {
var asset = await viewer.loadGlb("file://${testHelper.testDir}/assets/cube.glb");
await testHelper.capture(viewer, "asset_loaded");
await viewer.destroyAssets();
await viewer.destroyLights();
await viewer.removeSkybox();
await viewer.removeIbl();
await testHelper.capture(viewer, "assets_cleared");
asset = await viewer.loadGlb("file://${testHelper.testDir}/assets/cube.glb");
await testHelper.capture(viewer, "asset_reloaded");
}, bg: kRed);
});
});

View File

@@ -187,6 +187,24 @@ void main() async {
});
});
test(
'when a camera is the parent of another entity, setting the model matrix updates the parent transform ',
() async {
await testHelper.withViewer((viewer) async {
var camera = await viewer.createCamera();
var child = await viewer
.createGeometry(GeometryHelper.cube(normals: false, uvs: false));
await viewer.setParent(child.entity, camera.getEntity());
await testHelper.capture(viewer, "camera_as_parent1");
await camera.setModelMatrix(Matrix4.translation(Vector3(1, 0, 0)));
await testHelper.capture(viewer, "camera_as_parent2");
}, bg: kRed, cameraPosition: Vector3(0, 0, 10));
});
test('create camera', () async {
await testHelper.withViewer((viewer) async {
await viewer.setCameraPosition(0, 0, 5);

View File

@@ -22,7 +22,7 @@ void main() async {
final cube = await viewer
.createGeometry(GeometryHelper.cube(normals: false, uvs: false));
await testHelper.capture(viewer, "geometry_cube_no_normals_uvs");
await viewer.removeAsset(cube);
await viewer.destroyAsset(cube);
await testHelper.capture(viewer, "geometry_remove_cube");
});
});
@@ -86,7 +86,7 @@ void main() async {
instance.entity, Matrix4.translation(Vector3.all(1)));
await testHelper.capture(viewer, "geometry_instanced");
await viewer.removeAsset(instance);
await viewer.destroyAsset(instance);
await testHelper.capture(viewer, "geometry_instance_removed");
});
});
@@ -169,7 +169,7 @@ void main() async {
"baseColorFactor", 0.0, 1.0, 0.0, 0.0);
await testHelper.capture(
viewer, "geometry_cube_with_custom_material_ubershader");
await viewer.removeAsset(cube);
await viewer.destroyAsset(cube);
});
});
@@ -193,7 +193,7 @@ void main() async {
await viewer.applyTexture(texture as ThermionFFITexture, cube.entity);
await testHelper.capture(
viewer, "geometry_cube_with_custom_material_ubershader_texture");
await viewer.removeAsset(cube);
await viewer.destroyAsset(cube);
await viewer.destroyTexture(texture);
});
@@ -223,7 +223,7 @@ void main() async {
var texture = await viewer.createTexture(textureData);
await viewer.applyTexture(texture, cube.entity);
await testHelper.capture(viewer, "unlit_material_texture_only");
await viewer.removeAsset(cube);
await viewer.destroyAsset(cube);
});
});
@@ -258,6 +258,18 @@ void main() async {
await testHelper.capture(viewer, "geometry_sphere_no_normals");
});
test('create multiple (non-instanced) geometry', () async {
await testHelper.withViewer((viewer) async {
final cube1 = await viewer
.createGeometry(GeometryHelper.cube(normals: false, uvs: false));
final cube2 = await viewer
.createGeometry(GeometryHelper.cube(normals: false, uvs: false));
await viewer.setTransform(
cube2.entity, Matrix4.translation(Vector3(0, 1.5, 0)));
await testHelper.capture(viewer, "multiple_geometry");
}, bg: kRed);
});
test('create camera geometry', () async {
await testHelper.withViewer((viewer) async {
final camera = await viewer.createGeometry(

View File

@@ -225,7 +225,7 @@ void main() async {
// await testHelper.capture(viewer, "texture_applied_to_geometry");
// await viewer.removeEntity(cube);
// await viewer.destroyAsset(cube);
// await viewer.destroyTexture(texture);
// await viewer.dispose();
// });
@@ -334,7 +334,7 @@ void main() async {
// await viewer.setToneMapping(ToneMapper.LINEAR);
// final unlit = await viewer.createUnlitMaterialInstance();
// await viewer.removeEntity(cube);
// await viewer.destroyAsset(cube);
// cube = await viewer.createGeometry(GeometryHelper.cube(),
// materialInstance: unlit);
// var reconstructedTexture = await viewer.createTexture(pixelBufferPng);

View File

@@ -16,7 +16,7 @@ void main() async {
var model = await viewer
.loadGlb("file://${testHelper.testDir}/assets/cube.glb");
await testHelper.capture(viewer, "load_glb_from_file");
await viewer.removeAsset(model);
await viewer.destroyAsset(model);
});
});
@@ -41,11 +41,11 @@ void main() async {
await testHelper.capture(viewer, "load_glb_from_buffer_with_instances");
await viewer.removeAsset(instance);
await viewer.destroyAsset(instance);
await testHelper.capture(viewer, "load_glb_from_buffer_instance_removed");
await viewer.removeAsset(model);
await viewer.destroyAsset(model);
await testHelper.capture(viewer, "load_glb_from_buffer_original_removed");
}, bg: kRed);
@@ -125,7 +125,7 @@ void main() async {
"baseColorFactor", 1.0, 1.0, 0.0, 1.0);
await model.setMaterialInstanceAt(materialInstance);
await testHelper.capture(viewer, "gltf_set_material_instance");
await viewer.removeAsset(model);
await viewer.destroyAsset(model);
await viewer.destroyMaterialInstance(materialInstance);
});
});

View File

@@ -19,6 +19,7 @@ import 'package:path/path.dart' as p;
Color kWhite = ColorFloat32(4)..setRgba(1.0, 1.0, 1.0, 1.0);
Color kRed = ColorFloat32(4)..setRgba(1.0, 0.0, 0.0, 1.0);
Color kGreen = ColorFloat32(4)..setRgba(0.0, 1.0, 0.0, 1.0);
/// Test files are run in a variety of ways, find this package root in all.
///

View File

@@ -572,9 +572,9 @@ class MockThermionViewer extends _i1.Mock implements _i5.ThermionViewer {
) as _i6.Future<dynamic>);
@override
_i6.Future<dynamic> clearLights() => (super.noSuchMethod(
_i6.Future<dynamic> destroyLights() => (super.noSuchMethod(
Invocation.method(
#clearLights,
#destroyLights,
[],
),
returnValue: _i6.Future<dynamic>.value(),
@@ -940,18 +940,18 @@ class MockThermionViewer extends _i1.Mock implements _i5.ThermionViewer {
) as _i6.Future<dynamic>);
@override
_i6.Future<dynamic> removeEntity(int? entity) => (super.noSuchMethod(
_i6.Future<dynamic> removeAsset(int? entity) => (super.noSuchMethod(
Invocation.method(
#removeEntity,
#removeAsset,
[entity],
),
returnValue: _i6.Future<dynamic>.value(),
) as _i6.Future<dynamic>);
@override
_i6.Future<dynamic> clearEntities() => (super.noSuchMethod(
_i6.Future<dynamic> destroyAssets() => (super.noSuchMethod(
Invocation.method(
#clearEntities,
#destroyAssets,
[],
),
returnValue: _i6.Future<dynamic>.value(),

View File

@@ -30,5 +30,17 @@ void main() async {
await testHelper.capture(viewer, "remove_ibl");
});
});
test('add/remove skybox', () async {
await testHelper.withViewer((viewer) async {
await viewer.loadGlb("file://${testHelper.testDir}/assets/cube.glb");
await viewer
.loadSkybox("file://${testHelper.testDir}/assets/default_env_skybox.ktx");
await testHelper.capture(viewer, "load_skybox");
await viewer.removeSkybox();
await testHelper.capture(viewer, "remove_skybox");
});
});
});
}

View File

@@ -123,7 +123,7 @@ void main() async {
await viewer.applyTexture(texture as ThermionFFITexture, cube.entity);
await testHelper.capture(
viewer, "geometry_cube_with_custom_material_ubershader_texture");
await viewer.removeAsset(cube);
await viewer.destroyAsset(cube);
await viewer.destroyMaterialInstance(materialInstance);
await viewer.destroyTexture(texture);
await viewer.dispose();
@@ -149,7 +149,7 @@ void main() async {
await viewer.applyTexture(texture, cube.entity);
await testHelper.capture(
viewer, "geometry_cube_with_custom_material_unlit_texture_only");
await viewer.removeAsset(cube);
await viewer.destroyAsset(cube);
cube = await viewer.createGeometry(GeometryHelper.cube(),
materialInstances: [materialInstance]);
@@ -159,7 +159,7 @@ void main() async {
"baseColorFactor", 0.0, 1.0, 0.0, 1.0);
await testHelper.capture(
viewer, "geometry_cube_with_custom_material_unlit_color_only");
await viewer.removeAsset(cube);
await viewer.destroyAsset(cube);
cube = await viewer.createGeometry(GeometryHelper.cube(),
materialInstances: [materialInstance]);
@@ -172,7 +172,7 @@ void main() async {
await testHelper.capture(
viewer, "geometry_cube_with_custom_material_unlit_color_and_texture");
await viewer.removeAsset(cube);
await viewer.destroyAsset(cube);
await viewer.destroyTexture(texture);
await viewer.destroyMaterialInstance(materialInstance);
@@ -418,7 +418,7 @@ void main() async {
// await testHelper.capture(viewer, "texture_applied_to_geometry");
// await viewer.removeAsset(cube);
// await viewer.destroyAsset(cube);
// await viewer.destroyTexture(texture);
// await viewer.dispose();
// });
@@ -527,7 +527,7 @@ void main() async {
// await viewer.setToneMapping(ToneMapper.LINEAR);
// final unlit = await viewer.createUnlitMaterialInstance();
// await viewer.removeAsset(cube);
// await viewer.destroyAsset(cube);
// cube = await viewer.createGeometry(GeometryHelper.cube(),
// materialInstance: unlit);
// var reconstructedTexture = await viewer.createTexture(pixelBufferPng);

View File

@@ -0,0 +1,782 @@
// import 'dart:async';
// import 'dart:io';
// import 'dart:math';
// import 'package:thermion_dart/src/viewer/src/events.dart';
// import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';
// import 'package:thermion_dart/thermion_dart.dart';
// import 'package:test/test.dart';
// import 'package:vector_math/vector_math_64.dart';
// import 'helpers.dart';
// void main() async {
// final testHelper = TestHelper("integration");
// group('background', () {
// test('set background color to solid green', () async {
// var viewer = await testHelper.createViewer();
// await viewer.setBackgroundColor(0.0, 1.0, 0.0, 1.0);
// await testHelper.capture(viewer, "set_background_color_to_solid_green");
// await viewer.dispose();
// });
// test('set background color to full transparency', () async {
// var viewer = await testHelper.createViewer();
// await viewer.setBackgroundColor(0.0, 1.0, 0.0, 0.0);
// await testHelper.capture(
// viewer, "set_background_color_to_transparent_green");
// await viewer.dispose();
// });
// test('set background image', () async {
// var viewer = await testHelper.createViewer();
// await viewer.setBackgroundImage(
// "file:///${testHelper.testDir}/assets/cube_texture_512x512.png");
// await viewer.setPostProcessing(true);
// await viewer.setToneMapping(ToneMapper.LINEAR);
// await testHelper.capture(viewer, "set_background_image");
// await viewer.dispose();
// });
// });
// group("scene update events", () {
// test('add light fires SceneUpdateEvent', () async {
// var viewer = await testHelper.createViewer();
// final success = Completer<bool>();
// var light = DirectLight(
// type: LightType.POINT,
// color: 6500,
// intensity: 1000000,
// position: Vector3(0, 0.6, 0.6),
// direction: Vector3(0, 0, 0),
// falloffRadius: 2.0);
// late StreamSubscription listener;
// listener = viewer.sceneUpdated.listen((updateEvent) {
// var wasSuccess = updateEvent.eventType == EventType.EntityAdded &&
// updateEvent.addedEntityType == EntityType.DirectLight &&
// updateEvent.getDirectLight() == light;
// success.complete(wasSuccess);
// listener.cancel();
// });
// await viewer.addDirectLight(light);
// expect(await success.future, true);
// });
// test('remove light fires SceneUpdateEvent', () async {
// var viewer = await testHelper.createViewer();
// final success = Completer<bool>();
// var light = await viewer.addDirectLight(DirectLight.point());
// late StreamSubscription listener;
// listener = viewer.sceneUpdated.listen((updateEvent) {
// var wasSuccess = updateEvent.eventType == EventType.EntityRemoved &&
// updateEvent.entity == light;
// success.complete(wasSuccess);
// listener.cancel();
// });
// await viewer.removeLight(light);
// expect(await success.future, true);
// });
// test('add geometry fires SceneUpdateEvent', () async {
// var viewer = await testHelper.createViewer();
// final success = Completer<bool>();
// var geometry = GeometryHelper.cube();
// late StreamSubscription listener;
// listener = viewer.sceneUpdated.listen((updateEvent) {
// var wasSuccess = updateEvent.eventType == EventType.EntityAdded &&
// updateEvent.addedEntityType == EntityType.Geometry &&
// updateEvent.getAsGeometry() == geometry;
// success.complete(wasSuccess);
// listener.cancel();
// });
// await viewer.createGeometry(geometry);
// expect(await success.future, true);
// });
// test('remove geometry fires SceneUpdateEvent', () async {
// var viewer = await testHelper.createViewer();
// var geometry = await viewer.createGeometry(GeometryHelper.cube());
// final success = Completer<bool>();
// late StreamSubscription listener;
// listener = viewer.sceneUpdated.listen((updateEvent) {
// var wasSuccess = updateEvent.eventType == EventType.EntityRemoved &&
// updateEvent.entity == geometry;
// success.complete(wasSuccess);
// listener.cancel();
// });
// await viewer.destroyAsset(geometry);
// expect(await success.future, true);
// });
// test('loadGlb fires SceneUpdateEvent', () async {
// var viewer = await testHelper.createViewer();
// final success = Completer<bool>();
// late StreamSubscription listener;
// final uri = "${testHelper.testDir}/cube.glb";
// listener = viewer.sceneUpdated.listen((updateEvent) {
// var wasSuccess = updateEvent.eventType == EventType.EntityAdded &&
// updateEvent.addedEntityType == EntityType.Gltf &&
// updateEvent.getAsGLTF().uri == uri;
// success.complete(wasSuccess);
// listener.cancel();
// });
// await viewer.loadGlb(uri, keepData: false);
// expect(await success.future, true);
// });
// test('remove glb fires SceneUpdateEvent', () async {
// var viewer = await testHelper.createViewer();
// final uri = "${testHelper.testDir}/cube.glb";
// var entity = await viewer.loadGlb(uri, keepData: false);
// final success = Completer<bool>();
// late StreamSubscription listener;
// listener = viewer.sceneUpdated.listen((updateEvent) {
// var wasSuccess = updateEvent.eventType == EventType.EntityRemoved &&
// updateEvent.entity == entity;
// success.complete(wasSuccess);
// listener.cancel();
// });
// await viewer.destroyAsset(entity);
// expect(await success.future, true);
// });
// });
// group("MaterialInstance", () {
// test('disable depth write', () async {
// var viewer = await testHelper.createViewer();
// await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
// await viewer.setCameraPosition(0, 0, 6);
// await viewer.addDirectLight(
// DirectLight.sun(direction: Vector3(0, 0, -1)..normalize()));
// final cube1 = await viewer.createGeometry(GeometryHelper.cube());
// var materialInstance = await viewer.getMaterialInstanceAt(cube1, 0);
// final cube2 = await viewer.createGeometry(GeometryHelper.cube());
// await viewer.setMaterialPropertyFloat4(
// cube2, "baseColorFactor", 0, 0, 1, 0, 1);
// await viewer.setPosition(cube2, 1.0, 0.0, -1.0);
// expect(materialInstance, isNotNull);
// // with depth write enabled on both materials, cube2 renders behind the white cube
// await testHelper.capture(viewer, "material_instance_depth_write_enabled");
// // if we disable depth write on cube1, then cube2 will always appear in front
// // (relying on insertion order)
// materialInstance!.setDepthWriteEnabled(false);
// await testHelper.capture(
// viewer, "material_instance_depth_write_disabled");
// // set priority for the cube1 cube to 7 (render) last, cube1 renders in front
// await viewer.setPriority(cube1, 7);
// await testHelper.capture(
// viewer, "material_instance_depth_write_disabled_with_priority");
// });
// });
// // test('create instance from glb when keepData is true', () async {
// // var model = await viewer.loadGlb("${testHelper.testDir}/cube.glb", keepData: true);
// // await viewer.transformToUnitCube(model);
// // var instance = await viewer.createInstance(model);
// // await viewer.setPosition(instance, 0.5, 0.5, -0.5);
// // await viewer.setBackgroundColor(0.0, 0.0, 1.0, 1.0);
// // await viewer.setCameraPosition(0, 1, 5);
// // await viewer
// // .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
// // await viewer.setRendering(true);
// // await testHelper.capture(viewer, "glb_create_instance");
// // await viewer.setRendering(false);
// // });
// // test('create instance from glb fails when keepData is false', () async {
// // var model = await viewer.loadGlb("${testHelper.testDir}/cube.glb", keepData: false);
// // bool thrown = false;
// // try {
// // await viewer.createInstance(model);
// // } catch (err) {
// // thrown = true;
// // }
// // expect(thrown, true);
// // });
// // });
// // group('Skinning & animations', () {
// // test('get bone names', () async {
// // var model = await viewer.loadGlb("${testHelper.testDir}/assets/shapes.glb");
// // var names = await viewer.getBoneNames(model);
// // expect(names.first, "Bone");
// // });
// // test('reset bones', () async {
// // var model = await viewer.loadGlb("${testHelper.testDir}/assets/shapes.glb");
// // await viewer.resetBones(model);
// // });
// // test('set from BVH', () async {
// // var model = await viewer.loadGlb("${testHelper.testDir}/assets/shapes.glb");
// // var animation = BVHParser.parse(
// // File("${testHelper.testDir}/assets/animation.bvh").readAsStringSync(),
// // boneRegex: RegExp(r"Bone$"));
// // await viewer.addBoneAnimation(model, animation);
// // });
// // test('fade in/out', () async {
// // var model = await viewer.loadGlb("${testHelper.testDir}/assets/shapes.glb");
// // var animation = BVHParser.parse(
// // File("${testHelper.testDir}/assets/animation.bvh").readAsStringSync(),
// // boneRegex: RegExp(r"Bone$"));
// // await viewer.addBoneAnimation(model, animation,
// // fadeInInSecs: 0.5, fadeOutInSecs: 0.5);
// // await Future.delayed(Duration(seconds: 1));
// // });
// group("materials", () {
// test('set float4 material property for custom geometry', () async {
// var viewer = await testHelper.createViewer();
// await viewer.setCameraPosition(0, 0, 6);
// await viewer.setBackgroundColor(0.0, 0.0, 1.0, 1.0);
// var light = await viewer.addLight(
// LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);
// final cube = await viewer.createGeometry(GeometryHelper.cube());
// await testHelper.capture(viewer, "set_material_float4_pre");
// await viewer.setMaterialPropertyFloat4(
// cube, "baseColorFactor", 0, 0.0, 1.0, 0.0, 1.0);
// await testHelper.capture(viewer, "set_material_float4_post");
// });
// test('set float material property for custom geometry', () async {
// var viewer = await testHelper.createViewer();
// await viewer.setCameraPosition(0, 0, 6);
// await viewer.setBackgroundColor(0.0, 0.0, 1.0, 1.0);
// var light = await viewer.addLight(
// LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);
// final cube = await viewer.createGeometry(GeometryHelper.cube());
// // this won't actually do anything because the default ubershader doesn't use specular/glossiness
// // but we can at least check that the call succeeds
// await testHelper.capture(viewer, "set_material_specular_pre");
// await viewer.setMaterialPropertyFloat(cube, "specularFactor", 0, 0.0);
// await testHelper.capture(viewer, "set_material_specular_post");
// });
// test('set float material property (roughness) for custom geometry',
// () async {
// var viewer = await testHelper.createViewer();
// await viewer.setCameraPosition(0, 0, 6);
// await viewer.setBackgroundColor(0.0, 0.0, 1.0, 1.0);
// var light = await viewer.addLight(
// LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);
// final cube = await viewer.createGeometry(GeometryHelper.cube());
// // this won't actually do anything because the default ubershader doesn't use specular/glossiness
// // but we can at least check that the call succeeds
// await testHelper.capture(viewer, "set_material_roughness_pre");
// await viewer.setMaterialPropertyFloat(cube, "metallicFactor", 0, 0.0);
// await viewer.setMaterialPropertyFloat(cube, "roughnessFactor", 0, 0.0);
// await testHelper.capture(viewer, "set_material_roughness_post");
// });
// });
// group("transforms & parenting", () {
// test('set multiple transforms simultaneously with setTransforms', () async {
// var viewer =
// await testHelper.createViewer(bg: kRed, cameraPosition: Vector3(0, 0, 5));
// final cube1 = await viewer.createGeometry(GeometryHelper.cube());
// final cube2 = await viewer.createGeometry(GeometryHelper.cube());
// await viewer.queueTransformUpdates([
// cube1,
// cube2
// ], [
// Matrix4.translation(Vector3(-1, 0, 0)),
// Matrix4.translation(Vector3(1, 0, 0))
// ]);
// await viewer.render(testHelper.swapChain);
// await testHelper.capture(viewer, "set_multiple_transforms");
// });
// test('getParent and getAncestor both return null when entity has no parent',
// () async {
// var viewer = await testHelper.createViewer();
// final cube = await viewer.createGeometry(GeometryHelper.cube());
// expect(await viewer.getParent(cube), isNull);
// expect(await viewer.getAncestor(cube), isNull);
// });
// test(
// 'getParent returns the parent entity after one has been set via setParent',
// () async {
// var viewer = await testHelper.createViewer();
// final cube1 = await viewer.createGeometry(GeometryHelper.cube());
// final cube2 = await viewer.createGeometry(GeometryHelper.cube());
// await viewer.setParent(cube1, cube2);
// final parent = await viewer.getParent(cube1);
// expect(parent, cube2);
// });
// test('getAncestor returns the ultimate parent entity', () async {
// var viewer = await testHelper.createViewer();
// final grandparent = await viewer.createGeometry(GeometryHelper.cube());
// final parent = await viewer.createGeometry(GeometryHelper.cube());
// final child = await viewer.createGeometry(GeometryHelper.cube());
// await viewer.setParent(child, parent);
// await viewer.setParent(parent, grandparent);
// expect(await viewer.getAncestor(child), grandparent);
// });
// test('set position based on screenspace coord', () async {
// var viewer = await testHelper.createViewer();
// print(await viewer.getCameraFov(true));
// await viewer.createIbl(1.0, 1.0, 1.0, 1000);
// await viewer.setCameraPosition(0, 0, 6);
// await viewer.setBackgroundColor(0.0, 0.0, 1.0, 1.0);
// // Create the cube geometry
// final cube = await viewer.createGeometry(GeometryHelper.cube());
// // await viewer.setPosition(cube, -0.05, 0.04, 5.9);
// // await viewer.setPosition(cube, -2.54, 2.54, 0);
// await viewer.queuePositionUpdateFromViewportCoords(cube, 0, 0);
// // we need an explicit render call here to process the transform queue
// await viewer.render(testHelper.swapChain);
// await testHelper.capture(viewer, "set_position_from_viewport_coords");
// });
// });
// group("layers & overlays", () {
// test('enable grid overlay', () async {
// var viewer = await testHelper.createViewer();
// await viewer.setBackgroundColor(0, 0, 0, 1);
// await viewer
// .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
// await viewer.setCameraPosition(0, 2, 0);
// await testHelper.capture(viewer, "grid_overlay_default");
// await viewer.setLayerVisibility(7, true);
// await testHelper.capture(viewer, "grid_overlay_enabled");
// await viewer.setLayerVisibility(7, false);
// await testHelper.capture(viewer, "grid_overlay_disabled");
// });
// test('load glb from buffer with layer', () async {
// var viewer = await testHelper.createViewer();
// await viewer.setBackgroundColor(1, 0, 1, 1);
// await viewer.setCameraPosition(0, 2, 5);
// await viewer
// .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
// var buffer = File("${testHelper.testDir}/cube.glb").readAsBytesSync();
// var model = await viewer.loadGlbFromBuffer(buffer, layer: 1);
// await testHelper.capture(
// viewer, "load_glb_from_buffer_with_layer_disabled");
// await viewer.setLayerVisibility(1, true);
// await testHelper.capture(
// viewer, "load_glb_from_buffer_with_layer_enabled");
// });
// test('change layer visibility at runtime', () async {
// var viewer = await testHelper.createViewer();
// await viewer.setBackgroundColor(1, 0, 1, 1);
// await viewer.setCameraPosition(0, 2, 5);
// await viewer
// .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
// var cube = await viewer.createGeometry(GeometryHelper.cube());
// await testHelper.capture(
// viewer, "change_layer_visibility_at_runtime_default");
// // all entities set to layer 0 by default, so this should now be invisible
// await viewer.setLayerVisibility(0, false);
// await testHelper.capture(
// viewer, "change_layer_visibility_at_runtime_layer0_invisible");
// // now change the visibility layer to 5, should be invisible
// await viewer.setVisibilityLayer(cube, 5);
// await testHelper.capture(
// viewer, "change_layer_visibility_at_runtime_layer5_invisible");
// // now toggle layer 5 visibility, cube should now be visible
// await viewer.setLayerVisibility(5, true);
// await testHelper.capture(
// viewer, "change_layer_visibility_at_runtime_layer5_visible");
// });
// });
// // test('point light', () async {
// // var model = await viewer.loadGlb("${testHelper.testDir}/cube.glb");
// // await viewer.transformToUnitCube(model);
// // var light = await viewer.addLight(
// // LightType.POINT, 6500, 1000000, 0, 2, 0, 0, -1, 0,
// // falloffRadius: 10.0);
// // await viewer.setBackgroundColor(0.0, 0.0, 0.0, 1.0);
// // await viewer.setCameraPosition(0, 1, 5);
// // await viewer
// // .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
// // await viewer.setRendering(true);
// // await testHelper.capture(viewer, "point_light");
// // await viewer.setRendering(false);
// // });
// // test('set point light position', () async {
// // var model = await viewer.loadGlb("${testHelper.testDir}/cube.glb");
// // await viewer.transformToUnitCube(model);
// // var light = await viewer.addLight(
// // LightType.POINT, 6500, 1000000, 0, 2, 0, 0, -1, 0,
// // falloffRadius: 10.0);
// // await viewer.setLightPosition(light, 0.5, 2, 0);
// // await viewer.setBackgroundColor(0.0, 0.0, 0.0, 1.0);
// // await viewer.setCameraPosition(0, 1, 5);
// // await viewer
// // .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
// // await viewer.setRendering(true);
// // await testHelper.capture(viewer, "move_point_light");
// // await viewer.setRendering(false);
// // });
// // test('directional light', () async {
// // var model = await viewer.loadGlb("${testHelper.testDir}/cube.glb");
// // await viewer.transformToUnitCube(model);
// // var light = await viewer.addLight(
// // LightType.SUN, 6500, 1000000, 0, 0, 0, 0, -1, 0);
// // await viewer.setBackgroundColor(0.0, 0.0, 0.0, 1.0);
// // await viewer.setCameraPosition(0, 1, 5);
// // await viewer
// // .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
// // await viewer.setRendering(true);
// // await testHelper.capture(viewer, "directional_light");
// // await viewer.setRendering(false);
// // });
// // test('set directional light direction', () async {
// // var model = await viewer.loadGlb("${testHelper.testDir}/cube.glb");
// // await viewer.transformToUnitCube(model);
// // var light = await viewer.addLight(
// // LightType.SUN, 6500, 1000000, 0, 0, 0, 0, -1, 0);
// // await viewer.setLightDirection(light, Vector3(-1, -1, -1));
// // await viewer.setBackgroundColor(0.0, 0.0, 0.0, 1.0);
// // await viewer.setCameraPosition(0, 1, 5);
// // await viewer
// // .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
// // await viewer.setRendering(true);
// // await testHelper.capture(viewer, "set_directional_light_direction");
// // await viewer.setRendering(false);
// // });
// group("stencil", () {
// test('set stencil highlight for glb', () async {
// final viewer = await testHelper.createViewer();
// var model = await viewer.loadGlb("${testHelper.testDir}/cube.glb", keepData: true);
// await viewer.setPostProcessing(true);
// var light = await viewer.addLight(
// LightType.SUN, 6500, 1000000, 0, 0, 0, 0, -1, 0);
// await viewer.setLightDirection(light, Vector3(0, 1, -1));
// await viewer.setBackgroundColor(0.0, 1.0, 0.0, 1.0);
// await viewer.setCameraPosition(0, -1, 5);
// await viewer
// .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), pi / 8));
// await viewer.setStencilHighlight(model);
// await testHelper.capture(viewer, "stencil_highlight_glb");
// });
// test('set stencil highlight for geometry', () async {
// var viewer = await testHelper.createViewer();
// await viewer.setPostProcessing(true);
// await viewer.setBackgroundColor(0.0, 1.0, 0.0, 1.0);
// await viewer.setCameraPosition(0, 2, 5);
// await viewer
// .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
// var cube = await viewer.createGeometry(GeometryHelper.cube());
// await viewer.setStencilHighlight(cube);
// await testHelper.capture(viewer, "stencil_highlight_geometry");
// await viewer.removeStencilHighlight(cube);
// await testHelper.capture(viewer, "stencil_highlight_geometry_remove");
// });
// test('set stencil highlight for gltf asset', () async {
// var viewer = await testHelper.createViewer();
// await viewer.setPostProcessing(true);
// await viewer.setBackgroundColor(0.0, 1.0, 0.0, 1.0);
// await viewer.setCameraPosition(0, 1, 5);
// await viewer
// .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
// var cube1 = await viewer.loadGlb("${testHelper.testDir}/cube.glb", keepData: true);
// await viewer.transformToUnitCube(cube1);
// await viewer.setStencilHighlight(cube1);
// await testHelper.capture(viewer, "stencil_highlight_gltf");
// await viewer.removeStencilHighlight(cube1);
// await testHelper.capture(viewer, "stencil_highlight_gltf_removed");
// });
// test('set stencil highlight for multiple geometry ', () async {
// var viewer = await testHelper.createViewer();
// await viewer.setPostProcessing(true);
// await viewer.setBackgroundColor(0.0, 1.0, 0.0, 1.0);
// await viewer.setCameraPosition(0, 1, 5);
// await viewer
// .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
// var cube1 = await viewer.createGeometry(GeometryHelper.cube());
// var cube2 = await viewer.createGeometry(GeometryHelper.cube());
// await viewer.setPosition(cube2, 0.5, 0.5, 0);
// await viewer.setStencilHighlight(cube1);
// await viewer.setStencilHighlight(cube2, r: 0.0, g: 0.0, b: 1.0);
// await testHelper.capture(viewer, "stencil_highlight_multiple_geometry");
// await viewer.removeStencilHighlight(cube1);
// await viewer.removeStencilHighlight(cube2);
// await testHelper.capture(
// viewer, "stencil_highlight_multiple_geometry_removed");
// });
// test('set stencil highlight for multiple gltf assets ', () async {
// var viewer = await testHelper.createViewer();
// await viewer.setPostProcessing(true);
// await viewer.setBackgroundColor(0.0, 1.0, 0.0, 1.0);
// await viewer.setCameraPosition(0, 1, 5);
// await viewer
// .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -0.5));
// var cube1 = await viewer.loadGlb("${testHelper.testDir}/cube.glb", keepData: true);
// await viewer.transformToUnitCube(cube1);
// var cube2 = await viewer.loadGlb("${testHelper.testDir}/cube.glb", keepData: true);
// await viewer.transformToUnitCube(cube2);
// await viewer.setPosition(cube2, 0.5, 0.5, 0);
// await viewer.setStencilHighlight(cube1);
// await viewer.setStencilHighlight(cube2, r: 0.0, g: 0.0, b: 1.0);
// await testHelper.capture(viewer, "stencil_highlight_multiple_geometry");
// await viewer.removeStencilHighlight(cube1);
// await viewer.removeStencilHighlight(cube2);
// await testHelper.capture(
// viewer, "stencil_highlight_multiple_geometry_removed");
// });
// });
// group("texture", () {
// test("create/apply/dispose texture", () async {
// var viewer = await testHelper.createViewer();
// var textureData =
// File("${testHelper.testDir}/assets/cube_texture_512x512.png").readAsBytesSync();
// var texture = await viewer.createTexture(textureData);
// await viewer.setBackgroundColor(0.0, 0.0, 0.0, 1.0);
// await viewer.addDirectLight(
// DirectLight.sun(direction: Vector3(0, -10, -1)..normalize()));
// await viewer.addDirectLight(DirectLight.spot(
// intensity: 1000000,
// position: Vector3(0, 0, 1.5),
// direction: Vector3(0, 0, -1)..normalize(),
// falloffRadius: 10,
// spotLightConeInner: 1,
// spotLightConeOuter: 1));
// await viewer.setCameraPosition(0, 2, 6);
// await viewer
// .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
// var materialInstance =
// await viewer.createUbershaderMaterialInstance(unlit: true);
// var cube = await viewer.createGeometry(GeometryHelper.cube(),
// materialInstance: materialInstance);
// await viewer.setPostProcessing(true);
// await viewer.setToneMapping(ToneMapper.LINEAR);
// await viewer.applyTexture(texture, cube,
// materialIndex: 0, parameterName: "baseColorMap");
// await testHelper.capture(viewer, "texture_applied_to_geometry");
// await viewer.destroyAsset(cube);
// await viewer.destroyTexture(texture);
// });
// });
// // group("unproject", () {
// // test("unproject", () async {
// // final dimensions = (width: 1280, height: 768);
// // var viewer = await testHelper.createViewer(viewportDimensions: dimensions);
// // await viewer.setPostProcessing(false);
// // // await viewer.setToneMapping(ToneMapper.LINEAR);
// // await viewer.setBackgroundColor(1.0, 1.0, 1.0, 1.0);
// // // await viewer.createIbl(1.0, 1.0, 1.0, 100000);
// // await viewer.addLight(LightType.SUN, 6500, 100000, -2, 0, 0, 1, -1, 0);
// // await viewer.addLight(LightType.SPOT, 6500, 500000, 0, 0, 2, 0, 0, -1,
// // falloffRadius: 10, spotLightConeInner: 1.0, spotLightConeOuter: 2.0);
// // await viewer.setCameraPosition(-3, 4, 6);
// // await viewer.setCameraRotation(
// // Quaternion.axisAngle(Vector3(0, 1, 0), -pi / 8) *
// // Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 6));
// // var cube =
// // await viewer.createGeometry(GeometryHelper.cube(), keepData: true);
// // await viewer.setMaterialPropertyFloat4(
// // cube, "baseColorFactor", 0, 1.0, 1.0, 1.0, 1.0);
// // var textureData =
// // File("${testHelper.testDir}/assets/cube_texture_512x512.png").readAsBytesSync();
// // var texture = await viewer.createTexture(textureData);
// // await viewer.applyTexture(texture, cube,
// // materialIndex: 0, parameterName: "baseColorMap");
// // var numFrames = 60;
// // // first do the render
// // for (int i = 0; i < numFrames; i++) {
// // await viewer.setCameraPosition(-3 + (i / numFrames * 2), 4, 6);
// // await viewer.setCameraRotation(
// // Quaternion.axisAngle(Vector3(0, 1, 0), -pi / 8) *
// // Quaternion.axisAngle(
// // Vector3(1, 0, 0), -pi / 6 - (i / numFrames * pi / 6)));
// // var rendered = await testHelper.capture(viewer, "unproject_render$i");
// // var renderPng =
// // await pixelsToPng(rendered, dimensions.width, dimensions.height);
// // File("${outDir.path}/unproject_render${i}.png")
// // .writeAsBytesSync(renderPng);
// // }
// // // then go off and convert the video
// // // now unproject the render back onto the geometry
// // final textureSize = (width: 1280, height: 768);
// // var pixels = <Uint8List>[];
// // // note we skip the first frame
// // for (int i = 0; i < numFrames; i++) {
// // await viewer.setCameraPosition(-3 + (i / numFrames * 2), 4, 6);
// // await viewer.setCameraRotation(
// // Quaternion.axisAngle(Vector3(0, 1, 0), -pi / 8) *
// // Quaternion.axisAngle(
// // Vector3(1, 0, 0), -pi / 6 - (i / numFrames * pi / 6)));
// // var input = pngToPixelBuffer(File(
// // "${outDir.path}/a8c317af-6081-4848-8a06-f6b69bc57664_${i + 1}.png")
// // .readAsBytesSync());
// // var pixelBuffer = await (await viewer as ThermionViewerFFI).unproject(
// // cube,
// // input,
// // dimensions.width,
// // dimensions.height,
// // textureSize.width,
// // textureSize.height);
// // // var png = await pixelsToPng(Uint8List.fromList(pixelBuffer),
// // // dimensions.width, dimensions.height);
// // await savePixelBufferToBmp(
// // pixelBuffer,
// // textureSize.width,
// // textureSize.height,
// // p.join(outDir.path, "unprojected_texture${i}.bmp"));
// // pixels.add(pixelBuffer);
// // if (i > 10) {
// // break;
// // }
// // }
// // // }
// // final aggregatePixelBuffer = medianImages(pixels);
// // await savePixelBufferToBmp(aggregatePixelBuffer, textureSize.width,
// // textureSize.height, "unproject_texture.bmp");
// // var pixelBufferPng = await pixelsToPng(
// // Uint8List.fromList(aggregatePixelBuffer),
// // dimensions.width,
// // dimensions.height);
// // File("${outDir.path}/unproject_texture.png")
// // .writeAsBytesSync(pixelBufferPng);
// // await viewer.setPostProcessing(true);
// // await viewer.setToneMapping(ToneMapper.LINEAR);
// // final unlit = await viewer.createUnlitMaterialInstance();
// // await viewer.destroyAsset(cube);
// // cube = await viewer.createGeometry(GeometryHelper.cube(),
// // materialInstance: unlit);
// // var reconstructedTexture = await viewer.createTexture(pixelBufferPng);
// // await viewer.applyTexture(reconstructedTexture, cube);
// // await viewer.setCameraRotation(
// // Quaternion.axisAngle(Vector3(0, 1, 0), -pi / 8) *
// // Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 6));
// // await testHelper.capture(viewer, "unproject_reconstruct");
// // // now re-render
// // for (int i = 0; i < numFrames; i++) {
// // await viewer.setCameraPosition(-3 + (i / numFrames * 2), 4, 6);
// // await viewer.setCameraRotation(
// // Quaternion.axisAngle(Vector3(0, 1, 0), -pi / 8) *
// // Quaternion.axisAngle(
// // Vector3(1, 0, 0), -pi / 6 - (i / numFrames * pi / 6)));
// // var rendered = await testHelper.capture(viewer, "unproject_rerender$i");
// // var renderPng =
// // await pixelsToPng(rendered, dimensions.width, dimensions.height);
// // File("${outDir.path}/unproject_rerender${i}.png")
// // .writeAsBytesSync(renderPng);
// // }
// // }, timeout: Timeout(Duration(minutes: 2)));
// // });
// }

View File

@@ -145,7 +145,7 @@ void main() async {
await testHelper.capture(
viewer, "geometry_bounding_box_not_visible");
await cube.setBoundingBoxVisibility(true);
await viewer.removeAsset(cube);
await viewer.destroyAsset(cube);
await testHelper.capture(
viewer, "geometry_bounding_box_removed");
},
@@ -229,7 +229,7 @@ void main() async {
// await testHelper.capture(viewer, "texture_applied_to_geometry");
// await viewer.removeAsset(cube);
// await viewer.destroyAsset(cube);
// await viewer.destroyTexture(texture);
// await viewer.dispose();
// });
@@ -338,7 +338,7 @@ void main() async {
// await viewer.setToneMapping(ToneMapper.LINEAR);
// final unlit = await viewer.createUnlitMaterialInstance();
// await viewer.removeAsset(cube);
// await viewer.destroyAsset(cube);
// cube = await viewer.createGeometry(GeometryHelper.cube(),
// materialInstance: unlit);
// var reconstructedTexture = await viewer.createTexture(pixelBufferPng);