refactoring
This commit is contained in:
@@ -32,6 +32,11 @@ abstract class ThermionAsset {
|
|||||||
///
|
///
|
||||||
Future<List<ThermionEntity>> getChildEntities();
|
Future<List<ThermionEntity>> getChildEntities();
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
Future<List<String?>> getChildEntityNames();
|
||||||
|
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@@ -91,6 +96,21 @@ abstract class ThermionAsset {
|
|||||||
///
|
///
|
||||||
Future setReceiveShadows(bool castShadows);
|
Future setReceiveShadows(bool castShadows);
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
Future<bool> isCastShadowsEnabled({ThermionEntity? entity});
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
Future<bool> isReceiveShadowsEnabled({ThermionEntity? entity});
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
Future transformToUnitCube();
|
||||||
|
|
||||||
///
|
///
|
||||||
/// All renderable entities are assigned a layer mask.
|
/// All renderable entities are assigned a layer mask.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ abstract class FilamentApp<T> {
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
Future<ThermionAsset> loadGlbFromBuffer(Uint8List data, T animationManager,
|
Future<ThermionAsset> loadGltfFromBuffer(Uint8List data, T animationManager,
|
||||||
{int numInstances = 1,
|
{int numInstances = 1,
|
||||||
bool keepData = false,
|
bool keepData = false,
|
||||||
int priority = 4,
|
int priority = 4,
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ class BackgroundImage extends ThermionAsset {
|
|||||||
Future destroy() async {
|
Future destroy() async {
|
||||||
Scene_removeEntity(scene.scene, entity);
|
Scene_removeEntity(scene.scene, entity);
|
||||||
|
|
||||||
await texture!.dispose();
|
await texture?.dispose();
|
||||||
await sampler!.dispose();
|
await sampler?.dispose();
|
||||||
await mi.destroy();
|
await mi.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,6 +63,10 @@ class BackgroundImage extends ThermionAsset {
|
|||||||
await mi.setParameterFloat4("backgroundColor", r, g, b, a);
|
await mi.setParameterFloat4("backgroundColor", r, g, b, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future hideImage() async {
|
||||||
|
await mi.setParameterInt("showImage", 0);
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@@ -317,4 +321,25 @@ class BackgroundImage extends ThermionAsset {
|
|||||||
// TODO: implement updateBoneMatrices
|
// TODO: implement updateBoneMatrices
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<String>> getChildEntityNames() async {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<bool> isCastShadowsEnabled({ThermionEntity? entity}) async {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<bool> isReceiveShadowsEnabled({ThermionEntity? entity}) async {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future transformToUnitCube() {
|
||||||
|
// TODO: implement transformToUnitCube
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ Future<void> withVoidCallback2(Function() func) async {
|
|||||||
completer.complete();
|
completer.complete();
|
||||||
};
|
};
|
||||||
final nativeCallable = NativeCallable<Void Function()>.listener(callback);
|
final nativeCallable = NativeCallable<Void Function()>.listener(callback);
|
||||||
RenderLoop_addTask(nativeCallable.nativeFunction);
|
RenderThread_addTask(nativeCallable.nativeFunction);
|
||||||
await completer.future;
|
await completer.future;
|
||||||
nativeCallable.close();
|
nativeCallable.close();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,24 @@ class FFIAsset extends ThermionAsset {
|
|||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
@override
|
||||||
|
Future<List<String?>> getChildEntityNames() async {
|
||||||
|
final childEntities = await getChildEntities();
|
||||||
|
var names = <String?>[];
|
||||||
|
for (final entity in childEntities) {
|
||||||
|
var name = NameComponentManager_getName(app.nameComponentManager, entity);
|
||||||
|
if (name == nullptr) {
|
||||||
|
names.add(null);
|
||||||
|
} else {
|
||||||
|
names.add(name.cast<Utf8>().toDartString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@@ -392,14 +410,16 @@ class FFIAsset extends ThermionAsset {
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
Future<bool> isCastShadowsEnabled(ThermionEntity entity) async {
|
Future<bool> isCastShadowsEnabled({ThermionEntity? entity}) async {
|
||||||
|
entity ??= this.entity;
|
||||||
return RenderableManager_isShadowCaster(app.renderableManager, entity);
|
return RenderableManager_isShadowCaster(app.renderableManager, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
Future<bool> isReceiveShadowsEnabled(ThermionEntity entity) async {
|
Future<bool> isReceiveShadowsEnabled({ThermionEntity? entity}) async {
|
||||||
|
entity ??= this.entity;
|
||||||
return RenderableManager_isShadowReceiver(app.renderableManager, entity);
|
return RenderableManager_isShadowReceiver(app.renderableManager, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
|
|||||||
await FilamentApp.instance!.destroy();
|
await FilamentApp.instance!.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderLoop_destroy();
|
RenderThread_destroy();
|
||||||
RenderLoop_create();
|
RenderThread_create();
|
||||||
|
|
||||||
final engine = await withPointerCallback<TEngine>((cb) =>
|
final engine = await withPointerCallback<TEngine>((cb) =>
|
||||||
Engine_createRenderThread(
|
Engine_createRenderThread(
|
||||||
@@ -95,6 +95,8 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
|
|||||||
|
|
||||||
final renderTicker = RenderTicker_create(renderer);
|
final renderTicker = RenderTicker_create(renderer);
|
||||||
|
|
||||||
|
RenderThread_setRenderTicker(renderTicker);
|
||||||
|
|
||||||
final nameComponentManager = NameComponentManager_create();
|
final nameComponentManager = NameComponentManager_create();
|
||||||
|
|
||||||
FilamentApp.instance = FFIFilamentApp(
|
FilamentApp.instance = FFIFilamentApp(
|
||||||
@@ -110,30 +112,34 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
|
|||||||
config.resourceLoader);
|
config.resourceLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
final _views = <FFISwapChain, List<FFIView>>{};
|
final _swapChains = <FFISwapChain, List<FFIView>>{};
|
||||||
final _viewMappings = <FFIView, FFISwapChain>{};
|
final viewsPtr = calloc<Pointer<TView>>(255);
|
||||||
|
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
Future setRenderable(covariant FFIView view, bool renderable) async {
|
Future setRenderable(covariant FFIView view, bool renderable) async {
|
||||||
final swapChain = _viewMappings[view]!;
|
await view.setRenderable(renderable);
|
||||||
if (renderable && !_views[swapChain]!.contains(view)) {
|
await _updateRenderableSwapChains();
|
||||||
_views[swapChain]!.add(view);
|
}
|
||||||
} else if (!renderable && _views[swapChain]!.contains(view)) {
|
|
||||||
_views[swapChain]!.remove(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
final views = calloc<Pointer<TView>>(255);
|
Future _updateRenderableSwapChains() async {
|
||||||
for (final swapChain in _views.keys) {
|
for (final swapChain in _swapChains.keys) {
|
||||||
var numViews = _views[swapChain]!.length;
|
final views = _swapChains[swapChain];
|
||||||
for (int i = 0; i < numViews; i++) {
|
if (views == null) {
|
||||||
views[i] = _views[swapChain]![i].view;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int numRenderable = 0;
|
||||||
|
for (final view in views) {
|
||||||
|
if (view.renderable) {
|
||||||
|
viewsPtr[numRenderable] = view.view;
|
||||||
|
numRenderable++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
RenderTicker_setRenderable(
|
RenderTicker_setRenderable(
|
||||||
renderTicker, swapChain.swapChain, views, numViews);
|
renderTicker, swapChain.swapChain, viewsPtr, numRenderable);
|
||||||
}
|
}
|
||||||
calloc.free(views);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -143,6 +149,7 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
|
|||||||
if (hasStencilBuffer) {
|
if (hasStencilBuffer) {
|
||||||
flags |= TSWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER;
|
flags |= TSWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER;
|
||||||
}
|
}
|
||||||
|
print("swapchain flags $flags");
|
||||||
final swapChain = await withPointerCallback<TSwapChain>((cb) =>
|
final swapChain = await withPointerCallback<TSwapChain>((cb) =>
|
||||||
Engine_createHeadlessSwapChainRenderThread(
|
Engine_createHeadlessSwapChainRenderThread(
|
||||||
this.engine, width, height, flags, cb));
|
this.engine, width, height, flags, cb));
|
||||||
@@ -173,6 +180,7 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
|
|||||||
Engine_destroySwapChainRenderThread(
|
Engine_destroySwapChainRenderThread(
|
||||||
engine, (swapChain as FFISwapChain).swapChain, callback);
|
engine, (swapChain as FFISwapChain).swapChain, callback);
|
||||||
});
|
});
|
||||||
|
_swapChains.remove(swapChain);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -180,17 +188,21 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
|
|||||||
///
|
///
|
||||||
@override
|
@override
|
||||||
Future destroy() async {
|
Future destroy() async {
|
||||||
for (final swapChain in _views.keys) {
|
for (final swapChain in _swapChains.keys) {
|
||||||
for (final view in _views[swapChain]!) {
|
if (_swapChains[swapChain] == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (final view in _swapChains[swapChain]!) {
|
||||||
await setRenderable(view, false);
|
await setRenderable(view, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (final swapChain in _views.keys) {
|
for (final swapChain in _swapChains.keys.toList()) {
|
||||||
await destroySwapChain(swapChain);
|
await destroySwapChain(swapChain);
|
||||||
}
|
}
|
||||||
RenderLoop_destroy();
|
RenderThread_destroy();
|
||||||
RenderTicker_destroy(renderTicker);
|
RenderTicker_destroy(renderTicker);
|
||||||
Engine_destroy(engine);
|
Engine_destroy(engine);
|
||||||
|
calloc.free(viewsPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -440,8 +452,24 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
|
|||||||
///
|
///
|
||||||
@override
|
@override
|
||||||
Future render() async {
|
Future render() async {
|
||||||
await withVoidCallback(
|
// await withVoidCallback(
|
||||||
(cb) => RenderTicker_renderRenderThread(renderTicker, 0, cb));
|
// (cb) => RenderTicker_renderRenderThread(renderTicker, 0, cb));
|
||||||
|
final swapchain = _swapChains.keys.first;
|
||||||
|
final view = _swapChains[swapchain]!.first;
|
||||||
|
await withBoolCallback((cb) {
|
||||||
|
Renderer_beginFrameRenderThread(renderer, swapchain.swapChain, 0, cb);
|
||||||
|
});
|
||||||
|
await withVoidCallback((cb) {
|
||||||
|
Renderer_renderRenderThread(
|
||||||
|
renderer,
|
||||||
|
view.view,
|
||||||
|
cb,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
await withVoidCallback((cb) {
|
||||||
|
Renderer_endFrameRenderThread(renderer, cb);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -450,11 +478,11 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
|
|||||||
@override
|
@override
|
||||||
Future register(
|
Future register(
|
||||||
covariant FFISwapChain swapChain, covariant FFIView view) async {
|
covariant FFISwapChain swapChain, covariant FFIView view) async {
|
||||||
_viewMappings[view] = swapChain;
|
if (!_swapChains.containsKey(swapChain)) {
|
||||||
if (!_views.containsKey(swapChain)) {
|
_swapChains[swapChain] = [];
|
||||||
_views[swapChain] = [];
|
|
||||||
}
|
}
|
||||||
_views[swapChain]!.add(view);
|
_swapChains[swapChain]!.add(view);
|
||||||
|
await _updateRenderableSwapChains();
|
||||||
}
|
}
|
||||||
|
|
||||||
final _hooks = <Future Function()>[];
|
final _hooks = <Future Function()>[];
|
||||||
@@ -493,7 +521,7 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
|
|||||||
completer.complete(true);
|
completer.complete(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
RenderLoop_requestAnimationFrame(callback.nativeFunction.cast());
|
RenderThread_requestAnimationFrame(callback.nativeFunction.cast());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await completer.future.timeout(Duration(seconds: 1));
|
await completer.future.timeout(Duration(seconds: 1));
|
||||||
@@ -572,15 +600,20 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
|
|||||||
Future<Uint8List> capture(covariant FFIView view,
|
Future<Uint8List> capture(covariant FFIView view,
|
||||||
{bool captureRenderTarget = false}) async {
|
{bool captureRenderTarget = false}) async {
|
||||||
final viewport = await view.getViewport();
|
final viewport = await view.getViewport();
|
||||||
final swapChain = _viewMappings[view];
|
final swapChain = _swapChains.keys
|
||||||
|
.firstWhere((x) => _swapChains[x]?.contains(view) == true);
|
||||||
final out = Uint8List(viewport.width * viewport.height * 4);
|
final out = Uint8List(viewport.width * viewport.height * 4);
|
||||||
|
|
||||||
await withVoidCallback((cb) {
|
await withVoidCallback((cb) {
|
||||||
Engine_flushAndWaitRenderThead(engine, cb);
|
Engine_flushAndWaitRenderThead(engine, cb);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var fence = await withPointerCallback<TFence>((cb) {
|
||||||
|
Engine_createFenceRenderThread(engine, cb);
|
||||||
|
});
|
||||||
|
|
||||||
await withBoolCallback((cb) {
|
await withBoolCallback((cb) {
|
||||||
Renderer_beginFrameRenderThread(renderer, swapChain!.swapChain, 0, cb);
|
Renderer_beginFrameRenderThread(renderer, swapChain.swapChain, 0, cb);
|
||||||
});
|
});
|
||||||
await withVoidCallback((cb) {
|
await withVoidCallback((cb) {
|
||||||
Renderer_renderRenderThread(
|
Renderer_renderRenderThread(
|
||||||
@@ -607,9 +640,14 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
|
|||||||
await withVoidCallback((cb) {
|
await withVoidCallback((cb) {
|
||||||
Renderer_endFrameRenderThread(renderer, cb);
|
Renderer_endFrameRenderThread(renderer, cb);
|
||||||
});
|
});
|
||||||
|
|
||||||
await withVoidCallback((cb) {
|
await withVoidCallback((cb) {
|
||||||
Engine_flushAndWaitRenderThead(engine, cb);
|
Engine_destroyFenceRenderThread(engine, fence, cb);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// await withVoidCallback((cb) {
|
||||||
|
// Engine_flushAndWaitRenderThead(engine, cb);
|
||||||
|
// });
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -623,7 +661,7 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
Future<ThermionAsset> loadGlbFromBuffer(
|
Future<ThermionAsset> loadGltfFromBuffer(
|
||||||
Uint8List data, Pointer animationManager,
|
Uint8List data, Pointer animationManager,
|
||||||
{int numInstances = 1,
|
{int numInstances = 1,
|
||||||
bool keepData = false,
|
bool keepData = false,
|
||||||
@@ -631,7 +669,7 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
|
|||||||
int layer = 0,
|
int layer = 0,
|
||||||
String? relativeResourcePath,
|
String? relativeResourcePath,
|
||||||
bool loadResourcesAsync = false}) async {
|
bool loadResourcesAsync = false}) async {
|
||||||
if (relativeResourcePath != null && !relativeResourcePath!.endsWith("/")) {
|
if (relativeResourcePath != null && !relativeResourcePath.endsWith("/")) {
|
||||||
relativeResourcePath = "$relativeResourcePath/";
|
relativeResourcePath = "$relativeResourcePath/";
|
||||||
}
|
}
|
||||||
var gltfResourceLoader = await withPointerCallback<TGltfResourceLoader>(
|
var gltfResourceLoader = await withPointerCallback<TGltfResourceLoader>(
|
||||||
@@ -648,7 +686,6 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
|
|||||||
|
|
||||||
var resourceUris = SceneAsset_getResourceUris(asset);
|
var resourceUris = SceneAsset_getResourceUris(asset);
|
||||||
var resourceUriCount = SceneAsset_getResourceUriCount(asset);
|
var resourceUriCount = SceneAsset_getResourceUriCount(asset);
|
||||||
|
|
||||||
final resources = <FinalizableUint8List>[];
|
final resources = <FinalizableUint8List>[];
|
||||||
|
|
||||||
for (int i = 0; i < resourceUriCount; i++) {
|
for (int i = 0; i < resourceUriCount; i++) {
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ class FFIMaterialInstance extends MaterialInstance {
|
|||||||
completer.complete();
|
completer.complete();
|
||||||
};
|
};
|
||||||
final nativeCallable = NativeCallable<Void Function()>.listener(func);
|
final nativeCallable = NativeCallable<Void Function()>.listener(func);
|
||||||
RenderLoop_addTask(nativeCallable.nativeFunction);
|
RenderThread_addTask(nativeCallable.nativeFunction);
|
||||||
await completer.future;
|
await completer.future;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ class FFIView extends View {
|
|||||||
final Pointer<TView> view;
|
final Pointer<TView> view;
|
||||||
final FFIFilamentApp app;
|
final FFIFilamentApp app;
|
||||||
|
|
||||||
|
bool _renderable = false;
|
||||||
|
bool get renderable => _renderable;
|
||||||
|
|
||||||
FFIRenderTarget? renderTarget;
|
FFIRenderTarget? renderTarget;
|
||||||
|
|
||||||
FFIView(this.view, this.app) {
|
FFIView(this.view, this.app) {
|
||||||
@@ -20,8 +23,19 @@ class FFIView extends View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future setRenderable(bool renderable) async {
|
||||||
|
this._renderable = renderable;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future setViewport(int width, int height) async {
|
Future setViewport(int width, int height) async {
|
||||||
|
// var width_logbase2 = log(width) / ln2;
|
||||||
|
// var height_logbase2 = log(height) / ln2;
|
||||||
|
// var newWidth = pow(2.0, width_logbase2.ceil());
|
||||||
|
// var newHeight = pow(2.0, height_logbase2.ceil());
|
||||||
|
// print("old: ${width}x${height} new: ${height}x${newHeight}");
|
||||||
|
// width = newWidth.toInt();
|
||||||
|
// height = newHeight.toInt();
|
||||||
View_setViewport(view, width, height);
|
View_setViewport(view, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,8 +94,7 @@ class FFIView extends View {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future setToneMapper(ToneMapper mapper) async {
|
Future setToneMapper(ToneMapper mapper) async {
|
||||||
await withVoidCallback((cb) =>
|
await withVoidCallback((cb) => View_setToneMappingRenderThread(
|
||||||
View_setToneMappingRenderThread(
|
|
||||||
view, app.engine, TToneMapping.values[mapper.index], cb));
|
view, app.engine, TToneMapping.values[mapper.index], cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -473,6 +473,22 @@ external TViewport View_getViewport(
|
|||||||
ffi.Pointer<TView> view,
|
ffi.Pointer<TView> view,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.UnsignedInt)>(
|
||||||
|
symbol: "View_setBlendMode", isLeaf: true)
|
||||||
|
external void _View_setBlendMode(
|
||||||
|
ffi.Pointer<TView> view,
|
||||||
|
int blendMode,
|
||||||
|
);
|
||||||
|
|
||||||
|
void View_setBlendMode(
|
||||||
|
ffi.Pointer<TView> view,
|
||||||
|
TBlendMode blendMode,
|
||||||
|
) =>
|
||||||
|
_View_setBlendMode(
|
||||||
|
view,
|
||||||
|
blendMode.value,
|
||||||
|
);
|
||||||
|
|
||||||
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Uint32, ffi.Uint32)>(
|
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Uint32, ffi.Uint32)>(
|
||||||
isLeaf: true)
|
isLeaf: true)
|
||||||
external void View_setViewport(
|
external void View_setViewport(
|
||||||
@@ -1494,18 +1510,30 @@ external void RenderTicker_setRenderable(
|
|||||||
);
|
);
|
||||||
|
|
||||||
@ffi.Native<ffi.Void Function()>(isLeaf: true)
|
@ffi.Native<ffi.Void Function()>(isLeaf: true)
|
||||||
external void RenderLoop_create();
|
external void RenderThread_create();
|
||||||
|
|
||||||
@ffi.Native<ffi.Void Function()>(isLeaf: true)
|
@ffi.Native<ffi.Void Function()>(isLeaf: true)
|
||||||
external void RenderLoop_destroy();
|
external void RenderThread_destroy();
|
||||||
|
|
||||||
@ffi.Native<
|
@ffi.Native<
|
||||||
ffi.Void Function(
|
ffi.Void Function(
|
||||||
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
|
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
|
||||||
external void RenderLoop_requestAnimationFrame(
|
external void RenderThread_requestAnimationFrame(
|
||||||
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
|
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ffi.Native<ffi.Void Function(ffi.Pointer<TRenderTicker>)>(isLeaf: true)
|
||||||
|
external void RenderThread_setRenderTicker(
|
||||||
|
ffi.Pointer<TRenderTicker> tRenderTicker,
|
||||||
|
);
|
||||||
|
|
||||||
|
@ffi.Native<
|
||||||
|
ffi.Void Function(
|
||||||
|
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
|
||||||
|
external void RenderThread_addTask(
|
||||||
|
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> task,
|
||||||
|
);
|
||||||
|
|
||||||
@ffi.Native<
|
@ffi.Native<
|
||||||
ffi.Void Function(ffi.Pointer<TRenderTicker>, ffi.Uint64,
|
ffi.Void Function(ffi.Pointer<TRenderTicker>, ffi.Uint64,
|
||||||
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
|
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
|
||||||
@@ -1515,13 +1543,6 @@ external void RenderTicker_renderRenderThread(
|
|||||||
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
|
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ffi.Native<
|
|
||||||
ffi.Void Function(
|
|
||||||
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
|
|
||||||
external void RenderLoop_addTask(
|
|
||||||
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> task,
|
|
||||||
);
|
|
||||||
|
|
||||||
@ffi.Native<
|
@ffi.Native<
|
||||||
ffi.Void Function(
|
ffi.Void Function(
|
||||||
ffi.Pointer<TEngine>,
|
ffi.Pointer<TEngine>,
|
||||||
@@ -3212,6 +3233,13 @@ external ffi.Pointer<TAnimationManager> AnimationManager_create(
|
|||||||
ffi.Pointer<TScene> tScene,
|
ffi.Pointer<TScene> tScene,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ffi.Native<ffi.Void Function(ffi.Pointer<TAnimationManager>, ffi.Uint64)>(
|
||||||
|
isLeaf: true)
|
||||||
|
external void AnimationManager_update(
|
||||||
|
ffi.Pointer<TAnimationManager> tAnimationManager,
|
||||||
|
int frameTimeInNanos,
|
||||||
|
);
|
||||||
|
|
||||||
@ffi.Native<ffi.Void Function(ffi.Pointer<TAnimationManager>, EntityId)>(
|
@ffi.Native<ffi.Void Function(ffi.Pointer<TAnimationManager>, EntityId)>(
|
||||||
isLeaf: true)
|
isLeaf: true)
|
||||||
external void AnimationManager_addAnimationComponent(
|
external void AnimationManager_addAnimationComponent(
|
||||||
@@ -3951,6 +3979,20 @@ enum TQualityLevel {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum TBlendMode {
|
||||||
|
OPAQUE(0),
|
||||||
|
TRANSLUCENT(1);
|
||||||
|
|
||||||
|
final int value;
|
||||||
|
const TBlendMode(this.value);
|
||||||
|
|
||||||
|
static TBlendMode fromValue(int value) => switch (value) {
|
||||||
|
0 => OPAQUE,
|
||||||
|
1 => TRANSLUCENT,
|
||||||
|
_ => throw ArgumentError("Unknown value for TBlendMode: $value"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
typedef PickCallback = ffi.Pointer<ffi.NativeFunction<PickCallbackFunction>>;
|
typedef PickCallback = ffi.Pointer<ffi.NativeFunction<PickCallbackFunction>>;
|
||||||
typedef PickCallbackFunction = ffi.Void Function(
|
typedef PickCallbackFunction = ffi.Void Function(
|
||||||
ffi.Uint32 requestId,
|
ffi.Uint32 requestId,
|
||||||
|
|||||||
@@ -33,8 +33,6 @@ class ThermionViewerFFI extends ThermionViewer {
|
|||||||
|
|
||||||
late final FFIFilamentApp app;
|
late final FFIFilamentApp app;
|
||||||
|
|
||||||
final FFIRenderTarget? renderTarget;
|
|
||||||
|
|
||||||
late final FFIView view;
|
late final FFIView view;
|
||||||
late final FFIScene scene;
|
late final FFIScene scene;
|
||||||
late final Pointer<TAnimationManager> animationManager;
|
late final Pointer<TAnimationManager> animationManager;
|
||||||
@@ -43,7 +41,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
ThermionViewerFFI({required this.loadAssetFromUri, this.renderTarget}) {
|
ThermionViewerFFI({required this.loadAssetFromUri}) {
|
||||||
if (FilamentApp.instance == null) {
|
if (FilamentApp.instance == null) {
|
||||||
throw Exception("FilamentApp has not been created");
|
throw Exception("FilamentApp has not been created");
|
||||||
}
|
}
|
||||||
@@ -56,7 +54,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
Future setViewport(double width, double height) async {
|
Future setViewport(int width, int height) async {
|
||||||
await view.setViewport(width.toInt(), height.toInt());
|
await view.setViewport(width.toInt(), height.toInt());
|
||||||
|
|
||||||
for (final camera in _cameras) {
|
for (final camera in _cameras) {
|
||||||
@@ -69,12 +67,12 @@ class ThermionViewerFFI extends ThermionViewer {
|
|||||||
far = kFar;
|
far = kFar;
|
||||||
}
|
}
|
||||||
|
|
||||||
var aspect = width / height;
|
var aspect = width.toDouble() / height.toDouble();
|
||||||
var focalLength = await camera.getFocalLength();
|
var focalLength = await camera.getFocalLength();
|
||||||
if (focalLength.abs() < 0.1) {
|
if (focalLength.abs() < 0.1) {
|
||||||
focalLength = kFocalLength;
|
focalLength = kFocalLength;
|
||||||
}
|
}
|
||||||
camera.setLensProjection(
|
await camera.setLensProjection(
|
||||||
near: near, far: far, aspect: aspect, focalLength: focalLength);
|
near: near, far: far, aspect: aspect, focalLength: focalLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,6 +83,14 @@ class ThermionViewerFFI extends ThermionViewer {
|
|||||||
await withPointerCallback<TView>(
|
await withPointerCallback<TView>(
|
||||||
(cb) => Engine_createViewRenderThread(app.engine, cb)),
|
(cb) => Engine_createViewRenderThread(app.engine, cb)),
|
||||||
app);
|
app);
|
||||||
|
await view.setFrustumCullingEnabled(true);
|
||||||
|
View_setBlendMode(view.view, TBlendMode.TRANSLUCENT);
|
||||||
|
View_setShadowsEnabled(view.view, false);
|
||||||
|
View_setStencilBufferEnabled(view.view, false);
|
||||||
|
View_setAntiAliasing(view.view, false, false, false);
|
||||||
|
View_setDitheringEnabled(view.view, false);
|
||||||
|
View_setRenderQuality(view.view, TQualityLevel.MEDIUM);
|
||||||
|
await FilamentApp.instance!.setClearColor(1.0, 0.0, 0.0, 1.0);
|
||||||
scene = FFIScene(Engine_createScene(app.engine));
|
scene = FFIScene(Engine_createScene(app.engine));
|
||||||
await view.setScene(scene);
|
await view.setScene(scene);
|
||||||
final camera = FFICamera(
|
final camera = FFICamera(
|
||||||
@@ -92,12 +98,10 @@ class ThermionViewerFFI extends ThermionViewer {
|
|||||||
(cb) => Engine_createCameraRenderThread(app.engine, cb)),
|
(cb) => Engine_createCameraRenderThread(app.engine, cb)),
|
||||||
app);
|
app);
|
||||||
_cameras.add(camera);
|
_cameras.add(camera);
|
||||||
|
await camera.setLensProjection();
|
||||||
|
|
||||||
await view.setCamera(camera);
|
await view.setCamera(camera);
|
||||||
|
|
||||||
if (renderTarget != null) {
|
|
||||||
await view.setRenderTarget(renderTarget);
|
|
||||||
}
|
|
||||||
animationManager = await withPointerCallback<TAnimationManager>((cb) =>
|
animationManager = await withPointerCallback<TAnimationManager>((cb) =>
|
||||||
AnimationManager_createRenderThread(app.engine, scene.scene, cb));
|
AnimationManager_createRenderThread(app.engine, scene.scene, cb));
|
||||||
|
|
||||||
@@ -180,9 +184,13 @@ class ThermionViewerFFI extends ThermionViewer {
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
@override
|
@override
|
||||||
Future clearBackgroundImage() async {
|
Future clearBackgroundImage({bool destroy = false}) async {
|
||||||
await _backgroundImage?.destroy();
|
if (destroy) {
|
||||||
_backgroundImage = null;
|
await _backgroundImage?.destroy();
|
||||||
|
_backgroundImage = null;
|
||||||
|
} else {
|
||||||
|
_backgroundImage?.hideImage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -335,7 +343,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
|||||||
///
|
///
|
||||||
@override
|
@override
|
||||||
Future destroyLights() async {
|
Future destroyLights() async {
|
||||||
for (final light in _lights) {
|
for (final light in _lights.toList()) {
|
||||||
await removeLight(light);
|
await removeLight(light);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -347,37 +355,45 @@ class ThermionViewerFFI extends ThermionViewer {
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
@override
|
@override
|
||||||
Future<ThermionAsset> loadGlb(String path,
|
Future<ThermionAsset> loadGltf(String path,
|
||||||
{int numInstances = 1, bool keepData = false, String? relativeResourcePath}) async {
|
{bool addToScene = true,
|
||||||
|
int numInstances = 1,
|
||||||
|
bool keepData = false,
|
||||||
|
String? relativeResourcePath}) async {
|
||||||
final data = await loadAssetFromUri(path);
|
final data = await loadAssetFromUri(path);
|
||||||
|
|
||||||
return loadGlbFromBuffer(data,
|
return loadGltfFromBuffer(data,
|
||||||
numInstances: numInstances, keepData: keepData, relativeResourcePath: relativeResourcePath);
|
addToScene: addToScene,
|
||||||
|
numInstances: numInstances,
|
||||||
|
keepData: keepData,
|
||||||
|
relativeResourcePath: relativeResourcePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@override
|
@override
|
||||||
Future<ThermionAsset> loadGlbFromBuffer(Uint8List data,
|
Future<ThermionAsset> loadGltfFromBuffer(Uint8List data,
|
||||||
{int numInstances = 1,
|
{bool addToScene = true,
|
||||||
|
int numInstances = 1,
|
||||||
bool keepData = false,
|
bool keepData = false,
|
||||||
int priority = 4,
|
int priority = 4,
|
||||||
int layer = 0,
|
int layer = 0,
|
||||||
bool loadResourcesAsync = false,
|
bool loadResourcesAsync = false,
|
||||||
String? relativeResourcePath}) async {
|
String? relativeResourcePath}) async {
|
||||||
var asset = await FilamentApp.instance!.loadGlbFromBuffer(data, animationManager,
|
var asset = await FilamentApp.instance!.loadGltfFromBuffer(
|
||||||
|
data, animationManager,
|
||||||
numInstances: numInstances,
|
numInstances: numInstances,
|
||||||
keepData: keepData,
|
keepData: keepData,
|
||||||
priority: priority,
|
priority: priority,
|
||||||
layer: layer,
|
layer: layer,
|
||||||
loadResourcesAsync: loadResourcesAsync,
|
loadResourcesAsync: loadResourcesAsync,
|
||||||
relativeResourcePath:relativeResourcePath
|
relativeResourcePath: relativeResourcePath) as FFIAsset;
|
||||||
) as FFIAsset;
|
|
||||||
|
|
||||||
_assets.add(asset);
|
|
||||||
|
|
||||||
await scene.add(asset);
|
_assets.add(asset);
|
||||||
|
if (addToScene) {
|
||||||
|
await scene.add(asset);
|
||||||
|
}
|
||||||
|
|
||||||
return asset;
|
return asset;
|
||||||
}
|
}
|
||||||
@@ -424,6 +440,8 @@ class ThermionViewerFFI extends ThermionViewer {
|
|||||||
@override
|
@override
|
||||||
Future setPostProcessing(bool enabled) async {
|
Future setPostProcessing(bool enabled) async {
|
||||||
View_setPostProcessing(view.view, enabled);
|
View_setPostProcessing(view.view, enabled);
|
||||||
|
await withVoidCallback(
|
||||||
|
(cb) => Engine_flushAndWaitRenderThead(app.engine, cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -655,7 +673,8 @@ class ThermionViewerFFI extends ThermionViewer {
|
|||||||
@override
|
@override
|
||||||
Future<ThermionAsset> createGeometry(Geometry geometry,
|
Future<ThermionAsset> createGeometry(Geometry geometry,
|
||||||
{List<MaterialInstance>? materialInstances,
|
{List<MaterialInstance>? materialInstances,
|
||||||
bool keepData = false}) async {
|
bool keepData = false,
|
||||||
|
bool addToScene = true}) async {
|
||||||
var assetPtr = await withPointerCallback<TSceneAsset>((callback) {
|
var assetPtr = await withPointerCallback<TSceneAsset>((callback) {
|
||||||
var ptrList = Int64List(materialInstances?.length ?? 0);
|
var ptrList = Int64List(materialInstances?.length ?? 0);
|
||||||
if (materialInstances != null && materialInstances.isNotEmpty) {
|
if (materialInstances != null && materialInstances.isNotEmpty) {
|
||||||
@@ -688,7 +707,9 @@ class ThermionViewerFFI extends ThermionViewer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var asset = FFIAsset(assetPtr, app, animationManager);
|
var asset = FFIAsset(assetPtr, app, animationManager);
|
||||||
|
if (addToScene) {
|
||||||
|
await scene.add(asset);
|
||||||
|
}
|
||||||
return asset;
|
return asset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ abstract class ThermionViewer {
|
|||||||
///
|
///
|
||||||
/// Removes the background image.
|
/// Removes the background image.
|
||||||
///
|
///
|
||||||
Future clearBackgroundImage();
|
Future clearBackgroundImage({bool destroy = false});
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Sets the color for the background plane (positioned at the maximum depth, i.e. behind all other objects including the skybox).
|
/// Sets the color for the background plane (positioned at the maximum depth, i.e. behind all other objects including the skybox).
|
||||||
@@ -128,10 +128,11 @@ abstract class ThermionViewer {
|
|||||||
/// If you want to be able to call [createInstance] at a later time, you must pass true for [keepData].
|
/// 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 [keepData] is false, the source glTF data will be released and [createInstance] will throw an exception.
|
||||||
///
|
///
|
||||||
Future<ThermionAsset> loadGlb(String path,
|
Future<ThermionAsset> loadGltf(String path,
|
||||||
{int numInstances = 1,
|
{ bool addToScene=true,
|
||||||
|
int numInstances = 1,
|
||||||
bool keepData = false,
|
bool keepData = false,
|
||||||
String relativeResourcePath});
|
String? relativeResourcePath});
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Load the .glb asset from the specified buffer, adding all entities to the scene.
|
/// Load the .glb asset from the specified buffer, adding all entities to the scene.
|
||||||
@@ -142,7 +143,7 @@ abstract class ThermionViewer {
|
|||||||
/// be loaded asynchronously (so expect some material/texture pop-in);
|
/// be loaded asynchronously (so expect some material/texture pop-in);
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
Future<ThermionAsset> loadGlbFromBuffer(Uint8List data,
|
Future<ThermionAsset> loadGltfFromBuffer(Uint8List data,
|
||||||
{int numInstances = 1,
|
{int numInstances = 1,
|
||||||
bool keepData = false,
|
bool keepData = false,
|
||||||
int priority = 4,
|
int priority = 4,
|
||||||
@@ -177,6 +178,11 @@ abstract class ThermionViewer {
|
|||||||
///
|
///
|
||||||
Future setViewFrustumCulling(bool enabled);
|
Future setViewFrustumCulling(bool enabled);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Sets the viewport sizes and updates all cameras to use the new aspect ratio.
|
||||||
|
///
|
||||||
|
Future setViewport(int width, int height);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Set the world space position for [lightEntity] to the given coordinates.
|
/// Set the world space position for [lightEntity] to the given coordinates.
|
||||||
///
|
///
|
||||||
@@ -230,7 +236,7 @@ abstract class ThermionViewer {
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
Future<ThermionAsset> createGeometry(Geometry geometry,
|
Future<ThermionAsset> createGeometry(Geometry geometry,
|
||||||
{List<MaterialInstance>? materialInstances, bool keepData = false});
|
{List<MaterialInstance>? materialInstances, bool keepData = false, bool addToScene=true});
|
||||||
|
|
||||||
///
|
///
|
||||||
/// The gizmo for translating/rotating objects. Only one gizmo can be active for a given view.
|
/// The gizmo for translating/rotating objects. Only one gizmo can be active for a given view.
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ class ThermionViewerStub extends ThermionViewer {
|
|||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future addToScene(covariant ThermionAsset asset) {
|
||||||
|
// TODO: implement addToScene
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future clearBackgroundImage() {
|
Future clearBackgroundImage() {
|
||||||
// TODO: implement clearBackgroundImage
|
// TODO: implement clearBackgroundImage
|
||||||
@@ -21,12 +27,6 @@ class ThermionViewerStub extends ThermionViewer {
|
|||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<ThermionAsset> createGeometry(Geometry geometry, {List<MaterialInstance>? materialInstances, bool keepData = false}) {
|
|
||||||
// TODO: implement createGeometry
|
|
||||||
throw UnimplementedError();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<GizmoAsset> createGizmo(covariant View view, GizmoType type) {
|
Future<GizmoAsset> createGizmo(covariant View view, GizmoType type) {
|
||||||
// TODO: implement createGizmo
|
// TODO: implement createGizmo
|
||||||
@@ -92,23 +92,17 @@ class ThermionViewerStub extends ThermionViewer {
|
|||||||
Future<bool> get initialized => throw UnimplementedError();
|
Future<bool> get initialized => throw UnimplementedError();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<ThermionAsset> loadGlb(String path, {int numInstances = 1, bool keepData = false}) {
|
Future<ThermionAsset> loadGltf(String path, {int numInstances = 1, bool keepData = false, String? relativeResourcePath}) {
|
||||||
// TODO: implement loadGlb
|
|
||||||
throw UnimplementedError();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<ThermionAsset> loadGlbFromBuffer(Uint8List data, {int numInstances = 1, bool keepData = false, int priority = 4, int layer = 0, bool loadResourcesAsync = false}) {
|
|
||||||
// TODO: implement loadGlbFromBuffer
|
|
||||||
throw UnimplementedError();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<ThermionAsset> loadGltf(String path, String relativeResourcePath, {bool keepData = false}) {
|
|
||||||
// TODO: implement loadGltf
|
// TODO: implement loadGltf
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<ThermionAsset> loadGltfFromBuffer(Uint8List data, {int numInstances = 1, bool keepData = false, int priority = 4, int layer = 0, bool loadResourcesAsync = false, String? relativeResourcePath}) {
|
||||||
|
// TODO: implement loadGltfFromBuffer
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future loadIbl(String lightingPath, {double intensity = 30000}) {
|
Future loadIbl(String lightingPath, {double intensity = 30000}) {
|
||||||
// TODO: implement loadIbl
|
// TODO: implement loadIbl
|
||||||
@@ -136,6 +130,12 @@ class ThermionViewerStub extends ThermionViewer {
|
|||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future removeFromScene(covariant ThermionAsset asset) {
|
||||||
|
// TODO: implement removeFromScene
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future removeGridOverlay() {
|
Future removeGridOverlay() {
|
||||||
// TODO: implement removeGridOverlay
|
// TODO: implement removeGridOverlay
|
||||||
@@ -287,5 +287,5 @@ class ThermionViewerStub extends ThermionViewer {
|
|||||||
@override
|
@override
|
||||||
// TODO: implement view
|
// TODO: implement view
|
||||||
View get view => throw UnimplementedError();
|
View get view => throw UnimplementedError();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,3 +4,4 @@ export 'package:vector_math/vector_math_64.dart' hide Colors;
|
|||||||
export 'src/viewer/viewer.dart';
|
export 'src/viewer/viewer.dart';
|
||||||
export 'src/input/input.dart';
|
export 'src/input/input.dart';
|
||||||
export 'src/utils/utils.dart';
|
export 'src/utils/utils.dart';
|
||||||
|
export 'src/filament/filament.dart';
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ extern "C"
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE TAnimationManager *AnimationManager_create(TEngine *tEngine, TScene *tScene);
|
EMSCRIPTEN_KEEPALIVE TAnimationManager *AnimationManager_create(TEngine *tEngine, TScene *tScene);
|
||||||
|
|
||||||
|
EMSCRIPTEN_KEEPALIVE void AnimationManager_update(TAnimationManager *tAnimationManager, uint64_t frameTimeInNanos);
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_addAnimationComponent(TAnimationManager *tAnimationManager, EntityId entityId);
|
EMSCRIPTEN_KEEPALIVE void AnimationManager_addAnimationComponent(TAnimationManager *tAnimationManager, EntityId entityId);
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,14 @@ enum TQualityLevel {
|
|||||||
ULTRA
|
ULTRA
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum TBlendMode {
|
||||||
|
OPAQUE,
|
||||||
|
TRANSLUCENT
|
||||||
|
};
|
||||||
|
|
||||||
// View
|
// View
|
||||||
EMSCRIPTEN_KEEPALIVE TViewport View_getViewport(TView *view);
|
EMSCRIPTEN_KEEPALIVE TViewport View_getViewport(TView *view);
|
||||||
|
EMSCRIPTEN_KEEPALIVE void View_setBlendMode(TView *view, TBlendMode blendMode);
|
||||||
EMSCRIPTEN_KEEPALIVE void View_setViewport(TView *view, uint32_t width, uint32_t height);
|
EMSCRIPTEN_KEEPALIVE void View_setViewport(TView *view, uint32_t width, uint32_t height);
|
||||||
EMSCRIPTEN_KEEPALIVE void View_setRenderTarget(TView *view, TRenderTarget *renderTarget);
|
EMSCRIPTEN_KEEPALIVE void View_setRenderTarget(TView *view, TRenderTarget *renderTarget);
|
||||||
EMSCRIPTEN_KEEPALIVE void View_setFrustumCullingEnabled(TView *view, bool enabled);
|
EMSCRIPTEN_KEEPALIVE void View_setFrustumCullingEnabled(TView *view, bool enabled);
|
||||||
|
|||||||
@@ -14,12 +14,13 @@ namespace thermion
|
|||||||
typedef int32_t EntityId;
|
typedef int32_t EntityId;
|
||||||
typedef void (*FilamentRenderCallback)(void *const owner);
|
typedef void (*FilamentRenderCallback)(void *const owner);
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void RenderLoop_create();
|
EMSCRIPTEN_KEEPALIVE void RenderThread_create();
|
||||||
EMSCRIPTEN_KEEPALIVE void RenderLoop_destroy();
|
EMSCRIPTEN_KEEPALIVE void RenderThread_destroy();
|
||||||
EMSCRIPTEN_KEEPALIVE void RenderLoop_requestAnimationFrame(void (*onComplete)());
|
EMSCRIPTEN_KEEPALIVE void RenderThread_requestAnimationFrame(void (*onComplete)());
|
||||||
|
EMSCRIPTEN_KEEPALIVE void RenderThread_setRenderTicker(TRenderTicker *tRenderTicker);
|
||||||
|
EMSCRIPTEN_KEEPALIVE void RenderThread_addTask(void (*task)());
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void RenderTicker_renderRenderThread(TRenderTicker *tRenderTicker, uint64_t frameTimeInNanos, void (*onComplete)());
|
EMSCRIPTEN_KEEPALIVE void RenderTicker_renderRenderThread(TRenderTicker *tRenderTicker, uint64_t frameTimeInNanos, void (*onComplete)());
|
||||||
EMSCRIPTEN_KEEPALIVE void RenderLoop_addTask(void (*task)());
|
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_createRenderThread(TEngine *tEngine, TScene *tScene, void (*onComplete)(TAnimationManager *));
|
EMSCRIPTEN_KEEPALIVE void AnimationManager_createRenderThread(TEngine *tEngine, TScene *tScene, void (*onComplete)(TAnimationManager *));
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Engine_createRenderThread(
|
EMSCRIPTEN_KEEPALIVE void Engine_createRenderThread(
|
||||||
|
|||||||
@@ -17,17 +17,17 @@ namespace thermion {
|
|||||||
* This class handles frame rendering requests, viewer creation, and maintains
|
* This class handles frame rendering requests, viewer creation, and maintains
|
||||||
* a task queue for rendering operations.
|
* a task queue for rendering operations.
|
||||||
*/
|
*/
|
||||||
class RenderLoop {
|
class RenderThread {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Constructs a new RenderLoop and starts the render thread.
|
* @brief Constructs a new RenderThread and starts the render thread.
|
||||||
*/
|
*/
|
||||||
explicit RenderLoop();
|
explicit RenderThread();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destroys the RenderLoop and stops the render thread.
|
* @brief Destroys the RenderThread and stops the render thread.
|
||||||
*/
|
*/
|
||||||
~RenderLoop();
|
~RenderThread();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Requests a frame to be rendered.
|
* @brief Requests a frame to be rendered.
|
||||||
@@ -74,7 +74,7 @@ private:
|
|||||||
|
|
||||||
// Template implementation
|
// Template implementation
|
||||||
template <class Rt>
|
template <class Rt>
|
||||||
auto RenderLoop::add_task(std::packaged_task<Rt()>& pt) -> std::future<Rt> {
|
auto RenderThread::add_task(std::packaged_task<Rt()>& pt) -> std::future<Rt> {
|
||||||
std::unique_lock<std::mutex> lock(_taskMutex);
|
std::unique_lock<std::mutex> lock(_taskMutex);
|
||||||
auto ret = pt.get_future();
|
auto ret = pt.get_future();
|
||||||
_tasks.push_back([pt = std::make_shared<std::packaged_task<Rt()>>(
|
_tasks.push_back([pt = std::make_shared<std::packaged_task<Rt()>>(
|
||||||
@@ -69,12 +69,21 @@ namespace thermion
|
|||||||
|
|
||||||
for (auto animationManager : mAnimationManagers) {
|
for (auto animationManager : mAnimationManagers) {
|
||||||
animationManager->update(frameTimeInNanos);
|
animationManager->update(frameTimeInNanos);
|
||||||
}
|
TRACE("Updated AnimationManager");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_TRACING
|
||||||
|
int numRendered = 0;
|
||||||
|
TRACE("%d swapchains", mRenderable.size());
|
||||||
|
#endif
|
||||||
|
|
||||||
for (const auto& [swapChain, views] : mRenderable)
|
for (const auto& [swapChain, views] : mRenderable)
|
||||||
{
|
{
|
||||||
if (!views.empty())
|
if (!views.empty())
|
||||||
{
|
{
|
||||||
|
TRACE("Rendering %d views", views.size());
|
||||||
|
|
||||||
bool beginFrame = mRenderer->beginFrame(swapChain, frameTimeInNanos);
|
bool beginFrame = mRenderer->beginFrame(swapChain, frameTimeInNanos);
|
||||||
if (beginFrame)
|
if (beginFrame)
|
||||||
{
|
{
|
||||||
@@ -84,7 +93,15 @@ namespace thermion
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mRenderer->endFrame();
|
mRenderer->endFrame();
|
||||||
|
#ifdef ENABLE_TRACING
|
||||||
|
numRendered++;
|
||||||
|
} else {
|
||||||
|
TRACE("No views for swapchain");
|
||||||
}
|
}
|
||||||
|
TRACE("%d swapchains rendered", numRendered);
|
||||||
|
#else
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
_engine->execute();
|
_engine->execute();
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ extern "C"
|
|||||||
return reinterpret_cast<TAnimationManager *>(animationManager);
|
return reinterpret_cast<TAnimationManager *>(animationManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EMSCRIPTEN_KEEPALIVE void AnimationManager_update(TAnimationManager *tAnimationManager, uint64_t frameTimeInNanos) {
|
||||||
|
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||||
|
animationManager->update(frameTimeInNanos);
|
||||||
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_addAnimationComponent(TAnimationManager *tAnimationManager, EntityId entityId)
|
EMSCRIPTEN_KEEPALIVE void AnimationManager_addAnimationComponent(TAnimationManager *tAnimationManager, EntityId entityId)
|
||||||
{
|
{
|
||||||
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
auto animationManager = reinterpret_cast<AnimationManager *>(tAnimationManager);
|
||||||
|
|||||||
@@ -80,14 +80,38 @@ namespace thermion
|
|||||||
EMSCRIPTEN_KEEPALIVE TSwapChain *Engine_createSwapChain(TEngine *tEngine, void *window, uint64_t flags)
|
EMSCRIPTEN_KEEPALIVE TSwapChain *Engine_createSwapChain(TEngine *tEngine, void *window, uint64_t flags)
|
||||||
{
|
{
|
||||||
auto *engine = reinterpret_cast<Engine *>(tEngine);
|
auto *engine = reinterpret_cast<Engine *>(tEngine);
|
||||||
|
#ifdef ENABLE_TRACING
|
||||||
|
if((flags & filament::backend::SWAP_CHAIN_CONFIG_TRANSPARENT) == filament::backend::SWAP_CHAIN_CONFIG_TRANSPARENT) {
|
||||||
|
TRACE("SWAP_CHAIN_CONFIG_TRANSPARENT");
|
||||||
|
|
||||||
|
}
|
||||||
|
if((flags & filament::backend::SWAP_CHAIN_CONFIG_READABLE) == filament::backend::SWAP_CHAIN_CONFIG_READABLE) {
|
||||||
|
TRACE("SWAP_CHAIN_CONFIG_READABLE");
|
||||||
|
}
|
||||||
|
if((flags & filament::backend::SWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER) == filament::backend::SWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER) {
|
||||||
|
TRACE("SWAP_CHAIN_CONFIG_READABLE");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
auto *swapChain = engine->createSwapChain(window, flags);
|
auto *swapChain = engine->createSwapChain(window, flags);
|
||||||
return reinterpret_cast<TSwapChain *>(swapChain);
|
return reinterpret_cast<TSwapChain *>(swapChain);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE TSwapChain *Engine_createHeadlessSwapChain(TEngine *tEngine, uint32_t width, uint32_t height, uint64_t flags)
|
EMSCRIPTEN_KEEPALIVE TSwapChain *Engine_createHeadlessSwapChain(TEngine *tEngine, uint32_t width, uint32_t height, uint64_t flags)
|
||||||
{
|
{
|
||||||
|
TRACE("Creating headless swapchain %dx%d, flags %flags", width, height, flags);
|
||||||
auto *engine = reinterpret_cast<Engine *>(tEngine);
|
auto *engine = reinterpret_cast<Engine *>(tEngine);
|
||||||
auto *swapChain = engine->createSwapChain(width, height, flags);
|
auto *swapChain = engine->createSwapChain(width, height, flags);
|
||||||
|
#ifdef ENABLE_TRACING
|
||||||
|
if((flags & filament::backend::SWAP_CHAIN_CONFIG_TRANSPARENT) == filament::backend::SWAP_CHAIN_CONFIG_TRANSPARENT) {
|
||||||
|
TRACE("SWAP_CHAIN_CONFIG_TRANSPARENT");
|
||||||
|
}
|
||||||
|
if((flags & filament::backend::SWAP_CHAIN_CONFIG_READABLE) == filament::backend::SWAP_CHAIN_CONFIG_READABLE) {
|
||||||
|
TRACE("SWAP_CHAIN_CONFIG_READABLE");
|
||||||
|
}
|
||||||
|
if((flags & filament::backend::SWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER) == filament::backend::SWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER) {
|
||||||
|
TRACE("SWAP_CHAIN_CONFIG_READABLE");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return reinterpret_cast<TSwapChain *>(swapChain);
|
return reinterpret_cast<TSwapChain *>(swapChain);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,6 +125,9 @@ namespace thermion
|
|||||||
{
|
{
|
||||||
auto *engine = reinterpret_cast<Engine *>(tEngine);
|
auto *engine = reinterpret_cast<Engine *>(tEngine);
|
||||||
auto *view = engine->createView();
|
auto *view = engine->createView();
|
||||||
|
view->setShadowingEnabled(false);
|
||||||
|
view->setAmbientOcclusionOptions({.enabled = false});
|
||||||
|
view->setDynamicResolutionOptions({.enabled = false});
|
||||||
return reinterpret_cast<TView *>(view);
|
return reinterpret_cast<TView *>(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,10 +14,14 @@ extern "C"
|
|||||||
return reinterpret_cast<TNameComponentManager *>(ncm);
|
return reinterpret_cast<TNameComponentManager *>(ncm);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE const char *NameComponentManager_getName(TNameComponentManager *tNameComponentManager, EntityId entity)
|
EMSCRIPTEN_KEEPALIVE const char *NameComponentManager_getName(TNameComponentManager *tNameComponentManager, EntityId entityId)
|
||||||
{
|
{
|
||||||
auto ncm = reinterpret_cast<utils::NameComponentManager *>(tNameComponentManager);
|
auto ncm = reinterpret_cast<utils::NameComponentManager *>(tNameComponentManager);
|
||||||
auto instance = ncm->getInstance(utils::Entity::import(entity));
|
auto entity = utils::Entity::import(entityId);
|
||||||
|
if(!ncm->hasComponent(entity)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto instance = ncm->getInstance(entity);
|
||||||
return ncm->getName(instance);
|
return ncm->getName(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,11 @@ using namespace filament;
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
EMSCRIPTEN_KEEPALIVE void View_setBlendMode(TView *tView, TBlendMode tBlendMode) {
|
||||||
|
auto view = reinterpret_cast<View *>(tView);
|
||||||
|
view->setBlendMode(static_cast<filament::View::BlendMode>(tBlendMode));
|
||||||
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE TViewport View_getViewport(TView *tView)
|
EMSCRIPTEN_KEEPALIVE TViewport View_getViewport(TView *tView)
|
||||||
{
|
{
|
||||||
auto view = reinterpret_cast<View *>(tView);
|
auto view = reinterpret_cast<View *>(tView);
|
||||||
@@ -58,6 +63,8 @@ using namespace filament;
|
|||||||
{
|
{
|
||||||
auto view = reinterpret_cast<View *>(tView);
|
auto view = reinterpret_cast<View *>(tView);
|
||||||
view->setPostProcessingEnabled(enabled);
|
view->setPostProcessingEnabled(enabled);
|
||||||
|
TRACE("Set postprocessing enabled : %d", enabled);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void View_setShadowsEnabled(TView *tView, bool enabled)
|
EMSCRIPTEN_KEEPALIVE void View_setShadowsEnabled(TView *tView, bool enabled)
|
||||||
@@ -88,6 +95,7 @@ using namespace filament;
|
|||||||
decltype(view->getBloomOptions()) opts;
|
decltype(view->getBloomOptions()) opts;
|
||||||
opts.enabled = enabled;
|
opts.enabled = enabled;
|
||||||
opts.strength = strength;
|
opts.strength = strength;
|
||||||
|
TRACE("Setting bloom options {.enabled = %d, strength = %f}", enabled, strength);
|
||||||
view->setBloomOptions(opts);
|
view->setBloomOptions(opts);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -101,19 +109,19 @@ using namespace filament;
|
|||||||
switch (tToneMapping)
|
switch (tToneMapping)
|
||||||
{
|
{
|
||||||
case TToneMapping::ACES:
|
case TToneMapping::ACES:
|
||||||
Log("Setting tone mapping to ACES");
|
TRACE("Setting tone mapping to ACES");
|
||||||
tm = new ACESToneMapper();
|
tm = new ACESToneMapper();
|
||||||
break;
|
break;
|
||||||
case TToneMapping::LINEAR:
|
case TToneMapping::LINEAR:
|
||||||
Log("Setting tone mapping to Linear");
|
TRACE("Setting tone mapping to Linear");
|
||||||
tm = new LinearToneMapper();
|
tm = new LinearToneMapper();
|
||||||
break;
|
break;
|
||||||
case TToneMapping::FILMIC:
|
case TToneMapping::FILMIC:
|
||||||
Log("Setting tone mapping to Filmic");
|
TRACE("Setting tone mapping to Filmic");
|
||||||
tm = new FilmicToneMapper();
|
tm = new FilmicToneMapper();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log("ERROR: Unsupported tone mapping");
|
TRACE("ERROR: Unsupported tone mapping");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto newColorGrading = ColorGrading::Builder().toneMapper(tm).build(*engine);
|
auto newColorGrading = ColorGrading::Builder().toneMapper(tm).build(*engine);
|
||||||
@@ -200,6 +208,21 @@ using namespace filament;
|
|||||||
auto view = reinterpret_cast<View *>(tView);
|
auto view = reinterpret_cast<View *>(tView);
|
||||||
RenderQuality rq;
|
RenderQuality rq;
|
||||||
rq.hdrColorBuffer = (filament::QualityLevel)qualityLevel;
|
rq.hdrColorBuffer = (filament::QualityLevel)qualityLevel;
|
||||||
|
switch(rq.hdrColorBuffer) {
|
||||||
|
case filament::QualityLevel::LOW:
|
||||||
|
TRACE("Render Quality: LOW");
|
||||||
|
break;
|
||||||
|
case filament::QualityLevel::MEDIUM:
|
||||||
|
TRACE("Render Quality: MEDIUM");
|
||||||
|
break;
|
||||||
|
case filament::QualityLevel::HIGH:
|
||||||
|
TRACE("Render Quality: HIGH");
|
||||||
|
break;
|
||||||
|
case filament::QualityLevel::ULTRA:
|
||||||
|
TRACE("Render Quality: ULTRA");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
view->setRenderQuality(rq);
|
view->setRenderQuality(rq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
#include "c_api/TView.h"
|
#include "c_api/TView.h"
|
||||||
#include "c_api/ThermionDartRenderThreadApi.h"
|
#include "c_api/ThermionDartRenderThreadApi.h"
|
||||||
|
|
||||||
#include "rendering/RenderLoop.hpp"
|
#include "rendering/RenderThread.hpp"
|
||||||
#include "Log.hpp"
|
#include "Log.hpp"
|
||||||
|
|
||||||
using namespace thermion;
|
using namespace thermion;
|
||||||
@@ -29,36 +29,41 @@ using namespace std::chrono_literals;
|
|||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
|
||||||
static std::unique_ptr<RenderLoop> _rl;
|
static std::unique_ptr<RenderThread> _renderThread;
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void RenderLoop_create() {
|
EMSCRIPTEN_KEEPALIVE void RenderThread_create() {
|
||||||
TRACE("RenderLoop_create");
|
TRACE("RenderThread_create");
|
||||||
if (_rl)
|
if (_renderThread)
|
||||||
{
|
{
|
||||||
Log("WARNING - you are attempting to create a RenderLoop when the previous one has not been disposed.");
|
Log("WARNING - you are attempting to create a RenderThread when the previous one has not been disposed.");
|
||||||
}
|
}
|
||||||
_rl = std::make_unique<RenderLoop>();
|
_renderThread = std::make_unique<RenderThread>();
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void RenderLoop_destroy() {
|
EMSCRIPTEN_KEEPALIVE void RenderThread_destroy() {
|
||||||
TRACE("RenderLoop_destroy");
|
TRACE("RenderThread_destroy");
|
||||||
if (_rl)
|
if (_renderThread)
|
||||||
{
|
{
|
||||||
_rl = nullptr;
|
_renderThread = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void RenderLoop_addTask(void (*task)()) {
|
EMSCRIPTEN_KEEPALIVE void RenderThread_addTask(void (*task)()) {
|
||||||
std::packaged_task<void()> lambda(
|
std::packaged_task<void()> lambda(
|
||||||
[=]() mutable
|
[=]() mutable
|
||||||
{
|
{
|
||||||
task();
|
task();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void RenderLoop_requestAnimationFrame(void (*onComplete)()) {
|
EMSCRIPTEN_KEEPALIVE void RenderThread_setRenderTicker(TRenderTicker *tRenderTicker) {
|
||||||
_rl->requestFrame(onComplete);
|
auto *renderTicker = reinterpret_cast<RenderTicker *>(tRenderTicker);
|
||||||
|
_renderThread->setRenderTicker(renderTicker);
|
||||||
|
}
|
||||||
|
|
||||||
|
EMSCRIPTEN_KEEPALIVE void RenderThread_requestAnimationFrame(void (*onComplete)()) {
|
||||||
|
_renderThread->requestFrame(onComplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -69,7 +74,7 @@ extern "C"
|
|||||||
RenderTicker_render(tRenderTicker, frameTimeInNanos);
|
RenderTicker_render(tRenderTicker, frameTimeInNanos);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Engine_createRenderThread(
|
EMSCRIPTEN_KEEPALIVE void Engine_createRenderThread(
|
||||||
@@ -85,7 +90,7 @@ extern "C"
|
|||||||
auto engine = Engine_create(backend, platform, sharedContext, stereoscopicEyeCount, disableHandleUseAfterFreeCheck);
|
auto engine = Engine_create(backend, platform, sharedContext, stereoscopicEyeCount, disableHandleUseAfterFreeCheck);
|
||||||
onComplete(engine);
|
onComplete(engine);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Engine_createRendererRenderThread(TEngine *tEngine, void (*onComplete)(TRenderer *)) {
|
EMSCRIPTEN_KEEPALIVE void Engine_createRendererRenderThread(TEngine *tEngine, void (*onComplete)(TRenderer *)) {
|
||||||
@@ -95,7 +100,7 @@ extern "C"
|
|||||||
auto renderer = Engine_createRenderer(tEngine);
|
auto renderer = Engine_createRenderer(tEngine);
|
||||||
onComplete(renderer);
|
onComplete(renderer);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Engine_createSwapChainRenderThread(TEngine *tEngine, void *window, uint64_t flags, void (*onComplete)(TSwapChain *)) {
|
EMSCRIPTEN_KEEPALIVE void Engine_createSwapChainRenderThread(TEngine *tEngine, void *window, uint64_t flags, void (*onComplete)(TSwapChain *)) {
|
||||||
@@ -105,7 +110,7 @@ extern "C"
|
|||||||
auto swapChain = Engine_createSwapChain(tEngine, window, flags);
|
auto swapChain = Engine_createSwapChain(tEngine, window, flags);
|
||||||
onComplete(swapChain);
|
onComplete(swapChain);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Engine_createHeadlessSwapChainRenderThread(TEngine *tEngine, uint32_t width, uint32_t height, uint64_t flags, void (*onComplete)(TSwapChain *)) {
|
EMSCRIPTEN_KEEPALIVE void Engine_createHeadlessSwapChainRenderThread(TEngine *tEngine, uint32_t width, uint32_t height, uint64_t flags, void (*onComplete)(TSwapChain *)) {
|
||||||
@@ -115,7 +120,7 @@ extern "C"
|
|||||||
auto swapChain = Engine_createHeadlessSwapChain(tEngine, width, height, flags);
|
auto swapChain = Engine_createHeadlessSwapChain(tEngine, width, height, flags);
|
||||||
onComplete(swapChain);
|
onComplete(swapChain);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Engine_destroySwapChainRenderThread(TEngine *tEngine, TSwapChain *tSwapChain, void (*onComplete)()) {
|
EMSCRIPTEN_KEEPALIVE void Engine_destroySwapChainRenderThread(TEngine *tEngine, TSwapChain *tSwapChain, void (*onComplete)()) {
|
||||||
@@ -125,7 +130,7 @@ extern "C"
|
|||||||
Engine_destroySwapChain(tEngine, tSwapChain);
|
Engine_destroySwapChain(tEngine, tSwapChain);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Engine_createCameraRenderThread(TEngine* tEngine, void (*onComplete)(TCamera *)) {
|
EMSCRIPTEN_KEEPALIVE void Engine_createCameraRenderThread(TEngine* tEngine, void (*onComplete)(TCamera *)) {
|
||||||
@@ -135,7 +140,7 @@ extern "C"
|
|||||||
auto camera = Engine_createCamera(tEngine);
|
auto camera = Engine_createCamera(tEngine);
|
||||||
onComplete(camera);
|
onComplete(camera);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Engine_createViewRenderThread(TEngine *tEngine, void (*onComplete)(TView *)) {
|
EMSCRIPTEN_KEEPALIVE void Engine_createViewRenderThread(TEngine *tEngine, void (*onComplete)(TView *)) {
|
||||||
@@ -145,7 +150,7 @@ extern "C"
|
|||||||
auto * view = Engine_createView(tEngine);
|
auto * view = Engine_createView(tEngine);
|
||||||
onComplete(view);
|
onComplete(view);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyTextureRenderThread(TEngine *engine, TTexture *tTexture, void (*onComplete)())
|
EMSCRIPTEN_KEEPALIVE void Engine_destroyTextureRenderThread(TEngine *engine, TTexture *tTexture, void (*onComplete)())
|
||||||
@@ -156,7 +161,7 @@ extern "C"
|
|||||||
Engine_destroyTexture(engine, tTexture);
|
Engine_destroyTexture(engine, tTexture);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Engine_destroySkyboxRenderThread(TEngine *tEngine, TSkybox *tSkybox, void (*onComplete)()) {
|
EMSCRIPTEN_KEEPALIVE void Engine_destroySkyboxRenderThread(TEngine *tEngine, TSkybox *tSkybox, void (*onComplete)()) {
|
||||||
@@ -166,7 +171,7 @@ extern "C"
|
|||||||
Engine_destroySkybox(tEngine, tSkybox);
|
Engine_destroySkybox(tEngine, tSkybox);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyIndirectLightRenderThread(TEngine *tEngine, TIndirectLight *tIndirectLight, void (*onComplete)()) {
|
EMSCRIPTEN_KEEPALIVE void Engine_destroyIndirectLightRenderThread(TEngine *tEngine, TIndirectLight *tIndirectLight, void (*onComplete)()) {
|
||||||
@@ -176,7 +181,7 @@ extern "C"
|
|||||||
Engine_destroyIndirectLight(tEngine, tIndirectLight);
|
Engine_destroyIndirectLight(tEngine, tIndirectLight);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t *materialData, size_t length, void (*onComplete)(TMaterial *))
|
EMSCRIPTEN_KEEPALIVE void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t *materialData, size_t length, void (*onComplete)(TMaterial *))
|
||||||
@@ -187,7 +192,7 @@ extern "C"
|
|||||||
auto material = Engine_buildMaterial(tEngine, materialData, length);
|
auto material = Engine_buildMaterial(tEngine, materialData, length);
|
||||||
onComplete(material);
|
onComplete(material);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -199,7 +204,17 @@ extern "C"
|
|||||||
Engine_destroyMaterial(tEngine, tMaterial);
|
Engine_destroyMaterial(tEngine, tMaterial);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
|
}
|
||||||
|
|
||||||
|
EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialInstanceRenderThread(TEngine *tEngine, TMaterialInstance *tMaterialInstance, void (*onComplete)()) {
|
||||||
|
std::packaged_task<void()> lambda(
|
||||||
|
[=]() mutable
|
||||||
|
{
|
||||||
|
Engine_destroyMaterialInstance(tEngine, tMaterialInstance);
|
||||||
|
onComplete();
|
||||||
|
});
|
||||||
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Engine_createFenceRenderThread(TEngine *tEngine, void (*onComplete)(TFence*)) {
|
EMSCRIPTEN_KEEPALIVE void Engine_createFenceRenderThread(TEngine *tEngine, void (*onComplete)(TFence*)) {
|
||||||
@@ -209,7 +224,7 @@ extern "C"
|
|||||||
auto *fence = Engine_createFence(tEngine);
|
auto *fence = Engine_createFence(tEngine);
|
||||||
onComplete(fence);
|
onComplete(fence);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyFenceRenderThread(TEngine *tEngine, TFence *tFence, void (*onComplete)()) {
|
EMSCRIPTEN_KEEPALIVE void Engine_destroyFenceRenderThread(TEngine *tEngine, TFence *tFence, void (*onComplete)()) {
|
||||||
@@ -219,7 +234,7 @@ extern "C"
|
|||||||
Engine_destroyFence(tEngine, tFence);
|
Engine_destroyFence(tEngine, tFence);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Engine_flushAndWaitRenderThead(TEngine *tEngine, void (*onComplete)()) {
|
EMSCRIPTEN_KEEPALIVE void Engine_flushAndWaitRenderThead(TEngine *tEngine, void (*onComplete)()) {
|
||||||
@@ -229,7 +244,7 @@ extern "C"
|
|||||||
Engine_flushAndWait(tEngine);
|
Engine_flushAndWait(tEngine);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Engine_buildSkyboxRenderThread(TEngine *tEngine, uint8_t *skyboxData, size_t length, void (*onComplete)(TSkybox *), void (*onTextureUploadComplete)()) {
|
EMSCRIPTEN_KEEPALIVE void Engine_buildSkyboxRenderThread(TEngine *tEngine, uint8_t *skyboxData, size_t length, void (*onComplete)(TSkybox *), void (*onTextureUploadComplete)()) {
|
||||||
@@ -239,7 +254,7 @@ extern "C"
|
|||||||
auto *skybox = Engine_buildSkybox(tEngine, skyboxData, length, onTextureUploadComplete);
|
auto *skybox = Engine_buildSkybox(tEngine, skyboxData, length, onTextureUploadComplete);
|
||||||
onComplete(skybox);
|
onComplete(skybox);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Engine_buildIndirectLightRenderThread(TEngine *tEngine, uint8_t *iblData, size_t length, float intensity, void (*onComplete)(TIndirectLight *), void (*onTextureUploadComplete)()) {
|
EMSCRIPTEN_KEEPALIVE void Engine_buildIndirectLightRenderThread(TEngine *tEngine, uint8_t *iblData, size_t length, float intensity, void (*onComplete)(TIndirectLight *), void (*onTextureUploadComplete)()) {
|
||||||
@@ -249,7 +264,7 @@ extern "C"
|
|||||||
auto *indirectLight = Engine_buildIndirectLight(tEngine, iblData, length, intensity, onTextureUploadComplete);
|
auto *indirectLight = Engine_buildIndirectLight(tEngine, iblData, length, intensity, onTextureUploadComplete);
|
||||||
onComplete(indirectLight);
|
onComplete(indirectLight);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Renderer_beginFrameRenderThread(TRenderer *tRenderer, TSwapChain *tSwapChain, uint64_t frameTimeInNanos, void (*onComplete)(bool)) {
|
EMSCRIPTEN_KEEPALIVE void Renderer_beginFrameRenderThread(TRenderer *tRenderer, TSwapChain *tSwapChain, uint64_t frameTimeInNanos, void (*onComplete)(bool)) {
|
||||||
@@ -259,7 +274,7 @@ extern "C"
|
|||||||
auto result = Renderer_beginFrame(tRenderer, tSwapChain, frameTimeInNanos);
|
auto result = Renderer_beginFrame(tRenderer, tSwapChain, frameTimeInNanos);
|
||||||
onComplete(result);
|
onComplete(result);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
EMSCRIPTEN_KEEPALIVE void Renderer_endFrameRenderThread(TRenderer *tRenderer, void (*onComplete)()) {
|
EMSCRIPTEN_KEEPALIVE void Renderer_endFrameRenderThread(TRenderer *tRenderer, void (*onComplete)()) {
|
||||||
std::packaged_task<void()> lambda(
|
std::packaged_task<void()> lambda(
|
||||||
@@ -268,7 +283,7 @@ extern "C"
|
|||||||
Renderer_endFrame(tRenderer);
|
Renderer_endFrame(tRenderer);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Renderer_renderRenderThread(TRenderer *tRenderer, TView *tView, void (*onComplete)()) {
|
EMSCRIPTEN_KEEPALIVE void Renderer_renderRenderThread(TRenderer *tRenderer, TView *tView, void (*onComplete)()) {
|
||||||
@@ -278,7 +293,7 @@ extern "C"
|
|||||||
Renderer_render(tRenderer, tView);
|
Renderer_render(tRenderer, tView);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Renderer_renderStandaloneViewRenderThread(TRenderer *tRenderer, TView *tView, void (*onComplete)()) {
|
EMSCRIPTEN_KEEPALIVE void Renderer_renderStandaloneViewRenderThread(TRenderer *tRenderer, TView *tView, void (*onComplete)()) {
|
||||||
@@ -288,7 +303,7 @@ extern "C"
|
|||||||
Renderer_renderStandaloneView(tRenderer, tView);
|
Renderer_renderStandaloneView(tRenderer, tView);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Renderer_setClearOptionsRenderThread(
|
EMSCRIPTEN_KEEPALIVE void Renderer_setClearOptionsRenderThread(
|
||||||
@@ -306,7 +321,7 @@ extern "C"
|
|||||||
Renderer_setClearOptions(tRenderer, clearR, clearG, clearB, clearA, clearStencil, clear, discard);
|
Renderer_setClearOptions(tRenderer, clearR, clearG, clearB, clearA, clearStencil, clear, discard);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Renderer_readPixelsRenderThread(
|
EMSCRIPTEN_KEEPALIVE void Renderer_readPixelsRenderThread(
|
||||||
@@ -323,7 +338,7 @@ extern "C"
|
|||||||
Renderer_readPixels(tRenderer, tView, tRenderTarget, tPixelBufferFormat, tPixelDataType, out);
|
Renderer_readPixels(tRenderer, tView, tRenderTarget, tPixelBufferFormat, tPixelDataType, out);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Material_createImageMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *)) {
|
EMSCRIPTEN_KEEPALIVE void Material_createImageMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *)) {
|
||||||
@@ -333,7 +348,7 @@ extern "C"
|
|||||||
auto *instance = Material_createImageMaterial(tEngine);
|
auto *instance = Material_createImageMaterial(tEngine);
|
||||||
onComplete(instance);
|
onComplete(instance);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Material_createInstanceRenderThread(TMaterial *tMaterial, void (*onComplete)(TMaterialInstance *))
|
EMSCRIPTEN_KEEPALIVE void Material_createInstanceRenderThread(TMaterial *tMaterial, void (*onComplete)(TMaterialInstance *))
|
||||||
@@ -344,7 +359,7 @@ extern "C"
|
|||||||
auto *instance = Material_createInstance(tMaterial);
|
auto *instance = Material_createInstance(tMaterial);
|
||||||
onComplete(instance);
|
onComplete(instance);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_destroyRenderThread(TSceneAsset *tSceneAsset, void (*onComplete)()) {
|
EMSCRIPTEN_KEEPALIVE void SceneAsset_destroyRenderThread(TSceneAsset *tSceneAsset, void (*onComplete)()) {
|
||||||
@@ -354,7 +369,7 @@ extern "C"
|
|||||||
SceneAsset_destroy(tSceneAsset);
|
SceneAsset_destroy(tSceneAsset);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_loadGlbRenderThread(
|
EMSCRIPTEN_KEEPALIVE void SceneAsset_loadGlbRenderThread(
|
||||||
@@ -372,7 +387,7 @@ extern "C"
|
|||||||
auto sceneAsset = SceneAsset_loadGlb(tEngine, tAssetLoader, tNameComponentManager, data, length, numInstances);
|
auto sceneAsset = SceneAsset_loadGlb(tEngine, tAssetLoader, tNameComponentManager, data, length, numInstances);
|
||||||
callback(sceneAsset);
|
callback(sceneAsset);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_createGeometryRenderThread(
|
EMSCRIPTEN_KEEPALIVE void SceneAsset_createGeometryRenderThread(
|
||||||
@@ -396,7 +411,7 @@ extern "C"
|
|||||||
auto sceneAsset = SceneAsset_createGeometry(tEngine, vertices, numVertices, normals, numNormals, uvs, numUvs, indices, numIndices, tPrimitiveType, materialInstances, materialInstanceCount);
|
auto sceneAsset = SceneAsset_createGeometry(tEngine, vertices, numVertices, normals, numNormals, uvs, numUvs, indices, numIndices, tPrimitiveType, materialInstances, materialInstanceCount);
|
||||||
callback(sceneAsset);
|
callback(sceneAsset);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_createInstanceRenderThread(
|
EMSCRIPTEN_KEEPALIVE void SceneAsset_createInstanceRenderThread(
|
||||||
@@ -410,7 +425,7 @@ extern "C"
|
|||||||
auto instanceAsset = SceneAsset_createInstance(asset, tMaterialInstances, materialInstanceCount);
|
auto instanceAsset = SceneAsset_createInstance(asset, tMaterialInstances, materialInstanceCount);
|
||||||
callback(instanceAsset);
|
callback(instanceAsset);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void MaterialProvider_createMaterialInstanceRenderThread(TMaterialProvider *tMaterialProvider, TMaterialKey *tKey, void (*callback)(TMaterialInstance *))
|
EMSCRIPTEN_KEEPALIVE void MaterialProvider_createMaterialInstanceRenderThread(TMaterialProvider *tMaterialProvider, TMaterialKey *tKey, void (*callback)(TMaterialInstance *))
|
||||||
@@ -421,7 +436,7 @@ extern "C"
|
|||||||
auto materialInstance = MaterialProvider_createMaterialInstance(tMaterialProvider, tKey);
|
auto materialInstance = MaterialProvider_createMaterialInstance(tMaterialProvider, tKey);
|
||||||
callback(materialInstance);
|
callback(materialInstance);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void View_setToneMappingRenderThread(TView *tView, TEngine *tEngine, TToneMapping toneMapping, void (*callback)())
|
EMSCRIPTEN_KEEPALIVE void View_setToneMappingRenderThread(TView *tView, TEngine *tEngine, TToneMapping toneMapping, void (*callback)())
|
||||||
@@ -432,7 +447,7 @@ extern "C"
|
|||||||
View_setToneMapping(tView, tEngine, toneMapping);
|
View_setToneMapping(tView, tEngine, toneMapping);
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void View_setBloomRenderThread(TView *tView, bool enabled, double strength, void (*callback)())
|
EMSCRIPTEN_KEEPALIVE void View_setBloomRenderThread(TView *tView, bool enabled, double strength, void (*callback)())
|
||||||
@@ -443,7 +458,7 @@ extern "C"
|
|||||||
View_setBloom(tView, enabled, strength);
|
View_setBloom(tView, enabled, strength);
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void View_setCameraRenderThread(TView *tView, TCamera *tCamera, void (*callback)())
|
EMSCRIPTEN_KEEPALIVE void View_setCameraRenderThread(TView *tView, TCamera *tCamera, void (*callback)())
|
||||||
@@ -454,7 +469,7 @@ extern "C"
|
|||||||
View_setCamera(tView, tCamera);
|
View_setCamera(tView, tCamera);
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_createRenderThread(TEngine *tEngine, TScene *tScene, void (*onComplete)(TAnimationManager *)) {
|
EMSCRIPTEN_KEEPALIVE void AnimationManager_createRenderThread(TEngine *tEngine, TScene *tScene, void (*onComplete)(TAnimationManager *)) {
|
||||||
@@ -464,7 +479,7 @@ extern "C"
|
|||||||
auto *animationManager = AnimationManager_create(tEngine, tScene);
|
auto *animationManager = AnimationManager_create(tEngine, tScene);
|
||||||
onComplete(animationManager);
|
onComplete(animationManager);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_updateBoneMatricesRenderThread(
|
EMSCRIPTEN_KEEPALIVE void AnimationManager_updateBoneMatricesRenderThread(
|
||||||
@@ -478,7 +493,7 @@ extern "C"
|
|||||||
bool result = AnimationManager_updateBoneMatrices(tAnimationManager, sceneAsset);
|
bool result = AnimationManager_updateBoneMatrices(tAnimationManager, sceneAsset);
|
||||||
callback(result);
|
callback(result);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_setMorphTargetWeightsRenderThread(
|
EMSCRIPTEN_KEEPALIVE void AnimationManager_setMorphTargetWeightsRenderThread(
|
||||||
@@ -494,7 +509,7 @@ extern "C"
|
|||||||
bool result = AnimationManager_setMorphTargetWeights(tAnimationManager, entityId, morphData, numWeights);
|
bool result = AnimationManager_setMorphTargetWeights(tAnimationManager, entityId, morphData, numWeights);
|
||||||
callback(result);
|
callback(result);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add these implementations to your ThermionDartRenderThreadApi.cpp file
|
// Add these implementations to your ThermionDartRenderThreadApi.cpp file
|
||||||
@@ -508,7 +523,7 @@ extern "C"
|
|||||||
auto image = Image_createEmpty(width, height, channel);
|
auto image = Image_createEmpty(width, height, channel);
|
||||||
onComplete(image);
|
onComplete(image);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Image_decodeRenderThread(uint8_t *data, size_t length, const char *name, void (*onComplete)(TLinearImage *))
|
EMSCRIPTEN_KEEPALIVE void Image_decodeRenderThread(uint8_t *data, size_t length, const char *name, void (*onComplete)(TLinearImage *))
|
||||||
@@ -519,7 +534,7 @@ extern "C"
|
|||||||
auto image = Image_decode(data, length, name);
|
auto image = Image_decode(data, length, name);
|
||||||
onComplete(image);
|
onComplete(image);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Image_getBytesRenderThread(TLinearImage *tLinearImage, void (*onComplete)(float *))
|
EMSCRIPTEN_KEEPALIVE void Image_getBytesRenderThread(TLinearImage *tLinearImage, void (*onComplete)(float *))
|
||||||
@@ -530,7 +545,7 @@ extern "C"
|
|||||||
auto bytes = Image_getBytes(tLinearImage);
|
auto bytes = Image_getBytes(tLinearImage);
|
||||||
onComplete(bytes);
|
onComplete(bytes);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Image_destroyRenderThread(TLinearImage *tLinearImage, void (*onComplete)())
|
EMSCRIPTEN_KEEPALIVE void Image_destroyRenderThread(TLinearImage *tLinearImage, void (*onComplete)())
|
||||||
@@ -541,7 +556,7 @@ extern "C"
|
|||||||
Image_destroy(tLinearImage);
|
Image_destroy(tLinearImage);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Image_getWidthRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t))
|
EMSCRIPTEN_KEEPALIVE void Image_getWidthRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t))
|
||||||
@@ -552,7 +567,7 @@ extern "C"
|
|||||||
auto width = Image_getWidth(tLinearImage);
|
auto width = Image_getWidth(tLinearImage);
|
||||||
onComplete(width);
|
onComplete(width);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Image_getHeightRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t))
|
EMSCRIPTEN_KEEPALIVE void Image_getHeightRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t))
|
||||||
@@ -563,7 +578,7 @@ extern "C"
|
|||||||
auto height = Image_getHeight(tLinearImage);
|
auto height = Image_getHeight(tLinearImage);
|
||||||
onComplete(height);
|
onComplete(height);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Image_getChannelsRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t))
|
EMSCRIPTEN_KEEPALIVE void Image_getChannelsRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t))
|
||||||
@@ -574,7 +589,7 @@ extern "C"
|
|||||||
auto channels = Image_getChannels(tLinearImage);
|
auto channels = Image_getChannels(tLinearImage);
|
||||||
onComplete(channels);
|
onComplete(channels);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Texture_buildRenderThread(
|
EMSCRIPTEN_KEEPALIVE void Texture_buildRenderThread(
|
||||||
@@ -593,7 +608,7 @@ extern "C"
|
|||||||
auto *texture = Texture_build(tEngine, width, height, depth, levels, tUsage, import, sampler, format);
|
auto *texture = Texture_build(tEngine, width, height, depth, levels, tUsage, import, sampler, format);
|
||||||
onComplete(texture);
|
onComplete(texture);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Texture methods
|
// Texture methods
|
||||||
@@ -607,7 +622,7 @@ extern "C"
|
|||||||
bool result = Texture_loadImage(tEngine, tTexture, tImage, bufferFormat, pixelDataType);
|
bool result = Texture_loadImage(tEngine, tTexture, tImage, bufferFormat, pixelDataType);
|
||||||
onComplete(result);
|
onComplete(result);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Texture_setImageRenderThread(
|
EMSCRIPTEN_KEEPALIVE void Texture_setImageRenderThread(
|
||||||
@@ -630,7 +645,7 @@ extern "C"
|
|||||||
bufferFormat, pixelDataType);
|
bufferFormat, pixelDataType);
|
||||||
onComplete(result);
|
onComplete(result);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Texture_setImageWithDepthRenderThread(
|
EMSCRIPTEN_KEEPALIVE void Texture_setImageWithDepthRenderThread(
|
||||||
@@ -671,7 +686,7 @@ extern "C"
|
|||||||
);
|
);
|
||||||
onComplete(result);
|
onComplete(result);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void RenderTarget_getColorTextureRenderThread(TRenderTarget *tRenderTarget, void (*onComplete)(TTexture *))
|
EMSCRIPTEN_KEEPALIVE void RenderTarget_getColorTextureRenderThread(TRenderTarget *tRenderTarget, void (*onComplete)(TTexture *))
|
||||||
@@ -682,7 +697,7 @@ extern "C"
|
|||||||
auto texture = RenderTarget_getColorTexture(tRenderTarget);
|
auto texture = RenderTarget_getColorTexture(tRenderTarget);
|
||||||
onComplete(texture);
|
onComplete(texture);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void RenderTarget_createRenderThread(
|
EMSCRIPTEN_KEEPALIVE void RenderTarget_createRenderThread(
|
||||||
@@ -702,7 +717,7 @@ extern "C"
|
|||||||
auto texture = RenderTarget_create(tEngine, width, height, tColor, tDepth);
|
auto texture = RenderTarget_create(tEngine, width, height, tColor, tDepth);
|
||||||
onComplete(texture);
|
onComplete(texture);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -716,7 +731,7 @@ extern "C"
|
|||||||
auto sampler = TextureSampler_create();
|
auto sampler = TextureSampler_create();
|
||||||
onComplete(sampler);
|
onComplete(sampler);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_createWithFilteringRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_createWithFilteringRenderThread(
|
||||||
@@ -733,7 +748,7 @@ extern "C"
|
|||||||
auto sampler = TextureSampler_createWithFiltering(minFilter, magFilter, wrapS, wrapT, wrapR);
|
auto sampler = TextureSampler_createWithFiltering(minFilter, magFilter, wrapS, wrapT, wrapR);
|
||||||
onComplete(sampler);
|
onComplete(sampler);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_createWithComparisonRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_createWithComparisonRenderThread(
|
||||||
@@ -747,7 +762,7 @@ extern "C"
|
|||||||
auto sampler = TextureSampler_createWithComparison(compareMode, compareFunc);
|
auto sampler = TextureSampler_createWithComparison(compareMode, compareFunc);
|
||||||
onComplete(sampler);
|
onComplete(sampler);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setMinFilterRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_setMinFilterRenderThread(
|
||||||
@@ -761,7 +776,7 @@ extern "C"
|
|||||||
TextureSampler_setMinFilter(sampler, filter);
|
TextureSampler_setMinFilter(sampler, filter);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setMagFilterRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_setMagFilterRenderThread(
|
||||||
@@ -775,7 +790,7 @@ extern "C"
|
|||||||
TextureSampler_setMagFilter(sampler, filter);
|
TextureSampler_setMagFilter(sampler, filter);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeSRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeSRenderThread(
|
||||||
@@ -789,7 +804,7 @@ extern "C"
|
|||||||
TextureSampler_setWrapModeS(sampler, mode);
|
TextureSampler_setWrapModeS(sampler, mode);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeTRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeTRenderThread(
|
||||||
@@ -803,7 +818,7 @@ extern "C"
|
|||||||
TextureSampler_setWrapModeT(sampler, mode);
|
TextureSampler_setWrapModeT(sampler, mode);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeRRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeRRenderThread(
|
||||||
@@ -817,7 +832,7 @@ extern "C"
|
|||||||
TextureSampler_setWrapModeR(sampler, mode);
|
TextureSampler_setWrapModeR(sampler, mode);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setAnisotropyRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_setAnisotropyRenderThread(
|
||||||
@@ -831,7 +846,7 @@ extern "C"
|
|||||||
TextureSampler_setAnisotropy(sampler, anisotropy);
|
TextureSampler_setAnisotropy(sampler, anisotropy);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setCompareModeRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_setCompareModeRenderThread(
|
||||||
@@ -846,7 +861,7 @@ extern "C"
|
|||||||
TextureSampler_setCompareMode(sampler, mode, func);
|
TextureSampler_setCompareMode(sampler, mode, func);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_destroyRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_destroyRenderThread(
|
||||||
@@ -859,7 +874,7 @@ extern "C"
|
|||||||
TextureSampler_destroy(sampler);
|
TextureSampler_destroy(sampler);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void GltfAssetLoader_createRenderThread(TEngine *tEngine, TMaterialProvider *tMaterialProvider, void (*callback)(TGltfAssetLoader *)) {
|
EMSCRIPTEN_KEEPALIVE void GltfAssetLoader_createRenderThread(TEngine *tEngine, TMaterialProvider *tMaterialProvider, void (*callback)(TGltfAssetLoader *)) {
|
||||||
@@ -869,7 +884,7 @@ extern "C"
|
|||||||
auto loader = GltfAssetLoader_create(tEngine, tMaterialProvider);
|
auto loader = GltfAssetLoader_create(tEngine, tMaterialProvider);
|
||||||
callback(loader);
|
callback(loader);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_createRenderThread(TEngine *tEngine, const char* relativeResourcePath, void (*callback)(TGltfResourceLoader *)) {
|
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_createRenderThread(TEngine *tEngine, const char* relativeResourcePath, void (*callback)(TGltfResourceLoader *)) {
|
||||||
@@ -879,7 +894,7 @@ extern "C"
|
|||||||
auto loader = GltfResourceLoader_create(tEngine, relativeResourcePath);
|
auto loader = GltfResourceLoader_create(tEngine, relativeResourcePath);
|
||||||
callback(loader);
|
callback(loader);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_destroyRenderThread(TEngine *tEngine, TGltfResourceLoader *tResourceLoader, void (*callback)()) {
|
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_destroyRenderThread(TEngine *tEngine, TGltfResourceLoader *tResourceLoader, void (*callback)()) {
|
||||||
@@ -889,7 +904,7 @@ extern "C"
|
|||||||
GltfResourceLoader_destroy(tEngine, tResourceLoader);
|
GltfResourceLoader_destroy(tEngine, tResourceLoader);
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_loadResourcesRenderThread(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset, void (*callback)(bool)) {
|
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_loadResourcesRenderThread(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset, void (*callback)(bool)) {
|
||||||
@@ -899,7 +914,7 @@ extern "C"
|
|||||||
auto result = GltfResourceLoader_loadResources(tGltfResourceLoader, tFilamentAsset);
|
auto result = GltfResourceLoader_loadResources(tGltfResourceLoader, tFilamentAsset);
|
||||||
callback(result);
|
callback(result);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_addResourceDataRenderThread(
|
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_addResourceDataRenderThread(
|
||||||
@@ -914,7 +929,7 @@ extern "C"
|
|||||||
GltfResourceLoader_addResourceData(tGltfResourceLoader, uri, data, length);
|
GltfResourceLoader_addResourceData(tGltfResourceLoader, uri, data, length);
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void GltfAssetLoader_loadRenderThread(
|
EMSCRIPTEN_KEEPALIVE void GltfAssetLoader_loadRenderThread(
|
||||||
@@ -931,7 +946,7 @@ extern "C"
|
|||||||
auto loader = GltfAssetLoader_load(tEngine, tAssetLoader, data, length, numInstances);
|
auto loader = GltfAssetLoader_load(tEngine, tAssetLoader, data, length, numInstances);
|
||||||
callback(loader);
|
callback(loader);
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE void Scene_addFilamentAssetRenderThread(TScene* tScene, TFilamentAsset *tAsset, void (*callback)()) {
|
EMSCRIPTEN_KEEPALIVE void Scene_addFilamentAssetRenderThread(TScene* tScene, TFilamentAsset *tAsset, void (*callback)()) {
|
||||||
@@ -941,6 +956,6 @@ extern "C"
|
|||||||
Scene_addFilamentAsset(tScene, tAsset);
|
Scene_addFilamentAsset(tScene, tAsset);
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
auto fut = _rl->add_task(lambda);
|
auto fut = _renderThread->add_task(lambda);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "rendering/RenderLoop.hpp"
|
#include "rendering/RenderThread.hpp"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
namespace thermion {
|
namespace thermion {
|
||||||
|
|
||||||
RenderLoop::RenderLoop()
|
RenderThread::RenderThread()
|
||||||
{
|
{
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
t = new std::thread([this]() {
|
t = new std::thread([this]() {
|
||||||
@@ -18,26 +18,27 @@ RenderLoop::RenderLoop()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderLoop::~RenderLoop()
|
RenderThread::~RenderThread()
|
||||||
{
|
{
|
||||||
TRACE("Destroying RenderLoop");
|
TRACE("Destroying RenderThread");
|
||||||
_stop = true;
|
_stop = true;
|
||||||
_cv.notify_one();
|
_cv.notify_one();
|
||||||
TRACE("Joining RenderLoop thread..");
|
TRACE("Joining RenderThread thread..");
|
||||||
t->join();
|
t->join();
|
||||||
delete t;
|
delete t;
|
||||||
|
|
||||||
TRACE("RenderLoop destructor complete");
|
TRACE("RenderThread destructor complete");
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderLoop::requestFrame(void (*callback)())
|
void RenderThread::requestFrame(void (*callback)())
|
||||||
{
|
{
|
||||||
|
TRACE("Request frame");
|
||||||
std::unique_lock<std::mutex> lock(_mutex);
|
std::unique_lock<std::mutex> lock(_mutex);
|
||||||
this->_requestFrameRenderCallback = callback;
|
this->_requestFrameRenderCallback = callback;
|
||||||
_cv.notify_one();
|
_cv.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderLoop::iter()
|
void RenderThread::iter()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(_mutex);
|
std::unique_lock<std::mutex> lock(_mutex);
|
||||||
@@ -10,283 +10,288 @@ void main() async {
|
|||||||
final testHelper = TestHelper("geometry");
|
final testHelper = TestHelper("geometry");
|
||||||
await testHelper.setup();
|
await testHelper.setup();
|
||||||
group("custom geometry", () {
|
group("custom geometry", () {
|
||||||
test('create cube (uvs only)', () async {
|
test('add geometry', () async {
|
||||||
var viewer = await testHelper.createViewer();
|
|
||||||
await viewer
|
|
||||||
.createGeometry(GeometryHelper.cube(normals: false, uvs: true));
|
|
||||||
await testHelper.capture(viewer, "geometry_cube_with_uvs");
|
|
||||||
});
|
|
||||||
test('create cube with normals & uvs', () async {
|
|
||||||
var viewer = await testHelper.createViewer();
|
|
||||||
await viewer
|
|
||||||
.createGeometry(GeometryHelper.cube(normals: true, uvs: true));
|
|
||||||
await testHelper.capture(viewer, "geometry_cube_with_normals_uvs");
|
|
||||||
});
|
|
||||||
|
|
||||||
test('create cube (no normals/uvs)', () async {
|
|
||||||
await testHelper.withViewer((viewer) async {
|
await testHelper.withViewer((viewer) async {
|
||||||
var viewMatrix =
|
final asset = await viewer.createGeometry(GeometryHelper.cube());
|
||||||
makeViewMatrix(Vector3(0, 2, 5), Vector3.zero(), Vector3(0, 1, 0));
|
await viewer.addToScene(asset);
|
||||||
viewMatrix.invert();
|
await testHelper.capture(viewer.view, "add_geometry");
|
||||||
await viewer.setCameraModelMatrix4(viewMatrix);
|
await viewer.removeFromScene(asset);
|
||||||
final cube = await viewer
|
await testHelper.capture(viewer.view, "remove_geometry");
|
||||||
.createGeometry(GeometryHelper.cube(normals: false, uvs: false));
|
await viewer.destroyAsset(asset);
|
||||||
await testHelper.capture(viewer, "geometry_cube_no_normals_uvs");
|
|
||||||
await viewer.destroyAsset(cube);
|
|
||||||
await testHelper.capture(viewer, "geometry_remove_cube");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('create cube with unlit ubershader material (no normals/uvs)',
|
|
||||||
() async {
|
|
||||||
await testHelper.withViewer((viewer) async {
|
|
||||||
final materialInstance =
|
|
||||||
await viewer.createUbershaderMaterialInstance(unlit: true);
|
|
||||||
await materialInstance.setParameterFloat4(
|
|
||||||
"baseColorFactor", 1.0, 0.0, 0.0, 1.0);
|
|
||||||
final cube = await viewer.createGeometry(
|
|
||||||
GeometryHelper.cube(normals: false, uvs: false),
|
|
||||||
materialInstances: [materialInstance]);
|
|
||||||
await testHelper.capture(viewer, "geometry_cube_ubershader");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('create cube with lit ubershader material (normals/ no uvs)',
|
|
||||||
() async {
|
|
||||||
await testHelper.withViewer((viewer) async {
|
|
||||||
final materialInstance = await viewer.createUbershaderMaterialInstance(
|
|
||||||
unlit: false, alphaMode: AlphaMode.BLEND, hasVertexColors: false);
|
|
||||||
await materialInstance.setParameterFloat4(
|
|
||||||
"baseColorFactor", 1.0, 0.0, 0.0, 1.0);
|
|
||||||
final cube = await viewer.createGeometry(
|
|
||||||
GeometryHelper.cube(normals: true, uvs: false),
|
|
||||||
materialInstances: [materialInstance]);
|
|
||||||
|
|
||||||
await viewer.addDirectLight(DirectLight.sun(
|
|
||||||
intensity: 100000,
|
|
||||||
castShadows: false,
|
|
||||||
direction: Vector3(0, -0.5, -1)));
|
|
||||||
// await viewer.addDirectLight(DirectLight.spot(
|
|
||||||
// intensity: 1000000,
|
|
||||||
// position: Vector3(0,3,3),
|
|
||||||
// direction: Vector3(0,-1.5,-1),
|
|
||||||
// falloffRadius: 10));
|
|
||||||
await materialInstance.setParameterFloat4(
|
|
||||||
"baseColorFactor", 1.0, 0.0, 0.0, 1.0);
|
|
||||||
await testHelper.capture(viewer, "geometry_cube_lit_ubershader");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('create instance', () async {
|
|
||||||
await testHelper.withViewer((viewer) async {
|
|
||||||
final cube = await viewer
|
|
||||||
.createGeometry(GeometryHelper.cube(normals: false, uvs: false));
|
|
||||||
await viewer.setTransform(
|
|
||||||
cube.entity, Matrix4.translation(Vector3.all(-1)));
|
|
||||||
final instance = await cube.createInstance();
|
|
||||||
await instance.addToScene();
|
|
||||||
await viewer.setTransform(
|
|
||||||
instance.entity, Matrix4.translation(Vector3.all(1)));
|
|
||||||
|
|
||||||
await testHelper.capture(viewer, "geometry_instanced");
|
|
||||||
await viewer.destroyAsset(instance);
|
|
||||||
await testHelper.capture(viewer, "geometry_instance_removed");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('create instance (shared material)', () async {
|
|
||||||
await testHelper.withViewer((viewer) async {
|
|
||||||
final materialInstance = await viewer.createUnlitMaterialInstance();
|
|
||||||
await materialInstance.setParameterFloat4(
|
|
||||||
"baseColorFactor", 1.0, 0.0, 0.0, 1.0);
|
|
||||||
final cube = await viewer.createGeometry(
|
|
||||||
GeometryHelper.cube(normals: true, uvs: false),
|
|
||||||
materialInstances: [materialInstance]);
|
|
||||||
|
|
||||||
final instance = await cube.createInstance();
|
|
||||||
await instance.addToScene();
|
|
||||||
await viewer.setTransform(
|
|
||||||
instance.entity, Matrix4.translation(Vector3.all(1)));
|
|
||||||
|
|
||||||
await testHelper.capture(
|
|
||||||
viewer, "geometry_instanced_with_shared_material");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// test('create instance (no material on second instance)', () async {
|
|
||||||
// await testHelper.withViewer((viewer) async {
|
|
||||||
// final materialInstance = await viewer.createUnlitMaterialInstance();
|
|
||||||
// await materialInstance.setParameterFloat4(
|
|
||||||
// "baseColorFactor", 1.0, 0.0, 0.0, 1.0);
|
|
||||||
// final cube = await viewer.createGeometry(
|
|
||||||
// GeometryHelper.cube(normals: true, uvs: false),
|
|
||||||
// materialInstances: [materialInstance]);
|
|
||||||
|
|
||||||
// final instance = await viewer
|
|
||||||
// .createInstance(cube);
|
|
||||||
// await viewer.setTransform(
|
|
||||||
// instance.entity, Matrix4.translation(Vector3.all(1)));
|
|
||||||
|
|
||||||
// await testHelper.capture(
|
|
||||||
// viewer, "geometry_instanced_with_no_material_instance");
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
// test('create instance (separate materials)', () async {
|
|
||||||
// await testHelper.withViewer((viewer) async {
|
|
||||||
// final materialInstance = await viewer.createUnlitMaterialInstance();
|
|
||||||
// await materialInstance.setParameterFloat4(
|
|
||||||
// "baseColorFactor", 1.0, 0.0, 0.0, 1.0);
|
|
||||||
// final cube = await viewer.createGeometry(
|
|
||||||
// GeometryHelper.cube(normals: true, uvs: false),
|
|
||||||
// materialInstances: [materialInstance]);
|
|
||||||
|
|
||||||
// final materialInstance2 = await viewer.createUnlitMaterialInstance();
|
|
||||||
// await materialInstance2.setParameterFloat4(
|
|
||||||
// "baseColorFactor", 0.0, 1.0, 0.0, 1.0);
|
|
||||||
// final instance = await viewer
|
|
||||||
// .createInstance(cube, materialInstances: [materialInstance2]);
|
|
||||||
// await viewer.setTransform(
|
|
||||||
// instance.entity, Matrix4.translation(Vector3.all(1)));
|
|
||||||
|
|
||||||
// await testHelper.capture(
|
|
||||||
// viewer, "geometry_instanced_with_separate_material_instances");
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
test('create cube with custom ubershader material (color)', () async {
|
|
||||||
await testHelper.withViewer((viewer) async {
|
|
||||||
await viewer.addLight(LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);
|
|
||||||
await viewer.setCameraPosition(0, 2, 6);
|
|
||||||
await viewer
|
|
||||||
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
|
|
||||||
await viewer.setBackgroundColor(1.0, 0.0, 1.0, 1.0);
|
|
||||||
|
|
||||||
var materialInstance =
|
|
||||||
await viewer.createUbershaderMaterialInstance(unlit: true);
|
|
||||||
final cube = await viewer.createGeometry(
|
|
||||||
GeometryHelper.cube(uvs: false, normals: true),
|
|
||||||
materialInstances: [materialInstance]);
|
|
||||||
await materialInstance.setParameterFloat4(
|
|
||||||
"baseColorFactor", 0.0, 1.0, 0.0, 0.0);
|
|
||||||
await testHelper.capture(
|
|
||||||
viewer, "geometry_cube_with_custom_material_ubershader");
|
|
||||||
await viewer.destroyAsset(cube);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('create cube with custom ubershader material instance (texture)',
|
|
||||||
() async {
|
|
||||||
var viewer = await testHelper.createViewer();
|
|
||||||
await viewer.addLight(LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);
|
|
||||||
await viewer.setCameraPosition(0, 2, 6);
|
|
||||||
await viewer
|
|
||||||
.setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
|
|
||||||
await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
|
|
||||||
|
|
||||||
var materialInstance = await viewer.createUbershaderMaterialInstance();
|
|
||||||
final cube = await viewer.createGeometry(
|
|
||||||
GeometryHelper.cube(uvs: true, normals: true),
|
|
||||||
materialInstances: [materialInstance]);
|
|
||||||
final image = await viewer.decodeImage(
|
|
||||||
File("${testHelper.testDir}/assets/cube_texture_512x512.png")
|
|
||||||
.readAsBytesSync());
|
|
||||||
var texture = await viewer.createTexture(
|
|
||||||
await image.getWidth(), await image.getHeight());
|
|
||||||
await texture.setLinearImage(
|
|
||||||
image, PixelDataFormat.RGBA, PixelDataType.FLOAT);
|
|
||||||
await testHelper.capture(
|
|
||||||
viewer, "geometry_cube_with_custom_material_ubershader_texture");
|
|
||||||
await viewer.destroyAsset(cube);
|
|
||||||
await texture.dispose();
|
|
||||||
await image.destroy();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('unlit material with color only', () async {
|
|
||||||
await testHelper.withViewer((viewer) async {
|
|
||||||
var materialInstance = await viewer.createUnlitMaterialInstance();
|
|
||||||
var cube = await viewer.createGeometry(GeometryHelper.cube(),
|
|
||||||
materialInstances: [materialInstance]);
|
|
||||||
|
|
||||||
await materialInstance.setParameterFloat4(
|
|
||||||
"baseColorFactor", 0.0, 1.0, 0.0, 1.0);
|
|
||||||
|
|
||||||
await testHelper.capture(viewer, "unlit_material_base_color");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('unlit material with texture', () async {
|
|
||||||
await testHelper.withViewer((viewer) async {
|
|
||||||
var materialInstance = await viewer.createUnlitMaterialInstance();
|
|
||||||
var cube = await viewer.createGeometry(GeometryHelper.cube(),
|
|
||||||
materialInstances: [materialInstance]);
|
|
||||||
|
|
||||||
await materialInstance.setParameterInt("baseColorIndex", 0);
|
|
||||||
|
|
||||||
final image = await viewer.decodeImage(
|
|
||||||
File("${testHelper.testDir}/assets/cube_texture_512x512.png")
|
|
||||||
.readAsBytesSync());
|
|
||||||
var texture = await viewer.createTexture(
|
|
||||||
await image.getWidth(), await image.getHeight());
|
|
||||||
await texture.setLinearImage(
|
|
||||||
image, PixelDataFormat.RGBA, PixelDataType.FLOAT);
|
|
||||||
await testHelper.capture(viewer, "unlit_material_texture_only");
|
|
||||||
await viewer.destroyAsset(cube);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('shared material instance with texture and base color', () async {
|
|
||||||
await testHelper.withViewer((viewer) async {
|
|
||||||
var materialInstance = await viewer.createUnlitMaterialInstance();
|
|
||||||
var cube1 = await viewer.createGeometry(GeometryHelper.cube(),
|
|
||||||
materialInstances: [materialInstance]);
|
|
||||||
var cube2 = await viewer.createGeometry(GeometryHelper.cube(),
|
|
||||||
materialInstances: [materialInstance]);
|
|
||||||
await viewer.setTransform(
|
|
||||||
cube2.entity, Matrix4.translation(Vector3(1, 1, 1)));
|
|
||||||
|
|
||||||
await materialInstance.setParameterInt("baseColorIndex", 0);
|
|
||||||
final image = await viewer.decodeImage(
|
|
||||||
File("${testHelper.testDir}/assets/cube_texture_512x512.png")
|
|
||||||
.readAsBytesSync());
|
|
||||||
var texture = await viewer.createTexture(
|
|
||||||
await image.getWidth(), await image.getHeight());
|
|
||||||
await texture.setLinearImage(
|
|
||||||
image, PixelDataFormat.RGBA, PixelDataType.FLOAT);
|
|
||||||
|
|
||||||
await testHelper.capture(viewer, "unlit_material_shared");
|
|
||||||
await texture.dispose();
|
|
||||||
await image.destroy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('create sphere (no normals)', () async {
|
|
||||||
await testHelper.withViewer((viewer) async {
|
|
||||||
await viewer
|
|
||||||
.createGeometry(GeometryHelper.sphere(normals: false, uvs: false));
|
|
||||||
await testHelper.capture(viewer, "geometry_sphere_no_normals");
|
|
||||||
}, bg: kBlue, cameraPosition: Vector3(0, 0, 6));
|
|
||||||
});
|
|
||||||
|
|
||||||
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);
|
}, bg: kRed);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('create camera geometry', () async {
|
|
||||||
await testHelper.withViewer((viewer) async {
|
|
||||||
final camera = await viewer.createGeometry(
|
|
||||||
GeometryHelper.wireframeCamera(normals: false, uvs: false));
|
|
||||||
await viewer.setTransform(camera.entity, Matrix4.rotationY(pi / 4));
|
|
||||||
await testHelper.capture(viewer, "camera_geometry");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
// test('create cube with normals & uvs', () async {
|
||||||
|
// var viewer = await testHelper.createViewer();
|
||||||
|
// await viewer
|
||||||
|
// .createGeometry(GeometryHelper.cube(normals: true, uvs: true));
|
||||||
|
// await testHelper.capture(viewer, "geometry_cube_with_normals_uvs");
|
||||||
|
// });
|
||||||
|
|
||||||
|
// test('create cube (no normals/uvs)', () async {
|
||||||
|
// await testHelper.withViewer((viewer) async {
|
||||||
|
// var viewMatrix =
|
||||||
|
// makeViewMatrix(Vector3(0, 2, 5), Vector3.zero(), Vector3(0, 1, 0));
|
||||||
|
// viewMatrix.invert();
|
||||||
|
// await viewer.setCameraModelMatrix4(viewMatrix);
|
||||||
|
// final cube = await viewer
|
||||||
|
// .createGeometry(GeometryHelper.cube(normals: false, uvs: false));
|
||||||
|
// await testHelper.capture(viewer, "geometry_cube_no_normals_uvs");
|
||||||
|
// await viewer.destroyAsset(cube);
|
||||||
|
// await testHelper.capture(viewer, "geometry_remove_cube");
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// test('create cube with unlit ubershader material (no normals/uvs)',
|
||||||
|
// () async {
|
||||||
|
// await testHelper.withViewer((viewer) async {
|
||||||
|
// final materialInstance =
|
||||||
|
// await viewer.createUbershaderMaterialInstance(unlit: true);
|
||||||
|
// await materialInstance.setParameterFloat4(
|
||||||
|
// "baseColorFactor", 1.0, 0.0, 0.0, 1.0);
|
||||||
|
// final cube = await viewer.createGeometry(
|
||||||
|
// GeometryHelper.cube(normals: false, uvs: false),
|
||||||
|
// materialInstances: [materialInstance]);
|
||||||
|
// await testHelper.capture(viewer, "geometry_cube_ubershader");
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// test('create cube with lit ubershader material (normals/ no uvs)',
|
||||||
|
// () async {
|
||||||
|
// await testHelper.withViewer((viewer) async {
|
||||||
|
// final materialInstance = await viewer.createUbershaderMaterialInstance(
|
||||||
|
// unlit: false, alphaMode: AlphaMode.BLEND, hasVertexColors: false);
|
||||||
|
// await materialInstance.setParameterFloat4(
|
||||||
|
// "baseColorFactor", 1.0, 0.0, 0.0, 1.0);
|
||||||
|
// final cube = await viewer.createGeometry(
|
||||||
|
// GeometryHelper.cube(normals: true, uvs: false),
|
||||||
|
// materialInstances: [materialInstance]);
|
||||||
|
|
||||||
|
// await viewer.addDirectLight(DirectLight.sun(
|
||||||
|
// intensity: 100000,
|
||||||
|
// castShadows: false,
|
||||||
|
// direction: Vector3(0, -0.5, -1)));
|
||||||
|
// // await viewer.addDirectLight(DirectLight.spot(
|
||||||
|
// // intensity: 1000000,
|
||||||
|
// // position: Vector3(0,3,3),
|
||||||
|
// // direction: Vector3(0,-1.5,-1),
|
||||||
|
// // falloffRadius: 10));
|
||||||
|
// await materialInstance.setParameterFloat4(
|
||||||
|
// "baseColorFactor", 1.0, 0.0, 0.0, 1.0);
|
||||||
|
// await testHelper.capture(viewer, "geometry_cube_lit_ubershader");
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// test('create instance', () async {
|
||||||
|
// await testHelper.withViewer((viewer) async {
|
||||||
|
// final cube = await viewer
|
||||||
|
// .createGeometry(GeometryHelper.cube(normals: false, uvs: false));
|
||||||
|
// await viewer.setTransform(
|
||||||
|
// cube.entity, Matrix4.translation(Vector3.all(-1)));
|
||||||
|
// final instance = await cube.createInstance();
|
||||||
|
// await instance.addToScene();
|
||||||
|
// await viewer.setTransform(
|
||||||
|
// instance.entity, Matrix4.translation(Vector3.all(1)));
|
||||||
|
|
||||||
|
// await testHelper.capture(viewer, "geometry_instanced");
|
||||||
|
// await viewer.destroyAsset(instance);
|
||||||
|
// await testHelper.capture(viewer, "geometry_instance_removed");
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// test('create instance (shared material)', () async {
|
||||||
|
// await testHelper.withViewer((viewer) async {
|
||||||
|
// final materialInstance = await viewer.createUnlitMaterialInstance();
|
||||||
|
// await materialInstance.setParameterFloat4(
|
||||||
|
// "baseColorFactor", 1.0, 0.0, 0.0, 1.0);
|
||||||
|
// final cube = await viewer.createGeometry(
|
||||||
|
// GeometryHelper.cube(normals: true, uvs: false),
|
||||||
|
// materialInstances: [materialInstance]);
|
||||||
|
|
||||||
|
// final instance = await cube.createInstance();
|
||||||
|
// await instance.addToScene();
|
||||||
|
// await viewer.setTransform(
|
||||||
|
// instance.entity, Matrix4.translation(Vector3.all(1)));
|
||||||
|
|
||||||
|
// await testHelper.capture(
|
||||||
|
// viewer, "geometry_instanced_with_shared_material");
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// // test('create instance (no material on second instance)', () async {
|
||||||
|
// // await testHelper.withViewer((viewer) async {
|
||||||
|
// // final materialInstance = await viewer.createUnlitMaterialInstance();
|
||||||
|
// // await materialInstance.setParameterFloat4(
|
||||||
|
// // "baseColorFactor", 1.0, 0.0, 0.0, 1.0);
|
||||||
|
// // final cube = await viewer.createGeometry(
|
||||||
|
// // GeometryHelper.cube(normals: true, uvs: false),
|
||||||
|
// // materialInstances: [materialInstance]);
|
||||||
|
|
||||||
|
// // final instance = await viewer
|
||||||
|
// // .createInstance(cube);
|
||||||
|
// // await viewer.setTransform(
|
||||||
|
// // instance.entity, Matrix4.translation(Vector3.all(1)));
|
||||||
|
|
||||||
|
// // await testHelper.capture(
|
||||||
|
// // viewer, "geometry_instanced_with_no_material_instance");
|
||||||
|
// // });
|
||||||
|
// // });
|
||||||
|
|
||||||
|
// // test('create instance (separate materials)', () async {
|
||||||
|
// // await testHelper.withViewer((viewer) async {
|
||||||
|
// // final materialInstance = await viewer.createUnlitMaterialInstance();
|
||||||
|
// // await materialInstance.setParameterFloat4(
|
||||||
|
// // "baseColorFactor", 1.0, 0.0, 0.0, 1.0);
|
||||||
|
// // final cube = await viewer.createGeometry(
|
||||||
|
// // GeometryHelper.cube(normals: true, uvs: false),
|
||||||
|
// // materialInstances: [materialInstance]);
|
||||||
|
|
||||||
|
// // final materialInstance2 = await viewer.createUnlitMaterialInstance();
|
||||||
|
// // await materialInstance2.setParameterFloat4(
|
||||||
|
// // "baseColorFactor", 0.0, 1.0, 0.0, 1.0);
|
||||||
|
// // final instance = await viewer
|
||||||
|
// // .createInstance(cube, materialInstances: [materialInstance2]);
|
||||||
|
// // await viewer.setTransform(
|
||||||
|
// // instance.entity, Matrix4.translation(Vector3.all(1)));
|
||||||
|
|
||||||
|
// // await testHelper.capture(
|
||||||
|
// // viewer, "geometry_instanced_with_separate_material_instances");
|
||||||
|
// // });
|
||||||
|
// // });
|
||||||
|
|
||||||
|
// test('create cube with custom ubershader material (color)', () async {
|
||||||
|
// await testHelper.withViewer((viewer) async {
|
||||||
|
// await viewer.addLight(LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);
|
||||||
|
// await viewer.setCameraPosition(0, 2, 6);
|
||||||
|
// await viewer
|
||||||
|
// .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
|
||||||
|
// await viewer.setBackgroundColor(1.0, 0.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
// var materialInstance =
|
||||||
|
// await viewer.createUbershaderMaterialInstance(unlit: true);
|
||||||
|
// final cube = await viewer.createGeometry(
|
||||||
|
// GeometryHelper.cube(uvs: false, normals: true),
|
||||||
|
// materialInstances: [materialInstance]);
|
||||||
|
// await materialInstance.setParameterFloat4(
|
||||||
|
// "baseColorFactor", 0.0, 1.0, 0.0, 0.0);
|
||||||
|
// await testHelper.capture(
|
||||||
|
// viewer, "geometry_cube_with_custom_material_ubershader");
|
||||||
|
// await viewer.destroyAsset(cube);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// test('create cube with custom ubershader material instance (texture)',
|
||||||
|
// () async {
|
||||||
|
// var viewer = await testHelper.createViewer();
|
||||||
|
// await viewer.addLight(LightType.SUN, 6500, 1000000, 0, 0, 0, 0, 0, -1);
|
||||||
|
// await viewer.setCameraPosition(0, 2, 6);
|
||||||
|
// await viewer
|
||||||
|
// .setCameraRotation(Quaternion.axisAngle(Vector3(1, 0, 0), -pi / 8));
|
||||||
|
// await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
// var materialInstance = await viewer.createUbershaderMaterialInstance();
|
||||||
|
// final cube = await viewer.createGeometry(
|
||||||
|
// GeometryHelper.cube(uvs: true, normals: true),
|
||||||
|
// materialInstances: [materialInstance]);
|
||||||
|
// final image = await viewer.decodeImage(
|
||||||
|
// File("${testHelper.testDir}/assets/cube_texture_512x512.png")
|
||||||
|
// .readAsBytesSync());
|
||||||
|
// var texture = await viewer.createTexture(
|
||||||
|
// await image.getWidth(), await image.getHeight());
|
||||||
|
// await texture.setLinearImage(
|
||||||
|
// image, PixelDataFormat.RGBA, PixelDataType.FLOAT);
|
||||||
|
// await testHelper.capture(
|
||||||
|
// viewer, "geometry_cube_with_custom_material_ubershader_texture");
|
||||||
|
// await viewer.destroyAsset(cube);
|
||||||
|
// await texture.dispose();
|
||||||
|
// await image.destroy();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// test('unlit material with color only', () async {
|
||||||
|
// await testHelper.withViewer((viewer) async {
|
||||||
|
// var materialInstance = await viewer.createUnlitMaterialInstance();
|
||||||
|
// var cube = await viewer.createGeometry(GeometryHelper.cube(),
|
||||||
|
// materialInstances: [materialInstance]);
|
||||||
|
|
||||||
|
// await materialInstance.setParameterFloat4(
|
||||||
|
// "baseColorFactor", 0.0, 1.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
// await testHelper.capture(viewer, "unlit_material_base_color");
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// test('unlit material with texture', () async {
|
||||||
|
// await testHelper.withViewer((viewer) async {
|
||||||
|
// var materialInstance = await viewer.createUnlitMaterialInstance();
|
||||||
|
// var cube = await viewer.createGeometry(GeometryHelper.cube(),
|
||||||
|
// materialInstances: [materialInstance]);
|
||||||
|
|
||||||
|
// await materialInstance.setParameterInt("baseColorIndex", 0);
|
||||||
|
|
||||||
|
// final image = await viewer.decodeImage(
|
||||||
|
// File("${testHelper.testDir}/assets/cube_texture_512x512.png")
|
||||||
|
// .readAsBytesSync());
|
||||||
|
// var texture = await viewer.createTexture(
|
||||||
|
// await image.getWidth(), await image.getHeight());
|
||||||
|
// await texture.setLinearImage(
|
||||||
|
// image, PixelDataFormat.RGBA, PixelDataType.FLOAT);
|
||||||
|
// await testHelper.capture(viewer, "unlit_material_texture_only");
|
||||||
|
// await viewer.destroyAsset(cube);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// test('shared material instance with texture and base color', () async {
|
||||||
|
// await testHelper.withViewer((viewer) async {
|
||||||
|
// var materialInstance = await viewer.createUnlitMaterialInstance();
|
||||||
|
// var cube1 = await viewer.createGeometry(GeometryHelper.cube(),
|
||||||
|
// materialInstances: [materialInstance]);
|
||||||
|
// var cube2 = await viewer.createGeometry(GeometryHelper.cube(),
|
||||||
|
// materialInstances: [materialInstance]);
|
||||||
|
// await viewer.setTransform(
|
||||||
|
// cube2.entity, Matrix4.translation(Vector3(1, 1, 1)));
|
||||||
|
|
||||||
|
// await materialInstance.setParameterInt("baseColorIndex", 0);
|
||||||
|
// final image = await viewer.decodeImage(
|
||||||
|
// File("${testHelper.testDir}/assets/cube_texture_512x512.png")
|
||||||
|
// .readAsBytesSync());
|
||||||
|
// var texture = await viewer.createTexture(
|
||||||
|
// await image.getWidth(), await image.getHeight());
|
||||||
|
// await texture.setLinearImage(
|
||||||
|
// image, PixelDataFormat.RGBA, PixelDataType.FLOAT);
|
||||||
|
|
||||||
|
// await testHelper.capture(viewer, "unlit_material_shared");
|
||||||
|
// await texture.dispose();
|
||||||
|
// await image.destroy();
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// test('create sphere (no normals)', () async {
|
||||||
|
// await testHelper.withViewer((viewer) async {
|
||||||
|
// await viewer
|
||||||
|
// .createGeometry(GeometryHelper.sphere(normals: false, uvs: false));
|
||||||
|
// await testHelper.capture(viewer, "geometry_sphere_no_normals");
|
||||||
|
// }, bg: kBlue, cameraPosition: Vector3(0, 0, 6));
|
||||||
|
// });
|
||||||
|
|
||||||
|
// 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(
|
||||||
|
// GeometryHelper.wireframeCamera(normals: false, uvs: false));
|
||||||
|
// await viewer.setTransform(camera.entity, Matrix4.rotationY(pi / 4));
|
||||||
|
// await testHelper.capture(viewer, "camera_geometry");
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,22 +165,25 @@ class TestHelper {
|
|||||||
resourceLoader.ref.freeResource = freeResource.nativeFunction;
|
resourceLoader.ref.freeResource = freeResource.nativeFunction;
|
||||||
await FFIFilamentApp.create();
|
await FFIFilamentApp.create();
|
||||||
|
|
||||||
await FilamentApp.instance!.setClearColor(0, 0, 0, 1);
|
await FilamentApp.instance!.setClearColor(0, 1, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
Future withViewer(Future Function(ThermionViewer viewer) fn,
|
Future withViewer(
|
||||||
{img.Color? bg,
|
Future Function(ThermionViewer viewer) fn, {
|
||||||
Vector3? cameraPosition,
|
img.Color? bg,
|
||||||
({int width, int height}) viewportDimensions = (width: 500, height: 500),
|
Vector3? cameraPosition,
|
||||||
bool postProcessing = false,
|
({int width, int height}) viewportDimensions = (width: 512, height: 512),
|
||||||
bool createRenderTarget = false}) async {
|
bool postProcessing = false,
|
||||||
|
bool addSkybox = false,
|
||||||
|
bool createRenderTarget = false,
|
||||||
|
}) async {
|
||||||
cameraPosition ??= Vector3(0, 2, 6);
|
cameraPosition ??= Vector3(0, 2, 6);
|
||||||
|
|
||||||
var swapChain = await FilamentApp.instance!.createHeadlessSwapChain(
|
var swapChain = await FilamentApp.instance!
|
||||||
viewportDimensions.width, viewportDimensions.height) as FFISwapChain;
|
.createHeadlessSwapChain(viewportDimensions.width, viewportDimensions.height) as FFISwapChain;
|
||||||
|
|
||||||
FFIRenderTarget? renderTarget;
|
FFIRenderTarget? renderTarget;
|
||||||
if (createRenderTarget) {
|
if (createRenderTarget) {
|
||||||
@@ -198,7 +201,8 @@ class TestHelper {
|
|||||||
},
|
},
|
||||||
textureFormat: TextureFormat.RGB32F,
|
textureFormat: TextureFormat.RGB32F,
|
||||||
importedTextureHandle: metalColorTexture.metalTextureAddress);
|
importedTextureHandle: metalColorTexture.metalTextureAddress);
|
||||||
|
var width = await color.getWidth();
|
||||||
|
var height = await color.getHeight();
|
||||||
var depth = await FilamentApp.instance!
|
var depth = await FilamentApp.instance!
|
||||||
.createTexture(viewportDimensions.width, viewportDimensions.height,
|
.createTexture(viewportDimensions.width, viewportDimensions.height,
|
||||||
flags: {
|
flags: {
|
||||||
@@ -216,16 +220,23 @@ class TestHelper {
|
|||||||
|
|
||||||
var viewer = ThermionViewerFFI(
|
var viewer = ThermionViewerFFI(
|
||||||
loadAssetFromUri: (path) async =>
|
loadAssetFromUri: (path) async =>
|
||||||
File(path.replaceAll("file://", "")).readAsBytesSync(),
|
File(path.replaceAll("file://", "")).readAsBytesSync());
|
||||||
renderTarget: renderTarget);
|
|
||||||
|
|
||||||
await viewer.initialized;
|
await viewer.initialized;
|
||||||
await FilamentApp.instance!.register(swapChain, viewer.view);
|
await FilamentApp.instance!.register(swapChain, viewer.view);
|
||||||
|
if (renderTarget != null) {
|
||||||
|
await viewer.view.setRenderTarget(renderTarget);
|
||||||
|
}
|
||||||
await viewer.view
|
await viewer.view
|
||||||
.setViewport(viewportDimensions.width, viewportDimensions.height);
|
.setViewport(
|
||||||
|
viewportDimensions.width,
|
||||||
|
viewportDimensions.height
|
||||||
|
);
|
||||||
|
|
||||||
await viewer.view.setBloom(false, 0);
|
if (addSkybox) {
|
||||||
|
await viewer
|
||||||
|
.loadSkybox("file://${testDir}/assets/default_env_skybox.ktx");
|
||||||
|
}
|
||||||
|
|
||||||
if (bg != null) {
|
if (bg != null) {
|
||||||
await viewer.setBackgroundColor(
|
await viewer.setBackgroundColor(
|
||||||
|
|||||||
@@ -20,4 +20,5 @@ class ThermionFlutterPlugin {
|
|||||||
|
|
||||||
return viewer;
|
return viewer;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,98 +1,98 @@
|
|||||||
import 'dart:math';
|
// import 'dart:math';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
// import 'package:flutter/material.dart';
|
||||||
import 'package:thermion_flutter/thermion_flutter.dart';
|
// import 'package:thermion_flutter/thermion_flutter.dart';
|
||||||
import 'package:vector_math/vector_math_64.dart' as v64;
|
// import 'package:vector_math/vector_math_64.dart' as v64;
|
||||||
|
|
||||||
class CameraOrientationWidget extends StatefulWidget {
|
// class CameraOrientationWidget extends StatefulWidget {
|
||||||
final ThermionViewer viewer;
|
// final ThermionViewer viewer;
|
||||||
|
|
||||||
const CameraOrientationWidget({Key? key, required this.viewer})
|
// const CameraOrientationWidget({Key? key, required this.viewer})
|
||||||
: super(key: key);
|
// : super(key: key);
|
||||||
|
|
||||||
@override
|
// @override
|
||||||
_CameraOrientationWidgetState createState() =>
|
// _CameraOrientationWidgetState createState() =>
|
||||||
_CameraOrientationWidgetState();
|
// _CameraOrientationWidgetState();
|
||||||
}
|
// }
|
||||||
|
|
||||||
class _CameraOrientationWidgetState extends State<CameraOrientationWidget>
|
// class _CameraOrientationWidgetState extends State<CameraOrientationWidget>
|
||||||
with SingleTickerProviderStateMixin {
|
// with SingleTickerProviderStateMixin {
|
||||||
late AnimationController _controller;
|
// late AnimationController _controller;
|
||||||
v64.Vector3? _position;
|
// v64.Vector3? _position;
|
||||||
v64.Matrix3? _rotation;
|
// v64.Matrix3? _rotation;
|
||||||
|
|
||||||
@override
|
// @override
|
||||||
void initState() {
|
// void initState() {
|
||||||
super.initState();
|
// super.initState();
|
||||||
_controller = AnimationController(
|
// _controller = AnimationController(
|
||||||
vsync: this,
|
// vsync: this,
|
||||||
duration: const Duration(milliseconds: 16), // ~60 FPS
|
// duration: const Duration(milliseconds: 16), // ~60 FPS
|
||||||
)..repeat();
|
// )..repeat();
|
||||||
|
|
||||||
_controller.addListener(_updateCameraInfo);
|
// _controller.addListener(_updateCameraInfo);
|
||||||
}
|
// }
|
||||||
|
|
||||||
void _updateCameraInfo() async {
|
// void _updateCameraInfo() async {
|
||||||
final camera = await widget.viewer.getActiveCamera();
|
// final camera = await widget.viewer.getActiveCamera();
|
||||||
final position = await widget.viewer.getCameraPosition();
|
// final position = await widget.viewer.getCameraPosition();
|
||||||
final rotation = await widget.viewer.getCameraRotation();
|
// final rotation = await widget.viewer.getCameraRotation();
|
||||||
setState(() {
|
// setState(() {
|
||||||
_position = position;
|
// _position = position;
|
||||||
_rotation = rotation;
|
// _rotation = rotation;
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
@override
|
// @override
|
||||||
void dispose() {
|
// void dispose() {
|
||||||
_controller.dispose();
|
// _controller.dispose();
|
||||||
super.dispose();
|
// super.dispose();
|
||||||
}
|
// }
|
||||||
|
|
||||||
@override
|
// @override
|
||||||
Widget build(BuildContext context) {
|
// Widget build(BuildContext context) {
|
||||||
return Container(
|
// return Container(
|
||||||
padding: const EdgeInsets.all(8.0),
|
// padding: const EdgeInsets.all(8.0),
|
||||||
decoration: BoxDecoration(
|
// decoration: BoxDecoration(
|
||||||
color: Colors.black.withOpacity(0.7),
|
// color: Colors.black.withOpacity(0.7),
|
||||||
borderRadius: BorderRadius.circular(8.0),
|
// borderRadius: BorderRadius.circular(8.0),
|
||||||
),
|
// ),
|
||||||
child: Column(
|
// child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisSize: MainAxisSize.min,
|
// mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
// children: [
|
||||||
Text(
|
// Text(
|
||||||
'Position: ${_formatVector(_position)}',
|
// 'Position: ${_formatVector(_position)}',
|
||||||
style: const TextStyle(color: Colors.white),
|
// style: const TextStyle(color: Colors.white),
|
||||||
),
|
// ),
|
||||||
const SizedBox(height: 4),
|
// const SizedBox(height: 4),
|
||||||
Text(
|
// Text(
|
||||||
'Rotation: ${_formatMatrix(_rotation)}',
|
// 'Rotation: ${_formatMatrix(_rotation)}',
|
||||||
style: const TextStyle(color: Colors.white),
|
// style: const TextStyle(color: Colors.white),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
String _formatVector(v64.Vector3? vector) {
|
// String _formatVector(v64.Vector3? vector) {
|
||||||
if (vector == null) return 'N/A';
|
// if (vector == null) return 'N/A';
|
||||||
return '(${vector.x.toStringAsFixed(2)}, ${vector.y.toStringAsFixed(2)}, ${vector.z.toStringAsFixed(2)})';
|
// return '(${vector.x.toStringAsFixed(2)}, ${vector.y.toStringAsFixed(2)}, ${vector.z.toStringAsFixed(2)})';
|
||||||
}
|
// }
|
||||||
|
|
||||||
String _formatMatrix(v64.Matrix3? matrix) {
|
// String _formatMatrix(v64.Matrix3? matrix) {
|
||||||
if (matrix == null) return 'N/A';
|
// if (matrix == null) return 'N/A';
|
||||||
return 'Yaw: ${_getYaw(matrix).toStringAsFixed(2)}°, Pitch: ${_getPitch(matrix).toStringAsFixed(2)}°, Roll: ${_getRoll(matrix).toStringAsFixed(2)}°';
|
// return 'Yaw: ${_getYaw(matrix).toStringAsFixed(2)}°, Pitch: ${_getPitch(matrix).toStringAsFixed(2)}°, Roll: ${_getRoll(matrix).toStringAsFixed(2)}°';
|
||||||
}
|
// }
|
||||||
|
|
||||||
double _getYaw(v64.Matrix3 matrix) {
|
// double _getYaw(v64.Matrix3 matrix) {
|
||||||
return -atan2(matrix[2], matrix[0]) * 180 / pi;
|
// return -atan2(matrix[2], matrix[0]) * 180 / pi;
|
||||||
}
|
// }
|
||||||
|
|
||||||
double _getPitch(v64.Matrix3 matrix) {
|
// double _getPitch(v64.Matrix3 matrix) {
|
||||||
return -asin(matrix[5]) * 180 / pi;
|
// return -asin(matrix[5]) * 180 / pi;
|
||||||
}
|
// }
|
||||||
|
|
||||||
double _getRoll(v64.Matrix3 matrix) {
|
// double _getRoll(v64.Matrix3 matrix) {
|
||||||
return atan2(matrix[3], matrix[4]) * 180 / pi;
|
// return atan2(matrix[3], matrix[4]) * 180 / pi;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|||||||
@@ -1,79 +1,79 @@
|
|||||||
import 'package:flutter/material.dart';
|
// import 'package:flutter/material.dart';
|
||||||
import 'package:thermion_dart/thermion_dart.dart';
|
// import 'package:thermion_dart/thermion_dart.dart';
|
||||||
|
|
||||||
class CameraSelectorWidget extends StatefulWidget {
|
// class CameraSelectorWidget extends StatefulWidget {
|
||||||
final ThermionViewer viewer;
|
// final ThermionViewer viewer;
|
||||||
|
|
||||||
const CameraSelectorWidget({Key? key, required this.viewer}) : super(key: key);
|
// const CameraSelectorWidget({Key? key, required this.viewer}) : super(key: key);
|
||||||
|
|
||||||
@override
|
// @override
|
||||||
_CameraSelectorWidgetState createState() => _CameraSelectorWidgetState();
|
// _CameraSelectorWidgetState createState() => _CameraSelectorWidgetState();
|
||||||
}
|
// }
|
||||||
|
|
||||||
class _CameraSelectorWidgetState extends State<CameraSelectorWidget> {
|
// class _CameraSelectorWidgetState extends State<CameraSelectorWidget> {
|
||||||
int _activeIndex = 0;
|
// int _activeIndex = 0;
|
||||||
|
|
||||||
@override
|
// @override
|
||||||
Widget build(BuildContext context) {
|
// Widget build(BuildContext context) {
|
||||||
int cameraCount = widget.viewer.getCameraCount();
|
// int cameraCount = widget.viewer.getCameraCount();
|
||||||
|
|
||||||
return Container(
|
// return Container(
|
||||||
height:32,
|
// height:32,
|
||||||
margin: const EdgeInsets.all(8),
|
// margin: const EdgeInsets.all(8),
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
|
// padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
|
||||||
decoration: BoxDecoration(
|
// decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(8),
|
// borderRadius: BorderRadius.circular(8),
|
||||||
boxShadow: [
|
// boxShadow: [
|
||||||
BoxShadow(
|
// BoxShadow(
|
||||||
color: Colors.black.withOpacity(0.1),
|
// color: Colors.black.withOpacity(0.1),
|
||||||
blurRadius: 4,
|
// blurRadius: 4,
|
||||||
offset: const Offset(0, 2),
|
// offset: const Offset(0, 2),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
child: Row(
|
// child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisSize: MainAxisSize.min,
|
// mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
// children: [
|
||||||
_buildCameraButton("Main", 0),
|
// _buildCameraButton("Main", 0),
|
||||||
if (cameraCount > 1) const VerticalDivider(width: 16, thickness: 1),
|
// if (cameraCount > 1) const VerticalDivider(width: 16, thickness: 1),
|
||||||
...List.generate(cameraCount - 1, (index) {
|
// ...List.generate(cameraCount - 1, (index) {
|
||||||
return _buildCameraButton("${index + 1}", index + 1);
|
// return _buildCameraButton("${index + 1}", index + 1);
|
||||||
}),
|
// }),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
Widget _buildCameraButton(String label, int index) {
|
// Widget _buildCameraButton(String label, int index) {
|
||||||
bool isActive = _activeIndex == index;
|
// bool isActive = _activeIndex == index;
|
||||||
return Flexible(child:TextButton(
|
// return Flexible(child:TextButton(
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
if (index == 0) {
|
// if (index == 0) {
|
||||||
await widget.viewer.setMainCamera();
|
// await widget.viewer.setMainCamera();
|
||||||
} else {
|
// } else {
|
||||||
Camera camera = widget.viewer.getCameraAt(index);
|
// Camera camera = widget.viewer.getCameraAt(index);
|
||||||
await widget.viewer.setActiveCamera(camera);
|
// await widget.viewer.setActiveCamera(camera);
|
||||||
}
|
// }
|
||||||
setState(() {
|
// setState(() {
|
||||||
_activeIndex = index;
|
// _activeIndex = index;
|
||||||
});
|
// });
|
||||||
},
|
// },
|
||||||
style: TextButton.styleFrom(
|
// style: TextButton.styleFrom(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
// padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
minimumSize: Size.zero,
|
// minimumSize: Size.zero,
|
||||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
// tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
backgroundColor: isActive ? Colors.blue.withOpacity(0.1) : null,
|
// backgroundColor: isActive ? Colors.blue.withOpacity(0.1) : null,
|
||||||
),
|
// ),
|
||||||
child: Text(
|
// child: Text(
|
||||||
label,
|
// label,
|
||||||
style: TextStyle(
|
// style: TextStyle(
|
||||||
fontSize: 10,
|
// fontSize: 10,
|
||||||
fontWeight: isActive ? FontWeight.bold : FontWeight.normal,
|
// fontWeight: isActive ? FontWeight.bold : FontWeight.normal,
|
||||||
color: isActive ? Colors.blue : Colors.black87,
|
// color: isActive ? Colors.blue : Colors.black87,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
));
|
// ));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
@@ -1,110 +1,110 @@
|
|||||||
import 'package:animation_tools_dart/animation_tools_dart.dart';
|
// import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||||
import 'package:thermion_dart/thermion_dart.dart';
|
// import 'package:thermion_dart/thermion_dart.dart';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
// import 'package:flutter/material.dart';
|
||||||
import 'dart:math';
|
// import 'dart:math';
|
||||||
|
|
||||||
class ChildRenderableWidget extends StatelessWidget {
|
// class ChildRenderableWidget extends StatelessWidget {
|
||||||
final ThermionViewer controller;
|
// final ThermionViewer controller;
|
||||||
final ThermionEntity entity;
|
// final ThermionEntity entity;
|
||||||
|
|
||||||
const ChildRenderableWidget(
|
// const ChildRenderableWidget(
|
||||||
{super.key, required this.controller, required this.entity});
|
// {super.key, required this.controller, required this.entity});
|
||||||
|
|
||||||
Widget _childRenderable(ThermionEntity childEntity) {
|
// Widget _childRenderable(ThermionEntity childEntity) {
|
||||||
var name = controller.getNameForEntity(childEntity) ?? "<none>";
|
// var name = controller.getNameForEntity(childEntity) ?? "<none>";
|
||||||
var names = controller.getMorphTargetNames(entity, childEntity);
|
// var names = controller.getMorphTargetNames(entity, childEntity);
|
||||||
|
|
||||||
return FutureBuilder(
|
// return FutureBuilder(
|
||||||
future: names,
|
// future: names,
|
||||||
builder: (_, morphTargetsSnapshot) {
|
// builder: (_, morphTargetsSnapshot) {
|
||||||
if (!morphTargetsSnapshot.hasData) {
|
// if (!morphTargetsSnapshot.hasData) {
|
||||||
return Container();
|
// return Container();
|
||||||
}
|
// }
|
||||||
var morphTargets = morphTargetsSnapshot.data!;
|
// var morphTargets = morphTargetsSnapshot.data!;
|
||||||
|
|
||||||
final menuChildren = <Widget>[];
|
// final menuChildren = <Widget>[];
|
||||||
if (morphTargets.isEmpty) {
|
// if (morphTargets.isEmpty) {
|
||||||
menuChildren.add(Text("None"));
|
// menuChildren.add(Text("None"));
|
||||||
} else {
|
// } else {
|
||||||
for (int i = 0; i < 2; i++) {
|
// for (int i = 0; i < 2; i++) {
|
||||||
var newWeights = List.filled(morphTargets.length, i.toDouble());
|
// var newWeights = List.filled(morphTargets.length, i.toDouble());
|
||||||
menuChildren.add(MenuItemButton(
|
// menuChildren.add(MenuItemButton(
|
||||||
child: Text("Set to $i"),
|
// child: Text("Set to $i"),
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
try {
|
// try {
|
||||||
await controller!
|
// await controller!
|
||||||
.setMorphTargetWeights(childEntity, newWeights);
|
// .setMorphTargetWeights(childEntity, newWeights);
|
||||||
} catch (err, st) {
|
// } catch (err, st) {
|
||||||
print("Error setting morph target weights");
|
// print("Error setting morph target weights");
|
||||||
print(err);
|
// print(err);
|
||||||
print(st);
|
// print(st);
|
||||||
}
|
// }
|
||||||
}));
|
// }));
|
||||||
}
|
// }
|
||||||
menuChildren.add(MenuItemButton(
|
// menuChildren.add(MenuItemButton(
|
||||||
child: Text("Animate all morph target from 0 to 1"),
|
// child: Text("Animate all morph target from 0 to 1"),
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
var morphData = MorphAnimationData(
|
// var morphData = MorphAnimationData(
|
||||||
List<List<double>>.generate(
|
// List<List<double>>.generate(
|
||||||
120,
|
// 120,
|
||||||
(i) => List<double>.filled(
|
// (i) => List<double>.filled(
|
||||||
morphTargets.length, i / 120)),
|
// morphTargets.length, i / 120)),
|
||||||
morphTargets);
|
// morphTargets);
|
||||||
await controller!.setMorphAnimationData(entity, morphData,
|
// await controller!.setMorphAnimationData(entity, morphData,
|
||||||
targetMeshNames: [name]);
|
// targetMeshNames: [name]);
|
||||||
}));
|
// }));
|
||||||
menuChildren.addAll(morphTargets.map((t) => Text(t)));
|
// menuChildren.addAll(morphTargets.map((t) => Text(t)));
|
||||||
}
|
// }
|
||||||
return SubmenuButton(child: Text(name), menuChildren: menuChildren);
|
// return SubmenuButton(child: Text(name), menuChildren: menuChildren);
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
@override
|
// @override
|
||||||
Widget build(BuildContext context) {
|
// Widget build(BuildContext context) {
|
||||||
return FutureBuilder(
|
// return FutureBuilder(
|
||||||
future: controller!.getChildEntities(entity, true),
|
// future: controller!.getChildEntities(entity, true),
|
||||||
builder: (ctx, snapshot) {
|
// builder: (ctx, snapshot) {
|
||||||
if (!snapshot.hasData) {
|
// if (!snapshot.hasData) {
|
||||||
return Container();
|
// return Container();
|
||||||
}
|
// }
|
||||||
|
|
||||||
var children = snapshot.data!;
|
// var children = snapshot.data!;
|
||||||
return SubmenuButton(
|
// return SubmenuButton(
|
||||||
child: Text("Renderable entities"),
|
// child: Text("Renderable entities"),
|
||||||
menuChildren: <Widget>[
|
// menuChildren: <Widget>[
|
||||||
MenuItemButton(
|
// MenuItemButton(
|
||||||
child: Text("Set children transforms to identity"),
|
// child: Text("Set children transforms to identity"),
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
var childEntities =
|
// var childEntities =
|
||||||
await controller.getChildEntities(entity, true);
|
// await controller.getChildEntities(entity, true);
|
||||||
for (final child in childEntities) {
|
// for (final child in childEntities) {
|
||||||
await controller.setTransform(
|
// await controller.setTransform(
|
||||||
child, Matrix4.identity());
|
// child, Matrix4.identity());
|
||||||
}
|
// }
|
||||||
}),
|
// }),
|
||||||
MenuItemButton(
|
// MenuItemButton(
|
||||||
child: Text("Set children transforms to 90/X"),
|
// child: Text("Set children transforms to 90/X"),
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
var childEntities =
|
// var childEntities =
|
||||||
await controller.getChildEntities(entity, true);
|
// await controller.getChildEntities(entity, true);
|
||||||
for (final child in childEntities) {
|
// for (final child in childEntities) {
|
||||||
await controller.setTransform(
|
// await controller.setTransform(
|
||||||
child, Matrix4.rotationX(pi / 2));
|
// child, Matrix4.rotationX(pi / 2));
|
||||||
}
|
// }
|
||||||
}),
|
// }),
|
||||||
MenuItemButton(
|
// MenuItemButton(
|
||||||
child: Text("Set children transforms to 90/Y"),
|
// child: Text("Set children transforms to 90/Y"),
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
var childEntities =
|
// var childEntities =
|
||||||
await controller.getChildEntities(entity, true);
|
// await controller.getChildEntities(entity, true);
|
||||||
for (final child in childEntities) {
|
// for (final child in childEntities) {
|
||||||
await controller.setTransform(
|
// await controller.setTransform(
|
||||||
child, Matrix4.rotationY(pi / 2));
|
// child, Matrix4.rotationY(pi / 2));
|
||||||
}
|
// }
|
||||||
}),
|
// }),
|
||||||
] +
|
// ] +
|
||||||
children.map(_childRenderable).toList());
|
// children.map(_childRenderable).toList());
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|||||||
@@ -1,421 +1,421 @@
|
|||||||
import 'dart:math';
|
// import 'dart:math';
|
||||||
|
|
||||||
import 'package:thermion_dart/thermion_dart.dart';
|
// import 'package:thermion_dart/thermion_dart.dart';
|
||||||
import 'package:animation_tools_dart/animation_tools_dart.dart';
|
// import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||||
import 'package:flutter/material.dart';
|
// import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
// import 'package:flutter/widgets.dart';
|
||||||
import 'package:vector_math/vector_math_64.dart';
|
// import 'package:vector_math/vector_math_64.dart';
|
||||||
|
|
||||||
class SkeletonMenuItemWidget extends StatelessWidget {
|
// class SkeletonMenuItemWidget extends StatelessWidget {
|
||||||
final ThermionViewer controller;
|
// final ThermionViewer controller;
|
||||||
final ThermionEntity entity;
|
// final ThermionEntity entity;
|
||||||
|
|
||||||
const SkeletonMenuItemWidget(
|
// const SkeletonMenuItemWidget(
|
||||||
{super.key, required this.controller, required this.entity});
|
// {super.key, required this.controller, required this.entity});
|
||||||
|
|
||||||
void _addBoneAnimation(String bone) async {
|
// void _addBoneAnimation(String bone) async {
|
||||||
await controller.addAnimationComponent(entity);
|
// await controller.addAnimationComponent(entity);
|
||||||
var numFrames = 120;
|
// var numFrames = 120;
|
||||||
var animationData = List<List<BoneAnimationFrame>>.generate(
|
// var animationData = List<List<BoneAnimationFrame>>.generate(
|
||||||
numFrames,
|
// numFrames,
|
||||||
(frameNum) => [
|
// (frameNum) => [
|
||||||
(
|
// (
|
||||||
rotation: Quaternion.axisAngle(
|
// rotation: Quaternion.axisAngle(
|
||||||
Vector3(1, 0, 0), (frameNum / 90) * 2 * pi),
|
// Vector3(1, 0, 0), (frameNum / 90) * 2 * pi),
|
||||||
translation: Vector3.zero()
|
// translation: Vector3.zero()
|
||||||
)
|
// )
|
||||||
]);
|
// ]);
|
||||||
var animation =
|
// var animation =
|
||||||
BoneAnimationData([bone], animationData, space: Space.ParentWorldRotation);
|
// BoneAnimationData([bone], animationData, space: Space.ParentWorldRotation);
|
||||||
await controller.addAnimationComponent(entity);
|
// await controller.addAnimationComponent(entity);
|
||||||
await controller.addBoneAnimation(entity, animation);
|
// await controller.addBoneAnimation(entity, animation);
|
||||||
}
|
// }
|
||||||
|
|
||||||
@override
|
// @override
|
||||||
Widget build(BuildContext context) {
|
// Widget build(BuildContext context) {
|
||||||
var boneNames = controller.getBoneNames(entity);
|
// var boneNames = controller.getBoneNames(entity);
|
||||||
|
|
||||||
return FutureBuilder(
|
// return FutureBuilder(
|
||||||
future: boneNames,
|
// future: boneNames,
|
||||||
builder: (_, boneNamesSnapshot) {
|
// builder: (_, boneNamesSnapshot) {
|
||||||
if (!boneNamesSnapshot.hasData) {
|
// if (!boneNamesSnapshot.hasData) {
|
||||||
return Container();
|
// return Container();
|
||||||
}
|
// }
|
||||||
var boneNames = boneNamesSnapshot.data!;
|
// var boneNames = boneNamesSnapshot.data!;
|
||||||
if (boneNames.isEmpty) {
|
// if (boneNames.isEmpty) {
|
||||||
return Text("No bones");
|
// return Text("No bones");
|
||||||
}
|
// }
|
||||||
|
|
||||||
return SubmenuButton(
|
// return SubmenuButton(
|
||||||
menuChildren: <Widget>[
|
// menuChildren: <Widget>[
|
||||||
MenuItemButton(
|
// MenuItemButton(
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
await controller.resetBones(entity);
|
// await controller.resetBones(entity);
|
||||||
},
|
// },
|
||||||
child: Text("Reset")),
|
// child: Text("Reset")),
|
||||||
MenuItemButton(
|
// MenuItemButton(
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
await controller.resetBones(entity);
|
// await controller.resetBones(entity);
|
||||||
|
|
||||||
var bone = await controller.getBone(entity, 1);
|
// var bone = await controller.getBone(entity, 1);
|
||||||
var frames = <List<BoneAnimationFrame>>[];
|
// var frames = <List<BoneAnimationFrame>>[];
|
||||||
for (int i = 0; i < 60; i++) {
|
// for (int i = 0; i < 60; i++) {
|
||||||
var frame = <BoneAnimationFrame>[];
|
// var frame = <BoneAnimationFrame>[];
|
||||||
frame.add((
|
// frame.add((
|
||||||
rotation:
|
// rotation:
|
||||||
Quaternion.axisAngle(
|
// Quaternion.axisAngle(
|
||||||
Vector3(1, 0, 0), i/60 * pi/4) *
|
// Vector3(1, 0, 0), i/60 * pi/4) *
|
||||||
(Quaternion.axisAngle(
|
// (Quaternion.axisAngle(
|
||||||
Vector3(0, 0, 1), i/60*-pi/4)
|
// Vector3(0, 0, 1), i/60*-pi/4)
|
||||||
*
|
// *
|
||||||
Quaternion.axisAngle(
|
// Quaternion.axisAngle(
|
||||||
Vector3(0, 1, 0), i/60 * pi/4) ),
|
// Vector3(0, 1, 0), i/60 * pi/4) ),
|
||||||
translation: Vector3.zero()
|
// translation: Vector3.zero()
|
||||||
));
|
// ));
|
||||||
frames.add(frame);
|
// frames.add(frame);
|
||||||
}
|
// }
|
||||||
|
|
||||||
var animation = BoneAnimationData(["Bone.002"], frames,
|
// var animation = BoneAnimationData(["Bone.002"], frames,
|
||||||
space: Space.ParentWorldRotation);
|
// space: Space.ParentWorldRotation);
|
||||||
await controller.addAnimationComponent(entity);
|
// await controller.addAnimationComponent(entity);
|
||||||
await controller.addBoneAnimation(entity, animation);
|
// await controller.addBoneAnimation(entity, animation);
|
||||||
},
|
// },
|
||||||
child: Text("Test animation (parent space)")),
|
// child: Text("Test animation (parent space)")),
|
||||||
MenuItemButton(
|
// MenuItemButton(
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
await controller.resetBones(entity);
|
// await controller.resetBones(entity);
|
||||||
|
|
||||||
var bone = await controller.getBone(entity, 1);
|
// var bone = await controller.getBone(entity, 1);
|
||||||
|
|
||||||
var frames = <List<BoneAnimationFrame>>[];
|
// var frames = <List<BoneAnimationFrame>>[];
|
||||||
for (int i = 0; i < 60; i++) {
|
// for (int i = 0; i < 60; i++) {
|
||||||
var frame = <BoneAnimationFrame>[];
|
// var frame = <BoneAnimationFrame>[];
|
||||||
frame.add((
|
// frame.add((
|
||||||
rotation: Quaternion.axisAngle(
|
// rotation: Quaternion.axisAngle(
|
||||||
Vector3(0, 0, 1), (i / 60) * pi / 2),
|
// Vector3(0, 0, 1), (i / 60) * pi / 2),
|
||||||
translation: Vector3.zero()
|
// translation: Vector3.zero()
|
||||||
));
|
// ));
|
||||||
frames.add(frame);
|
// frames.add(frame);
|
||||||
}
|
// }
|
||||||
var animation = BoneAnimationData(
|
// var animation = BoneAnimationData(
|
||||||
["Bone.001"], frames,
|
// ["Bone.001"], frames,
|
||||||
space: Space.Bone);
|
// space: Space.Bone);
|
||||||
await controller.addAnimationComponent(entity);
|
// await controller.addAnimationComponent(entity);
|
||||||
await controller.addBoneAnimation(entity, animation);
|
// await controller.addBoneAnimation(entity, animation);
|
||||||
},
|
// },
|
||||||
child: Text("Test animation (bone space)")),
|
// child: Text("Test animation (bone space)")),
|
||||||
MenuItemButton(
|
// MenuItemButton(
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
var frames = <List<BoneAnimationFrame>>[];
|
// var frames = <List<BoneAnimationFrame>>[];
|
||||||
for (int i = 0; i < 60; i++) {
|
// for (int i = 0; i < 60; i++) {
|
||||||
var frame = <BoneAnimationFrame>[];
|
// var frame = <BoneAnimationFrame>[];
|
||||||
frame.add((
|
// frame.add((
|
||||||
rotation: Quaternion.axisAngle(
|
// rotation: Quaternion.axisAngle(
|
||||||
Vector3(0, 0, 1), (i / 60) * pi / 2),
|
// Vector3(0, 0, 1), (i / 60) * pi / 2),
|
||||||
translation: Vector3.zero()
|
// translation: Vector3.zero()
|
||||||
));
|
// ));
|
||||||
frames.add(frame);
|
// frames.add(frame);
|
||||||
}
|
// }
|
||||||
var animation = BoneAnimationData(
|
// var animation = BoneAnimationData(
|
||||||
["Bone.001"], frames,
|
// ["Bone.001"], frames,
|
||||||
space: Space.ParentWorldRotation);
|
// space: Space.ParentWorldRotation);
|
||||||
await controller.addAnimationComponent(entity);
|
// await controller.addAnimationComponent(entity);
|
||||||
await controller.addBoneAnimation(entity, animation);
|
// await controller.addBoneAnimation(entity, animation);
|
||||||
},
|
// },
|
||||||
child: Text("Test animation 2")),
|
// child: Text("Test animation 2")),
|
||||||
MenuItemButton(
|
// MenuItemButton(
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
var frames = <List<BoneAnimationFrame>>[];
|
// var frames = <List<BoneAnimationFrame>>[];
|
||||||
for (int i = 0; i < 60; i++) {
|
// for (int i = 0; i < 60; i++) {
|
||||||
var frame = <BoneAnimationFrame>[];
|
// var frame = <BoneAnimationFrame>[];
|
||||||
frame.add((
|
// frame.add((
|
||||||
rotation: Quaternion.axisAngle(
|
// rotation: Quaternion.axisAngle(
|
||||||
Vector3(0, 0, 1), (i / 60) * pi / 2),
|
// Vector3(0, 0, 1), (i / 60) * pi / 2),
|
||||||
translation: Vector3.zero()
|
// translation: Vector3.zero()
|
||||||
));
|
// ));
|
||||||
frames.add(frame);
|
// frames.add(frame);
|
||||||
}
|
// }
|
||||||
var animation = BoneAnimationData(
|
// var animation = BoneAnimationData(
|
||||||
["Bone.002"], frames,
|
// ["Bone.002"], frames,
|
||||||
space: Space.ParentWorldRotation);
|
// space: Space.ParentWorldRotation);
|
||||||
await controller.addAnimationComponent(entity);
|
// await controller.addAnimationComponent(entity);
|
||||||
await controller.addBoneAnimation(entity, animation);
|
// await controller.addBoneAnimation(entity, animation);
|
||||||
},
|
// },
|
||||||
child: Text("Test animation 3"))
|
// child: Text("Test animation 3"))
|
||||||
] +
|
// ] +
|
||||||
boneNames
|
// boneNames
|
||||||
.map((name) {
|
// .map((name) {
|
||||||
var boneIndex = boneNames.indexOf(name);
|
// var boneIndex = boneNames.indexOf(name);
|
||||||
return SubmenuButton(child: Text(name), menuChildren: [
|
// return SubmenuButton(child: Text(name), menuChildren: [
|
||||||
MenuItemButton(
|
// MenuItemButton(
|
||||||
child: Text("Print bone transforms "),
|
// child: Text("Print bone transforms "),
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
var boneEntity =
|
// var boneEntity =
|
||||||
await controller.getBone(entity, boneIndex);
|
// await controller.getBone(entity, boneIndex);
|
||||||
var localTransform = await controller
|
// var localTransform = await controller
|
||||||
.getLocalTransform(boneEntity);
|
// .getLocalTransform(boneEntity);
|
||||||
var worldTransform = await controller
|
// var worldTransform = await controller
|
||||||
.getWorldTransform(boneEntity);
|
// .getWorldTransform(boneEntity);
|
||||||
var inverseWorldTransform = Matrix4.identity()
|
// var inverseWorldTransform = Matrix4.identity()
|
||||||
..copyInverse(worldTransform);
|
// ..copyInverse(worldTransform);
|
||||||
print("Local $localTransform");
|
// print("Local $localTransform");
|
||||||
print("World $worldTransform");
|
// print("World $worldTransform");
|
||||||
print("World inverse $inverseWorldTransform");
|
// print("World inverse $inverseWorldTransform");
|
||||||
}),
|
// }),
|
||||||
MenuItemButton(
|
// MenuItemButton(
|
||||||
child: Text("Set bone transform to identity"),
|
// child: Text("Set bone transform to identity"),
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
var boneEntity =
|
// var boneEntity =
|
||||||
await controller.getBone(entity, boneIndex);
|
// await controller.getBone(entity, boneIndex);
|
||||||
var localTransform = Matrix4.identity();
|
// var localTransform = Matrix4.identity();
|
||||||
await controller.setTransform(
|
// await controller.setTransform(
|
||||||
boneEntity, localTransform);
|
// boneEntity, localTransform);
|
||||||
await controller.updateBoneMatrices(entity);
|
// await controller.updateBoneMatrices(entity);
|
||||||
}),
|
// }),
|
||||||
MenuItemButton(
|
// MenuItemButton(
|
||||||
child: Text(
|
// child: Text(
|
||||||
"Set bone transform to 90/X (parent space)"),
|
// "Set bone transform to 90/X (parent space)"),
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
var boneEntity =
|
// var boneEntity =
|
||||||
await controller.getBone(entity, boneIndex);
|
// await controller.getBone(entity, boneIndex);
|
||||||
var localTransform = Matrix4.rotationX(pi / 2);
|
// var localTransform = Matrix4.rotationX(pi / 2);
|
||||||
await controller.setTransform(
|
// await controller.setTransform(
|
||||||
boneEntity, localTransform);
|
// boneEntity, localTransform);
|
||||||
await controller.updateBoneMatrices(entity);
|
// await controller.updateBoneMatrices(entity);
|
||||||
}),
|
// }),
|
||||||
MenuItemButton(
|
// MenuItemButton(
|
||||||
child: Text(
|
// child: Text(
|
||||||
"Set bone transform to 90/X (pose space)"),
|
// "Set bone transform to 90/X (pose space)"),
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
var boneEntity =
|
// var boneEntity =
|
||||||
await controller.getBone(entity, boneIndex);
|
// await controller.getBone(entity, boneIndex);
|
||||||
var localTransform = await controller
|
// var localTransform = await controller
|
||||||
.getLocalTransform(boneEntity);
|
// .getLocalTransform(boneEntity);
|
||||||
localTransform =
|
// localTransform =
|
||||||
localTransform * Matrix4.rotationX(pi / 2);
|
// localTransform * Matrix4.rotationX(pi / 2);
|
||||||
await controller.setTransform(
|
// await controller.setTransform(
|
||||||
boneEntity, localTransform);
|
// boneEntity, localTransform);
|
||||||
await controller.updateBoneMatrices(entity);
|
// await controller.updateBoneMatrices(entity);
|
||||||
}),
|
// }),
|
||||||
MenuItemButton(
|
// MenuItemButton(
|
||||||
child: Text("Set bone transform to 90/X"),
|
// child: Text("Set bone transform to 90/X"),
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
var boneEntity =
|
// var boneEntity =
|
||||||
await controller.getBone(entity, boneIndex);
|
// await controller.getBone(entity, boneIndex);
|
||||||
var localTransform = Matrix4.rotationX(pi / 2);
|
// var localTransform = Matrix4.rotationX(pi / 2);
|
||||||
await controller.setTransform(
|
// await controller.setTransform(
|
||||||
boneEntity, localTransform);
|
// boneEntity, localTransform);
|
||||||
await controller.updateBoneMatrices(entity);
|
// await controller.updateBoneMatrices(entity);
|
||||||
}),
|
// }),
|
||||||
MenuItemButton(
|
// MenuItemButton(
|
||||||
child: Text("Set bone transform to 0,-1,0"),
|
// child: Text("Set bone transform to 0,-1,0"),
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
var boneEntity =
|
// var boneEntity =
|
||||||
await controller.getBone(entity, boneIndex);
|
// await controller.getBone(entity, boneIndex);
|
||||||
var localTransform =
|
// var localTransform =
|
||||||
Matrix4.translation(Vector3(0, -1, 0));
|
// Matrix4.translation(Vector3(0, -1, 0));
|
||||||
await controller.setTransform(
|
// await controller.setTransform(
|
||||||
boneEntity, localTransform);
|
// boneEntity, localTransform);
|
||||||
await controller.updateBoneMatrices(entity);
|
// await controller.updateBoneMatrices(entity);
|
||||||
}),
|
// }),
|
||||||
MenuItemButton(
|
// MenuItemButton(
|
||||||
child: Text(
|
// child: Text(
|
||||||
"Set bone matrices/transform to identity"),
|
// "Set bone matrices/transform to identity"),
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
var boneEntity = await controller.getBone(
|
// var boneEntity = await controller.getBone(
|
||||||
entity, boneNames.indexOf(name));
|
// entity, boneNames.indexOf(name));
|
||||||
await controller.setTransform(
|
// await controller.setTransform(
|
||||||
boneEntity, Matrix4.identity());
|
// boneEntity, Matrix4.identity());
|
||||||
var childEntities = await controller
|
// var childEntities = await controller
|
||||||
.getChildEntities(entity, true);
|
// .getChildEntities(entity, true);
|
||||||
for (final child in childEntities) {
|
// for (final child in childEntities) {
|
||||||
await controller.setBoneTransform(
|
// await controller.setBoneTransform(
|
||||||
child,
|
// child,
|
||||||
boneNames.indexOf(name),
|
// boneNames.indexOf(name),
|
||||||
Matrix4.identity());
|
// Matrix4.identity());
|
||||||
}
|
// }
|
||||||
}),
|
// }),
|
||||||
SubmenuButton(
|
// SubmenuButton(
|
||||||
child: Text("Set bone matrices to"),
|
// child: Text("Set bone matrices to"),
|
||||||
menuChildren: [
|
// menuChildren: [
|
||||||
MenuItemButton(
|
// MenuItemButton(
|
||||||
child: Text("Identity"),
|
// child: Text("Identity"),
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
await controller
|
// await controller
|
||||||
.removeAnimationComponent(entity);
|
// .removeAnimationComponent(entity);
|
||||||
for (var child in await controller
|
// for (var child in await controller
|
||||||
.getChildEntities(entity, true)) {
|
// .getChildEntities(entity, true)) {
|
||||||
print(
|
// print(
|
||||||
"Setting transform for ${await controller.getNameForEntity(child)}");
|
// "Setting transform for ${await controller.getNameForEntity(child)}");
|
||||||
await controller.setBoneTransform(
|
// await controller.setBoneTransform(
|
||||||
child,
|
// child,
|
||||||
boneNames.indexOf(name),
|
// boneNames.indexOf(name),
|
||||||
Matrix4.identity());
|
// Matrix4.identity());
|
||||||
}
|
// }
|
||||||
}),
|
// }),
|
||||||
SubmenuButton(
|
// SubmenuButton(
|
||||||
child: Text("Global"),
|
// child: Text("Global"),
|
||||||
menuChildren: ["90/X", "90/Y"]
|
// menuChildren: ["90/X", "90/Y"]
|
||||||
.map((rot) => MenuItemButton(
|
// .map((rot) => MenuItemButton(
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
var transform = rot == "90/X"
|
// var transform = rot == "90/X"
|
||||||
? Matrix4.rotationX(pi / 2)
|
// ? Matrix4.rotationX(pi / 2)
|
||||||
: Matrix4.rotationY(pi / 2);
|
// : Matrix4.rotationY(pi / 2);
|
||||||
await controller
|
// await controller
|
||||||
.removeAnimationComponent(
|
// .removeAnimationComponent(
|
||||||
entity);
|
// entity);
|
||||||
|
|
||||||
var index =
|
// var index =
|
||||||
boneNames.indexOf(name);
|
// boneNames.indexOf(name);
|
||||||
var childEntities =
|
// var childEntities =
|
||||||
await controller
|
// await controller
|
||||||
.getChildEntities(
|
// .getChildEntities(
|
||||||
entity, true);
|
// entity, true);
|
||||||
|
|
||||||
for (var child in childEntities) {
|
// for (var child in childEntities) {
|
||||||
print(
|
// print(
|
||||||
"Setting transform for ${await controller.getNameForEntity(child)} / bone $name (index $index)");
|
// "Setting transform for ${await controller.getNameForEntity(child)} / bone $name (index $index)");
|
||||||
await controller
|
// await controller
|
||||||
.setBoneTransform(child,
|
// .setBoneTransform(child,
|
||||||
index, transform);
|
// index, transform);
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
child: Text(rot)))
|
// child: Text(rot)))
|
||||||
.toList()),
|
// .toList()),
|
||||||
SubmenuButton(
|
// SubmenuButton(
|
||||||
child: Text("Bone"),
|
// child: Text("Bone"),
|
||||||
menuChildren: ["90/X", "90/Y", "90/Z"]
|
// menuChildren: ["90/X", "90/Y", "90/Z"]
|
||||||
.map((rot) => MenuItemButton(
|
// .map((rot) => MenuItemButton(
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
await controller
|
// await controller
|
||||||
.removeAnimationComponent(
|
// .removeAnimationComponent(
|
||||||
entity);
|
// entity);
|
||||||
var index =
|
// var index =
|
||||||
boneNames.indexOf(name);
|
// boneNames.indexOf(name);
|
||||||
var boneEntity = await controller
|
// var boneEntity = await controller
|
||||||
.getBone(entity, index);
|
// .getBone(entity, index);
|
||||||
var rotation = rot == "90/X"
|
// var rotation = rot == "90/X"
|
||||||
? Matrix4.rotationX(pi / 2)
|
// ? Matrix4.rotationX(pi / 2)
|
||||||
: rot == "90/Y"
|
// : rot == "90/Y"
|
||||||
? Matrix4.rotationY(
|
// ? Matrix4.rotationY(
|
||||||
pi / 2)
|
// pi / 2)
|
||||||
: Matrix4.rotationZ(
|
// : Matrix4.rotationZ(
|
||||||
pi / 2);
|
// pi / 2);
|
||||||
|
|
||||||
var inverseBindMatrix =
|
// var inverseBindMatrix =
|
||||||
await controller
|
// await controller
|
||||||
.getInverseBindMatrix(
|
// .getInverseBindMatrix(
|
||||||
entity, index);
|
// entity, index);
|
||||||
var bindMatrix =
|
// var bindMatrix =
|
||||||
Matrix4.identity();
|
// Matrix4.identity();
|
||||||
bindMatrix.copyInverse(
|
// bindMatrix.copyInverse(
|
||||||
inverseBindMatrix);
|
// inverseBindMatrix);
|
||||||
var childEntities =
|
// var childEntities =
|
||||||
await controller
|
// await controller
|
||||||
.getChildEntities(
|
// .getChildEntities(
|
||||||
entity, true);
|
// entity, true);
|
||||||
|
|
||||||
for (var child in childEntities) {
|
// for (var child in childEntities) {
|
||||||
var childGlobalTransform =
|
// var childGlobalTransform =
|
||||||
await controller
|
// await controller
|
||||||
.getWorldTransform(
|
// .getWorldTransform(
|
||||||
child);
|
// child);
|
||||||
var inverseGlobalTransform =
|
// var inverseGlobalTransform =
|
||||||
Matrix4.identity();
|
// Matrix4.identity();
|
||||||
inverseGlobalTransform
|
// inverseGlobalTransform
|
||||||
.copyInverse(
|
// .copyInverse(
|
||||||
childGlobalTransform);
|
// childGlobalTransform);
|
||||||
var globalBoneTransform =
|
// var globalBoneTransform =
|
||||||
childGlobalTransform *
|
// childGlobalTransform *
|
||||||
bindMatrix;
|
// bindMatrix;
|
||||||
|
|
||||||
var transform =
|
// var transform =
|
||||||
(inverseGlobalTransform *
|
// (inverseGlobalTransform *
|
||||||
(globalBoneTransform *
|
// (globalBoneTransform *
|
||||||
rotation)) *
|
// rotation)) *
|
||||||
inverseBindMatrix;
|
// inverseBindMatrix;
|
||||||
await controller
|
// await controller
|
||||||
.setBoneTransform(child,
|
// .setBoneTransform(child,
|
||||||
index, transform);
|
// index, transform);
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
child: Text(rot)))
|
// child: Text(rot)))
|
||||||
.toList()),
|
// .toList()),
|
||||||
]),
|
// ]),
|
||||||
MenuItemButton(
|
// MenuItemButton(
|
||||||
onPressed: () => _addBoneAnimation(name),
|
// onPressed: () => _addBoneAnimation(name),
|
||||||
child: Text(
|
// child: Text(
|
||||||
"Test animation (90 degreees around pose Y)")),
|
// "Test animation (90 degreees around pose Y)")),
|
||||||
]);
|
// ]);
|
||||||
})
|
// })
|
||||||
.cast<Widget>()
|
// .cast<Widget>()
|
||||||
.toList(),
|
// .toList(),
|
||||||
child: Text("Skeleton"));
|
// child: Text("Skeleton"));
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// MenuItemButton(
|
// // MenuItemButton(
|
||||||
// onPressed: () async {
|
// // onPressed: () async {
|
||||||
// var frames = <List<BoneAnimationFrame>>[];
|
// // var frames = <List<BoneAnimationFrame>>[];
|
||||||
// for (int i = 0; i < 60; i++) {
|
// // for (int i = 0; i < 60; i++) {
|
||||||
// var frame = <BoneAnimationFrame>[];
|
// // var frame = <BoneAnimationFrame>[];
|
||||||
// frame.add((
|
// // frame.add((
|
||||||
// rotation: Quaternion.axisAngle(
|
// // rotation: Quaternion.axisAngle(
|
||||||
// Vector3(0, 0, 1), (i / 60) * pi / 2),
|
// // Vector3(0, 0, 1), (i / 60) * pi / 2),
|
||||||
// translation: Vector3.zero()
|
// // translation: Vector3.zero()
|
||||||
// ));
|
// // ));
|
||||||
// frame.add((
|
// // frame.add((
|
||||||
// rotation: Quaternion.identity(),
|
// // rotation: Quaternion.identity(),
|
||||||
// translation: Vector3.zero()
|
// // translation: Vector3.zero()
|
||||||
// ));
|
// // ));
|
||||||
// frame.add((
|
// // frame.add((
|
||||||
// rotation: Quaternion.identity(),
|
// // rotation: Quaternion.identity(),
|
||||||
// translation: Vector3.zero()
|
// // translation: Vector3.zero()
|
||||||
// ));
|
// // ));
|
||||||
// frames.add(frame);
|
// // frames.add(frame);
|
||||||
// }
|
// // }
|
||||||
// for (int i = 0; i < 60; i++) {
|
// // for (int i = 0; i < 60; i++) {
|
||||||
// var frame = <BoneAnimationFrame>[];
|
// // var frame = <BoneAnimationFrame>[];
|
||||||
// frame.add((
|
// // frame.add((
|
||||||
// rotation: Quaternion.axisAngle(
|
// // rotation: Quaternion.axisAngle(
|
||||||
// Vector3(0, 0, 1), pi / 2),
|
// // Vector3(0, 0, 1), pi / 2),
|
||||||
// translation: Vector3.zero()
|
// // translation: Vector3.zero()
|
||||||
// ));
|
// // ));
|
||||||
// frame.add((
|
// // frame.add((
|
||||||
// rotation: Quaternion.axisAngle(
|
// // rotation: Quaternion.axisAngle(
|
||||||
// Vector3(1, 0, 0), i / 60 * (-pi / 2)),
|
// // Vector3(1, 0, 0), i / 60 * (-pi / 2)),
|
||||||
// translation: Vector3.zero()
|
// // translation: Vector3.zero()
|
||||||
// ));
|
// // ));
|
||||||
// frame.add((
|
// // frame.add((
|
||||||
// rotation: Quaternion.identity(),
|
// // rotation: Quaternion.identity(),
|
||||||
// translation: Vector3.zero()
|
// // translation: Vector3.zero()
|
||||||
// ));
|
// // ));
|
||||||
// frames.add(frame);
|
// // frames.add(frame);
|
||||||
// }
|
// // }
|
||||||
// for (int i = 0; i < 60; i++) {
|
// // for (int i = 0; i < 60; i++) {
|
||||||
// var frame = <BoneAnimationFrame>[];
|
// // var frame = <BoneAnimationFrame>[];
|
||||||
// frame.add((
|
// // frame.add((
|
||||||
// rotation: Quaternion.axisAngle(
|
// // rotation: Quaternion.axisAngle(
|
||||||
// Vector3(0, 0, 1), pi / 2),
|
// // Vector3(0, 0, 1), pi / 2),
|
||||||
// translation: Vector3.zero()
|
// // translation: Vector3.zero()
|
||||||
// ));
|
// // ));
|
||||||
// frame.add((
|
// // frame.add((
|
||||||
// rotation: Quaternion.axisAngle(
|
// // rotation: Quaternion.axisAngle(
|
||||||
// Vector3(1, 0, 0), (-pi / 2)),
|
// // Vector3(1, 0, 0), (-pi / 2)),
|
||||||
// translation: Vector3.zero()
|
// // translation: Vector3.zero()
|
||||||
// ));
|
// // ));
|
||||||
// frame.add((
|
// // frame.add((
|
||||||
// rotation: Quaternion.axisAngle(
|
// // rotation: Quaternion.axisAngle(
|
||||||
// Vector3(1, 0, 0), i / 60 * (pi / 2)),
|
// // Vector3(1, 0, 0), i / 60 * (pi / 2)),
|
||||||
// translation: Vector3.zero()
|
// // translation: Vector3.zero()
|
||||||
// ));
|
// // ));
|
||||||
// frames.add(frame);
|
// // frames.add(frame);
|
||||||
// }
|
// // }
|
||||||
|
|
||||||
// var animation = BoneAnimationData(
|
// // var animation = BoneAnimationData(
|
||||||
// ["Bone", "Bone.001", "Bone.002"], frames);
|
// // ["Bone", "Bone.001", "Bone.002"], frames);
|
||||||
// await controller.addAnimationComponent(entity);
|
// // await controller.addAnimationComponent(entity);
|
||||||
// await controller.addBoneAnimation(entity, animation);
|
// // await controller.addBoneAnimation(entity, animation);
|
||||||
// },
|
// // },
|
||||||
// child: Text("Test animation (pose space)")),
|
// // child: Text("Test animation (pose space)")),
|
||||||
@@ -174,6 +174,7 @@ class _ThermionTextureWidgetState extends State<ThermionTextureWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WidgetsBinding.instance.scheduleFrameCallback((d) async {
|
WidgetsBinding.instance.scheduleFrameCallback((d) async {
|
||||||
|
|
||||||
if (!mounted) {
|
if (!mounted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -241,7 +242,7 @@ class _ThermionTextureWidgetState extends State<ThermionTextureWidget> {
|
|||||||
_logger.info(
|
_logger.info(
|
||||||
"Resized texture to dimensions ${_texture!.width}x${_texture!.height} (pixel ratio : $dpr)");
|
"Resized texture to dimensions ${_texture!.width}x${_texture!.height} (pixel ratio : $dpr)");
|
||||||
|
|
||||||
await widget.viewer.view.setViewport(_texture!.width, _texture!.height);
|
await widget.viewer.setViewport(_texture!.width, _texture!.height);
|
||||||
|
|
||||||
await widget.onResize?.call(
|
await widget.onResize?.call(
|
||||||
Size(_texture!.width.toDouble(), _texture!.height.toDouble()),
|
Size(_texture!.width.toDouble(), _texture!.height.toDouble()),
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ public class ThermionFlutterTexture : NSObject, FlutterTexture {
|
|||||||
init(registry:FlutterTextureRegistry, width:Int64, height:Int64) {
|
init(registry:FlutterTextureRegistry, width:Int64, height:Int64) {
|
||||||
self.registry = registry
|
self.registry = registry
|
||||||
self.texture = ThermionTextureSwift(width:width, height: height, isDepth: false)
|
self.texture = ThermionTextureSwift(width:width, height: height, isDepth: false)
|
||||||
|
// if you need to debug
|
||||||
|
// self.texture.fillColor()
|
||||||
|
// let imageURL = URL(fileURLWithPath: "/Users/nickfisher/Documents/thermion/thermion_dart/test/assets/cube_texture_512x512.png")
|
||||||
|
// let success = self.texture.fillWithPNGImage(imageURL: imageURL)
|
||||||
super.init()
|
super.init()
|
||||||
self.flutterTextureId = registry.register(self)
|
self.flutterTextureId = registry.register(self)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../..//thermion_dart/native/macos/ThermionTexture.swift
|
||||||
@@ -18,7 +18,7 @@ import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dar
|
|||||||
///
|
///
|
||||||
class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
||||||
final channel = const MethodChannel("dev.thermion.flutter/event");
|
final channel = const MethodChannel("dev.thermion.flutter/event");
|
||||||
|
|
||||||
late final _logger = Logger(this.runtimeType.toString());
|
late final _logger = Logger(this.runtimeType.toString());
|
||||||
|
|
||||||
static SwapChain? _swapChain;
|
static SwapChain? _swapChain;
|
||||||
@@ -37,9 +37,10 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
|||||||
return File(path.replaceAll("file://", "")).readAsBytesSync();
|
return File(path.replaceAll("file://", "")).readAsBytesSync();
|
||||||
}
|
}
|
||||||
if (path.startsWith("asset://")) {
|
if (path.startsWith("asset://")) {
|
||||||
throw UnimplementedError();
|
path = path.replaceAll("asset://", "");
|
||||||
}
|
}
|
||||||
throw UnimplementedError();
|
var asset = await rootBundle.load(path);
|
||||||
|
return asset.buffer.asUint8List(asset.offsetInBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ThermionViewer> createViewer({ThermionFlutterOptions? options}) async {
|
Future<ThermionViewer> createViewer({ThermionFlutterOptions? options}) async {
|
||||||
@@ -92,18 +93,19 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
|||||||
throw Exception("Unsupported platform");
|
throw Exception("Unsupported platform");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final config = FFIFilamentConfig(
|
final config = FFIFilamentConfig(
|
||||||
backend: backend,
|
backend: backend,
|
||||||
resourceLoader: resourceLoader,
|
resourceLoader: loadAsset,
|
||||||
driver: driverPtr,
|
driver: driverPtr,
|
||||||
platform: nullptr,
|
platform: nullptr,
|
||||||
sharedContext: sharedContextPtr,
|
sharedContext: sharedContextPtr,
|
||||||
uberArchivePath: options?.uberarchivePath);
|
uberArchivePath: options?.uberarchivePath);
|
||||||
|
|
||||||
await FFIFilamentApp.create(config);
|
await FFIFilamentApp.create(config: config);
|
||||||
|
|
||||||
final viewer = ThermionViewerFFI(
|
final viewer = ThermionViewerFFI(
|
||||||
loadAsset: loadAsset,
|
loadAssetFromUri: loadAsset,
|
||||||
);
|
);
|
||||||
|
|
||||||
await viewer.initialized;
|
await viewer.initialized;
|
||||||
@@ -117,9 +119,10 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
|||||||
// avoid this
|
// avoid this
|
||||||
if (Platform.isMacOS || Platform.isIOS) {
|
if (Platform.isMacOS || Platform.isIOS) {
|
||||||
_swapChain = await FilamentApp.instance!.createHeadlessSwapChain(1, 1);
|
_swapChain = await FilamentApp.instance!.createHeadlessSwapChain(1, 1);
|
||||||
|
await FilamentApp.instance!.register(_swapChain!, viewer.view);
|
||||||
}
|
}
|
||||||
|
|
||||||
return viewer!;
|
return viewer;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<PlatformTextureDescriptor> createTextureDescriptor(
|
Future<PlatformTextureDescriptor> createTextureDescriptor(
|
||||||
@@ -157,27 +160,36 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
|||||||
|
|
||||||
_swapChain = await FilamentApp.instance!
|
_swapChain = await FilamentApp.instance!
|
||||||
.createHeadlessSwapChain(descriptor.width, descriptor.height);
|
.createHeadlessSwapChain(descriptor.width, descriptor.height);
|
||||||
|
await FilamentApp.instance!.register(_swapChain!, view);
|
||||||
} else if (Platform.isAndroid) {
|
} else if (Platform.isAndroid) {
|
||||||
if (_swapChain != null) {
|
if (_swapChain != null) {
|
||||||
await FilamentApp.instance!.setRenderable(view, false);
|
await FilamentApp.instance!.setRenderable(view, false);
|
||||||
await FilamentApp.instance!.destroySwapChain(_swapChain!);
|
await FilamentApp.instance!.destroySwapChain(_swapChain!);
|
||||||
}
|
}
|
||||||
_swapChain = await FilamentApp.instance!.createSwapChain(descriptor.windowHandle!);
|
_swapChain =
|
||||||
|
await FilamentApp.instance!.createSwapChain(descriptor.windowHandle!);
|
||||||
|
await FilamentApp.instance!.register(_swapChain!, view);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
final color = await FilamentApp.instance!.createTexture(
|
final color = await FilamentApp.instance!
|
||||||
descriptor.width, descriptor.height,
|
.createTexture(descriptor.width, descriptor.height,
|
||||||
importedTextureHandle: descriptor.hardwareId,
|
importedTextureHandle: descriptor.hardwareId,
|
||||||
flags: {
|
flags: {
|
||||||
TextureUsage.TEXTURE_USAGE_BLIT_DST,
|
// TextureUsage.TEXTURE_USAGE_BLIT_DST,
|
||||||
TextureUsage.TEXTURE_USAGE_COLOR_ATTACHMENT,
|
TextureUsage.TEXTURE_USAGE_COLOR_ATTACHMENT,
|
||||||
TextureUsage.TEXTURE_USAGE_SAMPLEABLE
|
TextureUsage.TEXTURE_USAGE_SAMPLEABLE
|
||||||
});
|
},
|
||||||
final depth =
|
textureFormat: TextureFormat.RGBA8,
|
||||||
await FilamentApp.instance!.createTexture(descriptor.width, descriptor.height, flags: {
|
textureSamplerType: TextureSamplerType.SAMPLER_2D);
|
||||||
TextureUsage.TEXTURE_USAGE_BLIT_DST,
|
final depth = await FilamentApp.instance!
|
||||||
TextureUsage.TEXTURE_USAGE_DEPTH_ATTACHMENT,
|
.createTexture(descriptor.width, descriptor.height,
|
||||||
TextureUsage.TEXTURE_USAGE_SAMPLEABLE
|
flags: {
|
||||||
});
|
// TextureUsage.TEXTURE_USAGE_BLIT_DST,
|
||||||
|
TextureUsage.TEXTURE_USAGE_DEPTH_ATTACHMENT,
|
||||||
|
TextureUsage.TEXTURE_USAGE_SAMPLEABLE,
|
||||||
|
},
|
||||||
|
textureFormat: TextureFormat.DEPTH32F,
|
||||||
|
textureSamplerType: TextureSamplerType.SAMPLER_2D);
|
||||||
|
|
||||||
var renderTarget = await FilamentApp.instance!.createRenderTarget(
|
var renderTarget = await FilamentApp.instance!.createRenderTarget(
|
||||||
descriptor.width, descriptor.height,
|
descriptor.width, descriptor.height,
|
||||||
@@ -185,7 +197,6 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
|||||||
|
|
||||||
await view.setRenderTarget(renderTarget);
|
await view.setRenderTarget(renderTarget);
|
||||||
}
|
}
|
||||||
await FilamentApp.instance!.register(_swapChain!, view);
|
|
||||||
|
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:thermion_dart/thermion_dart.dart' as t;
|
|
||||||
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
|
||||||
import 'package:thermion_dart/thermion_dart.dart';
|
import 'package:thermion_dart/thermion_dart.dart';
|
||||||
|
import 'package:thermion_dart/src/filament/filament.dart';
|
||||||
|
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
||||||
import 'thermion_flutter_texture.dart';
|
import 'thermion_flutter_texture.dart';
|
||||||
|
|
||||||
class ThermionFlutterOptions {
|
class ThermionFlutterOptions {
|
||||||
final String? uberarchivePath;
|
final String? uberarchivePath;
|
||||||
|
final Backend? backend;
|
||||||
|
|
||||||
ThermionFlutterOptions({this.uberarchivePath});
|
const ThermionFlutterOptions({this.uberarchivePath = null, this.backend = null});
|
||||||
const ThermionFlutterOptions.empty() : uberarchivePath = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
abstract class ThermionFlutterPlatform extends PlatformInterface {
|
abstract class ThermionFlutterPlatform extends PlatformInterface {
|
||||||
ThermionFlutterPlatform() : super(token: _token);
|
ThermionFlutterPlatform() : super(token: _token);
|
||||||
|
|
||||||
@@ -34,12 +32,13 @@ abstract class ThermionFlutterPlatform extends PlatformInterface {
|
|||||||
{covariant ThermionFlutterOptions? options});
|
{covariant ThermionFlutterOptions? options});
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Creates a raw rendering surface.
|
/// Creates a raw rendering surface.
|
||||||
///
|
///
|
||||||
/// This is internal; unless you are [thermion_*] package developer, don't
|
/// This is internal; unless you are [thermion_*] package developer, don't
|
||||||
/// call this yourself. May not be supported on all platforms.
|
/// call this yourself. May not be supported on all platforms.
|
||||||
///
|
///
|
||||||
Future<PlatformTextureDescriptor> createTextureDescriptor(int width, int height);
|
Future<PlatformTextureDescriptor> createTextureDescriptor(
|
||||||
|
int width, int height);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Destroys a raw rendering surface.
|
/// Destroys a raw rendering surface.
|
||||||
@@ -53,15 +52,14 @@ abstract class ThermionFlutterPlatform extends PlatformInterface {
|
|||||||
/// call this yourself. May not be supported on all platforms.
|
/// call this yourself. May not be supported on all platforms.
|
||||||
///
|
///
|
||||||
Future<PlatformTextureDescriptor?> createTextureAndBindToView(
|
Future<PlatformTextureDescriptor?> createTextureAndBindToView(
|
||||||
t.View view, int width, int height);
|
View view, int width, int height);
|
||||||
|
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
Future<PlatformTextureDescriptor?> resizeTexture(
|
Future<PlatformTextureDescriptor?> resizeTexture(
|
||||||
PlatformTextureDescriptor texture, t.View view, int width, int height);
|
PlatformTextureDescriptor texture, View view, int width, int height);
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class ThermionFlutterWebPlugin extends ThermionFlutterPlatform {
|
|||||||
(offsetTop * pixelRatio).ceil().toString();
|
(offsetTop * pixelRatio).ceil().toString();
|
||||||
|
|
||||||
_viewer!
|
_viewer!
|
||||||
.updateViewportAndCameraProjection(width.ceil(), height.ceil(), 1.0);
|
.setViewportAndCameraProjection(width.ceil(), height.ceil(), 1.0);
|
||||||
|
|
||||||
return PlatformTextureDescriptor(null, null, 0, 0, null);
|
return PlatformTextureDescriptor(null, null, 0, 0, null);
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ class ThermionFlutterWebPlugin extends ThermionFlutterPlatform {
|
|||||||
(offsetLeft * pixelRatio).ceil().toString();
|
(offsetLeft * pixelRatio).ceil().toString();
|
||||||
(canvas as HTMLElement).style.top =
|
(canvas as HTMLElement).style.top =
|
||||||
(offsetTop * pixelRatio).ceil().toString();
|
(offsetTop * pixelRatio).ceil().toString();
|
||||||
_viewer!.updateViewportAndCameraProjection(width, height, 1.0);
|
_viewer!.setViewportAndCameraProjection(width, height, 1.0);
|
||||||
return PlatformTextureDescriptor(null, null, 0, 0, null);
|
return PlatformTextureDescriptor(null, null, 0, 0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,5 @@ class ThermionFlutterWebOptions extends ThermionFlutterOptions {
|
|||||||
String? uberarchivePath})
|
String? uberarchivePath})
|
||||||
: super(uberarchivePath: uberarchivePath);
|
: super(uberarchivePath: uberarchivePath);
|
||||||
|
|
||||||
const ThermionFlutterWebOptions.empty(
|
|
||||||
{this.importCanvasAsWidget = false,
|
|
||||||
this.createCanvas = true,
|
|
||||||
String? uberarchivePath})
|
|
||||||
: super.empty();
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user