Simpul tanpa loop
Saya sedang mengerjakan skrip Python untuk mengekspor mesh. Saya perlu mengekspor normals, jadi saya menggunakan kode ini:
def get_custom_vertex_normals(mesh_obj):
mesh_obj.data.calc_normals_split()
nrm_avg_list = [None] * len(mesh_obj.data.vertices)
for loop in mesh_obj.data.loops:
nrm_avg_list[loop.vertex_index] = (loop.normal.x, loop.normal.y, loop.normal.z)
return nrm_avg_list
(Seperti yang ditunjukkan oleh @batFinger, metode ini akan mengambil info dari loop terakhir yang berbagi simpul yang sama. Ini bagus untuk alur kerja saya sendiri karena saya menggabungkan normals sebelum mengekspor, tetapi pembaca pertanyaan ini harus menggunakan metodenya jika mereka menginginkan normals rata-rata untuk sebuah simpul).
Masalahnya adalah nrm_avg_listmemiliki elemen Nonedi atasnya. Apakah beberapa debugging dan efektif simpul ini tidak memiliki loop pada mereka.
Apakah mencoba untuk membersihkan mesh saya (menghapus geometri longgar) tetapi simpul ini masih ada (dan saya tidak dapat menemukannya di viewport).
Bagaimana cara membersihkan simpul nakal ini? Apakah ada cara, menggunakan Python API (menghindari bpy.opsjika mungkin) untuk menghapus simpul ini?
Jawaban
Skrip bmesh untuk menghapus verts yang tidak ditautkan ke wajah mana pun
import bpy
import bmesh
from bpy import context
ob = context.object
me = ob.data
# clean all verts not connected to faces
bm = bmesh.new()
bm.from_mesh(me)
bmesh.ops.delete(
bm,
geom=[v for v in bm.verts if not v.link_faces],
context='VERTS', # default
)
bm.to_mesh(me)
Re-metode pertanyaan Anda
Masalah dengan metode pertanyaan adalah bahwa vert yang sama dapat menjadi anggota dari banyak loop. Hanya simpul di perulangan terakhir yang akan ditugaskan ke daftar Anda.
Temukan dengan satu ke banyak hubungan seperti ini yang defaultdictkelasnya collectionsketika dibuat dengan listmemberikan kunci apa pun nilai default list()atau []yang dapat ditambahkan ke.
import bpy
from collections import defaultdict
def get_custom_vertex_normals(me):
me.calc_normals_split()
loop_norms = defaultdict(list)
for loop in me.loops:
loop_norms[loop.vertex_index].append(loop.normal)
return loop_norms
ob = bpy.context.object
loop_norms = get_custom_vertex_normals(ob.data)
for i, normals in loop_norms.items():
print(i, [tuple(round(x, 4) for x in v) for v in normals])
ketika dijalankan pada kubus default, keluaran:
0 [(0.0, 0.0, -1.0), (1.0, -0.0, 0.0), (0.0, 1.0, 0.0)]
1 [(0.0, 0.0, -1.0), (1.0, -0.0, 0.0), (-0.0, -1.0, -0.0)]
2 [(0.0, 0.0, -1.0), (-0.0, -1.0, -0.0), (-1.0, 0.0, -0.0)]
3 [(0.0, 0.0, -1.0), (-1.0, 0.0, -0.0), (0.0, 1.0, 0.0)]
4 [(0.0, 0.0, 1.0), (1.0, -0.0, 0.0), (0.0, 1.0, 0.0)]
7 [(0.0, 0.0, 1.0), (-1.0, 0.0, -0.0), (0.0, 1.0, 0.0)]
6 [(0.0, 0.0, 1.0), (-0.0, -1.0, -0.0), (-1.0, 0.0, -0.0)]
5 [(0.0, 0.0, 1.0), (1.0, -0.0, 0.0), (-0.0, -1.0, -0.0)]
yaitu setiap vert memiliki 3 loop untuk setiap wajah yang dimilikinya.
Rata-rata normal dapat dihitung melalui
avge_normal = sum(normals, Vector()) / len(normals)
atau
avge_normal = sum(normals, Vector()).normalized()
untuk mendapatkan vektor penjumlahan yang dinormalisasi. yang ketika dijalankan pada kubus default diedit di atas
for i, normals in loop_norms.items():
print(i, sum(normals, Vector()).normalized())
keluaran
0 <Vector (0.5774, 0.5774, -0.5774)>
1 <Vector (0.5774, -0.5774, -0.5774)>
2 <Vector (-0.5774, -0.5774, -0.5774)>
3 <Vector (-0.5774, 0.5774, -0.5774)>
4 <Vector (0.5774, 0.5774, 0.5774)>
7 <Vector (-0.5774, 0.5774, 0.5774)>
6 <Vector (-0.5774, -0.5774, 0.5774)>
5 <Vector (0.5774, -0.5774, 0.5774)>
yang bisa lebih seperti hasil yang Anda kejar.
untuk memilih simpul dengan API standar, Anda perlu membatalkan pilihan semuanya dan meninggalkan editmode. Pengaturan .select ke False tidak berfungsi, hanya pengaturan ke True yang didukung menggunakan pendekatan ini.
import bpy
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.mode_set(mode='OBJECT')
for v in bpy.context.object.data.vertices:
if v.co[1] > 0:
v.select = True
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.delete(type='VERT')