Crate trackball[][src]

Virtual Trackball Orbiting via the Exponential Map

This is an alternative trackball technique using exponential map and parallel transport to preserve distances and angles for inducing coherent and intuitive trackball rotations. For instance, displacements on straight radial lines through the screen’s center are carried to arcs of the same length on great circles of the trackball. This is in contrast to state-of-the-art techniques using orthogonal projection which distorts radial distances further away from the screen’s center. This implementation strictly follows the recipe given in the paper of Stantchev, G.. “Virtual Trackball Modeling and the Exponential Map.” . S2CID 44199608.

Present Features

  • Common trackball operations split into several operation handlers.
  • Coherent and intuitive orbiting via the exponential map, see Orbit operation handler.
  • Identical C11 implementation for Orbit operation handler behind cc feature gate.
  • Observer frame with Frame::slide(), Frame::orbit(), Frame::scale() operations in world space and their local complements in camera space.
  • Object inspection mode scaling clip plane distances by measuring from target instead of eye.
  • Scale-preserving transitioning between orthographic and perspective projection mode.
  • Time-free touch gesture recognition for slide, orbit, scale, and focus operations.

Future Features

  • Add Clamp operation handler ensuring user boundary conditions of Frame and Scene.
  • Compute bounding box of scene graph and track total slide to prevent clip plane collisions.

Example

A trackball camera mode implementation can be as easy as this by delegating events of your 3D graphics library of choice to the Orbit operation handler along with other handlers.

use nalgebra::{Point2, UnitQuaternion, Vector3};
use std::f32::consts::PI;
use trackball::{Frame, Image, Orbit};

/// Trackball camera mode.
pub struct Trackball {
	// Frame wrt camera eye and target.
	frame: Frame<f32>,
	// Image as projection of `Scene` wrt `Frame`.
	image: Image<f32>,
	// Orbit induced by displacement on screen.
	orbit: Orbit<f32>,
}

impl Trackball {
	// Usually, a cursor position event with left mouse button being pressed.
	fn handle_left_button_displacement(&mut self, pos: &Point2<f32>) {
		// Maximum position as screen's width and height.
		let max = self.image.max();
		// Induced rotation in camera space.
		let rot = self.orbit.compute(&pos, max).unwrap_or_default();
		// Apply induced rotation to local observer frame.
		self.frame.local_orbit(&rot);
	}
	// Event when left mouse button is released again.
	fn handle_left_button_release(&mut self) {
		// Can also or instead be invoked on `Self::handle_left_button_press()`.
		self.orbit.discard();
	}
}

Structs

Frame

Frame wrt camera eye and target.

Image

Image as projection of Scene wrt Frame.

Orbit

Orbit induced by displacement on screen.

Scale

Scale induced by relative input.

Scene

Scene wrt enclosing viewing frustum.

Slide

Slide induced by displacement on screen.

Touch

Touch gestures inducing slide, orbit, scale, and focus.