1 # SPDX-FileCopyrightText: 2015-2023 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
10 from bpy
.types
import Operator
11 from mathutils
import (
15 from bpy
.props
import (
21 from bpy_extras
import object_utils
23 # mesh generating function, returns mesh
24 def add_mesh_Brilliant(context
, s
, table_w
, crown_h
, girdle_t
, pavi_d
, bezel_f
,
25 pavi_f
, culet
, girdle_real
, keep_lga
, g_real_smooth
):
27 # # possible user inputs ( output 100% = 2 blender units )
28 # s # no. of girdle facets (steps) default: 16
29 # table_w # table width default: 0.530
30 # crown_h # crown height default: 0.162
31 # girdle_t # girdle thickness default: 0.017
32 # pavi_d # pavilion depth default: 0.431
33 # bezel_f # bezel factor default: 0.250
34 # pavi_f # pavilion factor default: 0.400
35 # culet # culet size default: 0.000
36 # girdle_real # type of girdle flat/real default: True
37 # g_real_smooth # smooth or flat shading default: False
38 # keep_lga # when culet > 0, keep lga default: False
40 # variables / shortcuts
41 if s
% 2: # prevent odd number of steps (messes up mesh)
45 ang
= 2 * pi
/ s
# angle step size
46 Verts
= [] # collect all vertices
47 Faces
= [] # collect all faces
54 def fa(*vs
): # shortcut Faces.append
60 def va(vx
, vz
, iang
, sang
, n
): # shortcut Verts.append
62 v
= Vector((vx
, 0, vz
))
64 E_rot
= Euler((0, 0, ai
), 'XYZ')
66 Verts
.append((v
.x
, v
.y
, v
.z
))
69 uga
= (1 - bezel_f
) * crown_h
* 2 / (ca2
-
70 (table_w
+ (1 - table_w
) * bezel_f
) * ca2
/ ca
)
74 if pavi_f
> 0 and pavi_f
< 1:
75 lga
= (1 - pavi_f
) * pavi_d
* 2 / (ca2
- pavi_f
* ca2
/ ca
)
81 lga
= (1 - pavi_f
) * pavi_d
* 2 / (ca2
-
82 (culet
+ (1 - culet
) * pavi_f
) * ca2
/ ca
)
84 # append girdle vertices
86 va(1, 2 * girdle_t
, ang
, 0, s
)
88 # append real girdle vertices
91 dfu
= uga
* (ta8
+ ta4
) * sa4
93 dfl
= lga
* (ta8
+ ta4
) * sa4
94 if abs(dnu
) + abs(dnl
) > 2 * girdle_t
or dnu
< 0 or dnl
< 0:
97 va(1, dnl
, ang
, ang
/ 2, s
)
98 va(1, 2 * girdle_t
- dnu
, ang
, ang
/ 2, s
)
99 va(1, dfl
, ang
/ 2, ang
/ 4, 2 * s
)
100 va(1, 2 * girdle_t
- dfu
, ang
/ 2, ang
/ 4, 2 * s
)
103 l1
= len(Verts
) # 2*s / 8*s
107 fa(i
, i
+ s
, 2 * i
+ 6 * s
, 2 * i
+ 4 * s
)
109 fa(i
, s
, l1
- 1, 6 * s
- 1)
111 fa(i
, i
+ s
, 2 * i
+ 6 * s
- 1, 2 * i
+ 4 * s
- 1)
112 elif i
> 2 * s
- 1 and i
< 3 * s
:
113 fa(i
, i
+ s
, 2 * (i
+ s
), 2 * i
)
114 fa(i
, i
+ s
, 2 * (i
+ s
) + 1, 2 * i
+ 1)
117 fa(i
, i
+ s
, i
+ s
+ 1, i
+ 1)
121 # append upper girdle facet vertices
122 va((table_w
+ (1 - table_w
) * bezel_f
) / ca
, (1 - bezel_f
) * 2 * crown_h
+
123 2 * girdle_t
, 2 * ang
, ang
, int(s
/ 2))
125 # make upper girdle facet faces
126 l2
= len(Verts
) # 2.5*s / 8.5*s
128 if i
> s
and i
< 2 * s
- 1 and i
% 2 != 0:
130 fa(i
, 2 * (i
+ 2 * s
), i
+ 2 * s
, 2 * (i
+ 2 * s
) + 1, i
+ 1,
131 int(7.5 * s
) + int((i
- 1) / 2))
132 fa(i
, 2 * (i
+ 2 * s
) - 1, i
+ 2 * s
- 1, 2 * (i
+ 2 * s
- 1),
133 i
- 1, int(7.5 * s
) + int((i
- 1) / 2))
135 fa(i
, i
+ 1, int((i
+ 3 * s
) / 2))
136 fa(i
, i
- 1, int((i
+ 3 * s
) / 2))
139 fa(i
, l1
- 1, 4 * s
- 1, l1
- 2, 2 * i
- 1, l2
- 1)
140 fa(2 * i
- 2, l1
- 4, 4 * s
- 2, l1
- 3, 2 * i
- 1, l2
- 1)
142 fa(i
, 2 * i
- 1, l2
- 1)
143 fa(2 * i
- 1, 2 * i
- 2, l2
- 1)
145 # append table vertices
146 va(table_w
, (crown_h
+ girdle_t
) * 2, 2 * ang
, 0, int(s
/ 2))
148 # make bezel facet faces and star facet faces
149 l3
= len(Verts
) # 3*s / 9*s
151 if i
> l2
- 1 and i
< l3
- 1:
152 fa(i
, i
+ 1, i
- int(s
/ 2))
153 fa(i
+ 1, i
- int(s
/ 2), 2 * (i
- l2
) + 2 + s
, i
- int(s
/ 2) + 1)
156 fa(s
, l2
- 1, l2
, l2
- int(s
/ 2))
158 # make table facet face
165 # append lower girdle facet vertices
167 va(pavi_f
/ ca
, (pavi_f
- 1) * pavi_d
* 2, 2 * ang
, ang
, int(s
/ 2))
169 va((pavi_f
* (1 - culet
) + culet
) / ca
, (pavi_f
- 1) * pavi_d
* 2, 2 * ang
,
172 # make lower girdle facet faces
173 l4
= len(Verts
) # 3.5*s / 9.5*s
175 if i
> 0 and i
< s
- 1 and i
% 2 == 0:
177 fa(i
, 2 * (i
+ 2 * s
), i
+ 2 * s
, 2 * (i
+ 2 * s
) + 1, i
+ 1,
179 fa(i
, 2 * (i
+ 2 * s
) - 1, i
+ 2 * s
- 1, 2 * (i
+ 2 * s
- 1),
180 i
- 1, int(i
/ 2) + 9 * s
- 1)
182 fa(i
, i
+ 1, int(i
/ 2) + l4
- int(s
/ 2))
183 fa(i
, i
- 1, int(i
/ 2) + l4
- int(s
/ 2) - 1)
186 fa(0, 4 * s
, 2 * s
, 4 * s
+ 1, 1, 9 * s
)
187 fa(0, 6 * s
- 1, 3 * s
- 1, 6 * s
- 2, s
- 1, l4
- 1)
189 fa(0, 1, l4
- int(s
/ 2))
192 # append culet vertice(s)
194 va(0, pavi_d
* (-2), 0, 0, 1)
197 va(culet
* pavi_f
/ ca
, pavi_d
* (-2) + culet
* pavi_f
* 2 * pavi_d
,
198 2 * ang
, ang
, int(s
/ 2))
200 va(culet
/ ca
, pavi_d
* (-2), 2 * ang
, ang
, int(s
/ 2))
202 # make pavilion facet face
203 l5
= len(Verts
) # 4*s / 10*s //if !culet: 3.5*s+1 / 9.5*s+1
205 if i
> 0 and i
< s
- 1 and i
% 2 == 0:
207 fa(i
, l3
+ int(i
/ 2), l3
+ int((s
+ i
) / 2),
208 l3
+ int((s
+ i
) / 2) - 1, l3
+ int(i
/ 2) - 1)
210 fa(i
, l3
+ int(i
/ 2), l5
- 1, l3
+ int(i
/ 2) - 1)
213 fa(i
, l3
, l4
, l5
- 1, l4
- 1)
215 fa(i
, l3
, l5
- 1, l4
- 1)
217 # make culet facet face
225 # create actual mesh and object based on Verts and Faces given
226 dmesh
= bpy
.data
.meshes
.new("dmesh")
227 dmesh
.from_pydata(Verts
, [], Faces
)
232 # object generating function, returns final object
233 def addBrilliant(context
, self
, s
, table_w
, crown_h
, girdle_t
, pavi_d
, bezel_f
,
234 pavi_f
, culet
, girdle_real
, keep_lga
, g_real_smooth
):
236 # deactivate possible active Objects
237 bpy
.context
.view_layer
.objects
.active
= None
239 # create actual mesh and object based on Verts and Faces given
240 dmesh
= add_mesh_Brilliant(context
, s
, table_w
, crown_h
, girdle_t
, pavi_d
, bezel_f
,
241 pavi_f
, culet
, girdle_real
, keep_lga
, g_real_smooth
)
243 # Create object and link it into scene.
244 dobj
= object_utils
.object_data_add(context
, dmesh
, operator
=self
, name
="dobj")
246 # activate and select object
247 bpy
.context
.view_layer
.objects
.active
= dobj
248 dobj
.select_set(True)
249 obj
= bpy
.context
.active_object
251 # flip all face normals outside
252 bpy
.ops
.object.mode_set(mode
='EDIT', toggle
=False)
253 sel_mode
= bpy
.context
.tool_settings
.mesh_select_mode
254 bpy
.context
.tool_settings
.mesh_select_mode
= [False, False, True]
255 bpy
.ops
.object.mode_set(mode
='OBJECT', toggle
=False)
256 for i
, face
in enumerate(obj
.data
.polygons
):
258 bpy
.ops
.object.mode_set(mode
='EDIT', toggle
=False)
259 bpy
.ops
.mesh
.normals_make_consistent(inside
=False)
260 bpy
.context
.tool_settings
.mesh_select_mode
= sel_mode
261 bpy
.ops
.object.mode_set(mode
='OBJECT', toggle
=False)
263 # make girdle smooth for complex girdle
264 if girdle_real
and g_real_smooth
:
266 bpy
.ops
.object.mode_set(mode
='EDIT', toggle
=False)
268 bpy
.ops
.mesh
.select_all(action
='DESELECT') # deselect all mesh data
269 bpy
.ops
.object.mode_set(mode
='OBJECT')
271 dp
= obj
.data
.polygons
[:4 * s
] # only consider faces of girdle
272 ov
= obj
.data
.vertices
274 for i
, p
in enumerate(dp
):
275 pls
.extend(p
.vertices
) # list all verts of girdle
277 for i
, e
in enumerate(obj
.data
.edges
): # select edges to mark sharp
278 if e
.vertices
[0] in pls
and e
.vertices
[1] in pls
and abs(
279 ov
[e
.vertices
[0]].co
.x
- ov
[e
.vertices
[1]].co
.x
):
280 obj
.data
.edges
[i
].select
= True
282 obj
.data
.edges
[i
].select
= False
284 bpy
.ops
.object.mode_set(mode
='EDIT', toggle
=False)
285 bpy
.ops
.mesh
.mark_sharp()
287 bpy
.context
.tool_settings
.mesh_select_mode
= [False, False, True]
288 bpy
.ops
.object.mode_set(mode
='OBJECT', toggle
=False)
289 bpy
.ops
.object.select_all(action
='DESELECT')
290 for i
, face
in enumerate(obj
.data
.polygons
):
295 bpy
.ops
.object.mode_set(mode
='EDIT', toggle
=False)
296 bpy
.ops
.mesh
.faces_shade_smooth()
298 edge_split_modifier
= context
.object.modifiers
.new("", 'EDGE_SPLIT')
300 bpy
.context
.tool_settings
.mesh_select_mode
= sel_mode
301 bpy
.ops
.object.mode_set(mode
='OBJECT', toggle
=False)
303 bpy
.ops
.object.modifier_apply(modifier
=edge_split_modifier
.name
)
308 # add new operator for object
309 class MESH_OT_primitive_brilliant_add(Operator
, object_utils
.AddObjectHelper
):
310 bl_idname
= "mesh.primitive_brilliant_add"
311 bl_label
= "Custom Brilliant"
312 bl_description
= "Construct a custom brilliant mesh"
313 bl_options
= {'REGISTER', 'UNDO', 'PRESET'}
315 Brilliant
: BoolProperty(name
= "Brilliant",
317 description
= "Brilliant")
318 change
: BoolProperty(name
= "Change",
320 description
= "change Brilliant")
324 description
="Longitudial segmentation",
331 table_w
: FloatProperty(
333 description
="Width of table",
339 crown_h
: FloatProperty(
341 description
="Height of crown",
347 girdle_t
: FloatProperty(
348 name
="Girdle height",
349 description
="Height of girdle",
355 girdle_real
: BoolProperty(
357 description
="More beautiful girdle; has more polygons",
360 g_real_smooth
: BoolProperty(
361 name
="Smooth girdle",
362 description
="smooth shading for girdle, only available for real girdle",
365 pavi_d
: FloatProperty(
366 name
="Pavilion depth",
367 description
="Height of pavilion",
373 bezel_f
: FloatProperty(
374 name
="Upper facet factor",
375 description
="Determines the form of bezel and upper girdle facets",
381 pavi_f
: FloatProperty(
382 name
="Lower facet factor",
383 description
="Determines the form of pavilion and lower girdle facets",
389 culet
: FloatProperty(
391 description
="0: no culet (default)",
397 keep_lga
: BoolProperty(
398 name
="Retain lower angle",
399 description
="If culet > 0, retains angle of pavilion facets",
403 def draw(self
, context
):
407 box
.prop(self
, "table_w")
408 box
.prop(self
, "crown_h")
409 box
.prop(self
, "girdle_t")
410 box
.prop(self
, "girdle_real")
411 box
.prop(self
, "g_real_smooth")
412 box
.prop(self
, "pavi_d")
413 box
.prop(self
, "bezel_f")
414 box
.prop(self
, "pavi_f")
415 box
.prop(self
, "culet")
416 box
.prop(self
, "keep_lga")
418 if self
.change
== False:
419 # generic transform props
421 box
.prop(self
, 'align', expand
=True)
422 box
.prop(self
, 'location', expand
=True)
423 box
.prop(self
, 'rotation', expand
=True)
425 # call mesh/object generator function with user inputs
426 def execute(self
, context
):
427 # turn off 'Enter Edit Mode'
428 use_enter_edit_mode
= bpy
.context
.preferences
.edit
.use_enter_edit_mode
429 bpy
.context
.preferences
.edit
.use_enter_edit_mode
= False
431 if bpy
.context
.mode
== "OBJECT":
432 if context
.selected_objects
!= [] and context
.active_object
and \
433 (context
.active_object
.data
is not None) and ('Brilliant' in context
.active_object
.data
.keys()) and \
434 (self
.change
== True):
435 obj
= context
.active_object
437 oldmeshname
= obj
.data
.name
438 mesh
= add_mesh_Brilliant(context
, self
.s
, self
.table_w
, self
.crown_h
,
439 self
.girdle_t
, self
.pavi_d
, self
.bezel_f
,
440 self
.pavi_f
, self
.culet
, self
.girdle_real
,
441 self
.keep_lga
, self
.g_real_smooth
444 for material
in oldmesh
.materials
:
445 obj
.data
.materials
.append(material
)
446 bpy
.data
.meshes
.remove(oldmesh
)
447 obj
.data
.name
= oldmeshname
449 obj
= addBrilliant(context
, self
, self
.s
, self
.table_w
, self
.crown_h
,
450 self
.girdle_t
, self
.pavi_d
, self
.bezel_f
,
451 self
.pavi_f
, self
.culet
, self
.girdle_real
,
452 self
.keep_lga
, self
.g_real_smooth
455 obj
.data
["Brilliant"] = True
456 obj
.data
["change"] = False
457 for prm
in BrilliantParameters():
458 obj
.data
[prm
] = getattr(self
, prm
)
460 if bpy
.context
.mode
== "EDIT_MESH":
461 active_object
= context
.active_object
462 name_active_object
= active_object
.name
463 bpy
.ops
.object.mode_set(mode
='OBJECT')
464 obj
= addBrilliant(context
, self
, self
.s
, self
.table_w
, self
.crown_h
,
465 self
.girdle_t
, self
.pavi_d
, self
.bezel_f
,
466 self
.pavi_f
, self
.culet
, self
.girdle_real
,
467 self
.keep_lga
, self
.g_real_smooth
470 active_object
.select_set(True)
471 bpy
.context
.view_layer
.objects
.active
= active_object
472 bpy
.ops
.object.join()
473 context
.active_object
.name
= name_active_object
474 bpy
.ops
.object.mode_set(mode
='EDIT')
476 if use_enter_edit_mode
:
477 bpy
.ops
.object.mode_set(mode
= 'EDIT')
479 # restore pre operator state
480 bpy
.context
.preferences
.edit
.use_enter_edit_mode
= use_enter_edit_mode
484 def BrilliantParameters():
485 BrilliantParameters
= [
498 return BrilliantParameters