I make a terrain (ground + vegetation mesh) for an old game engine which needs all the geometry to be separated into chunks consisting of ~ 25k vertices max.
So far I use my "separate by radius" script which enters Edit mode, select faces in a given radius, separate using bpy.ops.mesh.separate(type='SELECTED')
and continues until it is separated completely.
This is the original script:
import bpy
import bmesh
import time
class SeparateByRadius(bpy.types.Operator):
bl_idname = "object.separate_by_radius"
bl_label = "Separate by Radius"
bl_options = {'REGISTER', 'UNDO'}
max_diameter = bpy.props.IntProperty(name="Radius", default=0)
def execute(self, context):
if self.max_diameter == 0:
return {'FINISHED'}
context = bpy.context
scene = context.scene
bpy.ops.object.mode_set(mode="EDIT")
obj = bpy.context.edit_object
me = obj.data
bm = bmesh.from_edit_mesh(me)
time_start_updating = time.time()
def separateNextChunk():
bm.faces.ensure_lookup_table()
if len(bm.faces) == 0:
bpy.ops.object.mode_set(mode="OBJECT")
bpy.ops.object.select_all(action='DESELECT')
context.active_object.select = True
bpy.ops.object.delete()
else:
active_median = bm.faces[-1].calc_center_median()
continue_next = False
for f in bm.faces:
f.select = False
if (f.calc_center_median()-active_median).length <= self.max_diameter / 2:
f.select = True
continue_next = True
bpy.ops.mesh.separate(type='SELECTED')
# Show the updates in the viewport
# and recalculate n-gon tessellation.
bmesh.update_edit_mesh(me, True)
if continue_next == True:
separateNextChunk()
separateNextChunk()
print("Separated in " + str(time.time() - time_start_updating))
return {'FINISHED'}
def register():
bpy.utils.register_class(SeparateByRadius)
def unregister():
bpy.utils.unregister_class(SeparateByRadius)
if __name__ == "__main__":
register()
While it does the job, it is EXTREMELY slow - the splitting often results into ~2000 objects and this take hours to separate using this method. I suspect the reason is that we are doing modifications of the original (large) mesh with each single separation.
I have tried to find some alternative methods that would create new objects from the original one, but as I am not a Python programmer, it started to be too complex for me.
I would appreciate so much if anyone can share some specific ideas how to enhance the script to get it work noticeably faster with the same output, the requirements are:
- separating into chunks of a given max vertex count or given area
- separation must be based on the existing mesh, no cutting
- UVs, materials and vertex colors must be preserved perfectly