Newer
Older
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
Maurice Raybaud
committed
############ To get POV-Ray specific objects In and Out of Blender ###########
import bpy
Maurice Raybaud
committed
from bpy_extras.io_utils import ImportHelper
from bpy_extras import object_utils
from bpy.utils import register_class
Maurice Raybaud
committed
from math import atan, pi, degrees, sqrt, cos, sin
from bpy.props import (
StringProperty,
BoolProperty,
IntProperty,
FloatProperty,
FloatVectorProperty,
EnumProperty,
PointerProperty,
CollectionProperty,
)
Maurice Raybaud
committed
from mathutils import (
Maurice Raybaud
committed
#import collections
Maurice Raybaud
committed
def pov_define_mesh(mesh, verts, edges, faces, name, hide_geometry=True):
Maurice Raybaud
committed
if mesh is None:
mesh = bpy.data.meshes.new(name)
mesh.from_pydata(verts, edges, faces)
mesh.update()
mesh.validate(verbose = False) # Set it to True to see debug messages (helps ensure you generate valid geometry).
Maurice Raybaud
committed
if hide_geometry:
mesh.vertices.foreach_set("hide", [True] * len(mesh.vertices))
mesh.edges.foreach_set("hide", [True] * len(mesh.edges))
mesh.polygons.foreach_set("hide", [True] * len(mesh.polygons))
return mesh
class POVRAY_OT_lathe_add(bpy.types.Operator):
"""Add the representation of POV lathe using a screw modifier."""
Maurice Raybaud
committed
bl_idname = "pov.addlathe"
bl_label = "Lathe"
bl_options = {'REGISTER','UNDO'}
bl_description = "adds lathe"
def execute(self, context):
location=context.scene.cursor.location,
ob = context.view_layer.objects.active
ob_data = ob.data
ob.name = ob_data.name = "PovLathe"
ob_data.dimensions = '2D'
ob_data.transform(Matrix.Rotation(-pi / 2.0, 4, 'Z'))
self.report({'INFO'}, "This native POV-Ray primitive")
Maurice Raybaud
committed
ob.pov.curveshape = "lathe"
bpy.ops.object.modifier_add(type='SCREW')
mod = ob.modifiers[-1]
mod.axis = 'Y'
mod.show_render = False
Maurice Raybaud
committed
return {'FINISHED'}
Maurice Raybaud
committed
def pov_superellipsoid_define(context, op, ob):
"""Create the proxy mesh of a POV superellipsoid using the pov_superellipsoid_define() function."""
Maurice Raybaud
committed
Maurice Raybaud
committed
u = op.se_u
v = op.se_v
n1 = op.se_n1
n2 = op.se_n2
edit = op.se_edit
se_param1 = n2 # op.se_param1
se_param2 = n1 # op.se_param2
Maurice Raybaud
committed
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
u = ob.pov.se_u
v = ob.pov.se_v
n1 = ob.pov.se_n1
n2 = ob.pov.se_n2
edit = ob.pov.se_edit
se_param1 = ob.pov.se_param1
se_param2 = ob.pov.se_param2
verts = []
r=1
stepSegment=360/v*pi/180
stepRing=pi/u
angSegment=0
angRing=-pi/2
step=0
for ring in range(0,u-1):
angRing += stepRing
for segment in range(0,v):
step += 1
angSegment += stepSegment
x = r*(abs(cos(angRing))**n1)*(abs(cos(angSegment))**n2)
if (cos(angRing) < 0 and cos(angSegment) > 0) or \
(cos(angRing) > 0 and cos(angSegment) < 0):
x = -x
y = r*(abs(cos(angRing))**n1)*(abs(sin(angSegment))**n2)
if (cos(angRing) < 0 and sin(angSegment) > 0) or \
(cos(angRing) > 0 and sin(angSegment) < 0):
y = -y
z = r*(abs(sin(angRing))**n1)
if sin(angRing) < 0:
z = -z
x = round(x,4)
y = round(y,4)
z = round(z,4)
verts.append((x,y,z))
if edit == 'TRIANGLES':
verts.append((0,0,1))
verts.append((0,0,-1))
faces = []
for i in range(0,u-2):
m=i*v
for p in range(0,v):
if p < v-1:
face=(m+p,1+m+p,v+1+m+p,v+m+p)
if p == v-1:
face=(m+p,m,v+m,v+m+p)
Maurice Raybaud
committed
faces.append(face)
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
if edit == 'TRIANGLES':
indexUp=len(verts)-2
indexDown=len(verts)-1
indexStartDown=len(verts)-2-v
for i in range(0,v):
if i < v-1:
face=(indexDown,i,i+1)
faces.append(face)
if i == v-1:
face=(indexDown,i,0)
faces.append(face)
for i in range(0,v):
if i < v-1:
face=(indexUp,i+indexStartDown,i+indexStartDown+1)
faces.append(face)
if i == v-1:
face=(indexUp,i+indexStartDown,indexStartDown)
faces.append(face)
if edit == 'NGONS':
face=[]
for i in range(0,v):
face.append(i)
faces.append(face)
face=[]
indexUp=len(verts)-1
for i in range(0,v):
face.append(indexUp-i)
faces.append(face)
mesh = pov_define_mesh(mesh, verts, [], faces, "SuperEllipsoid")
Maurice Raybaud
committed
if not ob:
ob = object_utils.object_data_add(context, mesh, operator=None)
#engine = context.scene.render.engine what for?
ob = context.object
ob.name = ob.data.name = "PovSuperellipsoid"
ob.pov.object_as = 'SUPERELLIPSOID'
ob.pov.se_param1 = n2
ob.pov.se_param2 = n1
ob.pov.se_u = u
ob.pov.se_v = v
ob.pov.se_n1 = n1
ob.pov.se_n2 = n2
ob.pov.se_edit = edit
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
Maurice Raybaud
committed
class POVRAY_OT_superellipsoid_add(bpy.types.Operator):
"""Add the representation of POV superellipsoid using the pov_superellipsoid_define() function."""
Maurice Raybaud
committed
bl_idname = "pov.addsuperellipsoid"
bl_label = "Add SuperEllipsoid"
bl_description = "Create a SuperEllipsoid"
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {'POVRAY_RENDER'}
# XXX Keep it in sync with __init__'s RenderPovSettingsConePrimitive
# If someone knows how to define operators' props from a func, I'd be delighted to learn it!
Maurice Raybaud
committed
name="Parameter 1",
description="",
min=0.00, max=10.0, default=0.04)
Maurice Raybaud
committed
name="Parameter 2",
description="",
min=0.00, max=10.0, default=0.04)
se_u: IntProperty(name = "U-segments",
Maurice Raybaud
committed
description = "radial segmentation",
default = 20, min = 4, max = 265)
se_v: IntProperty(name = "V-segments",
Maurice Raybaud
committed
description = "lateral segmentation",
default = 20, min = 4, max = 265)
se_n1: FloatProperty(name = "Ring manipulator",
Maurice Raybaud
committed
description = "Manipulates the shape of the Ring",
default = 1.0, min = 0.01, max = 100.0)
se_n2: FloatProperty(name = "Cross manipulator",
Maurice Raybaud
committed
description = "Manipulates the shape of the cross-section",
default = 1.0, min = 0.01, max = 100.0)
se_edit: EnumProperty(items=[("NOTHING", "Nothing", ""),
Maurice Raybaud
committed
("NGONS", "N-Gons", ""),
("TRIANGLES", "Triangles", "")],
name="Fill up and down",
description="",
default='TRIANGLES')
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
return (engine in cls.COMPAT_ENGINES)
Maurice Raybaud
committed
def execute(self,context):
pov_superellipsoid_define(context, self, None)
self.report({'INFO'}, "This native POV-Ray primitive won't have any vertex to show in edit mode")
Maurice Raybaud
committed
return {'FINISHED'}
class POVRAY_OT_superellipsoid_update(bpy.types.Operator):
"""Update the superellipsoid.
Delete its previous proxy geometry and rerun pov_superellipsoid_define() function
with the new parameters"""
Maurice Raybaud
committed
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
bl_idname = "pov.superellipsoid_update"
bl_label = "Update"
bl_description = "Update Superellipsoid"
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {'POVRAY_RENDER'}
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
ob = context.object
return (ob and ob.data and ob.type == 'MESH' and engine in cls.COMPAT_ENGINES)
def execute(self, context):
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.reveal()
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.delete(type='VERT')
bpy.ops.object.mode_set(mode="OBJECT")
pov_superellipsoid_define(context, None, context.object)
return {'FINISHED'}
def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
faces = []
if not vertIdx1 or not vertIdx2:
return None
if len(vertIdx1) < 2 and len(vertIdx2) < 2:
return None
fan = False
if (len(vertIdx1) != len(vertIdx2)):
if (len(vertIdx1) == 1 and len(vertIdx2) > 1):
fan = True
else:
return None
total = len(vertIdx2)
if closed:
if flipped:
face = [
vertIdx1[0],
vertIdx2[0],
vertIdx2[total - 1]]
if not fan:
face.append(vertIdx1[total - 1])
faces.append(face)
else:
face = [vertIdx2[0], vertIdx1[0]]
if not fan:
face.append(vertIdx1[total - 1])
face.append(vertIdx2[total - 1])
faces.append(face)
for num in range(total - 1):
if flipped:
if fan:
face = [vertIdx2[num], vertIdx1[0], vertIdx2[num + 1]]
else:
face = [vertIdx2[num], vertIdx1[num],
vertIdx1[num + 1], vertIdx2[num + 1]]
faces.append(face)
else:
if fan:
face = [vertIdx1[0], vertIdx2[num], vertIdx2[num + 1]]
else:
face = [vertIdx1[num], vertIdx2[num],
vertIdx2[num + 1], vertIdx1[num + 1]]
faces.append(face)
return faces
def power(a,b):
if a < 0:
return -((-a)**b)
return a**b
Maurice Raybaud
committed
def supertoroid(R,r,u,v,n1,n2):
a = 2*pi/u
b = 2*pi/v
verts = []
faces = []
for i in range(u):
s = power(sin(i*a),n1)
c = power(cos(i*a),n1)
for j in range(v):
c2 = R+r*power(cos(j*b),n2)
s2 = r*power(sin(j*b),n2)
verts.append((c*c2,s*c2,s2))# type as a (mathutils.Vector(c*c2,s*c2,s2))?
if i > 0:
f = createFaces(range((i-1)*v,i*v),range(i*v,(i+1)*v),closed = True)
faces.extend(f)
f = createFaces(range((u-1)*v,u*v),range(v),closed=True)
faces.extend(f)
return verts, faces
Maurice Raybaud
committed
if op:
mesh = None
st_R = op.st_R
st_r = op.st_r
st_u = op.st_u
st_v = op.st_v
st_n1 = op.st_n1
st_n2 = op.st_n2
st_ie = op.st_ie
st_edit = op.st_edit
else:
assert(ob)
mesh = ob.data
st_R = ob.pov.st_major_radius
st_r = ob.pov.st_minor_radius
st_u = ob.pov.st_u
st_v = ob.pov.st_v
st_n1 = ob.pov.st_ring
st_n2 = ob.pov.st_cross
st_ie = ob.pov.st_ie
st_edit = ob.pov.st_edit
Maurice Raybaud
committed
if st_ie:
rad1 = (st_R+st_r)/2
rad2 = (st_R-st_r)/2
if rad2 > rad1:
[rad1,rad2] = [rad2,rad1]
else:
rad1 = st_R
rad2 = st_r
if rad2 > rad1:
rad1 = rad2
verts,faces = supertoroid(rad1,
rad2,
st_u,
st_v,
st_n1,
st_n2)
mesh = pov_define_mesh(mesh, verts, [], faces, "PovSuperTorus", True)
if not ob:
ob = object_utils.object_data_add(context, mesh, operator=None)
Maurice Raybaud
committed
ob.pov.object_as = 'SUPERTORUS'
ob.pov.st_major_radius = st_R
ob.pov.st_minor_radius = st_r
ob.pov.st_u = st_u
ob.pov.st_v = st_v
ob.pov.st_ring = st_n1
ob.pov.st_cross = st_n2
ob.pov.st_ie = st_ie
ob.pov.st_edit = st_edit
Maurice Raybaud
committed
class POVRAY_OT_supertorus_add(bpy.types.Operator):
"""Add the representation of POV supertorus using the pov_supertorus_define() function."""
Maurice Raybaud
committed
bl_idname = "pov.addsupertorus"
bl_label = "Add Supertorus"
bl_description = "Create a SuperTorus"
bl_options = {'REGISTER', 'UNDO'}
st_R: FloatProperty(name = "big radius",
Maurice Raybaud
committed
description = "The radius inside the tube",
default = 1.0, min = 0.01, max = 100.0)
st_r: FloatProperty(name = "small radius",
Maurice Raybaud
committed
description = "The radius of the tube",
default = 0.3, min = 0.01, max = 100.0)
st_u: IntProperty(name = "U-segments",
Maurice Raybaud
committed
description = "radial segmentation",
default = 16, min = 3, max = 265)
st_v: IntProperty(name = "V-segments",
Maurice Raybaud
committed
description = "lateral segmentation",
default = 8, min = 3, max = 265)
st_n1: FloatProperty(name = "Ring manipulator",
Maurice Raybaud
committed
description = "Manipulates the shape of the Ring",
default = 1.0, min = 0.01, max = 100.0)
st_n2: FloatProperty(name = "Cross manipulator",
Maurice Raybaud
committed
description = "Manipulates the shape of the cross-section",
default = 1.0, min = 0.01, max = 100.0)
st_ie: BoolProperty(name = "Use Int.+Ext. radii",
Maurice Raybaud
committed
description = "Use internal and external radii",
default = False)
Maurice Raybaud
committed
description="",
default=False,
Maurice Raybaud
committed
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
return (engine in cls.COMPAT_ENGINES)
def execute(self, context):
pov_supertorus_define(context, self, None)
self.report({'INFO'}, "This native POV-Ray primitive won't have any vertex to show in edit mode")
return {'FINISHED'}
Maurice Raybaud
committed
class POVRAY_OT_supertorus_update(bpy.types.Operator):
"""Update the supertorus.
Delete its previous proxy geometry and rerun pov_supetorus_define() function
with the new parameters"""
Maurice Raybaud
committed
bl_idname = "pov.supertorus_update"
bl_label = "Update"
bl_description = "Update SuperTorus"
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {'POVRAY_RENDER'}
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
ob = context.object
return (ob and ob.data and ob.type == 'MESH' and engine in cls.COMPAT_ENGINES)
def execute(self, context):
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.reveal()
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.delete(type='VERT')
bpy.ops.object.mode_set(mode="OBJECT")
pov_supertorus_define(context, None, context.object)
return {'FINISHED'}
#########################################################################################################
class POVRAY_OT_loft_add(bpy.types.Operator):
"""Create the representation of POV loft using Blender curves."""
Maurice Raybaud
committed
bl_idname = "pov.addloft"
bl_label = "Add Loft Data"
bl_description = "Create a Curve data for Meshmaker"
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {'POVRAY_RENDER'}
loft_n: IntProperty(name = "Segments",
Maurice Raybaud
committed
description = "Vertical segments",
default = 16, min = 3, max = 720)
loft_rings_bottom: IntProperty(name = "Bottom",
Maurice Raybaud
committed
description = "Bottom rings",
default = 5, min = 2, max = 100)
loft_rings_side: IntProperty(name = "Side",
Maurice Raybaud
committed
description = "Side rings",
default = 10, min = 2, max = 100)
loft_thick: FloatProperty(name = "Thickness",
Maurice Raybaud
committed
description = "Manipulates the shape of the Ring",
default = 0.3, min = 0.01, max = 1.0)
loft_r: FloatProperty(name = "Radius",
Maurice Raybaud
committed
description = "Radius",
default = 1, min = 0.01, max = 10)
loft_height: FloatProperty(name = "Height",
Maurice Raybaud
committed
description = "Manipulates the shape of the Ring",
default = 2, min = 0.01, max = 10.0)
def execute(self,context):
Maurice Raybaud
committed
props = self.properties
loftData = bpy.data.curves.new('Loft', type='CURVE')
loftData.dimensions = '3D'
loftData.resolution_u = 2
# loftData.show_normal_face = False # deprecated in 2.8
Maurice Raybaud
committed
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
n=props.loft_n
thick = props.loft_thick
side = props.loft_rings_side
bottom = props.loft_rings_bottom
h = props.loft_height
r = props.loft_r
distB = r/bottom
r0 = 0.00001
z = -h/2
print("New")
for i in range(bottom+1):
coords = []
angle = 0
for p in range(n):
x = r0*cos(angle)
y = r0*sin(angle)
coords.append((x,y,z))
angle+=pi*2/n
r0+=distB
nurbs = loftData.splines.new('NURBS')
nurbs.points.add(len(coords)-1)
for i, coord in enumerate(coords):
x,y,z = coord
nurbs.points[i].co = (x, y, z, 1)
nurbs.use_cyclic_u = True
for i in range(side):
z+=h/side
coords = []
angle = 0
for p in range(n):
x = r*cos(angle)
y = r*sin(angle)
coords.append((x,y,z))
angle+=pi*2/n
nurbs = loftData.splines.new('NURBS')
nurbs.points.add(len(coords)-1)
for i, coord in enumerate(coords):
x,y,z = coord
nurbs.points[i].co = (x, y, z, 1)
nurbs.use_cyclic_u = True
r-=thick
for i in range(side):
coords = []
angle = 0
for p in range(n):
x = r*cos(angle)
y = r*sin(angle)
coords.append((x,y,z))
angle+=pi*2/n
nurbs = loftData.splines.new('NURBS')
nurbs.points.add(len(coords)-1)
for i, coord in enumerate(coords):
x,y,z = coord
nurbs.points[i].co = (x, y, z, 1)
nurbs.use_cyclic_u = True
z-=h/side
z = (-h/2) + thick
distB = (r-0.00001)/bottom
for i in range(bottom+1):
coords = []
angle = 0
for p in range(n):
x = r*cos(angle)
y = r*sin(angle)
coords.append((x,y,z))
angle+=pi*2/n
r-=distB
nurbs = loftData.splines.new('NURBS')
nurbs.points.add(len(coords)-1)
for i, coord in enumerate(coords):
x,y,z = coord
nurbs.points[i].co = (x, y, z, 1)
nurbs.use_cyclic_u = True
ob = bpy.data.objects.new('Loft_shape', loftData)
scn = bpy.context.scene
Maurice Raybaud
committed
ob.pov.curveshape = "loft"
return {'FINISHED'}
class POVRAY_OT_plane_add(bpy.types.Operator):
"""Add the representation of POV infinite plane using just a very big Blender Plane.
Flag its primitive type with a specific pov.object_as attribute and lock edit mode
to keep proxy consistency by hiding edit geometry."""
Maurice Raybaud
committed
bl_idname = "pov.addplane"
bl_label = "Plane"
bl_description = "Add Plane"
bl_options = {'REGISTER', 'UNDO'}
def execute(self,context):
#layers = 20*[False]
#layers[0] = True
bpy.ops.mesh.primitive_plane_add(size = 100000)
Maurice Raybaud
committed
ob = context.object
ob.name = ob.data.name = 'PovInfinitePlane'
bpy.ops.object.mode_set(mode="EDIT")
self.report({'INFO'}, "This native POV-Ray primitive "
Maurice Raybaud
committed
"won't have any vertex to show in edit mode")
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
bpy.ops.object.shade_smooth()
ob.pov.object_as = "PLANE"
return {'FINISHED'}
Maurice Raybaud
committed
class POVRAY_OT_box_add(bpy.types.Operator):
"""Add the representation of POV box using a simple Blender mesh cube.
Flag its primitive type with a specific pov.object_as attribute and lock edit mode
to keep proxy consistency by hiding edit geometry."""
Maurice Raybaud
committed
bl_idname = "pov.addbox"
bl_label = "Box"
bl_description = "Add Box"
bl_options = {'REGISTER', 'UNDO'}
def execute(self,context):
# layers = 20*[False]
# layers[0] = True
bpy.ops.mesh.primitive_cube_add()
Maurice Raybaud
committed
ob = context.object
ob.name = ob.data.name = 'PovBox'
bpy.ops.object.mode_set(mode="EDIT")
self.report({'INFO'}, "This native POV-Ray primitive "
Maurice Raybaud
committed
"won't have any vertex to show in edit mode")
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
ob.pov.object_as = "BOX"
return {'FINISHED'}
Maurice Raybaud
committed
def pov_cylinder_define(context, op, ob, radius, loc, loc_cap):
if op:
R = op.R
loc = bpy.context.scene.cursor.location
Maurice Raybaud
committed
loc_cap[0] = loc[0]
loc_cap[1] = loc[1]
loc_cap[2] = (loc[2]+2)
vec = Vector(loc_cap) - Vector(loc)
depth = vec.length
rot = Vector((0, 0, 1)).rotation_difference(vec) # Rotation from Z axis.
trans = rot @ Vector((0, 0, depth / 2)) # Such that origin is at center of the base of the cylinder.
Maurice Raybaud
committed
roteuler = rot.to_euler()
if not ob:
bpy.ops.object.add(type='MESH', location=loc)
ob = context.object
ob.name = ob.data.name = "PovCylinder"
ob.pov.cylinder_radius = radius
ob.pov.cylinder_location_cap = vec
ob.pov.object_as = "CYLINDER"
else:
ob.location = loc
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.reveal()
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.delete(type='VERT')
bpy.ops.mesh.primitive_cylinder_add(radius=radius, depth=depth, location=loc, rotation=roteuler, end_fill_type='NGON') #'NOTHING'
bpy.ops.transform.translate(value=trans)
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
bpy.ops.object.shade_smooth()
Maurice Raybaud
committed
class POVRAY_OT_cylinder_add(bpy.types.Operator):
"""Add the representation of POV cylinder using pov_cylinder_define() function.
Use imported_cyl_loc when this operator is run by POV importer."""
Maurice Raybaud
committed
bl_idname = "pov.addcylinder"
bl_label = "Cylinder"
bl_description = "Add Cylinder"
bl_options = {'REGISTER', 'UNDO'}
Maurice Raybaud
committed
# XXX Keep it in sync with __init__'s cylinder Primitive
R: FloatProperty(name="Cylinder radius", min=0.00, max=10.0, default=1.0)
Maurice Raybaud
committed
imported_cyl_loc: FloatVectorProperty(
Maurice Raybaud
committed
name="Imported Pov base location",
Maurice Raybaud
committed
imported_cyl_loc_cap: FloatVectorProperty(
Maurice Raybaud
committed
name="Imported Pov cap location",
Maurice Raybaud
committed
default=(0.0, 0.0, 2.0))
Maurice Raybaud
committed
def execute(self,context):
Maurice Raybaud
committed
props = self.properties
R = props.R
Maurice Raybaud
committed
if ob:
if ob.pov.imported_cyl_loc:
LOC = ob.pov.imported_cyl_loc
if ob.pov.imported_cyl_loc_cap:
LOC_CAP = ob.pov.imported_cyl_loc_cap
else:
if not props.imported_cyl_loc:
LOC_CAP = LOC = bpy.context.scene.cursor.location
Maurice Raybaud
committed
LOC_CAP[2] += 2.0
else:
LOC = props.imported_cyl_loc
LOC_CAP = props.imported_cyl_loc_cap
self.report({'INFO'}, "This native POV-Ray primitive "
Maurice Raybaud
committed
pov_cylinder_define(context, self, None, self.R, LOC, LOC_CAP)
return {'FINISHED'}
class POVRAY_OT_cylinder_update(bpy.types.Operator):
"""Update the POV cylinder.
Delete its previous proxy geometry and rerun pov_cylinder_define() function
with the new parameters"""
Maurice Raybaud
committed
bl_idname = "pov.cylinder_update"
bl_label = "Update"
bl_description = "Update Cylinder"
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {'POVRAY_RENDER'}
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
Maurice Raybaud
committed
ob = context.object
Maurice Raybaud
committed
return (ob and ob.data and ob.type == 'MESH' and ob.pov.object_as == "CYLINDER" and engine in cls.COMPAT_ENGINES)
def execute(self, context):
ob = context.object
radius = ob.pov.cylinder_radius
loc = ob.location
loc_cap = loc + ob.pov.cylinder_location_cap
pov_cylinder_define(context, None, ob, radius, loc, loc_cap)
Maurice Raybaud
committed
return {'FINISHED'}
Maurice Raybaud
committed
Maurice Raybaud
committed
################################SPHERE##########################################
def pov_sphere_define(context, op, ob, loc):
"""create the representation of POV sphere using a Blender icosphere.
Maurice Raybaud
committed
Its nice platonic solid curvature better represents pov rendertime
tesselation than a UV sphere"""
if op:
R = op.R
loc = bpy.context.scene.cursor.location
else:
assert(ob)
R = ob.pov.sphere_radius
#keep object rotation and location for the add object operator
obrot = ob.rotation_euler
#obloc = ob.location
obscale = ob.scale
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.reveal()
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.delete(type='VERT')
bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=4, radius=ob.pov.sphere_radius, location=loc, rotation=obrot)
#bpy.ops.transform.rotate(axis=obrot,orient_type='GLOBAL')
bpy.ops.transform.resize(value=obscale)
#bpy.ops.transform.rotate(axis=obrot, proportional_size=1)
Maurice Raybaud
committed
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
bpy.ops.object.shade_smooth()
#bpy.ops.transform.rotate(axis=obrot,orient_type='GLOBAL')
if not ob:
bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=4, radius=R, location=loc)
ob = context.object
ob.name = ob.data.name = "PovSphere"
ob.pov.object_as = "SPHERE"
ob.pov.sphere_radius = R
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
Maurice Raybaud
committed
Maurice Raybaud
committed
class POVRAY_OT_sphere_add(bpy.types.Operator):
"""Add the representation of POV sphere using pov_sphere_define() function.
Use imported_loc when this operator is run by POV importer."""
Maurice Raybaud
committed
bl_idname = "pov.addsphere"
bl_label = "Sphere"
bl_description = "Add Sphere Shape"
bl_options = {'REGISTER', 'UNDO'}
# XXX Keep it in sync with __init__'s torus Primitive
R: FloatProperty(name="Sphere radius",min=0.00, max=10.0, default=0.5)
imported_loc: FloatVectorProperty(
Maurice Raybaud
committed
name="Imported Pov location",
Maurice Raybaud
committed
default=(0.0, 0.0, 0.0))
Maurice Raybaud
committed
def execute(self,context):
props = self.properties
R = props.R
ob = context.object
Maurice Raybaud
committed
if ob:
if ob.pov.imported_loc:
LOC = ob.pov.imported_loc
else:
Maurice Raybaud
committed
if not props.imported_loc:
LOC = bpy.context.scene.cursor.location
Maurice Raybaud
committed
else:
self.report({'INFO'}, "This native POV-Ray primitive "
Maurice Raybaud
committed
pov_sphere_define(context, self, None, LOC)
Maurice Raybaud
committed
Maurice Raybaud
committed
return {'FINISHED'}
Maurice Raybaud
committed
# def execute(self,context):
Maurice Raybaud
committed
# bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=4, radius=ob.pov.sphere_radius)
Maurice Raybaud
committed
# ob = context.object
# bpy.ops.object.mode_set(mode="EDIT")
# self.report({'INFO'}, "This native POV-Ray primitive "
Maurice Raybaud
committed
# "won't have any vertex to show in edit mode")
# bpy.ops.mesh.hide(unselected=False)
# bpy.ops.object.mode_set(mode="OBJECT")
# bpy.ops.object.shade_smooth()
# ob.pov.object_as = "SPHERE"
# ob.name = ob.data.name = 'PovSphere'
# return {'FINISHED'}
class POVRAY_OT_sphere_update(bpy.types.Operator):
"""Update the POV sphere.
Delete its previous proxy geometry and rerun pov_sphere_define() function
with the new parameters"""
Maurice Raybaud
committed
bl_idname = "pov.sphere_update"
bl_label = "Update"
bl_description = "Update Sphere"
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {'POVRAY_RENDER'}
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
ob = context.object
return (ob and ob.data and ob.type == 'MESH' and engine in cls.COMPAT_ENGINES)
def execute(self, context):
pov_sphere_define(context, None, context.object,context.object.location)
Maurice Raybaud
committed
####################################CONE#######################################
def pov_cone_define(context, op, ob):
"""Add the representation of POV cone using pov_define_mesh() function.
Blender cone does not offer the same features such as a second radius."""
Maurice Raybaud
committed
verts = []
faces = []
if op:
mesh = None
base = op.base
cap = op.cap
seg = op.seg
height = op.height
else:
assert(ob)
mesh = ob.data
base = ob.pov.cone_base_radius
cap = ob.pov.cone_cap_radius
seg = ob.pov.cone_segments
Maurice Raybaud
committed
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
zc = height / 2
zb = -zc
angle = 2 * pi / seg
t = 0
for i in range(seg):
xb = base * cos(t)
yb = base * sin(t)
xc = cap * cos(t)
yc = cap * sin(t)
verts.append((xb, yb, zb))
verts.append((xc, yc, zc))
t += angle
for i in range(seg):
f = i * 2
if i == seg - 1:
faces.append([0, 1, f + 1, f])
else:
faces.append([f + 2, f + 3, f + 1, f])
if base != 0:
base_face = []
for i in range(seg - 1, -1, -1):
p = i * 2
base_face.append(p)
faces.append(base_face)
if cap != 0:
cap_face = []
for i in range(seg):
p = i * 2 + 1
cap_face.append(p)
faces.append(cap_face)
mesh = pov_define_mesh(mesh, verts, [], faces, "PovCone", True)
if not ob:
ob = object_utils.object_data_add(context, mesh, operator=None)
Maurice Raybaud
committed
ob.pov.object_as = "CONE"
ob.pov.cone_base_radius = base
ob.pov.cone_cap_radius = cap
ob.pov.cone_height = height
ob.pov.cone_base_z = zb
ob.pov.cone_cap_z = zc
class POVRAY_OT_cone_add(bpy.types.Operator):
"""Add the representation of POV cone using pov_cone_define() function."""
Maurice Raybaud
committed
bl_idname = "pov.cone_add"
bl_label = "Cone"
bl_description = "Add Cone"
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {'POVRAY_RENDER'}
# XXX Keep it in sync with __init__.py's RenderPovSettingsConePrimitive
Maurice Raybaud
committed
# If someone knows how to define operators' props from a func, I'd be delighted to learn it!
Maurice Raybaud
committed
name = "Base radius", description = "The first radius of the cone",
default = 1.0, min = 0.01, max = 100.0)
Maurice Raybaud
committed
name = "Cap radius", description = "The second radius of the cone",
default = 0.3, min = 0.0, max = 100.0)
Maurice Raybaud
committed
name = "Segments", description = "Radial segmentation of the proxy mesh",
default = 16, min = 3, max = 265)
Maurice Raybaud
committed
name = "Height", description = "Height of the cone",
default = 2.0, min = 0.01, max = 100.0)
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
return (engine in cls.COMPAT_ENGINES)
def execute(self, context):
pov_cone_define(context, self, None)
self.report({'INFO'}, "This native POV-Ray primitive won't have any vertex to show in edit mode")
Maurice Raybaud
committed
return {'FINISHED'}
class POVRAY_OT_cone_update(bpy.types.Operator):
"""Update the POV cone.
Delete its previous proxy geometry and rerun pov_cone_define() function
with the new parameters"""
Maurice Raybaud
committed
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
bl_idname = "pov.cone_update"
bl_label = "Update"
bl_description = "Update Cone"
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {'POVRAY_RENDER'}
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
ob = context.object
return (ob and ob.data and ob.type == 'MESH' and engine in cls.COMPAT_ENGINES)
def execute(self, context):
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.reveal()
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.delete(type='VERT')
bpy.ops.object.mode_set(mode="OBJECT")
pov_cone_define(context, None, context.object)
return {'FINISHED'}
########################################ISOSURFACES##################################
Maurice Raybaud
committed
class POVRAY_OT_isosurface_box_add(bpy.types.Operator):
"""Add the representation of POV isosurface box using also just a Blender mesh cube.
Flag its primitive type with a specific pov.object_as attribute and lock edit mode
to keep proxy consistency by hiding edit geometry."""
Maurice Raybaud
committed
bl_idname = "pov.addisosurfacebox"
bl_label = "Isosurface Box"
bl_description = "Add Isosurface contained by Box"
bl_options = {'REGISTER', 'UNDO'}
def execute(self,context):
#layers = 20*[False]
#layers[0] = True
bpy.ops.mesh.primitive_cube_add()
Maurice Raybaud
committed
ob = context.object
bpy.ops.object.mode_set(mode="EDIT")
self.report({'INFO'}, "This native POV-Ray primitive "
Maurice Raybaud
committed
"won't have any vertex to show in edit mode")
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
ob.pov.object_as = "ISOSURFACE"
ob.pov.contained_by = 'box'
ob.name = 'PovIsosurfaceBox'
Maurice Raybaud
committed
return {'FINISHED'}
class POVRAY_OT_isosurface_sphere_add(bpy.types.Operator):
"""Add the representation of POV isosurface sphere by a Blender mesh icosphere.
Flag its primitive type with a specific pov.object_as attribute and lock edit mode
to keep proxy consistency by hiding edit geometry."""
Maurice Raybaud
committed
bl_idname = "pov.addisosurfacesphere"
bl_label = "Isosurface Sphere"
bl_description = "Add Isosurface contained by Sphere"
bl_options = {'REGISTER', 'UNDO'}
def execute(self,context):
#layers = 20*[False]
#layers[0] = True
bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=4)
Maurice Raybaud
committed
ob = context.object
bpy.ops.object.mode_set(mode="EDIT")
self.report({'INFO'}, "This native POV-Ray primitive "
Maurice Raybaud
committed
"won't have any vertex to show in edit mode")
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
bpy.ops.object.shade_smooth()
ob.pov.object_as = "ISOSURFACE"
ob.pov.contained_by = 'sphere'
ob.name = 'PovIsosurfaceSphere'
Maurice Raybaud
committed
return {'FINISHED'}
class POVRAY_OT_sphere_sweep_add(bpy.types.Operator):
"""Add the representation of POV sphere_sweep using a Blender NURBS curve.
Flag its primitive type with a specific ob.pov.curveshape attribute and
leave access to edit mode to keep user editable handles."""
Maurice Raybaud
committed
bl_idname = "pov.addspheresweep"
bl_label = "Sphere Sweep"
bl_description = "Create Sphere Sweep along curve"
bl_options = {'REGISTER', 'UNDO'}
def execute(self,context):
#layers = 20*[False]
#layers[0] = True
bpy.ops.curve.primitive_nurbs_curve_add()
Maurice Raybaud
committed
ob = context.object
ob.name = ob.data.name = "PovSphereSweep"
ob.pov.curveshape = "sphere_sweep"
ob.data.bevel_depth = 0.02
ob.data.bevel_resolution = 4
ob.data.fill_mode = 'FULL'
#ob.data.splines[0].order_u = 4
return {'FINISHED'}
class POVRAY_OT_blob_add(bpy.types.Operator):
"""Add the representation of POV blob using a Blender meta ball.
No need to flag its primitive type as meta are exported to blobs
and leave access to edit mode to keep user editable thresholds."""
Maurice Raybaud
committed
bl_idname = "pov.addblobsphere"
bl_label = "Blob Sphere"
bl_description = "Add Blob Sphere"
bl_options = {'REGISTER', 'UNDO'}
def execute(self,context):
#layers = 20*[False]
#layers[0] = True
bpy.ops.object.metaball_add(type = 'BALL')
Maurice Raybaud
committed
ob = context.object
ob.name = "PovBlob"
Maurice Raybaud
committed
return {'FINISHED'}
class POVRAY_OT_rainbow_add(bpy.types.Operator):
"""Add the representation of POV rainbow using a Blender spot light.
Rainbows indeed propagate along a visibility cone.
Flag its primitive type with a specific ob.pov.object_as attribute
and leave access to edit mode to keep user editable handles.
Add a constraint to orient it towards camera because POV Rainbows
are view dependant and having it always initially visible is less
confusing """
Maurice Raybaud
committed
bl_idname = "pov.addrainbow"
bl_label = "Rainbow"
bl_description = "Add Rainbow"
bl_options = {'REGISTER', 'UNDO'}
Maurice Raybaud
committed
def execute(self,context):
cam = context.scene.camera
bpy.ops.object.light_add(type='SPOT', radius=1)
Maurice Raybaud
committed
ob = context.object
ob.data.show_cone = False
ob.data.spot_blend = 0.5
# ob.data.shadow_buffer_clip_end = 0 # deprecated in 2.8
Maurice Raybaud
committed
ob.data.shadow_buffer_clip_start = 4*cam.location.length
ob.data.distance = cam.location.length
Maurice Raybaud
committed
ob.name = ob.data.name = "PovRainbow"
ob.pov.object_as = "RAINBOW"
Maurice Raybaud
committed
#obj = context.object
bpy.ops.object.constraint_add(type='DAMPED_TRACK')
ob.constraints["Damped Track"].target = cam
ob.constraints["Damped Track"].track_axis = 'TRACK_NEGATIVE_Z'
ob.location = -cam.location
#refocus on the actual rainbow
bpy.context.view_layer.objects.active = ob
Maurice Raybaud
committed
return {'FINISHED'}
class POVRAY_OT_height_field_add(bpy.types.Operator, ImportHelper):
"""Add the representation of POV height_field using a displaced grid.
texture slot fix and displace modifier will be needed because noise
displace operator was deprecated in 2.8"""
Maurice Raybaud
committed
bl_idname = "pov.addheightfield"
bl_label = "Height Field"
bl_description = "Add Height Field "
bl_options = {'REGISTER', 'UNDO'}
Maurice Raybaud
committed
# XXX Keep it in sync with __init__'s hf Primitive
# filename_ext = ".png"
Maurice Raybaud
committed
# filter_glob = StringProperty(
# 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",
# options={'HIDDEN'},
# )
quality: IntProperty(name = "Quality",
Maurice Raybaud
committed
description = "",
default = 100, min = 1, max = 100)
hf_filename: StringProperty(maxlen = 1024)
Maurice Raybaud
committed
name="Gamma",
description="Gamma",
min=0.0001, max=20.0, default=1.0)
Maurice Raybaud
committed
name="Premultiplied",
description="Premultiplied",
default=True)
Maurice Raybaud
committed
name="Smooth",
description="Smooth",
default=False)
Maurice Raybaud
committed
name="Water Level",
description="Wather Level",
min=0.00, max=1.00, default=0.0)
Maurice Raybaud
committed
name="Hierarchy",
description="Height field hierarchy",
default=True)
def execute(self,context):
props = self.properties
impath = bpy.path.abspath(self.filepath)
img = bpy.data.images.load(impath)
im_name = img.name
im_name, file_extension = os.path.splitext(im_name)
hf_tex = bpy.data.textures.new('%s_hf_image'%im_name, type = 'IMAGE')
hf_tex.image = img
mat = bpy.data.materials.new('Tex_%s_hf'%im_name)
hf_slot = mat.pov_texture_slots.add()
hf_slot.texture = hf_tex.name
Maurice Raybaud
committed
quality = props.quality
res = 100/quality
w,h = hf_tex.image.size[:]
w = int(w/res)
h = int(h/res)
bpy.ops.mesh.primitive_grid_add(x_subdivisions=w, y_subdivisions=h,size = 0.5)
Maurice Raybaud
committed
ob = context.object
ob.name = ob.data.name = '%s'%im_name
ob.data.materials.append(mat)
bpy.ops.object.mode_set(mode="EDIT")
# bpy.ops.mesh.noise(factor=1) # TODO replace by a displace modifier as noise deprecated in 2.8
Maurice Raybaud
committed
bpy.ops.object.mode_set(mode="OBJECT")
Maurice Raybaud
committed
#bpy.ops.object.material_slot_remove()
#material just left there for now
Maurice Raybaud
committed
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
ob.pov.object_as = 'HEIGHT_FIELD'
ob.pov.hf_filename = impath
return {'FINISHED'}
Maurice Raybaud
committed
############################TORUS############################################
def pov_torus_define(context, op, ob):
"""Add the representation of POV torus using just a Blender torus.
But flag its primitive type with a specific pov.object_as attribute and lock edit mode
to keep proxy consistency by hiding edit geometry."""
if op:
mas = op.mas
mis = op.mis
mar = op.mar
mir = op.mir
else:
assert(ob)
mas = ob.pov.torus_major_segments
mis = ob.pov.torus_minor_segments
mar = ob.pov.torus_major_radius
mir = ob.pov.torus_minor_radius
#keep object rotation and location for the add object operator
obrot = ob.rotation_euler
obloc = ob.location
Maurice Raybaud
committed
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.reveal()
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.delete(type='VERT')
bpy.ops.mesh.primitive_torus_add(rotation = obrot, location = obloc, major_segments=mas, minor_segments=mis,major_radius=mar, minor_radius=mir)
Maurice Raybaud
committed
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
if not ob:
bpy.ops.mesh.primitive_torus_add(major_segments=mas, minor_segments=mis,major_radius=mar, minor_radius=mir)
ob = context.object
ob.name = ob.data.name = "PovTorus"
ob.pov.object_as = "TORUS"
ob.pov.torus_major_segments = mas
ob.pov.torus_minor_segments = mis
ob.pov.torus_major_radius = mar
ob.pov.torus_minor_radius = mir
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
Maurice Raybaud
committed
class POVRAY_OT_torus_add(bpy.types.Operator):
"""Add the representation of POV torus using using pov_torus_define() function."""
Maurice Raybaud
committed
bl_idname = "pov.addtorus"
bl_label = "Torus"
bl_description = "Add Torus"
bl_options = {'REGISTER', 'UNDO'}
Maurice Raybaud
committed
# XXX Keep it in sync with __init__'s torus Primitive
mas: IntProperty(name = "Major Segments",
Maurice Raybaud
committed
description = "",
default = 48, min = 3, max = 720)
mis: IntProperty(name = "Minor Segments",
Maurice Raybaud
committed
description = "",
default = 12, min = 3, max = 720)
mar: FloatProperty(name = "Major Radius",
Maurice Raybaud
committed
description = "",
default = 1.0)
mir: FloatProperty(name = "Minor Radius",
Maurice Raybaud
committed
description = "",
default = 0.25)
def execute(self,context):
props = self.properties
mar = props.mar
mir = props.mir
mas = props.mas
mis = props.mis
pov_torus_define(context, self, None)
self.report({'INFO'}, "This native POV-Ray primitive "
Maurice Raybaud
committed
"won't have any vertex to show in edit mode")
return {'FINISHED'}
class POVRAY_OT_torus_update(bpy.types.Operator):
"""Update the POV torus.
Delete its previous proxy geometry and rerun pov_torus_define() function
with the new parameters"""
Maurice Raybaud
committed
bl_idname = "pov.torus_update"
bl_label = "Update"
bl_description = "Update Torus"
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {'POVRAY_RENDER'}
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
ob = context.object
return (ob and ob.data and ob.type == 'MESH' and engine in cls.COMPAT_ENGINES)
def execute(self, context):
pov_torus_define(context, None, context.object)
Maurice Raybaud
committed
###################################################################################
class POVRAY_OT_prism_add(bpy.types.Operator):
"""Add the representation of POV prism using using an extruded curve."""
Maurice Raybaud
committed
bl_idname = "pov.addprism"
bl_label = "Prism"
bl_description = "Create Prism"
bl_options = {'REGISTER', 'UNDO'}
prism_n: IntProperty(name = "Sides",
Maurice Raybaud
committed
description = "Number of sides",
default = 5, min = 3, max = 720)
prism_r: FloatProperty(name = "Radius",
Maurice Raybaud
committed
description = "Radius",
default = 1.0)
def execute(self,context):
Maurice Raybaud
committed
props = self.properties
loftData = bpy.data.curves.new('Prism', type='CURVE')
loftData.dimensions = '2D'
loftData.resolution_u = 2
Maurice Raybaud
committed
loftData.extrude = 2
n=props.prism_n
r=props.prism_r
coords = []
z = 0
angle = 0
for p in range(n):
x = r*cos(angle)
y = r*sin(angle)
coords.append((x,y,z))
angle+=pi*2/n
poly = loftData.splines.new('POLY')
poly.points.add(len(coords)-1)
for i, coord in enumerate(coords):
x,y,z = coord
poly.points[i].co = (x, y, z, 1)
poly.use_cyclic_u = True
ob = bpy.data.objects.new('Prism_shape', loftData)
scn = bpy.context.scene
context.view_layer.objects.active = ob
Maurice Raybaud
committed
ob.pov.curveshape = "prism"
ob.name = ob.data.name = "Prism"
return {'FINISHED'}
Maurice Raybaud
committed
##############################PARAMETRIC######################################
"""Add the representation of POV parametric surfaces by math surface from add mesh extra objects addon."""
Maurice Raybaud
committed
if op:
u_min = op.u_min
u_max = op.u_max
v_min = op.v_min
v_max = op.v_max
x_eq = op.x_eq
y_eq = op.y_eq
z_eq = op.z_eq
Maurice Raybaud
committed
else:
assert(ob)
u_min = ob.pov.u_min
u_max = ob.pov.u_max
v_min = ob.pov.v_min
v_max = ob.pov.v_max
x_eq = ob.pov.x_eq
y_eq = ob.pov.y_eq
z_eq = ob.pov.z_eq
#keep object rotation and location for the updated object
obloc = ob.location
obrot = ob.rotation_euler # In radians
#Parametric addon has no loc rot, some extra work is needed
#in case cursor has moved
curloc = bpy.context.scene.cursor.location
Maurice Raybaud
committed
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.reveal()
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.delete(type='VERT')
bpy.ops.mesh.primitive_xyz_function_surface(x_eq=x_eq, y_eq=y_eq, z_eq=z_eq, range_u_min=u_min, range_u_max=u_max, range_v_min=v_min, range_v_max=v_max)
bpy.ops.mesh.select_all(action='SELECT')
#extra work:
bpy.ops.transform.translate(value=(obloc-curloc), proportional_size=1)
bpy.ops.transform.rotate(axis=obrot, proportional_size=1)
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
if not ob:
bpy.ops.mesh.primitive_xyz_function_surface(x_eq=x_eq, y_eq=y_eq, z_eq=z_eq, range_u_min=u_min, range_u_max=u_max, range_v_min=v_min, range_v_max=v_max)
ob = context.object
ob.name = ob.data.name = "PovParametric"
ob.pov.object_as = "PARAMETRIC"
ob.pov.u_min = u_min
ob.pov.u_max = u_max
ob.pov.v_min = v_min
ob.pov.v_max = v_max
ob.pov.x_eq = x_eq
ob.pov.y_eq = y_eq
ob.pov.z_eq = z_eq
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
Maurice Raybaud
committed
class POVRAY_OT_parametric_add(bpy.types.Operator):
"""Add the representation of POV parametric surfaces using pov_parametric_define() function."""
Maurice Raybaud
committed
bl_idname = "pov.addparametric"
bl_label = "Parametric"
bl_description = "Add Paramertic"
bl_options = {'REGISTER', 'UNDO'}
# XXX Keep it in sync with __init__'s Parametric primitive
u_min: FloatProperty(name = "U Min",
Maurice Raybaud
committed
description = "",
default = 0.0)
v_min: FloatProperty(name = "V Min",
Maurice Raybaud
committed
description = "",
default = 0.0)
u_max: FloatProperty(name = "U Max",
Maurice Raybaud
committed
description = "",
default = 6.28)
v_max: FloatProperty(name = "V Max",
Maurice Raybaud
committed
description = "",
default = 12.57)
Maurice Raybaud
committed
maxlen=1024, default = "cos(v)*(1+cos(u))*sin(v/8)")
Maurice Raybaud
committed
maxlen=1024, default = "sin(u)*sin(v/8)+cos(v/8)*1.5")
Maurice Raybaud
committed
maxlen=1024, default = "sin(v)*(1+cos(u))*sin(v/8)")
Maurice Raybaud
committed
def execute(self,context):
props = self.properties
u_min = props.u_min
v_min = props.v_min
u_max = props.u_max
v_max = props.v_max
x_eq = props.x_eq
y_eq = props.y_eq
z_eq = props.z_eq
Maurice Raybaud
committed
pov_parametric_define(context, self, None)
self.report({'INFO'}, "This native POV-Ray primitive "
Maurice Raybaud
committed
"won't have any vertex to show in edit mode")
return {'FINISHED'}
class POVRAY_OT_parametric_update(bpy.types.Operator):
"""Update the representation of POV parametric surfaces.
Delete its previous proxy geometry and rerun pov_parametric_define() function
with the new parameters"""
Maurice Raybaud
committed
bl_idname = "pov.parametric_update"
bl_label = "Update"
bl_description = "Update parametric object"
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {'POVRAY_RENDER'}
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
ob = context.object
return (ob and ob.data and ob.type == 'MESH' and engine in cls.COMPAT_ENGINES)
def execute(self, context):
pov_parametric_define(context, None, context.object)
return {'FINISHED'}
#######################################################################
Maurice Raybaud
committed
class POVRAY_OT_shape_polygon_to_circle_add(bpy.types.Operator):
"""Add the proxy mesh for POV Polygon to circle lofting macro"""
Maurice Raybaud
committed
bl_idname = "pov.addpolygontocircle"
bl_label = "Polygon To Circle Blending"
bl_description = "Add Polygon To Circle Blending Surface"
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {'POVRAY_RENDER'}
Maurice Raybaud
committed
# XXX Keep it in sync with __init__'s polytocircle properties
polytocircle_resolution: IntProperty(name = "Resolution",
Maurice Raybaud
committed
description = "",
default = 3, min = 0, max = 256)
polytocircle_ngon: IntProperty(name = "NGon",
Maurice Raybaud
committed
description = "",
min = 3, max = 64,default = 5)
polytocircle_ngonR: FloatProperty(name = "NGon Radius",
Maurice Raybaud
committed
description = "",
default = 0.3)
polytocircle_circleR: FloatProperty(name = "Circle Radius",
Maurice Raybaud
committed
description = "",
default = 1.0)
def execute(self,context):
props = self.properties
ngon = props.polytocircle_ngon
ngonR = props.polytocircle_ngonR
circleR = props.polytocircle_circleR
resolution = props.polytocircle_resolution
#layers = 20*[False]
#layers[0] = True
bpy.ops.mesh.primitive_circle_add(vertices=ngon, radius=ngonR, fill_type='NGON',enter_editmode=True)
Maurice Raybaud
committed
bpy.ops.transform.translate(value=(0, 0, 1))
bpy.ops.mesh.subdivide(number_cuts=resolution)
numCircleVerts = ngon + (ngon*resolution)
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.mesh.primitive_circle_add(vertices=numCircleVerts, radius=circleR, fill_type='NGON',enter_editmode=True)
Maurice Raybaud
committed
bpy.ops.transform.translate(value=(0, 0, -1))
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.bridge_edge_loops()
if ngon < 5:
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.mesh.primitive_circle_add(vertices=ngon, radius=ngonR, fill_type='TRIFAN',enter_editmode=True)
Maurice Raybaud
committed
bpy.ops.transform.translate(value=(0, 0, 1))
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.remove_doubles()
bpy.ops.object.mode_set(mode='OBJECT')
ob = context.object
ob.name = "Polygon_To_Circle"
ob.pov.object_as = 'POLYCIRCLE'
ob.pov.ngon = ngon
ob.pov.ngonR = ngonR
ob.pov.circleR = circleR
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
return {'FINISHED'}
Maurice Raybaud
committed
#############################IMPORT
Maurice Raybaud
committed
class ImportPOV(bpy.types.Operator, ImportHelper):
"""Load Povray files"""
bl_idname = "import_scene.pov"
bl_label = "POV-Ray files (.pov/.inc)"
Maurice Raybaud
committed
bl_options = {'PRESET', 'UNDO'}
COMPAT_ENGINES = {'POVRAY_RENDER'}
Maurice Raybaud
committed
# -----------
# File props.
files: CollectionProperty(type=bpy.types.OperatorFileListElement, options={'HIDDEN', 'SKIP_SAVE'})
directory: StringProperty(maxlen=1024, subtype='FILE_PATH', options={'HIDDEN', 'SKIP_SAVE'})
Maurice Raybaud
committed
filename_ext = {".pov",".inc"}
Maurice Raybaud
committed
default="*.pov;*.inc",
Maurice Raybaud
committed
options={'HIDDEN'},
)
import_at_cur: BoolProperty(name="Import at Cursor Location",
Maurice Raybaud
committed
description = "Ignore Object Matrix",
default=False)
Maurice Raybaud
committed
def execute(self, context):
Maurice Raybaud
committed
from mathutils import Matrix
verts = []
faces = []
materials = []
blendMats = [] ##############
povMats = [] ##############
Maurice Raybaud
committed
colors = []
matNames = []
Maurice Raybaud
committed
lenverts = None
lenfaces = None
suffix = -1
name = 'Mesh2_%s'%suffix
name_search = False
verts_search = False
faces_search = False
plane_search = False
box_search = False
cylinder_search = False
sphere_search = False
cone_search = False
Maurice Raybaud
committed
cache = []
matrixes = {}
writematrix = False
index = None
value = None
#filepov = bpy.path.abspath(self.filepath) #was used for single files
def mat_search(cache):
r = g = b = 0.5
f = t = 0
color = None
if cache[item+2] in {'rgb','srgb'}:
pass
elif cache[item+2] in {'rgbf','srgbf'}:
pass
elif cache[item+2] in {'rgbt','srgbt'}:
try:
r,g,b,t = float(cache[item+3]),float(cache[item+4]),float(cache[item+5]),float(cache[item+6])
except:
r = g = b = t = float(cache[item+2])
color = (r,g,b,t)
elif cache[item+2] in {'rgbft','srgbft'}:
pass
Maurice Raybaud
committed
if colors == [] or (colors != [] and color not in colors):
colors.append(color)
name = ob.name+"_mat"
matNames.append(name)
mat = bpy.data.materials.new(name)
mat.diffuse_color = (r,g,b)
mat.alpha = 1-t
if mat.alpha != 1:
mat.use_transparency=True
Maurice Raybaud
committed
ob.data.materials.append(mat)
Maurice Raybaud
committed
else:
for i, value in enumerate(colors):
if color == value:
Maurice Raybaud
committed
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
ob.data.materials.append(bpy.data.materials[matNames[i]])
for file in self.files:
print ("Importing file: "+ file.name)
filepov = self.directory + file.name
for line in open(filepov):
string = line.replace("{"," ")
string = string.replace("}"," ")
string = string.replace("<"," ")
string = string.replace(">"," ")
string = string.replace(","," ")
lw = string.split()
lenwords = len(lw)
if lw:
if lw[0] == "object":
writematrix = True
if writematrix:
if lw[0] not in {"object","matrix"}:
index = lw[0]
if lw[0] in {"matrix"}:
value = [float(lw[1]),float(lw[2]),float(lw[3]),\
float(lw[4]),float(lw[5]),float(lw[6]),\
float(lw[7]),float(lw[8]),float(lw[9]),\
float(lw[10]),float(lw[11]),float(lw[12])]
matrixes[index]=value
writematrix = False
for line in open(filepov):
S = line.replace("{"," { ")
S = S.replace("}"," } ")
S = S.replace(","," ")
S = S.replace("<","")
S = S.replace(">"," ")
S = S.replace("="," = ")
S = S.replace(";"," ; ")
S = S.split()
lenS= len(S)
for i,word in enumerate(S):
##################Primitives Import##################
if word == 'cone':
cone_search = True
name_search = False
if cone_search:
cache.append(word)
if cache[-1] == '}':
try:
x0 = float(cache[2])
y0 = float(cache[3])
z0 = float(cache[4])
r0 = float(cache[5])
x1 = float(cache[6])
y1 = float(cache[7])
z1 = float(cache[8])
r1 = float(cache[9])
# Y is height in most pov files, not z
bpy.ops.pov.cone_add(base=r0, cap=r1, height=(y1-y0))
ob = context.object
ob.location = (x0,y0,z0)
#ob.scale = (r,r,r)
Maurice Raybaud
committed
except (ValueError):
pass
cache = []
Maurice Raybaud
committed
if word == 'plane':
plane_search = True
name_search = False
if plane_search:
cache.append(word)
if cache[-1] == '}':
try:
bpy.ops.pov.addplane()
ob = context.object
Maurice Raybaud
committed
except (ValueError):
pass
cache = []
Maurice Raybaud
committed
if word == 'box':
box_search = True
name_search = False
if box_search:
cache.append(word)
if cache[-1] == '}':
try:
x0 = float(cache[2])
y0 = float(cache[3])
z0 = float(cache[4])
x1 = float(cache[5])
y1 = float(cache[6])
z1 = float(cache[7])
#imported_corner_1=(x0, y0, z0)
#imported_corner_2 =(x1, y1, z1)
center = ((x0 + x1)/2,(y0 + y1)/2,(z0 + z1)/2)
bpy.ops.pov.addbox()
ob = context.object
ob.location = center
Maurice Raybaud
committed
except (ValueError):
pass
cache = []
Maurice Raybaud
committed
if word == 'cylinder':
cylinder_search = True
name_search = False
if cylinder_search:
cache.append(word)
if cache[-1] == '}':
try:
x0 = float(cache[2])
y0 = float(cache[3])
z0 = float(cache[4])
x1 = float(cache[5])
y1 = float(cache[6])
z1 = float(cache[7])
imported_cyl_loc=(x0, y0, z0)
imported_cyl_loc_cap =(x1, y1, z1)
r = float(cache[8])
Maurice Raybaud
committed
vec = Vector(imported_cyl_loc_cap ) - Vector(imported_cyl_loc)
depth = vec.length
rot = Vector((0, 0, 1)).rotation_difference(vec) # Rotation from Z axis.
trans = rot @ Vector((0, 0, depth / 2)) # Such that origin is at center of the base of the cylinder.
Maurice Raybaud
committed
#center = ((x0 + x1)/2,(y0 + y1)/2,(z0 + z1)/2)
scaleZ = sqrt((x1-x0)**2+(y1-y0)**2+(z1-z0)**2)/2
bpy.ops.pov.addcylinder(R=r, imported_cyl_loc=imported_cyl_loc, imported_cyl_loc_cap=imported_cyl_loc_cap)
ob = context.object
ob.location = (x0, y0, z0)
ob.rotation_euler = rot.to_euler()
Maurice Raybaud
committed
#scale data rather than obj?
# bpy.ops.object.mode_set(mode='EDIT')
# bpy.ops.mesh.reveal()
# bpy.ops.mesh.select_all(action='SELECT')
# bpy.ops.transform.resize(value=(1,1,scaleZ), orient_type='LOCAL')
Maurice Raybaud
committed
# bpy.ops.mesh.hide(unselected=False)
# bpy.ops.object.mode_set(mode='OBJECT')
mat_search(cache)
Maurice Raybaud
committed
except (ValueError):
pass
cache = []
cylinder_search = False
if word == 'sphere':
sphere_search = True
name_search = False
if sphere_search:
cache.append(word)
if cache[-1] == '}':
Maurice Raybaud
committed
try:
x = float(cache[2])
y = float(cache[3])
z = float(cache[4])
r = float(cache[5])
Maurice Raybaud
committed
except (ValueError):
pass
except:
x = y = z = float(cache[2])
r = float(cache[3])
bpy.ops.pov.addsphere(R=r, imported_loc=(x, y, z))
ob = context.object
ob.location = (x,y,z)
ob.scale = (r,r,r)
mat_search(cache)
Maurice Raybaud
committed
cache = []
##################End Primitives Import##################
Maurice Raybaud
committed
if word == '#declare':
name_search = True
if name_search:
cache.append(word)
if word == 'mesh2':
name_search = False
if cache[-2] == '=':
name = cache[-3]
else:
suffix+=1
cache = []
if word in {'texture',';'}:
name_search = False
cache = []
if word == 'vertex_vectors':
Maurice Raybaud
committed
if verts_search:
Maurice Raybaud
committed
if word == '}':
verts_search = False
lenverts=cache[2]
cache.pop()
cache.pop(0)
cache.pop(0)
cache.pop(0)
for i in range(int(lenverts)):
x=i*3
y=(i*3)+1
z=(i*3)+2
verts.append((float(cache[x]),float(cache[y]),float(cache[z])))
#if word == 'face_indices':
#faces_search = True
if word == 'texture_list': ########
tex_search = True #######
if tex_search: #########
if word not in {'texture_list','texture','{','}','face_indices'} and word.isdigit() == False: ##############
povMats.append(word) #################
Maurice Raybaud
committed
if word == 'face_indices':
tex_search = False ################
faces_search = True
Maurice Raybaud
committed
if faces_search:
Maurice Raybaud
committed
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
if word == '}':
faces_search = False
lenfaces = cache[2]
cache.pop()
cache.pop(0)
cache.pop(0)
cache.pop(0)
lf = int(lenfaces)
var=int(len(cache)/lf)
for i in range(lf):
if var == 3:
v0=i*3
v1=i*3+1
v2=i*3+2
faces.append((int(cache[v0]),int(cache[v1]),int(cache[v2])))
if var == 4:
v0=i*4
v1=i*4+1
v2=i*4+2
m=i*4+3
materials.append((int(cache[m])))
faces.append((int(cache[v0]),int(cache[v1]),int(cache[v2])))
if var == 6:
v0=i*6
v1=i*6+1
v2=i*6+2
m0=i*6+3
m1=i*6+4
m2=i*6+5
materials.append((int(cache[m0]),int(cache[m1]),int(cache[m2])))
faces.append((int(cache[v0]),int(cache[v1]),int(cache[v2])))
#mesh = pov_define_mesh(None, verts, [], faces, name, hide_geometry=False)
#ob = object_utils.object_data_add(context, mesh, operator=None)
me = bpy.data.meshes.new(name) ########
ob = bpy.data.objects.new(name, me) ##########
bpy.context.collection.objects.link(ob) #########
me.from_pydata(verts, [], faces) ############
for mat in bpy.data.materials: ##############
blendMats.append(mat.name) #############
for mName in povMats: #####################
if mName not in blendMats: ###########
povMat = bpy.data.materials.new(mName) #################
ob.data.materials.append(bpy.data.materials[mName]) ###################
if materials: ##################
for i,val in enumerate(materials): ####################
try: ###################
ob.data.polygons[i].material_index = val ####################
except TypeError: ###################
ob.data.polygons[i].material_index = int(val[0]) ##################
blendMats = [] #########################
povMats = [] #########################
materials = [] #########################
Maurice Raybaud
committed
cache = []
name_search = True
if name in matrixes and self.import_at_cur==False:
global_matrix = Matrix.Rotation(pi / 2.0, 4, 'X')
ob = bpy.context.object
matrix=ob.matrix_world
v=matrixes[name]
matrix[0][0] = v[0]
matrix[1][0] = v[1]
matrix[2][0] = v[2]
matrix[0][1] = v[3]
matrix[1][1] = v[4]
matrix[2][1] = v[5]
matrix[0][2] = v[6]
matrix[1][2] = v[7]
matrix[2][2] = v[8]
matrix[0][3] = v[9]
matrix[1][3] = v[10]
matrix[2][3] = v[11]
Maurice Raybaud
committed
matrix = global_matrix*ob.matrix_world
ob.matrix_world = matrix
verts = []
faces = []
Maurice Raybaud
committed
# if word == 'pigment':
# try:
# #all indices have been incremented once to fit a bad test file
# r,g,b,t = float(S[2]),float(S[3]),float(S[4]),float(S[5])
Maurice Raybaud
committed
# except (IndexError):
# #all indices have been incremented once to fit alternate test file
# r,g,b,t = float(S[3]),float(S[4]),float(S[5]),float(S[6])
Maurice Raybaud
committed
# except UnboundLocalError:
# # In case no transmit is specified ? put it to 0
# r,g,b,t = float(S[2]),float(S[3]),float(S[4],0)
# color = (r,g,b,t)
Maurice Raybaud
committed
# except (ValueError):
# color = (0.8,0.8,0.8,0)
# pass
Maurice Raybaud
committed
# if colors == [] or (colors != [] and color not in colors):
# colors.append(color)
# name = ob.name+"_mat"
# matNames.append(name)
# mat = bpy.data.materials.new(name)
# mat.diffuse_color = (r,g,b)
# mat.alpha = 1-t
# if mat.alpha != 1:
# mat.use_transparency=True
# ob.data.materials.append(mat)
# print (colors)
# else:
# for i in range(len(colors)):
# if color == colors[i]:
# ob.data.materials.append(bpy.data.materials[matNames[i]])
##To keep Avogadro Camera angle:
# for obj in bpy.context.view_layer.objects:
Maurice Raybaud
committed
# if obj.type == "CAMERA":
# track = obj.constraints.new(type = "TRACK_TO")
# track.target = ob
# track.track_axis ="TRACK_NEGATIVE_Z"
# track.up_axis = "UP_Y"
# obj.location = (0,0,0)
return {'FINISHED'}
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
classes = (
POVRAY_OT_lathe_add,
POVRAY_OT_superellipsoid_add,
POVRAY_OT_superellipsoid_update,
POVRAY_OT_supertorus_add,
POVRAY_OT_supertorus_update,
POVRAY_OT_loft_add,
POVRAY_OT_plane_add,
POVRAY_OT_box_add,
POVRAY_OT_cylinder_add,
POVRAY_OT_cylinder_update,
POVRAY_OT_sphere_add,
POVRAY_OT_sphere_update,
POVRAY_OT_cone_add,
POVRAY_OT_cone_update,
POVRAY_OT_isosurface_box_add,
POVRAY_OT_isosurface_sphere_add,
POVRAY_OT_sphere_sweep_add,
POVRAY_OT_blob_add,
POVRAY_OT_rainbow_add,
POVRAY_OT_height_field_add,
POVRAY_OT_torus_add,
POVRAY_OT_torus_update,
POVRAY_OT_prism_add,
POVRAY_OT_parametric_add,
POVRAY_OT_parametric_update,
POVRAY_OT_shape_polygon_to_circle_add,
ImportPOV,
)
def register():
#from bpy.utils import register_class
for cls in classes:
register_class(cls)
def unregister():
from bpy.utils import unregister_class
for cls in classes:
unregister_class(cls)