Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Buerbaum <martin.buerbaum@gmx.at>2010-04-16 14:29:39 +0400
committerMartin Buerbaum <martin.buerbaum@gmx.at>2010-04-16 14:29:39 +0400
commitbc0bd762e045ccaa3f9c35d984b1e273347ca17f (patch)
treee030bce78ac3cd0fa771108876f5cc895bc12134 /add_mesh_gears.py
parent4621f236c084890fb37e982e1cdef078e7701fac (diff)
* Gears Version 2.3
* Major refractor - removed most of the hardcoded stuff. * Separated functions into gear, worm gear (and experimental/non-working spokes) * "Gear" now doesn't have any duplicate vartices. * New submenu "Gears" (entries "Gear" and "Worm Gear") * TODO: Prevent doubles in "Worm Gear" (change it so only one row of verts is calculated for each step) * TODO: Finish/improve spokes code ("add_spokes"). * TODO: Create new "auto-spokes" function that addes a "Gear Spokes" Object for an existing "Gears" obj (either via the "recall" data - this stuff is usefull :-) or by creating 2 objects at the same time.)
Diffstat (limited to 'add_mesh_gears.py')
-rw-r--r--add_mesh_gears.py668
1 files changed, 500 insertions, 168 deletions
diff --git a/add_mesh_gears.py b/add_mesh_gears.py
index 2ffd8add..38ad918e 100644
--- a/add_mesh_gears.py
+++ b/add_mesh_gears.py
@@ -23,9 +23,9 @@
bl_addon_info = {
'name': 'Add Mesh: Gears',
'author': 'Michel J. Anders (varkenvarken)',
- 'version': '2.2',
+ 'version': '2.3',
'blender': (2, 5, 3),
- 'location': 'View3D > Add > Mesh ',
+ 'location': 'View3D > Add > Mesh > Gears ',
'description': 'Adds a mesh Gear to the Add Mesh menu',
'url': 'http://wiki.blender.org/index.php/Extensions:2.5/Py/' \
'Scripts/Add_Mesh/Add_Gear',
@@ -35,7 +35,7 @@ bl_addon_info = {
What was needed to port it from 2.49 -> 2.50 alpha 0?
The basic functions that calculate the geometry (verts and faces) are mostly
-unchanged (add_tooth, add_spoke2, add_gear)
+unchanged (add_tooth, add_spoke, add_gear)
Also, the vertex group API is changed a little bit but the concepts
are the same:
@@ -67,28 +67,6 @@ zip object to a list of tuples first.
The code to actually implement the AddGear() function is mostly copied from
add_mesh_torus() (distributed with Blender).
-
-Unresolved issues:
-
-- Removing doubles:
- The algorithm should not generate a full section to begin with.
- At least the last 4 vertices don't need to be created, because the
- next section will have them as their first 4 vertices anyway.
- OLD COMMENT ON DOUBLES:
- "The code that produces the teeth of the gears produces some duplicate
- vertices. The original script just called remove_doubles() but if we
- do that in 2.50 we have a problem.
- To apply the bpy.ops.mesh.remove_doubles() operator we have to change
- to edit mode. The moment we do that we loose to possibilty to
- interactively change the properties.
- Also changing back to object mode raises a strange exception (to
- investigate). So for now, removing doubles is left to the user
- once satisfied with the chosen setting for a gear."
-
-- No suitable icon:
- A rather minor point but I reused the torus icon for the add->mesh->gear
- menu entry as there doesn't seem to be a generic mesh icon or a way to
- add custom icons. Too bad, but as this is just eye candy it's no big deal.
"""
import bpy
@@ -97,40 +75,6 @@ from math import *
from copy import deepcopy
from bpy.props import *
-# Constants
-FACES = [
- [0, 5, 6, 1],
- [1, 6, 7, 2],
- [2, 7, 8, 3],
- [3, 8, 9, 4],
- [6, 10, 11, 7],
- [7, 11, 12, 8],
- [10, 13, 14, 11],
- [11, 14, 15, 12]]
-
-VERT_NUM = 16 # Number of vertices
-
-# Edgefaces
-EDGEFACES = [5, 6, 10, 13, 14, 15, 12, 8, 9]
-EDGEFACES2 = [i + VERT_NUM for i in EDGEFACES] # i.e. Indices are offset by 16
-
-# In python 3, zip() returns a zip object so we have to force the
-# result into a list of lists to keep deepcopy happy later on in the script.
-EFC = [[i, j, k, l] for i, j, k, l
- in zip(EDGEFACES[:-1], EDGEFACES2[:-1], EDGEFACES2[1:], EDGEFACES[1:])]
-VERTS_TOOTH = [13, 14, 15, 29, 30, 31] # Vertices on a tooth
-VERTS_VALLEY = [5, 6, 8, 9, 21, 22, 24, 25] # Vertices in a valley
-
-#SPOKEFACES = (
-# (0, 1, 2, 5),
-# (2, 3, 4, 7),
-# (5, 2, 7, 6),
-# (5, 6, 9, 8),
-# (6, 7, 10, 9),
-# (11, 8, 13, 12),
-# (8, 9, 10, 13),
-# (13, 10, 15, 14))
-
# Stores the values of a list of properties and the
# operator id in a property group ('recall_op') inside the object.
@@ -256,6 +200,54 @@ def create_mesh_object(context, verts, edges, faces, name, edit):
return ob_new
+# A very simple "bridge" tool.
+# Connects two equally long vertex rows with faces.
+# Returns a list of the new faces (list of lists)
+#
+# vertIdx1 ... First vertex list (list of vertex indices).
+# vertIdx2 ... Second vertex list (list of vertex indices).
+# closed ... Creates a loop (first & last are closed).
+# flipped ... Invert the normal of the face(s).
+def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
+ faces = []
+
+ if (len(vertIdx1) != len(vertIdx2)) or (len(vertIdx1) < 2):
+ return None
+
+ total = len(vertIdx1)
+
+ if closed:
+ # Bridge the start with the end.
+ if flipped:
+ faces.append([vertIdx1[0], vertIdx2[0],
+ vertIdx2[total - 1], vertIdx1[total - 1]])
+ else:
+ faces.append([vertIdx2[0], vertIdx1[0],
+ vertIdx1[total - 1], vertIdx2[total - 1]])
+
+ # Bridge the rest of the faces.
+ for num in range(total - 1):
+ if flipped:
+ faces.append([vertIdx2[num], vertIdx1[num],
+ vertIdx1[num + 1], vertIdx2[num + 1]])
+ else:
+ faces.append([vertIdx1[num], vertIdx2[num],
+ vertIdx2[num + 1], vertIdx1[num + 1]])
+
+ return faces
+
+
+# Calculate the vertex coordinates for a single
+# section of a gear tooth.
+# Returns 4 lists of vertex coords (list of tuples):
+# *-*---*---* (1.) verts_inner_base
+# | | | |
+# *-*---*---* (2.) verts_outer_base
+# | | |
+# *---*---* (3.) verts_middle_tooth
+# \ | /
+# *-*-* (4.) verts_tip_tooth
+#
# a
# t
# d
@@ -267,13 +259,7 @@ def create_mesh_object(context, verts, edges, faces, name, edit):
# rack
# crown
def add_tooth(a, t, d, radius, Ad, De, base, p_angle, rack=0, crown=0.0):
- """
- private function: calculate the vertex coords for a single side
- section of a gear tooth.
- Returns them as a list of tuples.
- """
-
- A = [a, a + t / 4, a + t / 2, a + 3 * t / 4, a + t]
+ A = [a, a + t / 4, a + t / 2, a + 3 * t / 4]
C = [cos(i) for i in A]
S = [sin(i) for i in A]
@@ -292,10 +278,10 @@ def add_tooth(a, t, d, radius, Ad, De, base, p_angle, rack=0, crown=0.0):
S = [sin(t / 4) * I for I in range(-2, 3)]
Sp = [0, sin(-t / 4 + p_angle), 0, sin(t / 4 - p_angle)]
- verts = [(Rb, radius * S[I], d) for I in range(5)]
- verts.extend([(Rd, radius * S[I], d) for I in range(5)])
- verts.extend([(radius, radius * S[I], d) for I in range(1, 4)])
- verts.extend([(Ra, radius * Sp[I], d) for I in range(1, 4)])
+ verts_inner_base = [(Rb, radius * S[I], d) for I in range(4)]
+ verts_outer_base = [(Rd, radius * S[I], d) for I in range(4)]
+ verts_middle_tooth = [(radius, radius * S[I], d) for I in range(1, 4)]
+ verts_tip_tooth = [(Ra, radius * Sp[I], d) for I in range(1, 4)]
else:
Cp = [
@@ -308,17 +294,23 @@ def add_tooth(a, t, d, radius, Ad, De, base, p_angle, rack=0, crown=0.0):
sin(a + t / 2),
sin(a + 3 * t / 4 - p_angle)]
- verts = [(Rb * C[I], Rb * S[I], d)
- for I in range(5)]
- verts.extend([(Rd * C[I], Rd * S[I], d) for I in range(5)])
- verts.extend([(radius * C[I], radius * S[I], d + crown / 3)
- for I in range(1, 4)])
- verts.extend([(Ra * Cp[I], Ra * Sp[I], d + crown)
- for I in range(1, 4)])
+ verts_inner_base = [(Rb * C[I], Rb * S[I], d)
+ for I in range(4)]
+ verts_outer_base = [(Rd * C[I], Rd * S[I], d)
+ for I in range(4)]
+ verts_middle_tooth = [(radius * C[I], radius * S[I], d + crown / 3)
+ for I in range(1, 4)]
+ verts_tip_tooth = [(Ra * Cp[I], Ra * Sp[I], d + crown)
+ for I in range(1, 4)]
- return verts
+ return (verts_inner_base, verts_outer_base,
+ verts_middle_tooth, verts_tip_tooth)
+# EXPERIMENTAL Calculate the vertex coordinates for a single
+# section of a gearspoke.
+# Returns them as a list of tuples.
+#
# a
# t
# d
@@ -330,13 +322,9 @@ def add_tooth(a, t, d, radius, Ad, De, base, p_angle, rack=0, crown=0.0):
# l
# gap
# width
-def add_spoke2(a, t, d, radius, De, base, s, w, l, gap=0, width=19):
- """
- EXPERIMENTAL private function: calculate the vertex coords for
- a single side section of a gearspoke.
- Returns them as a list of lists.
- """
-
+#
+# @todo Finish this.
+def add_spoke(a, t, d, radius, De, base, s, w, l, gap=0, width=19):
Rd = radius - De
Rb = Rd - base
Rl = Rb
@@ -348,7 +336,7 @@ def add_spoke2(a, t, d, radius, De, base, s, w, l, gap=0, width=19):
if not gap:
for N in range(width, 1, -2):
- edgefaces.append(len(v))
+ edgefaces.append(len(verts))
ts = t / 4
tm = a + 2 * ts
te = asin(w / Rb)
@@ -359,7 +347,7 @@ def add_spoke2(a, t, d, radius, De, base, s, w, l, gap=0, width=19):
S = [sin(i) for i in A]
verts.extend([(Rb * I, Rb * J, d) for (I, J) in zip(C, S)])
- edgefaces2.append(len(v) - 1)
+ edgefaces2.append(len(verts) - 1)
Rb = Rb - s
@@ -372,17 +360,233 @@ def add_spoke2(a, t, d, radius, De, base, s, w, l, gap=0, width=19):
n = n + N
- return v, edgefaces, edgefaces2, sf
+ return verts, edgefaces, edgefaces2, sf
# Create gear geometry.
# Returns:
+# * A list of vertices (list of tuples)
+# * A list of faces (list of lists)
+# * A list (group) of vertices of the tip (list of vertex indices).
+# * A list (group) of vertices of the valley (list of vertex indices).
+#
+# teethNum ... Number of teeth on the gear.
+# radius ... Radius of the gear, negative for crown gear
+# Ad ... Addendum, extent of tooth above radius.
+# De ... Dedendum, extent of tooth below radius.
+# base ... Base, extent of gear below radius.
+# p_angle ... Pressure angle. Skewness of tooth tip. (radiant)
+# width ... Width, thickness of gear.
+# skew ... Skew of teeth. (radiant)
+# conangle ... Conical angle of gear. (radiant)
+# rack
+# crown ... Inward pointing extend of crown teeth.
+#
+# inner radius = radius - (De + base)
+def add_gear(teethNum, radius, Ad, De, base, p_angle,
+ width=1, skew=0, conangle=0, rack=0, crown=0.0):
+
+ if teethNum < 2:
+ return None, None, None, None
+
+ t = 2 * pi / teethNum
+
+ if rack:
+ teethNum = 1
+
+ scale = (radius - 2 * width * tan(conangle)) / radius
+
+ verts = []
+ faces = []
+ vgroup_top = [] # Vertex group of top/tip? vertices.
+ vgroup_valley = [] # Vertex group of valley vertices
+
+ verts_bridge_prev = []
+ for toothCnt in range(teethNum):
+ a = toothCnt * t
+
+ verts_bridge_start = []
+ verts_bridge_end = []
+
+ verts_outside_top = []
+ verts_outside_bottom = []
+ for (s, d, c, top) \
+ in [(0, -width, 1, True), \
+ (skew, width, scale, False)]:
+
+ verts1, verts2, verts3, verts4 = add_tooth(a + s, t, d,
+ radius * c, Ad * c, De * c, base * c, p_angle,
+ rack, crown)
+
+ vertsIdx1 = list(range(len(verts), len(verts) + len(verts1)))
+ verts.extend(verts1)
+ vertsIdx2 = list(range(len(verts), len(verts) + len(verts2)))
+ verts.extend(verts2)
+ vertsIdx3 = list(range(len(verts), len(verts) + len(verts3)))
+ verts.extend(verts3)
+ vertsIdx4 = list(range(len(verts), len(verts) + len(verts4)))
+ verts.extend(verts4)
+
+ verts_outside = []
+ verts_outside.extend(vertsIdx2[:2])
+ verts_outside.append(vertsIdx3[0])
+ verts_outside.extend(vertsIdx4)
+ verts_outside.append(vertsIdx3[-1])
+ verts_outside.append(vertsIdx2[-1])
+
+ if top:
+ #verts_inside_top = vertsIdx1
+ verts_outside_top = verts_outside
+
+ verts_bridge_start.append(vertsIdx1[0])
+ verts_bridge_start.append(vertsIdx2[0])
+ verts_bridge_end.append(vertsIdx1[-1])
+ verts_bridge_end.append(vertsIdx2[-1])
+
+ else:
+ #verts_inside_bottom = vertsIdx1
+ verts_outside_bottom = verts_outside
+
+ verts_bridge_start.append(vertsIdx2[0])
+ verts_bridge_start.append(vertsIdx1[0])
+ verts_bridge_end.append(vertsIdx2[-1])
+ verts_bridge_end.append(vertsIdx1[-1])
+
+ # Valley = first 2 vertices of outer base:
+ vgroup_valley.extend(vertsIdx2[:1])
+ # Top/tip vertices:
+ vgroup_top.extend(vertsIdx4)
+
+ faces_tooth_middle_top = createFaces(vertsIdx2[1:], vertsIdx3,
+ flipped=top)
+ faces_tooth_outer_top = createFaces(vertsIdx3, vertsIdx4,
+ flipped=top)
+
+ faces_base_top = createFaces(vertsIdx1, vertsIdx2, flipped=top)
+ faces.extend(faces_base_top)
+
+ faces.extend(faces_tooth_middle_top)
+ faces.extend(faces_tooth_outer_top)
+
+ #faces_inside = createFaces(verts_inside_top, verts_inside_bottom)
+ #faces.extend(faces_inside)
+
+ faces_outside = createFaces(verts_outside_top, verts_outside_bottom,
+ flipped=True)
+ faces.extend(faces_outside)
+
+ if toothCnt == 0:
+ verts_bridge_first = verts_bridge_start
+
+ # Bridge one tooth to the next
+ if verts_bridge_prev:
+ faces_bridge = createFaces(verts_bridge_prev, verts_bridge_start)
+ #, closed=True (for "inside" faces)
+ faces.extend(faces_bridge)
+
+ # Remember "end" vertices for next tooth.
+ verts_bridge_prev = verts_bridge_end
+
+ # Bridge the first to the last tooth.
+ faces_bridge_f_l = createFaces(verts_bridge_prev, verts_bridge_first)
+ #, closed=True (for "inside" faces)
+ faces.extend(faces_bridge_f_l)
+
+ return verts, faces, vgroup_top, vgroup_valley
+
+
+# Create spokes geometry.
+# Returns:
+# * A list of vertices (list of tuples)
+# * A list of faces (list of lists)
+#
+# teethNum ... Number of teeth on the gear.
+# radius ... Radius of the gear, negative for crown gear
+# De ... Dedendum, extent of tooth below radius.
+# base ... Base, extent of gear below radius.
+# width ... Width, thickness of gear.
+# conangle ... Conical angle of gear. (radiant)
+# rack
+# spoke
+# spbevel
+# spwidth
+# splength
+# spresol
+#
+# @todo Finish this
+# @todo Create a function that takes a "Gear" and creates a
+# matching "Gear Spokes" object.
+def add_spokes(teethNum, radius, De, base, width=1, conangle=0, rack=0,
+ spoke=3, spbevel=0.1, spwidth=0.2, splength=1.0, spresol=9):
+
+ if teethNum < 2:
+ return None, None, None, None
+
+ if spoke < 2:
+ return None, None, None, None
+
+ t = 2 * pi / teethNum
+
+ if rack:
+ teethNum = 1
+
+ scale = (radius - 2 * width * tan(conangle)) / radius
+
+ verts = []
+ faces = []
+
+ c = scale # debug
+
+ fl = len(verts)
+ for toothCnt in range(teethNum):
+ a = toothCnt * t
+ s = 0 # For test
+
+ if toothCnt % spoke == 0:
+ for d in (-width, width):
+ sv, edgefaces, edgefaces2, sf = add_spoke(a + s, t, d,
+ radius * c, De * c, base * c,
+ spbevel, spwidth, splength, 0, spresol)
+ verts.extend(sv)
+ faces.extend([[j + fl for j in i] for i in sf])
+ fl += len(sv)
+
+ d1 = fl - len(sv)
+ d2 = fl - 2 * len(sv)
+
+ faces.extend([(i + d2, j + d2, j + d1, i + d1)
+ for (i, j) in zip(edgefaces[:-1], edgefaces[1:])])
+ faces.extend([(i + d2, j + d2, j + d1, i + d1)
+ for (i, j) in zip(edgefaces2[:-1], edgefaces2[1:])])
+
+ else:
+ for d in (-width, width):
+ sv, edgefaces, edgefaces2, sf = add_spoke(a + s, t, d,
+ radius * c, De * c, base * c,
+ spbevel, spwidth, splength, 1, spresol)
+
+ verts.extend(sv)
+ fl += len(sv)
+
+ d1 = fl - len(sv)
+ d2 = fl - 2 * len(sv)
+
+ faces.extend([[i + d2, i + 1 + d2, i + 1 + d1, i + d1]
+ for (i) in range(0, 3)])
+ faces.extend([[i + d2, i + 1 + d2, i + 1 + d1, i + d1]
+ for (i) in range(5, 8)])
+
+ return verts, faces
+
+
+# Create worm geometry.
+# Returns:
# * A list of vertices
# * A list of faces
# * A list (group) of vertices of the tip
# * A list (group) of vertices of the valley
#
-# teethNum ... Number of teeth on the gear. Set to 4 for "worm"
+# teethNum ... Number of teeth on the worm
# radius ... Radius of the gear, negative for crown gear
# Ad ... Addendum, extent of tooth above radius.
# De ... Dedendum, extent of tooth below radius.
@@ -398,14 +602,15 @@ def add_spoke2(a, t, d, radius, De, base, s, w, l, gap=0, width=19):
# spwidth
# splength
# spresol
-def add_gear(teethNum, radius, Ad, De, base, p_angle,
+#
+# @todo Prevent double vertices.
+# (Change it so only one row of verts is calculated for each step.)
+def add_worm(teethNum, radius, Ad, De, base, p_angle,
width=1, skew=0, conangle=0, rack=0, crown=0.0, spoke=0,
spbevel=0.1, spwidth=0.2, splength=1.0, spresol=9):
- worm = 0
- if teethNum < 5:
- worm = teethNum
- teethNum = 24
+ worm = teethNum
+ teethNum = 24
t = 2 * pi / teethNum
@@ -417,98 +622,98 @@ def add_gear(teethNum, radius, Ad, De, base, p_angle,
verts = []
faces = []
vgroup_top = [] # Vertex group of top/tip? vertices.
- vgroup_val = [] # Vertex group of valley vertices
+ vgroup_valley = [] # Vertex group of valley vertices
- M = [0]
- if worm:
- M = range(32)
- skew = radians(11.25)
- width = width / 2.0
+ rows = 32
+ M = range(rows)
+ skew = radians(11.25)
+ width = width / 2.0
for W in M:
- fl = W * teethNum * VERT_NUM * 2
- vertNum = 0 # Number of vertices
-
+ verts_bridge_prev = []
for toothCnt in range(teethNum):
a = toothCnt * t
- for (s, d, c, first) \
- in [(W * skew, W * 2 * width - width, 1, 1), \
- ((W + 1) * skew, W * 2 * width + width, scale, 0)]:
- if worm and toothCnt % (teethNum / worm) != 0:
- verts_tooth = add_tooth(a + s, t, d,
- radius - De, 0.0, 0.0, base, p_angle)
- verts.extend(verts_tooth)
+ verts_bridge_start = []
+ verts_bridge_end = []
+ verts_outside_top = []
+ verts_outside_bottom = []
+ for (s, d, c, top) \
+ in [(W * skew, W * 2 * width - width, 1, True), \
+ ((W + 1) * skew, W * 2 * width + width, scale, False)]:
+
+ if toothCnt % (teethNum / worm) != 0:
+ verts1, verts2, verts3, verts4 = add_tooth(a + s, t, d,
+ radius - De, 0.0, 0.0, base, p_angle)
else:
- verts_tooth = add_tooth(a + s, t, d,
+ verts1, verts2, verts3, verts4 = add_tooth(a + s, t, d,
radius * c, Ad * c, De * c, base * c, p_angle,
rack, crown)
- verts.extend(verts_tooth)
-
- if (not worm
- or (W == 0 and first)
- or (W == (len(M) - 1) and not first)):
- faces.extend([[j + vertNum + fl for j in i]
- for i in deepcopy(FACES)])
- vertNum += len(verts_tooth)
-
- faces.extend([[j + toothCnt * VERT_NUM * 2 + fl for j in i]
- for i in deepcopy(EFC)])
-
- vgroup_top.extend([i + toothCnt * VERT_NUM * 2
- for i in VERTS_TOOTH])
- vgroup_val.extend([i + toothCnt * VERT_NUM * 2
- for i in VERTS_VALLEY])
+ # Remove various unneeded vertices (if we are inside the worm)
+ del(verts2[2]) # Central vertex in the base of the tooth.
+ del(verts3[1]) # Central vertex in the middle of the tooth.
+
+ vertsIdx2 = list(range(len(verts), len(verts) + len(verts2)))
+ verts.extend(verts2)
+ vertsIdx3 = list(range(len(verts), len(verts) + len(verts3)))
+ verts.extend(verts3)
+ vertsIdx4 = list(range(len(verts), len(verts) + len(verts4)))
+ verts.extend(verts4)
+
+ verts_outside = []
+ verts_outside.extend(vertsIdx2[:2])
+ verts_outside.append(vertsIdx3[0])
+ verts_outside.extend(vertsIdx4)
+ verts_outside.append(vertsIdx3[-1])
+ verts_outside.append(vertsIdx2[-1])
+
+ if top:
+ verts_outside_top = verts_outside
+
+ verts_bridge_start.append(vertsIdx2[0])
+ verts_bridge_end.append(vertsIdx2[-1])
+ else:
+ verts_outside_bottom = verts_outside
- # EXPERIMENTAL: add spokes
- if not worm and spoke > 0:
- fl = len(v)
- for toothCnt in range(teethNum):
- a = toothCnt * t
- s = 0 # For test
+ verts_bridge_start.append(vertsIdx2[0])
+ verts_bridge_end.append(vertsIdx2[-1])
- if toothCnt % spoke == 0:
- for d in (-width, width):
- sv, edgefaces, edgefaces2, sf = add_spoke2(a + s, t, d,
- radius * c, De * c, base * c,
- spbevel, spwidth, splength, 0, spresol)
- verts.extend(sv)
- faces.extend([[j + fl for j in i] for i in sf])
- fl += len(sv)
+ # Valley = first 2 vertices of outer base:
+ vgroup_valley.extend(vertsIdx2[:1])
+ # Top/tip vertices:
+ vgroup_top.extend(vertsIdx4)
- d1 = fl - len(sv)
- d2 = fl - 2 * len(sv)
+ faces_outside = createFaces(
+ verts_outside_top,
+ verts_outside_bottom,
+ flipped=True)
+ faces.extend(faces_outside)
- faces.extend([(i + d2, j + d2, j + d1, i + d1)
- for (i, j) in zip(edgefaces[:-1], edgefaces[1:])])
- faces.extend([(i + d2, j + d2, j + d1, i + d1)
- for (i, j) in zip(edgefaces2[:-1], edgefaces2[1:])])
+ if toothCnt == 0:
+ verts_bridge_first = verts_bridge_start
- else:
- for d in (-width, width):
- sv, edgefaces, edgefaces2, sf = add_spoke2(a + s, t, d,
- radius * c, De * c, base * c,
- spbevel, spwidth, splength, 1, spresol)
+ # Bridge one tooth to the next
+ if verts_bridge_prev:
+ faces_bridge = createFaces(
+ verts_bridge_prev,
+ verts_bridge_start)
+ faces.extend(faces_bridge)
- verts.extend(sv)
- fl += len(sv)
+ # Remember "end" vertices for next tooth.
+ verts_bridge_prev = verts_bridge_end
- d1 = fl - len(sv)
- d2 = fl - 2 * len(sv)
+ # Bridge the first to the last tooth.
+ faces_bridge_f_l = createFaces(verts_bridge_prev, verts_bridge_first)
+ faces.extend(faces_bridge_f_l)
- #faces.extend([(i+d2, i+1+d2, i+1+d1, i+d1)
- # for (i) in (0, 1, 2, 3)])
- #faces.extend([(i+d2, i+1+d2, i+1+d1, i+d1)
- # for (i) in (5, 6, 7, 8)])
-
- return verts, faces, vgroup_top, vgroup_val
+ return verts, faces, vgroup_top, vgroup_valley
class AddGear(bpy.types.Operator):
'''Add a gear mesh.'''
- bl_idname = "mesh.gear_add"
+ bl_idname = "mesh.primitive_gear"
bl_label = "Add Gear"
bl_options = {'REGISTER', 'UNDO'}
@@ -519,8 +724,8 @@ class AddGear(bpy.types.Operator):
options={'HIDDEN'})
number_of_teeth = IntProperty(name="Number of Teeth",
description="Number of teeth on the gear",
- min=4,
- max=200,
+ min=2,
+ max=265,
default=12)
radius = FloatProperty(name="Radius",
description="Radius of the gear, negative for crown gear",
@@ -578,7 +783,7 @@ class AddGear(bpy.types.Operator):
props.dedendum,
props.base,
radians(props.angle),
- props.width,
+ width=props.width,
skew=radians(props.skew),
conangle=radians(props.conangle),
crown=props.crown)
@@ -613,12 +818,137 @@ class AddGear(bpy.types.Operator):
return {'FINISHED'}
-menu_func = (lambda self, context: self.layout.operator(AddGear.bl_idname,
- text="Gear", icon='PLUGIN'))
+class AddWormGear(bpy.types.Operator):
+ '''Add a worm gear mesh.'''
+ bl_idname = "mesh.primitive_worm_gear"
+ bl_label = "Add Worm Gear"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ # edit - Whether to add or update.
+ edit = BoolProperty(name="",
+ description="",
+ default=False,
+ options={'HIDDEN'})
+ number_of_teeth = IntProperty(name="Number of Teeth",
+ description="Number of teeth on the gear",
+ min=2,
+ max=265,
+ default=12)
+ radius = FloatProperty(name="Radius",
+ description="Radius of the gear, negative for crown gear",
+ min=-100.0,
+ max=100.0,
+ default=1.0)
+ addendum = FloatProperty(name="Addendum",
+ description="Addendum, extent of tooth above radius",
+ min=0.01,
+ max=100.0,
+ default=0.1)
+ dedendum = FloatProperty(name="Dedendum",
+ description="Dedendum, extent of tooth below radius",
+ min=0.0,
+ max=100.0,
+ default=0.1)
+ angle = FloatProperty(name="Pressure Angle",
+ description="Pressure angle, skewness of tooth tip (degrees)",
+ min=0.0,
+ max=45.0,
+ default=20.0)
+ base = FloatProperty(name="Base",
+ description="Base, extent of gear below radius",
+ min=0.0,
+ max=100.0,
+ default=0.2)
+ width = FloatProperty(name="Width",
+ description="Width, thickness of gear",
+ min=0.05,
+ max=100.0,
+ default=0.2)
+ skew = FloatProperty(name="Skewness",
+ description="Skew of teeth (degrees)",
+ min=-90.0,
+ max=90.0,
+ default=0.0)
+ conangle = FloatProperty(name="Conical angle",
+ description="Conical angle of gear (degrees)",
+ min=0.0,
+ max=90.0,
+ default=0.0)
+ crown = FloatProperty(name="Crown",
+ description="Inward pointing extend of crown teeth",
+ min=0.0,
+ max=100.0,
+ default=0.0)
+
+ def execute(self, context):
+ props = self.properties
+
+ verts, faces, verts_tip, verts_valley = add_worm(
+ props.number_of_teeth,
+ props.radius,
+ props.addendum,
+ props.dedendum,
+ props.base,
+ radians(props.angle),
+ props.width,
+ skew=radians(props.skew),
+ conangle=radians(props.conangle),
+ crown=props.crown)
+
+ # Actually create the mesh object from this geometry data.
+ obj = create_mesh_object(context, verts, [], faces, "Worm Gear",
+ props.edit)
+
+ # Store 'recall' properties in the object.
+ recall_args_list = {
+ "edit": True,
+ "number_of_teeth": props.number_of_teeth,
+ "radius": props.radius,
+ "addendum": props.addendum,
+ "dedendum": props.dedendum,
+ "angle": props.angle,
+ "base": props.base,
+ "width": props.width,
+ "skew": props.skew,
+ "conangle": props.conangle,
+ "crown": props.crown}
+ store_recall_properties(obj, self, recall_args_list)
+
+ # Create vertex groups from stored vertices.
+ tipGroup = obj.add_vertex_group('Tips')
+ for vert in verts_tip:
+ obj.add_vertex_to_group(vert, tipGroup, 1.0, 'ADD')
+
+ valleyGroup = obj.add_vertex_group('Valleys')
+ for vert in verts_valley:
+ obj.add_vertex_to_group(vert, valleyGroup, 1.0, 'ADD')
+
+ return {'FINISHED'}
+
+
+class INFO_MT_mesh_gears_add(bpy.types.Menu):
+ # Define the "Gears" menu
+ bl_idname = "INFO_MT_mesh_gears_add"
+ bl_label = "Gears"
+
+ def draw(self, context):
+ layout = self.layout
+ layout.operator_context = 'INVOKE_REGION_WIN'
+ layout.operator("mesh.primitive_gear",
+ text="Gear")
+ layout.operator("mesh.primitive_worm_gear",
+ text="Worm")
+
+
+# Define "Gears" menu
+menu_func = (lambda self,
+ context: self.layout.menu("INFO_MT_mesh_gears_add", icon="PLUGIN"))
def register():
bpy.types.register(AddGear)
+ bpy.types.register(AddWormGear)
+ bpy.types.register(INFO_MT_mesh_gears_add)
# Add "Gears" entry to the "Add Mesh" menu.
bpy.types.INFO_MT_mesh_add.append(menu_func)
@@ -626,6 +956,8 @@ def register():
def unregister():
bpy.types.unregister(AddGear)
+ bpy.types.unregister(AddWormGear)
+ bpy.types.unregister(INFO_MT_mesh_gears_add)
# Remove "Gears" entry from the "Add Mesh" menu.
bpy.types.INFO_MT_mesh_add.remove(menu_func)