Cleanup: trailing space
[blender-addons.git] / render_povray / primitives.py
blob6d864220306446ffa6c31d1d2ca813c7e4c89f2c
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 """ Get POV-Ray specific objects In and Out of Blender """
23 import bpy
24 import os.path
25 from bpy_extras.io_utils import ImportHelper
26 from bpy_extras import object_utils
27 from bpy.utils import register_class
28 from math import atan, pi, degrees, sqrt, cos, sin
29 from bpy.types import Operator
31 from bpy.props import (
32 StringProperty,
33 BoolProperty,
34 IntProperty,
35 FloatProperty,
36 FloatVectorProperty,
37 EnumProperty,
38 PointerProperty,
39 CollectionProperty,
42 from mathutils import Vector, Matrix
45 # import collections
48 def pov_define_mesh(mesh, verts, edges, faces, name, hide_geometry=True):
49 """Generate proxy mesh."""
50 if mesh is None:
51 mesh = bpy.data.meshes.new(name)
52 mesh.from_pydata(verts, edges, faces)
53 mesh.update()
54 mesh.validate(
55 verbose=False
56 ) # Set it to True to see debug messages (helps ensure you generate valid geometry).
57 if hide_geometry:
58 mesh.vertices.foreach_set("hide", [True] * len(mesh.vertices))
59 mesh.edges.foreach_set("hide", [True] * len(mesh.edges))
60 mesh.polygons.foreach_set("hide", [True] * len(mesh.polygons))
61 return mesh
64 class POVRAY_OT_lathe_add(Operator):
65 """Add the representation of POV lathe using a screw modifier."""
67 bl_idname = "pov.addlathe"
68 bl_label = "Lathe"
69 bl_options = {'REGISTER', 'UNDO'}
70 bl_description = "adds lathe"
72 def execute(self, context):
73 # ayers=[False]*20
74 # layers[0]=True
75 bpy.ops.curve.primitive_bezier_curve_add(
76 location=context.scene.cursor.location,
77 rotation=(0, 0, 0),
78 # layers=layers,
80 ob = context.view_layer.objects.active
81 ob_data = ob.data
82 ob.name = ob_data.name = "PovLathe"
83 ob_data.dimensions = '2D'
84 ob_data.transform(Matrix.Rotation(-pi / 2.0, 4, 'Z'))
85 ob.pov.object_as = 'LATHE'
86 self.report({'INFO'}, "This native POV-Ray primitive")
87 ob.pov.curveshape = "lathe"
88 bpy.ops.object.modifier_add(type='SCREW')
89 mod = ob.modifiers[-1]
90 mod.axis = 'Y'
91 mod.show_render = False
92 return {'FINISHED'}
95 def pov_superellipsoid_define(context, op, ob):
96 """Create the proxy mesh of a POV superellipsoid using the pov_superellipsoid_define() function."""
98 if op:
99 mesh = None
101 u = op.se_u
102 v = op.se_v
103 n1 = op.se_n1
104 n2 = op.se_n2
105 edit = op.se_edit
106 se_param1 = n2 # op.se_param1
107 se_param2 = n1 # op.se_param2
109 else:
110 assert ob
111 mesh = ob.data
113 u = ob.pov.se_u
114 v = ob.pov.se_v
115 n1 = ob.pov.se_n1
116 n2 = ob.pov.se_n2
117 edit = ob.pov.se_edit
118 se_param1 = ob.pov.se_param1
119 se_param2 = ob.pov.se_param2
121 verts = []
122 r = 1
124 stepSegment = 360 / v * pi / 180
125 stepRing = pi / u
126 angSegment = 0
127 angRing = -pi / 2
129 step = 0
130 for ring in range(0, u - 1):
131 angRing += stepRing
132 for segment in range(0, v):
133 step += 1
134 angSegment += stepSegment
135 x = r * (abs(cos(angRing)) ** n1) * (abs(cos(angSegment)) ** n2)
136 if (cos(angRing) < 0 and cos(angSegment) > 0) or (
137 cos(angRing) > 0 and cos(angSegment) < 0
139 x = -x
140 y = r * (abs(cos(angRing)) ** n1) * (abs(sin(angSegment)) ** n2)
141 if (cos(angRing) < 0 and sin(angSegment) > 0) or (
142 cos(angRing) > 0 and sin(angSegment) < 0
144 y = -y
145 z = r * (abs(sin(angRing)) ** n1)
146 if sin(angRing) < 0:
147 z = -z
148 x = round(x, 4)
149 y = round(y, 4)
150 z = round(z, 4)
151 verts.append((x, y, z))
152 if edit == 'TRIANGLES':
153 verts.append((0, 0, 1))
154 verts.append((0, 0, -1))
156 faces = []
158 for i in range(0, u - 2):
159 m = i * v
160 for p in range(0, v):
161 if p < v - 1:
162 face = (m + p, 1 + m + p, v + 1 + m + p, v + m + p)
163 if p == v - 1:
164 face = (m + p, m, v + m, v + m + p)
165 faces.append(face)
166 if edit == 'TRIANGLES':
167 indexUp = len(verts) - 2
168 indexDown = len(verts) - 1
169 indexStartDown = len(verts) - 2 - v
170 for i in range(0, v):
171 if i < v - 1:
172 face = (indexDown, i, i + 1)
173 faces.append(face)
174 if i == v - 1:
175 face = (indexDown, i, 0)
176 faces.append(face)
177 for i in range(0, v):
178 if i < v - 1:
179 face = (indexUp, i + indexStartDown, i + indexStartDown + 1)
180 faces.append(face)
181 if i == v - 1:
182 face = (indexUp, i + indexStartDown, indexStartDown)
183 faces.append(face)
184 if edit == 'NGONS':
185 face = []
186 for i in range(0, v):
187 face.append(i)
188 faces.append(face)
189 face = []
190 indexUp = len(verts) - 1
191 for i in range(0, v):
192 face.append(indexUp - i)
193 faces.append(face)
194 mesh = pov_define_mesh(mesh, verts, [], faces, "SuperEllipsoid")
196 if not ob:
197 ob = object_utils.object_data_add(context, mesh, operator=None)
198 # engine = context.scene.render.engine what for?
199 ob = context.object
200 ob.name = ob.data.name = "PovSuperellipsoid"
201 ob.pov.object_as = 'SUPERELLIPSOID'
202 ob.pov.se_param1 = n2
203 ob.pov.se_param2 = n1
205 ob.pov.se_u = u
206 ob.pov.se_v = v
207 ob.pov.se_n1 = n1
208 ob.pov.se_n2 = n2
209 ob.pov.se_edit = edit
211 bpy.ops.object.mode_set(mode="EDIT")
212 bpy.ops.mesh.hide(unselected=False)
213 bpy.ops.object.mode_set(mode="OBJECT")
216 class POVRAY_OT_superellipsoid_add(Operator):
217 """Add the representation of POV superellipsoid using the pov_superellipsoid_define() function."""
219 bl_idname = "pov.addsuperellipsoid"
220 bl_label = "Add SuperEllipsoid"
221 bl_description = "Create a SuperEllipsoid"
222 bl_options = {'REGISTER', 'UNDO'}
223 COMPAT_ENGINES = {'POVRAY_RENDER'}
225 # XXX Keep it in sync with __init__'s RenderPovSettingsConePrimitive
226 # If someone knows how to define operators' props from a func, I'd be delighted to learn it!
227 se_param1: FloatProperty(
228 name="Parameter 1", description="", min=0.00, max=10.0, default=0.04
231 se_param2: FloatProperty(
232 name="Parameter 2", description="", min=0.00, max=10.0, default=0.04
235 se_u: IntProperty(
236 name="U-segments",
237 description="radial segmentation",
238 default=20,
239 min=4,
240 max=265,
242 se_v: IntProperty(
243 name="V-segments",
244 description="lateral segmentation",
245 default=20,
246 min=4,
247 max=265,
249 se_n1: FloatProperty(
250 name="Ring manipulator",
251 description="Manipulates the shape of the Ring",
252 default=1.0,
253 min=0.01,
254 max=100.0,
256 se_n2: FloatProperty(
257 name="Cross manipulator",
258 description="Manipulates the shape of the cross-section",
259 default=1.0,
260 min=0.01,
261 max=100.0,
263 se_edit: EnumProperty(
264 items=[
265 ("NOTHING", "Nothing", ""),
266 ("NGONS", "N-Gons", ""),
267 ("TRIANGLES", "Triangles", ""),
269 name="Fill up and down",
270 description="",
271 default='TRIANGLES',
274 @classmethod
275 def poll(cls, context):
276 engine = context.scene.render.engine
277 return engine in cls.COMPAT_ENGINES
279 def execute(self, context):
280 pov_superellipsoid_define(context, self, None)
282 self.report(
283 {'INFO'},
284 "This native POV-Ray primitive won't have any vertex to show in edit mode",
287 return {'FINISHED'}
290 class POVRAY_OT_superellipsoid_update(Operator):
291 """Update the superellipsoid.
293 Delete its previous proxy geometry and rerun pov_superellipsoid_define() function
294 with the new parameters"""
296 bl_idname = "pov.superellipsoid_update"
297 bl_label = "Update"
298 bl_description = "Update Superellipsoid"
299 bl_options = {'REGISTER', 'UNDO'}
300 COMPAT_ENGINES = {'POVRAY_RENDER'}
302 @classmethod
303 def poll(cls, context):
304 engine = context.scene.render.engine
305 ob = context.object
306 return (
308 and ob.data
309 and ob.type == 'MESH'
310 and engine in cls.COMPAT_ENGINES
313 def execute(self, context):
314 bpy.ops.object.mode_set(mode="EDIT")
315 bpy.ops.mesh.reveal()
316 bpy.ops.mesh.select_all(action='SELECT')
317 bpy.ops.mesh.delete(type='VERT')
318 bpy.ops.object.mode_set(mode="OBJECT")
320 pov_superellipsoid_define(context, None, context.object)
322 return {'FINISHED'}
325 def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
326 faces = []
327 if not vertIdx1 or not vertIdx2:
328 return None
329 if len(vertIdx1) < 2 and len(vertIdx2) < 2:
330 return None
331 fan = False
332 if len(vertIdx1) != len(vertIdx2):
333 if len(vertIdx1) == 1 and len(vertIdx2) > 1:
334 fan = True
335 else:
336 return None
337 total = len(vertIdx2)
338 if closed:
339 if flipped:
340 face = [vertIdx1[0], vertIdx2[0], vertIdx2[total - 1]]
341 if not fan:
342 face.append(vertIdx1[total - 1])
343 faces.append(face)
345 else:
346 face = [vertIdx2[0], vertIdx1[0]]
347 if not fan:
348 face.append(vertIdx1[total - 1])
349 face.append(vertIdx2[total - 1])
350 faces.append(face)
351 for num in range(total - 1):
352 if flipped:
353 if fan:
354 face = [vertIdx2[num], vertIdx1[0], vertIdx2[num + 1]]
355 else:
356 face = [
357 vertIdx2[num],
358 vertIdx1[num],
359 vertIdx1[num + 1],
360 vertIdx2[num + 1],
362 faces.append(face)
363 else:
364 if fan:
365 face = [vertIdx1[0], vertIdx2[num], vertIdx2[num + 1]]
366 else:
367 face = [
368 vertIdx1[num],
369 vertIdx2[num],
370 vertIdx2[num + 1],
371 vertIdx1[num + 1],
373 faces.append(face)
375 return faces
378 def power(a, b):
379 if a < 0:
380 return -((-a) ** b)
381 return a ** b
384 def supertoroid(R, r, u, v, n1, n2):
385 a = 2 * pi / u
386 b = 2 * pi / v
387 verts = []
388 faces = []
389 for i in range(u):
390 s = power(sin(i * a), n1)
391 c = power(cos(i * a), n1)
392 for j in range(v):
393 c2 = R + r * power(cos(j * b), n2)
394 s2 = r * power(sin(j * b), n2)
395 verts.append(
396 (c * c2, s * c2, s2)
397 ) # type as a (mathutils.Vector(c*c2,s*c2,s2))?
398 if i > 0:
399 f = createFaces(
400 range((i - 1) * v, i * v),
401 range(i * v, (i + 1) * v),
402 closed=True,
404 faces.extend(f)
405 f = createFaces(range((u - 1) * v, u * v), range(v), closed=True)
406 faces.extend(f)
407 return verts, faces
410 def pov_supertorus_define(context, op, ob):
411 if op:
412 mesh = None
413 st_R = op.st_R
414 st_r = op.st_r
415 st_u = op.st_u
416 st_v = op.st_v
417 st_n1 = op.st_n1
418 st_n2 = op.st_n2
419 st_ie = op.st_ie
420 st_edit = op.st_edit
422 else:
423 assert ob
424 mesh = ob.data
425 st_R = ob.pov.st_major_radius
426 st_r = ob.pov.st_minor_radius
427 st_u = ob.pov.st_u
428 st_v = ob.pov.st_v
429 st_n1 = ob.pov.st_ring
430 st_n2 = ob.pov.st_cross
431 st_ie = ob.pov.st_ie
432 st_edit = ob.pov.st_edit
434 if st_ie:
435 rad1 = (st_R + st_r) / 2
436 rad2 = (st_R - st_r) / 2
437 if rad2 > rad1:
438 [rad1, rad2] = [rad2, rad1]
439 else:
440 rad1 = st_R
441 rad2 = st_r
442 if rad2 > rad1:
443 rad1 = rad2
444 verts, faces = supertoroid(rad1, rad2, st_u, st_v, st_n1, st_n2)
445 mesh = pov_define_mesh(mesh, verts, [], faces, "PovSuperTorus", True)
446 if not ob:
447 ob = object_utils.object_data_add(context, mesh, operator=None)
448 ob.pov.object_as = 'SUPERTORUS'
449 ob.pov.st_major_radius = st_R
450 ob.pov.st_minor_radius = st_r
451 ob.pov.st_u = st_u
452 ob.pov.st_v = st_v
453 ob.pov.st_ring = st_n1
454 ob.pov.st_cross = st_n2
455 ob.pov.st_ie = st_ie
456 ob.pov.st_edit = st_edit
459 class POVRAY_OT_supertorus_add(Operator):
460 """Add the representation of POV supertorus using the pov_supertorus_define() function."""
462 bl_idname = "pov.addsupertorus"
463 bl_label = "Add Supertorus"
464 bl_description = "Create a SuperTorus"
465 bl_options = {'REGISTER', 'UNDO'}
466 COMPAT_ENGINES = {'POVRAY_RENDER'}
468 st_R: FloatProperty(
469 name="big radius",
470 description="The radius inside the tube",
471 default=1.0,
472 min=0.01,
473 max=100.0,
475 st_r: FloatProperty(
476 name="small radius",
477 description="The radius of the tube",
478 default=0.3,
479 min=0.01,
480 max=100.0,
482 st_u: IntProperty(
483 name="U-segments",
484 description="radial segmentation",
485 default=16,
486 min=3,
487 max=265,
489 st_v: IntProperty(
490 name="V-segments",
491 description="lateral segmentation",
492 default=8,
493 min=3,
494 max=265,
496 st_n1: FloatProperty(
497 name="Ring manipulator",
498 description="Manipulates the shape of the Ring",
499 default=1.0,
500 min=0.01,
501 max=100.0,
503 st_n2: FloatProperty(
504 name="Cross manipulator",
505 description="Manipulates the shape of the cross-section",
506 default=1.0,
507 min=0.01,
508 max=100.0,
510 st_ie: BoolProperty(
511 name="Use Int.+Ext. radii",
512 description="Use internal and external radii",
513 default=False,
515 st_edit: BoolProperty(
516 name="", description="", default=False, options={'HIDDEN'}
519 @classmethod
520 def poll(cls, context):
521 engine = context.scene.render.engine
522 return engine in cls.COMPAT_ENGINES
524 def execute(self, context):
525 pov_supertorus_define(context, self, None)
527 self.report(
528 {'INFO'},
529 "This native POV-Ray primitive won't have any vertex to show in edit mode",
531 return {'FINISHED'}
534 class POVRAY_OT_supertorus_update(Operator):
535 """Update the supertorus.
537 Delete its previous proxy geometry and rerun pov_supetorus_define() function
538 with the new parameters"""
540 bl_idname = "pov.supertorus_update"
541 bl_label = "Update"
542 bl_description = "Update SuperTorus"
543 bl_options = {'REGISTER', 'UNDO'}
544 COMPAT_ENGINES = {'POVRAY_RENDER'}
546 @classmethod
547 def poll(cls, context):
548 engine = context.scene.render.engine
549 ob = context.object
550 return (
552 and ob.data
553 and ob.type == 'MESH'
554 and engine in cls.COMPAT_ENGINES
557 def execute(self, context):
558 bpy.ops.object.mode_set(mode="EDIT")
559 bpy.ops.mesh.reveal()
560 bpy.ops.mesh.select_all(action='SELECT')
561 bpy.ops.mesh.delete(type='VERT')
562 bpy.ops.object.mode_set(mode="OBJECT")
564 pov_supertorus_define(context, None, context.object)
566 return {'FINISHED'}
569 #########################################################################################################
570 class POVRAY_OT_loft_add(Operator):
571 """Create the representation of POV loft using Blender curves."""
573 bl_idname = "pov.addloft"
574 bl_label = "Add Loft Data"
575 bl_description = "Create a Curve data for Meshmaker"
576 bl_options = {'REGISTER', 'UNDO'}
577 COMPAT_ENGINES = {'POVRAY_RENDER'}
579 loft_n: IntProperty(
580 name="Segments",
581 description="Vertical segments",
582 default=16,
583 min=3,
584 max=720,
586 loft_rings_bottom: IntProperty(
587 name="Bottom", description="Bottom rings", default=5, min=2, max=100
589 loft_rings_side: IntProperty(
590 name="Side", description="Side rings", default=10, min=2, max=100
592 loft_thick: FloatProperty(
593 name="Thickness",
594 description="Manipulates the shape of the Ring",
595 default=0.3,
596 min=0.01,
597 max=1.0,
599 loft_r: FloatProperty(
600 name="Radius", description="Radius", default=1, min=0.01, max=10
602 loft_height: FloatProperty(
603 name="Height",
604 description="Manipulates the shape of the Ring",
605 default=2,
606 min=0.01,
607 max=10.0,
610 def execute(self, context):
612 props = self.properties
613 loftData = bpy.data.curves.new('Loft', type='CURVE')
614 loftData.dimensions = '3D'
615 loftData.resolution_u = 2
616 # loftData.show_normal_face = False # deprecated in 2.8
617 n = props.loft_n
618 thick = props.loft_thick
619 side = props.loft_rings_side
620 bottom = props.loft_rings_bottom
621 h = props.loft_height
622 r = props.loft_r
623 distB = r / bottom
624 r0 = 0.00001
625 z = -h / 2
626 print("New")
627 for i in range(bottom + 1):
628 coords = []
629 angle = 0
630 for p in range(n):
631 x = r0 * cos(angle)
632 y = r0 * sin(angle)
633 coords.append((x, y, z))
634 angle += pi * 2 / n
635 r0 += distB
636 nurbs = loftData.splines.new('NURBS')
637 nurbs.points.add(len(coords) - 1)
638 for i, coord in enumerate(coords):
639 x, y, z = coord
640 nurbs.points[i].co = (x, y, z, 1)
641 nurbs.use_cyclic_u = True
642 for i in range(side):
643 z += h / side
644 coords = []
645 angle = 0
646 for p in range(n):
647 x = r * cos(angle)
648 y = r * sin(angle)
649 coords.append((x, y, z))
650 angle += pi * 2 / n
651 nurbs = loftData.splines.new('NURBS')
652 nurbs.points.add(len(coords) - 1)
653 for i, coord in enumerate(coords):
654 x, y, z = coord
655 nurbs.points[i].co = (x, y, z, 1)
656 nurbs.use_cyclic_u = True
657 r -= thick
658 for i in range(side):
659 coords = []
660 angle = 0
661 for p in range(n):
662 x = r * cos(angle)
663 y = r * sin(angle)
664 coords.append((x, y, z))
665 angle += pi * 2 / n
666 nurbs = loftData.splines.new('NURBS')
667 nurbs.points.add(len(coords) - 1)
668 for i, coord in enumerate(coords):
669 x, y, z = coord
670 nurbs.points[i].co = (x, y, z, 1)
671 nurbs.use_cyclic_u = True
672 z -= h / side
673 z = (-h / 2) + thick
674 distB = (r - 0.00001) / bottom
675 for i in range(bottom + 1):
676 coords = []
677 angle = 0
678 for p in range(n):
679 x = r * cos(angle)
680 y = r * sin(angle)
681 coords.append((x, y, z))
682 angle += pi * 2 / n
683 r -= distB
684 nurbs = loftData.splines.new('NURBS')
685 nurbs.points.add(len(coords) - 1)
686 for i, coord in enumerate(coords):
687 x, y, z = coord
688 nurbs.points[i].co = (x, y, z, 1)
689 nurbs.use_cyclic_u = True
690 ob = bpy.data.objects.new('Loft_shape', loftData)
691 scn = bpy.context.scene
692 scn.collection.objects.link(ob)
693 context.view_layer.objects.active = ob
694 ob.select_set(True)
695 ob.pov.curveshape = "loft"
696 return {'FINISHED'}
699 class POVRAY_OT_plane_add(Operator):
700 """Add the representation of POV infinite plane using just a very big Blender Plane.
702 Flag its primitive type with a specific pov.object_as attribute and lock edit mode
703 to keep proxy consistency by hiding edit geometry."""
705 bl_idname = "pov.addplane"
706 bl_label = "Plane"
707 bl_description = "Add Plane"
708 bl_options = {'REGISTER', 'UNDO'}
710 def execute(self, context):
711 # layers = 20*[False]
712 # layers[0] = True
713 bpy.ops.mesh.primitive_plane_add(size=100000)
714 ob = context.object
715 ob.name = ob.data.name = 'PovInfinitePlane'
716 bpy.ops.object.mode_set(mode="EDIT")
717 self.report(
718 {'INFO'},
719 "This native POV-Ray primitive "
720 "won't have any vertex to show in edit mode",
722 bpy.ops.mesh.hide(unselected=False)
723 bpy.ops.object.mode_set(mode="OBJECT")
724 bpy.ops.object.shade_smooth()
725 ob.pov.object_as = "PLANE"
726 return {'FINISHED'}
729 class POVRAY_OT_box_add(Operator):
730 """Add the representation of POV box using a simple Blender mesh cube.
732 Flag its primitive type with a specific pov.object_as attribute and lock edit mode
733 to keep proxy consistency by hiding edit geometry."""
735 bl_idname = "pov.addbox"
736 bl_label = "Box"
737 bl_description = "Add Box"
738 bl_options = {'REGISTER', 'UNDO'}
740 def execute(self, context):
741 # layers = 20*[False]
742 # layers[0] = True
743 bpy.ops.mesh.primitive_cube_add()
744 ob = context.object
745 ob.name = ob.data.name = 'PovBox'
746 bpy.ops.object.mode_set(mode="EDIT")
747 self.report(
748 {'INFO'},
749 "This native POV-Ray primitive "
750 "won't have any vertex to show in edit mode",
752 bpy.ops.mesh.hide(unselected=False)
753 bpy.ops.object.mode_set(mode="OBJECT")
754 ob.pov.object_as = "BOX"
755 return {'FINISHED'}
758 def pov_cylinder_define(context, op, ob, radius, loc, loc_cap):
759 if op:
760 R = op.R
761 loc = bpy.context.scene.cursor.location
762 loc_cap[0] = loc[0]
763 loc_cap[1] = loc[1]
764 loc_cap[2] = loc[2] + 2
765 vec = Vector(loc_cap) - Vector(loc)
766 depth = vec.length
767 rot = Vector((0, 0, 1)).rotation_difference(vec) # Rotation from Z axis.
768 trans = rot @ Vector(
769 (0, 0, depth / 2)
770 ) # Such that origin is at center of the base of the cylinder.
771 roteuler = rot.to_euler()
772 if not ob:
773 bpy.ops.object.add(type='MESH', location=loc)
774 ob = context.object
775 ob.name = ob.data.name = "PovCylinder"
776 ob.pov.cylinder_radius = radius
777 ob.pov.cylinder_location_cap = vec
778 ob.pov.object_as = "CYLINDER"
779 else:
780 ob.location = loc
782 bpy.ops.object.mode_set(mode="EDIT")
783 bpy.ops.mesh.reveal()
784 bpy.ops.mesh.select_all(action='SELECT')
785 bpy.ops.mesh.delete(type='VERT')
786 bpy.ops.mesh.primitive_cylinder_add(
787 radius=radius,
788 depth=depth,
789 location=loc,
790 rotation=roteuler,
791 end_fill_type='NGON',
792 ) #'NOTHING'
793 bpy.ops.transform.translate(value=trans)
795 bpy.ops.mesh.hide(unselected=False)
796 bpy.ops.object.mode_set(mode="OBJECT")
797 bpy.ops.object.shade_smooth()
800 class POVRAY_OT_cylinder_add(Operator):
801 """Add the representation of POV cylinder using pov_cylinder_define() function.
803 Use imported_cyl_loc when this operator is run by POV importer."""
805 bl_idname = "pov.addcylinder"
806 bl_label = "Cylinder"
807 bl_description = "Add Cylinder"
808 bl_options = {'REGISTER', 'UNDO'}
810 # XXX Keep it in sync with __init__'s cylinder Primitive
811 R: FloatProperty(name="Cylinder radius", min=0.00, max=10.0, default=1.0)
813 imported_cyl_loc: FloatVectorProperty(
814 name="Imported Pov base location", precision=6, default=(0.0, 0.0, 0.0)
817 imported_cyl_loc_cap: FloatVectorProperty(
818 name="Imported Pov cap location", precision=6, default=(0.0, 0.0, 2.0)
821 def execute(self, context):
822 props = self.properties
823 R = props.R
824 ob = context.object
825 # layers = 20*[False]
826 # layers[0] = True
827 if ob:
828 if ob.pov.imported_cyl_loc:
829 LOC = ob.pov.imported_cyl_loc
830 if ob.pov.imported_cyl_loc_cap:
831 LOC_CAP = ob.pov.imported_cyl_loc_cap
832 else:
833 if not props.imported_cyl_loc:
834 LOC_CAP = LOC = bpy.context.scene.cursor.location
835 LOC_CAP[2] += 2.0
836 else:
837 LOC = props.imported_cyl_loc
838 LOC_CAP = props.imported_cyl_loc_cap
839 self.report(
840 {'INFO'},
841 "This native POV-Ray primitive "
842 "won't have any vertex to show in edit mode",
845 pov_cylinder_define(context, self, None, self.R, LOC, LOC_CAP)
847 return {'FINISHED'}
850 class POVRAY_OT_cylinder_update(Operator):
851 """Update the POV cylinder.
853 Delete its previous proxy geometry and rerun pov_cylinder_define() function
854 with the new parameters"""
856 bl_idname = "pov.cylinder_update"
857 bl_label = "Update"
858 bl_description = "Update Cylinder"
859 bl_options = {'REGISTER', 'UNDO'}
860 COMPAT_ENGINES = {'POVRAY_RENDER'}
862 @classmethod
863 def poll(cls, context):
864 engine = context.scene.render.engine
865 ob = context.object
866 return (
868 and ob.data
869 and ob.type == 'MESH'
870 and ob.pov.object_as == "CYLINDER"
871 and engine in cls.COMPAT_ENGINES
874 def execute(self, context):
875 ob = context.object
876 radius = ob.pov.cylinder_radius
877 loc = ob.location
878 loc_cap = loc + ob.pov.cylinder_location_cap
880 pov_cylinder_define(context, None, ob, radius, loc, loc_cap)
882 return {'FINISHED'}
885 ################################SPHERE##########################################
886 def pov_sphere_define(context, op, ob, loc):
887 """create the representation of POV sphere using a Blender icosphere.
889 Its nice platonic solid curvature better represents pov rendertime
890 tesselation than a UV sphere"""
892 if op:
893 R = op.R
894 loc = bpy.context.scene.cursor.location
895 else:
896 assert ob
897 R = ob.pov.sphere_radius
899 # keep object rotation and location for the add object operator
900 obrot = ob.rotation_euler
901 # obloc = ob.location
902 obscale = ob.scale
904 bpy.ops.object.mode_set(mode="EDIT")
905 bpy.ops.mesh.reveal()
906 bpy.ops.mesh.select_all(action='SELECT')
907 bpy.ops.mesh.delete(type='VERT')
908 bpy.ops.mesh.primitive_ico_sphere_add(
909 subdivisions=4,
910 radius=ob.pov.sphere_radius,
911 location=loc,
912 rotation=obrot,
914 # bpy.ops.transform.rotate(axis=obrot,orient_type='GLOBAL')
915 bpy.ops.transform.resize(value=obscale)
916 # bpy.ops.transform.rotate(axis=obrot, proportional_size=1)
918 bpy.ops.mesh.hide(unselected=False)
919 bpy.ops.object.mode_set(mode="OBJECT")
920 bpy.ops.object.shade_smooth()
921 # bpy.ops.transform.rotate(axis=obrot,orient_type='GLOBAL')
923 if not ob:
924 bpy.ops.mesh.primitive_ico_sphere_add(
925 subdivisions=4, radius=R, location=loc
927 ob = context.object
928 ob.name = ob.data.name = "PovSphere"
929 ob.pov.object_as = "SPHERE"
930 ob.pov.sphere_radius = R
931 bpy.ops.object.mode_set(mode="EDIT")
932 bpy.ops.mesh.hide(unselected=False)
933 bpy.ops.object.mode_set(mode="OBJECT")
936 class POVRAY_OT_sphere_add(Operator):
937 """Add the representation of POV sphere using pov_sphere_define() function.
939 Use imported_loc when this operator is run by POV importer."""
941 bl_idname = "pov.addsphere"
942 bl_label = "Sphere"
943 bl_description = "Add Sphere Shape"
944 bl_options = {'REGISTER', 'UNDO'}
946 # XXX Keep it in sync with __init__'s torus Primitive
947 R: FloatProperty(name="Sphere radius", min=0.00, max=10.0, default=0.5)
949 imported_loc: FloatVectorProperty(
950 name="Imported Pov location", precision=6, default=(0.0, 0.0, 0.0)
953 def execute(self, context):
954 props = self.properties
955 R = props.R
956 ob = context.object
958 if ob:
959 if ob.pov.imported_loc:
960 LOC = ob.pov.imported_loc
961 else:
962 if not props.imported_loc:
963 LOC = bpy.context.scene.cursor.location
965 else:
966 LOC = props.imported_loc
967 self.report(
968 {'INFO'},
969 "This native POV-Ray primitive "
970 "won't have any vertex to show in edit mode",
972 pov_sphere_define(context, self, None, LOC)
974 return {'FINISHED'}
976 # def execute(self,context):
977 ## layers = 20*[False]
978 ## layers[0] = True
980 # bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=4, radius=ob.pov.sphere_radius)
981 # ob = context.object
982 # bpy.ops.object.mode_set(mode="EDIT")
983 # self.report({'INFO'}, "This native POV-Ray primitive "
984 # "won't have any vertex to show in edit mode")
985 # bpy.ops.mesh.hide(unselected=False)
986 # bpy.ops.object.mode_set(mode="OBJECT")
987 # bpy.ops.object.shade_smooth()
988 # ob.pov.object_as = "SPHERE"
989 # ob.name = ob.data.name = 'PovSphere'
990 # return {'FINISHED'}
993 class POVRAY_OT_sphere_update(Operator):
994 """Update the POV sphere.
996 Delete its previous proxy geometry and rerun pov_sphere_define() function
997 with the new parameters"""
999 bl_idname = "pov.sphere_update"
1000 bl_label = "Update"
1001 bl_description = "Update Sphere"
1002 bl_options = {'REGISTER', 'UNDO'}
1003 COMPAT_ENGINES = {'POVRAY_RENDER'}
1005 @classmethod
1006 def poll(cls, context):
1007 engine = context.scene.render.engine
1008 ob = context.object
1009 return (
1011 and ob.data
1012 and ob.type == 'MESH'
1013 and engine in cls.COMPAT_ENGINES
1016 def execute(self, context):
1018 pov_sphere_define(
1019 context, None, context.object, context.object.location
1022 return {'FINISHED'}
1025 ####################################CONE#######################################
1026 def pov_cone_define(context, op, ob):
1027 """Add the representation of POV cone using pov_define_mesh() function.
1029 Blender cone does not offer the same features such as a second radius."""
1030 verts = []
1031 faces = []
1032 if op:
1033 mesh = None
1034 base = op.base
1035 cap = op.cap
1036 seg = op.seg
1037 height = op.height
1038 else:
1039 assert ob
1040 mesh = ob.data
1041 base = ob.pov.cone_base_radius
1042 cap = ob.pov.cone_cap_radius
1043 seg = ob.pov.cone_segments
1044 height = ob.pov.cone_height
1046 zc = height / 2
1047 zb = -zc
1048 angle = 2 * pi / seg
1049 t = 0
1050 for i in range(seg):
1051 xb = base * cos(t)
1052 yb = base * sin(t)
1053 xc = cap * cos(t)
1054 yc = cap * sin(t)
1055 verts.append((xb, yb, zb))
1056 verts.append((xc, yc, zc))
1057 t += angle
1058 for i in range(seg):
1059 f = i * 2
1060 if i == seg - 1:
1061 faces.append([0, 1, f + 1, f])
1062 else:
1063 faces.append([f + 2, f + 3, f + 1, f])
1064 if base != 0:
1065 base_face = []
1066 for i in range(seg - 1, -1, -1):
1067 p = i * 2
1068 base_face.append(p)
1069 faces.append(base_face)
1070 if cap != 0:
1071 cap_face = []
1072 for i in range(seg):
1073 p = i * 2 + 1
1074 cap_face.append(p)
1075 faces.append(cap_face)
1077 mesh = pov_define_mesh(mesh, verts, [], faces, "PovCone", True)
1078 if not ob:
1079 ob = object_utils.object_data_add(context, mesh, operator=None)
1080 ob.pov.object_as = "CONE"
1081 ob.pov.cone_base_radius = base
1082 ob.pov.cone_cap_radius = cap
1083 ob.pov.cone_height = height
1084 ob.pov.cone_base_z = zb
1085 ob.pov.cone_cap_z = zc
1088 class POVRAY_OT_cone_add(Operator):
1089 """Add the representation of POV cone using pov_cone_define() function."""
1091 bl_idname = "pov.cone_add"
1092 bl_label = "Cone"
1093 bl_description = "Add Cone"
1094 bl_options = {'REGISTER', 'UNDO'}
1095 COMPAT_ENGINES = {'POVRAY_RENDER'}
1097 # XXX Keep it in sync with __init__.py's RenderPovSettingsConePrimitive
1098 # If someone knows how to define operators' props from a func, I'd be delighted to learn it!
1099 base: FloatProperty(
1100 name="Base radius",
1101 description="The first radius of the cone",
1102 default=1.0,
1103 min=0.01,
1104 max=100.0,
1106 cap: FloatProperty(
1107 name="Cap radius",
1108 description="The second radius of the cone",
1109 default=0.3,
1110 min=0.0,
1111 max=100.0,
1113 seg: IntProperty(
1114 name="Segments",
1115 description="Radial segmentation of the proxy mesh",
1116 default=16,
1117 min=3,
1118 max=265,
1120 height: FloatProperty(
1121 name="Height",
1122 description="Height of the cone",
1123 default=2.0,
1124 min=0.01,
1125 max=100.0,
1128 @classmethod
1129 def poll(cls, context):
1130 engine = context.scene.render.engine
1131 return engine in cls.COMPAT_ENGINES
1133 def execute(self, context):
1134 pov_cone_define(context, self, None)
1136 self.report(
1137 {'INFO'},
1138 "This native POV-Ray primitive won't have any vertex to show in edit mode",
1140 return {'FINISHED'}
1143 class POVRAY_OT_cone_update(Operator):
1144 """Update the POV cone.
1146 Delete its previous proxy geometry and rerun pov_cone_define() function
1147 with the new parameters"""
1149 bl_idname = "pov.cone_update"
1150 bl_label = "Update"
1151 bl_description = "Update Cone"
1152 bl_options = {'REGISTER', 'UNDO'}
1153 COMPAT_ENGINES = {'POVRAY_RENDER'}
1155 @classmethod
1156 def poll(cls, context):
1157 engine = context.scene.render.engine
1158 ob = context.object
1159 return (
1161 and ob.data
1162 and ob.type == 'MESH'
1163 and engine in cls.COMPAT_ENGINES
1166 def execute(self, context):
1167 bpy.ops.object.mode_set(mode="EDIT")
1168 bpy.ops.mesh.reveal()
1169 bpy.ops.mesh.select_all(action='SELECT')
1170 bpy.ops.mesh.delete(type='VERT')
1171 bpy.ops.object.mode_set(mode="OBJECT")
1173 pov_cone_define(context, None, context.object)
1175 return {'FINISHED'}
1178 ########################################ISOSURFACES##################################
1181 class POVRAY_OT_isosurface_box_add(Operator):
1182 """Add the representation of POV isosurface box using also just a Blender mesh cube.
1184 Flag its primitive type with a specific pov.object_as attribute and lock edit mode
1185 to keep proxy consistency by hiding edit geometry."""
1187 bl_idname = "pov.addisosurfacebox"
1188 bl_label = "Isosurface Box"
1189 bl_description = "Add Isosurface contained by Box"
1190 bl_options = {'REGISTER', 'UNDO'}
1192 def execute(self, context):
1193 # layers = 20*[False]
1194 # layers[0] = True
1195 bpy.ops.mesh.primitive_cube_add()
1196 ob = context.object
1197 bpy.ops.object.mode_set(mode="EDIT")
1198 self.report(
1199 {'INFO'},
1200 "This native POV-Ray primitive "
1201 "won't have any vertex to show in edit mode",
1203 bpy.ops.mesh.hide(unselected=False)
1204 bpy.ops.object.mode_set(mode="OBJECT")
1205 ob.pov.object_as = "ISOSURFACE"
1206 ob.pov.contained_by = 'box'
1207 ob.name = 'PovIsosurfaceBox'
1208 return {'FINISHED'}
1211 class POVRAY_OT_isosurface_sphere_add(Operator):
1212 """Add the representation of POV isosurface sphere by a Blender mesh icosphere.
1214 Flag its primitive type with a specific pov.object_as attribute and lock edit mode
1215 to keep proxy consistency by hiding edit geometry."""
1217 bl_idname = "pov.addisosurfacesphere"
1218 bl_label = "Isosurface Sphere"
1219 bl_description = "Add Isosurface contained by Sphere"
1220 bl_options = {'REGISTER', 'UNDO'}
1222 def execute(self, context):
1223 # layers = 20*[False]
1224 # layers[0] = True
1225 bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=4)
1226 ob = context.object
1227 bpy.ops.object.mode_set(mode="EDIT")
1228 self.report(
1229 {'INFO'},
1230 "This native POV-Ray primitive "
1231 "won't have any vertex to show in edit mode",
1233 bpy.ops.mesh.hide(unselected=False)
1234 bpy.ops.object.mode_set(mode="OBJECT")
1235 bpy.ops.object.shade_smooth()
1236 ob.pov.object_as = "ISOSURFACE"
1237 ob.pov.contained_by = 'sphere'
1238 ob.name = 'PovIsosurfaceSphere'
1239 return {'FINISHED'}
1242 class POVRAY_OT_sphere_sweep_add(Operator):
1243 """Add the representation of POV sphere_sweep using a Blender NURBS curve.
1245 Flag its primitive type with a specific ob.pov.curveshape attribute and
1246 leave access to edit mode to keep user editable handles."""
1248 bl_idname = "pov.addspheresweep"
1249 bl_label = "Sphere Sweep"
1250 bl_description = "Create Sphere Sweep along curve"
1251 bl_options = {'REGISTER', 'UNDO'}
1253 def execute(self, context):
1254 # layers = 20*[False]
1255 # layers[0] = True
1256 bpy.ops.curve.primitive_nurbs_curve_add()
1257 ob = context.object
1258 ob.name = ob.data.name = "PovSphereSweep"
1259 ob.pov.curveshape = "sphere_sweep"
1260 ob.data.bevel_depth = 0.02
1261 ob.data.bevel_resolution = 4
1262 ob.data.fill_mode = 'FULL'
1263 # ob.data.splines[0].order_u = 4
1265 return {'FINISHED'}
1268 class POVRAY_OT_blob_add(Operator):
1269 """Add the representation of POV blob using a Blender meta ball.
1271 No need to flag its primitive type as meta are exported to blobs
1272 and leave access to edit mode to keep user editable thresholds."""
1274 bl_idname = "pov.addblobsphere"
1275 bl_label = "Blob Sphere"
1276 bl_description = "Add Blob Sphere"
1277 bl_options = {'REGISTER', 'UNDO'}
1279 def execute(self, context):
1280 # layers = 20*[False]
1281 # layers[0] = True
1282 bpy.ops.object.metaball_add(type='BALL')
1283 ob = context.object
1284 ob.name = "PovBlob"
1285 return {'FINISHED'}
1288 class POVRAY_OT_rainbow_add(Operator):
1289 """Add the representation of POV rainbow using a Blender spot light.
1291 Rainbows indeed propagate along a visibility cone.
1292 Flag its primitive type with a specific ob.pov.object_as attribute
1293 and leave access to edit mode to keep user editable handles.
1294 Add a constraint to orient it towards camera because POV Rainbows
1295 are view dependant and having it always initially visible is less
1296 confusing """
1298 bl_idname = "pov.addrainbow"
1299 bl_label = "Rainbow"
1300 bl_description = "Add Rainbow"
1301 bl_options = {'REGISTER', 'UNDO'}
1303 def execute(self, context):
1304 cam = context.scene.camera
1305 bpy.ops.object.light_add(type='SPOT', radius=1)
1306 ob = context.object
1307 ob.data.show_cone = False
1308 ob.data.spot_blend = 0.5
1309 # ob.data.shadow_buffer_clip_end = 0 # deprecated in 2.8
1310 ob.data.shadow_buffer_clip_start = 4 * cam.location.length
1311 ob.data.distance = cam.location.length
1312 ob.data.energy = 0
1313 ob.name = ob.data.name = "PovRainbow"
1314 ob.pov.object_as = "RAINBOW"
1316 # obj = context.object
1317 bpy.ops.object.constraint_add(type='DAMPED_TRACK')
1319 ob.constraints["Damped Track"].target = cam
1320 ob.constraints["Damped Track"].track_axis = 'TRACK_NEGATIVE_Z'
1321 ob.location = -cam.location
1323 # refocus on the actual rainbow
1324 bpy.context.view_layer.objects.active = ob
1325 ob.select_set(True)
1327 return {'FINISHED'}
1330 class POVRAY_OT_height_field_add(bpy.types.Operator, ImportHelper):
1331 """Add the representation of POV height_field using a displaced grid.
1333 texture slot fix and displace modifier will be needed because noise
1334 displace operator was deprecated in 2.8"""
1336 bl_idname = "pov.addheightfield"
1337 bl_label = "Height Field"
1338 bl_description = "Add Height Field"
1339 bl_options = {'REGISTER', 'UNDO'}
1341 # XXX Keep it in sync with __init__'s hf Primitive
1342 # filename_ext = ".png"
1344 # filter_glob = StringProperty(
1345 # default="*.exr;*.gif;*.hdr;*.iff;*.jpeg;*.jpg;*.pgm;*.png;*.pot;*.ppm;*.sys;*.tga;*.tiff;*.EXR;*.GIF;*.HDR;*.IFF;*.JPEG;*.JPG;*.PGM;*.PNG;*.POT;*.PPM;*.SYS;*.TGA;*.TIFF",
1346 # options={'HIDDEN'},
1348 quality: IntProperty(
1349 name="Quality", description="", default=100, min=1, max=100
1351 hf_filename: StringProperty(maxlen=1024)
1353 hf_gamma: FloatProperty(
1354 name="Gamma", description="Gamma", min=0.0001, max=20.0, default=1.0
1357 hf_premultiplied: BoolProperty(
1358 name="Premultiplied", description="Premultiplied", default=True
1361 hf_smooth: BoolProperty(name="Smooth", description="Smooth", default=False)
1363 hf_water: FloatProperty(
1364 name="Water Level",
1365 description="Wather Level",
1366 min=0.00,
1367 max=1.00,
1368 default=0.0,
1371 hf_hierarchy: BoolProperty(
1372 name="Hierarchy", description="Height field hierarchy", default=True
1375 def execute(self, context):
1376 props = self.properties
1377 impath = bpy.path.abspath(self.filepath)
1378 img = bpy.data.images.load(impath)
1379 im_name = img.name
1380 im_name, file_extension = os.path.splitext(im_name)
1381 hf_tex = bpy.data.textures.new('%s_hf_image' % im_name, type='IMAGE')
1382 hf_tex.image = img
1383 mat = bpy.data.materials.new('Tex_%s_hf' % im_name)
1384 hf_slot = mat.pov_texture_slots.add()
1385 hf_slot.texture = hf_tex.name
1386 # layers = 20*[False]
1387 # layers[0] = True
1388 quality = props.quality
1389 res = 100 / quality
1390 w, h = hf_tex.image.size[:]
1391 w = int(w / res)
1392 h = int(h / res)
1393 bpy.ops.mesh.primitive_grid_add(
1394 x_subdivisions=w, y_subdivisions=h, size=0.5
1396 ob = context.object
1397 ob.name = ob.data.name = '%s' % im_name
1398 ob.data.materials.append(mat)
1399 bpy.ops.object.mode_set(mode="EDIT")
1400 # bpy.ops.mesh.noise(factor=1) # TODO replace by a displace modifier as noise deprecated in 2.8
1401 bpy.ops.object.mode_set(mode="OBJECT")
1403 # needs a loop to select by index?
1404 # bpy.ops.object.material_slot_remove()
1405 # material just left there for now
1407 mat.pov_texture_slots.clear()
1408 bpy.ops.object.mode_set(mode="EDIT")
1409 bpy.ops.mesh.hide(unselected=False)
1410 bpy.ops.object.mode_set(mode="OBJECT")
1411 ob.pov.object_as = 'HEIGHT_FIELD'
1412 ob.pov.hf_filename = impath
1413 return {'FINISHED'}
1416 ############################TORUS############################################
1417 def pov_torus_define(context, op, ob):
1418 """Add the representation of POV torus using just a Blender torus.
1420 But flag its primitive type with a specific pov.object_as attribute and lock edit mode
1421 to keep proxy consistency by hiding edit geometry."""
1423 if op:
1424 mas = op.mas
1425 mis = op.mis
1426 mar = op.mar
1427 mir = op.mir
1428 else:
1429 assert ob
1430 mas = ob.pov.torus_major_segments
1431 mis = ob.pov.torus_minor_segments
1432 mar = ob.pov.torus_major_radius
1433 mir = ob.pov.torus_minor_radius
1435 # keep object rotation and location for the add object operator
1436 obrot = ob.rotation_euler
1437 obloc = ob.location
1439 bpy.ops.object.mode_set(mode="EDIT")
1440 bpy.ops.mesh.reveal()
1441 bpy.ops.mesh.select_all(action='SELECT')
1442 bpy.ops.mesh.delete(type='VERT')
1443 bpy.ops.mesh.primitive_torus_add(
1444 rotation=obrot,
1445 location=obloc,
1446 major_segments=mas,
1447 minor_segments=mis,
1448 major_radius=mar,
1449 minor_radius=mir,
1452 bpy.ops.mesh.hide(unselected=False)
1453 bpy.ops.object.mode_set(mode="OBJECT")
1455 if not ob:
1456 bpy.ops.mesh.primitive_torus_add(
1457 major_segments=mas,
1458 minor_segments=mis,
1459 major_radius=mar,
1460 minor_radius=mir,
1462 ob = context.object
1463 ob.name = ob.data.name = "PovTorus"
1464 ob.pov.object_as = "TORUS"
1465 ob.pov.torus_major_segments = mas
1466 ob.pov.torus_minor_segments = mis
1467 ob.pov.torus_major_radius = mar
1468 ob.pov.torus_minor_radius = mir
1469 bpy.ops.object.mode_set(mode="EDIT")
1470 bpy.ops.mesh.hide(unselected=False)
1471 bpy.ops.object.mode_set(mode="OBJECT")
1474 class POVRAY_OT_torus_add(Operator):
1475 """Add the representation of POV torus using using pov_torus_define() function."""
1477 bl_idname = "pov.addtorus"
1478 bl_label = "Torus"
1479 bl_description = "Add Torus"
1480 bl_options = {'REGISTER', 'UNDO'}
1482 # XXX Keep it in sync with __init__'s torus Primitive
1483 mas: IntProperty(
1484 name="Major Segments", description="", default=48, min=3, max=720
1486 mis: IntProperty(
1487 name="Minor Segments", description="", default=12, min=3, max=720
1489 mar: FloatProperty(name="Major Radius", description="", default=1.0)
1490 mir: FloatProperty(name="Minor Radius", description="", default=0.25)
1492 def execute(self, context):
1493 props = self.properties
1494 mar = props.mar
1495 mir = props.mir
1496 mas = props.mas
1497 mis = props.mis
1498 pov_torus_define(context, self, None)
1499 self.report(
1500 {'INFO'},
1501 "This native POV-Ray primitive "
1502 "won't have any vertex to show in edit mode",
1504 return {'FINISHED'}
1507 class POVRAY_OT_torus_update(Operator):
1508 """Update the POV torus.
1510 Delete its previous proxy geometry and rerun pov_torus_define() function
1511 with the new parameters"""
1513 bl_idname = "pov.torus_update"
1514 bl_label = "Update"
1515 bl_description = "Update Torus"
1516 bl_options = {'REGISTER', 'UNDO'}
1517 COMPAT_ENGINES = {'POVRAY_RENDER'}
1519 @classmethod
1520 def poll(cls, context):
1521 engine = context.scene.render.engine
1522 ob = context.object
1523 return (
1525 and ob.data
1526 and ob.type == 'MESH'
1527 and engine in cls.COMPAT_ENGINES
1530 def execute(self, context):
1532 pov_torus_define(context, None, context.object)
1534 return {'FINISHED'}
1537 ###################################################################################
1540 class POVRAY_OT_prism_add(Operator):
1541 """Add the representation of POV prism using using an extruded curve."""
1543 bl_idname = "pov.addprism"
1544 bl_label = "Prism"
1545 bl_description = "Create Prism"
1546 bl_options = {'REGISTER', 'UNDO'}
1548 prism_n: IntProperty(
1549 name="Sides", description="Number of sides", default=5, min=3, max=720
1551 prism_r: FloatProperty(name="Radius", description="Radius", default=1.0)
1553 def execute(self, context):
1555 props = self.properties
1556 loftData = bpy.data.curves.new('Prism', type='CURVE')
1557 loftData.dimensions = '2D'
1558 loftData.resolution_u = 2
1559 # loftData.show_normal_face = False
1560 loftData.extrude = 2
1561 n = props.prism_n
1562 r = props.prism_r
1563 coords = []
1564 z = 0
1565 angle = 0
1566 for p in range(n):
1567 x = r * cos(angle)
1568 y = r * sin(angle)
1569 coords.append((x, y, z))
1570 angle += pi * 2 / n
1571 poly = loftData.splines.new('POLY')
1572 poly.points.add(len(coords) - 1)
1573 for i, coord in enumerate(coords):
1574 x, y, z = coord
1575 poly.points[i].co = (x, y, z, 1)
1576 poly.use_cyclic_u = True
1578 ob = bpy.data.objects.new('Prism_shape', loftData)
1579 scn = bpy.context.scene
1580 scn.collection.objects.link(ob)
1581 context.view_layer.objects.active = ob
1582 ob.select_set(True)
1583 ob.pov.curveshape = "prism"
1584 ob.name = ob.data.name = "Prism"
1585 return {'FINISHED'}
1588 ##############################PARAMETRIC######################################
1589 def pov_parametric_define(context, op, ob):
1590 """Add the representation of POV parametric surfaces by math surface from add mesh extra objects addon."""
1592 if op:
1593 u_min = op.u_min
1594 u_max = op.u_max
1595 v_min = op.v_min
1596 v_max = op.v_max
1597 x_eq = op.x_eq
1598 y_eq = op.y_eq
1599 z_eq = op.z_eq
1601 else:
1602 assert ob
1603 u_min = ob.pov.u_min
1604 u_max = ob.pov.u_max
1605 v_min = ob.pov.v_min
1606 v_max = ob.pov.v_max
1607 x_eq = ob.pov.x_eq
1608 y_eq = ob.pov.y_eq
1609 z_eq = ob.pov.z_eq
1611 # keep object rotation and location for the updated object
1612 obloc = ob.location
1613 obrot = ob.rotation_euler # In radians
1614 # Parametric addon has no loc rot, some extra work is needed
1615 # in case cursor has moved
1616 curloc = bpy.context.scene.cursor.location
1618 bpy.ops.object.mode_set(mode="EDIT")
1619 bpy.ops.mesh.reveal()
1620 bpy.ops.mesh.select_all(action='SELECT')
1621 bpy.ops.mesh.delete(type='VERT')
1622 bpy.ops.mesh.primitive_xyz_function_surface(
1623 x_eq=x_eq,
1624 y_eq=y_eq,
1625 z_eq=z_eq,
1626 range_u_min=u_min,
1627 range_u_max=u_max,
1628 range_v_min=v_min,
1629 range_v_max=v_max,
1631 bpy.ops.mesh.select_all(action='SELECT')
1632 # extra work:
1633 bpy.ops.transform.translate(value=(obloc - curloc), proportional_size=1)
1634 bpy.ops.transform.rotate(axis=obrot, proportional_size=1)
1636 bpy.ops.mesh.hide(unselected=False)
1637 bpy.ops.object.mode_set(mode="OBJECT")
1639 if not ob:
1640 bpy.ops.mesh.primitive_xyz_function_surface(
1641 x_eq=x_eq,
1642 y_eq=y_eq,
1643 z_eq=z_eq,
1644 range_u_min=u_min,
1645 range_u_max=u_max,
1646 range_v_min=v_min,
1647 range_v_max=v_max,
1649 ob = context.object
1650 ob.name = ob.data.name = "PovParametric"
1651 ob.pov.object_as = "PARAMETRIC"
1653 ob.pov.u_min = u_min
1654 ob.pov.u_max = u_max
1655 ob.pov.v_min = v_min
1656 ob.pov.v_max = v_max
1657 ob.pov.x_eq = x_eq
1658 ob.pov.y_eq = y_eq
1659 ob.pov.z_eq = z_eq
1661 bpy.ops.object.mode_set(mode="EDIT")
1662 bpy.ops.mesh.hide(unselected=False)
1663 bpy.ops.object.mode_set(mode="OBJECT")
1666 class POVRAY_OT_parametric_add(Operator):
1667 """Add the representation of POV parametric surfaces using pov_parametric_define() function."""
1669 bl_idname = "pov.addparametric"
1670 bl_label = "Parametric"
1671 bl_description = "Add Paramertic"
1672 bl_options = {'REGISTER', 'UNDO'}
1674 # XXX Keep it in sync with __init__'s Parametric primitive
1675 u_min: FloatProperty(name="U Min", description="", default=0.0)
1676 v_min: FloatProperty(name="V Min", description="", default=0.0)
1677 u_max: FloatProperty(name="U Max", description="", default=6.28)
1678 v_max: FloatProperty(name="V Max", description="", default=12.57)
1679 x_eq: StringProperty(maxlen=1024, default="cos(v)*(1+cos(u))*sin(v/8)")
1680 y_eq: StringProperty(maxlen=1024, default="sin(u)*sin(v/8)+cos(v/8)*1.5")
1681 z_eq: StringProperty(maxlen=1024, default="sin(v)*(1+cos(u))*sin(v/8)")
1683 def execute(self, context):
1684 props = self.properties
1685 u_min = props.u_min
1686 v_min = props.v_min
1687 u_max = props.u_max
1688 v_max = props.v_max
1689 x_eq = props.x_eq
1690 y_eq = props.y_eq
1691 z_eq = props.z_eq
1693 pov_parametric_define(context, self, None)
1694 self.report(
1695 {'INFO'},
1696 "This native POV-Ray primitive "
1697 "won't have any vertex to show in edit mode",
1699 return {'FINISHED'}
1702 class POVRAY_OT_parametric_update(Operator):
1703 """Update the representation of POV parametric surfaces.
1705 Delete its previous proxy geometry and rerun pov_parametric_define() function
1706 with the new parameters"""
1708 bl_idname = "pov.parametric_update"
1709 bl_label = "Update"
1710 bl_description = "Update parametric object"
1711 bl_options = {'REGISTER', 'UNDO'}
1712 COMPAT_ENGINES = {'POVRAY_RENDER'}
1714 @classmethod
1715 def poll(cls, context):
1716 engine = context.scene.render.engine
1717 ob = context.object
1718 return (
1720 and ob.data
1721 and ob.type == 'MESH'
1722 and engine in cls.COMPAT_ENGINES
1725 def execute(self, context):
1727 pov_parametric_define(context, None, context.object)
1729 return {'FINISHED'}
1732 #######################################################################
1735 class POVRAY_OT_shape_polygon_to_circle_add(Operator):
1736 """Add the proxy mesh for POV Polygon to circle lofting macro"""
1738 bl_idname = "pov.addpolygontocircle"
1739 bl_label = "Polygon To Circle Blending"
1740 bl_description = "Add Polygon To Circle Blending Surface"
1741 bl_options = {'REGISTER', 'UNDO'}
1742 COMPAT_ENGINES = {'POVRAY_RENDER'}
1744 # XXX Keep it in sync with __init__'s polytocircle properties
1745 polytocircle_resolution: IntProperty(
1746 name="Resolution", description="", default=3, min=0, max=256
1748 polytocircle_ngon: IntProperty(
1749 name="NGon", description="", min=3, max=64, default=5
1751 polytocircle_ngonR: FloatProperty(
1752 name="NGon Radius", description="", default=0.3
1754 polytocircle_circleR: FloatProperty(
1755 name="Circle Radius", description="", default=1.0
1758 def execute(self, context):
1759 props = self.properties
1760 ngon = props.polytocircle_ngon
1761 ngonR = props.polytocircle_ngonR
1762 circleR = props.polytocircle_circleR
1763 resolution = props.polytocircle_resolution
1764 # layers = 20*[False]
1765 # layers[0] = True
1766 bpy.ops.mesh.primitive_circle_add(
1767 vertices=ngon, radius=ngonR, fill_type='NGON', enter_editmode=True
1769 bpy.ops.transform.translate(value=(0, 0, 1))
1770 bpy.ops.mesh.subdivide(number_cuts=resolution)
1771 numCircleVerts = ngon + (ngon * resolution)
1772 bpy.ops.mesh.select_all(action='DESELECT')
1773 bpy.ops.mesh.primitive_circle_add(
1774 vertices=numCircleVerts,
1775 radius=circleR,
1776 fill_type='NGON',
1777 enter_editmode=True,
1779 bpy.ops.transform.translate(value=(0, 0, -1))
1780 bpy.ops.mesh.select_all(action='SELECT')
1781 bpy.ops.mesh.bridge_edge_loops()
1782 if ngon < 5:
1783 bpy.ops.mesh.select_all(action='DESELECT')
1784 bpy.ops.mesh.primitive_circle_add(
1785 vertices=ngon,
1786 radius=ngonR,
1787 fill_type='TRIFAN',
1788 enter_editmode=True,
1790 bpy.ops.transform.translate(value=(0, 0, 1))
1791 bpy.ops.mesh.select_all(action='SELECT')
1792 bpy.ops.mesh.remove_doubles()
1793 bpy.ops.object.mode_set(mode='OBJECT')
1794 ob = context.object
1795 ob.name = "Polygon_To_Circle"
1796 ob.pov.object_as = 'POLYCIRCLE'
1797 ob.pov.ngon = ngon
1798 ob.pov.ngonR = ngonR
1799 ob.pov.circleR = circleR
1800 bpy.ops.object.mode_set(mode="EDIT")
1801 bpy.ops.mesh.hide(unselected=False)
1802 bpy.ops.object.mode_set(mode="OBJECT")
1803 return {'FINISHED'}
1806 #############################IMPORT
1809 class ImportPOV(bpy.types.Operator, ImportHelper):
1810 """Load Povray files"""
1812 bl_idname = "import_scene.pov"
1813 bl_label = "POV-Ray files (.pov/.inc)"
1814 bl_options = {'PRESET', 'UNDO'}
1815 COMPAT_ENGINES = {'POVRAY_RENDER'}
1817 # -----------
1818 # File props.
1819 files: CollectionProperty(
1820 type=bpy.types.OperatorFileListElement, options={'HIDDEN', 'SKIP_SAVE'}
1822 directory: StringProperty(
1823 maxlen=1024, subtype='FILE_PATH', options={'HIDDEN', 'SKIP_SAVE'}
1826 filename_ext = {".pov", ".inc"}
1827 filter_glob: StringProperty(default="*.pov;*.inc", options={'HIDDEN'})
1829 import_at_cur: BoolProperty(
1830 name="Import at Cursor Location",
1831 description="Ignore Object Matrix",
1832 default=False,
1835 def execute(self, context):
1836 from mathutils import Matrix
1838 verts = []
1839 faces = []
1840 materials = []
1841 blendMats = [] ##############
1842 povMats = [] ##############
1843 colors = []
1844 matNames = []
1845 lenverts = None
1846 lenfaces = None
1847 suffix = -1
1848 name = 'Mesh2_%s' % suffix
1849 name_search = False
1850 verts_search = False
1851 faces_search = False
1852 plane_search = False
1853 box_search = False
1854 cylinder_search = False
1855 sphere_search = False
1856 cone_search = False
1857 tex_search = False ##################
1858 cache = []
1859 matrixes = {}
1860 writematrix = False
1861 index = None
1862 value = None
1863 # filepov = bpy.path.abspath(self.filepath) #was used for single files
1865 def mat_search(cache):
1866 r = g = b = 0.5
1867 f = t = 0
1868 color = None
1870 for item, value in enumerate(cache):
1872 if value == 'texture':
1873 pass
1875 if value == 'pigment':
1877 if cache[item + 2] in {'rgb', 'srgb'}:
1878 pass
1880 elif cache[item + 2] in {'rgbf', 'srgbf'}:
1881 pass
1883 elif cache[item + 2] in {'rgbt', 'srgbt'}:
1884 try:
1885 r, g, b, t = (
1886 float(cache[item + 3]),
1887 float(cache[item + 4]),
1888 float(cache[item + 5]),
1889 float(cache[item + 6]),
1891 except:
1892 r = g = b = t = float(cache[item + 2])
1893 color = (r, g, b, t)
1895 elif cache[item + 2] in {'rgbft', 'srgbft'}:
1896 pass
1898 else:
1899 pass
1901 if colors == [] or (colors != [] and color not in colors):
1902 colors.append(color)
1903 name = ob.name + "_mat"
1904 matNames.append(name)
1905 mat = bpy.data.materials.new(name)
1906 mat.diffuse_color = (r, g, b)
1907 mat.alpha = 1 - t
1908 if mat.alpha != 1:
1909 mat.use_transparency = True
1910 ob.data.materials.append(mat)
1912 else:
1913 for i, value in enumerate(colors):
1914 if color == value:
1915 ob.data.materials.append(
1916 bpy.data.materials[matNames[i]]
1919 for file in self.files:
1920 print("Importing file: " + file.name)
1921 filepov = self.directory + file.name
1922 for line in open(filepov):
1923 string = line.replace("{", " ")
1924 string = string.replace("}", " ")
1925 string = string.replace("<", " ")
1926 string = string.replace(">", " ")
1927 string = string.replace(",", " ")
1928 lw = string.split()
1929 lenwords = len(lw)
1930 if lw:
1931 if lw[0] == "object":
1932 writematrix = True
1933 if writematrix:
1934 if lw[0] not in {"object", "matrix"}:
1935 index = lw[0]
1936 if lw[0] in {"matrix"}:
1937 value = [
1938 float(lw[1]),
1939 float(lw[2]),
1940 float(lw[3]),
1941 float(lw[4]),
1942 float(lw[5]),
1943 float(lw[6]),
1944 float(lw[7]),
1945 float(lw[8]),
1946 float(lw[9]),
1947 float(lw[10]),
1948 float(lw[11]),
1949 float(lw[12]),
1951 matrixes[index] = value
1952 writematrix = False
1953 for line in open(filepov):
1954 S = line.replace("{", " { ")
1955 S = S.replace("}", " } ")
1956 S = S.replace(",", " ")
1957 S = S.replace("<", "")
1958 S = S.replace(">", " ")
1959 S = S.replace("=", " = ")
1960 S = S.replace(";", " ; ")
1961 S = S.split()
1962 lenS = len(S)
1963 for i, word in enumerate(S):
1964 ##################Primitives Import##################
1965 if word == 'cone':
1966 cone_search = True
1967 name_search = False
1968 if cone_search:
1969 cache.append(word)
1970 if cache[-1] == '}':
1971 try:
1972 x0 = float(cache[2])
1973 y0 = float(cache[3])
1974 z0 = float(cache[4])
1975 r0 = float(cache[5])
1976 x1 = float(cache[6])
1977 y1 = float(cache[7])
1978 z1 = float(cache[8])
1979 r1 = float(cache[9])
1980 # Y is height in most pov files, not z
1981 bpy.ops.pov.cone_add(
1982 base=r0, cap=r1, height=(y1 - y0)
1984 ob = context.object
1985 ob.location = (x0, y0, z0)
1986 # ob.scale = (r,r,r)
1987 mat_search(cache)
1988 except (ValueError):
1989 pass
1990 cache = []
1991 cone_search = False
1992 if word == 'plane':
1993 plane_search = True
1994 name_search = False
1995 if plane_search:
1996 cache.append(word)
1997 if cache[-1] == '}':
1998 try:
1999 bpy.ops.pov.addplane()
2000 ob = context.object
2001 mat_search(cache)
2002 except (ValueError):
2003 pass
2004 cache = []
2005 plane_search = False
2006 if word == 'box':
2007 box_search = True
2008 name_search = False
2009 if box_search:
2010 cache.append(word)
2011 if cache[-1] == '}':
2012 try:
2013 x0 = float(cache[2])
2014 y0 = float(cache[3])
2015 z0 = float(cache[4])
2016 x1 = float(cache[5])
2017 y1 = float(cache[6])
2018 z1 = float(cache[7])
2019 # imported_corner_1=(x0, y0, z0)
2020 # imported_corner_2 =(x1, y1, z1)
2021 center = (
2022 (x0 + x1) / 2,
2023 (y0 + y1) / 2,
2024 (z0 + z1) / 2,
2026 bpy.ops.pov.addbox()
2027 ob = context.object
2028 ob.location = center
2029 mat_search(cache)
2031 except (ValueError):
2032 pass
2033 cache = []
2034 box_search = False
2035 if word == 'cylinder':
2036 cylinder_search = True
2037 name_search = False
2038 if cylinder_search:
2039 cache.append(word)
2040 if cache[-1] == '}':
2041 try:
2042 x0 = float(cache[2])
2043 y0 = float(cache[3])
2044 z0 = float(cache[4])
2045 x1 = float(cache[5])
2046 y1 = float(cache[6])
2047 z1 = float(cache[7])
2048 imported_cyl_loc = (x0, y0, z0)
2049 imported_cyl_loc_cap = (x1, y1, z1)
2051 r = float(cache[8])
2053 vec = Vector(imported_cyl_loc_cap) - Vector(
2054 imported_cyl_loc
2056 depth = vec.length
2057 rot = Vector((0, 0, 1)).rotation_difference(
2059 ) # Rotation from Z axis.
2060 trans = rot @ Vector(
2061 (0, 0, depth / 2)
2062 ) # Such that origin is at center of the base of the cylinder.
2063 # center = ((x0 + x1)/2,(y0 + y1)/2,(z0 + z1)/2)
2064 scaleZ = (
2065 sqrt(
2066 (x1 - x0) ** 2
2067 + (y1 - y0) ** 2
2068 + (z1 - z0) ** 2
2072 bpy.ops.pov.addcylinder(
2073 R=r,
2074 imported_cyl_loc=imported_cyl_loc,
2075 imported_cyl_loc_cap=imported_cyl_loc_cap,
2077 ob = context.object
2078 ob.location = (x0, y0, z0)
2079 ob.rotation_euler = rot.to_euler()
2080 ob.scale = (1, 1, scaleZ)
2082 # scale data rather than obj?
2083 # bpy.ops.object.mode_set(mode='EDIT')
2084 # bpy.ops.mesh.reveal()
2085 # bpy.ops.mesh.select_all(action='SELECT')
2086 # bpy.ops.transform.resize(value=(1,1,scaleZ), orient_type='LOCAL')
2087 # bpy.ops.mesh.hide(unselected=False)
2088 # bpy.ops.object.mode_set(mode='OBJECT')
2090 mat_search(cache)
2092 except (ValueError):
2093 pass
2094 cache = []
2095 cylinder_search = False
2096 if word == 'sphere':
2097 sphere_search = True
2098 name_search = False
2099 if sphere_search:
2100 cache.append(word)
2101 if cache[-1] == '}':
2102 x = y = z = r = 0
2103 try:
2104 x = float(cache[2])
2105 y = float(cache[3])
2106 z = float(cache[4])
2107 r = float(cache[5])
2109 except (ValueError):
2110 pass
2111 except:
2112 x = y = z = float(cache[2])
2113 r = float(cache[3])
2114 bpy.ops.pov.addsphere(R=r, imported_loc=(x, y, z))
2115 ob = context.object
2116 ob.location = (x, y, z)
2117 ob.scale = (r, r, r)
2118 mat_search(cache)
2119 cache = []
2120 sphere_search = False
2121 ##################End Primitives Import##################
2122 if word == '#declare':
2123 name_search = True
2124 if name_search:
2125 cache.append(word)
2126 if word == 'mesh2':
2127 name_search = False
2128 if cache[-2] == '=':
2129 name = cache[-3]
2130 else:
2131 suffix += 1
2132 cache = []
2133 if word in {'texture', ';'}:
2134 name_search = False
2135 cache = []
2136 if word == 'vertex_vectors':
2137 verts_search = True
2138 if verts_search:
2139 cache.append(word)
2140 if word == '}':
2141 verts_search = False
2142 lenverts = cache[2]
2143 cache.pop()
2144 cache.pop(0)
2145 cache.pop(0)
2146 cache.pop(0)
2147 for i in range(int(lenverts)):
2148 x = i * 3
2149 y = (i * 3) + 1
2150 z = (i * 3) + 2
2151 verts.append(
2153 float(cache[x]),
2154 float(cache[y]),
2155 float(cache[z]),
2158 cache = []
2159 # if word == 'face_indices':
2160 # faces_search = True
2161 if word == 'texture_list': ########
2162 tex_search = True #######
2163 if tex_search: #########
2164 if (
2165 word
2166 not in {
2167 'texture_list',
2168 'texture',
2169 '{',
2170 '}',
2171 'face_indices',
2173 and word.isdigit() == False
2174 ): ##############
2175 povMats.append(word) #################
2176 if word == 'face_indices':
2177 tex_search = False ################
2178 faces_search = True
2179 if faces_search:
2180 cache.append(word)
2181 if word == '}':
2182 faces_search = False
2183 lenfaces = cache[2]
2184 cache.pop()
2185 cache.pop(0)
2186 cache.pop(0)
2187 cache.pop(0)
2188 lf = int(lenfaces)
2189 var = int(len(cache) / lf)
2190 for i in range(lf):
2191 if var == 3:
2192 v0 = i * 3
2193 v1 = i * 3 + 1
2194 v2 = i * 3 + 2
2195 faces.append(
2197 int(cache[v0]),
2198 int(cache[v1]),
2199 int(cache[v2]),
2202 if var == 4:
2203 v0 = i * 4
2204 v1 = i * 4 + 1
2205 v2 = i * 4 + 2
2206 m = i * 4 + 3
2207 materials.append((int(cache[m])))
2208 faces.append(
2210 int(cache[v0]),
2211 int(cache[v1]),
2212 int(cache[v2]),
2215 if var == 6:
2216 v0 = i * 6
2217 v1 = i * 6 + 1
2218 v2 = i * 6 + 2
2219 m0 = i * 6 + 3
2220 m1 = i * 6 + 4
2221 m2 = i * 6 + 5
2222 materials.append(
2224 int(cache[m0]),
2225 int(cache[m1]),
2226 int(cache[m2]),
2229 faces.append(
2231 int(cache[v0]),
2232 int(cache[v1]),
2233 int(cache[v2]),
2236 # mesh = pov_define_mesh(None, verts, [], faces, name, hide_geometry=False)
2237 # ob = object_utils.object_data_add(context, mesh, operator=None)
2239 me = bpy.data.meshes.new(name) ########
2240 ob = bpy.data.objects.new(name, me) ##########
2241 bpy.context.collection.objects.link(ob) #########
2242 me.from_pydata(verts, [], faces) ############
2244 for mat in bpy.data.materials: ##############
2245 blendMats.append(mat.name) #############
2246 for mName in povMats: #####################
2247 if mName not in blendMats: ###########
2248 povMat = bpy.data.materials.new(
2249 mName
2250 ) #################
2251 mat_search(cache)
2252 ob.data.materials.append(
2253 bpy.data.materials[mName]
2254 ) ###################
2255 if materials: ##################
2256 for i, val in enumerate(
2257 materials
2258 ): ####################
2259 try: ###################
2260 ob.data.polygons[
2262 ].material_index = (
2264 ) ####################
2265 except TypeError: ###################
2266 ob.data.polygons[
2268 ].material_index = int(
2269 val[0]
2270 ) ##################
2272 blendMats = [] #########################
2273 povMats = [] #########################
2274 materials = [] #########################
2275 cache = []
2276 name_search = True
2277 if name in matrixes and self.import_at_cur == False:
2278 global_matrix = Matrix.Rotation(
2279 pi / 2.0, 4, 'X'
2281 ob = bpy.context.object
2282 matrix = ob.matrix_world
2283 v = matrixes[name]
2284 matrix[0][0] = v[0]
2285 matrix[1][0] = v[1]
2286 matrix[2][0] = v[2]
2287 matrix[0][1] = v[3]
2288 matrix[1][1] = v[4]
2289 matrix[2][1] = v[5]
2290 matrix[0][2] = v[6]
2291 matrix[1][2] = v[7]
2292 matrix[2][2] = v[8]
2293 matrix[0][3] = v[9]
2294 matrix[1][3] = v[10]
2295 matrix[2][3] = v[11]
2296 matrix = global_matrix * ob.matrix_world
2297 ob.matrix_world = matrix
2298 verts = []
2299 faces = []
2301 # if word == 'pigment':
2302 # try:
2303 # #all indices have been incremented once to fit a bad test file
2304 # r,g,b,t = float(S[2]),float(S[3]),float(S[4]),float(S[5])
2305 # color = (r,g,b,t)
2307 # except (IndexError):
2308 # #all indices have been incremented once to fit alternate test file
2309 # r,g,b,t = float(S[3]),float(S[4]),float(S[5]),float(S[6])
2310 # color = (r,g,b,t)
2311 # except UnboundLocalError:
2312 # # In case no transmit is specified ? put it to 0
2313 # r,g,b,t = float(S[2]),float(S[3]),float(S[4],0)
2314 # color = (r,g,b,t)
2316 # except (ValueError):
2317 # color = (0.8,0.8,0.8,0)
2318 # pass
2320 # if colors == [] or (colors != [] and color not in colors):
2321 # colors.append(color)
2322 # name = ob.name+"_mat"
2323 # matNames.append(name)
2324 # mat = bpy.data.materials.new(name)
2325 # mat.diffuse_color = (r,g,b)
2326 # mat.alpha = 1-t
2327 # if mat.alpha != 1:
2328 # mat.use_transparency=True
2329 # ob.data.materials.append(mat)
2330 # print (colors)
2331 # else:
2332 # for i in range(len(colors)):
2333 # if color == colors[i]:
2334 # ob.data.materials.append(bpy.data.materials[matNames[i]])
2336 ##To keep Avogadro Camera angle:
2337 # for obj in bpy.context.view_layer.objects:
2338 # if obj.type == "CAMERA":
2339 # track = obj.constraints.new(type = "TRACK_TO")
2340 # track.target = ob
2341 # track.track_axis ="TRACK_NEGATIVE_Z"
2342 # track.up_axis = "UP_Y"
2343 # obj.location = (0,0,0)
2344 return {'FINISHED'}
2347 classes = (
2348 POVRAY_OT_lathe_add,
2349 POVRAY_OT_superellipsoid_add,
2350 POVRAY_OT_superellipsoid_update,
2351 POVRAY_OT_supertorus_add,
2352 POVRAY_OT_supertorus_update,
2353 POVRAY_OT_loft_add,
2354 POVRAY_OT_plane_add,
2355 POVRAY_OT_box_add,
2356 POVRAY_OT_cylinder_add,
2357 POVRAY_OT_cylinder_update,
2358 POVRAY_OT_sphere_add,
2359 POVRAY_OT_sphere_update,
2360 POVRAY_OT_cone_add,
2361 POVRAY_OT_cone_update,
2362 POVRAY_OT_isosurface_box_add,
2363 POVRAY_OT_isosurface_sphere_add,
2364 POVRAY_OT_sphere_sweep_add,
2365 POVRAY_OT_blob_add,
2366 POVRAY_OT_rainbow_add,
2367 POVRAY_OT_height_field_add,
2368 POVRAY_OT_torus_add,
2369 POVRAY_OT_torus_update,
2370 POVRAY_OT_prism_add,
2371 POVRAY_OT_parametric_add,
2372 POVRAY_OT_parametric_update,
2373 POVRAY_OT_shape_polygon_to_circle_add,
2374 ImportPOV,
2378 def register():
2379 # from bpy.utils import register_class
2381 for cls in classes:
2382 register_class(cls)
2385 def unregister():
2386 from bpy.utils import unregister_class
2388 for cls in classes:
2389 unregister_class(cls)