Newer
Older
# SPDX-License-Identifier: GPL-2.0-or-later
""" Get POV-Ray specific objects In and Out of Blender """
import bpy
from bpy_extras.object_utils import object_data_add
Maurice Raybaud
committed
from bpy_extras.io_utils import ImportHelper
from bpy.utils import register_class, unregister_class
from bpy.types import Operator
Maurice Raybaud
committed
from bpy.props import (
StringProperty,
BoolProperty,
IntProperty,
FloatProperty,
FloatVectorProperty,
EnumProperty,
from mathutils import Vector, Matrix
from . import model_primitives
class POV_OT_lathe_add(Operator):
"""Add the representation of POV lathe using a screw modifier."""
Maurice Raybaud
committed
bl_idname = "pov.addlathe"
bl_label = "Lathe"
bl_description = "adds lathe"
Maurice Raybaud
committed
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {"POVRAY_RENDER"}
Maurice Raybaud
committed
def execute(self, context):
# ayers=[False]*20
# layers[0]=True
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"))
ob.pov.object_as = "LATHE"
{"INFO"}, "This native POV-Ray primitive" "won't have any vertex to show in edit mode"
Maurice Raybaud
committed
ob.pov.curveshape = "lathe"
bpy.ops.object.modifier_add(type="SCREW")
mod.axis = "Y"
ob.update_tag() # as prop set via python not updated in depsgraph
return {"FINISHED"}
Maurice Raybaud
committed
def pov_superellipsoid_define(context, op, ob):
"""Create the proxy mesh of a POV superellipsoid using pov_superellipsoid_define()."""
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
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 = []
stepSegment = 360 / v * pi / 180
stepRing = pi / u
angSegment = 0
angRing = -pi / 2
step = 0
for ring in range(0, u - 1):
for segment in range(0, v):
x = r * (abs(cos(angRing)) ** n1) * (abs(cos(angSegment)) ** n2)
if (cos(angRing) < 0 < cos(angSegment)) or (cos(angRing) > 0 > cos(angSegment)):
y = r * (abs(cos(angRing)) ** n1) * (abs(sin(angSegment)) ** n2)
if (cos(angRing) < 0 < sin(angSegment)) or (cos(angRing) > 0 > sin(angSegment)):
z = r * (abs(sin(angRing)) ** n1)
x = round(x, 4)
y = round(y, 4)
z = round(z, 4)
verts.append((x, y, z))
if edit == "TRIANGLES":
verts.extend([(0, 0, 1),(0, 0, -1)])
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)
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)
if i == v - 1:
face = (indexDown, i, 0)
for i in range(0, v):
if i < v - 1:
face = (indexUp, i + indexStartDown, i + indexStartDown + 1)
if i == v - 1:
face = (indexUp, i + indexStartDown, indexStartDown)
if edit == "NGONS":
face = list(range(v))
face = []
indexUp = len(verts) - 1
for i in range(0, v):
face.append(indexUp - i)
mesh = model_primitives.pov_define_mesh(mesh, verts, [], faces, "SuperEllipsoid")
Maurice Raybaud
committed
ob = object_data_add(context, mesh, operator=None)
# engine = context.scene.render.engine what for?
ob.name = ob.data.name = "PovSuperellipsoid"
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")
ob.data.auto_smooth_angle = 1.3
bpy.ops.object.shade_smooth()
ob.pov.object_as = "SUPERELLIPSOID"
ob.update_tag() # as prop set via python not updated in depsgraph
class POV_OT_superellipsoid_add(Operator):
"""Add the representation of POV superellipsoid using the pov_superellipsoid_define()."""
Maurice Raybaud
committed
bl_idname = "pov.addsuperellipsoid"
bl_label = "Add SuperEllipsoid"
bl_description = "Create a SuperEllipsoid"
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {"POVRAY_RENDER"}
Maurice Raybaud
committed
# Keep in sync within model_properties.py section Superellipsoid
Maurice Raybaud
committed
# If someone knows how to define operators' props from a func, I'd be delighted to learn it!
Maurice Raybaud
committed
# XXX ARE the first two used for import ? could we hide or suppress them otherwise?
se_param1: FloatProperty(name="Parameter 1", description="", min=0.00, max=10.0, default=0.04)
Maurice Raybaud
committed
se_param2: FloatProperty(name="Parameter 2", description="", min=0.00, max=10.0, default=0.04)
se_u: IntProperty(
name="U-segments", description="radial segmentation", default=20, min=4, max=265
)
se_v: IntProperty(
name="V-segments", description="lateral segmentation", default=20, min=4, max=265
)
se_n1: FloatProperty(
name="Ring manipulator",
description="Manipulates the shape of the Ring",
default=1.0,
min=0.01,
max=100.0,
)
se_n2: FloatProperty(
name="Cross manipulator",
description="Manipulates the shape of the cross-section",
default=1.0,
min=0.01,
max=100.0,
)
se_edit: EnumProperty(
items=[("NOTHING", "Nothing", ""), ("NGONS", "N-Gons", ""), ("TRIANGLES", "Triangles", "")],
name="Fill up and down",
description="",
default="TRIANGLES",
Maurice Raybaud
committed
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
return engine in cls.COMPAT_ENGINES
def execute(self, context):
Maurice Raybaud
committed
pov_superellipsoid_define(context, self, None)
{"INFO"}, "This native POV-Ray primitive" "won't have any vertex to show in edit mode"
Maurice Raybaud
committed
return {"FINISHED"}
Maurice Raybaud
committed
class POV_OT_superellipsoid_update(Operator):
"""Update the superellipsoid.
Delete its previous proxy geometry and rerun pov_superellipsoid_define() function
with the new parameters"""
Maurice Raybaud
committed
bl_idname = "pov.superellipsoid_update"
bl_label = "Update"
bl_description = "Update Superellipsoid"
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {"POVRAY_RENDER"}
Maurice Raybaud
committed
@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
Maurice Raybaud
committed
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")
Maurice Raybaud
committed
bpy.ops.object.mode_set(mode="OBJECT")
pov_superellipsoid_define(context, None, context.object)
return {"FINISHED"}
Maurice Raybaud
committed
def create_faces(vert_idx_1, vert_idx_2, closed=False, flipped=False):
"""Generate viewport proxy mesh data for some pov primitives"""
Maurice Raybaud
committed
faces = []
Maurice Raybaud
committed
return None
Maurice Raybaud
committed
return None
fan = False
if len(vert_idx_1) != len(vert_idx_2):
if len(vert_idx_1) == 1 and len(vert_idx_2) > 1:
Maurice Raybaud
committed
fan = True
else:
return None
Maurice Raybaud
committed
if closed:
if flipped:
face = [vert_idx_1[0], vert_idx_2[0], vert_idx_2[total - 1]]
Maurice Raybaud
committed
if not fan:
Maurice Raybaud
committed
else:
Maurice Raybaud
committed
if not fan:
face.append(vert_idx_1[total - 1])
face.append(vert_idx_2[total - 1])
faces.append(face)
Maurice Raybaud
committed
for num in range(total - 1):
if flipped:
if fan:
face = [vert_idx_2[num], vert_idx_1[0], vert_idx_2[num + 1]]
Maurice Raybaud
committed
else:
face = [vert_idx_2[num], vert_idx_1[num], vert_idx_1[num + 1], vert_idx_2[num + 1]]
elif fan:
face = [vert_idx_1[0], vert_idx_2[num], vert_idx_2[num + 1]]
Maurice Raybaud
committed
else:
face = [vert_idx_1[num], vert_idx_2[num], vert_idx_2[num + 1], vert_idx_1[num + 1]]
faces.append(face)
Maurice Raybaud
committed
return faces
"""Workaround to negative a, where the math.pow() method would return a ValueError."""
return -((-a) ** b) if a < 0 else a**b
def supertoroid(R, r, u, v, n1, n2):
a = 2 * pi / u
b = 2 * pi / v
Maurice Raybaud
committed
verts = []
faces = []
for i in range(u):
s = power(sin(i * a), n1)
c = power(cos(i * a), n1)
Maurice Raybaud
committed
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))?
Maurice Raybaud
committed
if i > 0:
f = create_faces(range((i - 1) * v, i * v), range(i * v, (i + 1) * v), closed=True)
Maurice Raybaud
committed
faces.extend(f)
f = create_faces(range((u - 1) * v, u * v), range(v), closed=True)
Maurice Raybaud
committed
faces.extend(f)
return verts, faces
"""Get POV supertorus properties from operator (object creation/import) or data update."""
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
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
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 = model_primitives.pov_define_mesh(mesh, verts, [], faces, "PovSuperTorus", True)
ob = object_data_add(context, mesh, operator=None)
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
ob.update_tag() # as prop set via python not updated in depsgraph
Maurice Raybaud
committed
class POV_OT_supertorus_add(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'}
COMPAT_ENGINES = {"POVRAY_RENDER"}
st_R: FloatProperty(
name="big radius",
description="The radius inside the tube",
default=1.0,
min=0.01,
max=100.0,
)
st_r: FloatProperty(
name="small radius", description="The radius of the tube", default=0.3, min=0.01, max=100.0
)
st_u: IntProperty(
name="U-segments", description="radial segmentation", default=16, min=3, max=265
)
st_v: IntProperty(
name="V-segments", description="lateral segmentation", default=8, min=3, max=265
)
st_n1: FloatProperty(
name="Ring manipulator",
description="Manipulates the shape of the Ring",
default=1.0,
min=0.01,
max=100.0,
)
st_n2: FloatProperty(
name="Cross manipulator",
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", description="Use internal and external radii", default=False
st_edit: BoolProperty(name="", description="", default=False, options={"HIDDEN"})
Maurice Raybaud
committed
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
return engine in cls.COMPAT_ENGINES
Maurice Raybaud
committed
def execute(self, context):
pov_supertorus_define(context, self, None)
{"INFO"}, "This native POV-Ray primitive" "won't have any vertex to show in edit mode"
return {"FINISHED"}
Maurice Raybaud
committed
class POV_OT_supertorus_update(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"}
Maurice Raybaud
committed
@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
Maurice Raybaud
committed
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")
Maurice Raybaud
committed
bpy.ops.object.mode_set(mode="OBJECT")
pov_supertorus_define(context, None, context.object)
return {"FINISHED"}
# -----------------------------------------------------------------------------
class POV_OT_loft_add(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"}
name="Segments", description="Vertical segments", default=16, min=3, max=720
)
loft_rings_bottom: IntProperty(
name="Bottom", description="Bottom rings", default=5, min=2, max=100
)
loft_rings_side: IntProperty(name="Side", description="Side rings", default=10, min=2, max=100)
loft_thick: FloatProperty(
name="Thickness",
description="Manipulates the shape of the Ring",
default=0.3,
min=0.01,
max=1.0,
)
loft_r: FloatProperty(name="Radius", description="Radius", default=1, min=0.01, max=10)
loft_height: FloatProperty(
name="Height",
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
loft_data = bpy.data.curves.new("Loft", type="CURVE")
loft_data.dimensions = "3D"
loft_data.resolution_u = 2
# loft_data.show_normal_face = False # deprecated in 2.8
Maurice Raybaud
committed
thick = props.loft_thick
side = props.loft_rings_side
bottom = props.loft_rings_bottom
h = props.loft_height
r = props.loft_r
Maurice Raybaud
committed
r0 = 0.00001
Maurice Raybaud
committed
print("New")
for i in range(bottom + 1):
Maurice Raybaud
committed
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 = loft_data.splines.new("NURBS")
nurbs.points.add(len(coords) - 1)
Maurice Raybaud
committed
nurbs.use_cyclic_u = True
for i in range(side):
Maurice Raybaud
committed
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 = loft_data.splines.new("NURBS")
nurbs.points.add(len(coords) - 1)
Maurice Raybaud
committed
nurbs.use_cyclic_u = True
Maurice Raybaud
committed
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 = loft_data.splines.new("NURBS")
nurbs.points.add(len(coords) - 1)
Maurice Raybaud
committed
nurbs.use_cyclic_u = True
z -= h / side
z = (-h / 2) + thick
distB = (r - 0.00001) / bottom
for i in range(bottom + 1):
Maurice Raybaud
committed
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 = loft_data.splines.new("NURBS")
nurbs.points.add(len(coords) - 1)
Maurice Raybaud
committed
nurbs.use_cyclic_u = True
ob = bpy.data.objects.new("Loft_shape", loft_data)
Maurice Raybaud
committed
scn = bpy.context.scene
Maurice Raybaud
committed
ob.pov.curveshape = "loft"
return {"FINISHED"}
# ----------------------------------- ISOSURFACES ----------------------------------- #
Maurice Raybaud
committed
Maurice Raybaud
committed
def pov_isosurface_view_define(context, op, ob, loc):
"""create the representation of POV isosurface using a Blender empty."""
if op:
eq = op.isosurface_eq
loc = bpy.context.scene.cursor.location
else:
assert ob
eq = ob.pov.isosurface_eq
# keep object rotation and location for the add object operator
obrot = ob.rotation_euler
# obloc = ob.location
obscale = ob.scale
# bpy.ops.object.empty_add(type='CUBE', location=loc, rotation=obrot)
Maurice Raybaud
committed
bpy.ops.mesh.primitive_emptyvert_add()
# bpy.ops.transform.rotate(axis=obrot,orient_type='GLOBAL')
bpy.ops.transform.resize(value=obscale)
# bpy.ops.transform.rotate(axis=obrot, proportional_size=1)
bpy.ops.object.mode_set(mode="OBJECT")
if not ob:
# bpy.ops.object.empty_add(type='CUBE', location=loc)
Maurice Raybaud
committed
bpy.ops.mesh.primitive_emptyvert_add()
ob = context.object
ob.name = ob.data.name = "PovIsosurface"
ob.pov.object_as = "ISOSURFACE_VIEW"
ob.pov.isosurface_eq = eq
ob.pov.contained_by = "box"
Maurice Raybaud
committed
bpy.ops.object.mode_set(mode="OBJECT")
ob.update_tag() # as prop set via python not updated in depsgraph
Maurice Raybaud
committed
class POV_OT_isosurface_add(Operator):
Maurice Raybaud
committed
"""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."""
bl_idname = "pov.addisosurface"
bl_label = "Generic Isosurface"
bl_description = "Add Isosurface"
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {"POVRAY_RENDER"}
Maurice Raybaud
committed
# Keep in sync within model_properties.py section Sphere
Maurice Raybaud
committed
# as this allows interactive update
isosurface_eq: StringProperty(
name="f(x,y,z)=",
description="Type the POV Isosurface function syntax for equation, "
"pattern,etc. ruling an implicit surface to be rendered",
default="sqrt(pow(x,2) + pow(y,2) + pow(z,2)) - 1.5",
)
imported_loc: FloatVectorProperty(
name="Imported Pov location", precision=6, default=(0.0, 0.0, 0.0)
)
def execute(self, context):
# layers = 20*[False]
# layers[0] = True
props = self.properties
if ob := context.object:
Maurice Raybaud
committed
if ob.pov.imported_loc:
LOC = ob.pov.imported_loc
elif not props.imported_loc:
LOC = bpy.context.scene.cursor.location
else:
LOC = props.imported_loc
try:
pov_isosurface_view_define(context, self, None, LOC)
self.report(
{"INFO"}, "This native POV-Ray primitive " "is only an abstract proxy in Blender"
)
except AttributeError:
self.report({"INFO"}, "Please enable Add Mesh: Extra Objects addon")
return {"FINISHED"}
Maurice Raybaud
committed
class POV_OT_isosurface_update(Operator):
Maurice Raybaud
committed
"""Update the POV isosurface.
Rerun pov_isosurface_view_define() function
with the new parameters"""
bl_idname = "pov.isosurface_update"
bl_label = "Update"
bl_description = "Update Isosurface"
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {"POVRAY_RENDER"}
Maurice Raybaud
committed
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
ob = context.object
return ob and ob.data and ob.type == "ISOSURFACE_VIEW" and engine in cls.COMPAT_ENGINES
Maurice Raybaud
committed
def execute(self, context):
pov_isosurface_view_define(context, None, context.object, context.object.location)
return {"FINISHED"}
Maurice Raybaud
committed
class POV_OT_isosurface_box_add(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'}
COMPAT_ENGINES = {"POVRAY_RENDER"}
Maurice Raybaud
committed
def execute(self, context):
# layers = 20*[False]
# layers[0] = True
Maurice Raybaud
committed
ob = context.object
bpy.ops.object.mode_set(mode="EDIT")
{"INFO"}, "This native POV-Ray primitive " "won't have any vertex to show in edit mode"
Maurice Raybaud
committed
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
Maurice Raybaud
committed
ob.pov.object_as = "ISOSURFACE_NODE"
ob.pov.contained_by = "box"
ob.name = "PovIsosurfaceBox"
ob.update_tag() # as prop set via python not updated in depsgraph
return {"FINISHED"}
Maurice Raybaud
committed
class POV_OT_isosurface_sphere_add(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'}
COMPAT_ENGINES = {"POVRAY_RENDER"}
Maurice Raybaud
committed
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")
{"INFO"}, "This native POV-Ray primitive " "won't have any vertex to show in edit mode"
Maurice Raybaud
committed
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
bpy.ops.object.shade_smooth()
Maurice Raybaud
committed
ob.pov.object_as = "ISOSURFACE_NODE"
ob.pov.contained_by = "sphere"
ob.name = "PovIsosurfaceSphere"
ob.update_tag() # as prop set via python not updated in depsgraph
return {"FINISHED"}
Maurice Raybaud
committed
class POV_OT_sphere_sweep_add(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'}
COMPAT_ENGINES = {"POVRAY_RENDER"}
Maurice Raybaud
committed
def execute(self, context):
# layers = 20*[False]
# layers[0] = True
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
Maurice Raybaud
committed
return {"FINISHED"}
Maurice Raybaud
committed
class POV_OT_blobsphere_add(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'}
COMPAT_ENGINES = {"POVRAY_RENDER"}
Maurice Raybaud
committed
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"
return {"FINISHED"}
Maurice Raybaud
committed
class POV_OT_blobcapsule_add(Operator):
Maurice Raybaud
committed
"""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."""
bl_idname = "pov.addblobcapsule"
bl_label = "Blob Capsule"
bl_description = "Add Blob Capsule"
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {"POVRAY_RENDER"}
Maurice Raybaud
committed
def execute(self, context):
# layers = 20*[False]
# layers[0] = True
bpy.ops.object.metaball_add(type="CAPSULE")
Maurice Raybaud
committed
ob = context.object
ob.name = "PovBlob"
return {"FINISHED"}
Maurice Raybaud
committed
class POV_OT_blobplane_add(Operator):
Maurice Raybaud
committed
"""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."""
bl_idname = "pov.addblobplane"
bl_label = "Blob Plane"
bl_description = "Add Blob Plane"
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {"POVRAY_RENDER"}
Maurice Raybaud
committed
def execute(self, context):
# layers = 20*[False]
# layers[0] = True
bpy.ops.object.metaball_add(type="PLANE")
Maurice Raybaud
committed
ob = context.object
ob.name = "PovBlob"
return {"FINISHED"}
Maurice Raybaud
committed
class POV_OT_blobellipsoid_add(Operator):
Maurice Raybaud
committed
"""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."""
bl_idname = "pov.addblobellipsoid"
bl_label = "Blob Ellipsoid"
bl_description = "Add Blob Ellipsoid"
Maurice Raybaud
committed
def execute(self, context):
# layers = 20*[False]
# layers[0] = True
bpy.ops.object.metaball_add(type="ELLIPSOID")
Maurice Raybaud
committed
ob = context.object
ob.name = "PovBlob"
return {"FINISHED"}
Maurice Raybaud
committed
class POV_OT_blobcube_add(Operator):
Maurice Raybaud
committed
"""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."""
bl_idname = "pov.addblobcube"
bl_label = "Blob Cube"
bl_description = "Add Blob Cube"
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {"POVRAY_RENDER"}
Maurice Raybaud
committed
def execute(self, context):
# layers = 20*[False]
# layers[0] = True
bpy.ops.object.metaball_add(type="CUBE")
Maurice Raybaud
committed
ob = context.object
ob.name = "PovBlob"
return {"FINISHED"}
Maurice Raybaud
committed
class POV_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"
Maurice Raybaud
committed
bl_options = {'REGISTER', 'UNDO'}
COMPAT_ENGINES = {"POVRAY_RENDER"}
# Keep in sync within model_properties.py section HeightFields
Maurice Raybaud
committed
# 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", description="", default=100, min=1, max=100)
hf_filename: StringProperty(maxlen=1024)
hf_gamma: FloatProperty(name="Gamma", description="Gamma", min=0.0001, max=20.0, default=1.0)
Maurice Raybaud
committed
hf_premultiplied: BoolProperty(name="Premultiplied", description="Premultiplied", default=True)
Maurice Raybaud
committed
hf_smooth: BoolProperty(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
hf_hierarchy: BoolProperty(name="Hierarchy", description="Height field hierarchy", default=True)
def execute(self, context):
Maurice Raybaud
committed
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")
Maurice Raybaud
committed
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
# layers = 20*[False]
# layers[0] = True
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
Maurice Raybaud
committed
ob.data.materials.append(mat)
bpy.ops.object.mode_set(mode="EDIT")
# bpy.ops.mesh.noise(factor=1) # TODO replace by displace modifier, noise deprecated in 2.8
Maurice Raybaud
committed
bpy.ops.object.mode_set(mode="OBJECT")
# needs a loop to select by index?
# 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"
# POV-Ray will soon use only forwards slashes on every OS and already can
forward_impath = impath.replace(os.sep, "/")
ob.update_tag() # as prop set via python not updated in depsgraph
return {"FINISHED"}
# ----------------------------------- PARAMETRIC ----------------------------------- #
"""Add the representation of POV parametric surfaces by math surface from add mesh extra objects addon.
Maurice Raybaud
committed
Picking properties either from creation operator, import, or data update.
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:
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
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
obrot = ob.rotation_euler # In radians
# Parametric addon has no loc rot, some extra work is needed