1 # GPL # Author, Anthony D'Agostino
4 from mathutils
import Vector
5 from math
import sin
, cos
, pi
6 from bpy
.props
import (
11 from bpy_extras
import object_utils
14 def create_mesh_object(context
, verts
, edges
, faces
, name
):
16 mesh
= bpy
.data
.meshes
.new(name
)
17 # Make a mesh from a list of verts/edges/faces.
18 mesh
.from_pydata(verts
, edges
, faces
)
19 # Update mesh geometry after adding stuff.
21 from bpy_extras
import object_utils
22 return object_utils
.object_data_add(context
, mesh
, operator
=None)
25 # ========================
26 # === Torus Knot Block ===
27 # ========================
30 x
= cos(t
) - 2 * cos(2 * t
)
31 y
= sin(t
) + 2 * sin(2 * t
)
33 return Vector([x
, y
, z
])
37 x
= 10 * (cos(t
) + cos(3 * t
)) + cos(2 * t
) + cos(4 * t
)
38 y
= 6 * sin(t
) + 10 * sin(3 * t
)
39 z
= 4 * sin(3 * t
) * sin(5 * t
/ 2) + 4 * sin(4 * t
) - 2 * sin(6 * t
)
40 return Vector([x
, y
, z
]) * 0.2
44 x
= 2.5 * cos(t
+ pi
) / 3 + 2 * cos(3 * t
)
45 y
= 2.5 * sin(t
) / 3 + 2 * sin(3 * t
)
46 z
= 1.5 * sin(4 * t
) + sin(2 * t
) / 3
47 return Vector([x
, y
, z
])
50 def make_verts(ures
, vres
, r2
, knotfunc
):
53 t1
= (i
+ 0) * 2 * pi
/ ures
54 t2
= (i
+ 1) * 2 * pi
/ ures
55 a
= knotfunc(t1
) # curr point
56 b
= knotfunc(t2
) # next point
57 a
, b
= map(Vector
, (a
, b
))
66 l
= (cos(k
), 0.0, sin(k
))
78 def make_faces(ures
, vres
):
80 for u
in range(0, ures
):
81 for v
in range(0, vres
):
83 p2
= v
+ ((u
+ 1) % ures
) * vres
84 p4
= (v
+ 1) % vres
+ u
* vres
85 p3
= (v
+ 1) % vres
+ ((u
+ 1) % ures
) * vres
86 faces
.append([p4
, p3
, p2
, p1
])
90 def make_knot(knotidx
, ures
):
92 knotfunc
= knots
[knotidx
- 1]
95 verts
= make_verts(ures
, vres
, r2
, knotfunc
)
96 faces
= make_faces(ures
, vres
)
100 class AddTorusKnot(bpy
.types
.Operator
, object_utils
.AddObjectHelper
):
101 bl_idname
= "mesh.primitive_torusknot_add"
102 bl_label
= "Add Torus Knot"
103 bl_description
= "Construct a torus knot mesh"
104 bl_options
= {"REGISTER", "UNDO"}
106 TorusKnot
: BoolProperty(name
= "TorusKnot",
108 description
= "TorusKnot")
109 change
: BoolProperty(name
= "Change",
111 description
= "change TorusKnot")
113 resolution
: IntProperty(
115 description
="Resolution of the Torus Knot",
119 objecttype
: IntProperty(
121 description
="Type of Knot",
126 def draw(self
, context
):
129 layout
.prop(self
, 'resolution', expand
=True)
130 layout
.prop(self
, 'objecttype', expand
=True)
132 if self
.change
== False:
133 col
= layout
.column(align
=True)
134 col
.prop(self
, 'align', expand
=True)
135 col
= layout
.column(align
=True)
136 col
.prop(self
, 'location', expand
=True)
137 col
= layout
.column(align
=True)
138 col
.prop(self
, 'rotation', expand
=True)
140 def execute(self
, context
):
141 # turn off 'Enter Edit Mode'
142 use_enter_edit_mode
= bpy
.context
.preferences
.edit
.use_enter_edit_mode
143 bpy
.context
.preferences
.edit
.use_enter_edit_mode
= False
145 if bpy
.context
.mode
== "OBJECT":
146 if context
.selected_objects
!= [] and context
.active_object
and \
147 (context
.active_object
.data
is not None) and ('TorusKnot' in context
.active_object
.data
.keys()) and \
148 (self
.change
== True):
149 obj
= context
.active_object
151 oldmeshname
= obj
.data
.name
152 verts
, faces
= make_knot(self
.objecttype
, self
.resolution
)
153 mesh
= bpy
.data
.meshes
.new('TorusKnot')
154 mesh
.from_pydata(verts
, [], faces
)
156 for material
in oldmesh
.materials
:
157 obj
.data
.materials
.append(material
)
158 bpy
.data
.meshes
.remove(oldmesh
)
159 obj
.data
.name
= oldmeshname
161 verts
, faces
= make_knot(self
.objecttype
, self
.resolution
)
162 mesh
= bpy
.data
.meshes
.new('TorusKnot')
163 mesh
.from_pydata(verts
, [], faces
)
164 obj
= object_utils
.object_data_add(context
, mesh
, operator
=self
)
166 obj
.data
["TorusKnot"] = True
167 obj
.data
["change"] = False
168 for prm
in TorusKnotParameters():
169 obj
.data
[prm
] = getattr(self
, prm
)
171 if bpy
.context
.mode
== "EDIT_MESH":
172 active_object
= context
.active_object
173 name_active_object
= active_object
.name
174 bpy
.ops
.object.mode_set(mode
='OBJECT')
175 verts
, faces
= make_knot(self
.objecttype
, self
.resolution
)
176 mesh
= bpy
.data
.meshes
.new('TorusKnot')
177 mesh
.from_pydata(verts
, [], faces
)
178 obj
= object_utils
.object_data_add(context
, mesh
, operator
=self
)
180 active_object
.select_set(True)
181 bpy
.context
.view_layer
.objects
.active
= active_object
182 bpy
.ops
.object.join()
183 context
.active_object
.name
= name_active_object
184 bpy
.ops
.object.mode_set(mode
='EDIT')
186 if use_enter_edit_mode
:
187 bpy
.ops
.object.mode_set(mode
= 'EDIT')
189 # restore pre operator state
190 bpy
.context
.preferences
.edit
.use_enter_edit_mode
= use_enter_edit_mode
194 def TorusKnotParameters():
195 TorusKnotParameters
= [
199 return TorusKnotParameters