import bpy
import bmesh
from mathutils import *
#
# take a mesh and alter it so that it has subdivided spikes.
# Each layer of spikes gets its own bone.
#
def average( coords):
sum = Vector(coords[0])
for i in range(1, len(coords)):
sum = sum + coords[i]
return sum / len(coords)
def fab_layer(verts, base_indices, layer, max_layers, max_radius):
vavg = average( [ verts[vi] for vi in base_indices])
tip = vavg * max_radius / vavg.magnitude
rval_vi = []
for i in range(len(base_indices)):
v0 = verts[base_indices[i]]
v1 = (v0 * (max_layers-layer) + tip*layer ) / max_layers
idx = len(verts)
rval_vi.append(idx)
verts.append(v1)
return rval_vi
def bridge_rings(faces, ring1, ring2):
n = len(ring1)
for i in range(n):
v1 = ring1[i]
v2 = ring1[ (i+1)%n]
v3 = ring2[ (i+1)%n]
v4 = ring2[i]
faces.append( [ v1,v2,v3,v4] )
def spikify(proto, layers=5, max_radius=3):
mesh = bpy.data.meshes.new("spikes")
verts = [ v.co for v in proto.vertices ]
faces = []
vi_for_layer = [ [] for r in range(layers)]
for poly in proto.polygons:
if poly.select:
# spikify this one
old_ring = poly.vertices
for r in range(layers):
new_ring = fab_layer(verts, poly.vertices, r+1, layers, max_radius)
vi_for_layer[r].extend(new_ring)
bridge_rings(faces, old_ring, new_ring)
old_ring = new_ring
faces.append( old_ring)
bpy.ops.object.mode_set(mode='OBJECT')
mesh.from_pydata(verts, [], faces)
for p in mesh.polygons:
p.use_smooth=True
obj = bpy.data.objects.new("spikes", mesh)
#
for layer in range(layers+1):
vg = obj.vertex_groups.new("layer %d"%layer)
if (layer==0):
vg.add(range(len(proto.vertices)), 1, 'REPLACE')
else:
vg.add(vi_for_layer[layer-1], 1, 'REPLACE')
#
arm = bpy.data.armatures.new("spikes")
ao = bpy.data.objects.new("armature.%s"%"spikes", arm)
scn.objects.link(ao)
scn.objects.active = ao
bpy.ops.object.mode_set(mode='EDIT')
for layer in range(layers+1):
b = arm.edit_bones.new("layer %d"%layer)
b.head = (0,0,0)
if (layer >0) :
z = max_radius * layer / layers
else:
z = -1
# if we don't set the tail!=head, the bone disappears
b.tail = (0,0, z)
bpy.ops.object.mode_set(mode='OBJECT')
#
mod = obj.modifiers.new("armature", "ARMATURE")
mod.object = ao
#
return obj
#if bpy.context.mode != 'EDIT':
# bpy.ops.object.mode_set(mode='EDIT')
scn = bpy.context.scene
obj = spikify(bpy.context.active_object.data, 40, 10)
scn.objects.link(obj)
|
Blender python API quick-start
Syntax highlighting by Pygments.