首页 / 模块目录 / 相机机位 / LookOffsetCameraRig

LookOffsetCameraRig

three

目标周围临时自由视角旋转,停止输入后回中。

类别相机机位
依赖档位three
相关模块
演示场camera-gallery · 相机机位 ↓
只取这个模块
modules/camera/LookOffsetCameraRig.js

连同其内部依赖一并复制,保留相对目录结构。

相机机位

three

自动行驶展示,无需操作。

源码

import { Quaternion } from 'three';
import { clamp, smoothingAlpha } from '../math/ScalarUtils.js';
import { toVec3 } from '../math/Vector3Utils.js';
import { BaseCameraRig } from './BaseCameraRig.js';
import { DEFAULT_WORLD_BASIS } from '../math/WorldBasis.js';

export class LookOffsetCameraRig extends BaseCameraRig {
  constructor({
    distance = 20,
    lookSensitivity = 0.0035, // 0.2 deg per input unit
    returnLag = 0.17,
    pitchMin = -1.4835, // -85 deg
    pitchMax = 1.4835, // 85 deg
    basis = DEFAULT_WORLD_BASIS,
  }) {
    super({ basis });
    Object.assign(this, {
      distance,
      lookSensitivity,
      returnLag,
      cameraYaw: 0,
      cameraPitch: 0,
      pitchMin,
      pitchMax,
    });
  }

  setSensitivity(value) {
    this.lookSensitivity = value;
    return this;
  }

  setLook(cameraYaw = 0, cameraPitch = 0) {
    this.cameraYaw = cameraYaw;
    this.cameraPitch = clamp(cameraPitch, this.pitchMin, this.pitchMax);
    return this;
  }

  step({
    targetPosition,
    targetYaw = 0,
    targetPitch = 0,
    targetRoll = 0,
    lookActive = false,
    lookDeltaX = 0,
    lookDeltaY = 0,
    deltaSeconds = 1 / 60,
    camera = null,
  }) {
    if (lookActive) {
      this.cameraYaw += lookDeltaX * this.lookSensitivity;
      this.cameraPitch += lookDeltaY * this.lookSensitivity;
      this.cameraPitch = clamp(this.cameraPitch, this.pitchMin, this.pitchMax);
    } else {
      const blend = smoothingAlpha(this.returnLag, deltaSeconds);
      this.cameraYaw += (0 - this.cameraYaw) * blend;
      this.cameraPitch += (0 - this.cameraPitch) * blend;
    }

    const lookAtPosition = toVec3(targetPosition);

    const frame = this.basis.yawPitchRollFrame(
      targetYaw + this.cameraYaw,
      targetPitch + this.cameraPitch,
      targetRoll
    );
    const cameraPosition = frame.back.clone()
      .multiplyScalar(this.distance)
      .add(lookAtPosition);

    this.setLookAtPose({
      position: cameraPosition, lookAt: lookAtPosition, up: frame.up
    });

    const pose = this.getPose();
    this.applyToCamera(camera, pose);
    return pose;
  }
}