跳转至

Camera模块

src/camera/ 提供了每个子系统(预处理、渲染器、控制、Three.js 桥接)所依赖的视图/投影基础架构。该模块特意保持精简:一个 Camera 接口、具体的 PerspectiveCamera + PerspectiveProjection,以及用于镜像 Three.js 相机的 CameraAdapter

职责

  • 为 GPU Uniforms 提供稳定的视图/投影矩阵(列主序,WebGPU NDC)。
  • 使用 PerspectiveProjection 管理视场 (FOV)、宽高比和近/远平面数学运算。
  • 暴露便捷的辅助函数 (fitNearFar, resize, focal, lerp),以便渲染器和控制器可以适应场景边界或视口变化。
  • 为工具或自定义相机提供 world2view / buildProj 实用程序。
  • 提供 CameraAdapter 以在预处理/排序管线中重用 Three.js 相机,而无需重写数学逻辑。

组件

组件 路径 目的
Camera 接口 perspective.ts 渲染器/预处理器使用的最小契约(视图矩阵、投影矩阵、位置、视锥体平面)。
PerspectiveProjection perspective.ts 存储 fovx, fovy, znear, zfar,处理大小调整 + 插值 + 矩阵生成。
PerspectiveCamera perspective.ts 具体的 Camera 实现,具有 positionV, rotationQ,近/远拟合,视锥体提取,以及支持缓存的 Getters。
CameraAdapter CameraAdapter.ts THREE.PerspectiveCamera 转换为预处理着色器所需的相同视图/投影/焦距数据。
实用工具 index.ts 重新导出 world2view, buildProj, 以及数学辅助函数 (deg2rad, focal2fov, fov2focal, VIEWPORT_Y_FLIP)。

数据流

PerspectiveCamera ──view/proj→ Uniform 缓冲 (渲染器 & 预处理)
PerspectiveProjection ──resize/focal/lerp→ 相机设置 UI / 动画
CameraAdapter ──update(THREE.PerspectiveCamera)→ 用于预处理调度的 view/proj/focal
world2view & buildProj ──utility hooks→ 自定义相机实现

亮点

  • 底层使用 gl-matrix: 所有数学运算均由 gl-matrix (vec3, quat, mat3, mat4) 支持,以实现可预测的性能和内存布局。
  • 右手坐标系,WebGPU 友好: 视图空间看向 -Z;投影矩阵映射到 WebGPU 的 [0,1] 深度范围。当某个阶段需要翻转一次 Y 时(预处理已进行补偿),会导出 VIEWPORT_Y_FLIP
  • 近/远拟合: PerspectiveCamera.fitNearFar(aabb) 计算包围盒周围的紧密深度范围(具有 1.5 倍远距余量和 1:1000 近/远钳位),以最大化预处理和渲染期间的精度。
  • 视锥体提取: frustumPlanes() 乘投影和视图矩阵,并发射六个归一化的平面方程用于剔除。
  • 视口感知: PerspectiveProjection.resize(viewport) 在画布大小更改时保持水平/垂直 FOV 比率一致,因此 UI 大小调整不会使图像变形。
  • 动画就绪: PerspectiveProjection.lerp() 和基于四元数的旋转使得为时间轴或控制系统插值相机变得容易。
  • Three.js 桥接: CameraAdapter.update() 复制 Three 的矩阵,应用预处理中使用的相同 Y 翻转补偿,计算各轴焦距,并暴露预处理期望的相同接口。这为 three-integration 演示提供了动力,而不会偏离核心管线。

集成点

子系统 用法
预处理 (GaussianPreprocessor) 需要视图/投影矩阵、焦距和相机 Uniforms 来投影 Splat。接受 PerspectiveCameraCameraAdapter 的输出。
渲染器 (GaussianRenderer) 每帧调用 camera.viewMatrix() / projMatrix() 以在绘制前填充相机 Uniform 缓冲。
控制模块 变异 positionV, rotationQ, 或 projection (通过 resize) 并在宿主应用中标记矩阵为脏 (dirty)。
Three.js 集成 CameraAdapter 镜像 PerspectiveCamera 状态,以便核心管线可以在 Three 的渲染循环中运行。

用法

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

const projection = new PerspectiveProjection(
  [canvas.width, canvas.height],
  [deg2rad(60), deg2rad(45)],
  0.1,
  1000,
);
const camera = new PerspectiveCamera(vec3.fromValues(0, 0, -1), quat.create(), projection);

// 匹配视口更改
window.addEventListener('resize', () => {
  projection.resize([canvas.width, canvas.height]);
});

// 将深度范围拟合到点云
camera.fitNearFar(pointCloud.bbox);

// 上传到 GPU
cameraUniforms.setData({
  view: camera.viewMatrix(),
  proj: camera.projMatrix(),
  position: camera.position(),
});

在 Three.js 中使用 CameraAdapter

const adapter = new CameraAdapter();
adapter.update(threeCamera, [canvas.width, canvas.height]);

preprocessor.dispatchModel({
  camera: adapter,
  viewport: [canvas.width, canvas.height],
  // ... 其他参数
}, encoder);

相关文档