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 #####
21 """ Get POV-Ray specific objects In and Out of Blender """
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 (
42 from mathutils
import Vector
, Matrix
48 def pov_define_mesh(mesh
, verts
, edges
, faces
, name
, hide_geometry
=True):
49 """Generate proxy mesh."""
51 mesh
= bpy
.data
.meshes
.new(name
)
52 mesh
.from_pydata(verts
, edges
, faces
)
56 ) # Set it to True to see debug messages (helps ensure you generate valid 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
))
64 class POVRAY_OT_lathe_add(Operator
):
65 """Add the representation of POV lathe using a screw modifier."""
67 bl_idname
= "pov.addlathe"
69 bl_options
= {'REGISTER', 'UNDO'}
70 bl_description
= "adds lathe"
72 def execute(self
, context
):
75 bpy
.ops
.curve
.primitive_bezier_curve_add(
76 location
=context
.scene
.cursor
.location
,
80 ob
= context
.view_layer
.objects
.active
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]
91 mod
.show_render
= False
95 def pov_superellipsoid_define(context
, op
, ob
):
96 """Create the proxy mesh of a POV superellipsoid using the pov_superellipsoid_define() function."""
106 se_param1
= n2
# op.se_param1
107 se_param2
= n1
# op.se_param2
117 edit
= ob
.pov
.se_edit
118 se_param1
= ob
.pov
.se_param1
119 se_param2
= ob
.pov
.se_param2
124 stepSegment
= 360 / v
* pi
/ 180
130 for ring
in range(0, u
- 1):
132 for segment
in range(0, v
):
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
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
145 z
= r
* (abs(sin(angRing
)) ** n1
)
151 verts
.append((x
, y
, z
))
152 if edit
== 'TRIANGLES':
153 verts
.append((0, 0, 1))
154 verts
.append((0, 0, -1))
158 for i
in range(0, u
- 2):
160 for p
in range(0, v
):
162 face
= (m
+ p
, 1 + m
+ p
, v
+ 1 + m
+ p
, v
+ m
+ p
)
164 face
= (m
+ p
, m
, v
+ m
, v
+ m
+ p
)
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
):
172 face
= (indexDown
, i
, i
+ 1)
175 face
= (indexDown
, i
, 0)
177 for i
in range(0, v
):
179 face
= (indexUp
, i
+ indexStartDown
, i
+ indexStartDown
+ 1)
182 face
= (indexUp
, i
+ indexStartDown
, indexStartDown
)
186 for i
in range(0, v
):
190 indexUp
= len(verts
) - 1
191 for i
in range(0, v
):
192 face
.append(indexUp
- i
)
194 mesh
= pov_define_mesh(mesh
, verts
, [], faces
, "SuperEllipsoid")
197 ob
= object_utils
.object_data_add(context
, mesh
, operator
=None)
198 # engine = context.scene.render.engine what for?
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
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
237 description
="radial segmentation",
244 description
="lateral segmentation",
249 se_n1
: FloatProperty(
250 name
="Ring manipulator",
251 description
="Manipulates the shape of the Ring",
256 se_n2
: FloatProperty(
257 name
="Cross manipulator",
258 description
="Manipulates the shape of the cross-section",
263 se_edit
: EnumProperty(
265 ("NOTHING", "Nothing", ""),
266 ("NGONS", "N-Gons", ""),
267 ("TRIANGLES", "Triangles", ""),
269 name
="Fill up and down",
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)
284 "This native POV-Ray primitive won't have any vertex to show in edit mode",
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"
298 bl_description
= "Update Superellipsoid"
299 bl_options
= {'REGISTER', 'UNDO'}
300 COMPAT_ENGINES
= {'POVRAY_RENDER'}
303 def poll(cls
, context
):
304 engine
= context
.scene
.render
.engine
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)
325 def createFaces(vertIdx1
, vertIdx2
, closed
=False, flipped
=False):
327 if not vertIdx1
or not vertIdx2
:
329 if len(vertIdx1
) < 2 and len(vertIdx2
) < 2:
332 if len(vertIdx1
) != len(vertIdx2
):
333 if len(vertIdx1
) == 1 and len(vertIdx2
) > 1:
337 total
= len(vertIdx2
)
340 face
= [vertIdx1
[0], vertIdx2
[0], vertIdx2
[total
- 1]]
342 face
.append(vertIdx1
[total
- 1])
346 face
= [vertIdx2
[0], vertIdx1
[0]]
348 face
.append(vertIdx1
[total
- 1])
349 face
.append(vertIdx2
[total
- 1])
351 for num
in range(total
- 1):
354 face
= [vertIdx2
[num
], vertIdx1
[0], vertIdx2
[num
+ 1]]
365 face
= [vertIdx1
[0], vertIdx2
[num
], vertIdx2
[num
+ 1]]
384 def supertoroid(R
, r
, u
, v
, n1
, n2
):
390 s
= power(sin(i
* a
), n1
)
391 c
= power(cos(i
* a
), n1
)
393 c2
= R
+ r
* power(cos(j
* b
), n2
)
394 s2
= r
* power(sin(j
* b
), n2
)
397 ) # type as a (mathutils.Vector(c*c2,s*c2,s2))?
400 range((i
- 1) * v
, i
* v
),
401 range(i
* v
, (i
+ 1) * v
),
405 f
= createFaces(range((u
- 1) * v
, u
* v
), range(v
), closed
=True)
410 def pov_supertorus_define(context
, op
, ob
):
425 st_R
= ob
.pov
.st_major_radius
426 st_r
= ob
.pov
.st_minor_radius
429 st_n1
= ob
.pov
.st_ring
430 st_n2
= ob
.pov
.st_cross
432 st_edit
= ob
.pov
.st_edit
435 rad1
= (st_R
+ st_r
) / 2
436 rad2
= (st_R
- st_r
) / 2
438 [rad1
, rad2
] = [rad2
, rad1
]
444 verts
, faces
= supertoroid(rad1
, rad2
, st_u
, st_v
, st_n1
, st_n2
)
445 mesh
= pov_define_mesh(mesh
, verts
, [], faces
, "PovSuperTorus", True)
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
453 ob
.pov
.st_ring
= st_n1
454 ob
.pov
.st_cross
= st_n2
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'}
470 description
="The radius inside the tube",
477 description
="The radius of the tube",
484 description
="radial segmentation",
491 description
="lateral segmentation",
496 st_n1
: FloatProperty(
497 name
="Ring manipulator",
498 description
="Manipulates the shape of the Ring",
503 st_n2
: FloatProperty(
504 name
="Cross manipulator",
505 description
="Manipulates the shape of the cross-section",
511 name
="Use Int.+Ext. radii",
512 description
="Use internal and external radii",
515 st_edit
: BoolProperty(
516 name
="", description
="", default
=False, options
={'HIDDEN'}
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)
529 "This native POV-Ray primitive won't have any vertex to show in edit mode",
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"
542 bl_description
= "Update SuperTorus"
543 bl_options
= {'REGISTER', 'UNDO'}
544 COMPAT_ENGINES
= {'POVRAY_RENDER'}
547 def poll(cls
, context
):
548 engine
= context
.scene
.render
.engine
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)
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'}
581 description
="Vertical segments",
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(
594 description
="Manipulates the shape of the Ring",
599 loft_r
: FloatProperty(
600 name
="Radius", description
="Radius", default
=1, min=0.01, max=10
602 loft_height
: FloatProperty(
604 description
="Manipulates the shape of the Ring",
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
618 thick
= props
.loft_thick
619 side
= props
.loft_rings_side
620 bottom
= props
.loft_rings_bottom
621 h
= props
.loft_height
627 for i
in range(bottom
+ 1):
633 coords
.append((x
, y
, z
))
636 nurbs
= loftData
.splines
.new('NURBS')
637 nurbs
.points
.add(len(coords
) - 1)
638 for i
, coord
in enumerate(coords
):
640 nurbs
.points
[i
].co
= (x
, y
, z
, 1)
641 nurbs
.use_cyclic_u
= True
642 for i
in range(side
):
649 coords
.append((x
, y
, z
))
651 nurbs
= loftData
.splines
.new('NURBS')
652 nurbs
.points
.add(len(coords
) - 1)
653 for i
, coord
in enumerate(coords
):
655 nurbs
.points
[i
].co
= (x
, y
, z
, 1)
656 nurbs
.use_cyclic_u
= True
658 for i
in range(side
):
664 coords
.append((x
, y
, z
))
666 nurbs
= loftData
.splines
.new('NURBS')
667 nurbs
.points
.add(len(coords
) - 1)
668 for i
, coord
in enumerate(coords
):
670 nurbs
.points
[i
].co
= (x
, y
, z
, 1)
671 nurbs
.use_cyclic_u
= True
674 distB
= (r
- 0.00001) / bottom
675 for i
in range(bottom
+ 1):
681 coords
.append((x
, y
, z
))
684 nurbs
= loftData
.splines
.new('NURBS')
685 nurbs
.points
.add(len(coords
) - 1)
686 for i
, coord
in enumerate(coords
):
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
695 ob
.pov
.curveshape
= "loft"
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"
707 bl_description
= "Add Plane"
708 bl_options
= {'REGISTER', 'UNDO'}
710 def execute(self
, context
):
711 # layers = 20*[False]
713 bpy
.ops
.mesh
.primitive_plane_add(size
=100000)
715 ob
.name
= ob
.data
.name
= 'PovInfinitePlane'
716 bpy
.ops
.object.mode_set(mode
="EDIT")
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"
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"
737 bl_description
= "Add Box"
738 bl_options
= {'REGISTER', 'UNDO'}
740 def execute(self
, context
):
741 # layers = 20*[False]
743 bpy
.ops
.mesh
.primitive_cube_add()
745 ob
.name
= ob
.data
.name
= 'PovBox'
746 bpy
.ops
.object.mode_set(mode
="EDIT")
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"
758 def pov_cylinder_define(context
, op
, ob
, radius
, loc
, loc_cap
):
761 loc
= bpy
.context
.scene
.cursor
.location
764 loc_cap
[2] = loc
[2] + 2
765 vec
= Vector(loc_cap
) - Vector(loc
)
767 rot
= Vector((0, 0, 1)).rotation_difference(vec
) # Rotation from Z axis.
768 trans
= rot
@ Vector(
770 ) # Such that origin is at center of the base of the cylinder.
771 roteuler
= rot
.to_euler()
773 bpy
.ops
.object.add(type='MESH', location
=loc
)
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"
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(
791 end_fill_type
='NGON',
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
825 # layers = 20*[False]
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
833 if not props
.imported_cyl_loc
:
834 LOC_CAP
= LOC
= bpy
.context
.scene
.cursor
.location
837 LOC
= props
.imported_cyl_loc
838 LOC_CAP
= props
.imported_cyl_loc_cap
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
)
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"
858 bl_description
= "Update Cylinder"
859 bl_options
= {'REGISTER', 'UNDO'}
860 COMPAT_ENGINES
= {'POVRAY_RENDER'}
863 def poll(cls
, context
):
864 engine
= context
.scene
.render
.engine
869 and ob
.type == 'MESH'
870 and ob
.pov
.object_as
== "CYLINDER"
871 and engine
in cls
.COMPAT_ENGINES
874 def execute(self
, context
):
876 radius
= ob
.pov
.cylinder_radius
878 loc_cap
= loc
+ ob
.pov
.cylinder_location_cap
880 pov_cylinder_define(context
, None, ob
, radius
, loc
, loc_cap
)
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"""
894 loc
= bpy
.context
.scene
.cursor
.location
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
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(
910 radius
=ob
.pov
.sphere_radius
,
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')
924 bpy
.ops
.mesh
.primitive_ico_sphere_add(
925 subdivisions
=4, radius
=R
, location
=loc
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"
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
959 if ob
.pov
.imported_loc
:
960 LOC
= ob
.pov
.imported_loc
962 if not props
.imported_loc
:
963 LOC
= bpy
.context
.scene
.cursor
.location
966 LOC
= props
.imported_loc
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
)
976 # def execute(self,context):
977 ## layers = 20*[False]
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"
1001 bl_description
= "Update Sphere"
1002 bl_options
= {'REGISTER', 'UNDO'}
1003 COMPAT_ENGINES
= {'POVRAY_RENDER'}
1006 def poll(cls
, context
):
1007 engine
= context
.scene
.render
.engine
1012 and ob
.type == 'MESH'
1013 and engine
in cls
.COMPAT_ENGINES
1016 def execute(self
, context
):
1019 context
, None, context
.object, context
.object.location
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."""
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
1048 angle
= 2 * pi
/ seg
1050 for i
in range(seg
):
1055 verts
.append((xb
, yb
, zb
))
1056 verts
.append((xc
, yc
, zc
))
1058 for i
in range(seg
):
1061 faces
.append([0, 1, f
+ 1, f
])
1063 faces
.append([f
+ 2, f
+ 3, f
+ 1, f
])
1066 for i
in range(seg
- 1, -1, -1):
1069 faces
.append(base_face
)
1072 for i
in range(seg
):
1075 faces
.append(cap_face
)
1077 mesh
= pov_define_mesh(mesh
, verts
, [], faces
, "PovCone", True)
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"
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(
1101 description
="The first radius of the cone",
1108 description
="The second radius of the cone",
1115 description
="Radial segmentation of the proxy mesh",
1120 height
: FloatProperty(
1122 description
="Height of the cone",
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)
1138 "This native POV-Ray primitive won't have any vertex to show in edit mode",
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"
1151 bl_description
= "Update Cone"
1152 bl_options
= {'REGISTER', 'UNDO'}
1153 COMPAT_ENGINES
= {'POVRAY_RENDER'}
1156 def poll(cls
, context
):
1157 engine
= context
.scene
.render
.engine
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)
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]
1195 bpy
.ops
.mesh
.primitive_cube_add()
1197 bpy
.ops
.object.mode_set(mode
="EDIT")
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'
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]
1225 bpy
.ops
.mesh
.primitive_ico_sphere_add(subdivisions
=4)
1227 bpy
.ops
.object.mode_set(mode
="EDIT")
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'
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]
1256 bpy
.ops
.curve
.primitive_nurbs_curve_add()
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
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]
1282 bpy
.ops
.object.metaball_add(type='BALL')
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
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)
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
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
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(
1365 description
="Wather Level",
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
)
1380 im_name
, file_extension
= os
.path
.splitext(im_name
)
1381 hf_tex
= bpy
.data
.textures
.new('%s_hf_image' % im_name
, type='IMAGE')
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]
1388 quality
= props
.quality
1390 w
, h
= hf_tex
.image
.size
[:]
1393 bpy
.ops
.mesh
.primitive_grid_add(
1394 x_subdivisions
=w
, y_subdivisions
=h
, size
=0.5
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
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."""
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
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(
1452 bpy
.ops
.mesh
.hide(unselected
=False)
1453 bpy
.ops
.object.mode_set(mode
="OBJECT")
1456 bpy
.ops
.mesh
.primitive_torus_add(
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"
1479 bl_description
= "Add Torus"
1480 bl_options
= {'REGISTER', 'UNDO'}
1482 # XXX Keep it in sync with __init__'s torus Primitive
1484 name
="Major Segments", description
="", default
=48, min=3, max=720
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
1498 pov_torus_define(context
, self
, None)
1501 "This native POV-Ray primitive "
1502 "won't have any vertex to show in edit mode",
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"
1515 bl_description
= "Update Torus"
1516 bl_options
= {'REGISTER', 'UNDO'}
1517 COMPAT_ENGINES
= {'POVRAY_RENDER'}
1520 def poll(cls
, context
):
1521 engine
= context
.scene
.render
.engine
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)
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"
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
1569 coords
.append((x
, y
, z
))
1571 poly
= loftData
.splines
.new('POLY')
1572 poly
.points
.add(len(coords
) - 1)
1573 for i
, coord
in enumerate(coords
):
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
1583 ob
.pov
.curveshape
= "prism"
1584 ob
.name
= ob
.data
.name
= "Prism"
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."""
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
1611 # keep object rotation and location for the updated object
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(
1631 bpy
.ops
.mesh
.select_all(action
='SELECT')
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")
1640 bpy
.ops
.mesh
.primitive_xyz_function_surface(
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
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
1693 pov_parametric_define(context
, self
, None)
1696 "This native POV-Ray primitive "
1697 "won't have any vertex to show in edit mode",
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"
1710 bl_description
= "Update parametric object"
1711 bl_options
= {'REGISTER', 'UNDO'}
1712 COMPAT_ENGINES
= {'POVRAY_RENDER'}
1715 def poll(cls
, context
):
1716 engine
= context
.scene
.render
.engine
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)
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]
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
,
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()
1783 bpy
.ops
.mesh
.select_all(action
='DESELECT')
1784 bpy
.ops
.mesh
.primitive_circle_add(
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')
1795 ob
.name
= "Polygon_To_Circle"
1796 ob
.pov
.object_as
= 'POLYCIRCLE'
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")
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'}
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",
1835 def execute(self
, context
):
1836 from mathutils
import Matrix
1841 blendMats
= [] ##############
1842 povMats
= [] ##############
1848 name
= 'Mesh2_%s' % suffix
1850 verts_search
= False
1851 faces_search
= False
1852 plane_search
= False
1854 cylinder_search
= False
1855 sphere_search
= False
1857 tex_search
= False ##################
1863 # filepov = bpy.path.abspath(self.filepath) #was used for single files
1865 def mat_search(cache
):
1870 for item
, value
in enumerate(cache
):
1872 if value
== 'texture':
1875 if value
== 'pigment':
1877 if cache
[item
+ 2] in {'rgb', 'srgb'}:
1880 elif cache
[item
+ 2] in {'rgbf', 'srgbf'}:
1883 elif cache
[item
+ 2] in {'rgbt', 'srgbt'}:
1886 float(cache
[item
+ 3]),
1887 float(cache
[item
+ 4]),
1888 float(cache
[item
+ 5]),
1889 float(cache
[item
+ 6]),
1892 r
= g
= b
= t
= float(cache
[item
+ 2])
1893 color
= (r
, g
, b
, t
)
1895 elif cache
[item
+ 2] in {'rgbft', 'srgbft'}:
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
)
1909 mat
.use_transparency
= True
1910 ob
.data
.materials
.append(mat
)
1913 for i
, value
in enumerate(colors
):
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(",", " ")
1931 if lw
[0] == "object":
1934 if lw
[0] not in {"object", "matrix"}:
1936 if lw
[0] in {"matrix"}:
1951 matrixes
[index
] = value
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(";", " ; ")
1963 for i
, word
in enumerate(S
):
1964 ##################Primitives Import##################
1970 if cache
[-1] == '}':
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
)
1985 ob
.location
= (x0
, y0
, z0
)
1986 # ob.scale = (r,r,r)
1988 except (ValueError):
1997 if cache
[-1] == '}':
1999 bpy
.ops
.pov
.addplane()
2002 except (ValueError):
2005 plane_search
= False
2011 if cache
[-1] == '}':
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)
2026 bpy
.ops
.pov
.addbox()
2028 ob
.location
= center
2031 except (ValueError):
2035 if word
== 'cylinder':
2036 cylinder_search
= True
2040 if cache
[-1] == '}':
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
)
2053 vec
= Vector(imported_cyl_loc_cap
) - Vector(
2057 rot
= Vector((0, 0, 1)).rotation_difference(
2059 ) # Rotation from Z axis.
2060 trans
= rot
@ Vector(
2062 ) # Such that origin is at center of the base of the cylinder.
2063 # center = ((x0 + x1)/2,(y0 + y1)/2,(z0 + z1)/2)
2072 bpy
.ops
.pov
.addcylinder(
2074 imported_cyl_loc
=imported_cyl_loc
,
2075 imported_cyl_loc_cap
=imported_cyl_loc_cap
,
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')
2092 except (ValueError):
2095 cylinder_search
= False
2096 if word
== 'sphere':
2097 sphere_search
= True
2101 if cache
[-1] == '}':
2109 except (ValueError):
2112 x
= y
= z
= float(cache
[2])
2114 bpy
.ops
.pov
.addsphere(R
=r
, imported_loc
=(x
, y
, z
))
2116 ob
.location
= (x
, y
, z
)
2117 ob
.scale
= (r
, r
, r
)
2120 sphere_search
= False
2121 ##################End Primitives Import##################
2122 if word
== '#declare':
2128 if cache
[-2] == '=':
2133 if word
in {'texture', ';'}:
2136 if word
== 'vertex_vectors':
2141 verts_search
= False
2147 for i
in range(int(lenverts
)):
2159 # if word == 'face_indices':
2160 # faces_search = True
2161 if word
== 'texture_list': ########
2162 tex_search
= True #######
2163 if tex_search
: #########
2173 and word
.isdigit() == False
2175 povMats
.append(word
) #################
2176 if word
== 'face_indices':
2177 tex_search
= False ################
2182 faces_search
= False
2189 var
= int(len(cache
) / lf
)
2207 materials
.append((int(cache
[m
])))
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(
2252 ob
.data
.materials
.append(
2253 bpy
.data
.materials
[mName
]
2254 ) ###################
2255 if materials
: ##################
2256 for i
, val
in enumerate(
2258 ): ####################
2259 try: ###################
2262 ].material_index
= (
2264 ) ####################
2265 except TypeError: ###################
2268 ].material_index
= int(
2270 ) ##################
2272 blendMats
= [] #########################
2273 povMats
= [] #########################
2274 materials
= [] #########################
2277 if name
in matrixes
and self
.import_at_cur
== False:
2278 global_matrix
= Matrix
.Rotation(
2281 ob
= bpy
.context
.object
2282 matrix
= ob
.matrix_world
2294 matrix
[1][3] = v
[10]
2295 matrix
[2][3] = v
[11]
2296 matrix
= global_matrix
* ob
.matrix_world
2297 ob
.matrix_world
= matrix
2301 # if word == 'pigment':
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])
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])
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)
2316 # except (ValueError):
2317 # color = (0.8,0.8,0.8,0)
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)
2327 # if mat.alpha != 1:
2328 # mat.use_transparency=True
2329 # ob.data.materials.append(mat)
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")
2341 # track.track_axis ="TRACK_NEGATIVE_Z"
2342 # track.up_axis = "UP_Y"
2343 # obj.location = (0,0,0)
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
,
2354 POVRAY_OT_plane_add
,
2356 POVRAY_OT_cylinder_add
,
2357 POVRAY_OT_cylinder_update
,
2358 POVRAY_OT_sphere_add
,
2359 POVRAY_OT_sphere_update
,
2361 POVRAY_OT_cone_update
,
2362 POVRAY_OT_isosurface_box_add
,
2363 POVRAY_OT_isosurface_sphere_add
,
2364 POVRAY_OT_sphere_sweep_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
,
2379 # from bpy.utils import register_class
2386 from bpy
.utils
import unregister_class
2389 unregister_class(cls
)