more camera work

This commit is contained in:
Nick Fisher
2024-09-26 18:41:34 +08:00
parent d1cd68cda6
commit 2408104bd0
14 changed files with 234 additions and 40 deletions

View File

@@ -69,11 +69,11 @@ class DelegateInputHandler implements InputHandler {
});
factory DelegateInputHandler.flight(ThermionViewer viewer,
{PickDelegate? pickDelegate, bool freeLook=false}) =>
{PickDelegate? pickDelegate, bool freeLook=false, double? clampY, ThermionEntity? entity}) =>
DelegateInputHandler(
viewer: viewer,
pickDelegate: pickDelegate,
transformDelegate: FreeFlightInputHandlerDelegate(viewer),
transformDelegate: FreeFlightInputHandlerDelegate(viewer, clampY:clampY, entity:entity),
actions: {
InputType.MMB_HOLD_AND_MOVE: InputAction.ROTATE,
InputType.SCROLLWHEEL: InputAction.TRANSLATE,

View File

@@ -5,14 +5,15 @@ import '../delegates.dart';
import '../input_handler.dart';
class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
final ThermionViewer viewer;
late Future<ThermionEntity> entity;
final Vector3? minBounds;
final Vector3? maxBounds;
final double rotationSensitivity;
final double movementSensitivity;
final double zoomSensitivity;
final double panSensitivity;
final double? clampY;
static final _up = Vector3(0, 1, 0);
static final _forward = Vector3(0, 0, -1);
@@ -23,15 +24,21 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
double _queuedZoomDelta = 0.0;
Vector3 _queuedMoveDelta = Vector3.zero();
FreeFlightInputHandlerDelegate(
this.viewer, {
this.minBounds,
this.maxBounds,
this.rotationSensitivity = 0.001,
this.movementSensitivity = 0.1,
this.zoomSensitivity = 0.1,
this.panSensitivity = 0.1,
});
FreeFlightInputHandlerDelegate(this.viewer,
{this.minBounds,
this.maxBounds,
this.rotationSensitivity = 0.001,
this.movementSensitivity = 0.1,
this.zoomSensitivity = 0.1,
this.panSensitivity = 0.1,
this.clampY,
ThermionEntity? entity}) {
if (entity != null) {
this.entity = Future.value(entity);
} else {
this.entity = viewer.getMainCameraEntity();
}
}
@override
Future<void> queue(InputAction action, Vector3? delta) async {
@@ -73,10 +80,14 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
return;
}
Matrix4 currentModelMatrix = await viewer.getCameraModelMatrix();
Vector3 currentPosition = currentModelMatrix.getTranslation();
final activeCamera = await viewer.getActiveCamera();
Matrix4 currentViewMatrix = activeCamera.getViewMatrix();
Matrix4 currentTransform = await viewer.getLocalTransform(await entity);
Vector3 currentPosition = currentTransform.getTranslation();
Quaternion currentRotation =
Quaternion.fromRotation(currentModelMatrix.getRotation());
Quaternion.fromRotation(currentTransform.getRotation());
// Apply rotation
if (_queuedRotationDelta.length2 > 0.0) {
@@ -135,7 +146,7 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
// Update camera
Matrix4 newModelMatrix =
Matrix4.compose(currentPosition, currentRotation, Vector3(1, 1, 1));
await viewer.setCameraModelMatrix4(newModelMatrix);
await viewer.setTransform(await entity, newModelMatrix);
_executing = false;
}
@@ -151,6 +162,10 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
position.y = position.y.clamp(double.negativeInfinity, maxBounds!.y);
position.z = position.z.clamp(double.negativeInfinity, maxBounds!.z);
}
if (clampY != null) {
position.y = clampY!;
}
return position;
}
}

View File

@@ -7,7 +7,6 @@ import '../../thermion_viewer_base.dart';
import 'thermion_dart.g.dart';
class ThermionFFICamera extends Camera {
final Pointer<TCamera> camera;
final Pointer<TEngine> engine;
late ThermionEntity _entity;
@@ -52,7 +51,7 @@ class ThermionFFICamera extends Camera {
Camera_setModelMatrix(camera, matrix4ToDouble4x4(matrix));
}
@override
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ThermionFFICamera &&
@@ -61,4 +60,19 @@ class ThermionFFICamera extends Camera {
@override
int get hashCode => camera.hashCode;
@override
Future<double> getCullingFar() async {
return Camera_getCullingFar(camera);
}
@override
Future<double> getNear() async {
return Camera_getNear(camera);
}
@override
Future<double> getFocalLength() async {
return Camera_getFocalLength(camera);
}
}

View File

@@ -819,11 +819,6 @@ external ffi.Pointer<TCamera> get_camera(
int entity,
);
@ffi.Native<ffi.Double Function(ffi.Pointer<TCamera>)>(isLeaf: true)
external double get_camera_focal_length(
ffi.Pointer<TCamera> camera,
);
@ffi.Native<double4x4 Function(ffi.Pointer<TCamera>)>(isLeaf: true)
external double4x4 get_camera_model_matrix(
ffi.Pointer<TCamera> camera,
@@ -872,6 +867,26 @@ external void set_camera_projection_from_fov(
bool horizontal,
);
@ffi.Native<ffi.Double Function(ffi.Pointer<TCamera>)>(isLeaf: true)
external double get_camera_focal_length(
ffi.Pointer<TCamera> camera,
);
@ffi.Native<ffi.Double Function(ffi.Pointer<TCamera>)>(isLeaf: true)
external double Camera_getFocalLength(
ffi.Pointer<TCamera> camera,
);
@ffi.Native<ffi.Double Function(ffi.Pointer<TCamera>)>(isLeaf: true)
external double Camera_getNear(
ffi.Pointer<TCamera> camera,
);
@ffi.Native<ffi.Double Function(ffi.Pointer<TCamera>)>(isLeaf: true)
external double Camera_getCullingFar(
ffi.Pointer<TCamera> camera,
);
@ffi.Native<ffi.Double Function(ffi.Pointer<TCamera>)>(isLeaf: true)
external double get_camera_near(
ffi.Pointer<TCamera> camera,
@@ -983,6 +998,12 @@ external ffi.Pointer<TCamera> SceneManager_getCameraAt(
int index,
);
@ffi.Native<ffi.Pointer<TCamera> Function(ffi.Pointer<TSceneManager>)>(
isLeaf: true)
external ffi.Pointer<TCamera> SceneManager_getActiveCamera(
ffi.Pointer<TSceneManager> sceneManager,
);
@ffi.Native<
ffi.Int Function(ffi.Pointer<TSceneManager>, EntityId,
ffi.Pointer<ffi.Char>)>(isLeaf: true)

View File

@@ -105,22 +105,28 @@ class ThermionViewerFFI extends ThermionViewer {
Future updateViewportAndCameraProjection(double width, double height) async {
viewportDimensions = (width * pixelRatio, height * pixelRatio);
update_viewport(_viewer!, width.toInt(), height.toInt());
var mainCamera = await getMainCamera() as ThermionFFICamera;
var near = await getCameraCullingNear();
if (near.abs() < 0.000001) {
near = kNear;
}
var far = await getCameraCullingFar();
if (far.abs() < 0.000001) {
far = kFar;
}
var aspect = viewportDimensions.$1 / viewportDimensions.$2;
var focalLength = get_camera_focal_length(mainCamera.camera);
if (focalLength.abs() < 0.1) {
focalLength = kFocalLength;
final cameraCount = await getCameraCount();
for (int i = 0; i < cameraCount; i++) {
var camera = await getCameraAt(i);
var near = await camera.getNear();
if (near.abs() < 0.000001) {
near = kNear;
}
var far = await camera.getCullingFar();
if (far.abs() < 0.000001) {
far = kFar;
}
var aspect = viewportDimensions.$1 / viewportDimensions.$2;
var focalLength = await camera.getFocalLength();
if (focalLength.abs() < 0.1) {
focalLength = kFocalLength;
}
camera.setLensProjection(
near: near, far: far, aspect: aspect, focalLength: focalLength);
}
Camera_setLensProjection(mainCamera.camera, near, far, aspect, focalLength);
}
Future createSwapChain(double width, double height,
@@ -2174,9 +2180,10 @@ class ThermionViewerFFI extends ThermionViewer {
}
Future<Camera> createCamera() async {
var camera = SceneManager_createCamera(_sceneManager!);
var cameraPtr = SceneManager_createCamera(_sceneManager!);
var engine = Viewer_getEngine(_viewer!);
return ThermionFFICamera(camera, engine);
var camera = ThermionFFICamera(cameraPtr, engine);
return camera;
}
Future destroyCamera(ThermionFFICamera camera) async {
@@ -2190,6 +2197,14 @@ class ThermionViewerFFI extends ThermionViewer {
SceneManager_setCamera(_sceneManager!, camera.camera);
}
///
///
///
Future<Camera> getActiveCamera() async {
final ptr = SceneManager_getActiveCamera(_sceneManager!);
return ThermionFFICamera(ptr, Viewer_getEngine(_viewer!));
}
final _hooks = <Future Function()>[];
@override

View File

@@ -18,4 +18,8 @@ abstract class Camera {
ThermionEntity getEntity();
Future setTransform(Matrix4 transform);
Future<double> getNear();
Future<double> getCullingFar();
Future<double> getFocalLength();
}

View File

@@ -970,6 +970,11 @@ abstract class ThermionViewer {
///
Future setActiveCamera(covariant Camera camera);
///
///
///
Future getActiveCamera();
///
///
///