Created
March 10, 2013 19:57
-
-
Save megafaunasoft/5130161 to your computer and use it in GitHub Desktop.
Blender cup with rings, Python script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import bpy, math | |
deg2rad = 2*math.pi/360.0 | |
scn = bpy.context.scene | |
scn.cursor_location = (0,0,0) | |
OVERALL_SCALE = 1/8.0 | |
cgap = 0.525 * OVERALL_SCALE | |
#-------------------------------------------------------------- | |
# Delete everything for starting over | |
# | |
bpy.ops.object.select_by_type(type="EMPTY") | |
bpy.ops.object.delete() | |
bpy.ops.object.select_by_type(type="MESH") | |
bpy.ops.object.delete() | |
bpy.ops.object.select_by_type(type="FONT") | |
bpy.ops.object.delete() | |
bpy.ops.object.select_by_type(type="CURVE") | |
bpy.ops.object.delete() | |
# add a font to the list for use -- stays in the list... | |
bpy.ops.font.open(filepath="/Library/Fonts/Georgia.ttf") | |
#---------------------------------------------------------- | |
# File curve_types.py | |
#---------------------------------------------------------- | |
import bpy | |
from math import sin, pi | |
''' | |
def make_half_torus(majorr, minorx, minory, run, y_off): | |
"""DEFUNCT! Problems with inside vs outside so replaced | |
with a mesh i make by hand. Definitely solvable though. | |
Make half torus -- white plastic""" | |
cu = bpy.data.curves.new("htorus", 'CURVE') | |
ob = bpy.data.objects.new("htorus", cu) | |
ob.location = (0,0,0) | |
bpy.context.scene.objects.link(ob) | |
spline = cu.splines.new('POLY') | |
cu.dimensions = '3D' | |
x1 = majorr-minorx | |
x2 = majorr+minorx | |
y1 = y_off-minory | |
y2 = y_off+minory | |
coords = [(0,majorr-minorx,y_off-minory), (0,majorr+minorx,y_off-minory)] | |
STEPS = 100 | |
for i in range(1,STEPS+1): | |
coords.append((0, | |
majorr+minorx + i*(float(run)/STEPS), | |
y_off-minory + ((2.0*i/STEPS)*minory))) | |
# finally cap it | |
coords.append((0,majorr-minorx+run,y_off+minory)) | |
coords.append((0,majorr-minorx,y_off-minory)) | |
spline.points.add(len(coords)-1) | |
for n in range(len(coords)): | |
spline.points[n].co = (coords[n][0], coords[n][1], coords[n][2], 1) | |
# Add empty object to rotate around | |
bpy.ops.object.add(type="EMPTY", location=(0,0,0),) | |
empty = bpy.context.object | |
scn.objects.active = ob | |
mod = ob.modifiers.new("mod_screw", "SCREW") | |
mod.object = empty | |
mod.angle = math.pi | |
mod.steps = 128 | |
mod.render_steps = 64 | |
scn.update() | |
return ob | |
''' | |
def make_alphabet(half, radius, extrude, y_off): | |
if half==1: | |
letters = "ABCDEFGHIJKLM" | |
TOTAL_DEGREES = 360 | |
elif half==2: | |
letters = "NOPQRSTUVWXYZ" | |
TOTAL_DEGREES = 360 | |
elif half==3: | |
letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |
TOTAL_DEGREES = 360 | |
elif half==4: | |
letters = "ABCD" | |
TOTAL_DEGREES = 360 | |
textobjs = {} | |
for i, ch in enumerate(letters): | |
# Add half a rotation | |
i = (i * (TOTAL_DEGREES / (len(letters)))) + (TOTAL_DEGREES / (2*(len(letters)))) | |
theta = i*deg2rad | |
#---------------------------------------- | |
# Text object | |
# | |
bpy.ops.object.text_add(location=(0,0,0)) | |
textobjs[ch] = bpy.context.object | |
textobjs[ch].name = ch+"_mytext" | |
tcu = textobjs[ch].data | |
tcu.name = ch+"_data" | |
tcu.body = ch | |
tcu.font = bpy.data.fonts[len(bpy.data.fonts)-1] | |
tcu.size = 0.8 | |
tcu.extrude = extrude | |
# ESSENTIAL FOR BOUNDING BOX TO WORK!!! | |
scn.update() | |
# Centering | |
bpy.ops.transform.translate( value=((textobjs[ch].bound_box[0][0] - textobjs[ch].bound_box[7][0])/2, | |
0, | |
(textobjs[ch].bound_box[0][2] - textobjs[ch].bound_box[7][2])/2)) | |
#------------------------------------------------- | |
# Little circle | |
# | |
print(textobjs[ch].bound_box[0][0],textobjs[ch].bound_box[7][0]) | |
bpy.ops.object.origin_set(type="ORIGIN_CURSOR") | |
scn.update() | |
bpy.ops.transform.rotate(axis=(1,0,0), value=math.pi/2 ) | |
print(dir(bpy.ops.object)) | |
# Converting font/text object to mesh is necessary | |
# for apply rotation to work! | |
# You must apply a rotation in order to do any new rotations | |
bpy.ops.object.convert(target='MESH', keep_original=False) | |
bpy.ops.object.transform_apply(rotation=True) | |
#------------------------------------------------ | |
# Big circle | |
# | |
bpy.ops.transform.translate(value=((0,radius,y_off))) | |
# ESSENTIAL FOR BIG ROTATION TO WORK | |
scn.cursor_location = (0,0,0) | |
bpy.ops.object.origin_set(type="ORIGIN_CURSOR") | |
scn.update() | |
# bpy.ops.transform requires textobj[ch].select=True | |
#bpy.ops.transform.rotate(axis=(0,0,1),value=[theta]) | |
textobjs[ch].rotation_euler.rotate_axis("Z",theta) | |
# I didn't know how to treat this group as one object | |
#alphabet_group = bpy.data.groups.new("alphabet_group") | |
#for textobj in textobjs.values(): | |
# alphabet_group.objects.link(textobj) | |
return textobjs | |
#------------------------------------------------------------------------- | |
# Cup | |
# | |
def make_cup(base_w, run, indent): | |
"""Make the cup -- black ceramic material""" | |
cu = bpy.data.curves.new("cup_curve", 'CURVE') | |
ob = bpy.data.objects.new("cup_object", cu) | |
ob.location = (0,0,0) | |
ob.show_name = False # text on the blender window | |
# Nothing shows up without linking it to the scene -- why? | |
bpy.context.scene.objects.link(ob) | |
# Create spline | |
spline = cu.splines.new('POLY') | |
cu.dimensions = '3D' | |
base_h = 3*OVERALL_SCALE #0.375 == 3mm | |
lip = 0.6 | |
# http://www.shapeways.com/design-rules/ceramics | |
round = 2*OVERALL_SCALE | |
coords = [(0,0,0), (0,base_w-round,0), (0,base_w+round*run,round), (0,base_w+1*run,1), | |
(0,base_w+1*run-indent,1),(0,base_w+2*run-indent,2), (0,base_w+2*run,2),(0,base_w+3*run,3), | |
(0,base_w+3*run-indent,3),(0,base_w+4*run-indent,4), (0,base_w+4*run,4),(0,base_w+5*run,5), | |
(0,base_w+5*run-indent,5),(0,base_w+6*run-indent,6), (0,base_w+6*run,6),(0,base_w+6*run,7), | |
# turn at the top -- including rounding | |
(0,base_w+6*run-.09,7+round*.85),(0,base_w+6*run-.18,7+round),(0,base_w+6*run-.27,7+round*.85), | |
(0,base_w+7*run-lip,7), | |
# back down the other side -- including rounding | |
(0,base_w-lip + run*(base_h+.3),base_h+.3), (0,base_w-lip-.3 + run*(base_h),base_h), | |
(0,0,base_h) | |
] | |
spline.points.add(len(coords)-1) | |
for n in range(len(coords)): | |
spline.points[n].co = (coords[n][0], coords[n][1], coords[n][2], 1) | |
# Add empty object to rotate around | |
bpy.ops.object.add(type="EMPTY", location=(0,0,0),) | |
empty = bpy.context.object | |
# Run screw modifier on ob | |
scn.objects.active = ob | |
mod = ob.modifiers.new("mod_screw", "SCREW") | |
mod.object = empty | |
mod.angle = 2*math.pi | |
mod.steps = 256 | |
mod.render_steps = 256 | |
return ob | |
#-------------------------------------------------------------------------- | |
# Mesh | |
# | |
def rotation_matrix(axis,theta): | |
axdot = math.sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]) | |
axis = (axis[0]/axdot, | |
axis[1]/axdot, | |
axis[2]/axdot) | |
a = math.cos(theta/2) | |
b = -axis[0]*math.sin(theta/2) | |
c = -axis[1]*math.sin(theta/2) | |
d = -axis[2]*math.sin(theta/2) | |
return [[a*a+b*b-c*c-d*d, 2*(b*c-a*d), 2*(b*d+a*c)], | |
[2*(b*c+a*d), a*a+c*c-b*b-d*d, 2*(c*d-a*b)], | |
[2*(b*d-a*c), 2*(c*d+a*b), a*a+d*d-b*b-c*c]] | |
def make_mesh(name, DEGREES, majorr, minorx, minory, run, y_off): | |
"""Make a band | |
""" | |
verts = [] | |
edges = [] | |
faces = [] | |
nrot = 64 #26 | |
axis = (0,0,1) | |
# Only use the minimum number of vertices necessary | |
# Otherwise, problems with inside and outside the mesh | |
spline = ((0, majorr-minorx+cgap, y_off-minory+cgap), | |
(0, majorr+minorx, y_off-minory+cgap), | |
(0, majorr+minorx+run, y_off+minory-cgap), | |
(0, majorr-minorx+cgap+run, y_off+minory-cgap),) | |
#(0, majorr-minorx, y_off-minory)) | |
rotation_offset = (DEGREES/(2*nrot)) * deg2rad | |
if DEGREES < 360: | |
real_nrot = nrot + 1 | |
else: | |
real_nrot = nrot | |
for n in range(real_nrot): | |
angle = -(rotation_offset) + (n * (DEGREES/(nrot))) | |
theta = angle * deg2rad | |
rmat = rotation_matrix(axis, theta) | |
for point in spline: | |
new_point = (rmat[0][0]*point[0] + rmat[0][1]*point[1] + rmat[0][2]*point[2], | |
rmat[1][0]*point[0] + rmat[1][1]*point[1] + rmat[1][2]*point[2], | |
rmat[2][0]*point[0] + rmat[2][1]*point[1] + rmat[2][2]*point[2]) | |
verts.append(new_point) | |
if DEGREES < 360 and n == 0: | |
faces.append((0,1,2,3)) | |
my_offset = n*len(spline) | |
if DEGREES == 360: | |
next_offset = ((n+1)*len(spline)) % (nrot*len(spline)) | |
else: | |
next_offset = ((n+1)*len(spline)) | |
if n == real_nrot-1: | |
continue | |
for i in range(len(spline)): | |
my_i = i + my_offset | |
my_i2 = (i+1)%len(spline) + my_offset | |
next_i = i + next_offset | |
next_i2 = (i+1)%len(spline) + next_offset | |
faces.append((my_i, my_i2, next_i2, next_i)) | |
if DEGREES < 360: | |
faces.append((len(verts)-1,len(verts)-2,len(verts)-3,len(verts)-4)) | |
me = bpy.data.meshes.new(name+"Mesh") | |
ob = bpy.data.objects.new(name, me) | |
ob.location = (0,0,0) | |
ob.show_name = False | |
# Link object to scene | |
bpy.context.scene.objects.link(ob) | |
# Create mesh from given verts, edges, faces. Either edges or | |
# faces should be [], or you ask for problems | |
me.from_pydata(verts, edges, faces) | |
# Update mesh with new data | |
me.update(calc_edges=True) | |
return ob | |
#---------------------------------------------------------------------------- | |
# Diff | |
# | |
def do_diff(tor, textobjs, gap=None): | |
for textobj in textobjs.values(): | |
scn.objects.active = tor | |
mod = tor.modifiers.new("mod_diff", "BOOLEAN") | |
mod.operation = "DIFFERENCE" | |
mod.object = textobj | |
bpy.ops.object.modifier_apply(apply_as="DATA", modifier="mod_diff") | |
scn.objects.unlink(textobj) | |
# This should also work | |
#textobj.select = True | |
#bpy.ops.object.delete() | |
if gap: | |
scn.objects.active = tor | |
mod = tor.modifiers.new("mod_diff", "BOOLEAN") | |
mod.operation = "DIFFERENCE" | |
mod.object = gap | |
bpy.ops.object.modifier_apply(apply_as="DATA", modifier="mod_diff") | |
def make_gap(): | |
me = bpy.data.meshes.new("gapMesh") | |
ob = bpy.data.objects.new("AAA_gap", me) | |
ob.location = (0,0,0) | |
# It's necessary to link object to scene | |
bpy.context.scene.objects.link(ob) | |
#----------------------------------------- | |
# 0.5mm wide gap -- hopefully avoid fusing | |
# | |
Xh = 0.25 * OVERALL_SCALE | |
Y = -4 | |
Z = 6 | |
verts = ((-Xh,Y,0),(Xh,Y,0),(Xh,0,0),(-Xh,0,0), | |
(-Xh,0,Z),(Xh,0,Z),(Xh,Y,Z),(-Xh,Y,Z)) | |
faces = ((0,3,2,1), | |
(7,6,5,4), | |
(0,1,6,7),(2,3,4,5), | |
(1,2,5,6),(7,4,3,0)) | |
me.from_pydata(verts, [], faces) | |
# Update mesh with new data | |
me.update(calc_edges=True) | |
return ob | |
if __name__ == "__main__": | |
# 8.6 units wide, 7 units high -> | |
# An espresso cup should be 2.25" by 2.25" = 57mm | |
# That would be a scale of 8.14 | |
PRINTING = False | |
DRAW_TEXT = True | |
base_w = 2.5 | |
run = 0.2 | |
indent = 0.3 | |
minorx = indent/2 | |
minory = 0.5 | |
cup = make_cup(base_w, run, indent) | |
#-------------------------------------------------------------------------------- | |
# Gap maker -- has to be in mm | |
# Cube is 2x2x2 so the gap = 0.5mm | |
# | |
gap = make_gap() | |
#-------------------------------------------------------------------------------- | |
# Bands | |
# | |
y_off = 1.5 | |
majorr = base_w + 1*run - indent/2 | |
t1 = make_mesh(name="one", DEGREES=360, | |
majorr=majorr, minorx=minorx, minory=minory, | |
run=run, y_off=y_off) | |
textr = majorr+indent | |
texte = indent*.75 | |
texty = y_off - 0.25 | |
if DRAW_TEXT: | |
textobjs1 = make_alphabet(half=3, radius=-textr, extrude=texte, y_off=texty) | |
else: | |
textobjs1 = {} | |
do_diff(t1, textobjs1, gap=gap) | |
# FINAL MOVE FOR PRINTING | |
if PRINTING: | |
t1.location = (6,0,-1.5+minory-cgap) | |
y_off = 3.5 | |
majorr = base_w + 3*run - indent/2 | |
t2 = make_mesh(name="two", DEGREES=360, | |
majorr=majorr, minorx=minorx, minory=minory, | |
run=run, y_off=y_off) | |
textr = majorr+indent | |
texte = indent*.7 | |
texty = y_off - 0.25 | |
if DRAW_TEXT: | |
textobjs2 = make_alphabet(half=3, radius=-textr, extrude=texte, y_off=texty) | |
else: | |
textobjs2 = {} | |
do_diff(t2, textobjs2, gap=gap) | |
# FINAL MOVE FOR PRINTING | |
if PRINTING: | |
t2.location = (6,7,-3.5+minory-cgap) | |
y_off = 5.5 | |
majorr = base_w + 5*run - indent/2 | |
t3 = make_mesh(name="three", DEGREES=360, | |
majorr=majorr, minorx=minorx, minory=minory, | |
run=run, y_off=y_off) | |
textr = majorr+indent | |
texte = indent*.65 | |
texty = y_off - 0.25 | |
if DRAW_TEXT: | |
textobjs3 = make_alphabet(half=3, radius=-textr, extrude=texte, y_off=texty) | |
else: | |
textobjs3 = {} | |
do_diff(t3, textobjs3, gap=gap) | |
# FINAL MOVE FOR PRINTING | |
if PRINTING: | |
t3.location = (6,-7,-5.5+minory-cgap) | |
# delete gap-maker | |
scn.objects.unlink(gap) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment