1 # SPDX-FileCopyrightText: 2016-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 # ----------------------------------------------------------
6 # Automatic generation of columns
7 # Author: Antonio Vazquez (antonioya)
9 # ----------------------------------------------------------
10 # noinspection PyUnresolvedReferences
12 from math
import cos
, sin
, radians
, atan
, sqrt
13 from bpy
.props
import BoolProperty
, IntProperty
, FloatProperty
, FloatVectorProperty
14 from .achm_tools
import *
17 # ------------------------------------------------------------------
20 # ------------------------------------------------------------------
21 class ARCHIMESH_OT_Column(bpy
.types
.Operator
):
22 bl_idname
= "mesh.archimesh_column"
24 bl_description
= "Columns Generator"
26 bl_options
= {'REGISTER', 'UNDO'}
29 model
: bpy
.props
.EnumProperty(
32 ('1', "Circular", ""),
33 ('2', "Rectangular", ""),
35 description
="Type of column",
37 keep_size
: BoolProperty(
38 name
="Keep radius equal",
39 description
="Keep all radius (top, mid and bottom) to the same size",
43 rad_top
: FloatProperty(
45 min=0.001, max=10, default
=0.15, precision
=3,
46 description
='Radius of the column in the top',
48 rad_mid
: FloatProperty(
50 min=0.001, max=10, default
=0.15, precision
=3,
51 description
='Radius of the column in the middle',
55 min=-1, max=1, default
=0, precision
=3,
56 description
='Middle displacement',
59 rad_bottom
: FloatProperty(
61 min=0.001, max=10, default
=0.15, precision
=3,
62 description
='Radius of the column in the bottom',
65 col_height
: FloatProperty(
67 min=0.001, max=10, default
=2.4, precision
=3,
68 description
='Total height of column, including bases and tops',
70 col_sx
: FloatProperty(
72 min=0.001, max=10, default
=0.30, precision
=3,
73 description
='Column size for x axis',
75 col_sy
: FloatProperty(
77 min=0.001, max=10, default
=0.30, precision
=3,
78 description
='Column size for y axis',
81 cir_base
: BoolProperty(
82 name
="Include circular base",
83 description
="Include a base with circular form",
86 cir_base_r
: FloatProperty(
88 min=0.001, max=10, default
=0.08, precision
=3,
89 description
='Rise up radio of base',
91 cir_base_z
: FloatProperty(
93 min=0.001, max=10, default
=0.05, precision
=3,
94 description
='Size for z axis',
97 cir_top
: BoolProperty(
98 name
="Include circular top",
99 description
="Include a top with circular form",
102 cir_top_r
: FloatProperty(
104 min=0.001, max=10, default
=0.08, precision
=3,
105 description
='Rise up radio of top',
107 cir_top_z
: FloatProperty(
109 min=0.001, max=10, default
=0.05, precision
=3,
110 description
='Size for z axis',
113 box_base
: BoolProperty(
114 name
="Include rectangular base",
115 description
="Include a base with rectangular form",
118 box_base_x
: FloatProperty(
120 min=0.001, max=10, default
=0.40, precision
=3,
121 description
='Size for x axis',
123 box_base_y
: FloatProperty(
125 min=0.001, max=10, default
=0.40, precision
=3,
126 description
='Size for y axis',
128 box_base_z
: FloatProperty(
130 min=0.001, max=10, default
=0.05, precision
=3,
131 description
='Size for z axis',
134 box_top
: BoolProperty(
135 name
="Include rectangular top",
136 description
="Include a top with rectangular form",
139 box_top_x
: FloatProperty(
141 min=0.001, max=10, default
=0.40, precision
=3,
142 description
='Size for x axis',
144 box_top_y
: FloatProperty(
146 min=0.001, max=10, default
=0.40, precision
=3,
147 description
='Size for y axis',
149 box_top_z
: FloatProperty(
151 min=0.001, max=10, default
=0.05, precision
=3,
152 description
='Size for z axis',
155 arc_top
: BoolProperty(
156 name
="Create top arch",
157 description
="Include an arch in the top of the column",
160 arc_radio
: FloatProperty(
162 min=0.001, max=10, default
=1, precision
=1,
163 description
='Radio of the arch',
165 arc_width
: FloatProperty(
167 min=0.01, max=10, default
=0.15, precision
=2,
168 description
='Thickness of the arch wall',
170 arc_gap
: FloatProperty(
172 min=0.01, max=10, default
=0.25, precision
=2,
173 description
='Size of the gap in the arch sides',
176 crt_mat
: BoolProperty(
177 name
="Create default Cycles materials",
178 description
="Create default materials for Cycles render",
181 crt_array
: BoolProperty(
182 name
="Create array of elements",
183 description
="Create a modifier array for all elemnst",
186 array_num_x
: IntProperty(
188 min=0, max=100, default
=3,
189 description
='Number of elements in array',
191 array_space_x
: FloatProperty(
193 min=0.000, max=10, default
=1, precision
=3,
194 description
='Distance between elements (only arc disabled)',
196 array_num_y
: IntProperty(
198 min=0, max=100, default
=0,
199 description
='Number of elements in array',
201 array_space_y
: FloatProperty(
203 min=0.000, max=10, default
=1, precision
=3,
204 description
='Distance between elements (only arc disabled)',
206 array_space_z
: FloatProperty(
208 min=-10, max=10, default
=0, precision
=3,
209 description
='Combined X/Z distance between elements (only arc disabled)',
213 description
="Deform top base with Z displacement", default
=True,
215 array_space_factor
: FloatProperty(
216 name
='Move Y center',
217 min=0.00, max=1, default
=0.0, precision
=3,
218 description
='Move the center of the arch in Y axis. (0 centered)',
221 # -----------------------------------------------------
222 # Draw (create UI interface)
223 # -----------------------------------------------------
224 # noinspection PyUnusedLocal
225 def draw(self
, context
):
227 space
= bpy
.context
.space_data
228 if not space
.local_view
:
229 # Imperial units warning
230 if bpy
.context
.scene
.unit_settings
.system
== "IMPERIAL":
232 row
.label(text
="Warning: Imperial units not supported", icon
='COLOR_RED')
234 box
.prop(self
, 'model')
236 if self
.model
== "1":
237 box
.prop(self
, 'keep_size')
238 box
.prop(self
, 'rad_top')
239 if self
.keep_size
is False:
241 row
.prop(self
, 'rad_mid')
242 row
.prop(self
, 'shift')
243 box
.prop(self
, 'rad_bottom')
246 if self
.model
== "2":
247 box
.prop(self
, 'col_sx')
248 box
.prop(self
, 'col_sy')
250 box
.prop(self
, 'col_height')
253 box
.prop(self
, 'box_base')
254 if self
.box_base
is True:
256 row
.prop(self
, 'box_base_x')
257 row
.prop(self
, 'box_base_y')
258 row
.prop(self
, 'box_base_z')
261 box
.prop(self
, 'box_top')
262 if self
.box_top
is True:
264 row
.prop(self
, 'box_top_x')
265 row
.prop(self
, 'box_top_y')
266 row
.prop(self
, 'box_top_z')
269 box
.prop(self
, 'cir_base')
270 if self
.cir_base
is True:
272 row
.prop(self
, 'cir_base_r')
273 row
.prop(self
, 'cir_base_z')
276 box
.prop(self
, 'cir_top')
277 if self
.cir_top
is True:
279 row
.prop(self
, 'cir_top_r')
280 row
.prop(self
, 'cir_top_z')
283 box
.prop(self
, 'arc_top')
284 if self
.arc_top
is True:
286 row
.prop(self
, 'arc_radio')
287 row
.prop(self
, 'arc_width')
289 row
.prop(self
, 'arc_gap')
290 row
.prop(self
, 'array_space_factor')
293 box
.prop(self
, 'crt_array')
294 if self
.crt_array
is True:
296 row
.prop(self
, 'array_num_x')
297 row
.prop(self
, 'array_num_y')
298 if self
.arc_top
is True:
299 box
.label(text
="Use arch radio and thickness to set distances")
301 if self
.arc_top
is False:
303 row
.prop(self
, 'array_space_x')
304 row
.prop(self
, 'array_space_y')
306 row
.prop(self
, 'array_space_z')
307 row
.prop(self
, 'ramp')
310 if not context
.scene
.render
.engine
in {'CYCLES', 'BLENDER_EEVEE'}:
312 box
.prop(self
, 'crt_mat')
315 row
.label(text
="Warning: Operator does not work in local view mode", icon
='ERROR')
317 # -----------------------------------------------------
319 # -----------------------------------------------------
320 # noinspection PyUnusedLocal
321 def execute(self
, context
):
322 if bpy
.context
.mode
== "OBJECT":
323 create_column_mesh(self
)
326 self
.report({'WARNING'}, "Archimesh: Option only valid in Object mode")
330 # ------------------------------------------------------------------------------
332 # All custom values are passed using self container (self.myvariable)
333 # ------------------------------------------------------------------------------
334 def create_column_mesh(self
):
342 for o
in bpy
.data
.objects
:
343 if o
.select_get() is True:
346 bpy
.ops
.object.select_all(action
='DESELECT')
348 radio_top
= self
.rad_top
349 if self
.keep_size
is True:
350 radio_mid
= radio_top
351 radio_bottom
= radio_top
353 radio_mid
= self
.rad_mid
354 radio_bottom
= self
.rad_bottom
357 height
= self
.col_height
359 height
= height
- self
.box_base_z
361 height
= height
- self
.box_top_z
363 # ------------------------
364 # Create circular column
365 # ------------------------
366 if self
.model
== "1":
367 bpy
.ops
.object.select_all(action
='DESELECT')
368 mycolumn
= create_circular_column(self
, "Column", radio_top
, radio_mid
, radio_bottom
, height
)
369 mycolumn
.select_set(True)
370 bpy
.context
.view_layer
.objects
.active
= mycolumn
373 set_modifier_subsurf(mycolumn
)
374 # ------------------------
375 # Create rectangular column
376 # ------------------------
377 if self
.model
== "2":
378 mycolumn
= create_rectangular_base(self
, "Column", self
.col_sx
, self
.col_sy
, height
)
379 bpy
.ops
.object.select_all(action
='DESELECT')
380 mycolumn
.select_set(True)
381 bpy
.context
.view_layer
.objects
.active
= mycolumn
382 set_normals(mycolumn
)
383 # ------------------------
385 # ------------------------
386 if self
.cir_base
is True:
387 cir_bottom
= create_torus("Column_cir_bottom", radio_bottom
, self
.cir_base_r
, self
.cir_base_z
)
388 bpy
.ops
.object.select_all(action
='DESELECT')
389 cir_bottom
.select_set(True)
390 bpy
.context
.view_layer
.objects
.active
= cir_bottom
391 set_modifier_subsurf(cir_bottom
)
392 set_smooth(cir_bottom
)
393 cir_bottom
.location
.x
= 0.0
394 cir_bottom
.location
.y
= 0.0
395 cir_bottom
.location
.z
= self
.cir_base_z
/ 2
396 cir_bottom
.parent
= mycolumn
398 # ------------------------
400 # ------------------------
401 if self
.box_base
is True:
402 box_bottom
= create_rectangular_base(self
, "Column_box_bottom", self
.box_base_x
, self
.box_base_y
,
404 bpy
.ops
.object.select_all(action
='DESELECT')
405 box_bottom
.select_set(True)
406 bpy
.context
.view_layer
.objects
.active
= box_bottom
407 box_bottom
.parent
= mycolumn
408 set_normals(box_bottom
)
409 box_bottom
.location
.x
= 0.0
410 box_bottom
.location
.y
= 0.0
411 box_bottom
.location
.z
= - self
.box_base_z
413 mycolumn
.location
.z
+= self
.box_base_z
415 # ------------------------
417 # ------------------------
418 if self
.cir_top
is True:
419 cir_top
= create_torus("Column_cir_top", radio_top
, self
.cir_top_r
, self
.cir_top_z
)
420 bpy
.ops
.object.select_all(action
='DESELECT')
421 cir_top
.select_set(True)
422 bpy
.context
.view_layer
.objects
.active
= cir_top
423 set_modifier_subsurf(cir_top
)
425 cir_top
.parent
= mycolumn
426 cir_top
.location
.x
= 0.0
427 cir_top
.location
.y
= 0.0
428 cir_top
.location
.z
= height
- self
.cir_top_z
/ 2
430 # ------------------------
432 # ------------------------
433 if self
.box_top
is True:
434 box_top
= create_rectangular_base(self
, "Column_box_top", self
.box_top_x
, self
.box_top_y
,
435 self
.box_top_z
, self
.ramp
)
436 bpy
.ops
.object.select_all(action
='DESELECT')
437 box_top
.select_set(True)
438 bpy
.context
.view_layer
.objects
.active
= box_top
440 box_top
.parent
= mycolumn
441 box_top
.location
.x
= 0.0
442 box_top
.location
.y
= 0.0
443 box_top
.location
.z
= height
445 # ------------------------
447 # ------------------------
449 myarc
= create_arc("Column_arch", self
.arc_radio
, self
.arc_gap
, self
.arc_width
,
450 self
.array_space_factor
)
451 myarc
.parent
= mycolumn
452 bpy
.ops
.object.select_all(action
='DESELECT')
453 myarc
.select_set(True)
454 bpy
.context
.view_layer
.objects
.active
= myarc
456 set_modifier_mirror(myarc
, "X")
457 myarc
.location
.x
= self
.arc_radio
+ self
.arc_gap
458 myarc
.location
.y
= 0.0
459 if self
.box_top
is True:
460 myarc
.location
.z
= height
+ self
.box_top_z
462 myarc
.location
.z
= height
463 # ------------------------
465 # ------------------------
466 if self
.array_num_x
> 0:
468 distance
= ((self
.arc_radio
+ self
.arc_gap
) * 2)
471 distance
= self
.array_space_x
472 zmove
= self
.array_space_z
475 set_modifier_array(mycolumn
, "X", 0, self
.array_num_x
, True, distance
, zmove
)
477 if self
.box_base
is True:
478 set_modifier_array(box_bottom
, "X", 0, self
.array_num_x
, True, distance
, zmove
)
479 if self
.box_top
is True:
480 set_modifier_array(box_top
, "X", 0, self
.array_num_x
, True, distance
, zmove
)
482 if self
.cir_base
is True:
483 set_modifier_array(cir_bottom
, "X", 0, self
.array_num_x
, True, distance
, zmove
)
484 if self
.cir_top
is True:
485 set_modifier_array(cir_top
, "X", 0, self
.array_num_x
, True, distance
, zmove
)
488 if self
.array_num_x
> 1:
489 set_modifier_array(myarc
, "X", 1, self
.array_num_x
- 1) # one arc minus
490 # ------------------------
492 # ------------------------
493 if self
.array_num_y
> 0:
495 distance
= self
.arc_width
497 distance
= self
.array_space_y
500 set_modifier_array(mycolumn
, "Y", 0, self
.array_num_y
, True, distance
)
502 if self
.box_base
is True:
503 set_modifier_array(box_bottom
, "Y", 0, self
.array_num_y
, True, distance
)
504 if self
.box_top
is True:
505 set_modifier_array(box_top
, "Y", 0, self
.array_num_y
, True, distance
)
507 if self
.cir_base
is True:
508 set_modifier_array(cir_bottom
, "Y", 0, self
.array_num_y
, True, distance
)
509 if self
.cir_top
is True:
510 set_modifier_array(cir_top
, "Y", 0, self
.array_num_y
, True, distance
)
513 if self
.array_num_y
> 1:
514 set_modifier_array(myarc
, "Y", 1, self
.array_num_y
- 1) # one less
516 # ------------------------
518 # ------------------------
519 if self
.crt_mat
and bpy
.context
.scene
.render
.engine
in {'CYCLES', 'BLENDER_EEVEE'}:
521 mat
= create_diffuse_material("Column_material", False, 0.748, 0.734, 0.392, 0.573, 0.581, 0.318)
522 set_material(mycolumn
, mat
)
524 if self
.box_base
is True or self
.box_top
is True:
525 mat
= create_diffuse_material("Column_rect", False, 0.56, 0.56, 0.56, 0.56, 0.56, 0.56)
526 if self
.box_base
is True:
527 set_material(box_bottom
, mat
)
528 if self
.box_top
is True:
529 set_material(box_top
, mat
)
531 if self
.cir_base
is True or self
.cir_top
is True:
532 mat
= create_diffuse_material("Column_cir", False, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65)
533 if self
.cir_base
is True:
534 set_material(cir_bottom
, mat
)
535 if self
.cir_top
is True:
536 set_material(cir_top
, mat
)
539 mat
= create_diffuse_material("Column_arch", False, 0.8, 0.8, 0.8)
540 set_material(myarc
, mat
)
542 bpy
.ops
.object.select_all(action
='DESELECT')
543 mycolumn
.select_set(True)
544 bpy
.context
.view_layer
.objects
.active
= mycolumn
549 # ------------------------------------------------------------------------------
551 # ------------------------------------------------------------------------------
552 def create_circular_column(self
, objname
, radio_top
, radio_mid
, radio_bottom
, height
):
555 pies
= [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330] # circle
559 x
= cos(radians(pie
)) * radio_bottom
560 y
= sin(radians(pie
)) * radio_bottom
561 mypoint
= [(x
, y
, 0.0)]
562 myvertex
.extend(mypoint
)
565 x
= cos(radians(pie
)) * radio_mid
566 y
= sin(radians(pie
)) * radio_mid
567 mypoint
= [(x
, y
, (height
/ 2) + ((height
/ 2) * self
.shift
))]
568 myvertex
.extend(mypoint
)
571 x
= cos(radians(pie
)) * radio_top
572 y
= sin(radians(pie
)) * radio_top
573 mypoint
= [(x
, y
, height
)]
574 myvertex
.extend(mypoint
)
575 # -------------------------------------
577 # -------------------------------------
579 for n
in range(0, len(pies
) * 2):
583 myface
= [(n
, n
- len(pies
) + 1, n
+ 1, n
+ len(pies
))]
584 myfaces
.extend(myface
)
586 myface
= [(n
, n
+ 1, n
+ len(pies
) + 1, n
+ len(pies
))]
587 myfaces
.extend(myface
)
589 mesh
= bpy
.data
.meshes
.new(objname
)
590 myobject
= bpy
.data
.objects
.new(objname
, mesh
)
592 myobject
.location
= bpy
.context
.scene
.cursor
.location
593 bpy
.context
.collection
.objects
.link(myobject
)
595 mesh
.from_pydata(myvertex
, [], myfaces
)
596 mesh
.update(calc_edges
=True)
601 # ------------------------------------------------------------------------------
603 # ------------------------------------------------------------------------------
604 def create_torus(objname
, radio_inside
, radio_outside
, height
):
607 pies
= [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330] # circle
608 segments
= [80, 60, 30, 0, 330, 300, 280] # section
610 radio_mid
= radio_outside
+ radio_inside
- (height
/ 2)
611 # Add internal circles Top
613 x
= cos(radians(pie
)) * radio_inside
614 y
= sin(radians(pie
)) * radio_inside
615 mypoint
= [(x
, y
, height
/ 2)]
616 myvertex
.extend(mypoint
)
617 # Add external circles Top
619 x
= cos(radians(pie
)) * radio_mid
620 y
= sin(radians(pie
)) * radio_mid
621 mypoint
= [(x
, y
, height
/ 2)]
622 myvertex
.extend(mypoint
)
623 # Add Intermediate lines
624 for segment
in segments
:
626 radio_externo
= radio_mid
+ (height
* cos(radians(segment
)))
627 x
= cos(radians(pie
)) * radio_externo
628 y
= sin(radians(pie
)) * radio_externo
629 z
= sin(radians(segment
)) * (height
/ 2)
631 mypoint
= [(x
, y
, z
)]
632 myvertex
.extend(mypoint
)
634 # Add internal circles Bottom
636 x
= cos(radians(pie
)) * radio_inside
637 y
= sin(radians(pie
)) * radio_inside
638 mypoint
= [(x
, y
, height
/ 2 * -1)]
639 myvertex
.extend(mypoint
)
640 # Add external circles bottom
642 x
= cos(radians(pie
)) * radio_mid
643 y
= sin(radians(pie
)) * radio_mid
644 mypoint
= [(x
, y
, height
/ 2 * -1)]
645 myvertex
.extend(mypoint
)
647 # -------------------------------------
649 # -------------------------------------
651 for n
in range(0, len(pies
) * len(segments
) + (len(pies
) * 2)):
655 myface
= [(n
, n
- len(pies
) + 1, n
+ 1, n
+ len(pies
))]
656 myfaces
.extend(myface
)
658 myface
= [(n
, n
+ 1, n
+ len(pies
) + 1, n
+ len(pies
))]
659 myfaces
.extend(myface
)
661 mesh
= bpy
.data
.meshes
.new(objname
)
662 myobject
= bpy
.data
.objects
.new(objname
, mesh
)
664 myobject
.location
= bpy
.context
.scene
.cursor
.location
665 bpy
.context
.collection
.objects
.link(myobject
)
667 mesh
.from_pydata(myvertex
, [], myfaces
)
668 mesh
.update(calc_edges
=True)
673 # ------------------------------------------------------------------------------
674 # Create rectangular base
675 # ------------------------------------------------------------------------------
676 def create_rectangular_base(self
, objname
, x
, y
, z
, ramp
=False):
677 elements
= self
.array_num_x
- 1
678 height
= self
.array_space_z
* elements
679 width
= self
.array_space_x
* elements
681 angle
= atan(height
/ width
)
685 radio
= sqrt((x
* x
) + (self
.array_space_z
* self
.array_space_z
))
686 disp
= radio
* sin(angle
)
688 if ramp
is False or self
.arc_top
:
692 if self
.array_space_z
>= 0:
699 myvertex
= [(-x
/ 2, -y
/ 2, 0.0),
700 (-x
/ 2, y
/ 2, 0.0),
702 (x
/ 2, -y
/ 2, 0.0),
703 (-x
/ 2, -y
/ 2, z
+ addz1
),
704 (-x
/ 2, y
/ 2, z
+ addz1
),
705 (x
/ 2, y
/ 2, z
+ addz2
),
706 (x
/ 2, -y
/ 2, z
+ addz2
)]
708 myfaces
= [(0, 1, 2, 3), (0, 1, 5, 4), (1, 2, 6, 5), (2, 6, 7, 3), (5, 6, 7, 4), (0, 4, 7, 3)]
710 mesh
= bpy
.data
.meshes
.new(objname
)
711 myobject
= bpy
.data
.objects
.new(objname
, mesh
)
713 myobject
.location
= bpy
.context
.scene
.cursor
.location
714 bpy
.context
.collection
.objects
.link(myobject
)
716 mesh
.from_pydata(myvertex
, [], myfaces
)
717 mesh
.update(calc_edges
=True)
722 # ------------------------------------------------------------------------------
724 # ------------------------------------------------------------------------------
725 def create_arc(objname
, radio
, gap
, thickness
, center
):
728 half
= (thickness
/ 2)
731 listdata
= [half
+ move
, -half
+ move
]
732 for pos_y
in listdata
:
733 # --------------------------------
735 # --------------------------------
736 myvertex
.extend([(-radio
- gap
, pos_y
, radio
+ radio
/ 10)])
738 angle
= 13 * (180 / 16)
739 for i
in range(1, 4):
740 z
= sin(radians(angle
)) * radio
741 mypoint
= [(-radio
- gap
, pos_y
, z
)]
742 myvertex
.extend(mypoint
)
745 myvertex
.extend([(-radio
- gap
, pos_y
, 0.0)])
746 # --------------------------------
748 # --------------------------------
750 for i
in range(0, 9):
751 x
= cos(radians(angle
)) * radio
752 z
= sin(radians(angle
)) * radio
753 mypoint
= [(x
, pos_y
, z
)]
754 myvertex
.extend(mypoint
)
757 # --------------------------------
758 # vertical cut points
759 # --------------------------------
760 angle
= 8 * (180 / 16)
761 for i
in range(1, 5):
762 x
= cos(radians(angle
)) * radio
763 mypoint
= [(x
, pos_y
, radio
+ radio
/ 10)]
764 myvertex
.extend(mypoint
)
768 myfaces
= [(23, 24, 21, 22), (24, 25, 20, 21), (25, 26, 19, 20), (27, 18, 19, 26), (18, 27, 28, 35),
769 (28, 29, 34, 35), (29, 30, 33, 34), (30, 31, 32, 33), (12, 13, 31, 30), (29, 11, 12, 30),
770 (11, 29, 28, 10), (10, 28, 27, 9), (9, 27, 26, 8), (25, 7, 8, 26), (24, 6, 7, 25),
771 (23, 5, 6, 24), (22, 4, 5, 23), (5, 4, 3, 6), (6, 3, 2, 7), (7, 2, 1, 8),
772 (8, 1, 0, 9), (9, 0, 17, 10), (10, 17, 16, 11), (11, 16, 15, 12), (14, 13, 12, 15),
773 (21, 3, 4, 22), (20, 2, 3, 21), (19, 1, 2, 20), (1, 19, 18, 0), (0, 18, 35, 17),
774 (17, 35, 34, 16), (33, 15, 16, 34), (32, 14, 15, 33)]
776 mesh
= bpy
.data
.meshes
.new(objname
)
777 myobject
= bpy
.data
.objects
.new(objname
, mesh
)
779 myobject
.location
= bpy
.context
.scene
.cursor
.location
780 bpy
.context
.collection
.objects
.link(myobject
)
782 mesh
.from_pydata(myvertex
, [], myfaces
)
783 mesh
.update(calc_edges
=True)