Mesh to script helper

Here is another handy little helper script I thought I’d post… It takes the context object mesh and saves the verts and faces lists to the text editor so the mesh can be created via a script using from_pydata.


import bpy
# rounded the vert locations to save a bit of blurb.. change the round value or remove for accuracy i suppose
def rounded_tuple(tup):
    return tuple(round(value,4) for value in tup)

ob = bpy.context.object
mesh = ob.data
txt = bpy.data.texts.new("makemesh"+ob.name)

faces = []
verts = []

for face in mesh.faces:
   x = [f for f in face.vertices]
   faces.append(x)
   # xprint(x)

for vertex in mesh.vertices:
   verts.append(rounded_tuple(vertex.co.to_tuple()))
#print(verts)
#print(faces)
txt.write("verts = %s
"%verts)
txt.write("faces = %s
"%faces)

# Use the following (or similar) code to create a mesh from the data
'''

mesh = bpy.data.meshes.new("mesh")
mesh.from_pydata(verts,[],faces)
x = bpy.data.objects.new("objectname",mesh)
base = bpy.context.scene.objects.link(x)

'''

2 weeks ago i was thinking about having a script like that while doing some primitive objects manually ! LOL
and there it is almost like what i wanted but not quit

you got the vert list and face list but then you need to add other little commands to make a new primitive and also include if possible the face’s color and proper normal!

normal are supposed to be outward but on certain models they are inward!

thanks for this script nice work
happy 2.5

Cheers RB,

went for very much a KISS approach on this one. All the material, normal etc stuff would be done in the script you want to use the mesh in.


# based on batFingers entry:
# http://blenderartists.org/forum/showthread.php?t=210351&
import bpy
# rounded the vert locations to save a bit of blurb.. change the round value or remove for accuracy i suppose
def rounded_tuple(tup):
    return tuple(round(value,4) for value in tup)

ob = bpy.context.object
if ob and ob.type == "MESH":
    mesh = ob.data
    txt = bpy.data.texts.new("makemesh_"+ob.name)

    faces = []
    verts = []

    for face in mesh.faces:
        x = [f for f in face.vertices]
        faces.append(x)
        # xprint(x)

    for vertex in mesh.vertices:
        verts.append(rounded_tuple(vertex.co.to_tuple()))
        #print(verts)
        #print(faces)
    txt.write("verts = %s
"%verts)
    txt.write("faces = %s
"%faces)
    s = """
import bpy
mesh = bpy.data.meshes.new("%s")
mesh.from_pydata(verts, [], faces)
ob = bpy.data.objects.new("%s", mesh)
bpy.context.scene.objects.link(ob)
"""
    txt.write(s%(mesh.name, ob.name))
    
# Use the following (or similar) code to create a mesh from the data
'''

mesh = bpy.data.meshes.new("mesh")
mesh.from_pydata(verts,[],faces)
x = bpy.data.objects.new("objectname",mesh)
base = bpy.context.scene.objects.link(x)

'''

a very little addon… just add always the needed lines to create the object into the text-file, so the “run script” creates the object with same name and uses blender-internal-renaming if the object already exists. And the check that the object is a MESH type thing …

Yeah not really needed mate, I considered making it create a method blah blah … but in the end there’s tabbing and stuff to consider… basically its for bone shapes and arrows and helper objects etc that I want to be able to create with scripts… It’s more for cut and paste than creating a functioning script.

so here is my ?no.1 tip since i used python more frequently:

never write code-lines at the start of the line,
i always start with a simple:


if True:
   ....
   ....
      ...

and so on.
Makes it easy to convert a written longer thing into a function
or when parts are copied to be split into functions, no need to
redo the tabs and spaces.
And if i want to go for classes
i use the double


if True:
    if True:
       ...

and to disable some code-parts it is easy to insert a “if False:” and so on.

Thanks! I used this in a script, but wanted to do additional things to the mesh via Python. I had to insert some addtional code to make it work (Blender 2.62). Hope this helps somebody.

After this line:


bpy.context.scene.objects.link(ob)

I had to insert the folling in order to move/rotate etc.


bpy.context.scene.objects.active = ob
bpy.ops.object.editmode_toggle() # For some reason, toggling edit mode on and off makes outline around active part show up.
bpy.ops.object.editmode_toggle()

I could then do things like:


context.scene.objects.active.location = context.scene.cursor_location
context.scene.objects.active.dimensions.y = 15
context.scene.objects.active.location.x += 2
context.scene.objects.active.rotation_euler.x += math.pi/2

Thanks! I used this in a script, but wanted to do additional things to the mesh via Python. I had to insert some addtional code to make it work (Blender 2.62). Hope this helps somebody.

After this line:


bpy.context.scene.objects.link(ob)

I had to insert the folling in order to move/rotate etc.


bpy.context.scene.objects.active = ob
bpy.ops.object.editmode_toggle() # For some reason, toggling edit mode on and off makes outline around active part show up.
bpy.ops.object.editmode_toggle()

I could then do things like:


context.scene.objects.active.location = context.scene.cursor_location
context.scene.objects.active.dimensions.y = 15
context.scene.objects.active.location.x += 2
context.scene.objects.active.rotation_euler.x += math.pi/2

Edit:
Here is the full code I modified.
Thanks again batFINGER. I know you wanted to keep it simple, but just thought I’d share in case anyone else wanted to do the same thing I did. Note: this creates a new text block internal to blender to create the mesh.


import bpy
# rounded the vert locations to save a bit of blurb.. change the round value or remove for accuracy i suppose
def rounded_tuple(tup):
    return tuple(round(value,4) for value in tup)
ob = bpy.context.object
if ob and ob.type == "MESH":
    mesh = ob.data
    txt = bpy.data.texts.new("makemesh_"+ob.name)
    faces = []
    verts = []
    for face in mesh.faces:
        x = [f for f in face.vertices]
        faces.append(x)
        # xprint(x)
    for vertex in mesh.vertices:
        verts.append(rounded_tuple(vertex.co.to_tuple()))
        #print(verts)
        #print(faces)
    txt.write("verts = %s
"%verts)
    txt.write("faces = %s
"%faces)
    s = """
import bpy
mesh = bpy.data.meshes.new("%s")
mesh.from_pydata(verts, [], faces)
ob = bpy.data.objects.new("%s", mesh)
bpy.context.scene.objects.link(ob)
bpy.context.scene.objects.active = ob
bpy.ops.object.editmode_toggle() # For some reason, toggling edit mode on and off makes outline around active part show up.
bpy.ops.object.editmode_toggle()
    """
    txt.write(s%(mesh.name, ob.name))


Hi! I’ve tried your script (blender 2.69) but it doesn’t work!
Blender gives me a generic message:“Python script fail, look in the console for now”.
Maybe there is a problem of indentation because the last posted script doesn’t have it.
It is possible to have an attachment with the python file?
Thank you! :slight_smile:

Hi,

the faces collection of a mesh object is is now polygons

Make this change to get the OP to work.


for face in mesh.<b>polygons</b>:
   x = [f for f in face.vertices]
   faces.append(x)


Thank you batFINGER!
Now it works :slight_smile:

Sorry about that!
I didn’t notice that when I pasted, it lost the indents.
Fixed. I re-tested, and it correctly creates a new text data block with the code to generate the mesh - in Blender 2.62 (I haven’t had time to update my script to the latest API, so it might not work in newer versions)