Skip to content

Added model bevel‑edge highlighting and precise picking module 新增模型斜棱线高亮与精确拾取模块 - #113

Merged
PigeonNian merged 1 commit into
Anvil-Dev:dev/1.21.1from
WhereisFff:fff/1.21.1-cube
Sep 7, 2026
Merged

Added model bevel‑edge highlighting and precise picking module 新增模型斜棱线高亮与精确拾取模块#113
PigeonNian merged 1 commit into
Anvil-Dev:dev/1.21.1from
WhereisFff:fff/1.21.1-cube

Conversation

@WhereisFff

Copy link
Copy Markdown
Contributor
  • 新增独立 cube 模块,接入 Gradle 工程、CI 模块清单与砧库聚合包
  • 提供按命名空间启用及按方块排除的客户端 API,默认同时启用模型轮廓与精确拾取
  • 支持父模型继承、cube 旋转与缩放补偿、反向描边壳、根变换、随机变体及 multipart 状态组合
  • 提取公共凸体几何、BVH 射线查询和并集棱线算法,去除内部棱线与共享接缝并合并共线线段
  • 按几何内容去重,不同整体朝向共享基础几何与轮廓,分离世界位置以保持大坐标下的绘制精度
  • 接管准星方块射线,使其穿过模型空隙并发现邻格伸出部件,保留实体距离比较、流体选取及普通射线行为
  • 提供可选 BER 部件接口,复用局部几何并通过姿态矩阵同步拾取与高亮
  • 使用单线程后台生成轮廓,限制任务数量、计算工作量、缓存占用和绘制线段数量,超预算时采用轻量回退
  • 在资源重载和退出世界时清理缓存与任务,阻止过期结果写入新缓存
  • 更新中英文 README,补充模块功能与接入说明

- 新增独立 cube 模块,接入 Gradle 工程、CI 模块清单与砧库聚合包
- 提供按命名空间启用及按方块排除的客户端 API,默认同时启用模型轮廓与精确拾取
- 支持父模型继承、cube 旋转与缩放补偿、反向描边壳、根变换、随机变体及 multipart 状态组合
- 提取公共凸体几何、BVH 射线查询和并集棱线算法,去除内部棱线与共享接缝并合并共线线段
- 按几何内容去重,不同整体朝向共享基础几何与轮廓,分离世界位置以保持大坐标下的绘制精度
- 接管准星方块射线,使其穿过模型空隙并发现邻格伸出部件,保留实体距离比较、流体选取及普通射线行为
- 提供可选 BER 部件接口,复用局部几何并通过姿态矩阵同步拾取与高亮
- 使用单线程后台生成轮廓,限制任务数量、计算工作量、缓存占用和绘制线段数量,超预算时采用轻量回退
- 在资源重载和退出世界时清理缓存与任务,阻止过期结果写入新缓存
- 更新中英文 README,补充模块功能与接入说明
@Gugle2308

Copy link
Copy Markdown

⚠️ Dangerous command requires approval:

cd /tmp && python3 -c "
import zipfile
z = zipfile.ZipFile('nf111-sources.jar')
names = z.namelist()
print('total:', len(names))
print([n for n in names if 'BlockGetter' in n or 'LevelRenderer' in n o...

Reason: script execution via -e/-c flag

Reply /approve to execute, /approve session to approve this pattern for the session, /approve always to approve permanently, or /deny to cancel.

@Gugle2308

Copy link
Copy Markdown

🌿 Roseau API Breaking Change Report

Module Status Breaking Changes
codec ⚪ Skipped
collision ⚪ Skipped
config ✅ Compatible 0
integration ✅ Compatible 0
moveable-entity-block ⚪ Skipped
network ✅ Compatible 0
rendering ⚪ Skipped
space-select ⚪ Skipped
font ✅ Compatible 0
util ⚪ Skipped
explosion ⚪ Skipped
rpc ⚪ Skipped
multiblock ⚪ Skipped
recipe ⚪ Skipped
registrum ⚪ Skipped
sync ⚪ Skipped
wheel ⚪ Skipped
main ⚪ Skipped

Full CSVs: see the Artifacts section of this workflow run.

@Gugle2308

Copy link
Copy Markdown

⚠️ Dangerous command requires approval:

cd /tmp && mkdir -p nfud2 && python3 -c "import zipfile; zipfile.ZipFile('/tmp/nf-userdev.jar').extractall('/tmp/nfud2')" 2>&1 | head -3; ls /tmp/nfud2 2>/dev/null | head; find /tmp/nfud2 -name "*Bloc...

Reason: script execution via -e/-c flag

Reply /approve to execute, /approve session to approve this pattern for the session, /approve always to approve permanently, or /deny to cancel.

@PigeonNian
PigeonNian merged commit b814337 into Anvil-Dev:dev/1.21.1 Sep 7, 2026
60 of 64 checks passed
@Gugle2308

Copy link
Copy Markdown

PR #113 的状态为 closed"state": "closed"),本次 webhook 触发事件是 PR 关闭。

按约束第 1 条「如果操作是 closed 或 labeled,stop here,不要发布评论」及 webhook-pr-review.md 验证清单:「closed / labeled → 停止,不发任何评论」,本次审查到此为止,不输出审查意见、不发布评论。

@Gugle2308

Copy link
Copy Markdown

代码审查摘要 — PR #113

操作: opened
范围: 39 个文件 (28 Java, 33 新增, 0 删除) / 2345 行 diff
模块: module.cube — AnvilLib 新客户端模块(模型轮廓高亮 + 精确拾取),接入 settings.gradle / modules.json / module.main jarJar

🔴 关键问题

  • CubeModelDecoder.java:963-974 — 旋转 origin 未除以 16,旋转中心偏移 16 倍(高置信) — box 坐标做了 /16.0 转方块单位,但 rotation.origin() 直接以像素值使用(JSON 中 origin 是 016 像素,如门/活板门的 [8,8,8][0,3.5,8])。vanilla FaceBakery 在同一坐标系中处理 from/to 与 rotation origin,而这里顶点是 01 空间、旋转中心却是 0~16 空间 → 带元素级旋转的模型(门、活板门、藤蔓、按钮、铁轨等)几何整体错位:大部分旋转后越出 [-2,3]supportedBounds 拒绝 → 静默降级为原版拾取(模块"支持 cube 旋转"的声称对这批方块失效);未越界的则会产生完全错误的拾取面/轮廓。修复:origin 也乘 1.0/16。建议启用任意命名空间后放置门/活板门做冒烟验证。

  • SelectionPart.java:914-918 — 法线"逆转置"实际是普通逆矩阵 — 注释声称用逆转置,但代码 inverse.m00()*nx + inverse.m01()*ny + inverse.m02()*nz 计算的是 M⁻¹·n;逆转置应为 (M⁻¹)ᵀ·n,即 m00*nx + m10*ny + m20*nz(索引交换)。对纯旋转二者等价(所以旋转部件看起来正常),但对非均匀缩放rescale、PR 声称支持的缩放补偿路径)及镜像变换,法线不再垂直于变换后的表面 → Direction.getNearest 给出的点击面/放置朝向错误。

⚠️ 警告

  • ModelSelection.java(Weighted.collect) — 随机变体选择与渲染不一致 — 用 Math.abs((int) random.nextLong()) % totalWeight,而 vanilla WeightedBakedModel/WeightedRandom 消费 nextInt(totalWeight) 的随机流。两者由同一 state.getSeed(pos) 派生但选择结果不同 → 拾取/轮廓选中的变体可能与画面显示不同(草丛/花/甘蔗等多变体方块)。同理 Multipart.collectrandom.nextLong() 派生种子让各 part 独立,也与 vanilla 逐 selector 顺序消费同一 RandomSource 不同。建议改为与 vanilla 完全一致的随机消费方式(或对 weighted/multipart 直接用各变体并集几何做拾取,避免随机同步问题)。
  • GameRendererMixin.java:2165 — mixin 目标签名需运行时验证 — target pick(Lnet/minecraft/world/entity/Entity;DDF) 为 3 参。若 1.21.1 的 GameRenderer.pick 实为 4 参(含 boolean fluids),defaultRequire=1 会在客户端启动时直接 MixinApply 崩溃。请确认实际签名(本模块 6 个 client mixin 均为 required:true,建议至少一次真实客户端启动验证准星行为)。
  • CubePicking.java:559-579 — 邻域补扫的最坏开销 — 射线每经过一格做 (2r+1)³(r 最大 2 → 125)次 getBlockState + extendsBlock 检查。命名空间启用后长射线每帧可达数千次块状态查询。有 visited 去重与帧缓存兜底,仍建议实测;r 较大时考虑先用伸出部件的 AABB 与射线做粗略相交预筛。

💡 建议

  • CubeModelDecoder.java:969-970 — rescale 的 scale 仅在 |angle| 恰为 22.5/45 时正确,其余角度一律按 45° 处理(1/cos(π/4));且 scale→rotate 与 vanilla 的矩阵顺序需对照确认(rescale 元素少,建议自测如红石中继器类模型)。
  • ModelCapture.remember — 模型烘焙在主线程单线程进行,synchronized + static IdentityHashMap 可简化或注明原因;take()ModifyBakingResult(LOWEST) 与 BakingCompleted 之间暂存,若中间抛异常 pending 会残留(低概率,可 try/finally 复位)。
  • CubeSelection.enableNamespaceResourceLocation.fromNamespaceAndPath(...) 仅作字符校验,用法略隐晦;且 exclude(Block) 需在模型烘焙前调用(烘焙后调用只影响拾取、不影响已生成的轮廓)。建议在 javadoc/README 注明注册时序。
  • 几何类包位置client/modelclient 引用了 ClientLevel 等客户端类,模块主类 AnvilLibCube@OnlyIn;作为库模块,建议在文档注明这些 API 只能在客户端逻辑调用,避免下游在服务端误触导致 NoClassDefFoundError

🟢 看起来不错

  • OutlineCache 预算设计成熟:单线程 daemon 低优先级执行器、8 任务上限、16MB pending / 4MB ready 字节预算、epoch 防过期写入、队列满回退轻量轮廓、LRU 淘汰时同时释放几何引用(key 强引用已计入预算)——干净且自洽。
  • 拾取架构正确BlockGetterMixin 将超出当前格的命中置空留给邻格 + CubePicking radial 补扫处理伸出部件的互补设计,避免"伸出部件遮挡后格"与"空隙误命中";ThreadLocal Context + try/finally + 重入回退到 vanilla 的防护完整。
  • 并集棱线算法(岛屿检测避免跨分量伪接缝、暴露面采样判可见、共线合并)实现细致;大坐标精度处理(双精度减相机后再入 PoseStack、缓存不持世界坐标)正确。
  • 几何去重共享ModelSelections.shared 按 shapes 列表 intern + OutlineCache 以 geometry 为键)与 16MB/32k states/256 帧缓存等上限设置合理。
  • Gradle/CI/聚合包集成完整(settings、modules.json、module.main 两条 jarJar 分支、.gitignore 本地测试门控),README 双语更新到位。

📋 声称验证表

声称 状态 说明
独立 cube 模块接入 Gradle/CI/聚合包 settings.gradle / modules.json / module.main jarJar
按命名空间启用 + 按方块排除客户端 API enableNamespace / exclude / registerDynamic
父模型继承 BlockModel.getElements 展开父模板(建议冒烟确认 cube_all 类方块被捕获)
cube 旋转与缩放补偿 ⚠️ 实现存在,但 origin 未 /16 使旋转错位(P1)
反向描边壳/反向 from-to ConvexShape.box 对无序 AABB 顶点集不变,几何正确
随机变体 / multipart 状态组合 ⚠️ 结构与实现完整,但随机消费与渲染不一致
公共凸体几何 + BVH 射线 + 并集棱线算法 ConvexShape / SelectionGeometry / OutlineBuilder
去内部棱线/共享接缝 + 共线合并 isVisibleEdge + mergeSegments
按几何内容去重、分离世界位置 intern + PackedOutline 无世界坐标
接管准星射线、保留实体/流体/普通射线 仅 redirect GameRenderer.pick 内 Entity.pick,范围>64 与重入均回退
BER 部件接口(BlockSelectionProvider) 姿态矩阵同步拾取与高亮、bounds 校验 [-2,3]
单线程后台轮廓 + 预算 + 轻量回退 100ms / 100 万次操作 / fallback
重载与退世界清理、防过期写入 epoch + cancel + clearWorld
README 中英文更新 双语模块说明

结论: REQUEST_CHANGES — 代码质量与架构设计整体很高,但两个数学错误直击核心声称:旋转 origin 单位错配(16 倍偏移,使"旋转 cube 支持"大面积失效或产生错误几何)与法线变换缺转置(非均匀缩放部件的面朝向错误)。修复这两处并补充一次真实客户端冒烟验证(门/活板门等旋转模型的轮廓与拾取、加权变体一致性)后即可合并。

🧪 测试建议

被测目标 推荐测试场景 优先级
CubeModelDecoder.decode 带元素旋转(origin≠0、22.5°/45°、rescale)的模型:几何与视觉对齐 🔴
SelectionPart.clip 非均匀缩放+旋转部件的命中面法线(朝向 Direction 正确) 🔴
ModelSelection.Weighted.collect 多变体方块拾取/轮廓与渲染变体一致 🟡
CubePicking.pick 伸出邻格部件命中、实体更近优先、空隙穿透不误中后格 🟡
OutlineCache 超预算回退、资源重载期间无过期结果写入、退世界线程干净退出 🟡

由 Hermes Agent 审查

@Gugle2308

Copy link
Copy Markdown

💾 Self-improvement review: Patched SKILL.md in skill 'minecraft-mod-pr-review' (1 replacement).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants