Files
blender-portable-repo/scripts/addons/jremesh-tools-main/jrt_remesh_op.py
T
2026-03-17 14:30:01 -06:00

229 lines
7.2 KiB
Python

import bpy
from bpy.types import Operator
import os
import shutil
import tempfile
import subprocess
from . jrt_pref import get_preferences
from . utils.select_utils import *
class JRT_OT_Remesh(Operator):
bl_idname = "object.jrt_remesh_op"
bl_label = "Quad remesh"
bl_description = "Execute quad remesher"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return len(context.selected_objects) > 0
def is_blender_quadriflow(self, context):
return context.scene.remesher == "Blender Quadriflow"
def is_instant_meshes(self, context):
return context.scene.remesher == "Instant Meshes"
def get_app_path(self, context):
pref = get_preferences()
if self.is_instant_meshes(context):
return pref.im_filepath
return None
def get_app_name(self, context):
if self.is_instant_meshes(context):
return "Instant Meshes"
return None
def execute(self, context):
# Instant meshes remesher is used
self.report({'INFO'}, "JRemesh started")
scn = context.scene
mode = get_mode()
to_object()
self.try_triangulate(context)
active_obj_name = context.active_object.name
if self.is_instant_meshes(context):
try:
app_name = self.get_app_name(context)
app_path = self.get_app_path(context)
if not os.path.isfile(app_path):
raise IOError(f"Path to {app_name} is missing.")
tmp_dir = tempfile.gettempdir()
orig = os.path.join(tmp_dir, 'orig_object.obj')
output = os.path.join(tmp_dir, 'remeshed_object.obj')
# Export original object
if bpy.app.version >= (3, 3, 0):
bpy.ops.wm.obj_export(filepath=orig,
check_existing=False,
export_selected_objects=True,
apply_modifiers=True,
export_smooth_groups=False,
smooth_group_bitflags=False,
export_normals=True,
export_uv=True)
else:
bpy.ops.export_scene.obj(filepath=orig,
check_existing=False,
use_selection=True,
use_mesh_modifiers=True,
use_edges=True,
use_smooth_groups=False,
use_smooth_groups_bitflags=False,
use_normals=True,
use_uvs=True)
orig_object = bpy.data.objects[active_obj_name]
self.do_remesh(app_path, orig, output, context)
# Import remeshed object
if bpy.app.version >= (3,3,0):
bpy.ops.wm.obj_import(filepath=output)
else:
bpy.ops.import_scene.obj(filepath=output,
use_split_objects=False,
use_smooth_groups=False,
use_image_search=False)
# Post import remeshed object
remeshed_object = bpy.context.selected_objects[0]
remeshed_object.name = active_obj_name + '_rm'
remeshed_object.data.materials.clear()
for mat in orig_object.data.materials:
remeshed_object.data.materials.append(mat)
for edge in remeshed_object.data.edges:
edge.use_edge_sharp = False
deselect_all()
select(remeshed_object)
bpy.ops.object.shade_flat()
bpy.ops.mesh.customdata_custom_splitnormals_clear()
orig_object.hide_set(True)
make_active(remeshed_object)
os.remove(output)
except IOError as ioerr:
self.report({'ERROR'}, "JRemesh: {0}".format(ioerr))
else:
self.report({'INFO'}, "JRemesh completed")
# Quadriflow remesher is used
elif self.is_blender_quadriflow(context):
try:
# Duplicate active mesh
bpy.ops.object.duplicate()
orig_object = bpy.data.objects[active_obj_name]
bpy.ops.object.quadriflow_remesh(
use_mesh_symmetry=scn.qf_use_mesh_sym,
use_preserve_sharp=scn.qf_preserve_sharp,
use_preserve_boundary=scn.qf_preserve_mesh_boundary,
preserve_paint_mask=scn.qf_preserve_paint_mask,
smooth_normals=scn.qf_smooth_normals,
target_faces=scn.qf_face_count
)
orig_object.hide_set(True)
new_name = active_obj_name + "_rm"
get_active().name = new_name
# Remove modifiers if triangulate was set
if scn.rm_triangulate:
get_active().modifiers.clear()
except RuntimeError as re:
self.report({'ERROR'}, "JRemesh: {0}".format(re))
else:
self.report({'INFO'}, "JRemesh completed")
self.try_make_manifold(scn)
to_mode(mode)
return {'FINISHED'}
def try_triangulate(self, context):
if context.scene.rm_triangulate:
for m in get_active().modifiers:
if m.type == "TRIANGULATE":
return
bpy.ops.object.modifier_add(type='TRIANGULATE')
def try_make_manifold(self, scn):
if scn.rm_fill_holes:
to_edit()
select_mesh()
bpy.ops.mesh.fill_holes()
deselect_mesh()
def do_remesh(self, app_path, orig, output, context):
cmd = self.build_im_command(context, app_path, orig, output)
subprocess.run(cmd)
# Quadriflow modifier can be called?
#
# def build_qf_command(self, context, app_path, orig, output):
# options= []
# if context.scene.qf_sharp:
# options.append('-sharp')
# options.extend(['-i', orig,
# '-o', output,
# '-f', str(context.scene.qf_face_count)])
# return [app_path] + options
def build_im_command(self, context, app_path, orig, output):
options = ['-c', str(context.scene.crease),
'-v', str(context.scene.vertex_count),
'-S', str(context.scene.smooth),
'-o', output]
if context.scene.deterministic:
options.append('-d')
if context.scene.dominant:
options.append('-D')
if context.scene.intrinsic:
options.append('-i')
if context.scene.boundaries:
options.append('-b')
return [app_path] + options + [orig]