Como usar a operação loopcut_slide sem nenhuma IU?
Portanto, preciso executar alguns operadores básicos de corte e deslizamento de loop em uma malha. O índice de borda é conhecido e o valor do slide também é fixo.
usando o método de substituição de Como faço para substituir o contexto de bpy.ops.mesh.loopcut? sou capaz de executar o corte com sucesso dentro do editor de script do blender. mas quando executado sem a IU, o script fornece um erro.
Eu também gostaria de saber se há métodos alternativos não baseados na IU para realizar cortes de loop com atualizações de UV adequadas
aqui está uma versão de exemplo que adiciona cortes em loop e operação suave. testado no editor de script do Blender 2.83
import bpy
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
bpy.ops.mesh.primitive_cube_add(enter_editmode=False, align='WORLD', location=(0, 0, 0))
bpy.ops.object.editmode_toggle()
win = bpy.context.window
scr = win.screen
areas3d = [area for area in scr.areas if area.type == 'VIEW_3D']
region = [region for region in areas3d[0].regions if region.type == 'WINDOW']
override = {'window':win,
'screen':scr,
'area' :areas3d[0],
'region':region[0],
'scene' :bpy.context.scene,
}
bpy.ops.mesh.loopcut_slide(override,
MESH_OT_loopcut={
"number_cuts":5,
"smoothness":1,
"falloff":'INVERSE_SQUARE',
"object_index":0,
"edge_index":4,
"mesh_select_mode_init":(False, True, False)
},
TRANSFORM_OT_edge_slide={
"value":0,
"single_side":False,
"use_even":False,
"flipped":False,
"use_clamp":True,
"mirror":True,
"snap":False,
"snap_target":'CLOSEST',
"snap_point":(0, 0, 0),
"snap_align":False,
"snap_normal":(0, 0, 0),
"correct_uv":False,
"release_confirm":False,
"use_accurate":False})
bpy.ops.object.editmode_toggle()
```
Respostas
Subdivide edge loops é um bom ajuste para slides com loop cut.
O loop cut and slide é um operador avançado que está fazendo um pouco dos bastidores. Pode selecionar uma única aresta e o corte em loop selecionará e cortará o anel de aresta definido pela aresta.
Bmesh subdividir operadores de borda
Se um loop de borda é alimentado no operador bmesh subdivide edge com usar preenchimento de grade, ele emula um corte e slide de loop básico.
Também existe o operador subdivide edge ring bmesh, que lançará um erro se as arestas enviadas não forem anéis de aresta válidos.
Existem várias opções disponíveis para ambos os operadores, incluindo a configuração dos espaçamentos dos cortes e o tipo de declínio suave.
Como o loop cut e o slide estão subdividindo as bordas, você perceberá uma série de opções familiares.
Consulte a docs ..
Consulte Adicionando uma malha cubóide para ver isso em operação para criar um$i \times j \times k$ cubóide.
Selecionando os anéis de aresta.
Usei um método recursivo semelhante ao mostrado aqui.
Como encontrar loops e anéis de malha
Não adicionei nenhuma verificação para não encontrar um anel de borda válido. (por exemplo, as últimas arestas encontradas devem ser iguais ou limites)
Teste o script, selecione a borda no modo de edição e execute o script. Usa a aresta ativa para selecionar o anel da aresta.
import bpy
import bmesh
cuts = 4
context = bpy.context
ob = context.object
me = ob.data
bm = bmesh.from_edit_mesh(me)
edge = bm.select_history.active
def edge_loops(edge):
def walk(edge):
yield edge
edge.tag = True
for l in edge.link_loops:
loop = l.link_loop_radial_next.link_loop_next.link_loop_next
if not (len(loop.face.verts) != 4 or loop.edge.tag):
yield from walk(loop.edge)
for e in bm.edges:
e.tag = False
return list(walk(edge))
if isinstance(edge, bmesh.types.BMEdge):
'''
bmesh.ops.subdivide_edges(
bm,
edges=edge_loops(edge),
cuts=cuts,
smooth_falloff='INVERSE_SQUARE',
use_grid_fill=True,
)
'''
bmesh.ops.subdivide_edgering(
bm,
edges=edge_loops(edge),
cuts=cuts,
profile_shape='INVERSE_SQUARE',
profile_shape_factor=0.0,
)
bmesh.update_edit_mesh(me)
Note ter usado um modo de edição bmesh a título de exemplo. Para o script de modo de objeto, carregue o bmesh conforme mostrado em sua resposta . O bisect IMO não vai dar um bom resultado se as bordas do loop de borda não estiverem bem alinhadas.
Evite postar, exclua todos os códigos de objetos em scripts de pergunta quando não for necessário.
bmesh bisect faz exatamente isso ... mas não é automatizado como o bpy loopcut, então certifique-se de selecionar todas as faces que você precisa para cortar e você mesmo precisará fornecer o local e a direção do corte.
import bpy
import bmesh
import math
import mathutils
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
bpy.ops.mesh.primitive_plane_add(enter_editmode=False, align='WORLD', location=(0, 0, 0))
def bmesh_loopcut(bm,face_list,direction_axis,center='auto'):
for f in bm.faces:
f.select = False
bm.faces.ensure_lookup_table()
for f in face_list:
bm.faces[f].select = True
edges = [e for e in bm.edges if e.select == True]
faces = [f for f in bm.faces if f.select == True]
if center=='auto':
weights = [f.calc_area() for f in faces]
weighted_centres = [f.calc_area() * f.calc_center_median() for f in faces]
cutting_point = sum(weighted_centres, mathutils.Vector()) / sum(weights)
else:
cutting_point = bpy.context.scene.cursor.location
geom = []
geom.extend(edges)
geom.extend(faces)
result = bmesh.ops.bisect_plane(bm,dist=0.01,geom=geom,plane_co=cutting_point,plane_no=direction_axis)
# Make a new BMesh
bm = bmesh.new()
obj = bpy.context.object
ob = obj
me = ob.data
bm = bmesh.new()
bm.from_mesh(me)
face_cut=([0])
bmesh_loopcut(bm,face_cut,[1,0,0])
bm.to_mesh(me)
bm.free()
me.update()
```