ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Pascal 3D 编辑器物品资产规范:用 `slot_` 命名打造可喷涂的 GLB 家具与部件

Pascal 3D 编辑器物品资产规范:用 `slot_` 命名打造可喷涂的 GLB 家具与部件 Pascal 3D 编辑器物品资产规范用slot_命名打造可喷涂的 GLB 家具与部件【免费下载链接】editorOpen-source 3D architectural editor with a local CLI, MCP tools, and practical workflows for humans and AI agents.项目地址: https://gitcode.com/GitHub_Trending/editor93/editor导读本文讲解 Pascal 3D 开源编辑器packages/core 与 packages/nodes 构成的场景体系中一条面向内容创作者Content Author的文件格式约定如何制作一个目录物品Catalog ItemGLB使它既保留作者烘焙的默认外观又能把命名部件暴露为可喷涂paintable的slot 插槽。读完本文你将掌握slot_材质命名契约、slot id 派生规则、UV 世界尺度约定、Blender 制作流程与 glTF 导出要点并理解编辑器在加载时如何依据材质名解析出可喷涂部件、喷涂后颜色如何落盘与回放。约定总览全部由材质名驱动全量 opt-in物品item在场景中是一个挂载 GLB 资产的节点其运行时代码位于 packages/nodes/src/item/renderer.tsx。整条喷涂约定的核心是一个按材质名 opt-in的规则glTF 中材质material名称以slot_开头不区分大小写该部件即被标记为可喷涂插槽没有任何slot_材质的物品运行时按作者烘焙/命名的外观原样渲染不暴露任何可喷涂内容也不需要切换任何模式——行为完全由文件名材质名决定详见后文编辑器如何读取。作者侧命名、存储的 slot 元数据与运行时网格三者共享同一份规范实现不会漂移规范代码集中在 packages/core/src/lib/slots.ts上传扫描与渲染器都引用它。插槽契约Slot Contract一个部件一个材质命名slot_part每个可喷涂部件对应一个材质命名形如slot_frame、slot_seat、slot_bed_frame。规范实现为// packages/core/src/lib/slots.ts export const SLOT_MATERIAL_PREFIX slot_ export function isSlotMaterialName(name: string): boolean { return name.toLowerCase().startsWith(SLOT_MATERIAL_PREFIX) }slot id 派生规则前缀剥离 去重后缀 小写化deriveSlotId是 id 的唯一定义见 packages/core/src/lib/slots.ts#L15-L20export function deriveSlotId(materialName: string): string | null { if (!isSlotMaterialName(materialName)) return null let rest materialName.slice(SLOT_MATERIAL_PREFIX.length) rest rest.replace(/\.\d$/, ) // 丢弃 Blender 数字去重后缀如 .001 return rest.toLowerCase() }按此规则材质名派生 slot idslot_Bed_Framebed_frameslot_bed_frame.001bed_frameslot_seatseat两个同名但带不同去重后缀的 Blender 材质会合并为同一个 slot——这是刻意设计一个逻辑部件因建模需要被拆成多份几何时喷涂仍然是一个整体。若一个网格使用多材质数组渲染器会按数组逐项派生 slot见 packages/nodes/src/item/renderer.tsx#L112-L125 的captureItemMeshMaterials。未标记材质永远保持作者外观不带slot_前缀的材质原样渲染且不暴露 slot。这对固定标签、贴花、标牌与烘焙细节如消防报警标志、空调前面板是正确选择——它们不应被喷涂污染。仅凭命名即可喷涂纯色 slot 不采样 UV一个平涂颜色的物品只要重命名材质即可整体可喷涂无需重新展 UV。这也意味着 UV 存在性校验见下文UV 世界尺度会区分需要 UV 却没有 UV的 slot 与纯色不需要 UV的 slot。默认外观作者材质数据即默认值slot 的默认外观就是作者材质自身的数据baseColorFactor/ 贴图从不编码在 slot 名里。喷涂会覆盖该默认值重置橡皮擦则回到它。运行时解析顺序见 packages/nodes/src/item/renderer.tsx#L163-L195 的resolveItemMaterial纹理关闭monochrome→ 折叠为furnishing角色的主题色createSurfaceRoleMaterial(furnishing, colorPreset)名为glass的材质 → 统一玻璃材质命中 slot id 且node.slots[slotId]有覆盖 → 用覆盖材质否则若有pascal_material精选引用 → 用精选材质都没有 → 返回作者材质本身。跨物品的精选默认值例如这把椅子的座垫默认用目录亚麻布作为 glTF 材质的pascal_materialextras随资产携带运行时从material.userData.pascal_material读取见 packages/nodes/src/item/renderer.tsx#L95-L102 的curatedRefFromMaterial支持library:/scene:前缀引用。它是可选的——不存在时作者材质就是默认值。slot 覆盖最终以MaterialRef字符串library:id或scene:id存入节点字段ItemNode.slots键为 slot id见 packages/core/src/schema/nodes/item.ts#L168-L171悬空引用会回退到默认值而非阻塞渲染。保留名cutoutcutout是一个网格mesh名而非材质名。名为cutout的网格被当作布尔切除辅助体运行时隐藏永不成为 slot也永不作为可见表面用于承载宿主开洞要减去的负体积不要用它装你想显示的几何。渲染器在加载后对名为cutout的节点强制visible false见 packages/nodes/src/item/renderer.tsx#L610-L612 与 packages/nodes/src/item/renderer.tsx#L637-L643。UV 世界尺度约 1 UV 单位 1 米可平铺饰面沿用程序化表面同一套世界尺度 UV 契约1 UV 单位 1 m相关说明见 wiki/architecture/materials-and-themes.md 中Texture world scale一节程序化表面如墙体、楼板、吊顶、屋顶都按米生成 UV。对 GLB 物品这是创作端要求不是渲染端修正——slot 校验器的 UV 存在性检查会标记需要 UV 却没有 UV的 slot平涂颜色 slot 则完全不需要 UV。同一 slot 内的固定多色细节应烘焙进顶点色喷涂会替换 slot 的材质但顶点色随网格一起保留因此双色部件在任何饰面下都保持双色。Blender 制作配方已校验文档给出并经验证的步骤应用缩放——CtrlA→ Scale使 1 个 Blender 单位导出为 1 m从而 UV 世界尺度承诺成立重命名材质为slot_part覆盖每个可喷涂部件硬表面 slot—— UV 使用Cube Projection立方体投影Cube Size 1.0。这样构造上恰好得到 1 UV 单位/米UV 岛重叠没问题因为饰面可平铺且无需烘焙曲面 / 柔软部件 slot—— 使用Texel Density纹素密度插件参数10.24 px/cm 1024 px导出前用 UV 网格纹理检查。导出关键步骤必须开启 Custom Properties自定义属性在 Blender glTF 导出器中打开Include → Custom Properties否则pascal_materialextras 永远到不了 GLB精选默认值会静默丢失优化时保留 extras使用保留 extras 的优化器——gltfpack 加-kekeep extras。作者侧 extras 在上传时只读取一次导出与上传之间任何剥离都会丢失它们校验器在 extras 疑似被剥离时会给出警告。编辑器如何读取结果加载即捕获一次捕获、多处消费物品模型通过ItemGLTFLoader支持 Draco / Meshopt / KTX2见 packages/nodes/src/item/renderer.tsx#L223-L233加载后captureItemMeshMaterials会遍历网格把作者材质数组、按材质派生的 slot id 数组、pascal_material精选引用一次性捕获并写入mesh.userData.pascalItemMaterialCapture与mesh.userData.slotId见 packages/nodes/src/item/renderer.tsx#L104-L138。之后每次外观状态变化shading/textures/colorPreset/node.slots/ 场景材质只需基于捕获结果重算无需重新解析 GLB。喷涂工具(nodeId, slotId)精准定位itemPaint实现了PaintCapability见 packages/nodes/src/item/paint.ts#L236-L256resolveRole通过射线命中的userData.slotId支持单材质与多材质数组解析出 slot idapplyPreview把目标 slot 的材质临时替换为预览材质并在恢复函数中还原commit将覆盖写入node.slots[role]若是一次性新颜色则先做场景材质去重findMatchingSceneMaterial找到结构相等的既有场景材质就复用引用否则新建场景材质并在同一个setState中同时写入材质与 slot 引用——保证 zundo 历史只记录一条、一次 undo 同时移除引用与其孤立材质getEffectiveMaterial把 slot 引用解析回可编辑的材质数据。节点定义 packages/nodes/src/item/definition.ts#L219 把paint: itemPaint挂到capabilities上并声明surfaceRole: furnishing——这正是渲染器在 monochrome 模式回退到主题色时使用的角色角色色解析见 wiki/architecture/materials-and-themes.md。喷涂作用域single / object / matching / room一次喷涂的扩散范围由被悬停节点派生见 packages/editor/src/lib/paint-scope.ts#L55-L61slot 数大于 1 的节点提供object整件物品所有 slot带asset的节点提供matching同一资产的所有实例、同一 slot 一次刷完声明roomScope的种类提供room。多目标批量提交在单条 undo 内完成先只解析一次材质引用一次性颜色在整个扩散范围内共享一个场景材质再一次性写入所有node.slots[role]见 packages/editor/src/lib/paint-scope.ts#L411-L466。没有slot_材质的物品加载后每个网格的 slot id 都是nullresolveItemMaterial直接返回作者材质纹理开启时——没有单独的模式需要设置行为由文件中的材质名自然决定。这保证老资产与纯装饰资产无需任何改造即可原样展示。小结与创作检查清单把以上内容压缩为一份可直接对照的 checklist每个可喷涂部件一个材质命名slot_part小写、下划线分隔最稳妥固定标签 / 贴花 / 烘焙细节不要加slot_前缀布尔切除辅助网格命名为cutout会被隐藏CtrlA应用缩放1 Blender 单位 1 m硬表面用 Cube ProjectionCube Size 1.0曲面用 Texel Density 10.24 px/cm 1024 px导出前用 UV 网格图检查需要跨物品默认饰面时在材质 extras 写入pascal_material引用导出时开启Include → Custom Properties优化时用 gltfpack-ke保留 extras同一 slot 内的固定多色细节烘焙进顶点色。遵循该契约任何目录物品 GLB 都会在 Pascal 编辑器中自动获得默认外观 可命名部件喷涂的双重能力且作者侧命名、存储元数据与运行时网格三者因共享 packages/core/src/lib/slots.ts 的同一实现而永不失配。【免费下载链接】editorOpen-source 3D architectural editor with a local CLI, MCP tools, and practical workflows for humans and AI agents.项目地址: https://gitcode.com/GitHub_Trending/editor93/editor创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表