RotationComposer

Looks at a target with a dead zone, off-center framing and damping.

Rotates the camera to keep the target at screenPosition. With a deadZone the target can move freely inside it before the camera turns, and damping makes the turn smooth. With the default settings it behaves like HardLookAt.

The zones react to the target's edge, not just its center, so its size matters. klipp.setSize keeps the screen proportions in sync with your viewport. With an orthographic camera, the screen spans orthographicSize at any distance.

Settings

SettingDescriptionDefault
targetWhat to look at. See Targets.
targetOffsetOffset from the target, in the target's own space. Use it to look at a head instead of the feet.[0, 0, 0]
screenPositionWhere the target should be on screen. [0, 0] is the center, ±1 the edges, with +y up.[0, 0]
deadZoneHow far the target can drift from screenPosition to each side before the camera turns, in the same units: [0.2, 0.1] is a box 0.4 wide and 0.2 tall.[0, 0]
hardLimitHow far the target can ever drift from screenPosition to each side, even while damping is catching up. [0, 0] turns it off.[0, 0]
dampingSeconds to catch up once the target leaves the dead zone. See Damping.0
maxSpeedMaximum turn speed, in degrees per second.Infinity
lookaheadTimeSeconds to look ahead of a moving target.0
lookaheadSmoothingSeconds used to smooth the target's measured speed for lookahead.1
lookaheadIgnoreYOnly look ahead horizontally, handy for jumping characters.false
radiusthree.js and React. The target's radius. On the core, set the target's extent.
sizethree.js and React. The target's box size, used instead of radius.measured for meshes
debugReact only. Draws the zones on screen. See Debugging.false

Combining with PositionComposer

When pairing it with PositionComposer, use the same screenPosition on both, and give both a non-zero deadZone. Without a dead zone on each side they cancel each other out.

Usage

import { RotationComposerAim, targetPose } from '@pmndrs/klipp';

const player = targetPose.create(); // keep player.position up to date
player.extent.radius = 0.5; // so the zones react to its edge
camera.aim = new RotationComposerAim(player, { deadZone: [0.2, 0.2], damping: 0.3 });

The target's size comes from player.extent, and its rotation is only used for targetOffset.