refactor: continual refactor to support multiple render targets
This commit is contained in:
@@ -1,21 +0,0 @@
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
import '../../thermion_dart.dart';
|
||||
|
||||
abstract class AbstractGizmo {
|
||||
|
||||
bool get isVisible;
|
||||
bool get isHovered;
|
||||
|
||||
Future translate(double transX, double transY);
|
||||
|
||||
void reset();
|
||||
|
||||
Future attach(ThermionEntity entity);
|
||||
|
||||
Future detach();
|
||||
|
||||
Stream<Aabb2> get boundingBox;
|
||||
|
||||
void checkHover(double x, double y);
|
||||
}
|
||||
@@ -56,6 +56,9 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
|
||||
return;
|
||||
}
|
||||
|
||||
final view = await viewer.getViewAt(0);
|
||||
final viewport = await view.getViewport();
|
||||
|
||||
var viewMatrix = await viewer.getCameraViewMatrix();
|
||||
var modelMatrix = await viewer.getCameraModelMatrix();
|
||||
var projectionMatrix = await viewer.getCameraProjectionMatrix();
|
||||
@@ -80,12 +83,8 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
|
||||
intersectionInClipSpace / intersectionInClipSpace.w;
|
||||
|
||||
// Calculate new camera position based on rotation
|
||||
final ndcX = 2 *
|
||||
((-_queuedRotationDelta.x * viewer.pixelRatio) /
|
||||
viewer.viewportDimensions.$1);
|
||||
final ndcY = 2 *
|
||||
((_queuedRotationDelta.y * viewer.pixelRatio) /
|
||||
viewer.viewportDimensions.$2);
|
||||
final ndcX = 2 * ((-_queuedRotationDelta.x) / viewport.width);
|
||||
final ndcY = 2 * ((_queuedRotationDelta.y) / viewport.height);
|
||||
final ndc = Vector4(ndcX, ndcY, intersectionInNdcSpace.z, 1.0);
|
||||
|
||||
var clipSpace = Vector4(
|
||||
|
||||
@@ -93,9 +93,9 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
|
||||
// Apply rotation
|
||||
if (_queuedRotationDelta.length2 > 0.0) {
|
||||
double deltaX =
|
||||
_queuedRotationDelta.x * rotationSensitivity * viewer.pixelRatio;
|
||||
_queuedRotationDelta.x * rotationSensitivity;
|
||||
double deltaY =
|
||||
_queuedRotationDelta.y * rotationSensitivity * viewer.pixelRatio;
|
||||
_queuedRotationDelta.y * rotationSensitivity;
|
||||
|
||||
Quaternion yawRotation = Quaternion.axisAngle(_up, -deltaX);
|
||||
Quaternion pitchRotation = Quaternion.axisAngle(_right, -deltaY);
|
||||
@@ -109,8 +109,8 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
|
||||
Vector3 right = _right.clone()..applyQuaternion(currentRotation);
|
||||
Vector3 up = _up.clone()..applyQuaternion(currentRotation);
|
||||
|
||||
double deltaX = _queuedPanDelta.x * panSensitivity * viewer.pixelRatio;
|
||||
double deltaY = _queuedPanDelta.y * panSensitivity * viewer.pixelRatio;
|
||||
double deltaX = _queuedPanDelta.x * panSensitivity;
|
||||
double deltaY = _queuedPanDelta.y * panSensitivity;
|
||||
|
||||
relativeTranslation += right * deltaX + up * deltaY;
|
||||
_queuedPanDelta = Vector2.zero();
|
||||
|
||||
@@ -96,9 +96,9 @@ class OverTheShoulderCameraDelegate implements InputHandlerDelegate {
|
||||
// camera is always looking at -Z, whereas models generally face towards +Z
|
||||
if (_queuedRotationDelta.length2 > 0.0) {
|
||||
double deltaX =
|
||||
_queuedRotationDelta.x * rotationSensitivity * viewer.pixelRatio;
|
||||
_queuedRotationDelta.x * rotationSensitivity;
|
||||
double deltaY =
|
||||
_queuedRotationDelta.y * rotationSensitivity * viewer.pixelRatio;
|
||||
_queuedRotationDelta.y * rotationSensitivity;
|
||||
|
||||
cameraLookAt = Matrix4.rotationY(-deltaX) *
|
||||
Matrix4.rotationX(-deltaY) *
|
||||
|
||||
@@ -1,19 +1,31 @@
|
||||
import 'dart:async';
|
||||
import 'package:thermion_dart/src/entities/abstract_gizmo.dart';
|
||||
|
||||
import 'package:thermion_dart/src/viewer/viewer.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
import '../viewer/viewer.dart';
|
||||
|
||||
class Gizmo extends AbstractGizmo {
|
||||
abstract class Gizmo {
|
||||
bool get isVisible;
|
||||
bool get isHovered;
|
||||
|
||||
void reset();
|
||||
|
||||
Future attach(ThermionEntity entity);
|
||||
Future detach();
|
||||
|
||||
Stream<Aabb2> get boundingBox;
|
||||
|
||||
void checkHover(int x, int y);
|
||||
}
|
||||
|
||||
abstract class BaseGizmo extends Gizmo {
|
||||
final ThermionEntity x;
|
||||
final ThermionEntity y;
|
||||
final ThermionEntity z;
|
||||
final ThermionEntity center;
|
||||
|
||||
final ThermionViewer _viewer;
|
||||
|
||||
ThermionEntity? _activeAxis;
|
||||
ThermionEntity? _activeEntity;
|
||||
ThermionViewer viewer;
|
||||
|
||||
bool _visible = false;
|
||||
bool get isVisible => _visible;
|
||||
@@ -26,10 +38,9 @@ class Gizmo extends AbstractGizmo {
|
||||
Stream<Aabb2> get boundingBox => _boundingBoxController.stream;
|
||||
final _boundingBoxController = StreamController<Aabb2>.broadcast();
|
||||
|
||||
Gizmo(this.x, this.y, this.z, this.center, this._viewer,
|
||||
{this.ignore = const <ThermionEntity>{}}) {
|
||||
_viewer.gizmoPickResult.listen(_onGizmoPickResult);
|
||||
_viewer.pickResult.listen(_onPickResult);
|
||||
BaseGizmo({required this.x, required this.y, required this.z, required this.center, required this.viewer,
|
||||
this.ignore = const <ThermionEntity>{}}) {
|
||||
onPick(_onGizmoPickResult);
|
||||
}
|
||||
|
||||
final _stopwatch = Stopwatch();
|
||||
@@ -52,12 +63,10 @@ class Gizmo extends AbstractGizmo {
|
||||
final axis = Vector3(_activeAxis == x ? 1.0 : 0.0,
|
||||
_activeAxis == y ? 1.0 : 0.0, _activeAxis == z ? 1.0 : 0.0);
|
||||
|
||||
await _viewer.queueRelativePositionUpdateWorldAxis(
|
||||
await viewer.queueRelativePositionUpdateWorldAxis(
|
||||
_activeEntity!,
|
||||
_transX * _viewer.pixelRatio,
|
||||
-_transY *
|
||||
_viewer
|
||||
.pixelRatio, // flip the sign because "up" in NDC Y axis is positive, but negative in Flutter
|
||||
_transX,
|
||||
-_transY, // flip the sign because "up" in NDC Y axis is positive, but negative in Flutter
|
||||
axis.x,
|
||||
axis.y,
|
||||
axis.z);
|
||||
@@ -70,10 +79,6 @@ class Gizmo extends AbstractGizmo {
|
||||
_activeAxis = null;
|
||||
}
|
||||
|
||||
void _onPickResult(FilamentPickResult result) async {
|
||||
await attach(result.entity);
|
||||
}
|
||||
|
||||
void _onGizmoPickResult(FilamentPickResult result) async {
|
||||
if (result.entity == x || result.entity == y || result.entity == z) {
|
||||
_activeAxis = result.entity;
|
||||
@@ -98,21 +103,25 @@ class Gizmo extends AbstractGizmo {
|
||||
_visible = true;
|
||||
|
||||
if (_activeEntity != null) {
|
||||
await _viewer.removeStencilHighlight(_activeEntity!);
|
||||
await viewer.removeStencilHighlight(_activeEntity!);
|
||||
}
|
||||
_activeEntity = entity;
|
||||
await _viewer.setGizmoVisibility(true);
|
||||
await _viewer.setParent(center, entity, preserveScaling: false);
|
||||
_boundingBoxController.sink.add(await _viewer.getViewportBoundingBox(x));
|
||||
|
||||
await viewer.setParent(center, entity, preserveScaling: false);
|
||||
_boundingBoxController.sink.add(await viewer.getViewportBoundingBox(x));
|
||||
}
|
||||
|
||||
Future detach() async {
|
||||
await _viewer.setGizmoVisibility(false);
|
||||
await setVisibility(false);
|
||||
}
|
||||
|
||||
@override
|
||||
void checkHover(double x, double y) {
|
||||
_viewer.pickGizmo(x.toInt(), y.toInt());
|
||||
void checkHover(int x, int y) {
|
||||
pick(x, y);
|
||||
}
|
||||
|
||||
Future pick(int x, int y);
|
||||
|
||||
Future setVisibility(bool visible);
|
||||
void onPick(void Function(PickResult result) callback);
|
||||
}
|
||||
50
thermion_dart/lib/src/viewer/src/ffi/src/ffi_gizmo.dart
Normal file
50
thermion_dart/lib/src/viewer/src/ffi/src/ffi_gizmo.dart
Normal file
@@ -0,0 +1,50 @@
|
||||
import 'dart:async';
|
||||
import 'dart:ffi';
|
||||
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
|
||||
|
||||
import '../../../../utils/gizmo.dart';
|
||||
import '../../../viewer.dart';
|
||||
|
||||
class FFIGizmo extends BaseGizmo {
|
||||
Pointer<TGizmo> pointer;
|
||||
|
||||
late NativeCallable<GizmoPickCallbackFunction> _nativeCallback;
|
||||
FFIGizmo(
|
||||
this.pointer, ThermionViewer viewer) : super(x: 0, y: 0, z: 0, center: 0, viewer: viewer) {
|
||||
_nativeCallback =
|
||||
NativeCallable<GizmoPickCallbackFunction>.listener(_onPickResult);
|
||||
}
|
||||
|
||||
///
|
||||
/// The result(s) of calling [pickGizmo] (see below).
|
||||
///
|
||||
// Stream<PickResult> get onPick => _pickResultController.stream;
|
||||
// final _pickResultController = StreamController<PickResult>.broadcast();
|
||||
|
||||
void Function(PickResult)? _callback;
|
||||
|
||||
void onPick(void Function(PickResult) callback) {
|
||||
_callback = callback;
|
||||
}
|
||||
|
||||
void _onPickResult(DartEntityId entityId, int x, int y, Pointer<TView> view) {
|
||||
_callback?.call((entity: entityId, x: x, y: y));
|
||||
}
|
||||
|
||||
///
|
||||
/// Used to test whether a Gizmo is at the given viewport coordinates.
|
||||
/// Called by `FilamentGestureDetector` on a mouse/finger down event. You probably don't want to call this yourself.
|
||||
/// This is asynchronous and will require 2-3 frames to complete - subscribe to the [gizmoPickResult] stream to receive the results of this method.
|
||||
/// [x] and [y] must be in local logical coordinates (i.e. where 0,0 is at top-left of the ThermionWidget).
|
||||
///
|
||||
@override
|
||||
Future pick(int x, int y) async {
|
||||
Gizmo_pick(pointer, x.toInt(), y, _nativeCallback.nativeFunction);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setVisibility(bool visible) async {
|
||||
Gizmo_setVisibility(pointer, visible);
|
||||
}
|
||||
}
|
||||
42
thermion_dart/lib/src/viewer/src/ffi/src/ffi_view.dart
Normal file
42
thermion_dart/lib/src/viewer/src/ffi/src/ffi_view.dart
Normal file
@@ -0,0 +1,42 @@
|
||||
import 'dart:ffi';
|
||||
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/shared_types/camera.dart';
|
||||
|
||||
import '../../shared_types/view.dart';
|
||||
import '../thermion_viewer_ffi.dart';
|
||||
import 'thermion_viewer_ffi.dart';
|
||||
|
||||
class FFIView extends View {
|
||||
final Pointer<TView> view;
|
||||
final Pointer<TViewer> viewer;
|
||||
|
||||
FFIView(this.view, this.viewer);
|
||||
|
||||
@override
|
||||
Future updateViewport(int width, int height) async {
|
||||
View_updateViewport(view, width, height);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setRenderTarget(covariant FFIRenderTarget renderTarget) async {
|
||||
View_setRenderTarget(view, renderTarget.renderTarget);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setCamera(FFICamera camera) async {
|
||||
View_setCamera(view, camera.camera);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Viewport> getViewport() async {
|
||||
TViewport vp = View_getViewport(view);
|
||||
return Viewport(vp.left, vp.bottom, vp.width, vp.height);
|
||||
}
|
||||
|
||||
@override
|
||||
Camera getCamera() {
|
||||
final engine = Viewer_getEngine(viewer);
|
||||
return FFICamera(View_getCamera(view), engine);
|
||||
}
|
||||
}
|
||||
@@ -139,6 +139,13 @@ external void Viewer_setMainCamera(
|
||||
ffi.Pointer<TView> tView,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Pointer<TSwapChain> Function(ffi.Pointer<TViewer>, ffi.Int)>(
|
||||
isLeaf: true)
|
||||
external ffi.Pointer<TSwapChain> Viewer_getSwapChainAt(
|
||||
ffi.Pointer<TViewer> tViewer,
|
||||
int index,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Pointer<TEngine> Function(ffi.Pointer<TViewer>)>(isLeaf: true)
|
||||
external ffi.Pointer<TEngine> Viewer_getEngine(
|
||||
ffi.Pointer<TViewer> viewer,
|
||||
@@ -662,9 +669,9 @@ external void SceneManager_setVisibilityLayer(
|
||||
int layer,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Pointer<TGizmo> Function(ffi.Pointer<TSceneManager>)>(
|
||||
@ffi.Native<ffi.Pointer<TScene> Function(ffi.Pointer<TSceneManager>)>(
|
||||
isLeaf: true)
|
||||
external ffi.Pointer<TGizmo> SceneManager_getGizmo(
|
||||
external ffi.Pointer<TScene> SceneManager_getScene(
|
||||
ffi.Pointer<TSceneManager> tSceneManager,
|
||||
);
|
||||
|
||||
@@ -1176,14 +1183,6 @@ external void set_priority(
|
||||
int priority,
|
||||
);
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Void Function(
|
||||
ffi.Pointer<TSceneManager>, ffi.Pointer<EntityId>)>(isLeaf: true)
|
||||
external void get_gizmo(
|
||||
ffi.Pointer<TSceneManager> sceneManager,
|
||||
ffi.Pointer<EntityId> out,
|
||||
);
|
||||
|
||||
@ffi.Native<
|
||||
Aabb2 Function(
|
||||
ffi.Pointer<TSceneManager>, ffi.Pointer<TView>, EntityId)>(isLeaf: true)
|
||||
@@ -1212,13 +1211,6 @@ external void get_bounding_box_to_out(
|
||||
ffi.Pointer<ffi.Float> maxY,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Void Function(ffi.Pointer<TSceneManager>, ffi.Bool)>(
|
||||
isLeaf: true)
|
||||
external void set_gizmo_visibility(
|
||||
ffi.Pointer<TSceneManager> sceneManager,
|
||||
bool visible,
|
||||
);
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Void Function(ffi.Pointer<TSceneManager>, EntityId, ffi.Float,
|
||||
ffi.Float, ffi.Float)>(isLeaf: true)
|
||||
@@ -1480,10 +1472,15 @@ external void set_rendering_render_thread(
|
||||
);
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Void Function(ffi.Pointer<TViewer>,
|
||||
ffi.Void Function(
|
||||
ffi.Pointer<TViewer>,
|
||||
ffi.Pointer<TView>,
|
||||
ffi.Pointer<TSwapChain>,
|
||||
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
|
||||
external void request_frame_render_thread(
|
||||
external void Viewer_requestFrameRenderThread(
|
||||
ffi.Pointer<TViewer> viewer,
|
||||
ffi.Pointer<TView> view,
|
||||
ffi.Pointer<TSwapChain> tSwapChain,
|
||||
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
|
||||
);
|
||||
|
||||
@@ -1892,7 +1889,7 @@ external void View_setBloom(
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Void Function(
|
||||
ffi.Pointer<TView>, ffi.Pointer<TEngine>, ffi.Int)>(isLeaf: true)
|
||||
ffi.Pointer<TView>, ffi.Pointer<TEngine>, ffi.Int32)>(isLeaf: true)
|
||||
external void View_setToneMapping(
|
||||
ffi.Pointer<TView> tView,
|
||||
ffi.Pointer<TEngine> tEngine,
|
||||
@@ -1924,30 +1921,39 @@ external void View_setCamera(
|
||||
ffi.Pointer<TCamera> tCamera,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Pointer<TScene> Function(ffi.Pointer<TView>)>(isLeaf: true)
|
||||
external ffi.Pointer<TScene> View_getScene(
|
||||
ffi.Pointer<TView> tView,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Pointer<TCamera> Function(ffi.Pointer<TView>)>(isLeaf: true)
|
||||
external ffi.Pointer<TCamera> View_getCamera(
|
||||
ffi.Pointer<TView> tView,
|
||||
);
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Void Function(
|
||||
ffi.Pointer<TGizmo>,
|
||||
ffi.Pointer<TView>,
|
||||
ffi.Int,
|
||||
ffi.Int,
|
||||
ffi.Pointer<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(
|
||||
EntityId entityId, ffi.Int x, ffi.Int y)>>)>(isLeaf: true)
|
||||
ffi.Pointer<TGizmo> Function(ffi.Pointer<TEngine>, ffi.Pointer<TView>,
|
||||
ffi.Pointer<TScene>)>(isLeaf: true)
|
||||
external ffi.Pointer<TGizmo> Gizmo_new(
|
||||
ffi.Pointer<TEngine> tEngine,
|
||||
ffi.Pointer<TView> tView,
|
||||
ffi.Pointer<TScene> tScene,
|
||||
);
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Void Function(ffi.Pointer<TGizmo>, ffi.Uint32, ffi.Uint32,
|
||||
GizmoPickCallback)>(isLeaf: true)
|
||||
external void Gizmo_pick(
|
||||
ffi.Pointer<TGizmo> tGizmo,
|
||||
ffi.Pointer<TView> tView,
|
||||
int x,
|
||||
int y,
|
||||
ffi.Pointer<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(EntityId entityId, ffi.Int x, ffi.Int y)>>
|
||||
callback,
|
||||
GizmoPickCallback callback,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Void Function(ffi.Pointer<TGizmo>, ffi.Bool)>(isLeaf: true)
|
||||
external void Gizmo_setVisibility(
|
||||
ffi.Pointer<TGizmo> tGizmo,
|
||||
bool visible,
|
||||
);
|
||||
|
||||
final class TCamera extends ffi.Opaque {}
|
||||
@@ -1970,6 +1976,8 @@ final class TView extends ffi.Opaque {}
|
||||
|
||||
final class TGizmo extends ffi.Opaque {}
|
||||
|
||||
final class TScene extends ffi.Opaque {}
|
||||
|
||||
final class TMaterialKey extends ffi.Struct {
|
||||
@ffi.Bool()
|
||||
external bool doubleSided;
|
||||
@@ -2216,6 +2224,19 @@ final class TViewport extends ffi.Struct {
|
||||
external int height;
|
||||
}
|
||||
|
||||
abstract class ToneMapping {
|
||||
static const int ACES = 0;
|
||||
static const int FILMIC = 1;
|
||||
static const int LINEAR = 2;
|
||||
}
|
||||
|
||||
typedef GizmoPickCallback
|
||||
= ffi.Pointer<ffi.NativeFunction<GizmoPickCallbackFunction>>;
|
||||
typedef GizmoPickCallbackFunction = ffi.Void Function(
|
||||
EntityId entityId, ffi.Uint32 x, ffi.Uint32 y, ffi.Pointer<TView> view);
|
||||
typedef DartGizmoPickCallbackFunction = void Function(
|
||||
DartEntityId entityId, int x, int y, ffi.Pointer<TView> view);
|
||||
|
||||
const int __bool_true_false_are_defined = 1;
|
||||
|
||||
const int true1 = 1;
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
import 'dart:async';
|
||||
import 'dart:ffi';
|
||||
import 'dart:math';
|
||||
import 'dart:typed_data';
|
||||
import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/shared_types/swap_chain.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_gizmo.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
import 'package:vector_math/vector_math_64.dart' as v64;
|
||||
import '../../../../entities/gizmo.dart';
|
||||
import '../../../../utils/gizmo.dart';
|
||||
import '../../../../utils/matrix.dart';
|
||||
import '../../events.dart';
|
||||
import '../../shared_types/camera.dart';
|
||||
import '../../shared_types/view.dart';
|
||||
import '../../thermion_viewer_base.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
import 'callbacks.dart';
|
||||
import 'camera_ffi.dart';
|
||||
import 'thermion_dart.g.dart';
|
||||
import 'ffi_view.dart';
|
||||
|
||||
// ignore: constant_identifier_names
|
||||
const ThermionEntity _FILAMENT_ASSET_ERROR = 0;
|
||||
@@ -26,8 +24,6 @@ typedef RenderCallback = Pointer<NativeFunction<Void Function(Pointer<Void>)>>;
|
||||
class ThermionViewerFFI extends ThermionViewer {
|
||||
final _logger = Logger("ThermionViewerFFI");
|
||||
|
||||
double pixelRatio = 1.0;
|
||||
|
||||
Pointer<TSceneManager>? _sceneManager;
|
||||
|
||||
Pointer<TViewer>? _viewer;
|
||||
@@ -87,13 +83,9 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
this._driver = driver ?? nullptr;
|
||||
this._sharedContext = sharedContext ?? nullptr;
|
||||
|
||||
_onPickResultCallable =
|
||||
NativeCallable<Void Function(EntityId entityId, Int x, Int y)>.listener(
|
||||
_onPickResult);
|
||||
|
||||
_onGizmoPickResultCallable =
|
||||
NativeCallable<Void Function(EntityId entityId, Int x, Int y)>.listener(
|
||||
_onGizmoPickResult);
|
||||
// _onPickResultCallable =
|
||||
// NativeCallable<Void Function(EntityId entityId, Int x, Int y)>.listener(
|
||||
// _onPickResult);
|
||||
|
||||
_initialize();
|
||||
}
|
||||
@@ -131,7 +123,6 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
///
|
||||
///
|
||||
Future updateViewportAndCameraProjection(double width, double height) async {
|
||||
viewportDimensions = (width * pixelRatio, height * pixelRatio);
|
||||
var mainView = FFIView(Viewer_getViewAt(_viewer!, 0), _viewer!);
|
||||
mainView.updateViewport(width.toInt(), height.toInt());
|
||||
|
||||
@@ -148,7 +139,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
far = kFar;
|
||||
}
|
||||
|
||||
var aspect = viewportDimensions.$1 / viewportDimensions.$2;
|
||||
var aspect = width / height;
|
||||
var focalLength = await camera.getFocalLength();
|
||||
if (focalLength.abs() < 0.1) {
|
||||
focalLength = kFocalLength;
|
||||
@@ -161,8 +152,8 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
Future<SwapChain> createSwapChain(int width, int height,
|
||||
{Pointer<Void>? surface}) async {
|
||||
var swapChain = await withPointerCallback<TSwapChain>((callback) {
|
||||
return Viewer_createSwapChainRenderThread(_viewer!, surface ?? nullptr,
|
||||
width, height, callback);
|
||||
return Viewer_createSwapChainRenderThread(
|
||||
_viewer!, surface ?? nullptr, width, height, callback);
|
||||
});
|
||||
return FFISwapChain(swapChain, _viewer!);
|
||||
}
|
||||
@@ -193,11 +184,6 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
|
||||
_sceneManager = Viewer_getSceneManager(_viewer!);
|
||||
|
||||
final gizmoEntities = allocator<Int32>(4);
|
||||
get_gizmo(_sceneManager!, gizmoEntities);
|
||||
_gizmo = Gizmo(gizmoEntities[0], gizmoEntities[1], gizmoEntities[2],
|
||||
gizmoEntities[3], this);
|
||||
allocator.free(gizmoEntities);
|
||||
this._initialized.complete(true);
|
||||
}
|
||||
|
||||
@@ -224,8 +210,9 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
///
|
||||
///
|
||||
@override
|
||||
Future render(FFISwapChain swapChain) async {
|
||||
Future render({FFISwapChain? swapChain}) async {
|
||||
final view = (await getViewAt(0)) as FFIView;
|
||||
swapChain ??= FFISwapChain(Viewer_getSwapChainAt(_viewer!, 0), _viewer!);
|
||||
Viewer_renderRenderThread(_viewer!, view.view, swapChain.swapChain);
|
||||
}
|
||||
|
||||
@@ -233,20 +220,24 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
///
|
||||
///
|
||||
@override
|
||||
Future<Uint8List> capture(FFISwapChain swapChain,
|
||||
{FFIView? view, FFIRenderTarget? renderTarget}) async {
|
||||
final length = this.viewportDimensions.$1.toInt() *
|
||||
this.viewportDimensions.$2.toInt() *
|
||||
4;
|
||||
final out = Uint8List(length);
|
||||
Future<Uint8List> capture(
|
||||
{FFIView? view,
|
||||
FFISwapChain? swapChain,
|
||||
FFIRenderTarget? renderTarget}) async {
|
||||
view ??= (await getViewAt(0)) as FFIView;
|
||||
final vp = await view.getViewport();
|
||||
final length = vp.width * vp.height * 4;
|
||||
final out = Uint8List(length);
|
||||
|
||||
swapChain ??= FFISwapChain(Viewer_getSwapChainAt(_viewer!, 0), _viewer!);
|
||||
|
||||
await withVoidCallback((cb) {
|
||||
if (renderTarget != null) {
|
||||
Viewer_captureRenderTargetRenderThread(_viewer!, view!.view,
|
||||
swapChain.swapChain, renderTarget.renderTarget, out.address, cb);
|
||||
swapChain!.swapChain, renderTarget.renderTarget, out.address, cb);
|
||||
} else {
|
||||
Viewer_captureRenderThread(
|
||||
_viewer!, view!.view, swapChain.swapChain, out.address, cb);
|
||||
_viewer!, view!.view, swapChain!.swapChain, out.address, cb);
|
||||
}
|
||||
});
|
||||
return out;
|
||||
@@ -1341,20 +1332,6 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
set_camera_model_matrix(mainCamera.camera, out);
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
@override
|
||||
Future setCameraLensProjection(
|
||||
{double near = kNear,
|
||||
double far = kFar,
|
||||
double? aspect,
|
||||
double focalLength = kFocalLength}) async {
|
||||
aspect ??= viewportDimensions.$1 / viewportDimensions.$2;
|
||||
var mainCamera = get_camera(_viewer!, get_main_camera(_viewer!));
|
||||
Camera_setLensProjection(mainCamera, near, far, aspect, focalLength);
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
@@ -1492,50 +1469,31 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
return result.cast<Utf8>().toDartString();
|
||||
}
|
||||
|
||||
void _onPickResult(ThermionEntity entityId, int x, int y) {
|
||||
_pickResultController.add((
|
||||
entity: entityId,
|
||||
x: (x / pixelRatio).toDouble(),
|
||||
y: (viewportDimensions.$2 - y) / pixelRatio
|
||||
));
|
||||
}
|
||||
void _onPickResult(
|
||||
ThermionEntity entityId, int x, int y, Pointer<TView> viewPtr) async {
|
||||
final view = FFIView(viewPtr, _viewer!);
|
||||
final viewport = await view.getViewport();
|
||||
|
||||
void _onGizmoPickResult(ThermionEntity entityId, int x, int y) {
|
||||
_gizmoPickResultController.add((
|
||||
entity: entityId,
|
||||
x: (x / pixelRatio).toDouble(),
|
||||
y: (viewportDimensions.$2 - y) / pixelRatio
|
||||
));
|
||||
// _pickResultController.add((
|
||||
// entity: entityId,
|
||||
// x: (x / pixelRatio).toDouble(),
|
||||
// y: (viewport.height - y) / pixelRatio
|
||||
// ));
|
||||
}
|
||||
|
||||
late NativeCallable<Void Function(EntityId entityId, Int x, Int y)>
|
||||
_onPickResultCallable;
|
||||
late NativeCallable<Void Function(EntityId entityId, Int x, Int y)>
|
||||
_onGizmoPickResultCallable;
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
@override
|
||||
void pick(int x, int y) async {
|
||||
x = (x * pixelRatio).ceil();
|
||||
y = (viewportDimensions.$2 - (y * pixelRatio)).ceil();
|
||||
final view = (await getViewAt(0)) as FFIView;
|
||||
filament_pick(
|
||||
_viewer!, view.view, x, y, _onPickResultCallable.nativeFunction);
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
@override
|
||||
void pickGizmo(int x, int y) async {
|
||||
x = (x * pixelRatio).ceil();
|
||||
y = (viewportDimensions.$2 - (y * pixelRatio)).ceil();
|
||||
final view = (await getViewAt(0)) as FFIView;
|
||||
final gizmo = SceneManager_getGizmo(_sceneManager!);
|
||||
Gizmo_pick(
|
||||
gizmo, view.view, x, y, _onGizmoPickResultCallable.nativeFunction);
|
||||
// x = (x * pixelRatio).ceil();
|
||||
// y = (viewportDimensions.$2 - (y * pixelRatio)).ceil();
|
||||
// final view = (await getViewAt(0)) as FFIView;
|
||||
// filament_pick(
|
||||
// _viewer!, view.view, x, y, _onPickResultCallable.nativeFunction);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -1866,13 +1824,6 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
SceneManager_setVisibilityLayer(_sceneManager!, entity, layer);
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
Future setGizmoVisibility(bool visible) async {
|
||||
set_gizmo_visibility(_sceneManager!, visible);
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
@@ -2088,7 +2039,11 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
completer.complete(true);
|
||||
});
|
||||
|
||||
request_frame_render_thread(_viewer!, callback.nativeFunction);
|
||||
final swapChain = Viewer_getSwapChainAt(_viewer!, 0);
|
||||
final view = Viewer_getViewAt(_viewer!, 0);
|
||||
|
||||
Viewer_requestFrameRenderThread(
|
||||
_viewer!, view, swapChain, callback.nativeFunction);
|
||||
|
||||
await completer.future;
|
||||
}
|
||||
@@ -2164,6 +2119,14 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
}
|
||||
return FFIView(view, _viewer!);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Gizmo> createGizmo(FFIView view) async {
|
||||
var view = (await getViewAt(0)) as FFIView;
|
||||
var scene = View_getScene(view.view);
|
||||
final gizmo = Gizmo_new(Viewer_getEngine(_viewer!), view.view, scene);
|
||||
return FFIGizmo(gizmo, this);
|
||||
}
|
||||
}
|
||||
|
||||
class ThermionFFITexture extends ThermionTexture {
|
||||
@@ -2218,32 +2181,3 @@ class FFISwapChain extends SwapChain {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class FFIView extends View {
|
||||
final Pointer<TView> view;
|
||||
final Pointer<TViewer> viewer;
|
||||
|
||||
FFIView(this.view, this.viewer);
|
||||
|
||||
@override
|
||||
Future updateViewport(int width, int height) async {
|
||||
View_updateViewport(view, width, height);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setRenderTarget(covariant FFIRenderTarget renderTarget) async {
|
||||
View_setRenderTarget(view, renderTarget.renderTarget);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setCamera(FFICamera camera) async {
|
||||
View_setCamera(view, camera.camera);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Viewport> getViewport() async {
|
||||
TViewport vp = View_getViewport(view);
|
||||
return Viewport(vp.left, vp.bottom, vp.width, vp.height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// "picking" means clicking/tapping on the viewport, and unprojecting the X/Y coordinate to determine whether any renderable entities were present at those coordinates.
|
||||
import '../../viewer.dart';
|
||||
|
||||
typedef FilamentPickResult = ({ThermionEntity entity, double x, double y});
|
||||
typedef ThermionPickResult = FilamentPickResult;
|
||||
typedef FilamentPickResult = ({ThermionEntity entity, int x, int y});
|
||||
typedef PickResult = FilamentPickResult;
|
||||
|
||||
@@ -12,7 +12,7 @@ class Viewport {
|
||||
abstract class View {
|
||||
Future<Viewport> getViewport();
|
||||
Future updateViewport(int width, int height);
|
||||
Future setRenderTarget(covariant RenderTarget renderTarget);
|
||||
Future setRenderTarget(covariant RenderTarget? renderTarget);
|
||||
Future setCamera(covariant Camera camera);
|
||||
|
||||
Camera getCamera();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:thermion_dart/src/viewer/src/events.dart';
|
||||
import '../../entities/abstract_gizmo.dart';
|
||||
import 'shared_types/camera.dart';
|
||||
import '../../utils/gizmo.dart';
|
||||
import 'shared_types/shared_types.dart';
|
||||
export 'shared_types/shared_types.dart';
|
||||
|
||||
@@ -10,7 +9,6 @@ import 'package:vector_math/vector_math_64.dart';
|
||||
import 'dart:async';
|
||||
import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||
|
||||
import 'shared_types/swap_chain.dart';
|
||||
import 'shared_types/view.dart';
|
||||
|
||||
const double kNear = 0.05;
|
||||
@@ -23,16 +21,6 @@ abstract class ThermionViewer {
|
||||
///
|
||||
Future<bool> get initialized;
|
||||
|
||||
///
|
||||
/// The current dimensions of the viewport (in physical pixels).
|
||||
///
|
||||
var viewportDimensions = (0.0, 0.0);
|
||||
|
||||
///
|
||||
/// The current ratio of logical to physical pixels.
|
||||
///
|
||||
late double pixelRatio;
|
||||
|
||||
///
|
||||
/// The result(s) of calling [pick] (see below).
|
||||
/// This may be a broadcast stream, so you should ensure you have subscribed to this stream before calling [pick].
|
||||
@@ -40,11 +28,6 @@ abstract class ThermionViewer {
|
||||
///
|
||||
Stream<FilamentPickResult> get pickResult;
|
||||
|
||||
///
|
||||
/// The result(s) of calling [pickGizmo] (see below).
|
||||
///
|
||||
Stream<FilamentPickResult> get gizmoPickResult;
|
||||
|
||||
///
|
||||
/// A Stream containing entities added/removed to/from to the scene.
|
||||
///
|
||||
@@ -63,7 +46,7 @@ abstract class ThermionViewer {
|
||||
///
|
||||
/// Render a single frame immediately.
|
||||
///
|
||||
Future render(covariant SwapChain swapChain);
|
||||
Future render({covariant SwapChain? swapChain});
|
||||
|
||||
///
|
||||
/// Requests a single frame to be rendered. This is only intended to be used internally.
|
||||
@@ -73,8 +56,8 @@ abstract class ThermionViewer {
|
||||
///
|
||||
/// Render a single frame and copy the pixel buffer to [out].
|
||||
///
|
||||
Future<Uint8List> capture(covariant SwapChain swapChain,
|
||||
{covariant View? view, covariant RenderTarget? renderTarget});
|
||||
Future<Uint8List> capture({covariant SwapChain? swapChain,
|
||||
covariant View? view, covariant RenderTarget? renderTarget});
|
||||
|
||||
///
|
||||
///
|
||||
@@ -96,7 +79,7 @@ abstract class ThermionViewer {
|
||||
///
|
||||
///
|
||||
Future<View> createView();
|
||||
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
@@ -400,7 +383,6 @@ abstract class ThermionViewer {
|
||||
///
|
||||
Future clearEntities();
|
||||
|
||||
|
||||
///
|
||||
/// Schedules the glTF animation at [index] in [entity] to start playing on the next frame.
|
||||
///
|
||||
@@ -493,15 +475,6 @@ abstract class ThermionViewer {
|
||||
///
|
||||
Future<double> getCameraCullingFar();
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
Future setCameraLensProjection(
|
||||
{double near = kNear,
|
||||
double far = kFar,
|
||||
double? aspect,
|
||||
double focalLength = kFocalLength});
|
||||
|
||||
///
|
||||
/// Sets the focus distance for the camera.
|
||||
///
|
||||
@@ -701,14 +674,6 @@ abstract class ThermionViewer {
|
||||
///
|
||||
void pick(int x, int y);
|
||||
|
||||
///
|
||||
/// Used to test whether a Gizmo is at the given viewport coordinates.
|
||||
/// Called by `FilamentGestureDetector` on a mouse/finger down event. You probably don't want to call this yourself.
|
||||
/// This is asynchronous and will require 2-3 frames to complete - subscribe to the [gizmoPickResult] stream to receive the results of this method.
|
||||
/// [x] and [y] must be in local logical coordinates (i.e. where 0,0 is at top-left of the ThermionWidget).
|
||||
///
|
||||
void pickGizmo(int x, int y);
|
||||
|
||||
///
|
||||
/// Retrieves the name assigned to the given ThermionEntity (usually corresponds to the glTF mesh name).
|
||||
///
|
||||
@@ -793,9 +758,9 @@ abstract class ThermionViewer {
|
||||
Future setPriority(ThermionEntity entityId, int priority);
|
||||
|
||||
///
|
||||
/// The gizmo for translating/rotating objects. Only one gizmo is present in the scene.
|
||||
/// The gizmo for translating/rotating objects. Only one gizmo can be active for a given view.
|
||||
///
|
||||
AbstractGizmo? get gizmo;
|
||||
Future<Gizmo> createGizmo(covariant View view);
|
||||
|
||||
///
|
||||
/// Register a callback to be invoked when this viewer is disposed.
|
||||
@@ -819,11 +784,6 @@ abstract class ThermionViewer {
|
||||
///
|
||||
Future setVisibilityLayer(ThermionEntity entity, int layer);
|
||||
|
||||
///
|
||||
/// Show/hide the translation gizmo.
|
||||
///
|
||||
Future setGizmoVisibility(bool visible);
|
||||
|
||||
///
|
||||
/// Renders an outline around [entity] with the given color.
|
||||
///
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import 'dart:math';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:thermion_dart/src/utils/gizmo.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/shared_types/swap_chain.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/shared_types/view.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
import 'dart:async';
|
||||
import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||
|
||||
import '../../entities/abstract_gizmo.dart';
|
||||
import 'events.dart';
|
||||
import 'shared_types/camera.dart';
|
||||
|
||||
@@ -242,10 +241,6 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
// TODO: implement gizmo
|
||||
AbstractGizmo? get gizmo => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
Future hide(ThermionEntity entity, String? meshName) {
|
||||
// TODO: implement hide
|
||||
@@ -1028,12 +1023,6 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
// TODO: implement setRenderTarget
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> capture(covariant SwapChain swapChain, {covariant RenderTarget? renderTarget}) {
|
||||
// TODO: implement capture
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<View> createView() {
|
||||
@@ -1052,6 +1041,18 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
// TODO: implement render
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> capture(covariant SwapChain swapChain, {covariant View? view, covariant RenderTarget? renderTarget}) {
|
||||
// TODO: implement capture
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Gizmo> createGizmo(covariant View view) {
|
||||
// TODO: implement createGizmo
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import 'dart:typed_data';
|
||||
import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
import '../../../../entities/abstract_gizmo.dart';
|
||||
import '../../shared_types/internal/gizmo.dart';
|
||||
import '../../../viewer.dart';
|
||||
import '../../events.dart';
|
||||
import '../../shared_types/camera.dart';
|
||||
|
||||
@@ -45,4 +45,28 @@ class ThermionWasmCamera extends Camera {
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'dart:convert';
|
||||
import '../../../../entities/abstract_gizmo.dart';
|
||||
import '../../../../entities/gizmo.dart';
|
||||
import '../../shared_types/internal/gizmo.dart';
|
||||
import '../../shared_types/internal/gizmo.dart';
|
||||
import '../../../viewer.dart';
|
||||
import '../../events.dart';
|
||||
import '../../shared_types/camera.dart';
|
||||
|
||||
Reference in New Issue
Block a user