跳转至

Camera模块 API 参考

本参考文档涵盖了 src/camera/ 的实际导出项。所有数学运算均基于 gl-matrix (vec3, vec2, quat, mat3, mat4)。

导出项 (Exports)

import {
  type Camera,
  PerspectiveCamera,
  PerspectiveProjection,
  CameraAdapter,
  world2view,
  buildProj,
  deg2rad,
  focal2fov,
  fov2focal,
  Aabb,
  VIEWPORT_Y_FLIP,
} from 'src/camera';

接口: Camera

interface Camera {
  viewMatrix(): mat4;
  projMatrix(): mat4;
  position(): vec3;
  frustumPlanes(): {
    near: Float32Array;
    far: Float32Array;
    left: Float32Array;
    right: Float32Array;
    top: Float32Array;
    bottom: Float32Array;
  };
}

任何传递给预处理或渲染器的相机都必须实现此接口。几点说明: - 矩阵必须是列主序 (column-major) 且已准备好上传至 GPU。 - position() 返回一个克隆副本(修改结果不会影响相机)。 - frustumPlanes() 返回适用于距离测试的归一化 [A, B, C, D] 平面。

类: PerspectiveProjection

class PerspectiveProjection {
  constructor(
    viewport: vec2 | [number, number],
    fov: vec2 | [number, number], // 弧度 [fovx, fovy]
    znear: number,
    zfar: number,
  );

  fovx: number;
  fovy: number;
  znear: number;
  zfar: number;

  clone(): PerspectiveProjection;
  resize(viewport: vec2 | [number, number]): void;
  projectionMatrix(): mat4;
  focal(viewport: vec2 | [number, number]): [number, number];
  lerp(other: PerspectiveProjection, t: number): PerspectiveProjection;
}

行为

  • resize() 通过内部的 fov2viewRatio 保持视口宽高比与 FOV 宽高比之间的原始关系。
  • projectionMatrix()buildProj(znear, zfar, fovx, fovy) 的简单封装(WebGPU 深度范围 [0, 1])。
  • focal() 返回以像素为单位的各轴焦距(由预处理使用)。
  • lerp() 对 FOV 和近/远平面进行插值,以实现平滑的相机动画。

类: PerspectiveCamera

class PerspectiveCamera implements Camera {
  constructor(position: vec3, rotation: quat, projection: PerspectiveProjection);

  static default(): PerspectiveCamera;
  positionV: vec3;       // 世界空间位置(赋值时请使用克隆)
  rotationQ: quat;       // 世界->相机 四元数
  projection: PerspectiveProjection;

  fitNearFar(aabb: Aabb): void;
  viewMatrix(): mat4;
  projMatrix(): mat4;
  position(): vec3;
  frustumPlanes(): {
    near: Float32Array;
    far: Float32Array;
    left: Float32Array;
    right: Float32Array;
    top: Float32Array;
    bottom: Float32Array;
  };
}

说明

  • fitNearFar(aabb) 根据相机与 AABB 中心的距离调整 znear/zfar,强制执行最小比率 (zfar / 1000)。
  • viewMatrix()rotationQ 转换为 3×3 矩阵并调用 world2view(世界→相机变换)。
  • frustumPlanes() 计算 projMatrix * viewMatrix 并提取 Gribb–Hartmann 平面;法线已归一化。
  • static default() 创建一个位于 (0,0,-1) 的相机,拥有 45° FOV 和 [0.1, 100] 的深度范围。

类: CameraAdapter

允许 Three.js 相机驱动核心管线。

class CameraAdapter implements Camera {
  update(camera: THREE.PerspectiveCamera, viewport: [number, number]): void;
  viewMatrix(): mat4;
  projMatrix(): mat4;
  position(): Float32Array;
  frustumPlanes(): Float32Array; // 占位符 (24 个值)
  projection: { focal(viewport?: [number, number]): [number, number] };
  transposeRotation: boolean;
  flipProjY: boolean;
  flipProjX: boolean;
}

行为

  • update() 复制 Three 的矩阵,预乘 diag(-1, 1, -1, 1) 使视图/投影符合核心约定,补偿预处理打包期间执行的 Y 翻转,并计算各轴焦距。
  • 调用 update 后,适配器满足 Camera 接口,可以直接传递给 dispatchModel 或渲染器代码。

函数

world2view(R_wc: mat3, C: vec3): mat4

根据旋转矩阵(世界→相机)和相机位置构建世界→相机变换。

buildProj(znear: number, zfar: number, fovx: number, fovy: number): mat4

返回兼容 WebGPU 裁剪空间约定的列主序透视矩阵。

数学辅助函数 (重新导出)

  • deg2rad(degrees: number): number
  • fov2focal(fovRadians: number, pixels: number): number
  • focal2fov(focalPixels: number, pixels: number): number
  • Aabb (fitNearFar 使用的轴对齐包围盒工具)。
  • VIEWPORT_Y_FLIP – 将 Y 乘以 -1 的 mat4 常量(用于需要单次翻转的地方)。

示例

import { PerspectiveCamera, PerspectiveProjection, deg2rad } from 'src/camera';

const projection = new PerspectiveProjection(
  [1920, 1080],
  [deg2rad(65), deg2rad(45)],
  0.1,
  500,
);
const camera = new PerspectiveCamera(vec3.fromValues(0, 2, -4), quat.create(), projection);
camera.fitNearFar(pointCloud.bbox);

const view = camera.viewMatrix();
const proj = camera.projMatrix();
const planes = camera.frustumPlanes();

使用 Three.js:

const adapter = new CameraAdapter();
adapter.update(threeCamera, [canvas.width, canvas.height]);
preprocessor.dispatchModel({ camera: adapter, viewport: [canvas.width, canvas.height], /* ... */ }, encoder);