# Can not figure out why this python mesh object script will not run

I am learning how to create mesh objects using python. The math will be complicated (fsolve and other special functions in Scipy), but I've simplified the problem to just four sides of a box. The first set of code does not run in blender 2.70a installed on my macbook air.

The error message in this case is only "Python script fail, look in the console for now..."

However, if I run the math part in python 2.7.6 first (second code segment below), then paste the output back into blender (third code segment), it works and draws four sides of a box.

This doesn't work:

import bpy
import numpy as np
from math import pi

mesh = bpy.data.meshes.new("Cubit")
object = bpy.data.objects.new("Cubit", mesh)

object.location = (0,0,0)  # bpy.context.scene.cursor_location

mesh.from_pydata(verts,[],faces)
mesh.update(calc_edges=True)

verts = []
faces = []

n_side = 4
n_seg = 1

i_seg = 0
while (i_seg < n_seg+1):
i_vert = 0
zv = 2. * i_seg
while (i_vert < n_side):
xv = np.cos(0.5 * pi * i_vert)
yv = np.sin(0.5 * pi * i_vert)
vert = (xv,yv,zv)
verts.append(vert)
i_vert = i_vert + 1
i_seg = i_seg + 1

i_seg = 0
while (i_seg < n_seg):
i_vert = 0
while (i_vert < n_side):
iv1 = i_seg*n_side + i_vert
iv2 = i_seg*n_side + np.mod(i_vert + 1, n_side)
iv3 = (i_seg + 1)*n_side + np.mod(i_vert + 1, n_side)
iv4 = (i_seg + 1)*n_side + i_vert
face = (iv1,iv2,iv3,iv4)
faces.append(face)
i_vert = i_vert + 1
i_seg = i_seg + 1

mesh = bpy.data.meshes.new("Cubit")
object = bpy.data.objects.new("Cubit", mesh)

object.location = (0,0,0)  #bpy.context.scene.cursor_location

mesh.from_pydata(verts,[],faces)
mesh.update(calc_edges=True)


But if I run this in Python IDLE

import numpy as np
from math import pi

verts = []
faces = []

n_side = 4
n_seg= 1

i_seg = 0
while (i_seg < n_seg+1):
i_vert = 0
zv = 2. * i_seg
while (i_vert < n_side):
xv = np.cos(0.5 * pi * i_vert)
yv = np.sin(0.5 * pi * i_vert)
vert = (xv,yv,zv)
verts.append(vert)
i_vert = i_vert + 1
i_seg = i_seg + 1

i_seg = 0
while (i_seg < n_seg):
i_vert = 0
while (i_vert < n_side):
iv1 = i_seg*n_side + i_vert
iv2 = i_seg*n_side + np.mod(i_vert + 1, n_side)
iv3 = (i_seg + 1)*n_side + np.mod(i_vert + 1, n_side)
iv4 = (i_seg + 1)*n_side + i_vert
face = (iv1,iv2,iv3,iv4)
faces.append(face)
i_vert = i_vert + 1
i_seg = i_seg + 1

print ' verts = ', verts
print ' faces = ', faces


...and then paste the (ugly) output into blender like this, it works fine and draws four sides of a box.

import bpy
import numpy as np
from math import pi

verts =  [(1.0, 0.0, 0.0), (6.123233995736766e-17, 1.0, 0.0), (-1.0, 1.2246467991473532e-16, 0.0), (-1.8369701987210297e-16, -1.0, 0.0), (1.0, 0.0, 2.0), (6.123233995736766e-17, 1.0, 2.0), (-1.0, 1.2246467991473532e-16, 2.0), (-1.8369701987210297e-16, -1.0, 2.0)]
faces =  [(0, 1, 5, 4), (1, 2, 6, 5), (2, 3, 7, 6), (3, 0, 4, 7)]

mesh = bpy.data.meshes.new("Cubit")
object = bpy.data.objects.new("Cubit", mesh)

object.location = (0,0,0)  #bpy.context.scene.cursor_location

mesh.from_pydata(verts,[],faces)
mesh.update(calc_edges=True)

• I've had further trouble - see this question – uhoh Aug 9 '15 at 12:16

Your script has two minor issues

Line 11,12 should be removed

#mesh.from_pydata(verts,[],faces)
#mesh.update(calc_edges=True)


The console window from Menu:Window/Toggle System Console shows a traceback:

  File "\Text", line 51, in <module>
File "C:\Program Files\Blender Foundation\Blender\2.70\scripts\modules\bpy_typ
es.py", line 418, in from_pydata
p.vertices = f
TypeError: bpy_struct: item.attr = val: expected sequence items of type int, not
numpy.int32


this means that for some reason the face's values are of type numpy.int32 instead of the expected int type.

This is easy to fix. Just add casts to int type in line 40:

face = (int(iv1),int(iv2),int(iv3),int(iv4))

• Great! The int() solves the problem. Line 12 seems unnecessary. but line 11 still seems to be required, otherwise only a dot appears. – uhoh Jul 24 '14 at 15:07
• I'll also have to read further about the console, it seems some homework is required to make it happen in OSX. Thank you!!! – uhoh Jul 24 '14 at 15:08
• To debug python running in blender in OSX, I followed the procedure outlined in wiki.blender.org/index.php/Doc:2.6/Manual/Interface/… In my case I open a Terminal from Applications, then typed the line "/Applications/BlenderApplication/blender.app/Contents/MacOS/blender" which reflects the name as shown in my Applications folder. This starts Blender from the terminal, and the python errors appear here. – uhoh Jul 24 '14 at 16:06

Just to add some things. If you're making scripts in Blender you definitely need to have the console open, so you can see the errors. You already discovered how to do that in OSX.

Furthermore I'm guessing you have a background in another programming language. The while loops you're using are very unpythonic. You can use simple for loops here, which looks cleaner and even saves you a little bit of typing ;).

The whole part between the import statements and verts = [] can be removed. You add the mesh and object at the end, so you absolutely don't need this.

I thinks it's better if you first create the mesh from_pydata, then create the object and then link the object to the scene. This way you're sure that any needed updates to the scene will happen. I also tested it in the order you have and it worked for me (even without mesh.update(calc_edges=True). So it might be just my preference.

Here is a simplified version. For simplicities sake I removed the dependency on numpy, but of course you can add it back to suit your needs. Only remember to convert any numpy values to int(), float() or whatever it should be, before passing it to Blender (like stacker mentioned).

import bpy
from math import pi, sin, cos

verts = []
faces = []

n_side = 4
n_seg = 1

for i_seg in range(n_seg + 1):
zv = 2 * i_seg
for i_vert in range(n_side):
xv = cos(0.5 * pi * i_vert)
yv = sin(0.5 * pi * i_vert)
vert = (xv, yv, zv)
verts.append(vert)

for i_seg in range(n_seg):
for i_vert in range(n_side):
iv1 = i_seg * n_side + i_vert
iv2 = i_seg * n_side + (i_vert + 1) % n_side
iv3 = (i_seg + 1) * n_side + (i_vert + 1) % n_side
iv4 = (i_seg + 1) * n_side + i_vert
face = (iv1, iv2, iv3, iv4)
faces.append(face)

mesh = bpy.data.meshes.new("Cubit")
mesh.from_pydata(verts, [], faces)

object = bpy.data.objects.new("Cubit", mesh)
object.location = (0, 0, 0)  # bpy.context.scene.cursor_location