remove custom camera delegate

This commit is contained in:
Nick Fisher
2025-05-12 12:32:59 +08:00
parent 826a22f348
commit 460000308a

View File

@@ -1,228 +0,0 @@
import 'dart:async';
import 'dart:math' as math;
import 'package:vector_math/vector_math_64.dart';
import '../../../viewer/viewer.dart';
import '../../input.dart';
class CustomInputHandlerDelegate implements InputHandlerDelegate {
final View view;
final ThermionAsset asset;
final InputSensitivityOptions sensitivity;
final Vector3 targetPoint;
final double minZoomDistance;
final double maxZoomDistance;
final worldUp = Vector3(0, 1, 0);
double _radius;
double _radiusScaleFactor = 1.0;
double _azimuth; // Angle around worldUp (Y-axis), in radians
double
_elevation; // Angle above the XZ plane (around local X-axis), in radians
bool _isInitialized = false;
bool _isMouseDown = false;
Vector2? _lastPointerPosition;
CustomInputHandlerDelegate(
this.view, this.asset, {
this.sensitivity = const InputSensitivityOptions(),
Vector3? targetPoint,
this.minZoomDistance = 1.0,
this.maxZoomDistance = 100.0,
}) : targetPoint = targetPoint ?? Vector3.zero(),
_radius =
(minZoomDistance + maxZoomDistance) / 2, // Initial default radius
_azimuth = 0.0,
_elevation = math.pi / 4; // Initial default elevation (45 degrees)
Future<void> _initializeFromCamera(Camera activeCamera) async {
final currentModelMatrix = await activeCamera.getModelMatrix();
final cameraPosition = currentModelMatrix.getTranslation();
final directionToCamera = cameraPosition - targetPoint;
_radius = directionToCamera.length;
_radius = _radius.clamp(minZoomDistance, maxZoomDistance);
if (_radius < 0.001) {
_radius = minZoomDistance;
_azimuth = 0.0;
_elevation = math.pi / 4;
} else {
final dirToCameraNormalized = directionToCamera.normalized();
// Elevation: angle with the XZ plane (plane perpendicular to worldUp)
// Assuming worldUp is (0,1,0), elevation is asin(y)
_elevation = math.asin(dirToCameraNormalized.dot(worldUp));
// Azimuth: angle in the XZ plane.
// Project dirToCameraNormalized onto the plane perpendicular to worldUp
Vector3 projectionOnPlane =
(dirToCameraNormalized - worldUp * math.sin(_elevation)).normalized();
if (projectionOnPlane.length2 < 0.0001 &&
worldUp.dot(Vector3(0, 0, 1)).abs() < 0.99) {
// looking straight up/down, pick a default reference for azimuth
projectionOnPlane =
Vector3(0, 0, 1); // if worldUp is Y, project onto XZ plane
} else if (projectionOnPlane.length2 < 0.0001) {
// if worldUp is Z, project onto XY plane
projectionOnPlane = Vector3(1, 0, 0);
}
// Define a reference vector in the plane (e.g., world X-axis or Z-axis)
// Let's use world Z-axis as the 0-azimuth reference, if not aligned with worldUp
Vector3 referenceAzimuthVector = Vector3(0, 0, 1);
if (worldUp.dot(referenceAzimuthVector).abs() > 0.99) {
// If worldUp is Z, use X instead
referenceAzimuthVector = Vector3(1, 0, 0);
}
// Ensure referenceAzimuthVector is also in the plane
referenceAzimuthVector = (referenceAzimuthVector -
worldUp * referenceAzimuthVector.dot(worldUp))
.normalized();
_azimuth = math.atan2(
projectionOnPlane.cross(referenceAzimuthVector).dot(worldUp),
projectionOnPlane.dot(referenceAzimuthVector));
}
_elevation = _elevation.clamp(
-math.pi / 2 + 0.01, math.pi / 2 - 0.01); // Clamp elevation
_isInitialized = true;
}
@override
Future<void> handle(Set<InputEvent> events) async {
final activeCamera = await view.getCamera();
if (!_isInitialized) {
await _initializeFromCamera(activeCamera);
}
double deltaAzimuth = 0;
double deltaElevation = 0;
double deltaRadius = 0;
for (final event in events) {
switch (event) {
case ScrollEvent(delta: final scrollDelta):
deltaRadius += sensitivity.scrollWheelSensitivity * scrollDelta;
break;
case MouseEvent(
type: final type,
button: final button,
localPosition: final localPosition,
// delta: final mouseDelta // Using localPosition to calculate delta from _lastPointerPosition
):
switch (type) {
case MouseEventType.buttonDown:
if (button == MouseButton.left) {
// Typically left mouse button for orbit
_isMouseDown = true;
_lastPointerPosition = localPosition;
}
break;
case MouseEventType.buttonUp:
if (button == MouseButton.left) {
_isMouseDown = false;
_lastPointerPosition = null;
}
break;
case MouseEventType.move:
case MouseEventType
.hover: // Some systems might only send hover when no buttons pressed
if (_isMouseDown && _lastPointerPosition != null) {
final dragDelta = localPosition - _lastPointerPosition!;
// X-drag affects azimuth, Y-drag affects elevation
deltaAzimuth -= dragDelta.x *
sensitivity.mouseSensitivity; // Invert X for natural feel
deltaElevation -= dragDelta.y *
sensitivity.mouseSensitivity; // Invert Y for natural feel
_lastPointerPosition = localPosition;
} else if (type == MouseEventType.hover) {
// Allow hover to set initial if not dragging
_lastPointerPosition = localPosition;
}
break;
}
break;
case TouchEvent(
type: final type,
localPosition: final localPosition,
delta: final touchDelta,
):
switch (type) {
case TouchEventType.tap:
break;
default:
break;
}
break;
case ScaleUpdateEvent(
numPointers: final numPointers,
scale: final scaleFactor,
localFocalPoint: final localFocalPoint,
localFocalPointDelta: final localFocalPointDelta
):
if (numPointers == 1) {
deltaAzimuth -=
localFocalPointDelta!.$1 * sensitivity.touchSensitivity;
deltaElevation -=
localFocalPointDelta.$2 * sensitivity.touchSensitivity;
} else {
_radiusScaleFactor = scaleFactor;
}
case ScaleEndEvent():
_radius *= _radiusScaleFactor;
_radiusScaleFactor = 1.0;
default:
break;
}
}
if (deltaAzimuth == 0 &&
deltaElevation == 0 &&
deltaRadius == 0 &&
_radiusScaleFactor == 1.0) {
return;
}
_azimuth += deltaAzimuth;
_elevation += deltaElevation;
_radius += deltaRadius;
var radius = _radius * _radiusScaleFactor;
// Clamp parameters
_elevation = _elevation.clamp(-math.pi / 2 + 0.01,
math.pi / 2 - 0.01); // Prevent gimbal lock at poles
radius = radius.clamp(minZoomDistance, maxZoomDistance);
_azimuth =
_azimuth % (2 * math.pi); // Keep azimuth within 0-2PI range (optional)
final double xOffset = radius * math.cos(_elevation) * math.sin(_azimuth);
final double yOffset = radius * math.sin(_elevation);
final double zOffset = radius * math.cos(_elevation) * math.cos(_azimuth);
Vector3 cameraPosition;
if (worldUp.dot(Vector3(0, 1, 0)).abs() > 0.99) {
// Standard Y-up
cameraPosition = targetPoint + Vector3(xOffset, yOffset, zOffset);
} else if (worldUp.dot(Vector3(0, 0, 1)).abs() > 0.99) {
cameraPosition = targetPoint +
Vector3(
radius * math.cos(_elevation) * math.cos(_azimuth), // x
radius * math.cos(_elevation) * math.sin(_azimuth), // y
radius * math.sin(_elevation) // z
);
} else {
cameraPosition = targetPoint + Vector3(xOffset, yOffset, zOffset);
}
final modelMatrix = makeViewMatrix(cameraPosition, targetPoint, worldUp)
..invert();
await activeCamera.setModelMatrix(modelMatrix);
}
}