remove custom camera delegate
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user