- 3D建模
- 图形学
【免费下载链接】SpaceshipGenerator
A Blender script to procedurally generate 3D spaceships
SpaceshipGenerator 是一款以 Blender 插件形式提供的程序化生成工具,只需一个随机种子,就能在几秒内生成一艘带完整材质、法线贴图与自发光窗灯的 3D 太空飞船。本指南以仓库根目录的 README.md 为主线,结合 spaceship_generator.py 与init.py 的源码实现,完整覆盖插件的安装启用、面板参数、生成算法原理、可编程调用与批量渲染等实战内容。读完本文,你将掌握如何安装并调参生成个性化飞船、如何通过种子复现同一艘飞船、如何在 Python 环境中以脚本方式批量产出飞船模型,以及算法每一步的底层实现逻辑。
一、项目概述:一个「方盒子 → 宇宙舰队」的生成器
SpaceshipGenerator 是一个 Blender 脚本,其核心理念一句话可以概括:从随机种子(random seed)程序化生成带纹理的 3D 太空飞船模型。它最初是作者 Michael Davies 为 /r/proceduralgeneration 社区 2016 年 6 月月度挑战赛而写的趣味项目,后经社区贡献者修复 Bug、补全 GUI 并完成 Blender 2.80 移植,最终以 MIT 许可证发布。
从插件元数据init.py 可以看到当前版本信息:
- 插件名称:Spaceship Generator,版本1.1.3;
- 目标 Blender 版本:2.80 及以上(
blender: (2, 80, 0)); - 菜单位置:View3D > Add > Mesh,分类为 Add Mesh。
脚本主体是单个文件 spaceship_generator.py,共 819 行,仅依赖 Blender 内置的bpy、bmesh、mathutils模块,无任何第三方 Python 依赖,因此安装即用、易于阅读和二次开发。
二、安装与启用:三步接入 Blender
README 给出的安装流程针对 Blender 2.80+,具体操作如下:
- 安装 Blender:前往 blender.org 下载并安装Blender 2.80 或更高版本(2.7x 老版本不支持);
- 下载插件压缩包:获取最新发布的
add_mesh_SpaceshipGenerator.zip; - 安装 ZIP 包:在 Blender 中进入
Edit > Preferences... > Add-ons > Install...,选择下载的 ZIP 文件; - 启用插件:在 Add-ons 面板中搜索"spaceship",勾选启用"Add Mesh: Spaceship Generator";
- 生成飞船:在 3D 视图中通过
Add > Mesh > Spaceship添加飞船; - 调节参数:展开视口左下角出现的Spaceship 选项卡,即可调整程序化生成的各项设置。
需要说明的是,本仓库为源码形式(spaceship_generator.py+__init__.py),与 Release 中打包的 ZIP 内容一致。启用后,init.py 的register()会将操作符mesh.generate_spaceship注册进VIEW3D_MT_mesh_add菜单(即Add > Mesh下的 "Spaceship" 条目),同时在撤销栈中登记(bl_options = {'REGISTER', 'UNDO'}),因此生成操作可以撤销重做。
三、面板参数全解:控制生成结果的核心旋钮
在 3D 视图底部弹出的 Spaceship 面板中,GenerateSpaceship操作符(init.py)暴露了 11 个参数。这些属性直接映射到generate_spaceship()函数的同名参数。下表完整列出每个参数的默认值、取值范围与生成影响:
| 参数(面板名) | 类型 | 默认值 | 取值范围/软上限 | 生成影响 |
|---|---|---|---|---|
random_seed(Seed) | 字符串 | ''(空) | 任意字符串 | 空串则每次随机;非空则同一种子永远生成同一艘飞船 |
num_hull_segments_min(Min. Hull Segments) | 整数 | 3 | min=0, soft_max=16 | 船体主骨架挤出段数下限 |
num_hull_segments_max(Max. Hull Segments) | 整数 | 6 | min=0, soft_max=16 | 船体主骨架挤出段数上限 |
create_asymmetry_segments(Create Asymmetry Segments) | 布尔 | True | 开/关 | 是否在船体上生成外凸的非对称结构 |
num_asymmetry_segments_min(Min. Asymmetry Segments) | 整数 | 1 | min=1, soft_max=16 | 单个非对称段的最小连续挤出次数 |
num_asymmetry_segments_max(Max. Asymmetry Segments) | 整数 | 5 | min=1, soft_max=16 | 单个非对称段的最大连续挤出次数 |
create_face_detail(Create Face Detail) | 布尔 | True | 开/关 | 是否在船体面上生成引擎、天线、炮塔等细节 |
allow_horizontal_symmetry(Allow Horizontal Symmetry) | 布尔 | True | 开/关 | 是否允许约 50% 概率做 Y 轴左右对称 |
allow_vertical_symmetry(Allow Vertical Symmetry) | 布尔 | False | 开/关 | 是否允许上下对称(源码注释提示会产生"飞船岛屿"问题,故默认关闭) |
apply_bevel_modifier(Apply Bevel Modifier) | 布尔 | True | 开/关 | 是否添加倒角修改器使造型棱角分明 |
assign_materials(Assign Materials) | 布尔 | True | 开/关 | 是否赋予完整材质(关闭则用空白材质) |
值得注意的调参要点:
- 段数上限的语义:
randrange(num_hull_segments_min, num_hull_segments_max)决定实际段数,因此段数实际落在[min, max)区间; - 垂直对称默认关闭:源码 spaceship_generator.py 注释明确写道垂直对称"会导致飞船'岛屿'(spaceship islands)",即船体可能被复制成上下分离的两半,因此默认
allow_vertical_symmetry=False; - 软上限 soft_max=16:面板滑块建议范围到 16,但
min只约束了下界,理论上仍可输入更大的数值——这正是 README "Extreme examples" 一节展示极端取值效果的前提。
四、工作原理:从盒子到飞船的七步流水线
README 用一个分步动画(step-by-step-animation.gif)直观演示了生成过程,其文字描述为七步。对照源码,每一步都能找到精确的实现位置:
Step 1 — 从一个盒子开始。spaceship_generator.py 创建单位立方体 BMesh,并用三个独立的随机缩放系数uniform(0.75, 2.0)拉伸 XYZ 三个轴,得到不规则的初始坯体。
Step 2 — 构建船体:沿法线反复挤出前后端面。对法线朝 X 轴(abs(face.normal.x) > 0.5)的端面,执行num_hull_segments次循环挤出(spaceship_generator.py)。每次挤出默认长度uniform(0.3, 1),途中以约 50% 概率随机施加 Y/Z 缩放(uniform(1.2, 1.5),末端段倾向收缩)、侧向平移(Z 方向uniform(0.1, 0.4)倍段长)与 ±5° 的 Y 轴旋转扰动;约 10% 概率改为调用ribbed_extrude_face()生成"肋骨"结构的船体段。
Step 3 — 为船体添加非对称结构。若create_asymmetry_segments开启(spaceship_generator.py),遍历所有面,跳过宽高比大于 4 的细长面,以约 15% 概率选中面并连续挤出randrange(min, max)次,每次以 75% 概率整体缩小(1 / uniform(1.1, 1.5)),形成炮台基座、副船体等凸出结构。
Step 4 — 为船体添加细节:按面朝向分类,生成引擎、天线、炮塔、灯光等。这是 README 描述中信息量最大的一步。源码 spaceship_generator.py 先按法线朝向把每个面归入engine_faces、grid_faces、antenna_faces、weapon_faces、sphere_faces、disc_faces、cylinder_faces七个桶,再分别调用对应的细节生成函数(详见下一节)。
Step 5 — 有时应用水平对称。约 50% 概率调用bmesh.ops.symmetrize(..., direction="Y")(spaceship_generator.py),把左半船体镜像到右半,产生左右对称的经典飞船造型。垂直对称同理,但默认关闭。
Step 6 — 添加倒角修改器,让造型棱角分明。spaceship_generator.py 为物体添加 Bevel 修改器:宽度uniform(5, 20)、offset_type='PERCENT'(按百分比偏移)、segments=2、profile=0.25(略偏圆滑的轮廓)、limit_method='NONE'(全边倒角)。这一步把程序化几何的硬边打磨成科幻舰船常见的"装甲接缝"质感。
Step 7 — 为最终结果赋予材质。调用create_materials()(见第六节)生成并绑定 hull、hull_lights、hull_dark、exhaust_burn、glow_disc 五套材质,随后将物体原点设为质心并归位到世界原点(spaceship_generator.py)。
Step 8 — (彩蛋)用你的新飞船舰队征服宇宙。README 最后一句的调侃:程序化生成的意义在于以近乎零成本批量产出无限舰船。
五、面分类与七类细节生成器:让船体"活"起来的秘密
Step 4 是整个生成器最出彩的部分。源码先用一个"转盘"(val = random())配合法线朝向完成分类与基础材质指派(spaceship_generator.py):
| 面朝向 | 判定条件 | 分类逻辑(按随机值 val 依次命中) |
|---|---|---|
| 尾部 | face.normal.x < -0.95 | 第一个面必为引擎;之后val>0.75引擎、>0.5圆柱、>0.25网格、否则窗灯面 |
| 前部 | face.normal.x > 0.9 | val>0.7且朝外 → 天线并涂窗灯;>0.4网格;否则窗灯面 |
| 顶部 | face.normal.z > 0.9 | val>0.7且朝外 → 天线;>0.6网格;>0.3圆柱 |
| 底部 | face.normal.z < -0.9 | val>0.75发光圆盘;>0.5网格;>0.25炮塔 |
| 侧面 | abs(face.normal.y) > 0.9 | 第一个面必为炮塔;val>0.75炮塔、>0.6网格、>0.4球体、否则窗灯面 |
| 细长面 | 宽高比 > 3 | 直接跳过("看起来会很蠢") |
随后,七类细节由对应的 BMesh 几何操作实现:
add_exhaust_to_face(spaceship_generator.py):用subdivide_edges把尾面切成网格(cuts = randint(1, 4 - 宽高比)),对每个网格单元挤出排气管:外扩1/uniform(1.3,1.6)、内缩1/uniform(1.05,1.1),侧壁指定exhaust_burn发光材质,形成嵌套的发动机喷口;add_grid_to_face(spaceship_generator.py):2~4 刀网格细分后每个单元挤出uniform(0.025, 0.15)高、缩小 0.8 倍,侧壁随机使用hull_lights或hull材质,模拟外挂装甲板与舷窗阵列;add_cylinders_to_face(spaceship_generator.py):在 1~3 × 1~3 的网格节点上用create_cone生成 6~12 段的圆柱阵列,可充当管线或散热器;add_weapons_to_face(spaceship_generator.py):生成完整炮塔——锥形基座 + 左右护盾 + 可俯仰(upward_angle = uniform(0, 45)度)的炮塔舱 + 双联装炮管,每个炮塔绕 Z 轴随机旋转uniform(0, 90)度;add_sphere_to_face(spaceship_generator.py):create_icosphere(细分 3 次)生成半径uniform(0.4, 1.0) × 面宽的球体,部分嵌入船体表面;add_surface_antenna_to_face(spaceship_generator.py):4~10 × 4~10 网格中约 10% 的节点长出尖塔(diameter1=0的锥体,高uniform(0.1, 1.5) × 面尺寸)加底座,天线与底座材质随机取hull或hull_dark;add_disc_to_face(spaceship_generator.py):32 段的双层锥体构成发光"着陆坪"圆盘,顶面使用glow_disc发光材质。
这些函数全部基于extrude_face(spaceship_generator.py,沿面法线平移挤出)、scale_face(spaceship_generator.py,在面局部坐标系缩放)与get_face_matrix(spaceship_generator.py,由面法线与边向量构造 4×4 变换矩阵)三个几何原语构建,理解这三个原语即可快速读懂全部细节逻辑。
六、材质系统与纹理:全局立方体 UV 的着色方案
README 特别指出:所有纹理都使用全局空间立方体 UV(global-space cube UV)应用,不生成传统 UV 坐标。对应源码中每张贴图节点的projection = 'BOX'([spaceship_generator.py](https://link.gitcode.com/i/a880f98d20d98a98e0c987c6a1ac5a08#L420、L471、L487)),即三平面投影——物体无论怎么建模,纹理都会沿世界轴方向正确贴附,这正是"零 UV 展开"方案可行性的关键。
create_materials()(spaceship_generator.py)为 Material 枚举 的五个成员逐一创建基于 EEVEE 节点树的材质(通过ntree.get_output_node('EEVEE')取输出节点):
| 材质 | 索引 | 用途 | 关键实现 |
|---|---|---|---|
hull | 0 | 标准船体外壳 | 基色 + 法线贴图 |
hull_lights | 1 | 带发光舷窗的外壳 | 基色 + 法线贴图 + 窗色漫反射 + 自发光 |
hull_dark | 2 | 暗色外壳(排气口/天线等) | 基色各通道 ×0.3 |
exhaust_burn | 3 | 发动机燃烧发光材质 | Emission直接设为辉光色 |
glow_disc | 4 | 着陆坪发光材质 | Emission直接设为辉光色 |
颜色生成同样是程序化的:船体基色hull_base_color = hls_to_rgb(random(), uniform(0.05, 0.5), uniform(0, 0.25))——随机色相、5%~50% 饱和度、0~25% 亮度,保证每艘船配色独特但不刺眼;辉光色glow_color = hls_to_rgb(random(), uniform(0.5, 1), 1)则取高饱和高亮度,用于发动机与圆盘。
三张贴图各司其职(位于 textures/ 目录,均为 4096×4096):
- hull_normal.png:法线贴图,为表面增加额外"greebles"(科幻模型常用的细碎凹凸细节),通过
ShaderNodeNormalMap接入 Principled BSDF 的 Normal 输入,且颜色空间设为Raw(spaceship_generator.py); - hull_lights_diffuse.png:加法性漫反射贴图,其 RGB 决定舷窗颜色——节点中先用
ShaderNodeRGB填充船体基色,再以贴图 Alpha 为因子混合(spaceship_generator.py); - hull_lights_emit.png:自发光贴图,输出直接接到材质的
Emission输入,让窗户在暗处真正"发光"(spaceship_generator.py)。
七、种子复现与 Python 脚本调用
README 的 Tips 强调:给generate_spaceship()传入种子即可稳定复现同一艘飞船,例如generate_spaceship('michael')。其原理在源码第 528-529 行:if random_seed: seed(random_seed)——只要种子的字符串非空,生成前就重置 Python 随机数生成器,此后所有random()/uniform()/randint()调用序列完全确定,从而得到逐面、逐细节都一致的飞船。
generate_spaceship()的完整签名(spaceship_generator.py)如下,与面板参数一一对应:
def generate_spaceship(random_seed='', num_hull_segments_min=3, num_hull_segments_max=6, create_asymmetry_segments=True, num_asymmetry_segments_min=1, num_asymmetry_segments_max=5, create_face_detail=True, allow_horizontal_symmetry=True, allow_vertical_symmetry=False, apply_bevel_modifier=True, assign_materials=True):该函数返回生成的bpy.types.Object(名为 'Spaceship' 的网格对象)。在 Blender 的 Scripting 工作区中,你可以这样在脚本模式下批量生产:
import spaceship_generator # 用种子复现同一艘船 ship = spaceship_generator.generate_spaceship('michael') # 关闭细节与材质,快速生成"素模"用于实验 spaceship_generator.generate_spaceship( random_seed='hull-only', create_face_detail=False, assign_materials=False, apply_bevel_modifier=False)需要注意的是:脚本以if __name__ == "__main__"直接运行时(spaceship_generator.py),默认会先调用reset_scene()清场再生成单艘飞船。reset_scene()(spaceship_generator.py)的实现逻辑是:选中所有名称以Spaceship开头的对象并删除,随后清理所有无引用的材质与纹理——这就是 README 所说"默认会删除所有 Spaceship 前缀对象"的来源。若你想在已有飞船的场景中追加生成,README 建议删除或注释主函数中约第 735 行的reset_scene()调用;在当前仓库版本中,该调用位于__main__单船分支(spaceship_generator.py)与电影渲染分支(spaceship_generator.py)两处,注释掉对应行即可保留旧飞船。
八、进阶技巧:自定义纹理与调参心得
README 的 Tips and Tricks 一节提供了三条实战经验,全部在源码中得到印证:
- 关闭自动清场:见上文
reset_scene()说明; - 使用种子复现:
generate_spaceship('michael')这类字符串种子即可稳定复现; - 替换自己的纹理:因为使用全局立方体投影,你完全可以换上自制贴图。替换 textures/hull_normal.png 可改变表面凹凸细节,替换 textures/hull_lights_diffuse.png 可改变舷窗颜色布局,替换 textures/hull_lights_emit.png 可改变窗户的发光图案——只要文件名不变,无需改动任何代码。
此外generate_spaceship()还暴露了大量影响生成过程的参数(段数、对称性、倒角、材质开关等),README 鼓励"多试试它们"。结合参数语义,几个实用的调参方向是:
- 想要修长战舰:拉高
num_hull_segments_max,并关闭create_asymmetry_segments减少杂乱; - 想要重型炮舰:关闭
allow_horizontal_symmetry并提高num_asymmetry_segments_max,侧面的炮塔面会更多; - 想要"骨架"预览:关闭
assign_materials与apply_bevel_modifier,获得干净的低多边形线框造型。
九、极值参数:算法边界的可视化验证
README 用"Extreme examples"一节展示了极端取值下的算法行为——把船体段数与不对称段数推到极大值,观察算法如何"失控"地堆叠几何。这正是理解生成器本质的最佳实验:由于段数上限soft_max=16只是滑块建议,你可以输入更大的数值,让船体拉伸出超长脊柱、非对称结构疯狂外凸,直观看到extrude_face/scale_face迭代累积的效果。
这类实验对二次开发尤其有价值:它暴露了算法对极端输入的鲁棒性边界(例如细长面跳过规则 spaceship_generator.py 正是为了避免畸形面),也帮你理解每个参数对最终形态的贡献权重。
十、彩蛋:批量渲染"舰队展示影片"
README 未展开但源码完整保留的第二个运行模式:把主函数中的generate_single_spaceship改为False(spaceship_generator.py),脚本会进入电影渲染模式——每隔total_spaceship_duration = 1秒生成一艘新飞船,相机绕船旋转拍摄,逐帧渲染输出,从而自动产出"舰队巡礼"影片(spaceship_generator.py)。
该模式内置了一批可调设置:
| 变量 | 默认值 | 含义 |
|---|---|---|
output_path | '' | 输出目录,留空则使用脚本所在目录 |
total_movie_duration | 16(秒) | 影片总时长 |
total_spaceship_duration | 1(秒) | 每艘飞船的展示时长 |
yaw_rate/yaw_offset | 45/220(度/秒) | 相机的偏航角速度与起始角度 |
camera_pole_rate | 1 | 相机俯仰摆动频率 |
camera_pole_pitch_min/max | 15/30(度) | 相机俯仰角上下限 |
camera_pole_length | 10 | 相机与飞船的距离(极轴半径) |
camera_refocus_object_every_frame | False | 是否每帧对准飞船 |
fov/fps | 60(度)/30 | 视场角与帧率 |
res_x/res_y | 1920/1080 | 渲染分辨率 |
渲染帧输出到renders/<时间戳>/<时间戳>_<帧号>.png,场景中若存在名为 'Plane' 的对象,脚本还会自动把它垫到飞船底部当反光地面(spaceship_generator.py)。
十一、许可与致谢
项目以MIT License发布(见仓库根目录 LICENSE),由 Michael Davies 编写并维护;社区贡献者 @panzi 修复了 Bug、提供了正式 GUI 与构建脚本,@mjrthemes 参与修 Bug,@LendoK 完成了 Blender 2.80 移植。得益于 MIT 许可与单文件脚本架构,你完全可以把spaceship_generator.py嵌入自己的 Blender 工具链,或将细节生成器抽取为自定义节点逻辑,在其上构建属于你自己的程序化资产管线。
- 3D建模
- 图形学
【免费下载链接】SpaceshipGenerator
A Blender script to procedurally generate 3D spaceships
相关推荐
如何用SpaceshipGenerator快速生成多样化的3D太空飞船模型
想要在游戏开发或科幻项目中创建独特的3D太空飞船模型吗?SpaceshipGenerator是一个基于Blender的程序化生成脚本,能够帮助设计师和开发者快速
3D建模图形学Rudeness:革命性Android全屏幕适配方案,让你的UI在任何设备上完美呈现
Rudeness:革命性Android全屏幕适配方案,让你的UI在任何设备上完美呈现 Rudeness是一款专注于Android全屏幕适配的解决方案,它以"粗暴
Jest 实践指南:Mock Timer 完全指南,轻松测试异步代码
Jest 实践指南:Mock Timer 完全指南,轻松测试异步代码 Jest 是 JavaScript 生态中最流行的测试框架之一,而 Mock Timer
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考