CameraPoseAdjuster
相机位姿调整器:相机没有特殊设计,宿主默认位姿刚好直视轨道,调整器直接控制位置 / 旋转 / FOV。链式语义、异常隔离、确定性契约与 TrackPoseAdjuster 同款。在 onPreInit 内经 ctx.registries().cameraPoseAdjusters() 注册。
方法速览
| 方法 | 用途 |
|---|---|
adjust(CameraPose, GameplayContext) | 每帧原地修改相机位姿 |
完整签名
public interface CameraPoseAdjuster {
void adjust(CameraPose pose, GameplayContext ctx);
}adjust(CameraPose pose, GameplayContext ctx)
签名:
void adjust(CameraPose pose, GameplayContext ctx);行为:每帧在相机 enter 点调用一次,pose 是宿主复用的可变对象,输入为本帧当前相机位姿:
- 未接管(未调用
GameStateAccess#setCameraPose):输入是宿主默认位姿(直视轨道推导)。setTrackTilt3D/ 谱面track_tilt的倾斜在未接管时已归一进位姿的 pitch 与位置分量;fovDeg通常为FOV_AUTO。 - 已接管:输入是
setCameraPose写入的绝对位姿;此时轨道 tilt 不再归一进 pitch(宿主把它作为内容旋转V = V_pose · R_content单独合成),CameraPose只承载视点位姿。
调整器原地修改后,宿主读取链尾值写回相机状态。写入链尾不会改变「相机接管」标志:接管只由 GameStateAccess#setCameraPose 建立、由 setCameraPoseAuto() 或倒带 / 新谱面复位清除;链每帧从当前输入重新执行,不保存上一帧的改写结果。
- 无注册者快速路径:注册表为空时宿主直通,渲染逐位不变。
- 异常隔离:单个调整器抛异常时该帧被跳过并限频告警,链继续。
- 禁跨帧持有:不得保存
pose引用跨帧使用;跨帧状态按 τ 重建。 - 纯视觉:判定引擎零消费。
确定性契约与 TrackPoseAdjuster 完全同款:禁随机 / 禁墙钟(时间取 ctx.musicTimeMs())/ 禁网络 / 禁跨帧可变共享态写入;输出位姿只由入参与本模组按 τ 重建的纯函数状态决定。违反的表现是「倒带后相机与首演不一致」。
与旧文档的差异:旧版本称「写相机后宿主
setTrackTilt3D通道让位(相机位姿 > tilt)」。宿主现行实现中,接管标志只由setCameraPose/setCameraPoseAuto迁移,adjuster 链的写回不改标志;且自 2026-10-11 起接管期间 tilt 不再被丢弃,而是作为内容旋转与相机位姿正交合成。
示例(在宿主推导的 FOV 上叠加呼吸):
@Override
public void onPreInit(ModContext ctx) {
ctx.registries().cameraPoseAdjusters().register(
RegistryKey.of("my_mod", "fov_pulse", CameraPoseAdjuster.class),
(pose, gameplayCtx) -> {
double base = pose.isFovAuto() ? 70.0 : pose.getFovDeg();
double t = gameplayCtx.musicTimeMs() / 1000.0;
pose.setFovDeg(base + Math.sin(t * 3.0) * 4.0);
});
}线程:宿主在每帧渲染的相机 enter 点调用(渲染线程,单线程同步)。
生命周期:onPreInit 注册,装配冻结后永久生效。
稳定性:2026-10-11 新增(2.0 起):2.x 内只增不破。