feat! js_interop improvements
This commit is contained in:
1 parent
63e2dcd0ca
commit
2f16908992
159 files changed
+12989
-8377
No files matched your search
@@ -0,0 +1,3 @@
|
||||
export 'src/ffi.dart'
|
||||
if (dart.library.io) 'src/ffi.dart'
|
||||
if (dart.library.js_interop) 'src/js_interop.dart';
|
||||
+94
-21
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 renamed without changes.
+659
-1536
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -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';
|
||||
@@ -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;
|
||||
}
|
||||
+9
-7
@@ -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);
|
||||
+110
-49
@@ -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");
|
||||
}
|
||||
+57
-13
@@ -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 {
|
||||
+219
-143
@@ -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);
|
||||
}
|
||||
+41
-18
@@ -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
|
||||
+24
-33
@@ -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);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -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 {
|
||||
+3
-3
@@ -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;
|
||||
+1
-1
@@ -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 {
|
||||
+32
-33
@@ -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 {
|
||||
+21
-12
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -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 {
|
||||
|
||||
@@ -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';
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
+1
-1
@@ -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';
|
||||
+1
-1
@@ -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 }
|
||||
File renamed without changes.
File renamed without changes.
+2
-6
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
+3
@@ -25,4 +25,7 @@ abstract class GizmoAsset extends ThermionAsset {
|
||||
Future unhighlight();
|
||||
bool isNonPickable(ThermionEntity entity);
|
||||
bool isGizmoEntity(ThermionEntity entity);
|
||||
|
||||
Future dispose();
|
||||
|
||||
}
|
||||
File renamed without changes.
Whitespace-only changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
-2
@@ -1,5 +1,3 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
+1
-1
@@ -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
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+6
-3
@@ -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();
|
||||
|
||||
|
||||
}
|
||||
+1
-5
@@ -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;
|
||||
|
||||
@@ -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]!);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -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';
|
||||
@@ -1,7 +1,9 @@
|
||||
library filament_dart;
|
||||
|
||||
export 'dart:typed_data';
|
||||
export 'package:vector_math/vector_math_64.dart' hide Colors;
|
||||
export 'src/viewer/viewer.dart';
|
||||
export 'src/input/input.dart';
|
||||
export 'src/utils/utils.dart';
|
||||
export 'src/filament/filament.dart';
|
||||
export 'src/bindings/bindings.dart' hide Aabb2, Aabb3;
|
||||
Reference in new issue
Block a user