11
$\begingroup$

I want to untriangulate every object in my scene with this script:

import bpy

for ob in bpy.data.objects:
    bpy.ops.mesh.tris_convert_to_quads(limit=0.9, uvs=False, vcols=False, sharp=False, materials=False)

But it doesn't work in object mode, any ideas on how I can get it working?

$\endgroup$

1 Answer 1

14
$\begingroup$

There are 2 ways you can do this:

  1. Standard API (bpy) - the most straightforward is to set each object in editmode and run the tool.

    Notice I'm not using bpy.data.objects, This will operate on all objects in your blend file, not just your scene, instead use bpy.context.scene.objects.

    import bpy
    
    scene = bpy.context.scene
    for ob in scene.objects:
        if ob.type == 'MESH':
            scene.objects.active = ob
            bpy.ops.object.mode_set(mode='EDIT', toggle=False)
    
            bpy.ops.mesh.reveal()
            bpy.ops.mesh.select_all(action='SELECT')
    
            # execute any editmode tool
            bpy.ops.mesh.tris_convert_to_quads(limit=0.9,
                                               uvs=False,
                                               vcols=False,
                                               sharp=False,
                                               materials=False)
    
            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
    

    Note: You need to be careful trying to edit all objects, some may be hidden, not on a visible layer, or linked in from an external file (and can't be edited). For this reason its often better to use context.selected_editable_objects


  2. bmesh module (Docs) - bypass bpy.ops modes and edit the mesh directly. In this case using the bmesh api. Note that this is specific to meshes, curves, metaballs etc will need to use bpy.ops still since they don't have an equivalent to bmesh.

    import bpy
    import bmesh
    
    scene = bpy.context.scene
    for ob in scene.objects:
        if ob.type == 'MESH':
            me = ob.data
            bm = bmesh.new()
            bm.from_mesh(me)
    
            # execute any bmesh operator
            bmesh.ops.join_triangles(bm, faces=bm.faces,
                                     limit=0.9,
                                     cmp_sharp=False,
                                     cmp_uvs=False,
                                     cmp_vcols=False,
                                     cmp_materials=False)
            bm.to_mesh(me)
            bm.free()
    

    Note: The examples above may touch the same mesh multiple times since many objects can share the mesh, You almost never want this, at worst it gives invalid results because the tool runs many times, at best the script just runs slowly and does a lot of useless calculation.

    Here is an example which ensures meshes are only edited once.

    import bpy
    import bmesh
    
    scene = bpy.context.scene
    unique_meshes = set([ob.data for ob in scene.objects if ob.type == 'MESH'])
    
    for me in unique_meshes:
        bm = bmesh.new()
        bm.from_mesh(me)
    
        # execute any bmesh operator
        bmesh.ops.join_triangles(bm, faces=bm.faces,
                                 limit=0.9,
                                 cmp_sharp=False,
                                 cmp_uvs=False,
                                 cmp_vcols=False,
                                 cmp_materials=False)
        bm.to_mesh(me)
        bm.free()
    
$\endgroup$
2
  • $\begingroup$ One question though, is it best to use the bmesh API or bpy.ops? Or does it not matter? $\endgroup$
    – JamesNZ
    Aug 29, 2013 at 5:05
  • 1
    $\begingroup$ When possible I would avoid using bpy.ops, These wrap tools in a way that relies on the context and dont have a good way to pass args and return results to scripts. If there is an alternative (as with bmesh), its better integrated into python, and you don't have to worry about active object, modes, visible layers etc. $\endgroup$
    – ideasman42
    Aug 29, 2013 at 8:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .