flutter3d
Showcase Changelog 38 packages API reference

Head tracking

since 0.1.0 Simulation, audio and XR

HeadTracker promises one thing: a pose that says which way the head is turned. SensorHeadTracker, the real implementation, reads that from a phone's rotation sensor. This page cannot run on one, so it implements the same interface by hand, driven by a drag of the pointer, and the rig on the other end cannot tell the two apart.

Step 1: A tracker that is not a sensor #

/// Turns pointer drags into a head pose, the same shape a sensor would.
final class _PointerHeadTracker implements HeadTracker {
  final ValueNotifier<HeadPose> _pose = ValueNotifier<HeadPose>(
    HeadPose.still(),
  );
  double _yaw = 0.0;

  @override
  ValueListenable<HeadPose> get pose => _pose;

  void dragBy(double dx) {
    _yaw -= dx * 0.01;
    _pose.value = HeadPose(
      rotation: Quaternion.axisAngle(Vector3(0.0, 1.0, 0.0), _yaw),
      position: Vector3.zero(),
    );
  }

  @override
  Future<void> start() async {}

  @override
  Future<void> stop() async {}
}

Step 2: Feed the pose to the rig #

StereoRig.applyHead reads a pose's rotation and position and points the head node with them, whichever kind of tracker produced it.

void _applyHead() => _rig.applyHead(_tracker.pose.value);

Drag across the page and the view turns, the same way turning a phone would.

Step 3: Check that turning the head turns the gaze #

final before = _rig.gaze();
_tracker.dragBy(200.0);
_applyHead();
final after = _rig.gaze();

StereoRig.gaze reads where the head is looking in world space. Dragging the pointer changes the tracker's pose, and applying that pose visibly turns it.