Created
January 23, 2020 10:56
-
-
Save batFINGER/a6831a816e008f1ddf0958f0f8ea99bd to your computer and use it in GitHub Desktop.
Add Mesh Spiral Thingy
This file contains hidden or 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
bl_info = { | |
"name": "Spiral Mesh", | |
"author": "batFINGER", | |
"version": (1, 0), | |
"blender": (2, 80, 0), | |
"location": "View3D > Add > Mesh > Spiral Mesh", | |
"description": "Adds a Spiral Thingy", | |
"warning": "", | |
"wiki_url": "", | |
"category": "Add Mesh", | |
} | |
import bmesh | |
from math import sin, cos, radians | |
from mathutils import Vector, Matrix | |
from bpy_extras.object_utils import AddObjectHelper, object_data_add | |
from bpy.props import FloatProperty, IntProperty, EnumProperty | |
from bpy.types import Operator | |
import bpy | |
def spiral_thingy_mesh(radius, | |
c, | |
segments, | |
growth_angle, | |
thickness, | |
thickness_type): | |
me = bpy.data.meshes.new("Spiral Thingy") | |
z_axis = Vector((0, 0, 1)) | |
def spherical_to_xyz(theta): | |
x = sin(theta) * cos(c * theta) | |
y = sin(theta) * sin(c * theta) | |
z = cos(theta) | |
return radius * Vector((x, y, z)) | |
bm = bmesh.new() | |
edges = [] | |
seg_angle = radians(180 / segments) | |
for i in range(segments + 1): | |
theta = i * seg_angle | |
co = spherical_to_xyz(theta) | |
axis = z_axis.cross(co) | |
v = bm.verts.new(co) | |
M = Matrix.Rotation(growth_angle, 4, co) | |
R = Matrix.Rotation(sin(theta) * growth_angle, 4, axis) | |
x = bm.verts.new(R @ M @ co) | |
R = Matrix.Rotation(sin(theta) * -growth_angle, 4, axis) | |
y = bm.verts.new(R @ M @ co) | |
et = bm.edges.new((x, v)) | |
eb = bm.edges.new((v, y)) | |
if edges: | |
bmesh.ops.bridge_loops(bm, | |
edges=edges + [et, eb]) | |
edges = [eb, et] | |
if thickness_type != 'NONE': | |
geom = bmesh.ops.extrude_face_region( | |
bm, | |
geom=bm.faces[:] + bm.edges[:] + bm.verts[:], | |
)["geom"] | |
verts = [e for e in geom if isinstance(e, bmesh.types.BMVert)] | |
if thickness_type == 'CONSTANT': | |
s = (radius - thickness) / radius | |
bmesh.ops.scale(bm, | |
verts=verts, | |
vec=(s,) * 3) | |
elif thickness_type == 'TAPER': | |
for v in verts: | |
s = sin(v.co.angle(z_axis)) * thickness | |
v.co -= s * thickness * v.co.normalized() | |
bm.to_mesh(me) | |
return me | |
class MESH_OT_add_spiral_thingy(Operator, AddObjectHelper): | |
"""Add a Spiral Thingy""" | |
bl_idname = "mesh.add_spiral_thingy" | |
bl_label = "Add Spiral Thingy" | |
bl_options = {'REGISTER', 'UNDO'} | |
radius: FloatProperty( | |
name="Radius", | |
default=1.0, | |
subtype='DISTANCE', | |
description="Sphere Radius", | |
) | |
turns: IntProperty( | |
name="Turns", | |
default=5, | |
min=2, | |
) | |
segments: IntProperty( | |
name="Segments", | |
default=64, | |
min=2, | |
) | |
growth_angle: FloatProperty( | |
name="Width Angle", | |
subtype='ANGLE', | |
default=radians(10), | |
) | |
# use_thickness enum | |
thickness: FloatProperty( | |
name="Thickness", | |
subtype='DISTANCE', | |
default=0.1, | |
) | |
thickness_type: EnumProperty( | |
items=[('NONE', "None", "No Thickness"), | |
('TAPER', "Taper", "Taper Thickness"), | |
('CONSTANT', "Constant", "Constant Thickness"), | |
], | |
default = 'NONE', | |
) | |
def draw(self, context): | |
layout = self.layout | |
col = layout.column() | |
col.prop(self, "radius") | |
col.prop(self, "turns") | |
col.prop(self, "segments") | |
col.prop(self, "growth_angle") | |
col.prop(self, "thickness_type") | |
if self.thickness_type != 'NONE': | |
col.prop(self, "thickness") | |
# annotated on AddObjectHelper | |
for prop in AddObjectHelper.__annotations__.keys(): | |
col.prop(self, prop) | |
def execute(self, context): | |
object_data_add(context, | |
spiral_thingy_mesh( | |
self.radius, | |
self.turns, | |
self.segments, | |
self.growth_angle, | |
self.thickness, | |
self.thickness_type), | |
operator=self) | |
return {'FINISHED'} | |
# Registration | |
def add_spiral_thingy_button(self, context): | |
self.layout.operator( | |
MESH_OT_add_spiral_thingy.bl_idname, | |
icon='FORCE_VORTEX') | |
classes = (MESH_OT_add_spiral_thingy,) | |
def register(): | |
for cls in classes: | |
bpy.utils.register_class(cls) | |
bpy.types.VIEW3D_MT_mesh_add.append(add_spiral_thingy_button) | |
def unregister(): | |
for cls in reversed(classes): | |
bpy.utils.unregister_class(cls) | |
bpy.types.VIEW3D_MT_mesh_add.remove(add_spiral_thingy_button) | |
if __name__ == "__main__": | |
register() |
Author
batFINGER
commented
Jan 23, 2020
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment