diff --git a/add_mesh_gears.py b/add_mesh_gears.py
index 2ffd8add4c8dcc3325763a1a91aa02953479268c..38ad918eccba94d919c90ae222a7827935493594 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)