W Blenderze 2.8 stworzyłem złożony obiekt, który chciałem podzielić na dwa osobne obiekty.

Procedura, którą zastosowałem (cała skrypty): Utwórz obiekt; zduplikowany obiekt; przejdź do trybu edycji i podziel na pół z '' 'clear_inner = True' ''. (działa doskonale!) Następnie wybierz inny (oryginalny) obiekt; przejdź do trybu edycji i podziel na pół z '' 'clear_outer = True' ''. Wydaje się, że pierwszy obiekt również został poddany podziałowi: pozostało tylko kilka punktów / ścian, z których została podzielona.

Załączam kod prostej kostki:

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()

Korzystanie z bisect do oddzielenia kostki w dwóch połówkach

Na rysunku widać, że wynik drugiej połówki z powodzeniem zmniejszył o połowę pierwszą kostkę („lewą”). Ale podzielił również zduplikowany sześcian („prawy”), który był już podzielony na połowę, co skutkowało jedynie twarzą w płaszczyźnie połaci.

Dlaczego to nie działa? Co ja robię źle?

2
Odvkram 2 styczeń 2020, 12:24

1 odpowiedź

Najlepsza odpowiedź

Problem jest spowodowany przez drugą bpy.ops.mesh.select_all(action='SELECT'). Żadne z nich nie jest potrzebne, ponieważ cała siatka jest zaznaczona, dopóki tego nie zmienisz. Powoduje to selekcjonowanie oczek obu kostek, a następnie nakładanie na nich dwóch połówek. Jest to możliwe, ponieważ Blender 2.80 umożliwia edycję wielu obiektów jednocześnie. Jednak źródłem problemu jest select_set(False). Spowoduje to odznaczenie obiektu, ale nie zmieni jego stanu aktywnego. Po przełączeniu trybu edycji dla drugiej kostki edytujesz obie, ponieważ jedna jest zaznaczona, a druga jest aktywna. Możesz tego spróbować, usuwając ostatnie 3 wiersze kodu, a zobaczysz, co się dzieje. Musisz to zmienić, ustawiając bpy.context.view_layer.objects.active, jak widać w drugim kodzie.

Nie musisz też wypełniać wszystkich parametrów funkcji bpy.ops.mesh.bisect, a plane_co jest punktem na płaszczyźnie cięcia, który moim zdaniem powinien wynosić zero, ale to zależy od Ciebie.

Dokumentacja: HTTPS: //docs.blender.org/api/current/bpy.s.mesh.html?highlight=mesh#bpy.s.mesh.bisect.

Edytowany kod przy użyciu 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()

Ten też działa - używając 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()
1
Jan Husák 2 styczeń 2020, 10:35