Controls API 参考
本参考文档对应 src/controls/ 下的 TypeScript 导出。所有数学运算均使用 gl-matrix 数据类型 (vec2, vec3, quat)。
接口 (Interfaces)
IController
interface IController {
update(camera: PerspectiveCamera, deltaTime: number): void;
processKeyboard(code: string, pressed: boolean): boolean;
processMouse(dx: number, dy: number): void;
processScroll(delta: number): void;
leftMousePressed: boolean;
rightMousePressed: boolean;
userInput: boolean;
resetOrientation?(): void;
getControllerType(): 'orbit' | 'fps';
}
CameraController (轨道) 和 FPSController 都实现了此契约,因此应用程序可以在运行时切换控制器。
类 (Classes)
CameraController
默认使用的轨道控制器。
class CameraController implements IController {
constructor(speed = 0.2, sensitivity = 0.1);
center: vec3;
up: vec3 | null;
amount: vec3; // 为键盘运动保留
shift: vec2; // 右键平移累加器
rotation: vec3; // 偏航/俯仰/翻滚 (yaw/pitch/roll) 累加器
scroll: number; // 对数缩放累加器
speed: number;
sensitivity: number;
leftMousePressed: boolean;
rightMousePressed: boolean;
altPressed: boolean;
userInput: boolean;
resetUp(u?: vec3): void;
processKeyboard(code: string, pressed: boolean): boolean;
processMouse(dx: number, dy: number): void;
processScroll(delta: number): void;
update(camera: PerspectiveCamera, deltaTime: number): void;
resetOrientation(): void;
getControllerType(): 'orbit';
}
resetUp(u)设置轨道参考的上向量(默认为WORLD_UP)。processKeyboard/processMouse/processScroll调用input.ts中的辅助函数,并在处理后设置userInput = true。update运行架构文档中描述的轨道管线,并更新camera.positionV/camera.rotationQ。
FPSController
WASD + 鼠标视角控制器(实验性但已导出)。
class FPSController implements IController {
constructor(moveSpeed?, rotateSpeed?, scrollSpeed?, moveInertia?, rotateInertia?);
moveSpeed: number;
rotateSpeed: number;
scrollSpeed: number;
moveInertia: number;
rotateInertia: number;
flyMode: boolean;
enable: boolean;
leftMousePressed: boolean;
rightMousePressed: boolean;
userInput: boolean;
processKeyboard(code: string, pressed: boolean): boolean;
processMouse(dx: number, dy: number): void;
processScroll(delta: number): void;
update(camera: PerspectiveCamera, deltaTime: number): void;
resetOrientation(): void;
getOrientation(): { yaw: number; pitch: number };
setOrientation(yaw: number, pitch: number): void;
setFlyMode(enabled: boolean): void;
getControllerType(): 'fps';
}
FPSController 监听文档级别的按键事件(在其构造函数中),并保持 yaw/pitch 角度以及用于惯性的速度向量。flyMode = false 将移动限制在 XZ 平面上。
输入辅助函数 (input.ts)
processKeyboardInput(code, pressed, amount, rotation, sensitivity)
原地更新 amount (vec3) 和 rotation (vec3) 数组。处理 KeyW/A/S/D, Space, ShiftLeft, KeyQ, KeyE。当识别到按键时返回 true。
processMouseInput(dx, dy, leftPressed, rightPressed, rotation, shift)
将鼠标增量添加到 rotation(左键)或 shift(右键)。如果有任何按钮处于活动状态,则返回 true。
processScrollInput(delta)
缩放滚轮增量(默认倍数为 3)并返回用于累加的值。
轨道数学 (orbit.ts)
常量
WORLD_UP = vec3(0, 1, 0)MIN_POLE_ANGLE = 5°MIN_DISTANCE = 0.1MAX_DISTANCE = 1000EPS = 1e-6
函数
lookAtW2C(forwardWorld: vec3, upWorld: vec3): quat;
projectOntoPlaneNormed(v: vec3, n: vec3, fallback: vec3): vec3;
calculateOrbitBasis(cameraPos: vec3, center: vec3, orbitUp: vec3)
=> { forward: vec3, right: vec3, yawAxis: vec3 };
applyDistanceScaling(cameraPos, center, scroll, deltaTime, speed): number;
applyPanning(center, shift, right, yawAxis, deltaTime, speed, distance): void;
applyRotation(forward, right, yawAxis, yaw, pitch, roll)
=> { forward: vec3, right: vec3, yawAxis: vec3 };
applyDecay(rotation: vec3, shift: vec2, scroll: number, deltaTime: number)
=> { rotation: vec3, shift: vec2, scroll: number };
这些函数是无状态的;控制器传入临时向量并重用结果。
使用片段
import { CameraController } from 'src/controls';
import { PerspectiveCamera } from 'src/camera';
const controller = new CameraController(0.25, 0.12);
const camera = PerspectiveCamera.default();
function frame(dt: number) {
controller.update(camera, dt);
renderer.prepareMulti(encoder, queue, [pointCloud], { camera, viewport: [w, h] });
}
鼠标/键盘连接(简化版):
window.addEventListener('keydown', (e) => controller.processKeyboard(e.code, true));
window.addEventListener('keyup', (e) => controller.processKeyboard(e.code, false));
canvas.addEventListener('mousemove', (e) => controller.processMouse(e.movementX, e.movementY));
canvas.addEventListener('wheel', (e) => controller.processScroll(e.deltaY));
参见 fps-controller.ts 了解具有惯性和 6自由度 (6DoF) 飞行控制的替代设置。