Sand3D数据集发布:10万+3D对象转成Python代码
Sandflow团队发布Sand3D数据集,将Objaverse、CAD等来源的106,094个3D对象统一转化为Python代码。这种“结构优先”的代码格式大幅降低了大语言模型学习3D几何的难度,解决了传统网格数据杂乱、难以编辑的问题,为AI生成可控、可编辑的3D内容提供了新基础。
大模型为什么搞不定3D?工具链太杂是主因
让大语言模型(LLM)写代码造一把3D椅子,试过的人多半会撞上两道坎:代码跑不起来;就算跑起来了,出来的模型也是一堆乱糟糟的三角面片,后面根本没法改。
这事不能全赖模型笨。眼下的3D创作工具链,对AI实在不够友好。拿Blender来说,它的Python API(bpy)本来是给人类操作员设计的:先选中物体,切换模式,再执行操作。这套“过程式”逻辑处处依赖状态,模型得先学会怎么操作软件界面,才谈得上建模。CAD软件、Web 3D引擎又各有一套conventions(惯例)。模型在工具之间跳来跳去,光适应这些“方言”就把注意力耗光了,哪还有余力去理解几何形状本身。
Sandflow团队新发布的Sand3D项目想换个路子:工具乱,那就统一成一种语言。他们拿出的数据集包含106,094个3D对象,每个对象不再是冷冰冰的一堆顶点坐标,而是一段简短、规范的Python代码。这些代码基于团队开源的sand3d库编写。Objaverse的通用资产也好,精密CAD零件、带关节的机械结构也好,全都遵守同一套语法规则。
写3D对象,就像写一份菜谱
Sand3D的思路不复杂:把3D对象当成一道菜,代码就是菜谱。
OBJ、GLTF这类传统3D网格文件,记下的是最终结果——表面上百万个坐标点。你很难从中看出这把椅子由“四条腿”和“一个座面”拼成,更别说去改腿的粗细。Sand3D则把对象描述成一系列参数化部件,外加它们的组装关系。
这么设计,直接带来两点好处:
第一,可编辑性第一,改起来方便。如果你想把椅子的腿变长,只需在代码里改一个长度参数,重新跑一遍脚本,模型就更新了。如果你想去掉某个装饰件,删掉对应的add_函数调用即可,其他部分不受影响。
第二,对AI友好。大模型本来就擅长处理结构化文本。3D对象一旦变成代码,模型就能借上自己在编程任务上的本事,靠预测下一个代码令牌来“生成”3D形状,不必从头去学几何拓扑。
结构优先:化解AI“不知道何时停笔”的老毛病
代码生成领域有个经典痛点:模型常常不知道什么时候该收尾。放到3D生成里,就是模型陷进死循环,一遍遍重复添加相同的几何细节,或者吐出残缺不全的结构。
Sand3D的应对办法是“结构优先,细节在后”的代码组织方式,这个问题由此得到缓解。
在Sand3D的程序里,主函数扮演目录的角色。它不做具体的几何计算,只列出对象由哪些部件组成、它们怎么装配。比如一个配重栈(weight stack),代码开头可能是这样:
def weight_stack(n_plates=14, selected=9):
stack = plate_column(n_plates) # 创建柱体
add_bumpers(stack) # 添加缓冲器
add_guide_rods(stack) # 添加导杆
add_selector(stack, selected) # 添加选择器
return stack.root这么写,模型一上来就把整体蓝图定下了。它清楚只要写完这四个部分,任务就算完。具体的几何细节封在各个子函数里,模型可以一个一个填。Sandflow团队的内部实验显示,这种结构能让模型更早确定计划并commit(提交)结果,无效的生成长度随之减少。反过来,同样30个CAD零件若用Blender Python API手写,Sand3D代码需要的Token数量只有前者的四分之一左右。
数据从哪来?干净是构造出来的
眼下主流的3D研究,大多靠Objaverse数据集。Objaverse规模是大,质量却参差不齐:破损网格、非流形几何体比比皆是,还有不少没有明确部件划分的“三角面片汤”。研究人员往往得花大量精力做预处理和后处理,而这些清洗过的数据通常并不公开。
Sand3D不一样,它的“干净”是内生的。每个对象都由代码生成,天然带着下面这些特征:
- 部件彼此分离、命名清晰:不存在粘连成一团的混乱网格。
- 拓扑规整:程序构建时倾向于生成以四边面为主的拓扑结构(尽管导出的OpenUSD文件为兼容性做了三角化)。
- 关节信息完整:可动对象的代码里,关节类型和连接关系都写得明明白白。
也就是说,Sand3D既能拿来训练AI,也适合人类艺术家上手。艺术家可以把AI生成的代码当作基础布局,再针对特定部件细调,不用在一堆杂乱顶点里大海捞针。
数据集构成与质量把关
Sand3D一共拆成五个子集,从日常生活里的小物件到工业零件都收进来了:
- sand3d-objaverse(66,887个对象):这批来自Objaverse,各种通用3D资产都有。
- sand3d-cad(24,495个对象):数据取自Zero-To-CAD和CADFS,机械零件占了大头。
- sand3d-articraft(9,209个对象):这批出自Articraft,主打带关节、能动的物体。
- sand3d-automate(3,169个对象):来源是AutoMate,装的是组件和零件。
- sand3d-simready(2,334个对象):这批来自NVIDIA SimReady,面向仿真场景。

团队还设了严格的F-score过滤,确保代码生成的模型跟原始资产对得上。Objaverse和静态SimReady资产,F-score不能低于0.70;CAD零件和刚性Articraft程序,门槛抬到0.90;可动对象则要求每个部件的F-score都到0.90,关节位置也得对。达不到的直接剔掉。

这些对象由Sandflow的迭代代理重建管道(iterative agentic reconstruction pipeline)自动编写完成。说白了,就是让AI去逆向现有的3D模型,先转成代码,再用代码把模型重新生成出来,两相对比做验证。

局限与后续方向

Sand3D当然不是万能的。眼下这个版本主要盯着“硬表面”(hard-surface)对象,比如家具、工具、机械零件和家电。换成角色、动物这类有机形态,现有的代码原语(primitives)还撑不起高效的表达。

团队的说法是,以后会往库里加新的“动词”,以便支持更复杂的几何形态,比如:

- 隐式表面:像元球(metaballs)这种,用来做平滑融合的有机形状。
- 细分曲面:靠控制笼驱动,适合生物建模。
- 沿曲线扫描/放样:生成肢体、茎干这类变截面结构时用得上。
- 骨骼蒙皮:用来支持姿态变形。
- 程序化位移:给模型补上雕刻级别的细节。
另外,过滤机制摆在那里,原始网格里的一些细微之处或噪声,可能在代码化途中就丢了。不过换个角度看,这反倒成了一种优势——等于自动做了“降噪”和抽象。
开源与使用
Sand3D数据集按CC BY 4.0协议发布,商业使用是允许的,但每个对象仍要遵守其原始来源的许可证要求。底层的sand3dPython库则以Apache 2.0协议开源。
开发者这边,可以直接从PyPI装库(pip install sand3d),数据集和在线Explorer在Hugging Face上就能浏览。每个对象都配齐了三样东西:生成它的Python程序、导出的OpenUSD文件(在Hub的3D查看器里能直接预览,关节动画也支持),还有渲染图。
这个项目的分量,不只是一个大规模数据集,更在于它拿出了新的3D内容表示范式:代码即几何。大语言模型在代码生成上还在往前走,这种范式说不定会成为AI理解和创造三维世界的那道关键桥梁。