You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
149 lines
7.1 KiB
149 lines
7.1 KiB
import bpy |
|
import bmesh |
|
|
|
|
|
def active_object(obj): |
|
bpy.context.view_layer.objects.active = obj |
|
obj.select_set(True) |
|
|
|
|
|
def get_obj_max_foot(workdir,filename,filename_tex): |
|
# 1.模型导入和初始化 |
|
# 删除当前场景中的所有对象: |
|
# use_global=False表示只删除当前场景中的对象,而不会影响到其他场景中的对象;confirm=False表示删除时不需要确认。 |
|
bpy.ops.object.delete(use_global=False, confirm=False) |
|
bpy.ops.import_scene.obj(filepath=filename) # 导入指定路径的 OBJ 格式模型文件 |
|
|
|
bpy.context.scene.unit_settings.scale_length = 0.001 # 将场景的长度单位缩放为0.001,相当于将长度单位从默认的米缩小为毫米 |
|
bpy.context.scene.unit_settings.length_unit = 'CENTIMETERS' # 将场景的长度单位设置为厘米 |
|
bpy.context.scene.unit_settings.mass_unit = 'GRAMS' # 将场景的质量单位设置为克 |
|
|
|
obj = bpy.context.selected_objects[0] # 获取了当前选中的对象列表,然后通过 [0] 取得列表中的第一个对象 |
|
bpy.context.view_layer.objects.active = obj # 将变量 obj 设置为当前活动对象 |
|
obj.select_set(True) # 将变量 obj 的选择状态设置为 True,表示选中该对象 |
|
pid = obj.name # 获取该对象的名字 |
|
|
|
# 对选定的对象进行对齐操作 |
|
bpy.ops.object.align(align_mode='OPT_1', relative_to='OPT_1', align_axis={'Z'}) |
|
# 设置选中对象的原点,参数1:将原点设置为对象的质心,参数2:使用对象的几何中心作为参考 |
|
bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS', center='MEDIAN') |
|
# 将选中对象的位置坐标分别设置为 (0, 0),即将对象移动到世界坐标系的原点位置 |
|
obj.location[0] = 0 |
|
obj.location[1] = 0 |
|
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) # 将选中对象的位置、旋转和缩放应用到对象的数据中 |
|
|
|
# 2.选择要复制的对象 |
|
obj_duplicate = obj.copy() |
|
obj_duplicate.data = obj.data.copy() |
|
bpy.context.collection.objects.link(obj_duplicate) |
|
# obj_duplicate.location.x += 5.0 |
|
bpy.ops.object.select_all(action='DESELECT') # 取消选中全部对象 |
|
|
|
# 3.处理复制的对象的脚底缝合边 |
|
# 选中复制对象 |
|
bpy.context.view_layer.objects.active = obj_duplicate |
|
obj_duplicate.select_set(True) |
|
|
|
selected_obj = bpy.context.active_object # 获取当前选中的对象 |
|
bpy.context.view_layer.objects.active = selected_obj # 将对象转换到编辑模式 |
|
|
|
# 切换到3D视图编辑模式 |
|
bpy.context.area.type = 'VIEW_3D' |
|
bpy.ops.object.mode_set(mode='EDIT') |
|
bpy.ops.mesh.select_all(action='SELECT') # 选择所有的边 |
|
|
|
# 切换到UV编辑器 |
|
bpy.context.area.type = 'IMAGE_EDITOR' |
|
pid_img = f"{pid}Tex1.jpg" |
|
bpy.ops.image.open(filepath=filename_tex, directory=workdir, |
|
files=[{"name": pid_img, "name": pid_img}], relative_path=True, |
|
show_multiview=False) |
|
bpy.context.area.ui_type = 'UV' |
|
bpy.ops.uv.select_all(action='SELECT') # 选择所有UV贴图顶点 |
|
# 标记所有沿孤岛的边为缝合边 |
|
bpy.ops.uv.seams_from_islands() |
|
bpy.context.area.type = 'VIEW_3D' |
|
bpy.ops.object.mode_set(mode='OBJECT') |
|
|
|
# 获取世界坐标系下z轴接近0的顶点的索引 |
|
z_zero_vertex_indices = [] |
|
for i, vertex in enumerate(selected_obj.data.vertices): |
|
world_vertex = selected_obj.matrix_world @ vertex.co |
|
if abs(world_vertex.z) < 0.2: |
|
z_zero_vertex_indices.append(i) |
|
# 将对象转换回对象模式 |
|
bpy.ops.object.mode_set(mode='OBJECT') |
|
# 创建一个新的顶点组,并将z_zero_vertices中的顶点添加到该顶点组中 |
|
vg = selected_obj.vertex_groups.new(name="z_zero_vertices") |
|
for index in z_zero_vertex_indices: |
|
vg.add([index], 1.0, 'REPLACE') |
|
# 将选中的顶点设置为活动顶点 |
|
bpy.ops.object.mode_set(mode='EDIT') |
|
bpy.ops.mesh.select_all(action='DESELECT') |
|
bpy.ops.object.vertex_group_select() # 选中待处理的顶点 |
|
bpy.ops.mesh.mark_seam(clear=True) # 取消所选区域内的缝合边 |
|
bpy.ops.mesh.region_to_loop() # 选择选定面周围的边界边!!! |
|
bpy.ops.mesh.select_mode(type="EDGE") # 转换为线模式 |
|
bpy.ops.mesh.mark_seam(clear=False) # 标记所选的线为缝合边 |
|
|
|
# 选中脚底顶点组 |
|
bpy.ops.uv.select_all(action='DESELECT') |
|
bpy.ops.object.vertex_group_set_active(group='z_zero_vertices') # 设置活动顶点组 |
|
bpy.ops.object.vertex_group_select() # 选择分配给活动顶点组的所有顶点 |
|
bpy.ops.uv.unwrap() |
|
|
|
# 处理贴图脚底部分孤岛,其他孤岛保持不变 |
|
# (1)反选模型顶点,方便贴图固定不需要处理的区域 |
|
bpy.ops.mesh.select_all(action='INVERT') |
|
bpy.context.area.type = 'IMAGE_EDITOR' # 切换到贴图模式 |
|
bpy.context.area.ui_type = 'UV' |
|
bpy.ops.uv.pin(clear=False) |
|
bpy.ops.object.vertex_group_set_active(group='z_zero_vertices') # 设置活动顶点组 |
|
bpy.ops.object.vertex_group_select() # 选择分配给活动顶点组的所有顶点 |
|
# (2)脚底部位UV展开,平均孤岛比例,重新排列孤岛 |
|
bpy.ops.uv.select_all(action='SELECT') |
|
bpy.ops.uv.average_islands_scale() |
|
bpy.ops.uv.pack_islands(margin=0.001) |
|
|
|
bpy.context.area.type = 'VIEW_3D' |
|
bpy.ops.object.mode_set(mode='OBJECT') |
|
|
|
# 4. 烘焙模式,参数设置 |
|
bpy.ops.object.select_all(action='DESELECT') # 取消选中全部对象 |
|
# # 选中原始对象 |
|
bpy.context.view_layer.objects.active = obj |
|
obj.select_set(True) |
|
# 选中复制对象 |
|
bpy.context.view_layer.objects.active = obj_duplicate |
|
obj_duplicate.select_set(True) |
|
bpy.context.scene.render.engine = 'CYCLES' |
|
bpy.context.scene.cycles.device = 'GPU' |
|
bpy.context.scene.cycles.preview_samples = 1 |
|
bpy.context.scene.cycles.samples = 1 |
|
bpy.context.scene.cycles.bake_type = 'DIFFUSE' |
|
bpy.context.scene.render.bake.use_pass_direct = False |
|
bpy.context.scene.render.bake.use_pass_indirect = False |
|
bpy.context.scene.render.bake.use_selected_to_active = True |
|
bpy.context.scene.render.bake.cage_extrusion = 0.01 |
|
bpy.ops.object.bake(type='DIFFUSE') # 开始 Bake |
|
|
|
# 5. 导出模型和贴图 |
|
bpy.ops.object.select_all(action='DESELECT') # 取消选中全部对象 |
|
# 选中复制对象 |
|
bpy.context.view_layer.objects.active = obj_duplicate |
|
obj_duplicate.select_set(True) |
|
bpy.ops.wm.obj_export(filepath=filename, export_selected_objects=True) |
|
bpy.context.area.type = 'IMAGE_EDITOR' # 切换到 |
|
bpy.ops.image.save_as(filepath=filename_tex) |
|
bpy.context.area.type = 'TEXT_EDITOR' # 切换到文本编辑器 |
|
|
|
|
|
if __name__ == '__main__': |
|
workdir = 'E:\\117080\\print_model' |
|
# filename = f'{workdir}\\117080_12cm_x1.obj' |
|
filename = f'{workdir}\\117080.obj' |
|
filename_tex = f'{workdir}\\117080Tex1.jpg' |
|
save_obj = f"{workdir}\\bake\\117080Tex1.obj" |
|
save_tex = f"{workdir}\\bake\\117080Tex1.jpg" |
|
|
|
get_obj_max_foot() |