您现在的位置是:首页 >技术杂谈 >Blender 3D建模——AI脚本3D建模技巧网站首页技术杂谈

Blender 3D建模——AI脚本3D建模技巧

水中加点糖 2025-03-03 00:01:02
简介blender的ai插件实现自动建模

前些天刷到了阮德升(Nguyen Duc Thang)老爷子的机械结构视频,颇受震撼。

Nguyen Duc Thang的模型源文件大多为AutoDesk Inventor格式的,3D建模领域小白的我折腾了一下体验还不错,奈何Inventor软件太贵最后只得转到Blender了。

Blender
Blender完全免费且开源,及具备script脚本功能,这为有编程知识背景的我们带来了许多遍历,即便对Blender软件操作不熟悉,通过翻阅Blender API生成式AI的普及下,也能让我们快速创作出我们想要的模型。

为避免遗忘,特此本文记录一些使用AI进行建模的技巧,方便后续快速查找。
(本文使用的Blender版本为4.3.2,脚本与方法基本通用)

1.软件基本操作

1.1 推荐插件

  • Bool Tool (布尔操作)
  • MeasureIt(测量)
  • Edit Mesh Tools(精确尺寸修改)

1.2 日志输出控制台

打开[窗口]->[切换系统控制台]
log-console
脚本print的输出信息将在此控制台中展示(调试利器)

1.3 查看操作对应的代码

在[建模]面板中对图形进行操作,之后进入[脚本],在界面左下角可以看到所做操作对应的代码。
script_record
如代码过多,可按A全选清空

2.定位脚本

2.1 定位点脚本

import bpy
import bmesh

# 获取当前选中的对象(确保是网格对象)
obj = bpy.context.active_object
if obj and obj.type == 'MESH':
    # 进入编辑模式
    bpy.ops.object.mode_set(mode='EDIT')
    # 获取当前网格数据
    me = obj.data
    bm = bmesh.from_edit_mesh(me)
    # 遍历所有选中的顶点并打印其坐标
    print("选中顶点的坐标:")
    for v in bm.verts:
        if v.select:  # 如果顶点被选中
            print(f"顶点 {v.index} 的坐标: {v.co}")
    # 退出编辑模式
    bpy.ops.object.mode_set(mode='OBJECT')
else:
    print("当前选中的对象不是网格类型!")

示例截图(可一次选中多个点)
point

2.2 定位边脚本

import bpy
import bmesh

# 获取当前选中的对象
obj = bpy.context.active_object

# 确保选中的对象是网格类型
if obj and obj.type == 'MESH':
    # 进入编辑模式
    bpy.ops.object.mode_set(mode='EDIT')
    
    # 获取当前网格数据
    me = obj.data
    bm = bmesh.from_edit_mesh(me)
    
    # 获取当前选中的边
    selected_edges = [edge for edge in bm.edges if edge.select]
    
    # 输出选中边的信息
    print("当前选中的边:")
    for edge in selected_edges:
        print(f"边索引: {edge.index}, 顶点: {[v.index for v in edge.verts]}, 长度: {edge.calc_length()}")
    
    # 退出编辑模式
    bpy.ops.object.mode_set(mode='OBJECT')
else:
    print("当前选中的对象不是网格类型!")

示例截图
side

2.3 AI生成定位提示词

点定位

输出blender的script代码:在blender的编辑模式下选中了某个点,输出选中点的坐标和索引信息

面定位

输出blender的script代码:在blender的编辑模式下选中了某个面,输出选中面的信息

3.常见操作

3.1 边倒角

对应API:https://docs.blender.org/api/current/bpy.ops.mesh.html#bpy.ops.mesh.bevel

示例:在一个立方体的一个边上进行倒角操作,代码如下:

import bpy
import bmesh

bpy.ops.mesh.primitive_cube_add(size=1,scale = (2, 0.5, 0.8))
# 获取当前选中的对象(即刚创建的立方体)
obj = bpy.context.active_object
# 进入编辑模式
bpy.ops.object.mode_set(mode='EDIT')
# 获取编辑模式下的网格数据
me = obj.data
bm = bmesh.from_edit_mesh(me)
# 确保索引表是最新的
bm.edges.ensure_lookup_table()
# 确保所有边未被选中
for edge in bm.edges:
    edge.select = False
# 选中第3个边
bm.edges[2].select = True
# 更新选择状态
bmesh.update_edit_mesh(me)
# 执行边线倒角操作,offset为宽带,segments为切段数(平滑程度),profile为弧度(0.5为圆)
bpy.ops.mesh.bevel(offset=0.9, segments=20, profile=0.5)

效果:
bevel

3.2 布尔操作(打洞)

对应API:https://docs.blender.org/api/current/bpy.ops.object.html#bpy.ops.object.modifier_apply

示例:在一个立方体上打一个洞,代码如下:

import bpy
import bmesh

def apply_boolean_difference():
    """对场景中的对象执行布尔差集操作"""
    # 确保场景中对象全选
    bpy.ops.object.select_all(action='SELECT')
    # 获取当前场景中的所有对象
    objects = bpy.context.selected_objects

    if len(objects) < 2:
        print("需要至少两个对象才能执行布尔差集操作")
        return

    # 将第一个对象作为布尔操作的基础对象
    base_obj = objects[0]
    # 确保进入对象模式
    bpy.ops.object.mode_set(mode='OBJECT')
    # 将其激活并选中
    bpy.context.view_layer.objects.active = base_obj
    # 遍历其余对象并执行布尔差集操作
    for obj in objects[1:]:
        # 添加布尔修改器
        bool_mod = base_obj.modifiers.new(name=f"Bool_Difference_{obj.name}", type='BOOLEAN')
        bool_mod.operation = 'DIFFERENCE'
        bool_mod.object = obj
        # 应用布尔修改器
        bpy.ops.object.modifier_apply(modifier=bool_mod.name)
        # 删除参与布尔操作的对象
        bpy.data.objects.remove(obj, do_unlink=True)

def create_scene():
    # 创建立方体
    bpy.ops.mesh.primitive_cube_add(size=1,scale = (1, 0.3, 0.5))
    # 在立方体上右侧创建一个圆柱体,1.5708为90度
    bpy.ops.mesh.primitive_cylinder_add(radius=1, depth=2, enter_editmode=False, location=(0.2, 0, 0), rotation=(1.5708, -1.5708, 0), scale=(0.1, 0.1, 1))
    # 执行布尔运算,difference求差集
    apply_boolean_difference()

if __name__ == "__main__":
    create_scene()

效果:
bool

3.3 椭圆体

创建一个中间直两边是圆的椭圆体(TT马达转动轴)

主要使用到的API:

示例代码如下:

import bpy
import bmesh

# 创建圆柱体
bpy.ops.mesh.primitive_cylinder_add(radius=1, depth=2, enter_editmode=False, location=(0, 0, 0), rotation=(1.5708, -1.5708, 0), scale=(0.1, 0.1, 0.1))
# 获取创建的圆柱体对象
cylinder_obj = bpy.context.active_object
# 进入编辑模式以访问网格数据
bpy.ops.object.mode_set(mode='EDIT')
me = cylinder_obj.data
bm = bmesh.from_edit_mesh(me)
# deselect all vertices
for vertex in bm.verts:
    vertex.select = False
# 选择特定的顶点(0, 1, 32, 33),顶点索引使用前面的订点定位脚本确定
indices_to_select = [0, 1, 32, 33]
# 遍历顶点并选择
for v in bm.verts:
    if v.index in indices_to_select:
        v.select = True
# 更新选择状态
bmesh.update_edit_mesh(me)
# 创建边连接这些选中的顶点
selected_verts = [v for v in bm.verts if v.select]
print(len(selected_verts))
if len(selected_verts) == 4:
    bm.edges.new([selected_verts[1], selected_verts[3]])  
    bm.edges.new([selected_verts[0], selected_verts[2]])
# 更新网格数据
bmesh.update_edit_mesh(me)
# deselect all edges
for edge in bm.edges:
    edge.select = False  # 取消所有边的选择
# 选择特定的边(2, 48, 96, 97),边索引使用前面的边定位脚本确定
edges_to_select = [2, 48, 96, 97]
for edge in bm.edges:
    if edge.index in edges_to_select:
        edge.select = True
# 更新选择状态
bmesh.update_edit_mesh(me)
# 执行倒角操作
bpy.ops.mesh.bevel(offset=0.006, offset_pct=0, affect='EDGES')
# 更新选择状态
bmesh.update_edit_mesh(me)
# 确保索引表是最新的
bm.edges.ensure_lookup_table()
# 取消所有边的选择
for edge in bm.edges:
    edge.select = False
# 要选择的边索引,边索引使用前面的边定位脚本确定
target_edge_indices = [87, 91, 100, 105]
selected_vertices = []
# 遍历选择边的顶点并记录其 X 坐标
edge_x_coords = []
for edge_index in target_edge_indices:
    if edge_index < len(bm.edges):
        edge = bm.edges[edge_index]
        edge.select = True
        for vert in edge.verts:
            if vert not in selected_vertices:
                selected_vertices.append(vert)
                edge_x_coords.append(vert.co.x)
# 获取选中边顶点的最小 x 坐标
x_threshold = min(edge_x_coords) if edge_x_coords else None
print(x_threshold)
# 更新选择状态
bmesh.update_edit_mesh(me)
# 选择位于边下方的所有顶点
for vertex in bm.verts:
    print(vertex.co.x)
    if x_threshold is not None and vertex.co.x < x_threshold:
        vertex.select = True
# 更新选择状态
bmesh.update_edit_mesh(me)
# 执行移动操作
bpy.ops.transform.translate(value=(0, 1.30385e-8, -0.13), 
                             orient_type='GLOBAL', 
                             orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), 
                             orient_matrix_type='GLOBAL', 
                             constraint_axis=(True, False, True), 
                             mirror=True, 
                             use_proportional_edit=False, 
                             proportional_edit_falloff='SMOOTH', 
                             proportional_size=1, 
                             use_proportional_connected=False, 
                             use_proportional_projected=False, 
                             snap=False, 
                             snap_elements={'INCREMENT'}, 
                             use_snap_project=False, 
                             snap_target='CLOSEST', 
                             use_snap_self=True, 
                             use_snap_edit=True, 
                             use_snap_nonedit=True, 
                             use_snap_selectable=False, 
                             release_confirm=True)
# 退出编辑模式
bpy.ops.object.mode_set(mode='OBJECT')

运行效果:
ellipse

4.综合示例(TT马达转柄)

将上面列举的示例整合在一起,创建出一个TT马达的转柄。

示例效果:
tt-motor
用到的一些AI提示词:

实现:选中索引为87、91、100、105的边的顶点,并让这4个边下面的所有顶点执行如下命令实现move,判断是否为边下面的方法为通过边的顶点Z轴坐标判断,Z轴坐标比选中的边顶点坐标小则代表位于边下面

修改脚本代码,以选中创建的cylinder的第0、1、32、33这4个顶点连成线

修改代码,在创建完边后选中索引为2、48、96、97的边,执行命令bpy.ops.mesh.bevel(offset=0.00647185, offset_pct=0, affect=‘EDGES’)

修改代码,实现:选择索引为87、91、100、105的边,并选中这4个边下面的所有边执行命令实现move

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。