Sun position: store previous settings for HDRI sun syncing operator
[blender-addons.git] / archimesh / achm_lamp_maker.py
bloba5c6621b81a5b6c1924ebb57d387fd4ebb067dda
1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
19 # <pep8 compliant>
21 # ----------------------------------------------------------
22 # Automatic generation of lamps
23 # Author: Antonio Vazquez (antonioya)
25 # ----------------------------------------------------------
26 import bpy
27 from math import cos, sin, radians
28 from copy import copy
29 from bpy.types import Operator
30 from bpy.props import EnumProperty, FloatProperty, IntProperty, BoolProperty, FloatVectorProperty
31 from .achm_tools import *
34 # ------------------------------------------------------
35 # set predefined designs
37 # self: self container
38 # ------------------------------------------------------
39 def set_preset(self):
40 # -----------------------
41 # Sphere
42 # -----------------------
43 if self.preset == "1":
44 self.base_height = 0.22
45 self.base_segments = 16
46 self.base_rings = 6
47 self.smooth = True
48 self.subdivide = True
49 self.br01 = 0.05
50 self.br02 = 0.07
51 self.br03 = 0.11
52 self.br04 = 0.11
53 self.br05 = 0.07
54 self.br06 = 0.03
56 self.bz01 = 0
57 self.bz02 = -1
58 self.bz03 = -0.456
59 self.bz04 = 0.089
60 self.bz05 = -0.038
61 self.bz06 = -0.165
62 # -----------------------
63 # Pear
64 # -----------------------
65 if self.preset == "2":
66 self.base_height = 0.20
67 self.base_segments = 16
68 self.base_rings = 6
69 self.smooth = True
70 self.subdivide = True
71 self.br01 = 0.056
72 self.br02 = 0.062
73 self.br03 = 0.072
74 self.br04 = 0.090
75 self.br05 = 0.074
76 self.br06 = 0.03
78 self.bz01 = 0
79 self.bz02 = 0
80 self.bz03 = 0
81 self.bz04 = 0
82 self.bz05 = 0
83 self.bz06 = 0
84 # -----------------------
85 # Vase
86 # -----------------------
87 if self.preset == "3":
88 self.base_height = 0.20
89 self.base_segments = 8
90 self.base_rings = 6
91 self.smooth = True
92 self.subdivide = True
93 self.br01 = 0.05
94 self.br02 = 0.11
95 self.br03 = 0.15
96 self.br04 = 0.07
97 self.br05 = 0.05
98 self.br06 = 0.03
100 self.bz01 = 0
101 self.bz02 = 0
102 self.bz03 = 0
103 self.bz04 = 0
104 self.bz05 = 0
105 self.bz06 = 0
106 # -----------------------
107 # Rectangular
108 # -----------------------
109 if self.preset == "4":
110 self.base_height = 0.15
111 self.base_segments = 4
112 self.base_rings = 5
113 self.smooth = False
114 self.subdivide = False
115 self.br01 = 0.08
116 self.br02 = 0.08
117 self.br03 = 0.08
118 self.br04 = 0.08
119 self.br05 = 0.03
121 self.bz01 = 0
122 self.bz02 = 0
123 self.bz03 = 0
124 self.bz04 = 0.25
125 self.bz05 = 0
128 # ------------------------------------------------------------------
129 # Define UI class
130 # Lamps
131 # ------------------------------------------------------------------
132 class ARCHIMESH_PT_Lamp(Operator):
133 bl_idname = "mesh.archimesh_light"
134 bl_label = "Lamp"
135 bl_description = "Lamp Generator"
136 bl_category = 'View'
137 bl_options = {'REGISTER', 'UNDO'}
138 # preset
139 preset: EnumProperty(
140 items=(
141 ('0', "None", ""),
142 ('1', "Sphere", ""),
143 ('2', "Pear", ""),
144 ('3', "Vase", ""),
145 ('4', "Rectangular", ""),
147 name="Predefined",
148 description="Apply predefined design",
150 oldpreset: EnumProperty(
151 items=(
152 ('0', "None", ""),
153 ('1', "Sphere", ""),
154 ('2', "Pear", ""),
155 ('3', "Vase", ""),
156 ('4', "Rectangular", ""),
158 name="Predefined",
159 description="Apply predefined design",
162 base_height: FloatProperty(
163 name='Height',
164 min=0.01, max=10, default=0.20, precision=3,
165 description='lamp base height',
167 base_segments: IntProperty(
168 name='Segments',
169 min=3, max=128, default=16,
170 description='Number of segments (vertical)',
172 base_rings: IntProperty(
173 name='Rings',
174 min=2, max=12, default=6,
175 description='Number of rings (horizontal)',
177 holder: FloatProperty(
178 name='Lampholder',
179 min=0.001, max=10, default=0.02, precision=3,
180 description='Lampholder height',
182 smooth: BoolProperty(
183 name="Smooth",
184 description="Use smooth shader",
185 default=True,
187 subdivide: BoolProperty(
188 name="Subdivide",
189 description="Add subdivision modifier",
190 default=True,
193 bz01: FloatProperty(name='S1', min=-1, max=1, default=0, precision=3, description='Z shift factor')
194 bz02: FloatProperty(name='S2', min=-1, max=1, default=0, precision=3, description='Z shift factor')
195 bz03: FloatProperty(name='S3', min=-1, max=1, default=0, precision=3, description='Z shift factor')
196 bz04: FloatProperty(name='S4', min=-1, max=1, default=0, precision=3, description='Z shift factor')
197 bz05: FloatProperty(name='S5', min=-1, max=1, default=0, precision=3, description='Z shift factor')
198 bz06: FloatProperty(name='S6', min=-1, max=1, default=0, precision=3, description='Z shift factor')
199 bz07: FloatProperty(name='S7', min=-1, max=1, default=0, precision=3, description='Z shift factor')
200 bz08: FloatProperty(name='S8', min=-1, max=1, default=0, precision=3, description='Z shift factor')
201 bz09: FloatProperty(name='S9', min=-1, max=1, default=0, precision=3, description='Z shift factor')
202 bz10: FloatProperty(name='S10', min=-1, max=1, default=0, precision=3, description='Z shift factor')
203 bz11: FloatProperty(name='S11', min=-1, max=1, default=0, precision=3, description='Z shift factor')
204 bz12: FloatProperty(name='S12', min=-1, max=1, default=0, precision=3, description='Z shift factor')
206 br01: FloatProperty(name='R1', min=0.001, max=10, default=0.06, precision=3, description='Ring radio')
207 br02: FloatProperty(name='R2', min=0.001, max=10, default=0.08, precision=3, description='Ring radio')
208 br03: FloatProperty(name='R3', min=0.001, max=10, default=0.09, precision=3, description='Ring radio')
209 br04: FloatProperty(name='R4', min=0.001, max=10, default=0.08, precision=3, description='Ring radio')
210 br05: FloatProperty(name='R5', min=0.001, max=10, default=0.06, precision=3, description='Ring radio')
211 br06: FloatProperty(name='R6', min=0.001, max=10, default=0.03, precision=3, description='Ring radio')
212 br07: FloatProperty(name='R7', min=0.001, max=10, default=0.10, precision=3, description='Ring radio')
213 br08: FloatProperty(name='R8', min=0.001, max=10, default=0.10, precision=3, description='Ring radio')
214 br09: FloatProperty(name='R9', min=0.001, max=10, default=0.10, precision=3, description='Ring radio')
215 br10: FloatProperty(name='R10', min=0.001, max=10, default=0.10, precision=3, description='Ring radio')
216 br11: FloatProperty(name='R11', min=0.001, max=10, default=0.10, precision=3, description='Ring radio')
217 br12: FloatProperty(name='R12', min=0.001, max=10, default=0.10, precision=3, description='Ring radio')
219 top_height: FloatProperty(
220 name='Height', min=0.01, max=10,
221 default=0.20, precision=3,
222 description='lampshade height',
224 top_segments: IntProperty(
225 name='Segments', min=3, max=128,
226 default=32,
227 description='Number of segments (vertical)',
229 tr01: FloatProperty(
230 name='R1', min=0.001, max=10,
231 default=0.16, precision=3,
232 description='lampshade bottom radio',
234 tr02: FloatProperty(name='R2', min=0.001, max=10,
235 default=0.08, precision=3,
236 description='lampshade top radio')
237 pleats: BoolProperty(
238 name="Pleats", description="Create pleats in the lampshade",
239 default=False,
241 tr03: FloatProperty(
242 name='R3', min=0.001, max=1,
243 default=0.01, precision=3, description='Pleats size',
245 energy: FloatProperty(
246 name='Light', min=0.00, max=1000,
247 default=15, precision=3,
248 description='Light intensity',
250 opacity: FloatProperty(
251 name='Translucency', min=0.00, max=1,
252 default=0.3, precision=3,
253 description='Lampshade translucency factor (1 completely translucent)',
256 # Materials
257 crt_mat: BoolProperty(
258 name="Create default Cycles materials",
259 description="Create default materials for Cycles render",
260 default=True,
262 objcol: FloatVectorProperty(
263 name="Color",
264 description="Color for material",
265 default=(1.0, 1.0, 1.0, 1.0),
266 min=0.1, max=1,
267 subtype='COLOR',
268 size=4,
271 # -----------------------------------------------------
272 # Draw (create UI interface)
273 # -----------------------------------------------------
274 # noinspection PyUnusedLocal
275 def draw(self, context):
276 layout = self.layout
277 space = bpy.context.space_data
278 if not space.local_view:
279 # Imperial units warning
280 if bpy.context.scene.unit_settings.system == "IMPERIAL":
281 row = layout.row()
282 row.label(text="Warning: Imperial units not supported", icon='COLOR_RED')
284 box = layout.box()
285 box.label(text="Lamp base")
286 row = box.row()
287 row.prop(self, 'preset')
288 row = box.row()
289 row.prop(self, 'base_height')
290 row.prop(self, 'base_segments')
291 row.prop(self, 'base_rings')
292 row = box.row()
293 row.prop(self, 'smooth')
294 row.prop(self, 'subdivide')
295 row = box.row()
296 row.prop(self, 'holder')
298 if self.base_rings >= 1:
299 row = box.row()
300 row.prop(self, 'br01')
301 row.prop(self, 'bz01', slider=True)
302 if self.base_rings >= 2:
303 row = box.row()
304 row.prop(self, 'br02')
305 row.prop(self, 'bz02', slider=True)
306 if self.base_rings >= 3:
307 row = box.row()
308 row.prop(self, 'br03')
309 row.prop(self, 'bz03', slider=True)
311 if self.base_rings >= 4:
312 row = box.row()
313 row.prop(self, 'br04')
314 row.prop(self, 'bz04', slider=True)
315 if self.base_rings >= 5:
316 row = box.row()
317 row.prop(self, 'br05')
318 row.prop(self, 'bz05', slider=True)
319 if self.base_rings >= 6:
320 row = box.row()
321 row.prop(self, 'br06')
322 row.prop(self, 'bz06', slider=True)
324 if self.base_rings >= 7:
325 row = box.row()
326 row.prop(self, 'br07')
327 row.prop(self, 'bz07', slider=True)
328 if self.base_rings >= 8:
329 row = box.row()
330 row.prop(self, 'br08')
331 row.prop(self, 'bz08', slider=True)
332 if self.base_rings >= 9:
333 row = box.row()
334 row.prop(self, 'br09')
335 row.prop(self, 'bz09', slider=True)
337 if self.base_rings >= 10:
338 row = box.row()
339 row.prop(self, 'br10')
340 row.prop(self, 'bz10', slider=True)
341 if self.base_rings >= 11:
342 row = box.row()
343 row.prop(self, 'br11')
344 row.prop(self, 'bz11', slider=True)
345 if self.base_rings >= 12:
346 row = box.row()
347 row.prop(self, 'br12')
348 row.prop(self, 'bz12', slider=True)
350 box = layout.box()
351 box.label(text="Lampshade")
352 row = box.row()
353 row.prop(self, 'top_height')
354 row.prop(self, 'top_segments')
355 row = box.row()
356 row.prop(self, 'tr01')
357 row.prop(self, 'tr02')
358 row = box.row()
359 row.prop(self, 'energy')
360 row.prop(self, 'opacity', slider=True)
361 row = box.row()
362 row.prop(self, 'pleats')
363 if self.pleats:
364 row.prop(self, 'tr03')
366 box = layout.box()
367 if not context.scene.render.engine in {'CYCLES', 'BLENDER_EEVEE'}:
368 box.enabled = False
369 box.prop(self, 'crt_mat')
370 if self.crt_mat:
371 row = box.row()
372 row.prop(self, 'objcol')
373 else:
374 row = layout.row()
375 row.label(text="Warning: Operator does not work in local view mode", icon='ERROR')
377 # -----------------------------------------------------
378 # Execute
379 # -----------------------------------------------------
380 # noinspection PyUnusedLocal
381 def execute(self, context):
382 if bpy.context.mode == "OBJECT":
383 if self.oldpreset != self.preset:
384 set_preset(self)
385 self.oldpreset = self.preset
387 # Create lamp
388 create_light_mesh(self)
389 return {'FINISHED'}
390 else:
391 self.report({'WARNING'}, "Archimesh: Option only valid in Object mode")
392 return {'CANCELLED'}
395 # ------------------------------------------------------------------------------
396 # Generate mesh data
397 # All custom values are passed using self container (self.myvariable)
398 # ------------------------------------------------------------------------------
399 def create_light_mesh(self):
400 # deactivate others
401 for o in bpy.data.objects:
402 if o.select_get() is True:
403 o.select_set(False)
404 bpy.ops.object.select_all(action='DESELECT')
405 generate_light(self)
407 return
410 # ------------------------------------------------------------------------------
411 # Generate lamps
412 # All custom values are passed using self container (self.myvariable)
413 # ------------------------------------------------------------------------------
414 def generate_light(self):
415 location = bpy.context.scene.cursor.location
416 myloc = copy(location) # copy location to keep 3D cursor position
417 # ---------------------
418 # Lamp base
419 # ---------------------
420 mydata = create_light_base("Lamp_base", self.base_height,
421 myloc.x, myloc.y, myloc.z,
422 self.base_segments, self.base_rings,
423 [self.br01, self.br02, self.br03, self.br04, self.br05, self.br06,
424 self.br07, self.br08, self.br09, self.br10, self.br11, self.br12],
425 (self.bz01, self.bz02, self.bz03, self.bz04, self.bz05, self.bz06,
426 self.bz07, self.bz08, self.bz09, self.bz10, self.bz11, self.bz12),
427 self.subdivide,
428 self.crt_mat, self.objcol)
429 mybase = mydata[0]
430 posz = mydata[1]
431 # refine
432 remove_doubles(mybase)
433 set_normals(mybase)
434 # Smooth
435 if self.smooth:
436 set_smooth(mybase)
437 if self.subdivide:
438 set_modifier_subsurf(mybase)
439 # ---------------------
440 # Lampholder
441 # ---------------------
442 myholder = create_lightholder("Lampholder", self.holder,
443 myloc.x, myloc.y, myloc.z,
444 self.crt_mat)
445 # refine
446 remove_doubles(myholder)
447 set_normals(myholder)
448 set_smooth(myholder)
450 myholder.parent = mybase
451 myholder.location.x = 0
452 myholder.location.y = 0
453 myholder.location.z = posz
454 # ---------------------
455 # Lamp strings
456 # ---------------------
457 mystrings = create_lightholder_strings("Lampstrings", self.holder,
458 myloc.x, myloc.y, myloc.z,
459 self.tr02,
460 self.top_height,
461 self.crt_mat)
462 # refine
463 remove_doubles(mystrings)
464 set_normals(mystrings)
466 mystrings.parent = myholder
467 mystrings.location.x = 0
468 mystrings.location.y = 0
469 mystrings.location.z = 0.03
470 # ---------------------
471 # Lampshade
472 # ---------------------
473 mytop = create_lightshade("Lampshade", self.top_height,
474 myloc.x, myloc.y, myloc.z,
475 self.top_segments,
476 self.tr01, self.tr02,
477 self.pleats, self.tr03,
478 self.opacity,
479 self.crt_mat)
480 # refine
481 remove_doubles(mytop)
482 set_normals(mytop)
483 if self.pleats is False:
484 set_smooth(mytop)
486 mytop.parent = mybase
487 mytop.location.x = 0
488 mytop.location.y = 0
489 mytop.location.z = posz + self.holder
490 # ---------------------
491 # Light bulb
492 # ---------------------
493 radbulb = 0.02
494 bpy.ops.mesh.primitive_uv_sphere_add(segments=16, radius=radbulb)
495 mybulb = bpy.data.objects[bpy.context.active_object.name]
496 mybulb.name = "Lamp_Bulb"
497 mybulb.parent = myholder
498 mybulb.location = (0, 0, radbulb + self.holder + 0.04)
499 if self.crt_mat and bpy.context.scene.render.engine in {'CYCLES', 'BLENDER_EEVEE'}:
500 mat = create_emission_material(mybulb.name, True, 0.8, 0.8, 0.8, self.energy)
501 set_material(mybulb, mat)
503 # deactivate others
504 for o in bpy.data.objects:
505 if o.select_get() is True:
506 o.select_set(False)
508 mybase.select_set(True)
509 bpy.context.view_layer.objects.active = mybase
511 return
514 # ------------------------------------------------------------------------------
515 # Create lamp base
517 # objName: Name for the new object
518 # height: Size in Z axis
519 # pX: position X axis
520 # pY: position Y axis
521 # pZ: position Z axis
522 # segments: number of segments
523 # rings: number of rings
524 # radios: ring radios
525 # ratios: Z shift ratios
526 # subdivide: Subdivision flag
527 # mat: Flag for creating materials
528 # objcol: Color
529 # ------------------------------------------------------------------------------
530 def create_light_base(objname, height, px, py, pz, segments, rings, radios, ratios, subdivide, mat, objcol):
531 # Calculate heights
532 h = height / (rings - 1)
533 listheight = []
534 z = 0
535 for f in range(0, rings):
536 listheight.extend([z + (z * ratios[f])])
537 z += h
539 mydata = create_cylinder_data(segments, listheight,
540 radios,
541 True, True, False, 0, subdivide)
542 myvertex = mydata[0]
543 myfaces = mydata[1]
545 mymesh = bpy.data.meshes.new(objname)
546 mycylinder = bpy.data.objects.new(objname, mymesh)
547 bpy.context.collection.objects.link(mycylinder)
549 mymesh.from_pydata(myvertex, [], myfaces)
550 mymesh.update(calc_edges=True)
551 # Position
552 mycylinder.location.x = px
553 mycylinder.location.y = py
554 mycylinder.location.z = pz
555 # Materials
556 if mat and bpy.context.scene.render.engine in {'CYCLES', 'BLENDER_EEVEE'}:
557 rgb = objcol
558 mymat = create_diffuse_material(mycylinder.name + "_material", True, rgb[0], rgb[1], rgb[2], rgb[0], rgb[1],
559 rgb[2], 0.1)
560 set_material(mycylinder, mymat)
562 return mycylinder, listheight[len(listheight) - 1]
565 # ------------------------------------------------------------------------------
566 # Create lampholder
568 # objName: Name for the new object
569 # height: Size in Z axis
570 # pX: position X axis
571 # pY: position Y axis
572 # pZ: position Z axis
573 # mat: Flag for creating materials
574 # ------------------------------------------------------------------------------
575 def create_lightholder(objname, height, px, py, pz, mat):
576 mydata = create_cylinder_data(16, [0, height, height + 0.005, height + 0.008, height + 0.05],
577 [0.005, 0.005, 0.010, 0.018, 0.018],
578 False, False, False, 0, False)
579 myvertex = mydata[0]
580 myfaces = mydata[1]
582 mymesh = bpy.data.meshes.new(objname)
583 mycylinder = bpy.data.objects.new(objname, mymesh)
584 bpy.context.collection.objects.link(mycylinder)
586 mymesh.from_pydata(myvertex, [], myfaces)
587 mymesh.update(calc_edges=True)
588 # Position
589 mycylinder.location.x = px
590 mycylinder.location.y = py
591 mycylinder.location.z = pz
593 # Materials
594 if mat and bpy.context.scene.render.engine in {'CYCLES', 'BLENDER_EEVEE'}:
595 mat = create_diffuse_material(mycylinder.name + "_material", True, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.1)
596 set_material(mycylinder, mat)
598 return mycylinder
601 # ------------------------------------------------------------------------------
602 # Create lampholder strings
604 # objName: Name for the new object
605 # height: Size in Z axis
606 # pX: position X axis
607 # pY: position Y axis
608 # pZ: position Z axis
609 # radio: radio of lampshade
610 # shadeh: height of lampshader
611 # mat: Flag for creating materials
612 # ------------------------------------------------------------------------------
613 def create_lightholder_strings(objname, height, px, py, pz, radio, shadeh, mat):
614 mydata = create_cylinder_data(32, [height + 0.005, height + 0.005, height + 0.006, height + 0.006],
615 [0.018, 0.025, 0.025, 0.018],
616 False, False, False, 0, False)
617 myvertex = mydata[0]
618 myfaces = mydata[1]
620 mymesh = bpy.data.meshes.new(objname)
621 mycylinder = bpy.data.objects.new(objname, mymesh)
622 bpy.context.collection.objects.link(mycylinder)
624 mymesh.from_pydata(myvertex, [], myfaces)
625 mymesh.update(calc_edges=True)
626 # Position
627 mycylinder.location.x = px
628 mycylinder.location.y = py
629 mycylinder.location.z = pz
630 # Box1
631 box1 = create_box_segments("Lamp_B1", shadeh - 0.036, radio - 0.023)
632 box1.parent = mycylinder
633 box1.location = (0.021, 0, height + 0.004)
634 # Box2
635 box2 = create_box_segments("Lamp_B2", shadeh - 0.036, -radio + 0.023)
636 box2.parent = mycylinder
637 box2.location = (-0.021, 0, height + 0.004)
639 # Materials
640 if mat and bpy.context.scene.render.engine in {'CYCLES', 'BLENDER_EEVEE'}:
641 mat = create_diffuse_material(mycylinder.name + "_material", True, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.1)
642 set_material(mycylinder, mat)
643 set_material(box1, mat)
644 set_material(box2, mat)
646 return mycylinder
649 # ------------------------------------------------------------------------------
650 # Create lampshade
652 # objName: Name for the new object
653 # height: Size in Z axis
654 # pX: position X axis
655 # pY: position Y axis
656 # pZ: position Z axis
657 # segments: number of segments
658 # radio1: ring radio 1
659 # radio2: ring radio 2
660 # pleats: flag for pleats
661 # pleatsize: difference in radios (less)
662 # opacity: opacity factor
663 # mat: Flag for creating materials
664 # ------------------------------------------------------------------------------
665 def create_lightshade(objname, height, px, py, pz, segments, radio1, radio2, pleats, pleatsize, opacity, mat):
666 gap = 0.002
667 radios = [radio1 - gap, radio1 - gap, radio1, radio2, radio2 - gap, radio2 - gap]
668 heights = [gap * 2, 0, 0, height, height, height - (gap * 2)]
669 mydata = create_cylinder_data(segments, heights,
670 radios,
671 False, False, pleats, pleatsize, False)
672 myvertex = mydata[0]
673 myfaces = mydata[1]
675 mymesh = bpy.data.meshes.new(objname)
676 mycylinder = bpy.data.objects.new(objname, mymesh)
677 bpy.context.collection.objects.link(mycylinder)
679 mymesh.from_pydata(myvertex, [], myfaces)
680 mymesh.update(calc_edges=True)
681 # Position
682 mycylinder.location.x = px
683 mycylinder.location.y = py
684 mycylinder.location.z = pz
685 # materials
686 if mat and bpy.context.scene.render.engine in {'CYCLES', 'BLENDER_EEVEE'}:
687 mymat = create_translucent_material(mycylinder.name + "_material", True, 0.8, 0.65, 0.45, 0.8, 0.65, 0.45,
688 opacity)
689 set_material(mycylinder, mymat)
691 return mycylinder
694 # ------------------------------------------------------------------------------
695 # Create box segments
697 # objName: Name for the new object
698 # height: Size in Z axis
699 # shift: Shift movement
700 # ------------------------------------------------------------------------------
701 def create_box_segments(objname, height, shift):
702 gap = 0.001
703 myvertex = [(0, 0, 0), (0, gap, 0), (gap, gap, 0), (gap, 0, 0),
704 (shift, 0, height),
705 (shift, gap, height),
706 (shift + gap, gap, height),
707 (shift + gap, 0, height)]
708 myfaces = [(6, 5, 1, 2), (7, 6, 2, 3), (4, 7, 3, 0), (1, 5, 4, 0)]
710 mymesh = bpy.data.meshes.new(objname)
711 mysegment = bpy.data.objects.new(objname, mymesh)
712 bpy.context.collection.objects.link(mysegment)
714 mymesh.from_pydata(myvertex, [], myfaces)
715 mymesh.update(calc_edges=True)
716 # Position
717 mysegment.location.x = 0
718 mysegment.location.y = 0
719 mysegment.location.z = 0
721 return mysegment
724 # ------------------------------------------------------------------------------
725 # Create cylinders data
727 # segments: Number of pies
728 # listHeight: list of heights
729 # listRadio: list of radios
730 # top: top face flag
731 # bottom: bottom face flag
732 # pleats: flag for pleats
733 # pleatsize: difference in radios (less)
734 # subdiv: fix subdivision problem
735 # ------------------------------------------------------------------------------
736 def create_cylinder_data(segments, listheight, listradio, bottom, top, pleats, pleatsize, subdiv):
737 myvertex = []
738 myfaces = []
739 if subdiv:
740 # Add at element 0 to fix subdivision problems
741 listheight.insert(0, listheight[0] + 0.001)
742 listradio.insert(0, listradio[0])
743 # Add at last element to fix subdivision problems
744 e = len(listheight) - 1
745 listheight.insert(e, listheight[e] + 0.001)
746 listradio.insert(e, listradio[e])
747 # -------------------------------------
748 # Vertices
749 # -------------------------------------
750 idx = 0
751 rp = 0
752 for z in listheight:
753 seg = 0
754 for i in range(segments):
755 x = cos(radians(seg)) * (listradio[idx] + rp)
756 y = sin(radians(seg)) * (listradio[idx] + rp)
757 mypoint = [(x, y, z)]
758 myvertex.extend(mypoint)
759 seg += 360 / segments
760 # pleats
761 if pleats is True and rp == 0:
762 rp = -pleatsize
763 else:
764 rp = 0
766 idx += 1
767 # -------------------------------------
768 # Faces
769 # -------------------------------------
770 for r in range(0, len(listheight) - 1):
771 s = r * segments
772 t = 1
773 for n in range(0, segments):
774 t += 1
775 if t > segments:
776 t = 1
777 myface = [(n + s, n + s - segments + 1, n + s + 1, n + s + segments)]
778 myfaces.extend(myface)
779 else:
780 myface = [(n + s, n + s + 1, n + s + segments + 1, n + s + segments)]
781 myfaces.extend(myface)
783 # -----------------
784 # bottom face
785 # -----------------
786 if bottom:
787 fa = []
788 for f in range(0, segments):
789 fa.extend([f])
790 myfaces.extend([fa])
791 # -----------------
792 # top face
793 # -----------------
794 if top:
795 fa = []
796 for f in range(len(myvertex) - segments, len(myvertex)):
797 fa.extend([f])
798 myfaces.extend([fa])
800 return myvertex, myfaces