Bagilah wajah objek berdasarkan area dalam skrip python
Saya memiliki pemandangan berikut dengan banyak objek:
Ini terutama model cad sehingga Anda dapat melihat beberapa wajah pada beberapa objek berbeda lebih besar dibandingkan dengan yang lain. Yang ingin saya lakukan adalah membagi setidaknya yang besar jika tidak semuanya (mengingat beberapa yang kecil yang akan memenuhi ambang batas wilayah yang panjang mungkin juga perlu direstrukturisasi) sehingga memenuhi batasan wilayah. Saya juga ingin objek baru yang terbagi tidak kehilangan properti material / size / name.
Selain itu, mengingat bahwa saya perlu melakukan itu untuk banyak adegan (hingga beberapa ratus) saya tidak tahu apakah mungkin untuk menangani tugas dalam mode GPU atau sesuatu (sejujurnya karena saya belum mencobanya dalam praktik, CPU mungkin cukup cepat).
Saya menemukan utas serupa di sini membagi semua wajah yang luasnya lebih besar dari 1mm sampai setiap area wajah lebih kecil dari 1mm tetapi solusinya dijelaskan dalam UI bukan dalam skrip python yang saya lebih suka.
Memperbarui:
Menguji solusi di bawah ini dari @batFINGER dengan operator remesh tidak memberikan hasil yang diinginkan (saya telah mengujinya dengan pengaturan 'SHARP' dan octree_depth=7-10, yang tampaknya paling relevan untuk menjaga geometri awal tetap utuh). Selain itu, tampaknya merusak pemetaan tekstur UV yang tidak saya inginkan jika memungkinkan. Saya sudah mencoba dyntopo dari UI, tetapi tampaknya juga menimbulkan masalah dengan pemetaan tekstur dan menjaga geometri awal tetap utuh.
Misalnya Remesh operator dengan octree_depth=7:
bm = bmesh.new()
dg = context.evaluated_depsgraph_get()
for o in obs:
rm = o.modifiers.new("Remesh", type='REMESH')
rm.mode = 'SHARP'
# rm.sharpness = 100
rm.octree_depth = 7
#rm.scale = 0.2
#rm.threshold = 0.5
dg.update()
bm.from_object(o,dg)
o.modifiers.clear()
bm.to_mesh(o.data)
bm.clear()
bm.free()
Dari apa yang saya pahami jika saya ingin menjaga geometri tetap utuh, saya benar-benar perlu membuat banyak permukaan kecil yang sebenarnya tidak saya inginkan dan tetap saja ini tidak dijamin. Untuk kasus saya, ukuran permukaan yang dimiliki furnitur harus mencukupi juga untuk objek pesawat besar saya, yaitu langit-langit, lantai, dinding, dll.
Maka dari itu saya telah mencoba mengikuti beberapa contoh yang diberikan pada tautan berikut ini:
https://blender.stackexchange.com/a/93597/106722
https://blender.stackexchange.com/a/168193/106722
https://blender.stackexchange.com/a/120244/106722
https://blender.stackexchange.com/a/163936/106722
dan saya telah menulis kode berikut di mana saya mencoba membagi objek saya berdasarkan panjang tepinya:
import bpy
from mathutils import Vector
from bpy import context
import numpy as np
import bmesh
def subdivide_edge_cuts(obj, cuts=1):
me = obj.data
# New bmesh
bm = bmesh.new()
# load the mesh
bm.from_mesh(me)
### collapse short edges
edges_len_average = 0
edges_count = 0
shortest_edge = 10000
for edge in bm.edges:
if True:#edge.is_boundary:
edges_count += 1
length = edge.calc_length()
edges_len_average += length
if length < shortest_edge:
shortest_edge = length
edges_len_average = edges_len_average/edges_count
print("Total edges: {}".format(len(bm.edges)))
print("Shortest edge: {}".format(shortest_edge))
print("Average edge: {}".format(edges_len_average))
subdivide_edges = []
for edge in bm.edges:
cut_count = int(edge.calc_length()/shortest_edge)*cuts
if cut_count <= 0:
cut_count = 0
subdivide_edges.append([edge,cut_count])
print("Edges to subdivide: {}\n".format(len(subdivide_edges)))
# group edges by found cut
grouped_edges = {}
for edge, cut in subdivide_edges:
grouped_edges.setdefault(cut, []).append(edge)
# This works
# bmesh.ops.subdivide_edges(bm, edges=list(np.array(subdivide_edges)[:,0]), cuts=5, use_grid_fill=True)
# This doesn't work
for cut in grouped_edges:
bmesh.ops.subdivide_edges(bm, edges=grouped_edges[cut], cuts=cut, use_grid_fill=True)
# Write back to the mesh
bm.to_mesh(me)
me.update()
bpy.ops.object.select_all(action='SELECT')
obs = [o for o in context.selected_objects
if o.type == 'MESH']
for ob in obs:
subdivide_edge_cuts(ob)
Tapi sepertinya itu tidak benar-benar berhasil. Jika di sisi lain membagi semua tepi dengan potongan tetap maka tampaknya berfungsi tetapi sekali lagi semua tepi dipotong dengan cara yang sama yang bukan yang saya inginkan.
Misalnya, ini adalah keluaran dengan potongan tetap 5 di dinding dan langit-langit:
Outputnya tampak baik-baik saja kecuali wajah di batas dengan tepi panjang yang semakin berantakan (ini juga sesuatu yang perlu saya temukan cara untuk mengatasinya jika memungkinkan).
Tahu mengapa forloop saya untuk membagi tepi dengan cut tidak berfungsi. Saran lain untuk mengatasi masalah ini juga diterima.
Jawaban
Remesh pengubah.
Salah satu jawaban yang terkait dengan merekomendasikan menggunakan pengubah remesh, tanpa melihat ke dalam pengaturan yang benar, yaitu ini adalah kode untuk "melakukannya" tetapi belum menyelidiki pengaturan, dan nilai apa yang harus ditetapkan.
Ulangi objek, tambahkan pengubah, dapatkan mesh yang cacat, hapus mesh pembaruan pengubah.
import bpy
import bmesh
from bpy import context
obs = [o for o in context.selected_objects
if o.type == 'MESH']
bm = bmesh.new()
dg = context.evaluated_depsgraph_get()
for o in obs:
rm = o.modifiers.new("Remesh", type='REMESH')
rm.mode = 'BLOCKS'
#rm.scale = 0.2
#rm.threshold = 0.5
dg.update()
bm.from_object(
o,
dg)
o.modifiers.clear()
bm.to_mesh(o.data)
bm.clear()
bm.free()