BMesh 简介
BMesh 是 Blender 中用于表示和操作网格数据的底层数据结构系统,它是传统网格数据结构的高级替代品。
主要特点
-
灵活拓扑支持:
- 支持 n-gons(任意边数的多边形),而不仅仅是三角形和四边形
- 允许边和顶点不属于任何面
-
高效操作:
- 设计用于支持复杂的网格编辑操作
- 提供丰富的 API 用于网格操作
-
数据结构:
- 基于半边数据结构(Half-Edge)
- 包含三种基本元素:顶点(verts)、边(edges)和面(faces)
使用场景
BMesh 主要用于:
- 编写 Blender 的网格编辑工具
- 开发复杂的网格处理插件
- 执行高级网格操作如布尔运算、细分等
基本元素
- BMVert:表示顶点
- BMEdge:表示边
- BMFace:表示面
BMesh 提供了比传统网格更强大的功能,特别是在处理复杂拓扑和非流形几何时表现优异。
访问方式
在 Python API 中,可以通过 bmesh
模块访问 BMesh 功能,通常用于编写网格处理脚本和插件。
创建一个bmesh后,可以贴图不同的材质吗?
是的,在一个 bmesh
对象中创建的多个面,完全可以赋予不同的材质,只要你后续把 bmesh
写入 mesh,并对 mesh.polygons[i].material_index
设置正确即可。
✅ 关键点总结
操作目标 | 是否可行 | 方法 |
---|---|---|
一个对象中多个面贴不同材质 | ✅ 支持 | 设置 face.material_index |
bmesh 创建时直接贴材质 | ❌ 不直接支持 | 需要在 bmesh.to_mesh() 之后,通过 mesh.polygons[...] 设置 |
一个 Object 支持多个材质 | ✅ 支持 | obj.data.materials.append(...) 添加多个材质槽 |
✅ 正确做法:一个 Object
、多个材质、不同面贴图
1. 创建 bmesh
添加多个面
import bpy
import bmesh# 新建 mesh 和 object
mesh = bpy.data.meshes.new("MyMesh")
obj = bpy.data.objects.new("MyObject", mesh)
bpy.context.collection.objects.link(obj)bm = bmesh.new()# 顶点
v1 = bm.verts.new((0, 0, 0))
v2 = bm.verts.new((2, 0, 0))
v3 = bm.verts.new((2, 2, 0))
v4 = bm.verts.new((0, 2, 0))v5 = bm.verts.new((3, 0, 0))
v6 = bm.verts.new((5, 0, 0))
v7 = bm.verts.new((5, 2, 0))
v8 = bm.verts.new((3, 2, 0))# 两个面
face1 = bm.faces.new([v1, v2, v3, v4])
face2 = bm.faces.new([v5, v6, v7, v8])
2. 写入 mesh
bm.to_mesh(mesh)
bm.free()
mesh.update()
3. 添加两个材质到 obj
mat1 = bpy.data.materials.new("Red")
mat2 = bpy.data.materials.new("Green")mat1.diffuse_color = (1, 0, 0, 1) # RGBA
mat2.diffuse_color = (0, 1, 0, 1)obj.data.materials.append(mat1)
obj.data.materials.append(mat2)
4. 给 mesh.polygons[i]
设置材质索引
# 给第一个面用第一个材质
obj.data.polygons[0].material_index = 0# 给第二个面用第二个材质
obj.data.polygons[1].material_index = 1
结果
🔁 所以流程是:
- 在
bmesh
中构建所有顶点和面; bm.to_mesh(mesh)
把面数据写到mesh.polygons
;- 添加所有材质到
obj.data.materials
; - 遍历
mesh.polygons[i]
,设置对应的material_index = X
。
❗注意事项
- 必须保证
obj.data.materials
中的材质数量 >= 所有material_index
的最大值 + 1; material_index
是一个整数索引(指向材质槽的位置),不是材质本身;- 所有
material_index
设置必须在bm.to_mesh()
后进行,因为bmesh
阶段没有material_index
概念。
撰写该博文的原因是有一个需要用脚本来控制一个立方体不同面的贴图,其实现的基本原理和上述代码是一致的。