1
$\begingroup$

I am trying to get the furthest/closest vertices on both the X and Y axis for a mesh object. However, Blender returns empty lists for the coordinates for the same object. I initially thought the mesh has not been loaded into blender but then I realized that although the object has been loaded, I still might get an empty list. I may note that the problem occurs for random meshes and not only for an specific mesh. Below I post the relevant codes:

Here's how I load a mesh:

    obj_file = os.path.join(model_path)
    bpy.ops.import_scene.obj(filepath=obj_file)

###############################################################
## obj file comes as a bunch of different meshes, unify them ##
###############################################################

    obs = []
    for ob in bpy.context.scene.objects:
        # whatever objects you want to join...
        if ob.type == 'MESH':
            obs.append(ob)


    if len(obs) > 1:
        # Join the meshes
        ctx = bpy.context.copy()
        ctx['active_object'] = obs[0]
        ctx['selected_objects'] = obs
        # we need the scene bases as well for joining
        ctx['selected_editable_bases'] = [bpy.context.scene.object_bases[ob.name] for ob in obs]
        bpy.ops.object.join(ctx)


    for ob in bpy.context.selectable_objects:
        #if ob.name.startswith('simplified_model'):
        if ob.type == 'MESH':
            obj = ob            # this is for scoping reasons
            obj.select = True
            bpy.context.scene.objects.active = obj

    if dissolve != None:
        if dissolve:
            # This is to be used for simplifying mesh models
            bpy.ops.object.mode_set(mode='EDIT')
            bpy.ops.mesh.dissolve_limited()
            bpy.ops.object.mode_set(mode='OBJECT')

            obj.collision.use = True

And then setting up the scene:

        bpy.context.scene.render.resolution_x = 448
        bpy.context.scene.render.resolution_y = 448
        bpy.context.scene.render.resolution_percentage = 100

        s = 1.25
        bpy.context.scene.camera.location.x = s
        bpy.context.scene.camera.location.y = s
        bpy.context.scene.camera.location.z = s

        empty = bpy.data.objects.new('empty', None)
        bpy.context.scene.objects.link(empty)
        bpy.context.scene.update()



        camera_follow_constraint = bpy.context.scene.camera.constraints.new(type='TRACK_TO')
        camera_follow_constraint.target = obj #empty
        camera_follow_constraint.track_axis = 'TRACK_NEGATIVE_Z'
        camera_follow_constraint.up_axis = 'UP_Y'

And finally here's how I get the coordinates. Sometimes, the xs or ys lists are returned empty and I haven't been able to find out why:

mat = obj.matrix_world
coords = [mat * vert.co for vert in obj.data.vertices]


xs = [co.x for co in coords]
ys = [co.y for co in coords]

I am using Python 3. I would appreciate if someone can give me some help on this.

Here are two links for two meshes for which I experienced the problem. I may note again that the problem does not only occur for these two models. I have thousands of meshes and each time it occurs for a bunch of them:

Model1 Model2

Thanks

$\endgroup$
3
  • $\begingroup$ Can you provide a minimal code example to reproduce your problem? Basically you mean that obj contains no data. It is not clear from your code what obj actually is. It looks like it is the last of bpy.context.selectable_objects: of type mesh. Are you sure this object exists and actually have vertices? Print out some information about this object. $\endgroup$
    – Noidea
    Oct 7, 2016 at 15:24
  • $\begingroup$ Well the thing is the problem occurs occasionally. Sometimes it occurs for the same mesh and sometimes it does not. I update my original post and put some links to some of the mesh models I use. I select the last (and actually first) mesh since I only have one mesh object in the scene (in addition to camera and lamp/light). $\endgroup$
    – Amir
    Oct 7, 2016 at 15:43
  • $\begingroup$ well, add print obj.name to check that you have the correct object $\endgroup$
    – Noidea
    Oct 7, 2016 at 15:51

1 Answer 1

1
$\begingroup$

Here is a take on this. Removed the context override on the join op, the import wavefront obj operator returns all imported objects as selected. This is the list context.selected_objects whereas scene.objects is all the objects in the scene. Not sure why you would want to use context.selectable_objects for this case.

Simply deselect if not a mesh, assign first mesh obj as active (if there are mesh objs) , and then call bpy.ops.object.join().

Used bmesh for limited dissolve, takes away the need to pop modes.

Tested fine on object1.obj

import bpy
from bpy import context
scene = context.scene
import bmesh

# make a bmesh
bm = bmesh.new()
dissolve = True
filepath = "/home/batfinger/Downloads/model1.obj"

bpy.ops.import_scene.obj(filepath=filepath)

mesh_objs = []
for o in context.selected_objects:
    if not o.type == 'MESH':
        o.select = False
        print(o.name, "not a mesh")
        continue
    if dissolve:
        # use bmesh to dissolve
        bm.from_mesh(o.data)
        print("Pre dissolve", len(bm.verts))
        geom = bmesh.ops.dissolve_limit(bm, angle_limit=0.082665,
                                        verts=bm.verts,
                                        edges=bm.edges,
                                        delimit=0)
        bm.to_mesh(o.data)
        print("Post dissolve", len(o.data.vertices))
        bm.clear()
    # append the mesh object
    mesh_objs.append(o)
bm.free()
# if no mesh objs do nothing
if mesh_objs:
    scene.objects.active = mesh_objs[0]

    bpy.ops.object.join()
    # newly joined obj
    obj = scene.objects.active
    # look at verts
    verts = obj.data.vertices
    vertsx = [v.co.x for v in verts]
    vertsy = [v.co.y for v in verts]
    print(len(vertsx), len(vertsy))
$\endgroup$
3
  • $\begingroup$ A list comprehension like meshes = [o for o in bpy.context.selected_objects[:] if o.type=="MESH"] might be suitable in this case. $\endgroup$
    – p2or
    Oct 8, 2016 at 16:23
  • $\begingroup$ @poor would still need to go thru list to deselect non meshes for the join operator. Thought it was easier to deselect or dissolve and append in the loop in this case. $\endgroup$
    – batFINGER
    Oct 8, 2016 at 16:35
  • $\begingroup$ yeah, you are right. The loop is required, only thought we can save some lines... $\endgroup$
    – p2or
    Oct 8, 2016 at 16:48

You must log in to answer this question.

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