1 # GPL # "author": "Pontiac, Fourmadmen, Dreampainter"
4 from bpy
.types
import Operator
5 from mathutils
import (
9 from math
import cos
, sin
, pi
10 from bpy
.props
import (
16 from bpy_extras
import object_utils
18 # Create a new mesh (object) from verts/edges/faces.
19 # verts/edges/faces ... List of vertices/edges/faces for the
20 # new mesh (as used in from_pydata)
21 # name ... Name of the new mesh (& object)
23 def create_mesh_object(context
, self
, verts
, edges
, faces
, name
):
26 mesh
= bpy
.data
.meshes
.new(name
)
28 # Make a mesh from a list of verts/edges/faces.
29 mesh
.from_pydata(verts
, edges
, faces
)
31 # Update mesh geometry after adding stuff.
34 from bpy_extras
import object_utils
35 return object_utils
.object_data_add(context
, mesh
, operator
=self
)
38 # A very simple "bridge" tool.
40 def createFaces(vertIdx1
, vertIdx2
, closed
=False, flipped
=False):
43 if not vertIdx1
or not vertIdx2
:
46 if len(vertIdx1
) < 2 and len(vertIdx2
) < 2:
50 if (len(vertIdx1
) != len(vertIdx2
)):
51 if (len(vertIdx1
) == 1 and len(vertIdx2
) > 1):
59 # Bridge the start with the end
66 face
.append(vertIdx1
[total
- 1])
70 face
= [vertIdx2
[0], vertIdx1
[0]]
72 face
.append(vertIdx1
[total
- 1])
73 face
.append(vertIdx2
[total
- 1])
76 # Bridge the rest of the faces
77 for num
in range(total
- 1):
80 face
= [vertIdx2
[num
], vertIdx1
[0], vertIdx2
[num
+ 1]]
82 face
= [vertIdx2
[num
], vertIdx1
[num
],
83 vertIdx1
[num
+ 1], vertIdx2
[num
+ 1]]
87 face
= [vertIdx1
[0], vertIdx2
[num
], vertIdx2
[num
+ 1]]
89 face
= [vertIdx1
[num
], vertIdx2
[num
],
90 vertIdx2
[num
+ 1], vertIdx1
[num
+ 1]]
96 # @todo Clean up vertex&face creation process a bit.
97 def add_gem(r1
, r2
, seg
, h1
, h2
):
101 seg = number of segments
104 Generates the vertices and faces of the gem
109 a
= 2.0 * pi
/ seg
# Angle between segments
110 offset
= a
/ 2.0 # Middle between segments
112 r3
= ((r1
+ r2
) / 2.0) / cos(offset
) # Middle of crown
113 r4
= (r1
/ 2.0) / cos(offset
) # Middle of pavilion
114 h3
= h2
/ 2.0 # Middle of crown height
115 h4
= -h1
/ 2.0 # Middle of pavilion height
118 vert_tip
= len(verts
)
119 verts
.append(Vector((0.0, 0.0, -h1
)))
121 # Middle vertex of the flat side (crown)
122 vert_flat
= len(verts
)
123 verts
.append(Vector((0.0, 0.0, h2
)))
128 s2
= sin(offset
+ i
* a
)
130 c2
= cos(offset
+ i
* a
)
132 verts
.append((r4
* s1
, r4
* c1
, h4
)) # Middle of pavilion
133 verts
.append((r1
* s2
, r1
* c2
, 0.0)) # Pavilion
134 verts
.append((r3
* s1
, r3
* c1
, h3
)) # Middle crown
135 edgeloop_flat
.append(len(verts
))
136 verts
.append((r2
* s2
, r2
* c2
, h2
)) # Crown
140 for index
in range(seg
):
142 j
= ((index
+ 1) % seg
) * 4
144 faces
.append([j
+ 2, vert_tip
, i
+ 2, i
+ 3]) # Tip -> Middle of pav
145 faces
.append([j
+ 2, i
+ 3, j
+ 3]) # Middle of pav -> pav
146 faces
.append([j
+ 3, i
+ 3, j
+ 4]) # Pav -> Middle crown
147 faces
.append([j
+ 4, i
+ 3, i
+ 4, i
+ 5]) # Crown quads
148 faces
.append([j
+ 4, i
+ 5, j
+ 5]) # Middle crown -> crown
150 faces_flat
= createFaces([vert_flat
], edgeloop_flat
, closed
=True)
151 faces
.extend(faces_flat
)
156 def add_diamond(segments
, girdle_radius
, table_radius
,
157 crown_height
, pavilion_height
):
160 z_axis
= (0.0, 0.0, -1.0)
165 height_flat
= crown_height
167 height_tip
= -pavilion_height
169 # Middle vertex of the flat side (crown)
170 vert_flat
= len(verts
)
171 verts
.append(Vector((0.0, 0.0, height_flat
)))
174 vert_tip
= len(verts
)
175 verts
.append(Vector((0.0, 0.0, height_tip
)))
180 for index
in range(segments
):
181 quat
= Quaternion(z_axis
, (index
/ segments
) * PI_2
)
183 # angle = PI_2 * index / segments # UNUSED
186 verts_flat
.append(len(verts
))
187 vec
= quat
@ Vector((table_radius
, 0.0, height_flat
))
190 # Row for the middle/girdle
191 verts_girdle
.append(len(verts
))
192 vec
= quat
@ Vector((girdle_radius
, 0.0, height_middle
))
196 faces_flat
= createFaces([vert_flat
], verts_flat
, closed
=True,
199 faces_side
= createFaces(verts_girdle
, verts_flat
, closed
=True)
201 faces_tip
= createFaces([vert_tip
], verts_girdle
, closed
=True)
203 faces
.extend(faces_tip
)
204 faces
.extend(faces_side
)
205 faces
.extend(faces_flat
)
210 class AddDiamond(Operator
, object_utils
.AddObjectHelper
):
211 bl_idname
= "mesh.primitive_diamond_add"
212 bl_label
= "Add Diamond"
213 bl_description
= "Construct a diamond mesh"
214 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
216 Diamond
: BoolProperty(name
= "Diamond",
218 description
= "Diamond")
220 #### change properties
221 name
: StringProperty(name
= "Name",
222 description
= "Name")
224 change
: BoolProperty(name
= "Change",
226 description
= "change Diamond")
228 segments
: IntProperty(
230 description
="Number of segments for the diamond",
235 girdle_radius
: FloatProperty(
236 name
="Girdle Radius",
237 description
="Girdle radius of the diamond",
242 table_radius
: FloatProperty(
244 description
="Girdle radius of the diamond",
249 crown_height
: FloatProperty(
251 description
="Crown height of the diamond",
256 pavilion_height
: FloatProperty(
257 name
="Pavilion Height",
258 description
="Pavilion height of the diamond",
264 def draw(self
, context
):
267 box
.prop(self
, "segments")
268 box
.prop(self
, "girdle_radius")
269 box
.prop(self
, "table_radius")
270 box
.prop(self
, "crown_height")
271 box
.prop(self
, "pavilion_height")
273 if self
.change
== False:
274 # generic transform props
276 box
.prop(self
, 'align', expand
=True)
277 box
.prop(self
, 'location', expand
=True)
278 box
.prop(self
, 'rotation', expand
=True)
280 def execute(self
, context
):
281 # turn off 'Enter Edit Mode'
282 use_enter_edit_mode
= bpy
.context
.preferences
.edit
.use_enter_edit_mode
283 bpy
.context
.preferences
.edit
.use_enter_edit_mode
= False
285 if bpy
.context
.mode
== "OBJECT":
286 if context
.selected_objects
!= [] and context
.active_object
and \
287 ('Diamond' in context
.active_object
.data
.keys()) and (self
.change
== True):
288 obj
= context
.active_object
290 oldmeshname
= obj
.data
.name
292 verts
, faces
= add_diamond(self
.segments
,
296 self
.pavilion_height
)
297 mesh
= bpy
.data
.meshes
.new("TMP")
298 mesh
.from_pydata(verts
, [], faces
)
302 for material
in oldmesh
.materials
:
303 obj
.data
.materials
.append(material
)
305 bpy
.data
.meshes
.remove(oldmesh
)
306 obj
.data
.name
= oldmeshname
308 verts
, faces
= add_diamond(self
.segments
,
312 self
.pavilion_height
)
314 obj
= create_mesh_object(context
, self
, verts
, [], faces
, "Diamond")
316 obj
.data
["Diamond"] = True
317 obj
.data
["change"] = False
318 for prm
in DiamondParameters():
319 obj
.data
[prm
] = getattr(self
, prm
)
321 if bpy
.context
.mode
== "EDIT_MESH":
322 active_object
= context
.active_object
323 name_active_object
= active_object
.name
324 bpy
.ops
.object.mode_set(mode
='OBJECT')
325 verts
, faces
= add_diamond(self
.segments
,
329 self
.pavilion_height
)
331 obj
= create_mesh_object(context
, self
, verts
, [], faces
, "TMP")
334 active_object
.select_set(True)
335 bpy
.ops
.object.join()
336 context
.active_object
.name
= name_active_object
337 bpy
.ops
.object.mode_set(mode
='EDIT')
339 if use_enter_edit_mode
:
340 bpy
.ops
.object.mode_set(mode
= 'EDIT')
342 # restore pre operator state
343 bpy
.context
.preferences
.edit
.use_enter_edit_mode
= use_enter_edit_mode
347 def DiamondParameters():
348 DiamondParameters
= [
355 return DiamondParameters
358 class AddGem(Operator
, object_utils
.AddObjectHelper
):
359 bl_idname
= "mesh.primitive_gem_add"
361 bl_description
= "Construct an offset faceted gem mesh"
362 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
364 Gem
: BoolProperty(name
= "Gem",
368 #### change properties
369 name
: StringProperty(name
= "Name",
370 description
= "Name")
372 change
: BoolProperty(name
= "Change",
374 description
= "change Gem")
376 segments
: IntProperty(
378 description
="Longitudial segmentation",
383 pavilion_radius
: FloatProperty(
385 description
="Radius of the gem",
390 crown_radius
: FloatProperty(
392 description
="Radius of the table(top)",
397 crown_height
: FloatProperty(
399 description
="Height of the top half",
404 pavilion_height
: FloatProperty(
405 name
="Pavilion height",
406 description
="Height of bottom half",
412 def draw(self
, context
):
415 box
.prop(self
, "segments")
416 box
.prop(self
, "pavilion_radius")
417 box
.prop(self
, "crown_radius")
418 box
.prop(self
, "crown_height")
419 box
.prop(self
, "pavilion_height")
421 if self
.change
== False:
422 # generic transform props
424 box
.prop(self
, 'align', expand
=True)
425 box
.prop(self
, 'location', expand
=True)
426 box
.prop(self
, 'rotation', expand
=True)
428 def execute(self
, context
):
429 # turn off 'Enter Edit Mode'
430 use_enter_edit_mode
= bpy
.context
.preferences
.edit
.use_enter_edit_mode
431 bpy
.context
.preferences
.edit
.use_enter_edit_mode
= False
433 if bpy
.context
.mode
== "OBJECT":
434 if context
.selected_objects
!= [] and context
.active_object
and \
435 ('Gem' in context
.active_object
.data
.keys()) and (self
.change
== True):
436 obj
= context
.active_object
438 oldmeshname
= obj
.data
.name
439 verts
, faces
= add_gem(
440 self
.pavilion_radius
,
443 self
.pavilion_height
,
445 mesh
= bpy
.data
.meshes
.new("TMP")
446 mesh
.from_pydata(verts
, [], faces
)
449 for material
in oldmesh
.materials
:
450 obj
.data
.materials
.append(material
)
451 bpy
.data
.meshes
.remove(oldmesh
)
452 obj
.data
.name
= oldmeshname
454 verts
, faces
= add_gem(
455 self
.pavilion_radius
,
458 self
.pavilion_height
,
461 obj
= create_mesh_object(context
, self
, verts
, [], faces
, "Gem")
463 obj
.data
["Gem"] = True
464 obj
.data
["change"] = False
465 for prm
in GemParameters():
466 obj
.data
[prm
] = getattr(self
, prm
)
468 if bpy
.context
.mode
== "EDIT_MESH":
469 active_object
= context
.active_object
470 name_active_object
= active_object
.name
471 bpy
.ops
.object.mode_set(mode
='OBJECT')
472 verts
, faces
= add_gem(
473 self
.pavilion_radius
,
476 self
.pavilion_height
,
479 obj
= create_mesh_object(context
, self
, verts
, [], faces
, "TMP")
482 active_object
.select_set(True)
483 bpy
.ops
.object.join()
484 context
.active_object
.name
= name_active_object
485 bpy
.ops
.object.mode_set(mode
='EDIT')
487 if use_enter_edit_mode
:
488 bpy
.ops
.object.mode_set(mode
= 'EDIT')
490 # restore pre operator state
491 bpy
.context
.preferences
.edit
.use_enter_edit_mode
= use_enter_edit_mode