is it possible to execute remove doubles in object mode using codes?

So is it!?

Yes/No.

bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.remove_doubles()
bpy.ops.object.mode_set(mode='OBJECT')

im gonna redevelop the original mesh extract i developed, one that separates part of the dyntopo mesh via mask for faster sculpting, the only problem is that it lags when welding it back in hi res meshes. ah well…

Is there some particular feature you’re missing from the one in sculpt tools?

the original name was mesh extract, roberto roch developed his own mesh extract, its final form in sculpt tools, in the original addon there are two mesh extracts, mine and roberto roch’s, mine separated parts of the mesh via masks (say the head) from a dyntopo sculpt so you could sculpt with just those resolution and not be bothered by the rest of the body so in principle faster sculpting, also generates a mask on the separation line (mask edge) to protect it from dyntopo change, when done it will be welded together with another button (the simple join and remove doubles routine)

Last I checked you couldn’t directly edit sculpt mask values from python. Has that changed recently? Or have you found another way to mask vertices?

works the same way as mesh extract in sculpt tools (code), mine just separates that part and a bit of hackish code generates the mask on the borders (works by hiding vertices, fill mask, show vertices trick), i could send you the code if you wish, its a short hackish one like the original mesh extract from rob roch

You could use bmesh to avoid the mode change.

@CoDEmanX: give it to me. :D, coz i dont know how, just the working part where you remove doubles on a single object in object mode. if this works, i’m gonna include this on a demo vid for the sculpt ui, retopo support i’m going to do

well it should be efficient if the mesh is already in edit mode, otherwise you need to create a bmesh from mesh, remove doubles and write everything back to mesh, which may actually be slower…

import bpy
import bmesh

me = bpy.context.object.data

if me.is_editmode:
    bm = bmesh.from_edit_mesh(me)
    bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.001)
    bmesh.update_edit_mesh(me)
else:
    bm = bmesh.new()
    bm.from_mesh(me)
    bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.001)
    bm.to_mesh(me)

thanks a lot bro, will test it out later, :D, will post a vid here too on what i’m trying to achieve, hopefully we could destroy the lag of the process by a lot

heres a bit of a demo of the tool

bl_info = {
“name”: “Mesh Extract”,
“author”: “Ian Lloyd Dela Cruz, Roberto Roch Diago”,
“version”: (1, 2),
“blender”: (2, 5, 5),
“location”: “3d View > Tool shelf”,
“description”: “Simple Sculpting SubTool Operator”,
“warning”: “”,
“wiki_url”: “”,
“tracker_url”: “”,
“category”: “Sculpting”}

import bpy
from bpy.props import *
import random
import bmesh

def edgemask():
wm = bpy.context.window_manager

bpy.ops.paint.mask_flood_fill(mode='VALUE', value=0)
bpy.ops.object.mode_set(mode='EDIT')
bpy.context.space_data.show_occlude_wire = True
bpy.ops.mesh.select_mode(type='EDGE')
bpy.ops.mesh.select_all(action = 'DESELECT')
bpy.ops.mesh.select_non_manifold()
for i in range(0, 5):
    bpy.ops.mesh.select_more()
bpy.ops.mesh.select_all(action = 'INVERT')
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode='SCULPT')
bpy.ops.paint.mask_flood_fill(mode='VALUE', value=1)
bpy.ops.paint.hide_show(action='SHOW', area='ALL')

def extractfaces():

bpy.ops.paint.hide_show(area='MASKED')
bpy.ops.object.mode_set(mode='EDIT')
#bpy.context.space_data.show_occlude_wire = True
bpy.ops.mesh.select_mode(type='EDGE')
bpy.ops.mesh.select_all(action = 'SELECT')
bpy.ops.mesh.separate()
bpy.ops.mesh.reveal()
bpy.ops.object.mode_set(mode='SCULPT')
edgemask()

def weldfaces():

bpy.ops.object.join()
#bpy.ops.object.mode_set(mode='EDIT')
me = bpy.context.object.data

if me.is_editmode:
    bm = bmesh.from_edit_mesh(me)
    bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.001)
    bmesh.update_edit_mesh(me)
else:
    bm = bmesh.new()
    bm.from_mesh(me)
    bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.001)
    bm.to_mesh(me)
#bpy.context.space_data.show_occlude_wire = True
#bpy.ops.mesh.select_mode(type='EDGE')
#bpy.ops.mesh.select_all(action = 'DESELECT')
#bpy.ops.mesh.select_non_manifold()
#bpy.ops.mesh.select_more()
#bpy.ops.mesh.remove_doubles()
#bpy.ops.mesh.select_all(action = 'DESELECT')
bpy.ops.object.mode_set(mode='SCULPT')
bpy.ops.paint.mask_flood_fill()

class MeshExtractOperator(bpy.types.Operator):
‘’‘Exracts Sculpt Mesh’’’
bl_idname = “mesh.extract”
bl_label = “Mask Extract”
bl_options = {‘REGISTER’, ‘UNDO’}

@classmethod
def poll(cls, context):
    return context.active_object is not None and context.active_object.mode == 'SCULPT'

def execute(self, context):
    currobj = context.active_object
    if currobj.users_group == ():
        idcol = "%06x" % random.randint(0,0xFFFFFF)
        gflag = currobj.name + "_" + idcol + "_group"
        if bpy.data.groups.find(gflag) == -1:
            bpy.ops.object.mode_set(mode='OBJECT')
            bpy.ops.group.create(name=gflag)
            bpy.ops.object.mode_set(mode='SCULPT')
        else:
            bpy.ops.object.mode_set(mode='OBJECT')
            bpy.ops.object.group_link(group = gflag)
            bpy.ops.object.mode_set(mode='SCULPT')                   
         
    if context.active_object.mode == 'SCULPT':    
        if context.sculpt_object.use_dynamic_topology_sculpting:
            bpy.ops.sculpt.dynamic_topology_toggle()
            extractfaces()
            bpy.ops.sculpt.dynamic_topology_toggle()
        else:                           
            extractfaces()

    return {'FINISHED'}

class MeshEdgeMaskOperator(bpy.types.Operator):
‘’‘Edge Masks Sculpt Mesh’’’
bl_idname = “mesh.edgemask”
bl_label = “Mesh Edge Mask”
bl_options = {‘REGISTER’, ‘UNDO’}

@classmethod
def poll(cls, context):
    return context.active_object is not None and context.active_object.mode == 'SCULPT'

def execute(self, context): 
    wm = context.window_manager
    if context.active_object.mode == 'SCULPT':    
        if context.sculpt_object.use_dynamic_topology_sculpting:
            bpy.ops.sculpt.dynamic_topology_toggle()
            edgemask()
            bpy.ops.sculpt.dynamic_topology_toggle()
        else:                           
            edgemask()

    return {'FINISHED'}

class MeshWeldOperator(bpy.types.Operator):
‘’‘Unifies previously extracted or joins sculpt meshes’’’
bl_idname = “mesh.weld”
bl_label = “Mesh Weld”
bl_options = {‘REGISTER’, ‘UNDO’}

@classmethod
def poll(cls, context):
    return context.active_object is not None and len(bpy.context.selected_objects)>1

def execute(self, context):
    activeObj = context.active_object
    for SelectedObject in bpy.context.selected_objects :
        if SelectedObject != activeObj :
            if context.active_object.mode == 'OBJECT':
                weldfaces()
                bpy.ops.object.mode_set(mode='OBJECT')
                
            if context.active_object.mode == 'SCULPT':
                if context.sculpt_object.use_dynamic_topology_sculpting:
                    bpy.ops.sculpt.dynamic_topology_toggle()
                    weldfaces()
                    bpy.ops.sculpt.dynamic_topology_toggle()
                else:
                    weldfaces()
                    bpy.ops.object.mode_set(mode='SCULPT')

            bpy.context.scene.objects.active = activeObj
    
    return {'FINISHED'}

class MeshExtractPanel(bpy.types.Panel):
“”“UI panel for Mesh Extraction Buttons”""
bl_label = “Mask Split”
bl_idname = “OBJECT_PT_extract”
bl_space_type = ‘VIEW_3D’
bl_region_type = ‘TOOLS’

def draw(self, context):
    layout = self.layout

    wm = context.window_manager
    
    row = layout.row(align=True)
    row.alignment = 'EXPAND'

    try:
        row.operator("mesh.extract", text='Split')
    except:
        pass
    row3 = layout.row(align=True)
    row3.alignment = 'EXPAND'
    row3.operator("mesh.edgemask", text="Edge Mask")
    row4 = layout.row(align=True)
    row4.alignment = 'EXPAND'
    row4.operator("mesh.weld", text="Weld")
    row5 = layout.row(align=True)

def register():
bpy.utils.register_module(name)

bpy.types.WindowManager.smokebomb= BoolProperty(default=False)
bpy.types.WindowManager.weldto= BoolProperty(default=False)

bpy.types.WindowManager.tricount= BoolProperty(default=False)

#bpy.types.WindowManager.unibools = BoolProperty(default=False)

bpy.types.WindowManager.solidthickness= FloatProperty(
min = -1, max = 1,
default = 0.1)

bpy.types.WindowManager.smoothmesh= IntProperty(
min = 0, max = 20,
default = 1)

bpy.types.WindowManager.maskwall= IntProperty(
min = 1, max = 10,
default = 1)

bpy.types.WindowManager.offsetthickness= FloatProperty(
min = -1, max = 1,
default = 0.1)

bpy.types.WindowManager.smoothoffset= IntProperty(
min = 0, max = 20,
default = 1)    

def unregister():
bpy.utils.unregister_module(name)

if name == “main”:
register()

here’s the code, i haven’t gone to refining this yet, it also have some of the early mesh extract coding in there, lol

please you code tags, or all code formatting is lost (and indentation matters in python)

@CoDEmanX:

http://www.pasteall.org/blend/26613

here sorry about that, my internet is about to run out and i panicked. the goal is simple reduce the overall delay in the process, its actually fast, faster with your code added, the only thing slowing it down in the video is the fact that the model is already 600k tri and the code re-enters dyntopo mode.

After giving this some thought and trying out some code, I’ve come to the conclusion that while nice when it works, the feature has way to much potential to destroy your mesh.

If you forget for a minute that you shouldn’t be using masks, you may and up with two meshes that you have no way of joining other than very painfully in edit mode. If there was some way of protecting the edge vertices other than a mask, which the user can edit freely, maybe it’d be feasible. As it is, I’ve decided not to add it to sculpt tools.

This is really a workaround for mesh hiding not increasing performance, and should IMHO be addressed at that level.

@Piotr:

yeah, you’re right, its clumsy, but it’s somewhat the best solution at present, i’m sculpting a full body alien cyborg now at present 850k tri, and the whole process is becoming technical as the resolution increases, though i had tried a repair tool (bridging the separation mark) in its early days, it really is a painful process if one is not careful.

unless of course, we get some tool that freezes parts of the mesh from dyntopo process. but i’m just daydreaming.

im gonna post a wip at the dyntopo test thread of the robot.