An Edmonton.py
presentation by
Chris Want /
cjwant@gmail.com /
@cwant
From the Blender website:
“Blender is a free and open source 3D animation suite. It supports the entirety of the 3D pipeline—modeling, rigging, animation, simulation, rendering, compositing and motion tracking, even video editing and game creation”
Three ways to access python
We'll run our scripts through the text editor
Execute with Alt-P while your mouse is in the editor
Most of the modeling is done through the menus or through hot keys. These execute bits of code called "operators". The Python API maps well to these operators.
Check out the tooltips
An object is defined by the type of data it points to, e.g., mesh, camera, lamp, curve, text ...
>>> ob = bpy.data.objects["Profile"]
>>> ob.data
bpy.data.meshes["Plane"]
>>> ob2 = bpy.data.objects["Camera"]
>>> ob2.data
bpy.data.cameras["Camera"]
Typically meshes are modeled in "Edit Mode".
Meshes are made of vertices, edges, and faces
Think of vertices as a zero-based list of coordinates
Think of faces/edges as pointers into the list of vertices
# A list of 3D coordinates
verts = [
[1, 1, 0],
[1, -1, 0],
[-1, -1, 0],
[-1, 1, 0]
]
# List the verts to connect
edges = [
[0, 1],
[1, 2]
]
# List the verts to span
faces = [
[0, 2, 3]
]
# The magic is done by:
# bpy.types.Mesh.from_pydata
me = bpy.data.meshes.new("me")
me.from_pydata(verts,
edges,
faces)
ob = bpy.data.objects.new("ob",
me)
scn = bpy.context.scene
scn.objects.link(ob)
# Not needed
scn.objects.active = ob
ob.select = True
To create the shape, we must specify:
Copy numverts vertices mulitple times, based on resolution
Old edges become new faces.
Exploit the fact that we are connecting vertices who's indices are numverts apart.
import bpy
from math import sin, cos, pi
num_cycles = 4
resolution = 64
radius = 5
amplitude = 1
def main():
oldob = bpy.data.objects["Profile"]
if oldob == None:
return
oldme = oldob.data
numvert = len(oldme.vertices)
numedge = len(oldme.edges)
numface = len(oldme.polygons)
verts = []
faces = []
###### ... main() cont'd
for i in range(resolution):
for j in range(numvert):
# Duplicate and transform vertices
vold = oldme.vertices[j].co
vnew = transform_vert(vold, i)
verts.append(vnew)
# Extrude old edges into new faces
for j in range(numedge):
if oldme.edges[j].is_loose:
e = oldme.edges[j].vertices
f = edge_to_face(e, i, numvert)
faces.append(f)
###### ... main() cont'd
me = bpy.data.meshes.new("thingy")
me.from_pydata(verts, [], faces)
ob = bpy.data.objects["thingy"]
ob.data = me
def transform_vert(v, i):
prop = float(i) / float(resolution)
a = 2*pi*prop
b = a * num_cycles
cosa = cos(a)
sina = sin(a)
sinb = sin(b)
x = (v[0] + radius) * cosa + v[1] * sina
y = -(v[0] + radius) * sina + v[1] * cosa
z = v[2] + sinb * amplitude
return [x, y, z]
def edge_to_face(e, i, numvert):
i1 = i
i2 = (i + 1) % (resolution)
f = [e[0] + i1*numvert,
e[1] + i1*numvert,
e[1] + i2*numvert,
e[0] + i2*numvert]
return f
main()
The interior must be clearly defined
The subdivision surface modifier is your friend!
From the File/Export menu ...
Recommendations:
I use ShapeWays, because: