feat! js_interop improvements

This commit is contained in:
Nick Fisher
2025-05-07 17:06:38 +08:00
parent 63e2dcd0ca
commit 2f16908992
159 changed files with 12989 additions and 8377 deletions

View File

@@ -0,0 +1,3 @@
export 'src/ffi.dart'
if (dart.library.io) 'src/ffi.dart'
if (dart.library.js_interop) 'src/js_interop.dart';

View File

@@ -1,29 +1,89 @@
export 'thermion_dart_ffi.g.dart';
export 'dart:typed_data';
import 'dart:async';
import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
import 'dart:io';
import 'package:thermion_dart/thermion_dart.dart';
export 'package:ffi/ffi.dart';
export 'dart:ffi';
export 'thermion_dart.g.dart';
export 'dart:ffi' hide Size;
final allocator = calloc;
const FILAMENT_SINGLE_THREADED = false;
const FILAMENT_WASM = false;
bool get IS_WINDOWS => Platform.isWindows;
void using(Pointer ptr, Future Function(Pointer ptr) function) async {
await function.call(ptr);
allocator.free(ptr);
class NativeLibrary {
static void initBindings(String name) {
throw Exception();
}
}
Future<void> withVoidCallback2(Function() func) async {
final completer = Completer();
void Function() callback = () {
func.call();
completer.complete();
};
final nativeCallable = NativeCallable<Void Function()>.listener(callback);
RenderThread_addTask(nativeCallable.nativeFunction);
await completer.future;
nativeCallable.close();
typedef IntPtrList = Int64List;
typedef Float64 = Double;
typedef PointerClass<T extends NativeType> = Pointer<T>;
typedef VoidPointerClass = Pointer<Void>;
class CallbackHolder<T extends Function> {
final NativeCallable<T> nativeCallable;
Pointer<NativeFunction<T>> get pointer => nativeCallable.nativeFunction;
CallbackHolder(this.nativeCallable);
void dispose() {
nativeCallable.close();
}
}
Pointer<T> allocate<T extends NativeType>(int count) {
return calloc.allocate<T>(count * sizeOf<Pointer>());
}
void free(Pointer ptr) {
calloc.free(ptr);
}
Pointer stackSave() {
throw Exception();
}
void stackRestore(Pointer ptr) {
throw Exception();
}
class FinalizableUint8List implements Finalizable {
final Pointer name;
final Uint8List data;
FinalizableUint8List(this.name, this.data);
}
extension GPFBP on void Function(int, double, double, double) {
CallbackHolder<GizmoPickCallbackFunction> asCallback() {
var nativeCallable =
NativeCallable<GizmoPickCallbackFunction>.listener(this);
return CallbackHolder(nativeCallable);
}
}
CallbackHolder<PickCallbackFunction> makePickCallbackFunctionPointer(
DartPickCallbackFunction fn) {
final nc = NativeCallable<PickCallbackFunction>.listener(fn);
final cbh = CallbackHolder(nc);
return cbh;
}
extension VFB on void Function() {
CallbackHolder<Void Function()> asCallback() {
var nativeCallable = NativeCallable<Void Function()>.listener(this);
return CallbackHolder(nativeCallable);
}
}
extension PCBF on DartPickCallbackFunction {
CallbackHolder<PickCallbackFunction> asCallback() {
var nativeCallable = NativeCallable<PickCallbackFunction>.listener(this);
return CallbackHolder(nativeCallable);
}
}
Future<void> withVoidCallback(
@@ -75,7 +135,8 @@ Future<double> withFloatCallback(
void Function(double) callback = (double result) {
completer.complete(result);
};
final nativeCallable = NativeCallable<Void Function(Float)>.listener(callback);
final nativeCallable =
NativeCallable<Void Function(Float)>.listener(callback);
func.call(nativeCallable.nativeFunction);
await completer.future;
nativeCallable.close();
@@ -127,3 +188,15 @@ Future<String> withCharPtrCallback(
nativeCallable.close();
return completer.future;
}
extension FreeTypedData<T> on TypedData {
void free() {
// noop
}
}
extension DartBigIntExtension on int {
int get toBigInt {
return this;
}
}

View File

@@ -0,0 +1,408 @@
import 'dart:async';
export 'dart:typed_data';
export 'thermion_dart_js_interop.g.dart';
export 'dart:js_interop';
export 'dart:js_interop_unsafe';
import 'package:thermion_dart/src/bindings/src/js_interop.dart';
const FILAMENT_SINGLE_THREADED = true;
const FILAMENT_WASM = true;
const IS_WINDOWS = false;
extension type _NativeLibrary(JSObject _) implements JSObject {
static _NativeLibrary get instance =>
NativeLibrary.instance as _NativeLibrary;
external JSUint8Array _emscripten_make_uint8_buffer(
Pointer<Uint8> ptr, int length);
external JSUint16Array _emscripten_make_uint16_buffer(
Pointer<Uint16> ptr, int length);
external JSInt16Array _emscripten_make_int16_buffer(
Pointer<Int16> ptr, int length);
external JSInt32Array _emscripten_make_int32_buffer(
Pointer<Int32> ptr, int length);
external JSFloat32Array _emscripten_make_f32_buffer(
Pointer<Float32> ptr, int length);
external JSFloat64Array _emscripten_make_f64_buffer(
Pointer<Float64> ptr, int length);
external Pointer _emscripten_get_byte_offset(JSObject obj);
external int _emscripten_stack_get_free();
external void _execute_queue();
@JS('stackSave')
external Pointer<Void> stackSave();
@JS('stackRestore')
external void stackRestore(Pointer<Void> ptr);
}
extension FreeTypedData<T> on TypedData {
void free() {
final ptr = Pointer<Void>(this.offsetInBytes);
ptr.free();
}
}
Pointer<T> getPointer<T extends NativeType>(TypedData data, JSObject obj) {
late Pointer<T> ptr;
if (data.lengthInBytes < 32 * 1024) {
ptr = stackAlloc(data.lengthInBytes).cast<T>();
} else {
ptr = malloc<T>(data.lengthInBytes);
}
return ptr;
}
extension JSBackingBuffer on JSUint8Array {
@JS('buffer')
external JSObject buffer;
}
@JS('Uint8Array')
extension type Uint8ArrayWrapper._(JSObject _) implements JSObject {
external Uint8ArrayWrapper(JSObject buffer, int offset, int length);
}
@JS('Int8Array')
extension type Int8ArrayWrapper._(JSObject _) implements JSObject {
external Int8ArrayWrapper(JSObject buffer, int offset, int length);
}
@JS('Uint16Array')
extension type Uint16ArrayWrapper._(JSObject _) implements JSObject {
external Uint16ArrayWrapper(JSObject buffer, int offset, int length);
}
@JS('Int16Array')
extension type Int16ArrayWrapper._(JSObject _) implements JSObject {
external Int16ArrayWrapper(JSObject buffer, int offset, int length);
}
@JS('Uint32Array')
extension type Uint32ArrayWrapper._(JSObject _) implements JSObject {
external Uint32ArrayWrapper(JSObject buffer, int offset, int length);
}
@JS('Int32Array')
extension type Int32ArrayWrapper._(JSObject _) implements JSObject {
external Int32ArrayWrapper(JSObject buffer, int offset, int length);
}
@JS('Float32Array')
extension type Float32ArrayWrapper._(JSObject _) implements JSObject {
external Float32ArrayWrapper(JSObject buffer, int offset, int length);
}
@JS('Float64Array')
extension type Float64ArrayWrapper._(JSObject _) implements JSObject {
external Float64ArrayWrapper(JSObject buffer, int offset, int length);
}
extension Uint8ListExtension on Uint8List {
Pointer<Uint8> get address {
if (this.lengthInBytes == 0) {
return nullptr;
}
final ptr = getPointer<Uint8>(this, this.toJS);
final bar =
Uint8ArrayWrapper(NativeLibrary.instance.HEAPU8.buffer, ptr, length)
as JSUint8Array;
bar.toDart.setRange(0, length, this);
return ptr;
}
}
extension Float32ListExtension on Float32List {
Pointer<Float32> get address {
final ptr = getPointer<Float32>(this, this.toJS);
final bar =
Float32ArrayWrapper(NativeLibrary.instance.HEAPU8.buffer, ptr, length)
as JSFloat32Array;
bar.toDart.setRange(0, length, this);
return ptr;
}
}
extension Int16ListExtension on Int16List {
Pointer<Int16> get address {
if (this.lengthInBytes == 0) {
return nullptr;
}
final ptr = getPointer<Int16>(this, this.toJS);
final bar = Int16ArrayWrapper(NativeLibrary.instance.HEAPU8, ptr, length)
as JSInt16Array;
bar.toDart.setRange(0, length, this);
return ptr;
}
}
extension Uint16ListExtension on Uint16List {
Pointer<Uint16> get address {
final ptr = getPointer<Uint16>(this, this.toJS);
final bar =
Uint16ArrayWrapper(NativeLibrary.instance.HEAPU8.buffer, ptr, length)
as JSUint16Array;
bar.toDart.setRange(0, length, this);
return ptr;
}
}
extension UInt32ListExtension on Uint32List {
Pointer<Uint32> get address {
if (this.lengthInBytes == 0) {
return nullptr;
}
final ptr = getPointer<Uint32>(this, this.toJS);
final bar = Uint32ArrayWrapper(NativeLibrary.instance.HEAPU8, ptr, length)
as JSUint32Array;
bar.toDart.setRange(0, length, this);
return ptr;
}
}
extension Int32ListExtension on Int32List {
Pointer<Int32> get address {
if (this.lengthInBytes == 0) {
return nullptr;
}
final ptr = getPointer<Int32>(this, this.toJS);
final bar = Int32ArrayWrapper(NativeLibrary.instance.HEAPU8, ptr, length)
as JSInt32Array;
bar.toDart.setRange(0, length, this);
return ptr;
}
}
extension Int64ListExtension on Int64List {
Pointer<Float32> get address {
throw Exception();
}
static Int64List create(int length) {
throw Exception();
}
}
extension Float64ListExtension on Float64List {
Pointer<Float64> get address {
if (this.lengthInBytes == 0) {
return nullptr;
}
final ptr = getPointer<Float64>(this, this.toJS);
final bar =
Float64ArrayWrapper(NativeLibrary.instance.HEAPU8.buffer, ptr, length)
as JSFloat64Array;
bar.toDart.setRange(0, length, this);
return ptr;
}
// static Float64List create(int length) {
// final ptr = malloc(length * 8);
// final buffer = _NativeLibrary.instance._emscripten_make_f64_buffer(ptr.cast(), length).toDart;
// _allocated.add(buffer);
// return buffer;
// }
}
int sizeOf<T extends NativeType>() {
switch (T) {
case Float:
return 4;
default:
throw Exception();
}
}
typedef IntPtrList = Int32List;
typedef Utf8 = Char;
typedef Float = Float32;
typedef Double = Float64;
typedef Bool = bool;
class FinalizableUint8List {
final Pointer name;
final Uint8List data;
FinalizableUint8List(this.name, this.data);
}
class CallbackHolder<T extends Function> {
final Pointer<NativeFunction<T>> pointer;
CallbackHolder(this.pointer);
void dispose() {
pointer.dispose();
}
}
extension DPCF on DartPickCallbackFunction {
CallbackHolder<DartPickCallbackFunction> asCallback() {
final ptr = addFunction<DartPickCallbackFunction>(this.toJS, "viidddd");
final cbh = CallbackHolder(ptr);
return cbh;
}
}
extension GPFBP on void Function(int, double, double, double) {
CallbackHolder<GizmoPickCallbackFunction> asCallback() {
final ptr = addFunction<GizmoPickCallbackFunction>(this.toJS, "viddd");
return CallbackHolder(ptr);
}
}
extension VFCB on void Function() {
CallbackHolder<void Function()> asCallback() {
final ptr = addFunction<void Function()>(this.toJS, "v");
return CallbackHolder(ptr);
}
}
final _completers = <int, Completer>{};
void Function(int) _voidCallback = (int requestId) {
_completers[requestId]!.complete();
_completers.remove(requestId);
};
final _voidCallbackPtr = _voidCallback.addFunction();
Future<void> withVoidCallback(
Function(Pointer<NativeFunction<Void Function()>>) func) async {
final completer = Completer();
final requestId = _completers.length;
_completers[requestId] = completer;
final fn = () {
completer.complete();
};
final ptr = fn.addFunction();
func.call(ptr.cast());
while (!completer.isCompleted) {
_NativeLibrary.instance._execute_queue();
await Future.delayed(Duration(milliseconds: 1));
}
await completer.future;
}
Future<Pointer<T>> withPointerCallback<T extends NativeType>(
Function(Pointer<NativeFunction<Void Function(Pointer<T>)>>) func) async {
final completer = Completer<Pointer<T>>();
// ignore: prefer_function_declarations_over_variables
void Function(Pointer<T>) callback = (Pointer<T> ptr) {
completer.complete(ptr.cast<T>());
};
final onComplete_interopFnPtr = callback.addFunction();
func.call(onComplete_interopFnPtr.cast());
var ptr = await completer.future;
onComplete_interopFnPtr.dispose();
return ptr;
}
Future<bool> withBoolCallback(
Function(Pointer<NativeFunction<Void Function(Bool)>>) func) async {
final completer = Completer<bool>();
// ignore: prefer_function_declarations_over_variables
void Function(int) callback = (int result) {
completer.complete(result == 1);
};
final onComplete_interopFnPtr = callback.addFunction();
func.call(onComplete_interopFnPtr.cast());
await completer.future;
return completer.future;
}
Future<double> withFloatCallback(
void Function(Pointer<NativeFunction<void Function(double)>>) func) async {
final completer = Completer<double>();
// ignore: prefer_function_declarations_over_variables
void Function(double) callback = (double result) {
completer.complete(result);
};
var ptr = callback.addFunction();
func.call(ptr);
await completer.future;
return completer.future;
}
Future<int> withIntCallback(
Function(Pointer<NativeFunction<Void Function(Int32)>>) func) async {
final completer = Completer<int>();
// ignore: prefer_function_declarations_over_variables
void Function(int) callback = (int result) {
completer.complete(result);
};
// final nativeCallable =
// NativeCallable<Void Function(Int32)>.listener(callback);
// func.call(nativeCallable.nativeFunction);
await completer.future;
// nativeCallable.close();
return completer.future;
}
Pointer<T> allocate<T extends NativeType>(int count) {
switch (T) {
case PointerClass:
return malloc(count * 4);
default:
throw Exception(T.toString());
}
}
Future<int> withUInt32Callback(
Function(Pointer<NativeFunction<Void Function(int)>>) func) async {
final completer = Completer<int>();
// ignore: prefer_function_declarations_over_variables
void Function(int) callback = (int result) {
completer.complete(result);
};
// final nativeCallable =
// NativeCallable<Void Function(Uint32)>.listener(callback);
// func.call(nativeCallable.nativeFunction);
await completer.future;
// nativeCallable.close();
return completer.future;
}
Future<String> withCharPtrCallback(
Function(Pointer<NativeFunction<Void Function(Pointer<Char>)>>)
func) async {
final completer = Completer<String>();
// ignore: prefer_function_declarations_over_variables
// void Function(Pointer<Char>) callback = (Pointer<Char> result) {
// completer.complete(result.cast<Utf8>().toDartString());
// };
// final nativeCallable =
// NativeCallable<Void Function(Pointer<Char>)>.listener(callback);
// func.call(nativeCallable.nativeFunction);
await completer.future;
// nativeCallable.close();
return completer.future;
}
extension DartBigIntExtension on int {
BigInt get toBigInt {
return BigInt.from(this);
}
}
Pointer stackSave() => _NativeLibrary.instance.stackSave();
void stackRestore(Pointer ptr) =>
_NativeLibrary.instance.stackRestore(ptr.cast());
void getStackFree() {
print(_NativeLibrary.instance._emscripten_stack_get_free());
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
export 'src/filament_app.dart';
export 'src/engine.dart';
export 'src/layers.dart';
export 'src/light_options.dart';
export 'src/interface/filament_app.dart';
export 'src/interface/engine.dart';
export 'src/interface/layers.dart';
export 'src/interface/light_options.dart';

View File

@@ -1,32 +0,0 @@
import 'dart:typed_data';
import '../../viewer/viewer.dart';
class Geometry {
final Float32List vertices;
final Uint16List indices;
final Float32List normals;
final Float32List uvs;
final PrimitiveType primitiveType;
Geometry(
this.vertices,
List<int> indices, {
Float32List? normals,
Float32List? uvs,
this.primitiveType = PrimitiveType.TRIANGLES,
}) : indices = Uint16List.fromList(indices),
normals = normals ?? Float32List(0),
uvs = uvs ?? Float32List(0) {
assert(this.uvs.length == 0 || this.uvs.length == (vertices.length ~/ 3 * 2), "Expected either zero or ${indices.length * 2} UVs, got ${this.uvs.length}");
}
void scale(double factor) {
for (int i = 0; i < vertices.length; i++) {
vertices[i] = vertices[i] * factor;
}
}
bool get hasNormals => normals.isNotEmpty;
bool get hasUVs => uvs.isNotEmpty;
}

View File

@@ -2,11 +2,11 @@ import 'dart:typed_data';
import 'package:vector_math/vector_math_64.dart' as v64;
import 'package:animation_tools_dart/src/bone_animation_data.dart';
import 'package:animation_tools_dart/src/morph_animation_data.dart';
import 'package:thermion_dart/src/filament/src/layers.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_scene.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_texture.dart';
import 'package:thermion_dart/src/filament/src/interface/layers.dart';
import 'package:thermion_dart/src/bindings/bindings.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_asset.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_scene.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_texture.dart';
import 'package:thermion_dart/thermion_dart.dart';
class BackgroundImage extends ThermionAsset {
@@ -47,10 +47,12 @@ class BackgroundImage extends ThermionAsset {
var backgroundImage =
await viewer.createGeometry(GeometryHelper.fullscreenQuad());
await imageMaterialInstance.setParameterInt("showImage", 0);
var transform = Matrix4.identity();
await imageMaterialInstance.setParameterMat4(
"transform", Matrix4.identity());
"transform", transform);
backgroundImage.setMaterialInstanceAt(imageMaterialInstance);
await backgroundImage.setMaterialInstanceAt(imageMaterialInstance);
await scene.add(backgroundImage as FFIAsset);
return BackgroundImage._(
backgroundImage, scene, null, null, imageMaterialInstance);

View File

@@ -1,13 +1,8 @@
import 'dart:typed_data';
import 'package:animation_tools_dart/animation_tools_dart.dart';
import 'package:logging/logging.dart';
import 'package:thermion_dart/src/filament/src/layers.dart';
import 'package:thermion_dart/src/utils/src/matrix.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_material.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_filament_app.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_material.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart' as v64;
@@ -52,15 +47,31 @@ class FFIAsset extends ThermionAsset {
entity = SceneAsset_getEntity(asset);
}
Int32List? _childEntities;
///
///
///
@override
Future<List<ThermionEntity>> getChildEntities() async {
var count = SceneAsset_getChildEntityCount(asset);
var children = Int32List(count);
SceneAsset_getChildEntities(asset, children.address);
return children;
if (_childEntities == null) {
var count = SceneAsset_getChildEntityCount(asset);
var childEntities = Int32List(count);
late Pointer stackPtr;
if (FILAMENT_WASM) {
//stackPtr = stackSave();
}
if (count > 0) {
SceneAsset_getChildEntities(asset, childEntities.address);
}
_childEntities = Int32List.fromList(childEntities);
childEntities.free();
if (FILAMENT_WASM) {
//stackRestore(stackPtr);
}
}
return _childEntities!;
}
///
@@ -118,24 +129,32 @@ class FFIAsset extends ThermionAsset {
@override
Future<FFIAsset> createInstance(
{covariant List<MaterialInstance>? materialInstances = null}) async {
var created = await withPointerCallback<TSceneAsset>((cb) {
var ptrList = Int64List(materialInstances?.length ?? 0);
if (materialInstances != null && materialInstances.isNotEmpty) {
ptrList.setRange(
0,
materialInstances.length,
materialInstances
.cast<FFIMaterialInstance>()
.map((mi) => mi.pointer.address)
.toList());
}
var ptrList = IntPtrList(materialInstances?.length ?? 0);
late Pointer stackPtr;
if (FILAMENT_WASM) {
//stackPtr = stackSave();
}
if (materialInstances != null && materialInstances.isNotEmpty) {
ptrList.setRange(
0,
materialInstances.length,
materialInstances
.cast<FFIMaterialInstance>()
.map((mi) => mi.pointer.address)
.toList());
}
var created = await withPointerCallback<TSceneAsset>((cb) {
SceneAsset_createInstanceRenderThread(
asset,
ptrList.address.cast<Pointer<TMaterialInstance>>(),
materialInstances?.length ?? 0,
cb);
asset, ptrList.address.cast(), materialInstances?.length ?? 0, cb);
});
if (FILAMENT_WASM) {
//stackRestore(stackPtr);
ptrList.free();
}
if (created == FILAMENT_ASSET_ERROR) {
throw Exception("Failed to create instance");
}
@@ -251,6 +270,13 @@ class FFIAsset extends ThermionAsset {
///
ThermionAsset? boundingBoxAsset;
///
///
///
Future dispose() async {
_childEntities?.free();
}
///
///
///
@@ -326,14 +352,14 @@ class FFIAsset extends ThermionAsset {
vertices[23] = max[2]; // v7
// Indices for lines (24 indices for 12 lines)
final indices = [
final indices = Uint16List.fromList([
// Bottom face
0, 1, 1, 2, 2, 3, 3, 0,
// Top face
4, 5, 5, 6, 6, 7, 7, 4,
// Vertical edges
0, 4, 1, 5, 2, 6, 3, 7
];
]);
// Create unlit material instance for the wireframe
final materialInstancePtr =
@@ -366,6 +392,10 @@ class FFIAsset extends ThermionAsset {
TransformManager_setParent(Engine_getTransformManager(app.engine),
boundingBoxAsset!.entity, entity, false);
geometry.uvs?.free();
geometry.normals?.free();
geometry.vertices.free();
geometry.indices.free();
}
return boundingBoxAsset!;
}
@@ -461,7 +491,7 @@ class FFIAsset extends ThermionAsset {
if (weights.isEmpty) {
throw Exception("Weights must not be empty");
}
var weightsPtr = allocator<Float>(weights.length);
var weightsPtr = allocate<Float>(weights.length);
for (int i = 0; i < weights.length; i++) {
weightsPtr[i] = weights[i];
@@ -470,7 +500,7 @@ class FFIAsset extends ThermionAsset {
AnimationManager_setMorphTargetWeightsRenderThread(
animationManager, entity, weightsPtr, weights.length, cb);
});
allocator.free(weightsPtr);
free(weightsPtr);
if (!success) {
throw Exception(
@@ -489,13 +519,13 @@ class FFIAsset extends ThermionAsset {
var count = AnimationManager_getMorphTargetNameCount(
animationManager, asset, entity);
var outPtr = allocator<Char>(255);
var outPtr = allocate<Char>(255);
for (int i = 0; i < count; i++) {
AnimationManager_getMorphTargetName(
animationManager, asset, entity, outPtr, i);
names.add(outPtr.cast<Utf8>().toDartString());
}
allocator.free(outPtr);
free(outPtr);
return names.cast<String>();
}
@@ -505,9 +535,9 @@ class FFIAsset extends ThermionAsset {
Future<List<String>> getBoneNames({int skinIndex = 0}) async {
var count =
AnimationManager_getBoneCount(animationManager, asset, skinIndex);
var out = allocator<Pointer<Char>>(count);
var out = allocate<PointerClass<Char>>(count);
for (int i = 0; i < count; i++) {
out[i] = allocator<Char>(255);
out[i] = allocate<Char>(255);
}
AnimationManager_getBoneNames(animationManager, asset, out, skinIndex);
@@ -516,6 +546,10 @@ class FFIAsset extends ThermionAsset {
var namePtr = out[i];
names.add(namePtr.cast<Utf8>().toDartString());
}
for (int i = 0; i < count; i++) {
free(out[i]);
}
free(out);
return names;
}
@@ -527,12 +561,12 @@ class FFIAsset extends ThermionAsset {
var animationCount =
AnimationManager_getAnimationCount(animationManager, asset);
var names = <String>[];
var outPtr = allocator<Char>(255);
var outPtr = allocate<Char>(255);
for (int i = 0; i < animationCount; i++) {
AnimationManager_getAnimationName(animationManager, asset, outPtr, i);
names.add(outPtr.cast<Utf8>().toDartString());
}
allocator.free(outPtr);
free(outPtr);
return names;
}
@@ -636,6 +670,9 @@ class FFIAsset extends ThermionAsset {
animation.numFrames,
animation.frameLengthInMs);
frameData.data.free();
indices.free();
if (!result) {
throw Exception("Failed to set morph animation data for ${meshName}");
}
@@ -659,7 +696,7 @@ class FFIAsset extends ThermionAsset {
throw UnimplementedError("TODO - support skinIndex != 0 ");
}
var boneNames = await getBoneNames();
var restLocalTransformsRaw = allocator<Float>(boneNames.length * 16);
var restLocalTransformsRaw = allocate<Float>(boneNames.length * 16);
AnimationManager_getRestLocalTransforms(animationManager, asset, skinIndex,
restLocalTransformsRaw, boneNames.length);
@@ -671,11 +708,11 @@ class FFIAsset extends ThermionAsset {
}
restLocalTransforms.add(Matrix4.fromList(values));
}
allocator.free(restLocalTransformsRaw);
free(restLocalTransformsRaw);
var numFrames = animation.frameData.length;
var data = allocator<Float>(numFrames * 16);
var data = allocate<Float>(numFrames * 16);
var bones = await Future.wait(List<Future<ThermionEntity>>.generate(
boneNames.length, (i) => getBone(i)));
@@ -720,8 +757,7 @@ class FFIAsset extends ThermionAsset {
baseTransform * (worldInverse * frameTransform * world);
}
for (int j = 0; j < 16; j++) {
data.elementAt((frameNum * 16) + j).value =
newLocalTransform.storage[j];
data[(frameNum * 16) + j] = newLocalTransform.storage[j];
}
}
@@ -737,25 +773,41 @@ class FFIAsset extends ThermionAsset {
fadeInInSecs,
maxDelta);
}
allocator.free(data);
free(data);
}
///
///
///
Future<Matrix4> getLocalTransform({ThermionEntity? entity}) async {
late Pointer stackPtr;
if (FILAMENT_WASM) {
//stackPtr = stackSave();
}
entity ??= this.entity;
return double4x4ToMatrix4(
final transform = double4x4ToMatrix4(
TransformManager_getLocalTransform(app.transformManager, entity));
if (FILAMENT_WASM) {
//stackRestore(stackPtr);
}
return transform;
}
///
///
///
Future<Matrix4> getWorldTransform({ThermionEntity? entity}) async {
late Pointer stackPtr;
if (FILAMENT_WASM) {
//stackPtr = stackSave();
}
entity ??= this.entity;
return double4x4ToMatrix4(
var transform = double4x4ToMatrix4(
TransformManager_getWorldTransform(app.transformManager, entity));
if (FILAMENT_WASM) {
//stackRestore(stackPtr);
}
return transform;
}
///
@@ -786,10 +838,19 @@ class FFIAsset extends ThermionAsset {
///
Future<Matrix4> getInverseBindMatrix(int boneIndex,
{int skinIndex = 0}) async {
var matrix = Float32List(16);
late Pointer stackPtr;
if (FILAMENT_WASM) {
//stackPtr = stackSave();
}
var matrixIn = Float32List(16);
AnimationManager_getInverseBindMatrix(
animationManager, asset, skinIndex, boneIndex, matrix.address);
return Matrix4.fromList(matrix);
animationManager, asset, skinIndex, boneIndex, matrixIn.address);
var matrixOut = Matrix4.fromList(matrixIn);
if (FILAMENT_WASM) {
//stackRestore(stackPtr);
matrixIn.free();
}
return matrixOut;
}
///
@@ -813,7 +874,7 @@ class FFIAsset extends ThermionAsset {
if (skinIndex != 0) {
throw UnimplementedError("TOOD");
}
final ptr = allocator<Float>(16);
final ptr = allocate<Float>(16);
for (int i = 0; i < 16; i++) {
ptr[i] = transform.storage[i];
}
@@ -822,7 +883,7 @@ class FFIAsset extends ThermionAsset {
animationManager, entity, skinIndex, boneIndex, ptr, cb);
});
allocator.free(ptr);
free(ptr);
if (!result) {
throw Exception("Failed to set bone transform");
}

View File

@@ -1,12 +1,7 @@
import 'dart:ffi';
import 'dart:typed_data';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
import 'package:thermion_dart/src/filament/src/layers.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_filament_app.dart';
import 'package:thermion_dart/thermion_dart.dart';
import '../../../../utils/src/matrix.dart';
import '../../../utils/src/matrix.dart';
class FFICamera extends Camera {
final Pointer<TCamera> camera;
@@ -31,7 +26,15 @@ class FFICamera extends Camera {
///
///
Future<Matrix4> getModelMatrix() async {
return double4x4ToMatrix4(Camera_getModelMatrix(camera));
late Pointer stackPtr;
if (FILAMENT_WASM) {
stackPtr = stackSave();
}
final modelMatrix = double4x4ToMatrix4(Camera_getModelMatrix(camera));
if (FILAMENT_WASM) {
stackRestore(stackPtr);
}
return modelMatrix;
}
///
@@ -39,8 +42,16 @@ class FFICamera extends Camera {
///
@override
Future<Matrix4> getProjectionMatrix() async {
late Pointer stackPtr;
if (FILAMENT_WASM) {
//stackPtr = stackSave();
}
var matrixStruct = Camera_getProjectionMatrix(camera);
return double4x4ToMatrix4(matrixStruct);
final pMat = double4x4ToMatrix4(matrixStruct);
if (FILAMENT_WASM) {
//stackRestore(stackPtr);
}
return pMat;
}
///
@@ -48,8 +59,17 @@ class FFICamera extends Camera {
///
@override
Future<Matrix4> getCullingProjectionMatrix() async {
late Pointer stackPtr;
if (FILAMENT_WASM) {
//stackPtr = stackSave();
}
var matrixStruct = Camera_getCullingProjectionMatrix(camera);
return double4x4ToMatrix4(matrixStruct);
final cpMat = double4x4ToMatrix4(matrixStruct);
if (FILAMENT_WASM) {
//stackRestore(stackPtr);
}
return cpMat;
}
@override
@@ -81,7 +101,15 @@ class FFICamera extends Camera {
///
@override
Future setModelMatrix(Matrix4 matrix) async {
late Pointer stackPtr;
if (FILAMENT_WASM) {
stackPtr = stackSave();
}
Camera_setModelMatrix(camera, matrix.storage.address);
if (FILAMENT_WASM) {
stackRestore(stackPtr);
matrix.storage.free();
}
}
@override
@@ -122,6 +150,10 @@ class FFICamera extends Camera {
///
///
Future<Frustum> getFrustum() async {
late Pointer stackPtr;
if (FILAMENT_WASM) {
//stackPtr = stackSave();
}
var out = Float64List(24);
Camera_getFrustum(camera, out.address);
@@ -132,19 +164,31 @@ class FFICamera extends Camera {
frustum.plane3.setFromComponents(out[12], out[13], out[14], out[15]);
frustum.plane4.setFromComponents(out[16], out[17], out[18], out[19]);
frustum.plane5.setFromComponents(out[20], out[21], out[22], out[23]);
if (FILAMENT_WASM) {
//stackRestore(stackPtr);
out.free();
}
return frustum;
}
@override
Future<Matrix4> getViewMatrix() async {
return double4x4ToMatrix4(Camera_getViewMatrix(camera));
late Pointer stackPtr;
if (FILAMENT_WASM) {
//stackPtr = stackSave();
}
final matrix = double4x4ToMatrix4(Camera_getViewMatrix(camera));
if (FILAMENT_WASM) {
//stackRestore(stackPtr);
}
return matrix;
}
@override
Future setProjection(Projection projection, double left, double right,
double bottom, double top, double near, double far) async {
Camera_setProjection(camera, TProjection.values[projection.index], left,
right, bottom, top, near, far);
Camera_setProjection(
camera, projection.index, left, right, bottom, top, near, far);
}
Future destroy() async {

View File

@@ -1,26 +1,23 @@
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:thermion_dart/src/filament/src/scene.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_gizmo.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_material.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_render_target.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_scene.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_swapchain.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_texture.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_view.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';
import 'package:thermion_dart/src/filament/src/interface/scene.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_asset.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_gizmo.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_material.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_render_target.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_scene.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_swapchain.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_texture.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_view.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:logging/logging.dart';
import 'resource_loader.dart';
typedef RenderCallback = Pointer<NativeFunction<Void Function(Pointer<Void>)>>;
class FFIFilamentConfig extends FilamentConfig<RenderCallback, Pointer<Void>> {
FFIFilamentConfig(
{required super.resourceLoader,
{super.resourceLoader = null,
super.backend = Backend.DEFAULT,
super.platform = null,
super.sharedContext = null,
@@ -38,9 +35,9 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
final Pointer<TRenderTicker> renderTicker;
final Pointer<TNameComponentManager> nameComponentManager;
final Future<Uint8List> Function(String uri) resourceLoader;
late final Future<Uint8List> Function(String uri) resourceLoader;
late final _logger = Logger(this.runtimeType.toString());
static final _logger = Logger("FFIFilamentApp");
FFIFilamentApp(
this.engine,
@@ -52,7 +49,7 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
this.ubershaderMaterialProvider,
this.renderTicker,
this.nameComponentManager,
this.resourceLoader)
Future<Uint8List> Function(String uri)? resourceLoader)
: super(
engine: engine,
gltfAssetLoader: gltfAssetLoader,
@@ -60,15 +57,13 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
transformManager: transformManager,
lightManager: lightManager,
renderableManager: renderableManager,
ubershaderMaterialProvider: ubershaderMaterialProvider) {}
static Future<Uint8List> _defaultResourceLoader(String path) {
print("Loading file $path");
return File(path).readAsBytes();
ubershaderMaterialProvider: ubershaderMaterialProvider) {
this.resourceLoader = resourceLoader ?? defaultResourceLoader;
}
static Future create({FFIFilamentConfig? config}) async {
config ??= FFIFilamentConfig(resourceLoader: _defaultResourceLoader);
config ??= FFIFilamentConfig();
if (FilamentApp.instance != null) {
await FilamentApp.instance!.destroy();
}
@@ -78,7 +73,7 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
final engine = await withPointerCallback<TEngine>((cb) =>
Engine_createRenderThread(
TBackend.values[config!.backend.index].index,
config!.backend.value,
config.platform ?? nullptr,
config.sharedContext ?? nullptr,
config.stereoscopicEyeCount,
@@ -96,7 +91,7 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
final lightManager = Engine_getLightManager(engine);
final renderableManager = Engine_getRenderableManager(engine);
final renderTicker = RenderTicker_create(renderer);
final renderTicker = RenderTicker_create(engine, renderer);
RenderThread_setRenderTicker(renderTicker);
@@ -113,18 +108,25 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
renderTicker,
nameComponentManager,
config.resourceLoader);
_logger.info("Initialization complete");
}
final _swapChains = <FFISwapChain, List<FFIView>>{};
final viewsPtr = calloc<Pointer<TView>>(255);
late Pointer<PointerClass<TView>> viewsPtr =
allocate<PointerClass>(255).cast();
///
///
///
Future updateRenderOrder() async {
_logger.info("updateRenderOrder");
if (_swapChains.length == 0) {
_logger.warning("No swapchains, ignoring updateRenderOrder");
}
for (final swapChain in _swapChains.keys) {
final views = _swapChains[swapChain];
if (views == null) {
_logger.info("No views found for swapchain $swapChain");
continue;
}
@@ -137,6 +139,7 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
}
RenderTicker_setRenderable(
renderTicker, swapChain.swapChain, viewsPtr, numRenderable);
_logger.info("Updated render order, $numRenderable renderable views");
}
}
@@ -227,7 +230,7 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
RenderThread_destroy();
RenderTicker_destroy(renderTicker);
calloc.free(viewsPtr);
free(viewsPtr);
FilamentApp.instance = null;
for (final callback in _onDestroy) {
await callback.call();
@@ -242,6 +245,7 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
Future destroyAsset(covariant FFIAsset asset) async {
await withVoidCallback(
(cb) => SceneAsset_destroyRenderThread(asset.asset, cb));
await asset.dispose();
}
///
@@ -298,8 +302,8 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
levels,
bitmask,
importedTextureHandle ?? 0,
TTextureSamplerType.values[textureSamplerType.index],
TTextureFormat.values[textureFormat.index],
textureSamplerType.index,
textureFormat.index,
cb);
});
if (texturePtr == nullptr) {
@@ -324,24 +328,17 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
TextureCompareMode compareMode = TextureCompareMode.NONE,
TextureCompareFunc compareFunc = TextureCompareFunc.LESS_EQUAL}) async {
final samplerPtr = TextureSampler_create();
TextureSampler_setMinFilter(
samplerPtr, TSamplerMinFilter.values[minFilter.index]);
TextureSampler_setMagFilter(
samplerPtr, TSamplerMagFilter.values[magFilter.index]);
TextureSampler_setWrapModeS(
samplerPtr, TSamplerWrapMode.values[wrapS.index]);
TextureSampler_setWrapModeT(
samplerPtr, TSamplerWrapMode.values[wrapT.index]);
TextureSampler_setWrapModeR(
samplerPtr, TSamplerWrapMode.values[wrapR.index]);
TextureSampler_setMinFilter(samplerPtr, minFilter.index);
TextureSampler_setMagFilter(samplerPtr, magFilter.index);
TextureSampler_setWrapModeS(samplerPtr, wrapS.index);
TextureSampler_setWrapModeT(samplerPtr, wrapT.index);
TextureSampler_setWrapModeR(samplerPtr, wrapR.index);
if (anisotropy > 0) {
TextureSampler_setAnisotropy(samplerPtr, anisotropy);
}
TextureSampler_setCompareMode(
samplerPtr,
TSamplerCompareMode.values[compareMode.index],
TSamplerCompareFunc.values[compareFunc.index]);
samplerPtr, compareMode.index, compareFunc.index);
return FFITextureSampler(samplerPtr);
}
@@ -351,11 +348,20 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
///
Future<LinearImage> decodeImage(Uint8List data) async {
final name = "image";
late Pointer stackPtr;
if (FILAMENT_WASM) {
//stackPtr = stackSave();
}
var ptr = Image_decode(
data.address,
data.length,
name.toNativeUtf8().cast<Char>(),
);
if (FILAMENT_WASM) {
//stackRestore(stackPtr);
data.free();
}
if (ptr == nullptr) {
throw Exception("Failed to decode image");
}
@@ -374,9 +380,17 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
///
///
Future<Material> createMaterial(Uint8List data) async {
late Pointer stackPtr;
if (FILAMENT_WASM) {
//stackPtr = stackSave();
}
var ptr = await withPointerCallback<TMaterial>((cb) {
Engine_buildMaterialRenderThread(engine, data.address, data.length, cb);
});
if (FILAMENT_WASM) {
//stackRestore(stackPtr);
data.free();
}
return FFIMaterial(ptr, this);
}
@@ -420,6 +434,11 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
bool hasSheen = false,
bool hasIOR = false,
bool hasVolume = false}) async {
late Pointer stackPtr;
if (FILAMENT_WASM) {
//stackPtr = stackSave();
}
final key = Struct.create<TMaterialKey>();
key.doubleSided = doubleSided;
@@ -464,6 +483,10 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
MaterialProvider_createMaterialInstanceRenderThread(
ubershaderMaterialProvider, key.address, cb);
});
if (FILAMENT_WASM) {
//stackRestore(stackPtr);
}
if (materialInstance == nullptr) {
throw Exception("Failed to create material instance");
}
@@ -506,7 +529,8 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
final swapchain = _swapChains.keys.first;
final view = _swapChains[swapchain]!.first;
await withBoolCallback((cb) {
Renderer_beginFrameRenderThread(renderer, swapchain.swapChain, 0, cb);
Renderer_beginFrameRenderThread(
renderer, swapchain.swapChain, 0.toBigInt, cb);
});
await withVoidCallback((cb) {
Renderer_renderRenderThread(
@@ -515,10 +539,16 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
cb,
);
});
await withVoidCallback((cb) {
Renderer_endFrameRenderThread(renderer, cb);
});
if (FILAMENT_SINGLE_THREADED) {
await withVoidCallback((cb) => Engine_executeRenderThread(engine, cb));
} else {
await withVoidCallback(
(cb) => Engine_flushAndWaitRenderThread(engine, cb));
}
}
///
@@ -581,19 +611,8 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
for (final hook in _hooks) {
await hook.call();
}
final completer = Completer();
final callback = NativeCallable<Void Function()>.listener(() {
completer.complete(true);
});
RenderThread_requestFrame(callback.nativeFunction.cast());
try {
await completer.future.timeout(Duration(seconds: 1));
} catch (err) {
print("WARNING - render call timed out");
}
RenderThread_requestFrameAsync();
}
///
@@ -669,7 +688,6 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
PixelDataFormat pixelDataFormat = PixelDataFormat.RGBA,
PixelDataType pixelDataType = PixelDataType.FLOAT,
Future Function(View)? beforeRender}) async {
if (swapChain == null) {
if (_swapChains.isEmpty) {
throw Exception("No swapchains registered");
@@ -683,7 +701,8 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
await updateRenderOrder();
await withBoolCallback((cb) {
Renderer_beginFrameRenderThread(renderer, swapChain!.swapChain, 0, cb);
Renderer_beginFrameRenderThread(
renderer, swapChain!.swapChain, 0.toBigInt, cb);
});
final views = <FFIView>[];
if (view != null) {
@@ -720,6 +739,8 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
: view.renderTarget!.renderTarget,
// TPixelDataFormat.PIXELDATAFORMAT_RGBA,
// TPixelDataType.PIXELDATATYPE_UBYTE,
// TPixelDataFormat.fromValue(pixelDataFormat.value),
// TPixelDataType.fromValue(pixelDataType.value),
pixelDataFormat.value,
pixelDataType.value,
pixelBuffer.address,
@@ -734,7 +755,11 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
});
await withVoidCallback((cb) {
Engine_flushAndWaitRenderThead(engine, cb);
if (FILAMENT_SINGLE_THREADED) {
Engine_executeRenderThread(engine, cb);
} else {
Engine_flushAndWaitRenderThread(engine, cb);
}
});
return pixelBuffers;
}
@@ -759,70 +784,96 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
int layer = 0,
String? relativeResourcePath,
bool loadResourcesAsync = false}) async {
if (relativeResourcePath != null && !relativeResourcePath.endsWith("/")) {
relativeResourcePath = "$relativeResourcePath/";
}
var gltfResourceLoader = await withPointerCallback<TGltfResourceLoader>(
(cb) => GltfResourceLoader_createRenderThread(engine,
relativeResourcePath?.toNativeUtf8().cast<Char>() ?? nullptr, cb));
var filamentAsset = await withPointerCallback<TFilamentAsset>((cb) =>
GltfAssetLoader_loadRenderThread(engine, gltfAssetLoader, data.address,
data.length, numInstances, cb));
if (filamentAsset == nullptr) {
throw Exception("An error occurred loading the asset");
}
var resourceUris = FilamentAsset_getResourceUris(filamentAsset);
var resourceUriCount = FilamentAsset_getResourceUriCount(filamentAsset);
final resources = <FinalizableUint8List>[];
try {
late Pointer stackPtr;
if (FILAMENT_WASM) {
//stackPtr = stackSave();
}
for (int i = 0; i < resourceUriCount; i++) {
final resourceUriDart = resourceUris[i].cast<Utf8>().toDartString();
final resourceData = await resourceLoader(relativeResourcePath == null
? resourceUriDart
: "$relativeResourcePath/$resourceUriDart");
loadResourcesAsync = FILAMENT_SINGLE_THREADED;
resources.add(FinalizableUint8List(resourceUris[i], resourceData));
await withVoidCallback((cb) =>
GltfResourceLoader_addResourceDataRenderThread(
gltfResourceLoader,
resourceUris[i],
resourceData.address,
resourceData.lengthInBytes,
if (relativeResourcePath != null && !relativeResourcePath.endsWith("/")) {
relativeResourcePath = "$relativeResourcePath/";
}
var gltfResourceLoader = await withPointerCallback<TGltfResourceLoader>(
(cb) => GltfResourceLoader_createRenderThread(
engine,
relativeResourcePath?.toNativeUtf8().cast<Char>() ?? nullptr,
cb));
}
if (loadResourcesAsync) {
final result = await withBoolCallback((cb) => GltfResourceLoader_asyncBeginLoadRenderThread(gltfResourceLoader, filamentAsset, cb));
if(!result) {
throw Exception("Failed to begin async loading");
var filamentAsset = await withPointerCallback<TFilamentAsset>((cb) =>
GltfAssetLoader_loadRenderThread(engine, gltfAssetLoader,
data.address, data.length, numInstances, cb));
if (filamentAsset == nullptr) {
throw Exception("An error occurred loading the asset");
}
GltfResourceLoader_asyncUpdateLoadRenderThread(gltfResourceLoader);
var resourceUris = FilamentAsset_getResourceUris(filamentAsset);
var resourceUriCount = FilamentAsset_getResourceUriCount(filamentAsset);
for (int i = 0; i < resourceUriCount; i++) {
final resourceUriDart = resourceUris[i].cast<Utf8>().toDartString();
final resourceData = await resourceLoader(relativeResourcePath == null
? resourceUriDart
: "$relativeResourcePath/$resourceUriDart");
resources.add(FinalizableUint8List(resourceUris[i], resourceData));
await withVoidCallback((cb) =>
GltfResourceLoader_addResourceDataRenderThread(
gltfResourceLoader,
resourceUris[i],
resourceData.address,
resourceData.lengthInBytes,
cb));
}
if (loadResourcesAsync) {
final result = await withBoolCallback((cb) =>
GltfResourceLoader_asyncBeginLoadRenderThread(
gltfResourceLoader, filamentAsset, cb));
if (!result) {
throw Exception("Failed to begin async loading");
}
var progress = await withFloatCallback((cb) => GltfResourceLoader_asyncGetLoadProgressRenderThread(gltfResourceLoader, cb));
while(progress < 1.0) {
GltfResourceLoader_asyncUpdateLoadRenderThread(gltfResourceLoader);
progress = await withFloatCallback((cb) => GltfResourceLoader_asyncGetLoadProgressRenderThread(gltfResourceLoader, cb));
var progress = await withFloatCallback((cb) =>
GltfResourceLoader_asyncGetLoadProgressRenderThread(
gltfResourceLoader, cb));
while (progress < 1.0) {
GltfResourceLoader_asyncUpdateLoadRenderThread(gltfResourceLoader);
progress = await withFloatCallback((cb) =>
GltfResourceLoader_asyncGetLoadProgressRenderThread(
gltfResourceLoader, cb));
}
} else {
final result = await withBoolCallback((cb) =>
GltfResourceLoader_loadResourcesRenderThread(
gltfResourceLoader, filamentAsset, cb));
if (!result) {
throw Exception("Failed to load resources");
}
}
} else {
final result = await withBoolCallback((cb) =>
GltfResourceLoader_loadResourcesRenderThread(
gltfResourceLoader, filamentAsset, cb));
if (!result) {
throw Exception("Failed to load resources");
final asset = await withPointerCallback<TSceneAsset>((cb) =>
SceneAsset_createFromFilamentAssetRenderThread(engine,
gltfAssetLoader, nameComponentManager, filamentAsset, cb));
await withVoidCallback((cb) => GltfResourceLoader_destroyRenderThread(
engine, gltfResourceLoader, cb));
return FFIAsset(asset, this, animationManager.cast<TAnimationManager>());
} finally {
if (FILAMENT_WASM) {
//stackRestore(stackPtr);
data.free();
for (final resource in resources) {
resource.data.free();
}
}
}
final asset = await withPointerCallback<TSceneAsset>((cb) =>
SceneAsset_createFromFilamentAssetRenderThread(
engine, gltfAssetLoader, nameComponentManager, filamentAsset, cb));
await withVoidCallback((cb) =>
GltfResourceLoader_destroyRenderThread(engine, gltfResourceLoader, cb));
return FFIAsset(asset, this, animationManager.cast<TAnimationManager>());
}
Future destroyView(covariant FFIView view) async {
@@ -833,12 +884,13 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
}
await withVoidCallback(
(cb) => Engine_destroyViewRenderThread(engine, view.view, cb));
for(final swapchain in _swapChains.keys) {
if(_swapChains[swapchain]!.contains(view)) {
for (final swapchain in _swapChains.keys) {
if (_swapChains[swapchain]!.contains(view)) {
_swapChains[swapchain]!.remove(view);
continue;
}
}
await view.dispose();
}
Future destroyScene(covariant FFIScene scene) async {
@@ -847,9 +899,8 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
}
Future<Pointer<TColorGrading>> createColorGrading(ToneMapper mapper) async {
return withPointerCallback<TColorGrading>((cb) =>
ColorGrading_createRenderThread(
engine, TToneMapping.values[mapper.index], cb));
return withPointerCallback<TColorGrading>(
(cb) => ColorGrading_createRenderThread(engine, mapper.index, cb));
}
FFIMaterial? _gizmoMaterial;
@@ -859,6 +910,11 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
///
Future<GizmoAsset> createGizmo(covariant FFIView view,
Pointer animationManager, GizmoType gizmoType) async {
late Pointer stackPtr;
if (FILAMENT_WASM) {
//stackPtr = stackSave();
}
if (_gizmoMaterial == null) {
final materialPtr = await withPointerCallback<TMaterial>((cb) {
Material_createGizmoMaterialRenderThread(engine, cb);
@@ -867,7 +923,8 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
}
var gltfResourceLoader = await withPointerCallback<TGltfResourceLoader>(
(cb) => GltfResourceLoader_createRenderThread(engine, nullptr, cb));
(cb) =>
GltfResourceLoader_createRenderThread(engine, nullptr.cast(), cb));
final gizmo = await withPointerCallback<TGizmo>((cb) {
Gizmo_createRenderThread(
@@ -877,7 +934,7 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
nameComponentManager,
view.view,
_gizmoMaterial!.pointer,
TGizmoType.values[gizmoType.index],
gizmoType.index,
cb);
});
if (gizmo == nullptr) {
@@ -889,11 +946,17 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
SceneAsset_getChildEntities(
gizmo.cast<TSceneAsset>(), gizmoEntities.address);
return FFIGizmo(gizmo.cast<TSceneAsset>(), this,
final gizmoAsset = FFIGizmo(gizmo.cast<TSceneAsset>(), this,
animationManager.cast<TAnimationManager>(),
view: view,
entities: gizmoEntities.toSet()
..add(SceneAsset_getEntity(gizmo.cast<TSceneAsset>())));
if (FILAMENT_WASM) {
//stackRestore(stackPtr);
gizmoEntities.free();
}
return gizmoAsset;
}
///
@@ -905,19 +968,24 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
{List<MaterialInstance>? materialInstances,
bool keepData = false,
bool addToScene = true}) async {
var assetPtr = await withPointerCallback<TSceneAsset>((callback) {
var ptrList = Int64List(materialInstances?.length ?? 0);
if (materialInstances != null && materialInstances.isNotEmpty) {
ptrList.setRange(
0,
materialInstances.length,
materialInstances
.cast<FFIMaterialInstance>()
.map((mi) => mi.pointer.address)
.toList());
}
late Pointer stackPtr;
if (FILAMENT_WASM) {
//stackPtr = stackSave();
}
return SceneAsset_createGeometryRenderThread(
final ptrList = IntPtrList(materialInstances?.length ?? 0);
if (materialInstances != null) {
ptrList.setRange(
0,
materialInstances.length,
materialInstances
.cast<FFIMaterialInstance>()
.map((mi) => mi.pointer.address)
.toList());
}
var assetPtr = await withPointerCallback<TSceneAsset>((callback) {
var ptr = SceneAsset_createGeometryRenderThread(
engine,
geometry.vertices.address,
geometry.vertices.length,
@@ -928,10 +996,20 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
geometry.indices.address,
geometry.indices.length,
geometry.primitiveType.index,
ptrList.address.cast<Pointer<TMaterialInstance>>(),
ptrList.length,
ptrList.address.cast(),
ptrList.length ?? 0,
callback);
return ptr;
});
if (FILAMENT_WASM) {
//stackRestore(stackPtr);
ptrList?.free();
geometry.vertices.free();
geometry.normals?.free();
geometry.uvs?.free();
}
if (assetPtr == nullptr) {
throw Exception("Failed to create geometry");
}
@@ -943,11 +1021,16 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
///
///
Future flush() async {
await withVoidCallback((cb) => Engine_flushAndWaitRenderThead(engine, cb));
if (FILAMENT_SINGLE_THREADED) {
await withVoidCallback((cb) => Engine_executeRenderThread(engine, cb));
} else {
await withVoidCallback(
(cb) => Engine_flushAndWaitRenderThread(engine, cb));
}
}
final _onDestroy = <Future Function()>[];
///
///
///
@@ -955,10 +1038,3 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
_onDestroy.add(callback);
}
}
class FinalizableUint8List implements Finalizable {
final Pointer name;
final Uint8List data;
FinalizableUint8List(this.name, this.data);
}

View File

@@ -1,29 +1,19 @@
import 'dart:async';
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart';
import 'package:thermion_dart/src/bindings/bindings.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_asset.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'ffi_view.dart';
class FFIGizmo extends FFIAsset implements GizmoAsset {
final Set<ThermionEntity> entities;
late NativeCallable<GizmoPickCallbackFunction> _nativeCallback;
late final CallbackHolder<GizmoPickCallbackFunction> _callbackHolder;
void Function(GizmoPickResultType axis, Vector3 coords)? _callback;
late FFIView view;
void _onPickResult(int resultType, double x, double y, double z) {
_callback?.call(GizmoPickResultType.values[resultType], Vector3(x, y, z));
}
bool isNonPickable(ThermionEntity entity) {
throw UnimplementedError();
// return SceneManager_isGridEntity(sceneManager, entity);
}
bool isGizmoEntity(ThermionEntity entity) => entities.contains(entity);
FFIGizmo(
super.asset,
super.app,
@@ -32,10 +22,38 @@ class FFIGizmo extends FFIAsset implements GizmoAsset {
required this.view,
required this.entities,
}) {
_nativeCallback =
NativeCallable<GizmoPickCallbackFunction>.listener(_onPickResult);
_callbackHolder = _onPickResult.asCallback();
}
///
///
///
Future dispose() async {
_callbackHolder.dispose();
}
void _onPickResult(int resultType, double x, double y, double z) {
final type = switch(resultType) {
TGizmoPickResultType.AxisX => GizmoPickResultType.AxisX,
TGizmoPickResultType.AxisY => GizmoPickResultType.AxisY,
TGizmoPickResultType.AxisZ => GizmoPickResultType.AxisZ,
TGizmoPickResultType.None => GizmoPickResultType.None,
TGizmoPickResultType.Parent => GizmoPickResultType.Parent,
_ => throw UnsupportedError(resultType.toString())
};
_callback?.call(type, Vector3(x, y, z));
}
bool isNonPickable(ThermionEntity entity) {
throw UnimplementedError();
// return SceneManager_isGridEntity(sceneManager, entity);
}
bool isGizmoEntity(ThermionEntity entity) => entities.contains(entity);
@override
Future removeStencilHighlight() async {
throw Exception("Not supported for gizmo");
@@ -58,13 +76,18 @@ class FFIGizmo extends FFIAsset implements GizmoAsset {
final viewport = await view.getViewport();
y = viewport.height - y;
Gizmo_pick(asset.cast<TGizmo>(), x, y, _nativeCallback.nativeFunction);
Gizmo_pick(asset.cast<TGizmo>(), x, y, _callbackHolder.pointer);
}
@override
Future highlight(Axis axis) async {
Gizmo_unhighlight(asset.cast<TGizmo>());
Gizmo_highlight(asset.cast<TGizmo>(), TGizmoAxis.values[axis.index]);
final tAxis = switch(axis) {
Axis.X => TGizmoAxis.X,
Axis.Y => TGizmoAxis.Y,
Axis.Z => TGizmoAxis.Z
};
Gizmo_highlight(asset.cast<TGizmo>(), tAxis);
}
@override

View File

@@ -1,9 +1,6 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_texture.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_filament_app.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_texture.dart';
import 'package:thermion_dart/thermion_dart.dart';
class FFIMaterial extends Material {
@@ -73,7 +70,11 @@ class FFIMaterialInstance extends MaterialInstance {
@override
Future setParameterFloat3Array(String name, List<Vector3> array) async {
final ptr = name.toNativeUtf8(allocator: calloc).cast<Char>();
late Pointer stackPtr;
if (FILAMENT_WASM) {
//stackPtr = stackSave();
}
final ptr = name.toNativeUtf8().cast<Char>();
final data = Float64List(array.length * 3);
int i = 0;
for (final item in array) {
@@ -84,7 +85,11 @@ class FFIMaterialInstance extends MaterialInstance {
}
MaterialInstance_setParameterFloat3Array(
pointer, ptr, data.address, array.length * 3);
calloc.free(ptr);
if (FILAMENT_WASM) {
//stackRestore(stackPtr);
data.free();
}
}
@override
@@ -102,45 +107,38 @@ class FFIMaterialInstance extends MaterialInstance {
@override
Future setDepthFunc(SamplerCompareFunction depthFunc) async {
MaterialInstance_setDepthFunc(
pointer, TSamplerCompareFunc.values[depthFunc.index]);
MaterialInstance_setDepthFunc(pointer, depthFunc.index);
}
@override
Future setStencilCompareFunction(SamplerCompareFunction func,
[StencilFace face = StencilFace.FRONT_AND_BACK]) async {
MaterialInstance_setStencilCompareFunction(
pointer,
TSamplerCompareFunc.values[func.index],
TStencilFace.values[face.index]);
MaterialInstance_setStencilCompareFunction(pointer, func.index, face.index);
}
@override
Future setStencilOpDepthFail(StencilOperation op,
[StencilFace face = StencilFace.FRONT_AND_BACK]) async {
MaterialInstance_setStencilOpDepthFail(pointer,
TStencilOperation.values[op.index], TStencilFace.values[face.index]);
MaterialInstance_setStencilOpDepthFail(pointer, op.index, face.index);
}
@override
Future setStencilOpDepthStencilPass(StencilOperation op,
[StencilFace face = StencilFace.FRONT_AND_BACK]) async {
MaterialInstance_setStencilOpDepthStencilPass(pointer,
TStencilOperation.values[op.index], TStencilFace.values[face.index]);
MaterialInstance_setStencilOpDepthStencilPass(
pointer, op.index, face.index);
}
@override
Future setStencilOpStencilFail(StencilOperation op,
[StencilFace face = StencilFace.FRONT_AND_BACK]) async {
MaterialInstance_setStencilOpStencilFail(pointer,
TStencilOperation.values[op.index], TStencilFace.values[face.index]);
MaterialInstance_setStencilOpStencilFail(pointer, op.index, face.index);
}
@override
Future setStencilReferenceValue(int value,
[StencilFace face = StencilFace.FRONT_AND_BACK]) async {
MaterialInstance_setStencilReferenceValue(
pointer, value, TStencilFace.values[face.index]);
MaterialInstance_setStencilReferenceValue(pointer, value, face.index);
}
@override
@@ -150,8 +148,8 @@ class FFIMaterialInstance extends MaterialInstance {
@override
Future setCullingMode(CullingMode cullingMode) async {
MaterialInstance_setCullingMode(
pointer, TCullingMode.values[cullingMode.index]);
MaterialInstance_setCullingMode(pointer, cullingMode.index);
;
}
@override
@@ -177,8 +175,7 @@ class FFIMaterialInstance extends MaterialInstance {
@override
Future setTransparencyMode(TransparencyMode mode) async {
MaterialInstance_setTransparencyMode(
pointer, TTransparencyMode.values[mode.index]);
MaterialInstance_setTransparencyMode(pointer, mode.index);
}
@override
@@ -196,13 +193,7 @@ class FFIMaterialInstance extends MaterialInstance {
@override
Future setParameterMat4(String name, Matrix4 matrix) async {
final completer = Completer();
final func = () {
MaterialInstance_setParameterMat4(pointer, name.toNativeUtf8().cast<Char>(), matrix.storage.address);
completer.complete();
};
final nativeCallable = NativeCallable<Void Function()>.listener(func);
RenderThread_addTask(nativeCallable.nativeFunction);
await completer.future;
MaterialInstance_setParameterMat4(
pointer, name.toNativeUtf8().cast<Char>(), matrix.storage.address);
}
}

View File

@@ -1,6 +1,6 @@
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_texture.dart';
import 'package:thermion_dart/src/bindings/bindings.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_filament_app.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_texture.dart';
import 'package:thermion_dart/thermion_dart.dart';
class FFIRenderTarget extends RenderTarget {

View File

@@ -1,6 +1,6 @@
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart';
import 'package:thermion_dart/src/filament/src/scene.dart';
import 'callbacks.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_asset.dart';
import 'package:thermion_dart/src/filament/src/interface/scene.dart';
import 'package:thermion_dart/src/bindings/bindings.dart';
class FFIScene extends Scene {
final Pointer<TScene> scene;

View File

@@ -1,4 +1,4 @@
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
import 'package:thermion_dart/src/bindings/bindings.dart';
import 'package:thermion_dart/thermion_dart.dart';
class FFISwapChain extends SwapChain {

View File

@@ -1,6 +1,6 @@
import 'dart:typed_data';
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
import 'package:thermion_dart/src/bindings/bindings.dart';
import 'package:thermion_dart/thermion_dart.dart';
class FFITexture extends Texture {
@@ -11,13 +11,15 @@ class FFITexture extends Texture {
Future<void> setLinearImage(covariant FFILinearImage image,
PixelDataFormat format, PixelDataType type) async {
final tPixelDataFormat = format.value;
final tPixelDataType = type.value;
final result = await withBoolCallback((cb) {
Texture_loadImageRenderThread(
_engine,
pointer,
image.pointer,
format.index,
type.index,
tPixelDataFormat,
tPixelDataType,
cb);
});
@@ -114,28 +116,29 @@ class FFITexture extends Texture {
Uint8List buffer,
PixelDataFormat format,
PixelDataType type) async {
final success = await withBoolCallback((cb) {
Texture_setImageWithDepthRenderThread(
_engine,
pointer,
level,
buffer.address,
buffer.lengthInBytes,
0,
0,
zOffset,
width,
height,
channels,
depth,
format.index,
type.index,
cb);
});
throw UnimplementedError();
// final success = await withBoolCallback((cb) {
// Texture_setImageWithDepthRenderThread(
// _engine,
// pointer,
// level,
// buffer.address,
// buffer.lengthInBytes,
// 0,
// 0,
// zOffset,
// width,
// height,
// channels,
// depth,
// format.index,
// type.index,
// cb);
// });
if (!success) {
throw Exception("Failed to set image");
}
// if (!success) {
// throw Exception("Failed to set image");
// }
}
@override
@@ -171,16 +174,12 @@ class FFILinearImage extends LinearImage {
[String name = "image"]) async {
final namePtr = name.toNativeUtf8();
try {
final imagePtr = await withPointerCallback<TLinearImage>((cb) {
Image_decodeRenderThread(
data.address, data.lengthInBytes, namePtr.cast(), cb);
});
final imagePtr = await withPointerCallback<TLinearImage>((cb) {
Image_decodeRenderThread(
data.address, data.lengthInBytes, namePtr.cast(), cb);
});
return FFILinearImage(imagePtr);
} finally {
calloc.free(namePtr);
}
return FFILinearImage(imagePtr);
}
Future<void> destroy() async {

View File

@@ -2,12 +2,12 @@ import 'dart:async';
import 'dart:math';
import 'package:logging/logging.dart';
import 'package:thermion_dart/src/filament/src/scene.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_render_target.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_scene.dart';
import 'package:thermion_dart/src/filament/src/interface/scene.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_filament_app.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_render_target.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_scene.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'callbacks.dart';
import 'ffi_camera.dart';
class FFIView extends View {
@@ -24,14 +24,24 @@ class FFIView extends View {
FFIRenderTarget? renderTarget;
late CallbackHolder<PickCallbackFunction> _onPickResultHolder;
FFIView(this.view, this.app) {
final renderTargetPtr = View_getRenderTarget(view);
if (renderTargetPtr != nullptr) {
renderTarget = FFIRenderTarget(renderTargetPtr, app);
}
_onPickResultCallable =
NativeCallable<PickCallbackFunction>.listener(_onPickResult);
_onPickResultHolder =
_onPickResult.asCallback();
}
///
///
///
Future dispose() async {
_onPickResultHolder.dispose();
}
///
@@ -76,7 +86,7 @@ class FFIView extends View {
@override
Future<Viewport> getViewport() async {
TViewport vp = View_getViewport(view);
final vp = View_getViewport(view);
return Viewport(vp.left, vp.bottom, vp.width, vp.height);
}
@@ -141,7 +151,7 @@ class FFIView extends View {
@override
Future setRenderQuality(QualityLevel quality) async {
View_setRenderQuality(view, TQualityLevel.values[quality.index]);
View_setRenderQuality(view, quality.index);
}
Future setScene(covariant FFIScene scene) async {
@@ -154,7 +164,7 @@ class FFIView extends View {
}
Future setBlendMode(BlendMode blendMode) async {
View_setBlendMode(view, TBlendMode.values[blendMode.index]);
View_setBlendMode(view, blendMode.index);
}
@override
@@ -168,7 +178,6 @@ class FFIView extends View {
static int kMaxPickRequests = 1024;
final _pickRequests = List<({void Function(PickResult) handler, int x, int y})?>.generate(kMaxPickRequests, (idx) => null);
late NativeCallable<PickCallbackFunction> _onPickResultCallable;
///
///
@@ -184,7 +193,7 @@ class FFIView extends View {
y = viewport.height - y;
View_pick(
view, pickRequestId, x, y, _onPickResultCallable.nativeFunction);
view, pickRequestId, x, y, _onPickResultHolder.pointer);
}

View File

@@ -1,6 +1,6 @@
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart';
import 'package:thermion_dart/src/bindings/bindings.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_asset.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_filament_app.dart';
class GridOverlay extends FFIAsset {

View File

@@ -0,0 +1,3 @@
export 'resource_loader_io.dart'
if (dart.library.io) 'resource_loader_io.dart'
if (dart.library.js_interop) 'resource_loader_js.dart';

View File

@@ -0,0 +1,8 @@
import 'dart:io';
import 'package:thermion_dart/thermion_dart.dart';
Future<Uint8List> defaultResourceLoader(String path) {
print("Loading file $path");
return File(path).readAsBytes();
}

View File

@@ -0,0 +1,11 @@
import 'package:thermion_dart/thermion_dart.dart';
import 'package:http/http.dart' as http;
Future<Uint8List> defaultResourceLoader(String path) async {
if(path.startsWith("file://")) {
throw Exception("Unsupported URI : $path");
}
final response = await http.get(Uri.parse(path));
return response.bodyBytes;
}

View File

@@ -1,7 +1,7 @@
library;
import 'package:animation_tools_dart/animation_tools_dart.dart';
import 'package:thermion_dart/src/filament/src/layers.dart';
import 'package:thermion_dart/src/filament/src/interface/layers.dart';
import 'package:thermion_dart/thermion_dart.dart';
export 'geometry.dart';

View File

@@ -1,4 +1,4 @@
import 'package:thermion_dart/src/filament/src/layers.dart';
import 'package:thermion_dart/src/filament/src/interface/layers.dart';
import 'package:thermion_dart/thermion_dart.dart';
enum Projection { Perspective, Orthographic }

View File

@@ -1,15 +1,11 @@
import 'dart:typed_data';
import 'package:thermion_dart/src/filament/src/engine.dart';
import 'package:thermion_dart/src/filament/src/scene.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_material.dart';
import 'package:thermion_dart/src/filament/src/interface/scene.dart';
import 'package:thermion_dart/thermion_dart.dart';
class FilamentConfig<T, U> {
final Backend backend;
final T? renderCallback;
final U? renderCallbackOwner;
final Future<Uint8List> Function(String) resourceLoader;
Future<Uint8List> Function(String)? resourceLoader;
final U? platform;
final U? sharedContext;
final String? uberArchivePath;

View File

@@ -0,0 +1,37 @@
import 'dart:typed_data';
import 'package:thermion_dart/src/bindings/bindings.dart';
import '../../../viewer/viewer.dart';
class Geometry {
final Float32List vertices;
final Uint16List indices;
late final Float32List normals;
late final Float32List uvs;
final PrimitiveType primitiveType;
Geometry(
this.vertices,
this.indices, {
Float32List? normals,
Float32List? uvs,
this.primitiveType = PrimitiveType.TRIANGLES,
}) {
this.uvs = uvs ?? Float32List(0);
this.normals = normals ?? Float32List(0);
if (this.uvs.length != 0 && this.uvs.length != (vertices.length ~/ 3 * 2)) {
throw Exception(
"Expected either ${indices.length * 2} UVs, got ${this.uvs!.length}");
}
}
void scale(double factor) {
for (int i = 0; i < vertices.length; i++) {
vertices[i] = vertices[i] * factor;
}
}
bool get hasNormals => normals?.isNotEmpty == true;
bool get hasUVs => uvs?.isNotEmpty == true;
}

View File

@@ -25,4 +25,7 @@ abstract class GizmoAsset extends ThermionAsset {
Future unhighlight();
bool isNonPickable(ThermionEntity entity);
bool isGizmoEntity(ThermionEntity entity);
Future dispose();
}

View File

@@ -1,5 +1,3 @@
import 'dart:typed_data';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart';

View File

@@ -1,4 +1,4 @@
import '../../viewer/viewer.dart';
import '../../../viewer/viewer.dart';
/// The result of a picking operation (see [ThermionViewer.pick] for more details).
/// [x] and [y] refer to the original screen coordinates used to call [pick]; this should

View File

@@ -1,5 +1,5 @@
import 'package:thermion_dart/src/filament/src/layers.dart';
import 'package:thermion_dart/src/filament/src/scene.dart';
import 'package:thermion_dart/src/filament/src/interface/layers.dart';
import 'package:thermion_dart/src/filament/src/interface/scene.dart';
import 'package:thermion_dart/thermion_dart.dart';
enum BlendMode {
@@ -57,7 +57,10 @@ abstract class View {
Future pick(int x, int y, void Function(PickResult) resultHandler);
///
///
///
Future dispose();
}

View File

@@ -78,12 +78,8 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
final camera = await view.getCamera();
final viewport = await view.getViewport();
var viewMatrix = await camera.getViewMatrix();
var modelMatrix = await camera.getModelMatrix();
var projectionMatrix = await camera.getProjectionMatrix();
var inverseProjectionMatrix = projectionMatrix.clone()..invert();
Vector3 currentPosition = modelMatrix.getTranslation();
Vector3 forward = modelMatrix.forward;

View File

@@ -1,30 +0,0 @@
import 'dart:ffi';
import 'dart:io';
import 'package:ffi/ffi.dart';
import '../../viewer/src/ffi/src/thermion_dart.g.dart';
class DartResourceLoader {
static final _assets = <int, Pointer>{};
static void loadResource(Pointer<Char> uri, Pointer<ResourceBuffer> out) {
try {
var data = File(uri.cast<Utf8>().toDartString().replaceAll("file://", ""))
.readAsBytesSync();
var ptr = calloc<Uint8>(data.lengthInBytes);
ptr.asTypedList(data.lengthInBytes).setRange(0, data.lengthInBytes, data);
out.ref.data = ptr.cast<Void>();
out.ref.size = data.lengthInBytes;
out.ref.id = _assets.length;
_assets[out.ref.id] = ptr;
} catch (err) {
print(err);
out.ref.size = -1;
}
}
static void freeResource(ResourceBuffer rb) {
calloc.free(_assets[rb.id]!);
}
}

View File

@@ -1,13 +1,11 @@
import 'dart:math';
import 'dart:typed_data';
import 'dart:math' ;
import '../../../thermion_dart.dart';
class GeometryHelper {
static Geometry fullscreenQuad() {
final vertices =
Float32List.fromList([-1.0, -1.0, 1.0, 3.0, -1.0, 1.0, -1.0, 3.0, 1.0]);
final indices = [0, 1, 2];
final vertices = Float32List.fromList([-1.0, -1.0, 1.0, 3.0, -1.0, 1.0, -1.0, 3.0, 1.0]);
final indices = Uint16List.fromList([0, 1, 2]);
return Geometry(vertices, indices);
}
@@ -56,7 +54,7 @@ class GeometryHelper {
Float32List? _normals = normals ? Float32List.fromList(normalsList) : null;
Float32List? _uvs = uvs ? Float32List.fromList(uvsList) : null;
return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
return Geometry(vertices, Uint16List.fromList(indices), normals: _normals, uvs: _uvs);
}
static Geometry cube(
@@ -236,7 +234,7 @@ class GeometryHelper {
20, 21, 22, 20, 22, 23 // 4,0,3,4,3,7
];
return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
return Geometry(vertices, Uint16List.fromList(indices), normals: _normals, uvs: _uvs);
}
// Helper function to flip the Y coordinate of UV coordinates (y = 1.0 - y)
@@ -316,7 +314,7 @@ class GeometryHelper {
Float32List? _normals = normals ? Float32List.fromList(normalsList) : null;
Float32List? _uvs = uvs ? Float32List.fromList(uvsList) : null;
return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
return Geometry(vertices, Uint16List.fromList(indices), normals: _normals, uvs: _uvs);
}
static Geometry conic(
@@ -440,7 +438,7 @@ class GeometryHelper {
Float32List? _normals = normals ? Float32List.fromList(normalsList) : null;
Float32List? _uvs = uvs ? Float32List.fromList(uvsList) : null;
return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
return Geometry(vertices, Uint16List.fromList(indices), normals: _normals, uvs: _uvs);
}
static Geometry plane(
@@ -493,14 +491,14 @@ class GeometryHelper {
])
: null;
List<int> indices = [
final indices = Uint16List.fromList([
0,
1,
2,
0,
2,
3,
];
]);
return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
}
@@ -640,7 +638,7 @@ class GeometryHelper {
Float32List? _normals = normals ? Float32List.fromList(normalsList) : null;
Float32List? _uvs = uvs ? Float32List.fromList(uvsList) : null;
return Geometry(vertices, indices,
return Geometry(vertices, Uint16List.fromList(indices),
normals: _normals, uvs: _uvs, primitiveType: PrimitiveType.LINES);
}
@@ -794,7 +792,7 @@ class GeometryHelper {
])
: null;
final indices = [
final indices = Uint16List.fromList([
// Front face
0, 1, 2, 0, 2, 3,
// Back face
@@ -807,7 +805,7 @@ class GeometryHelper {
16, 17, 18, 16, 18, 19,
// Left face
20, 21, 22, 20, 22, 23
];
]);
return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
}
@@ -865,7 +863,7 @@ class GeometryHelper {
: null;
// Define indices for triangular faces
List<int> indices = [
Uint16List indices = Uint16List.fromList([
// Bottom face (rectangle)
0, 1, 2,
0, 2, 3,
@@ -883,7 +881,7 @@ class GeometryHelper {
// Back rectangular face
2, 3, 4,
2, 4, 5,
];
]);
return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
}

View File

@@ -1,6 +1,7 @@
import 'dart:math';
import 'dart:typed_data';
import 'package:image/image.dart' as img;
import 'package:thermion_dart/thermion_dart.dart';
Future<Uint8List> pixelBufferToBmp(Uint8List pixelBuffer, int width, int height,
{bool hasAlpha = true, bool isFloat = false}) async {

View File

@@ -1,9 +1,8 @@
// Helper function to convert double4x4 to Matrix4
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
import 'package:thermion_dart/src/bindings/bindings.dart';
import 'package:vector_math/vector_math_64.dart';
import 'dart:ffi';
Matrix4 double4x4ToMatrix4(double4x4 mat) {
return Matrix4.fromList([
mat.col1[0],
mat.col1[1],
@@ -26,12 +25,16 @@ Matrix4 double4x4ToMatrix4(double4x4 mat) {
double4x4 matrix4ToDouble4x4(Matrix4 mat) {
final out = Struct.create<double4x4>();
Array<Float64> col1 =out.col1;
Array<Float64> col2 = out.col2;
Array<Float64> col3 =out.col3;
Array<Float64> col4= out.col4;
for (int i = 0; i < 4; i++) {
out.col1[i] = mat.storage[i];
out.col2[i] = mat.storage[i + 4];
out.col3[i] = mat.storage[i + 8];
out.col4[i] = mat.storage[i + 12];
col1[i] = mat.storage[i];
col2[i] = mat.storage[i + 4];
col3[i] = mat.storage[i + 8];
col4[i] = mat.storage[i + 12];
}
return out;

View File

@@ -1,9 +1,9 @@
import 'dart:io';
import 'dart:typed_data';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_render_target.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_scene.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_view.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_render_target.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_scene.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_view.dart';
import 'package:thermion_dart/thermion_dart.dart';
class TextureProjection {

View File

@@ -1,20 +1,15 @@
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:thermion_dart/src/filament/src/light_options.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/background_image.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_scene.dart';
import 'package:thermion_dart/src/filament/src/layers.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/grid_overlay.dart';
import 'package:thermion_dart/src/filament/src/implementation/background_image.dart';
import '../../../../filament/src/implementation/ffi_asset.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_filament_app.dart';
import '../../../../filament/src/implementation/ffi_scene.dart';
import '../../../../filament/src/implementation/grid_overlay.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart' as v64;
import 'package:logging/logging.dart';
import 'callbacks.dart';
import 'ffi_camera.dart';
import 'ffi_view.dart';
import '../../../../filament/src/implementation/ffi_camera.dart';
import '../../../../filament/src/implementation/ffi_view.dart';
const FILAMENT_ASSET_ERROR = 0;
@@ -50,6 +45,7 @@ class ThermionViewerFFI extends ThermionViewer {
///
///
Future setViewport(int width, int height) async {
print("Setting viewport to ${width}x${height}");
await view.setViewport(width.toInt(), height.toInt());
for (final camera in _cameras) {
@@ -121,8 +117,15 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future render() async {
await withVoidCallback(
(cb) => RenderTicker_renderRenderThread(app.renderTicker, 0, cb));
await withVoidCallback((cb) =>
RenderTicker_renderRenderThread(app.renderTicker, 0.toBigInt, cb));
if (FILAMENT_SINGLE_THREADED) {
await withVoidCallback(
(cb) => Engine_executeRenderThread(app.engine, cb));
} else {
await withVoidCallback(
(cb) => Engine_flushAndWaitRenderThread(app.engine, cb));
}
}
double _msPerFrame = 1000.0 / 60.0;
@@ -248,11 +251,21 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future loadIbl(String lightingPath, {double intensity = 30000}) async {
late Pointer stackPtr;
if (FILAMENT_WASM) {
//stackPtr = stackSave();
}
var data = await loadAssetFromUri(lightingPath);
indirectLight = await withPointerCallback<TIndirectLight>((cb) {
Engine_buildIndirectLightRenderThread(
app.engine, data.address, data.length, intensity, cb, nullptr);
});
if (FILAMENT_WASM) {
//stackRestore(stackPtr);
data.free();
}
data.free();
Scene_setIndirectLight(scene.scene, indirectLight!);
}
@@ -264,7 +277,18 @@ class ThermionViewerFFI extends ThermionViewer {
if (indirectLight == null) {
throw Exception("No IBL loaded");
}
late Pointer stackPtr;
if (FILAMENT_WASM) {
//stackPtr = stackSave();
}
IndirectLight_setRotation(indirectLight!, rotationMatrix.storage.address);
if (FILAMENT_WASM) {
//stackRestore(stackPtr);
rotationMatrix.storage.free();
}
}
///
@@ -303,8 +327,8 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future<ThermionEntity> addDirectLight(DirectLight directLight) async {
var entity = LightManager_createLight(app.engine, app.lightManager,
TLightType.values[directLight.type.index]);
var entity = LightManager_createLight(
app.engine, app.lightManager, directLight.type.index);
if (entity == FILAMENT_ASSET_ERROR) {
throw Exception("Failed to add light to scene");
}
@@ -446,8 +470,6 @@ class ThermionViewerFFI extends ThermionViewer {
@override
Future setPostProcessing(bool enabled) async {
View_setPostProcessing(view.view, enabled);
await withVoidCallback(
(cb) => Engine_flushAndWaitRenderThead(app.engine, cb));
}
///
@@ -478,10 +500,9 @@ class ThermionViewerFFI extends ThermionViewer {
///
@override
Future setAntiAliasing(bool msaa, bool fxaa, bool taa) async {
if (Platform.isWindows && msaa) {
if (!FILAMENT_SINGLE_THREADED && IS_WINDOWS && msaa) {
throw Exception("MSAA is not currently supported on Windows");
}
View_setAntiAliasing(view.view, msaa, fxaa, taa);
}

View File

@@ -1,7 +1,7 @@
import 'package:thermion_dart/src/filament/src/layers.dart';
import 'package:thermion_dart/src/filament/src/light_options.dart';
import 'package:thermion_dart/src/filament/src/interface/layers.dart';
import 'package:thermion_dart/src/filament/src/interface/light_options.dart';
import '../../filament/src/shared_types.dart';
import '../../filament/src/interface/shared_types.dart';
import 'dart:typed_data';
import 'package:vector_math/vector_math_64.dart';
import 'dart:async';

View File

@@ -1,317 +0,0 @@
import 'dart:typed_data';
import 'package:thermion_dart/src/filament/src/light_options.dart';
import 'package:thermion_dart/thermion_dart.dart';
class ThermionViewerStub extends ThermionViewer {
@override
Future<ThermionEntity> addDirectLight(DirectLight light) {
// TODO: implement addDirectLight
throw UnimplementedError();
}
@override
Future addToScene(covariant ThermionAsset asset) {
// TODO: implement addToScene
throw UnimplementedError();
}
@override
Future clearBackgroundImage({bool destroy = false}) {
// TODO: implement clearBackgroundImage
throw UnimplementedError();
}
@override
Future<Camera> createCamera() {
// TODO: implement createCamera
throw UnimplementedError();
}
@override
Future<ThermionAsset> createGeometry(Geometry geometry,
{List<MaterialInstance>? materialInstances,
bool keepData = false,
bool addToScene = true}) {
// TODO: implement createGeometry
throw UnimplementedError();
}
@override
Future destroyAsset(ThermionAsset asset) {
// TODO: implement destroyAsset
throw UnimplementedError();
}
@override
Future destroyAssets() {
// TODO: implement destroyAssets
throw UnimplementedError();
}
@override
Future destroyCamera(covariant Camera camera) {
// TODO: implement destroyCamera
throw UnimplementedError();
}
@override
Future destroyLights() {
// TODO: implement destroyLights
throw UnimplementedError();
}
@override
Future dispose() {
// TODO: implement dispose
throw UnimplementedError();
}
@override
Future<Camera> getActiveCamera() {
// TODO: implement getActiveCamera
throw UnimplementedError();
}
@override
int getCameraCount() {
// TODO: implement getCameraCount
throw UnimplementedError();
}
@override
Future<GizmoAsset> getGizmo(GizmoType type) {
// TODO: implement getGizmo
throw UnimplementedError();
}
@override
Future<Aabb3> getRenderableBoundingBox(ThermionEntity entity) {
// TODO: implement getRenderableBoundingBox
throw UnimplementedError();
}
@override
Future<Aabb2> getViewportBoundingBox(ThermionEntity entity) {
// TODO: implement getViewportBoundingBox
throw UnimplementedError();
}
@override
// TODO: implement initialized
Future<bool> get initialized => throw UnimplementedError();
@override
Future<ThermionAsset> loadGltf(String path,
{bool addToScene = true,
int numInstances = 1,
bool keepData = false,
String? relativeResourcePath}) {
// TODO: implement loadGltf
throw UnimplementedError();
}
@override
Future loadIbl(String lightingPath, {double intensity = 30000}) {
// TODO: implement loadIbl
throw UnimplementedError();
}
@override
Future loadSkybox(String skyboxPath) {
// TODO: implement loadSkybox
throw UnimplementedError();
}
@override
// TODO: implement msPerFrame
double get msPerFrame => throw UnimplementedError();
@override
void onDispose(Future Function() callback) {
// TODO: implement onDispose
}
@override
Future pick(int x, int y, void Function(PickResult p1) resultHandler) {
// TODO: implement pick
throw UnimplementedError();
}
@override
Future removeFromScene(covariant ThermionAsset asset) {
// TODO: implement removeFromScene
throw UnimplementedError();
}
@override
Future removeIbl() {
// TODO: implement removeIbl
throw UnimplementedError();
}
@override
Future removeLight(ThermionEntity light) {
// TODO: implement removeLight
throw UnimplementedError();
}
@override
Future removeSkybox() {
// TODO: implement removeSkybox
throw UnimplementedError();
}
@override
Future render() {
// TODO: implement render
throw UnimplementedError();
}
@override
// TODO: implement rendering
bool get rendering => throw UnimplementedError();
@override
Future rotateIbl(Matrix3 rotation) {
// TODO: implement rotateIbl
throw UnimplementedError();
}
@override
Future setActiveCamera(covariant Camera camera) {
// TODO: implement setActiveCamera
throw UnimplementedError();
}
@override
Future setAntiAliasing(bool msaa, bool fxaa, bool taa) {
// TODO: implement setAntiAliasing
throw UnimplementedError();
}
@override
Future setBackgroundColor(double r, double g, double b, double alpha) {
// TODO: implement setBackgroundColor
throw UnimplementedError();
}
@override
Future setBackgroundImage(String path, {bool fillHeight = false}) {
// TODO: implement setBackgroundImage
throw UnimplementedError();
}
@override
Future setBackgroundImagePosition(double x, double y, {bool clamp = false}) {
// TODO: implement setBackgroundImagePosition
throw UnimplementedError();
}
@override
Future setBloom(bool enabled, double strength) {
// TODO: implement setBloom
throw UnimplementedError();
}
@override
Future setFrameRate(int framerate) {
// TODO: implement setFrameRate
throw UnimplementedError();
}
@override
Future setGridOverlayVisibility(bool visible) {
// TODO: implement setGridOverlayVisibility
throw UnimplementedError();
}
@override
Future setLightDirection(ThermionEntity lightEntity, Vector3 direction) {
// TODO: implement setLightDirection
throw UnimplementedError();
}
@override
Future setLightPosition(
ThermionEntity lightEntity, double x, double y, double z) {
// TODO: implement setLightPosition
throw UnimplementedError();
}
@override
Future setPostProcessing(bool enabled) {
// TODO: implement setPostProcessing
throw UnimplementedError();
}
@override
Future setPriority(ThermionEntity entityId, int priority) {
// TODO: implement setPriority
throw UnimplementedError();
}
@override
Future setRendering(bool render) {
// TODO: implement setRendering
throw UnimplementedError();
}
@override
Future setShadowType(ShadowType shadowType) {
// TODO: implement setShadowType
throw UnimplementedError();
}
@override
Future setShadowsEnabled(bool enabled) {
// TODO: implement setShadowsEnabled
throw UnimplementedError();
}
@override
Future setSoftShadowOptions(double penumbraScale, double penumbraRatioScale) {
// TODO: implement setSoftShadowOptions
throw UnimplementedError();
}
@override
Future setToneMapping(ToneMapper mapper) {
// TODO: implement setToneMapping
throw UnimplementedError();
}
@override
Future setViewFrustumCulling(bool enabled) {
// TODO: implement setViewFrustumCulling
throw UnimplementedError();
}
@override
Future setViewport(int width, int height) {
// TODO: implement setViewport
throw UnimplementedError();
}
@override
// TODO: implement view
View get view => throw UnimplementedError();
@override
Future setLayerVisibility(VisibilityLayers layer, bool visible) {
// TODO: implement setLayerVisibility
throw UnimplementedError();
}
@override
Future<ThermionAsset> loadGltfFromBuffer(Uint8List data,
{
String? relativeResourcePath,
int numInstances = 1,
bool keepData = false,
int priority = 4,
int layer = 0,
bool loadResourcesAsync = false,
}) {
throw UnimplementedError();
}
}

View File

@@ -3,7 +3,7 @@ library thermion_flutter_js;
import 'dart:js_interop';
import '../../../../filament/src/shared_types.dart';
import '../../../../filament/src/interface/shared_types.dart';
///
/// An extension type on [JSObject] that represents a

View File

@@ -1,77 +0,0 @@
import 'package:vector_math/vector_math_64.dart';
import '../../thermion_viewer_base.dart';
class ThermionWasmCamera extends Camera {
final int pointer;
ThermionWasmCamera(this.pointer);
@override
Future setProjectionMatrixWithCulling(
Matrix4 projectionMatrix, double near, double far) {
// TODO: implement setProjectionMatrixWithCulling
throw UnimplementedError();
}
@override
Future<Matrix4> getModelMatrix() {
// TODO: implement getModelMatrix
throw UnimplementedError();
}
@override
Future setLensProjection({double near = kNear, double far = kFar, double aspect = 1.0, double focalLength = kFocalLength}) {
// TODO: implement setLensProjection
throw UnimplementedError();
}
@override
Future setTransform(Matrix4 transform) {
// TODO: implement setTransform
throw UnimplementedError();
}
@override
ThermionEntity getEntity() {
// TODO: implement getEntity
throw UnimplementedError();
}
@override
Future setModelMatrix(Matrix4 matrix) {
// TODO: implement setModelMatrix
throw UnimplementedError();
}
@override
Future<double> getCullingFar() {
// TODO: implement getCullingFar
throw UnimplementedError();
}
@override
Future<double> getFocalLength() {
// TODO: implement getFocalLength
throw UnimplementedError();
}
@override
Future<double> getNear() {
// TODO: implement getNear
throw UnimplementedError();
}
@override
Future<Matrix4> getViewMatrix() {
// TODO: implement getViewMatrix
throw UnimplementedError();
}
@override
Future setProjection(Projection projection, double left, double right, double bottom, double top, double near, double far) {
// TODO: implement setProjection
throw UnimplementedError();
}
}

View File

@@ -1,147 +0,0 @@
import 'package:vector_math/vector_math_64.dart';
import '../../../viewer.dart';
class ThermionWasmMaterialInstance extends MaterialInstance {
final int pointer;
ThermionWasmMaterialInstance(this.pointer);
@override
Future setParameterFloat2(String name, double x, double y) {
// TODO: implement setParameterFloat2
throw UnimplementedError();
}
@override
Future setParameterFloat(String name, double x) {
// TODO: implement setParameterFloat
throw UnimplementedError();
}
@override
Future setDepthFunc(SamplerCompareFunction depthFunc) {
// TODO: implement setDepthFunc
throw UnimplementedError();
}
@override
Future setParameterFloat4(String name, double x, double y, double z, double w) {
// TODO: implement setParameterFloat4
throw UnimplementedError();
}
@override
Future setParameterInt(String name, int value) {
// TODO: implement setParameterInt
throw UnimplementedError();
}
@override
Future setDepthCullingEnabled(enabled) {
// TODO: implement setDepthCullingEnabled
throw UnimplementedError();
}
@override
Future setDepthWriteEnabled(enabled) {
// TODO: implement setDepthWriteEnabled
throw UnimplementedError();
}
@override
Future setStencilCompareFunction(SamplerCompareFunction func, [StencilFace face = StencilFace.FRONT_AND_BACK]) {
// TODO: implement setStencilCompareFunction
throw UnimplementedError();
}
@override
Future setStencilOpDepthFail(StencilOperation op, [StencilFace face = StencilFace.FRONT_AND_BACK]) {
// TODO: implement setStencilOpDepthFail
throw UnimplementedError();
}
@override
Future setStencilOpDepthStencilPass(StencilOperation op, [StencilFace face = StencilFace.FRONT_AND_BACK]) {
// TODO: implement setStencilOpDepthStencilPass
throw UnimplementedError();
}
@override
Future setStencilOpStencilFail(StencilOperation op, [StencilFace face = StencilFace.FRONT_AND_BACK]) {
// TODO: implement setStencilOpStencilFail
throw UnimplementedError();
}
@override
Future setStencilReferenceValue(int value, [StencilFace face = StencilFace.FRONT_AND_BACK]) {
// TODO: implement setStencilReferenceValue
throw UnimplementedError();
}
@override
Future<bool> isStencilWriteEnabled() {
// TODO: implement isStencilWriteEnabled
throw UnimplementedError();
}
@override
Future setCullingMode(CullingMode cullingMode) {
// TODO: implement setCullingMode
throw UnimplementedError();
}
@override
Future setStencilWriteEnabled(bool enabled) {
// TODO: implement setStencilWriteEnabled
throw UnimplementedError();
}
@override
Future dispose() {
// TODO: implement dispose
throw UnimplementedError();
}
@override
Future setParameterBool(String name, bool value) {
// TODO: implement setParameterBool
throw UnimplementedError();
}
@override
Future setParameterFloat3(String name, double x, double y, double z) {
// TODO: implement setParameterFloat3
throw UnimplementedError();
}
@override
Future setParameterFloat3Array(String name, List<Vector3> data) {
// TODO: implement setParameterFloat3Array
throw UnimplementedError();
}
@override
Future setParameterTexture(String name, covariant Texture texture, covariant TextureSampler sampler) {
// TODO: implement setParameterTexture
throw UnimplementedError();
}
@override
Future setStencilReadMask(int mask) {
// TODO: implement setStencilReadMask
throw UnimplementedError();
}
@override
Future setStencilWriteMask(int mask) {
// TODO: implement setStencilWriteMask
throw UnimplementedError();
}
@override
Future setTransparencyMode(TransparencyMode mode) {
// TODO: implement setTransparencyMode
throw UnimplementedError();
}
}

View File

@@ -19,29 +19,29 @@
// import 'camera.dart';
// import 'material_instance.dart';
// extension type _EmscriptenModule(JSObject _) implements JSObject {
// external JSAny? ccall(String name, String returnType,
// JSArray<JSString> argTypes, JSArray<JSAny?> args, JSAny? opts);
extension type _EmscriptenModule(JSObject _) implements JSObject {
external JSAny? ccall(String name, String returnType,
JSArray<JSString> argTypes, JSArray<JSAny?> args, JSAny? opts);
// external JSNumber _malloc(int numBytes);
// external void _free(JSNumber addr);
// external JSNumber stackAlloc(int numBytes);
external JSNumber _malloc(int numBytes);
external void _free(JSNumber addr);
external JSNumber stackAlloc(int numBytes);
// external JSAny getValue(JSNumber addr, String llvmType);
// external void setValue(JSNumber addr, JSNumber value, String llvmType);
external JSAny getValue(JSNumber addr, String llvmType);
external void setValue(JSNumber addr, JSNumber value, String llvmType);
// external JSString intArrayToString(JSAny ptr);
// external JSString UTF8ToString(JSAny ptr);
// external void stringToUTF8(
// JSString str, JSNumber ptr, JSNumber maxBytesToWrite);
// external void writeArrayToMemory(JSUint8Array data, JSNumber ptr);
external JSString intArrayToString(JSAny ptr);
external JSString UTF8ToString(JSAny ptr);
external void stringToUTF8(
JSString str, JSNumber ptr, JSNumber maxBytesToWrite);
external void writeArrayToMemory(JSUint8Array data, JSNumber ptr);
// external JSNumber addFunction(JSFunction f, String signature);
// external void removeFunction(JSNumber f);
// external JSAny get ALLOC_STACK;
// external JSAny get HEAPU32;
// external JSAny get HEAP32;
// }
external JSNumber addFunction(JSFunction f, String signature);
external void removeFunction(JSNumber f);
external JSAny get ALLOC_STACK;
external JSAny get HEAPU32;
external JSAny get HEAP32;
}
// typedef ThermionViewerImpl = ThermionViewerWasm;
@@ -80,7 +80,6 @@
// _module = module as _EmscriptenModule;
// }
// }
// void _setAssetPathPrefix(String assetPathPrefix) {
// _module!.ccall(
// "thermion_dart_web_set_asset_path_prefix",

View File

@@ -1,9 +1,6 @@
library thermion_viewer;
export 'src/thermion_viewer_base.dart';
export '../filament/src/filament_app.dart';
export 'src/thermion_viewer_stub.dart'
if (dart.library.io) 'src/ffi/thermion_viewer_ffi.dart'
if (dart.library.js_interop) 'src/web_wasm/thermion_viewer_web_wasm.dart';
export '../filament/src/shared_types.dart';
export '../filament/src/interface/filament_app.dart';
export 'src/ffi/src/thermion_viewer_ffi.dart';
export '../filament/src/interface/shared_types.dart';