blender 2.8 python,使用二分法将对象分成两半会产生错误的结果

blender 2.8 python, dividing object in 2 halfs using bisect is producing wrong result

我使用 Blender 2.8 创建了一个复杂的对象,我想将其拆分为两个单独的对象。

我遵循的过程(所有脚本):创建对象;重复对象;进入编辑模式并用“'clear_inner=True'”平分。 (工作完美!) 然后 select 其他(原始)对象;进入编辑模式并用“'clear_outer=True'”平分。 现在第一个对象似乎也受到平分:只有一些 points/faces 是平分的。

我包含了一个简单立方体的代码:

import bpy

bpy.ops.mesh.primitive_cube_add(size=4, enter_editmode=False, location=(0, 0, 0))
bpy.context.object.name="left"    

bpy.ops.object.duplicate_move(OBJECT_OT_duplicate={"linked":False, "mode":'TRANSLATION'})  
bpy.context.object.name="right"    

# cutting in two (bisect)

bpy.data.objects['left'].select_set(False)
bpy.data.objects['right'].select_set(True)

bpy.ops.object.editmode_toggle()
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.bisect(plane_co=(0, 28.5249, 5.80484), plane_no=(1, 0, 0), use_fill=True, clear_inner=True, threshold=0.0001, xstart=1042, xend=1068, ystart=647, yend=130)
bpy.ops.object.editmode_toggle()

bpy.data.objects['right'].select_set(False)
bpy.data.objects['left'].select_set(True)

bpy.ops.object.editmode_toggle()
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.bisect(plane_co=(0, 28.5249, 5.80484), plane_no=(1, 0, 0), use_fill=True, clear_outer=True, threshold=0.0001, xstart=1042, xend=1068, ystart=647, yend=130)
bpy.ops.object.editmode_toggle()

using bisect to seperate cube in two halfs

在图片中您看到第二个平分的结果成功地将第一个立方体减半 ('left')。但它也分裂了复制的立方体('right'),它已经被减半,只在平分平面上产生一个面。

为什么不起作用?我究竟做错了什么?

问题是由第二个 bpy.ops.mesh.select_all(action='SELECT') 引起的。 None 是必需的,因为在您更改它之前会选择整个网格。这会导致选择两个立方体的网格,然后对它们进行平分。这是可能的,因为 Blender 2.80 允许您一次编辑多个对象。问题的根源是select_set(False)。这将取消选择对象,但不会更改其活动状态。当您切换第二个多维数据集的编辑模式时,您正在编辑两者,因为一个被选中并且第二个处于活动状态。您可以通过删除代码的最后 3 行来尝试,您将看到发生了什么。您必须通过设置 bpy.context.view_layer.objects.active 来更改它,如第二个代码所示。

此外,您不需要填写 bpy.ops.mesh.bisect 函数的所有参数,并且 plane_co 是切割平面上的点,我认为它应该为零,但这取决于您。

文档:https://docs.blender.org/api/current/bpy.ops.mesh.html?highlight=mesh#bpy.ops.mesh.bisect

使用 bpy.ops.object.select_all(action='DESELECT') 编辑代码:

...

# deselect all objects
bpy.ops.object.select_all(action='DESELECT')

# select just right object
bpy.data.objects['right'].select_set(True)

bpy.ops.object.editmode_toggle()
bpy.ops.mesh.bisect(plane_co=(0, 0, 0), plane_no=(1, 0, 0), use_fill=True, clear_inner=True)
bpy.ops.object.editmode_toggle()

# deselect all objects
bpy.ops.object.select_all(action='DESELECT')

# select just left object
bpy.data.objects['left'].select_set(True)

bpy.ops.object.editmode_toggle()
bpy.ops.mesh.bisect(plane_co=(0, 0, 0), plane_no=(1, 0, 0), use_fill=True, clear_outer=True)
bpy.ops.object.editmode_toggle()

这个也有效 - 使用 bpy.context.view_layer.objects.active:

...

bpy.data.objects['left'].select_set(False)
bpy.data.objects['right'].select_set(True)
bpy.context.view_layer.objects.active = bpy.data.objects['right'] # set right as active

bpy.ops.object.editmode_toggle()
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.bisect(plane_co=(0, 0, 0), plane_no=(1, 0, 0), use_fill=True, clear_inner=True)
bpy.ops.object.editmode_toggle()

bpy.data.objects['right'].select_set(False)
bpy.data.objects['left'].select_set(True)
bpy.context.view_layer.objects.active = bpy.data.objects['left'] # set left as active

bpy.ops.object.editmode_toggle()
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.bisect(plane_co=(0, 0, 0), plane_no=(1, 0, 0), use_fill=True, clear_outer=True)
bpy.ops.object.editmode_toggle()