AI 参与说明(Agent:Grok / Grok Bot):本文对照公开仓库 OpenGemCutting 的 tag
v1.1.1(commit1b76273882a9f1daeda6ce36d592b926d45c22f1,提交时间 2026-09-12 +08)源码与docs/契约文档整理。资料整理于 2026-09-14。运行记录:模型标识与 reasoning effort 未取得完整运行记录;执行入口为 Blog 助手的 Grok Bot executor。文中区分源码/官方文档已证实的事实与工程归纳;未实测真实切磨收益,也未把 Live Demo 与源码版本强行等同。
https://github.com/yuyou-dev/OpenGemCutting
OpenGemCutting(产品线标识 SUVA · FACET 96)是浏览器本地优先的参数化宝石琢型工作台:同一份设计可由人手在网页编辑,也可经可选本地 MCP 由对话式 Agent 预览与提交。它不是通用三维建模器,也不是生产级光学计量工具。
核心结论可以先记四条:
- 双视口分工明确:工程编辑视口用 p5(
WEBGL模式)画几何与 CUT 机械臂;光学仿真视口用原生 WebGL2 做材质与光线相关显示。 - 几何真值在 domain/mesh:切割是确定性半空间裁切;mesh 原石走保孔洞的索引内核,不以凸包偷偷替换凹槽与通孔。
- 人工与 MCP 共用 application → domain:文档与撤销历史的唯一 owner 是网页侧
WorkbenchEditor;MCP 不另建第二套 CUT 会话或持久化库。 - 导出格式按职责拆分:JSON 是完整主文件;PDF 服务阅读与沟通;ASC 交换最终有效切面,并显式预检信息损失。
| 英文术语 | 中文名称 | 简要解释 |
|---|---|---|
| CUT | 切割工序 / 切层 | 一条带行业角、深度、分度与对称参数的参数化切割;完整序列称 CUT STACK |
| CUT STACK | 切割栈 | 已提交的参数化工序列表;被后续覆盖的层仍保留,便于撤销后恢复 |
| Mesh | 网格实体 | 由顶点与面片描述的闭合材料边界;可含凹槽与孔 |
| Meet | 会合构造 | 用已有顶点或棱上比例点求解深度(及双点时的角度)的定位方式 |
| Jump | 候选跳转 | 在可解会合候选之间浏览,再原子应用角度/深度 |
| MCP | Model Context Protocol | 可选本地协议入口;工具语义与网页共用同一套设计契约 |
| ASC | GemCad ASCII | 与 GemCad 交换最终有效切面的文本格式,不是完整项目格式 |
| Index wheel | 分度盘 | 本项目固定 96 齿;显示上 96 与 0 等价 |
| Optical Lab | 光学实验室 | 独立页面入口;当前仅为空白骨架,实验工具尚未实现 |
| localStorage | 浏览器本地存储 | 按 origin 隔离的项目库;草稿与撤销历史不跨刷新自动恢复 |
技术栈与仓库分层
package.json(v1.1.1)声明:
| 层 | 选型 | 作用 |
|---|---|---|
| UI | React 19.2.0 + React DOM | 主页、工作台、对话框与页面 chrome |
| 构建 | Vite 6.4.3 + @vitejs/plugin-react | 开发服务与 dist/client 静态构建 |
| 工程视口 | p5 ^2.3.2 | GemViewport 动态 import("p5"),createCanvas(..., WEBGL) |
| 光学视口 | 原生 WebGL2 | OpticsViewport / meshTechnicalRenderer 直接 getContext("webgl2") |
| 报告 | pdf-lib + @pdf-lib/fontkit | A4 矢量技术报告与可搜索中文字体 |
| 图标 / 字体 | Tabler Icons、Noto Sans SC、IBM Plex Mono | 界面与等宽参数显示 |
| 运行时 | Node ^20.19.0 || >=22.12.0 | npm run dev / build / check / check:mcp |
可选对话能力在仓库的 mcp/ 目录独立维护依赖;根目录安装与静态 Pages 构建不要求安装 MCP。README 的依赖关系可以概括为:
src/domain + src/application → 同一套几何与设计规则
↑ ↑
浏览器手动编辑 可选本地 MCP
flowchart TB
UI["React UI / WorkbenchEditor"] --> AppLayer["application 设计操作"]
MCP["可选 MCP server"] --> AppLayer
AppLayer --> Domain["domain 文档 / CUT / Meet"]
Domain --> Mesh["domain/mesh 平面裁切内核"]
UI --> EngVP["GemViewport · p5 WEBGL"]
UI --> OptVP["OpticsViewport · WebGL2"]
Domain --> Persist["projectLibrary · localStorage"]
Domain --> Export["JSON / PDF / ASC"]
本地启动(官方 README):
git clone https://github.com/yuyou-dev/OpenGemCutting.git
cd OpenGemCutting
git checkout v1.1.1 # 或等价 commit 1b76273
npm ci
npm run dev
npm run build 产出独立前端 dist/client/;GitHub Pages 使用 npm run build:pages。完整工程门禁是 npm run check;加上 MCP 时用 npm run check:mcp。
双视口:工程几何 vs 光学显示
Engineering viewport and optical viewport do not share one renderer. 工程视口要服务 CUT 机械臂、分度盘、Meet 标记与正交预览;光学视口要服务折射率、色散、Fresnel 与多次内反射一类的显示参数。二者读取的是同一份当前可见实体,但绘制管线分离。
| 视口 | 实现入口 | 图形 API | 典型内容 |
|---|---|---|---|
| 工程编辑 | src/components/GemViewport.jsx | p5 WEBGL | 实体/X-ray、切割平面、Gizmo、正交缩略图数据源 |
| 光学仿真 | src/components/OpticsViewport.jsx | 原生 WebGL2 | 材质预设、观察位、检查器;无 WebGL2 时明确提示 |
| 技术预览辅助 | meshTechnicalRenderer.js | 原生 WebGL2 | mesh 技术线框/深度缓冲类绘制 |
画布左上的视口模式切换组在 编辑 / 切割助手 / 光学仿真 之间互斥切换。切割助手与光学仿真都会挂起/恢复编辑现场,但只读,不提交草稿、不写入撤销历史。Escape 退出当前模式并恢复进入前的 CUT 会话对象。
独立页面 Optical Lab(OpticalLabPage.jsx)目前只提供导航、当前项目名和「实验工具准备中」空态;README 与状态契约均写明:独立光学实验室仍为开发中入口。光学仿真的主入口在编辑画布模式切换组,不要把空白实验室页理解成已交付的实验平台。
几何原理:确定性平面裁切与保孔 Mesh
Facet 96 的分度常量在 src/domain/faceting.js:
INDEX_TEETH = 96DEGREES_PER_TOOTH = 360 / 96- 显示上 index
96是0的别名
一条 CUT 把行业角、深度、基分度、重复与镜像展开为一条或多条裁切平面,再按序作用于初始晶体(document.stock)。最终实体是派生结果,不是另一份可漂移的“手工网格”。
Mesh 内核(src/domain/mesh/,注释标明改编自 gemcut-core 实验内核,MIT)对多面体做半空间裁切:
- 计算顶点相对平面的有符号距离(带容差归零)。
- 保留内侧顶点,在跨平面边上插值交点。
- 重建截面边界环;非凸预览路径用 earcut 三角化截面,并在环归属中保留 holes。
- 写入带稳定 face id 的封口面片,再压缩未使用顶点。
docs/cut-performance.md 与状态契约写明:
- 旧 cube 来源:预览可用共享索引裁切;提交、Meet 来源与助手重放仍走原顺序精确核。
- mesh 项目:预览与保存共用保孔洞的索引内核;错误阻断该草稿并允许拖回,不以凸包替代凹槽/通孔。
因此,“确定性”指同一输入平面序列应得到同一拓扑结果;“保孔”指截面三角化显式处理外环与内孔,而不是把通孔实体偷偷凸化。导入 OBJ 初始晶体另有资源预算(例如源多边形与分解后面片上限),见 docs/limits.md。
flowchart TB
Stock["stock:cube 或 mesh 原石"] --> Planes["按序展开 CUT 平面"]
Planes --> Clip["mesh.cut / 半空间裁切"]
Clip --> Solid["派生实体 displaySolid"]
Solid --> Eng["工程视口 / 正交预览"]
Solid --> Opt["光学仿真"]
Solid --> Report["PDF / 有效面统计"]
Planes --> Stack["CUT STACK 仍保留完整参数层"]
CUT 业务流程
CUT 会话只有四态:idle / create / edit / group(实现见 src/domain/cutSession.js)。Meet / Jump 是新建或编辑中的构造子状态,不是第五态。
| 阶段 | 行为 | 是否入撤销历史 |
|---|---|---|
| 浏览 / 选层 | 恢复已保存参数与构造,不改实体 | 否 |
| 调参预览 | 草稿派生未保存实体;helper 与实体必须同一版草稿 | 否 |
| Meet / Jump | 会话内求解深度/角度;锁定后写入构造 metadata 需待提交 | 否 |
| 保存 CUT | 经统一提交门禁写入文档命令 | 是(一条历史) |
| 群组变换 | ΔZ、高度比例、整数齿旋转一次预览、一次提交 | 是 |
| 切割助手回放 | 只读重放已提交序列 | 否 |
| 光学仿真进出 | 只改视图态 | 否;材质修改若走文档命令则入历史 |
提交前评估(状态契约)大致分为:零有效面/仅接触可定位但禁止提交;普通冠/亭部分消面可提交并提示;整层消失需显式确认;结构层失效或实体为空则硬阻断。确认后的提交与普通提交一样只产生一条文档历史。
CUT STACK 保存完整参数化工序;被后续层完全覆盖的工序不得从文档删除。最终有效面从完整实体派生,因此撤销或移除覆盖层后,早先工序的面可以自动恢复。面数、切割指令、ASC 与 PDF 面表只消费最终有效面;JSON 继续保存完整栈。
MCP 与人工:同一套业务规则和撤销历史
docs/mcp/architecture.md 给出边界:
- MCP 只处理协议、静态服务和请求关联,不拥有当前文档、不复制几何算法。
- 参数与工具语义的唯一注册表在 application 层设计契约;服务端直接导入,不复制 schema。
- 批量计划是绑定当前 revision 的临时计算快照,不是第二套 CUT 会话,不写 JSON/项目存储。
- 网页用原生 WebSocket;只有
127.0.0.1上含显式连接片段的启动链接才建连。普通静态页不尝试连接、不加载 Node SDK。
人工保存 CUT 与自动化批量提交共用同一套提交准备逻辑(如 preparePatternCommit);群组变换共用同一 transformGroup。文档写入要求当前 projectId 与不透明 revision;手动编辑、撤销、会话变化或页面重挂载会使旧计划失效。有活动手动草稿时,能力约束会阻断外部写入,MCP 不会自动取消设计师的草稿。
The workbench remains usable without Codex, MCP, accounts, or API keys. AI 是可选创作入口,不是运行前提。
持久化:localStorage 项目库
项目库实现于 src/domain/projectLibrary.js,键前缀为 facet96:project:v1:,经 localStorage 读写,并可用 navigator.locks 做同名项目的读写互斥。
已核实的行为边界:
- 自动保存只写入已提交文档及物理材质/计算参数;默认合并写入,页面隐藏/切换时冲刷。
- 不跨刷新恢复:未保存 CUT/群组预览、相机、VIEW ONLY 参数与旧撤销历史。
- 按浏览器 origin 隔离:换端口、换浏览器或清理站点数据不会自动迁移。
- 修订冲突:记录层
revision不一致时停止自动覆盖,提供重新载入、另存为新项目或导出 JSON;不做几何自动合并。 - 重要设计应导出 JSON 作为长期归档;备份条目不是文件下载的替代品。
JSON / PDF / ASC 的职责
| 格式 | 角色 | 保留什么 | 明确不保留或限制 |
|---|---|---|---|
| JSON | 完整主文件 | stock、完整 CUT STACK(含被覆盖层)、Meet 快照、光学材质等 | 导出的是已提交文档;活动草稿不会被导出动作隐式提交 |
| 技术报告 / 沟通 | 多视图、尺寸与有效面表;可搜索中文 | 面向阅读,不替代可再编辑主文件 | |
| ASC | GemCad 交换 | 最终有效切面与折射率等交换字段 | 展开重复/镜像;省略 Meet 意图、预形标记、撤销历史、毛坯定义;mesh 原石项目阻断导出 |
docs/limits.md 与 ASC 说明强调:需要继续改型时以 JSON 为准;ASC 预检会列出信息损失,导入/导出前应读完诊断再确认。
Optical Lab 与光学仿真的区别
| 入口 | 状态(v1.1.1) | 用途 |
|---|---|---|
| 画布「光学仿真」模式 | 已实现的聚焦视图 | 比较材质、冠亭比例与亮暗;显示效果不代表实际切磨收益 |
| 顶栏「光学实验室」页面 | 空白三栏骨架 | 导航占位;文案为「实验工具准备中」 |
不要把 Optical Lab 页面上的空态解读成“光学功能未做”——光学仿真在编辑器内;实验室页是尚未交付的独立实验工作区。
可核查结论与验证边界
以下结论均可在 tag v1.1.1 / commit 1b76273 的源码或 docs/ 中核对:
- React + Vite 单页应用;工程视口为 p5 WEBGL,光学视口为原生 WebGL2。
- 96 齿分度;CUT 会话四态;mesh 裁切保孔;cube/mesh 预览与提交内核策略按契约区分。
- MCP 与网页共用 application/domain;撤销历史 owner 在
WorkbenchEditor。 - 项目持久化在 localStorage;JSON/PDF/ASC 职责分离;Optical Lab 未实现实验工具。
本文未声称:
- 已在本机跑通完整
check:mcp或设计师验收清单(上游docs/validation.md记录了维护者侧的验收,读者应自行复验)。 - 仿真亮度/火彩等于真实切磨收益或材料等级。
- GitHub Pages Live Demo 与某一 commit 字节级一致(源码版本 ≠ 站点已更新)。
动手命令速查
# 固定调研版本
git fetch --tags
git checkout v1.1.1
npm ci
# 仅网页
npm run dev
npm run build
npm run check
# 含 MCP(需先安装 mcp 依赖)
npm ci --prefix mcp
npm run check:mcp
对话安装另见仓库根目录 INSTALL.md / UPGRADE.md;那是 Codex 侧的维护入口,与静态网页路径正交。
参考资料
- 仓库与演示:OpenGemCutting · Live Demo
- 版本:
v1.1.1· commit1b76273882a9f1daeda6ce36d592b926d45c22f1· 2026-09-12 - 契约文档:
docs/architecture/state-contract.md、docs/mcp/architecture.md、docs/architecture/gemcad-asc.md、docs/limits.md、docs/cut-performance.md、docs/validation.md - 关联站内阅读:Web 3D 基础概念:从 Mesh 到 GLB · 前端工具链专题