ARTICLE DETAIL

资讯详情

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

大模型生成OpenSCAD代码:实现可编辑3D建模与自动零件分解

大模型生成OpenSCAD代码:实现可编辑3D建模与自动零件分解 用大模型生成 3D 建模代码正在成为计算机图形学里比“直接用 AI 生成网格”更接近工程落地的路径。传统 AI 生成 3D 模型通常直接输出三角面片、体积栅格或点云视觉上接近却很难进入装配、仿真和制造环节而大模型先生成可执行的 CAD 代码再由建模内核执行这段代码得到的是一组边界明确、尺寸可控、支持修改的实体。这种方式天然适合可编辑零件分解也能解释为什么它在精度和可控性上比直接生成模型更适合工程场景。这篇文章围绕“大模型生成建模代码 - OpenSCAD 渲染验证 - 零件分解与导出”这条链路跑通一个最小闭环。示例使用本地部署的开源代码模型来生成 OpenSCAD 脚本不需要在线服务适合图形学学习者、CAD 二次开发工程师以及想评估大模型在工程建模领域能力的算法工程师。读完后你可以把同样的提示词和脚本套到自己的零件、装配体或可打印模型上。1. 为什么“用大模型生成建模代码”能兼顾精度与可编辑性1.1 传统 AI 生成 3D 模型的精度短板传统生成模型走的是“从表示到样本”的路线。体素生成把空间划分成固定分辨率网格在 64 或 128 的分辨率下曲面都带有明显台阶点云生成输出空间散点没有连续表面直接生成网格的做法最难处理的是拓扑输出经常出现自交、非流形、孔洞和错误朝向的面片。结果是预览可以用工程化很难用。这些结果用于游戏概念图或者快速找灵感问题不大。但一旦进入装配零件与零件之间需要接触、配合、定位就必须有精确的边界和标注尺寸一旦进入仿真需要闭合实体一旦进入制造需要可靠的导出格式。传统生成模型在这些环节都需要大量后处理而且很难做到参数化修改你不能把一个孔从直径 4 改成 5然后要求模型只改这一处。1.2 代码生成是“先定义特征再离散化”代码生成建模绕开了直接预测几何的路线。大模型写出来的是 OpenSCAD、CadQuery 等建模脚本里面描述的是长宽高、圆心、孔径、布尔运算、特征阵列。OpenSCAD 的 CSG 内核执行这些操作时得到的是实体而不是一张表面采样。所谓高精度不在于分辨率采样而在于特征本身就是显式参数。圆就是圆孔就是孔配合面就是配合面。同时可编辑性来自代码结构。想改孔距找到参数改一个数字想增删特征增删一段函数想拆成零件模块边界就是零件边界。这比传统生成模型重新推理一次要确定得多。1.3 本文验证的闭环本文的验证目标很明确让本地大模型根据一段自然语言需求输出一个多零件的 OpenSCAD 模型用命令行渲染确认没有语法错误通过 explode 变量观察爆炸视图再把每个零件单独导出成 STL。整个过程不需要打开图形界面完全脚本化适合集成到生成式设计流水线中。这也是“自带可编辑零件分解”的核心含义零件分解不是渲染后的魔法而是建模代码里已经定义好的模块边界用户随时可以单独导出、改名、改参数或重新装配。2. 技术选型本地大模型 OpenSCAD为什么这样组合2.1 OpenSCAD 是适合大模型输出的建模语言OpenSCAD 是程序化 CAD脚本由基本体、变换、布尔运算和 module 组成没有复杂的 UI 状态。它的语法接近函数式模块化能力强天生适合按零件组织代码。这一点对生成代码的模型非常友好模型不需要记忆 GUI 操作序列只需要输出结构化的几何脚本。学习成本也低即使模型生成的代码有误人也能在几十行内读懂并修正。相比 CadQuery 或 FreeCAD 脚本OpenSCAD 安装轻命令行工具稳定适合在 CI 里跑批量渲染。如果你要生产级 STEP 数据可以在后面换 CadQuery本文先用 OpenSCAD 把链路打通。2.2 使用本地大模型的原因调用在线大模型 API 最省事但工程建模往往涉及设计尺寸不适合把图纸文本送到外部。本地部署的代码模型在数据隔离和离线能力上有明显优势。Ollama 将模型运行封装成了 HTTP 服务调用方式和 API 相似硬件要求也比预想低7B 到 14B 参数量的量化模型16GB 内存的普通开发机已经能跑只是速度不同。选择本地模型还有一个实际好处结果可复现。固定同一个模型、同一个量化版本同样的提示词出来的结果相对稳定方便做回归测试。在线模型频繁更新反而很难沉淀测试集。2.3 环境需求一览组件用途学习环境最低建议生产环境建议Ollama本地模型运行服务最新稳定版即可固定版本容器化部署代码模型生成 OpenSCAD 脚本7B 量化模型14B 或更高按测试集选型OpenSCAD渲染和导出 STL最新稳定版固定版本跨平台打包Python 3调用模型和渲染3.103.11日志和重试完整实现生产环境建议增加 GPU。纯 CPU 跑 7B 模型生成几百行代码可能需要几分钟GPU 会明显缩短。OpenSCAD 渲染本身是 CPU 计算大规模导出可以并行跑多个进程。3. 搭建本地生成环境Ollama、代码模型与 OpenSCAD 命令行3.1 安装 Ollama 并拉取模型不同系统安装方式不同。Linux 可以使用官方安装脚本macOS 和 Windows 安装对应安装包。安装完成后先确认服务在运行再拉取代码模型。Ollama 默认监听本机 11434 端口Python 脚本会通过这个端口访问模型。# Linux 安装示例 curl -fsSL https://ollama.com/install.sh | sh # 查看已安装模型 ollama list # 拉取一个代码模型这里以 qwen2.5-coder 系列为例 ollama pull qwen2.5-coder:7b拉取完成后再次执行ollama list能看到本地模型列表。模型名要记住后续 Python 调用会用到。不同版本的 Ollama 或模型库支持的标签可能不同落地上线前先确认目标模型和模型 tag 是否存在。3.2 安装 OpenSCAD 并确认命令行OpenSCAD 提供各平台安装包。macOS 下可以通过 Homebrew 安装Ubuntu 可以通过 apt 安装Windows 从官网下载安装包。安装后使用openscad --version检查版本确保命令行工具可用。openscad --version如果命令行找不到多半是安装路径没有加入 PATH。Windows 安装后要用完整路径或把安装目录加进系统 PATH。建议示例先写成openscad实际项目按本机路径调整。3.3 用最小脚本验证命令行链路这一步先手工创建一个最小测试文件目的是把环境问题提前暴露掉而不是等生成代码出错时再排查。创建test.scad$fn 32; difference() { cube([20, 20, 10], center true); cylinder(h 12, d 8, center true); }渲染成 PNGopenscad -o test.png --autocenter --viewall --imgsize 400,400 test.scad如果得到 PNG 文件说明 OpenSCAD 命令行链路可用。如果报错先检查安装路径。这一步不要跳过后面的自动化脚本会依赖同样的命令格式先验证最小链路能节省大量排查时间。4. 设计建模提示词让大模型输出“能编译”的 CAD 代码4.1 一个可复用的提示词模板想得到稳定结构提示词不能只写“帮我生成一个传感器安装台”。CAD 代码生成对格式、单位、模块命名都有要求这些必须写清楚。你是 OpenSCAD 建模专家。请根据下面的需求生成完整的 .scad 文件内容。 模型需求 - 名称传感器安装台 - 零件base底板、pillar立柱、platform顶板 - 材料单位毫米OpenSCAD 默认单位 - 坐标系每个 part_ 模块以自身基准面为原点 - 装配在 sensor_mount_assembly 模块中用 translate 完成装配 代码要求 1. 每个独立零件定义为一个独立 module命名前缀 part_ 2. 提供 render_part 变量值可以是 all/base/pillar/platform 3. 提供 explode 变量默认 0爆炸视图时零件沿 Z 轴分离 4. 使用 $fn 48 保证圆弧平滑 5. 不要输出 Markdown 以外的解释期望是一份能直接保存为 .scad 的代码。实际使用中模型可能多解释几句可以在后处理脚本里用正则截取scad 到之间的内容。4.2 必须写进提示词的五类约束实体闭合布尔差集必须是闭合实体不能在差集中留非流形面。尺寸显式所有数字都要写具体不写“稍大一点”这类模糊描述。模块边界零件间不能有公共特征交叉除非是装配配合。命名规范让后续脚本可按 render_part 过滤。坐标系和装配分离模块内原点是局部坐标装配模块负责定位。这些约束不是让模型“看起来更专业”而是为了让输出可以被自动化流水线消费。没有 render_part 约定批量导出单个零件就要人工改文件没有 explode 变量爆炸视图就要重写代码。4.3 用 few-shot 提高输出稳定性直接零样本生成格式漂移概率较高。一个有效办法是在提示词里加一小段 few-shot 示例演示 part_ 前缀、render_part 和 explode 三个约定。示例不需要完整复杂零件只要一个 20 行的轴承座或垫片即可。这样模型会模仿代码结构而不是重新发明格式。提示词工程在这里的关键不是话术而是把后处理需要的信息前置到生成阶段。后面的数据清洗工作量取决于这一步约束是否明确。5. 用 Python 串联大模型、代码生成与自动渲染5.1 生成流程整个自动化流程可以拆成六个步骤读取提示词模板并填入零件名。调用 Ollama 获取代码。从返回内容中截取 scad 代码块。写入 .scad 文件。调用 openscad 渲染 PNG。如果失败把 stderr 拼进修复提示词重新生成。每一步都是独立函数这样替换模型或渲染器时不牵动整体。5.2 调用 Ollama API 的 Python 脚本保存下面的脚本为generate_cad.py。它使用 requests 直接调用 Ollama 的/api/generate接口关闭流式输出降低解析成本。import json import re import subprocess import requests OLLAMA_URL http://localhost:11434/api/generate MODEL_NAME qwen2.5-coder:7b def complete(prompt: str, timeout: int 180) - str: payload { model: MODEL_NAME, prompt: prompt, stream: False, options: { temperature: 0.2, top_p: 0.8, }, } resp requests.post(OLLAMA_URL, jsonpayload, timeouttimeout) resp.raise_for_status() return resp.json()[response] def extract_scad(text: str) - str: patterns [ rscad\n(.*?), ropenscad\n(.*?), r\n([\s\S]*?), ] for pat in patterns: m re.search(pat, text, re.S) if m: return m.group(1).strip() return text.strip()temperature 调低可以让输出更稳定但过低也可能让模型只复述示例结构。这里取 0.2 是比较常见的折中值。5.3 渲染验证与简单失败重试渲染函数通过openscad命令行完成并把 render_part 变量传进去。这样既可以为整体装配体出图也可以为单个零件出图。def render_scad(scad_path: str, out_path: str, part: str all): cmd [ openscad, -D, frender_part{part}, -o, out_path, --autocenter, --viewall, --imgsize, 800,600, scad_path, ] proc subprocess.run(cmd, capture_outputTrue, textTrue, timeout120) return proc.returncode, proc.stderr def generate_and_render(prompt: str, scad_path: str, png_path: str): raw complete(prompt) code extract_scad(raw) with open(scad_path, w, encodingutf-8) as f: f.write(code) code, err render_scad(scad_path, png_path) if code ! 0: repair_prompt ( OpenSCAD 渲染报错请修复代码并输出完整 .scad\n f错误信息\n{err}\n fscad\n{open(scad_path, encodingutf-8).read()}\n ) raw complete(repair_prompt) with open(scad_path, w, encodingutf-8) as f: f.write(extract_scad(raw)) code, err render_scad(scad_path, png_path) return code, err修复重试只建议做一到两轮。超出两轮还在报错说明提示词或模型选型需要调整继续重试可能陷入循环。生产环境还要加入日志、超时、次数上限。6. 实现可编辑零件分解模块化、爆炸视图与批量导出6.1 在建模代码里预留零件边界这里的关键约定是每个零件模块内部只描述零件自身外部坐标系完全交给 assembly。这样既容易调试单个零件也方便导出。下面是一段通过提示词生成后经过核对可用的 OpenSCAD 代码。它定义了一个传感器安装台包含底板、立柱、顶板三个零件。$fn 48; render_part all; explode 0; module part_base() { difference() { cube([80, 60, 8], center true); for (x [-35, 35], y [-25, 25]) { translate([x, y, 0]) cylinder(h 12, d 6, center true); } } } module part_pillar() { difference() { cube([40, 40, 60], center true); cylinder(h 64, d 20, center true); } } module part_platform() { difference() { cube([80, 60, 6], center true); cube([42, 42, 12], center true); } } module sensor_mount_assembly() { part_base(); translate([0, 0, 8 30 explode]) part_pillar(); translate([0, 0, 8 60 3 2 * explode]) part_platform(); } if (render_part all) { sensor_mount_assembly(); } else if (render_part base) { part_base(); } else if (render_part pillar) { part_pillar(); } else if (render_part platform) { part_platform(); }这个模型是演示用的理想输出格式实际大模型生成结果可能在命名和结构上有差异但核心约定保持一致即可。配合间隙也很重要平台方孔 42mm立柱 40mm留出 1mm 装配间隙中心孔直径 20mm用于减轻重量或走线。注意生成代码后要重点检查布尔差集是否穿透。差集工具的高度如果小于被切体高度可能留下未闭合几何渲染时会出现警告。6.2 爆炸视图的 transform 策略爆炸视图本质是装配平移量的可视化。explode0 时是真实装配状态explode 增加时把零件沿装配法向推离观察内部结构。上面的代码中立柱偏移量是8 30 explode顶板偏移量是8 60 3 2 * explode不同零件使用不同倍数视觉上更清晰。渲染爆炸视图的命令openscad -D render_partall -D explode20 \ --autocenter --viewall --imgsize 1200,900 \ -o explosion.png sensor_mount_assembly.scad渲染出来的 PNG 能看到立柱和顶板离开底板孔位和配合面关系更清楚。这个图片适合做文档插图或生成评审材料。6.3 批量导出单个零件批量导出时用 for 循环遍历零件名通过-D传入 render_part 变量。注意 OpenSCAD 命令行传递字符串时要保留双引号。for part in base pillar platform; do openscad -D render_part\$part\ -D explode0 \ -o ${part}.stl sensor_mount_assembly.scad done导出后检查每个 STL 体积是否接近设计值。对实体建模结果可以用其他 CAD 工具打开验证。生产环境建议再写一个脚本批量检查 STL 非空、体积大于阈值、文件大小合理。7. 与传统 AI 生成 3D 方法的对比7.1 对比表对比维度传统 AI 直接生成网格/体素大模型生成建模代码精度来源分辨率采样显式尺寸参数拓扑容易出现自交、非流形由 CSG/CAD 内核保证可编辑性弱重新生成或网格后处理强改参数和代码数据需求需要大量三维数据集主要需要代码语料和 CAD 规范生成速度优化耗时分钟级到小时级秒到分钟级取决于模型和长度装配能力较差零件之间无配合语义可定义坐标系和装配关系适用场景概念、艺术资产、仿真输入占位机械零件、装配体、3D 打印、加工件这里的“效果更好”不是指视觉更像而是指工程可用性更强。对机械方向的设计任务可编辑性、尺寸准确性和装配语义往往比视觉表现更重要。7.2 什么场景仍需要传统生成网络传统生成网络并没有过时。复杂有机形状、流体形态、雕刻类模型、地形地物等用代码描述非常困难用生成式网络更合适。另外如果目标是快速产出几十个概念造型给设计师挑选直接生成网格的重要价值是“低门槛多样性”不是工程精确性。这两条路线不是替代关系。代码生成建模擅长规则几何和机械结构传统生成网络擅长自由曲面和艺术风格化混用场景会越来越多。7.3 大模型代码建模当前的能力边界大模型对 OpenSCAD 这类语法相对简单的语言掌握得不错但对复杂装配约束、公差配合、制造工艺并不总是理解到位。它可能写出语法正确但装配干涉的模型也可能在细节尺寸上不一致。能力边界集中在自由曲面、复杂曲面倒角、真实公差标注和 GDT 语义。因此评估标准不能只看代码能否运行还要检查实体体积、装配间隙、干涉检测、导出格式是否符合下游要求。把验证自动化才能把大模型从“demo 生成器”变成“参数化设计助手”。8. 常见报错与排查路径CAD 代码不是聊天代码8.1 语法错误与未闭合实体现象openscad 命令返回非零stderr 出现ERROR:。原因少括号、变量名错误、差集操作后留下非流形几何。检查方式先看 stderr再用openscad -o /dev/null file.scad做快速解析。解决把错误信息拼回提示词修复如果差集穿透导致未闭合把切削体高度加大到完全穿过被切体。8.2 尺寸与单位异常现象渲染成功但模型尺寸比预期大 25.4 倍或孔距不对称。原因模型沿用了英制单位或把毫米写成了英寸。OpenSCAD 没有单位概念数字本身是什么单位导出就是什么单位所以提示词里必须声明“毫米”。检查测量 PNG 或 STL 的包围盒。解决统一由提示词和验证脚本双重控制尺寸。8.3 装配相对位置错误现象整体渲染正常但零件叠加在同一个位置。原因assembly 模块里没有 translate或者零件模块内部用了绝对坐标。检查对比单个零件和装配体的包围盒。解决强制约束“模块内部以自身基准为原点装配时在 assembly 模块中偏移”。8.4 排查清单顺序检查项命令或方式处理建议1提示词是否包含尺寸、单位、模块约束阅读 prompt补齐约束再生成2OpenSCAD 是否进入 PATHopenscad --version安装或加 PATH3输出是否为合法 scadopenscad -o /dev/null file.scad截取代码块去掉 Markdown4渲染是否成功检查 PNG 输出用 stderr 修复5尺寸是否符合设计导入 CAD 或脚本测包围盒修正参数6零件是否有重叠explode 视图目检修正 assembly 平移量7STL 是否非空ls -l 或导入查看重新导出或检查 render_part9. 落地建议与扩展方向9.1 把提示词模板变成团队资产提示词模板应该像代码一样入库、版本化。每次调整都要记录哪些约束改过、为什么改配套一组固定测试零件。不要只把最佳提示词存在个人收藏里那样一换人就要重新踩坑。可以维护一个prompts/目录里面按零件类型存放模板例如bracket.prompt.md、gearbox.prompt.md。模板里只放结构、单位和约束不放客户名称和机密尺寸方便复用。9.2 从 OpenSCAD 扩展到参数化 CAD 工作流OpenSCAD 适合快速验证和打印但真正的机械设计需要 STEP、特征树、公差与材料信息。可以沿着同一思路把后端换成 CadQuery 或 FreeCAD 脚本。大模型输出 CadQuery Python 代码运行后直接导出 STEP保留 B-rep 精度。技术链路不变只是建模内核和后处理不同。换后端时提示词里的语法约束要同步替换例如 CadQuery 需要Workplane、box、circle、cut等 API。验证流程同样适用生成代码 - 脚本执行 - 检查输出 - 失败重试。9.3 用测试脚本约束生成质量给生成结果加测试很值得渲染成功只是最低门槛还要检查实体体积在合理区间、装配间隙大于某个值、导出的 STL 文件大小非零。把测试脚本接到生成流程里质量不达标就自动重试或转人工形成闭环。这样才能应对大模型输出不稳定的问题。例如可以写一个 Python 函数读取 STL 文件头或包围盒判断体积是否在 1000 到 200000 立方毫米之间。超出范围就判定生成失败并记录提示词版本和模型版本。把大模型当作 3D 建模入口真正改变的并不是“自动生成一个好看的网格”而是把设计意图变成可追溯、可修改、可执行的代码。高精度和可编辑性来自 CAD 内核而不是大模型的幻觉大模型负责的是把自然语言需求翻译成结构良好的建模指令。对计算机图形学方向的开发者来说这条链路值得完整跑一遍它能帮你理解代码生成、实体建模、渲染验证和后处理自动化是如何衔接的。下一步可以从一个简单传感器安装台扩展到参数化零件族再逐步把公差、干涉检查和批量导出纳入同一个自动化流程。
返回列表