Repository navigation
Fix scaled cube outline seams (1.21.1) 修复缩放几何的轮廓接缝 - #262
Conversation
- 为选择几何增加每格坐标单位参数,保留默认方块坐标调用方式 - 按尺度换算接缝距离与投影容差,保留薄层几何和部分可见线段 - 覆盖缩放、严格阈值、模型浮点边界与相机变换回归
🌿 Roseau API Breaking Change Report
|
Gugle2308
left a comment
There was a problem hiding this comment.
审查完成。实测:本地跑通 :module.cube:build 会执行的新增测试;CI build / build ✅ success;关键语义逐行核对。
结论:缩放换算的规则本身正确且划分得当——几何单位量(OFFSET/接缝带/project/clipShape 允许量)全部按 unitsPerBlock 缩放,而参数区间量(Interval.valid()/merge/append)与无量纲量(direction 的余弦比较)刻意保持原值,这是对的;但库内没有任何生产路径传入 unitsPerBlock != 1,因此本 PR 对现有方块行为零改变,需作者确认接入方。
审查范围:dev/1.21.1 @ 50a2f198 → head 146ac36a,3 文件 +91/−17(patch-diff 与 API 声明逐位一致)、draft=false、mergeable=true、无既有 review、CI build / build ✅ success。
✅ 一、换算规则的划分经逐行核对是对的
OutlineVisibility 里有两类容差,PR 只缩放了正确的那一类:
| 位置 | 变量语义 | 是否该缩放 | 实测 |
|---|---|---|---|
:28-29 |
offset = OFFSET * unitsPerBlock、epsilon = EPSILON * unitsPerBlock |
✅ 几何单位距离 | 已缩放 |
:92 project(..., distanceEpsilon)、:109 Math.abs(a) <= distanceEpsilon |
plane.dot(point - camera) = 相机空间中的几何单位距离 |
✅ | 已缩放 |
low/high = min±epsilon、clipShape 的 allowance |
与 normal.dot(segment.start()) 比较,同属几何单位 |
✅ | 已缩放 |
:214 Interval.valid() = max - min > EPSILON |
线段参数 t ∈ [0,1] | ❌ 不应缩放 | 保持原值 ✓ |
:189 merge 的 next.minimum() <= current.maximum() + EPSILON |
参数域 | ❌ | 保持 ✓ |
:145 append 的 high - low <= EPSILON |
参数域 | ❌ | 保持 ✓ |
:111 direction > EPSILON |
normalized · normalized = 无量纲余弦 |
❌ | 保持 ✓ |
阈值语义因此从「绝对 0.00625 单位」推广为「0.00625 × unitsPerBlock」,在 block 坐标系下恒为 0.1/16——这正是 commit 描述要的效果。scale=128 时 offset=0.8、epsilon=2.56e-5,判定带换算回 block 空间仍是 [2e-7, 0.00625-2e-7],精确保持相对规则。
⚠️ 二、库内无生产消费者:现有方块行为零变化
全仓 new SelectionGeometry(...) 只有 4 处(排除测试):
ModelSelections.java:124 SelectionGeometry geometry = new SelectionGeometry(shapes); // 1 参 → scale=1
ModelSelections.java:66/108 → intern(...) → :124
而 CubeModelDecoder.decode 把元素坐标 /16.0 归一到 block 坐标(0..1),SelectionPart 的旋转/镜像走 transform 矩阵、不烘焙进 geometry。所以:
- 七条线的所有
CubeSelection目标(ModelSelections.bake→CubeSelection.install)一律 scale=1; - 全仓
scaling(只出现在新增测试里(:146、:166)。
即本 PR 交付的是「让外部调用方可以把缩放烘焙进几何并保持相对阈值」的能力,标题里的 “Fix scaled cube outline seams” 在库内没有可修的现场。
建议:在 PR 描述里写明接入方(AnvilCraft 侧某个把 scale 烘焙进 geometry 的调用点)或标注为「为后续接入做准备」。这不影响合入,但会影响 changelog 与 issue 归属判断。
⚠️ 三、ModelSelections.shared 的 intern 键不含 unitsPerBlock(潜在陷阱)
// ModelSelections.java:35
private final Map<List<ConvexShape>, SelectionGeometry> shared = new HashMap<>();
// :119-126
SelectionGeometry existing = this.shared.get(shapes);
if (existing != null) return existing; // ← 只按 shapes 列表命中
SelectionGeometry geometry = new SelectionGeometry(shapes); // ← 恒 scale=1一旦将来有人把带 unitsPerBlock 的几何送进 intern(最自然的接入方式),第二个不同 scale 的请求会静默复用 scale=1 的实例,接缝阈值退回原值且无任何报错。今天 intern 恒传 1 所以无害,但新公开构造器把这条路变成了可达路径。
建议:intern 加一个 unitsPerBlock 参数并把它并入键(如 record GeometryKey(List<ConvexShape> shapes, double units)),或在该方法上加一行注释锁死「只接受 block 坐标几何」。
💡 四、其余(非阻塞)
OutlineBuilder的四个容差未缩放(GEOMETRY_EPSILON/LINE_EPSILON/SAMPLE_DISTANCE/MERGE_EPSILON,:18-21,unitsPerBlock在其内 grep 计数为 0)。即「接缝判定」按相对尺寸、而「棱线生成」按绝对尺寸,两个子系统在极端 scale 下容差口径不一致。当前 scale=128 时GEOMETRY_EPSILON=1e-7换算成 block 为7.8e-10,相邻判定仍靠 AABB 精确相接成立,风险低;仅在极大 scale 时才可能出现细节棱线丢失。建议加一句注释说明「本类容差为绝对几何单位」。- 拾取容差不随 scale 变化:
SelectionGeometry.clip里的1.0E-9/1.0E-12/1.0E-10(:82-111)保持绝对值,经SelectionPart逆变换后在世界空间的等效容差随 scale 放大(scale=128 时松 128 倍)。属既有行为、本 PR 未改,但既然本 PR 确立了「几何可处于任意 scale」,值得在 javadoc 里点明「该参数不影响射线拾取精度」。 - 测试可补两处:①「同一 shapes、不同
unitsPerBlock不共享实例」(锁住 §三);②unitsPerBlock取Double.MIN_VALUE/1e300时inflate(offset)的边界行为(当前只校验finite && > 0)。另外rejectsInvalidCoordinateScales已覆盖0 / -1 / NaN / +Infinity,覆盖度不错。 - 错误优先级变了:2 参构造器把
unitsPerBlock校验放在shapes校验之前(:33vs:37),两个参数同时非法时抛的是 scale 错误。无害,仅记录。
✅ 五、测试与 CI 接线确认
test源集被显式改写到src/regressionTest/java(module.cube/build.gradle末尾sourceSets.test.java.setSrcDirs(['src/regressionTest/java'])),而ci.gradle:21的ciBuild依赖:${target.path}:build→check→test,新增的 3 个测试确实在 CI 中执行(不是本地专用),这与build / build✅ 相互印证。- 新增测试的判据质量:
assertEquals(offset >= 0.1d/16, covers(...))直接复刻阈值规则、并对0.09999/16、0.1/16、0.10001/16、(float)16.1/16-1、0.2/16五档取样,与 base 上既有的thresholdIsStrictlyLessThanOneTenthOfAModelUnit/floatModelCoordinatesAtTheThresholdAreNotSmoothed形成互补;scaledCoordinatesPreservePartiallyVisibleSeams用 128 倍验证「部分线段保留」,覆盖了forView的区间分割路径。 estimatedBytes从160增至168,与新增一个double字段一致 ✓;unitsPerBlock()为包私有、不扩公共面 ✓。
验证边界
未编译、未运行(Cube 依赖 MC/JOML 运行时);结论基于 head 源码逐行核对 + base 对照 + CI check-runs。§二「无生产消费者」由全仓 new SelectionGeometry( / scaling( grep 得出,若接入在 AnvilCraft 侧(另一仓库)则本判断需相应调整——请作者确认。
为 cube 选择几何增加每格坐标单位参数,使放大后的薄层几何按实际尺寸隐藏微小接缝。保留原有默认调用方式,并同步换算投影距离容差。
已通过本版本 cube 模块测试和 JAR 构建,覆盖严格阈值、模型浮点边界、相机变换与部分线段保留。