Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaurice Raybaud <mauriceraybaud@hotmail.fr>2022-01-26 03:02:18 +0300
committerMaurice Raybaud <mauriceraybaud@hotmail.fr>2022-01-26 03:02:18 +0300
commit692611358a9189c2f54f916c42a08e1ddf54bb84 (patch)
tree68ee4016d4be897fd53d5c51419c43443cd9dbe9 /render_povray/object_mesh_topology.py
parentfd5697ebcf879894d84875b593fe00ede14e79a4 (diff)
POV: Add primitives workspace tools icons, blurry reflections, equation based isourface ; various fixes
* fix tiny formatting of quotes, docstrings, parenthesis * fix pov centered worspaces * fix (revert) bad default for text block insertion * fix primitive exports sorted by most frequent for (slight) speed up * fix some uninitialized hairstrand root diameter variable * fix extracted function for CSG inside vector * fix too big size of proxy mesh for ininite plane caused it to blink * fix end of render speach error handling * fix max specular value to better map out under a texture influence * fix emit, ambient, translucency shading properties UI broken post 2.8 * add workspace tools icons for pov primitives * add a user input equation based isosurface primitive * add micro normals based blurry reflections (glossy UI slider)
Diffstat (limited to 'render_povray/object_mesh_topology.py')
-rwxr-xr-xrender_povray/object_mesh_topology.py1104
1 files changed, 566 insertions, 538 deletions
diff --git a/render_povray/object_mesh_topology.py b/render_povray/object_mesh_topology.py
index cd98a6f4..e991070c 100755
--- a/render_povray/object_mesh_topology.py
+++ b/render_povray/object_mesh_topology.py
@@ -30,28 +30,48 @@ import bpy
from . import texturing # for how textures influence shaders
from .scenography import export_smoke
-
def matrix_as_pov_string(matrix):
"""Translate some transform matrix from Blender UI
to POV syntax and return that string """
- matrix_string = (
- "matrix <%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f>\n"
- % (
- matrix[0][0],
- matrix[1][0],
- matrix[2][0],
- matrix[0][1],
- matrix[1][1],
- matrix[2][1],
- matrix[0][2],
- matrix[1][2],
- matrix[2][2],
- matrix[0][3],
- matrix[1][3],
- matrix[2][3],
- )
- )
- return matrix_string
+ return "matrix <" \
+ "%.6f, %.6f, %.6f, " \
+ "%.6f, %.6f, %.6f, " \
+ "%.6f, %.6f, %.6f, " \
+ "%.6f, %.6f, %.6f" \
+ ">\n" % (
+ matrix[0][0],
+ matrix[1][0],
+ matrix[2][0],
+ matrix[0][1],
+ matrix[1][1],
+ matrix[2][1],
+ matrix[0][2],
+ matrix[1][2],
+ matrix[2][2],
+ matrix[0][3],
+ matrix[1][3],
+ matrix[2][3],
+ )
+
+
+def write_object_csg_inside_vector(ob, file):
+ """Write inside vector for use by pov CSG, only once per object using boolean"""
+ has_csg_inside_vector = False
+ for modif in ob.modifiers:
+ if (
+ not has_csg_inside_vector
+ and modif.type == 'BOOLEAN'
+ and ob.pov.boolean_mod == "POV"
+ ):
+ file.write(
+ "\tinside_vector <%.6g, %.6g, %.6g>\n"
+ % (
+ ob.pov.inside_vector[0],
+ ob.pov.inside_vector[1],
+ ob.pov.inside_vector[2],
+ )
+ )
+ has_csg_inside_vector = True
# objectNames = {}
@@ -59,32 +79,32 @@ DEF_OBJ_NAME = "Default"
def export_meshes(
- preview_dir,
- file,
- scene,
- sel,
- csg,
- string_strip_hyphen,
- safety,
- write_object_modifiers,
- material_names_dictionary,
- write_object_material_interior,
- exported_lights_count,
- unpacked_images,
- image_format,
- img_map,
- img_map_transforms,
- path_image,
- smoke_path,
- global_matrix,
- write_matrix,
- using_uberpov,
- comments,
- linebreaksinlists,
- tab,
- tab_level,
- tab_write,
- info_callback,
+ preview_dir,
+ file,
+ scene,
+ sel,
+ csg,
+ string_strip_hyphen,
+ safety,
+ write_object_modifiers,
+ material_names_dictionary,
+ write_object_material_interior,
+ exported_lights_count,
+ unpacked_images,
+ image_format,
+ img_map,
+ img_map_transforms,
+ path_image,
+ smoke_path,
+ global_matrix,
+ write_matrix,
+ using_uberpov,
+ comments,
+ linebreaksinlists,
+ tab,
+ tab_level,
+ tab_write,
+ info_callback,
):
"""write all meshes as POV mesh2{} syntax to exported file """
# # some numpy functions to speed up mesh export NOT IN USE YET
@@ -93,72 +113,72 @@ def export_meshes(
# # TODO: also write a numpy function to read matrices at object level?
# # feed below with mesh object.data, but only after doing data.calc_loop_triangles()
# def read_verts_co(self, mesh):
- # #'float64' would be a slower 64-bit floating-point number numpy datatype
- # # using 'float32' vert coordinates for now until any issue is reported
- # mverts_co = np.zeros((len(mesh.vertices) * 3), dtype=np.float32)
- # mesh.vertices.foreach_get("co", mverts_co)
- # return np.reshape(mverts_co, (len(mesh.vertices), 3))
+ # #'float64' would be a slower 64-bit floating-point number numpy datatype
+ # # using 'float32' vert coordinates for now until any issue is reported
+ # mverts_co = np.zeros((len(mesh.vertices) * 3), dtype=np.float32)
+ # mesh.vertices.foreach_get("co", mverts_co)
+ # return np.reshape(mverts_co, (len(mesh.vertices), 3))
# def read_verts_idx(self, mesh):
- # mverts_idx = np.zeros((len(mesh.vertices)), dtype=np.int64)
- # mesh.vertices.foreach_get("index", mverts_idx)
- # return np.reshape(mverts_idx, (len(mesh.vertices), 1))
+ # mverts_idx = np.zeros((len(mesh.vertices)), dtype=np.int64)
+ # mesh.vertices.foreach_get("index", mverts_idx)
+ # return np.reshape(mverts_idx, (len(mesh.vertices), 1))
# def read_verts_norms(self, mesh):
- # #'float64' would be a slower 64-bit floating-point number numpy datatype
- # # using less accurate 'float16' normals for now until any issue is reported
- # mverts_no = np.zeros((len(mesh.vertices) * 3), dtype=np.float16)
- # mesh.vertices.foreach_get("normal", mverts_no)
- # return np.reshape(mverts_no, (len(mesh.vertices), 3))
+ # #'float64' would be a slower 64-bit floating-point number numpy datatype
+ # # using less accurate 'float16' normals for now until any issue is reported
+ # mverts_no = np.zeros((len(mesh.vertices) * 3), dtype=np.float16)
+ # mesh.vertices.foreach_get("normal", mverts_no)
+ # return np.reshape(mverts_no, (len(mesh.vertices), 3))
# def read_faces_idx(self, mesh):
- # mfaces_idx = np.zeros((len(mesh.loop_triangles)), dtype=np.int64)
- # mesh.loop_triangles.foreach_get("index", mfaces_idx)
- # return np.reshape(mfaces_idx, (len(mesh.loop_triangles), 1))
+ # mfaces_idx = np.zeros((len(mesh.loop_triangles)), dtype=np.int64)
+ # mesh.loop_triangles.foreach_get("index", mfaces_idx)
+ # return np.reshape(mfaces_idx, (len(mesh.loop_triangles), 1))
# def read_faces_verts_indices(self, mesh):
- # mfaces_verts_idx = np.zeros((len(mesh.loop_triangles) * 3), dtype=np.int64)
- # mesh.loop_triangles.foreach_get("vertices", mfaces_verts_idx)
- # return np.reshape(mfaces_verts_idx, (len(mesh.loop_triangles), 3))
+ # mfaces_verts_idx = np.zeros((len(mesh.loop_triangles) * 3), dtype=np.int64)
+ # mesh.loop_triangles.foreach_get("vertices", mfaces_verts_idx)
+ # return np.reshape(mfaces_verts_idx, (len(mesh.loop_triangles), 3))
# # Why is below different from vertex indices?
# def read_faces_verts_loops(self, mesh):
- # mfaces_verts_loops = np.zeros((len(mesh.loop_triangles) * 3), dtype=np.int64)
- # mesh.loop_triangles.foreach_get("loops", mfaces_verts_loops)
- # return np.reshape(mfaces_verts_loops, (len(mesh.loop_triangles), 3))
+ # mfaces_verts_loops = np.zeros((len(mesh.loop_triangles) * 3), dtype=np.int64)
+ # mesh.loop_triangles.foreach_get("loops", mfaces_verts_loops)
+ # return np.reshape(mfaces_verts_loops, (len(mesh.loop_triangles), 3))
# def read_faces_norms(self, mesh):
- # #'float64' would be a slower 64-bit floating-point number numpy datatype
- # # using less accurate 'float16' normals for now until any issue is reported
- # mfaces_no = np.zeros((len(mesh.loop_triangles) * 3), dtype=np.float16)
- # mesh.loop_triangles.foreach_get("normal", mfaces_no)
- # return np.reshape(mfaces_no, (len(mesh.loop_triangles), 3))
+ # #'float64' would be a slower 64-bit floating-point number numpy datatype
+ # # using less accurate 'float16' normals for now until any issue is reported
+ # mfaces_no = np.zeros((len(mesh.loop_triangles) * 3), dtype=np.float16)
+ # mesh.loop_triangles.foreach_get("normal", mfaces_no)
+ # return np.reshape(mfaces_no, (len(mesh.loop_triangles), 3))
# def read_faces_smooth(self, mesh):
- # mfaces_smth = np.zeros((len(mesh.loop_triangles) * 1), dtype=np.bool)
- # mesh.loop_triangles.foreach_get("use_smooth", mfaces_smth)
- # return np.reshape(mfaces_smth, (len(mesh.loop_triangles), 1))
+ # mfaces_smth = np.zeros((len(mesh.loop_triangles) * 1), dtype=np.bool)
+ # mesh.loop_triangles.foreach_get("use_smooth", mfaces_smth)
+ # return np.reshape(mfaces_smth, (len(mesh.loop_triangles), 1))
# def read_faces_material_indices(self, mesh):
- # mfaces_mats_idx = np.zeros((len(mesh.loop_triangles)), dtype=np.int16)
- # mesh.loop_triangles.foreach_get("material_index", mfaces_mats_idx)
- # return np.reshape(mfaces_mats_idx, (len(mesh.loop_triangles), 1))
+ # mfaces_mats_idx = np.zeros((len(mesh.loop_triangles)), dtype=np.int16)
+ # mesh.loop_triangles.foreach_get("material_index", mfaces_mats_idx)
+ # return np.reshape(mfaces_mats_idx, (len(mesh.loop_triangles), 1))
# obmatslist = []
# def hasUniqueMaterial():
# # Grab materials attached to object instances ...
- # if hasattr(ob, 'material_slots'):
- # for ms in ob.material_slots:
+ # if hasattr(obj, 'material_slots'):
+ # for ms in obj.material_slots:
# if ms.material is not None and ms.link == 'OBJECT':
# if ms.material in obmatslist:
# return False
# else:
# obmatslist.append(ms.material)
# return True
- # def hasObjectMaterial(ob):
+ # def hasObjectMaterial(obj):
# # Grab materials attached to object instances ...
- # if hasattr(ob, 'material_slots'):
- # for ms in ob.material_slots:
+ # if hasattr(obj, 'material_slots'):
+ # for ms in obj.material_slots:
# if ms.material is not None and ms.link == 'OBJECT':
# # If there is at least one material slot linked to the object
# # and not the data (mesh), always create a new, "private" data instance.
@@ -173,12 +193,12 @@ def export_meshes(
# ... can share a same instance in POV export.
obmats2data = {}
- def check_object_materials(ob, name, dataname):
+ def check_object_materials(obj, obj_name, dataname):
"""Compare other objects exported material slots to avoid rewriting duplicates"""
- if hasattr(ob, 'material_slots'):
+ if hasattr(obj, 'material_slots'):
has_local_mats = False
key = [dataname]
- for ms in ob.material_slots:
+ for ms in obj.material_slots:
if ms.material is not None:
key.append(ms.material.name)
if ms.link == 'OBJECT' and not has_local_mats:
@@ -193,7 +213,7 @@ def export_meshes(
# Note that here also, we use object name as new, unique dataname for Pov.
key = tuple(key) # Lists are not hashable...
if key not in obmats2data:
- obmats2data[key] = name
+ obmats2data[key] = obj_name
return obmats2data[key]
return None
@@ -242,10 +262,10 @@ def export_meshes(
'LATTICE',
}:
continue
- fluid_flag = False
+ fluid_found = False
for mod in ob.modifiers:
if mod and hasattr(mod, 'fluid_type'):
- fluid_flag = True
+ fluid_found = True
if mod.fluid_type == 'DOMAIN':
if mod.domain_settings.domain_type == 'GAS':
export_smoke(
@@ -255,30 +275,26 @@ def export_meshes(
if mod.fluid_type == 'FLOW': # The domain contains all the smoke. so that's it.
if mod.flow_settings.flow_type == 'SMOKE': # Check how liquids behave
break # don't render smoke flow emitter mesh either, skip to next object.
- if not fluid_flag:
- # Export Hair
- # importing here rather than at the top recommended for addons startup footprint
- from .object_particles import export_hair
-
- render_emitter = True
+ if not fluid_found:
+ # No fluid found
if hasattr(ob, 'particle_systems'):
- render_emitter = False
- if ob.show_instancer_for_render:
- render_emitter = True
+ # Importing function Export Hair
+ # here rather than at the top recommended for addons startup footprint
+ from .object_particles import export_hair
for p_sys in ob.particle_systems:
- for mod in [
+ for particle_mod in [
m
for m in ob.modifiers
if (m is not None) and (m.type == 'PARTICLE_SYSTEM')
]:
if (
- (p_sys.settings.render_type == 'PATH')
- and mod.show_render
- and (p_sys.name == mod.particle_system.name)
+ (p_sys.settings.render_type == 'PATH')
+ and particle_mod.show_render
+ and (p_sys.name == particle_mod.particle_system.name)
):
- export_hair(file, ob, mod, p_sys, global_matrix, write_matrix)
- if not render_emitter:
- continue # don't render mesh, skip to next object.
+ export_hair(file, ob, particle_mod, p_sys, global_matrix, write_matrix)
+ if not ob.show_instancer_for_render:
+ continue # don't render emitter mesh, skip to next object.
# ------------------------------------------------
# Generating a name for object just like materials to be able to use it
@@ -300,8 +316,8 @@ def export_meshes(
# original included in list since 2.8
if eachduplicate.is_instance:
dataname_orig = "DATA" + eachduplicate.object.name
- # ob.dupli_list_clear() #just don't store any reference to instance since 2.8
- elif ob.data: # not an EMPTY type object
+ # obj.dupli_list_clear() #just don't store any reference to instance since 2.8
+ elif ob.data: # not an EMPTY type object
name_orig = "OB" + ob.name
dataname_orig = "DATA" + ob.data.name
elif ob.type == 'EMPTY':
@@ -312,7 +328,7 @@ def export_meshes(
dataname_orig = DEF_OBJ_NAME
name = string_strip_hyphen(bpy.path.clean_name(name_orig))
dataname = string_strip_hyphen(bpy.path.clean_name(dataname_orig))
- # for slot in ob.material_slots:
+ # for slot in obj.material_slots:
# if slot.material is not None and slot.link == 'OBJECT':
# obmaterial = slot.material
@@ -331,397 +347,25 @@ def export_meshes(
print("Writing Down First Occurrence of " + name)
- # ------------ Povray Primitives ------------ #
+ # ------------ Mesh Primitives ------------ #
# special export_curves() function takes care of writing
# lathe, sphere_sweep, birail, and loft except with modifiers
# converted to mesh
if not ob.is_modified(scene, 'RENDER'):
if ob.type == 'CURVE' and (
- ob.pov.curveshape in {'lathe', 'sphere_sweep', 'loft'}
+ ob.pov.curveshape in {'lathe', 'sphere_sweep', 'loft'}
):
continue # Don't render proxy mesh, skip to next object
# pov_mat_name = "Default_texture" # Not used...remove?
- if ob.pov.object_as == 'ISOSURFACE':
- tab_write("#declare %s = isosurface{ \n" % povdataname)
- tab_write("function{ \n")
- text_name = ob.pov.iso_function_text
- if text_name:
- node_tree = bpy.context.scene.node_tree
- for node in node_tree.nodes:
- if node.bl_idname == "IsoPropsNode" and node.label == ob.name:
- for inp in node.inputs:
- if inp:
- tab_write(
- "#declare %s = %.6g;\n" % (inp.name, inp.default_value)
- )
-
- text = bpy.data.texts[text_name]
- for line in text.lines:
- split = line.body.split()
- if split[0] != "#declare":
- tab_write("%s\n" % line.body)
- else:
- tab_write("abs(x) - 2 + y")
- tab_write("}\n")
- tab_write("threshold %.6g\n" % ob.pov.threshold)
- tab_write("max_gradient %.6g\n" % ob.pov.max_gradient)
- tab_write("accuracy %.6g\n" % ob.pov.accuracy)
- tab_write("contained_by { ")
- if ob.pov.contained_by == "sphere":
- tab_write("sphere {0,%.6g}}\n" % ob.pov.container_scale)
- else:
- tab_write(
- "box {-%.6g,%.6g}}\n" % (ob.pov.container_scale, ob.pov.container_scale)
- )
- if ob.pov.all_intersections:
- tab_write("all_intersections\n")
- else:
- if ob.pov.max_trace > 1:
- tab_write("max_trace %.6g\n" % ob.pov.max_trace)
- if ob.active_material:
- # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
- try:
- material = ob.active_material
- write_object_material_interior(material, ob, tab_write)
- except IndexError:
- print(me)
- # tab_write("texture {%s}\n"%pov_mat_name)
- tab_write("scale %.6g\n" % (1 / ob.pov.container_scale))
- tab_write("}\n")
- continue # Don't render proxy mesh, skip to next object
-
- if ob.pov.object_as == 'SUPERELLIPSOID':
- tab_write(
- "#declare %s = superellipsoid{ <%.4f,%.4f>\n"
- % (povdataname, ob.pov.se_n2, ob.pov.se_n1)
- )
- if ob.active_material:
- # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
- try:
- material = ob.active_material
- write_object_material_interior(material, ob, tab_write)
- except IndexError:
- print(me)
- # tab_write("texture {%s}\n"%pov_mat_name)
- write_object_modifiers(scene, ob, file)
- tab_write("}\n")
- continue # Don't render proxy mesh, skip to next object
-
- if ob.pov.object_as == 'SUPERTORUS':
- rad_maj = ob.pov.st_major_radius
- rad_min = ob.pov.st_minor_radius
- ring = ob.pov.st_ring
- cross = ob.pov.st_cross
- accuracy = ob.pov.st_accuracy
- gradient = ob.pov.st_max_gradient
- # --- Inline Supertorus macro
- file.write(
- "#macro Supertorus(RMj, RMn, MajorControl, MinorControl, Accuracy, MaxGradient)\n"
- )
- file.write(" #local CP = 2/MinorControl;\n")
- file.write(" #local RP = 2/MajorControl;\n")
- file.write(" isosurface {\n")
- file.write(
- " function { pow( pow(abs(pow(pow(abs(x),RP) + pow(abs(z),RP), 1/RP) - RMj),CP) + pow(abs(y),CP) ,1/CP) - RMn }\n"
- )
- file.write(" threshold 0\n")
- file.write(
- " contained_by {box {<-RMj-RMn,-RMn,-RMj-RMn>, < RMj+RMn, RMn, RMj+RMn>}}\n"
- )
- file.write(" #if(MaxGradient >= 1)\n")
- file.write(" max_gradient MaxGradient\n")
- file.write(" #else\n")
- file.write(" evaluate 1, 10, 0.1\n")
- file.write(" #end\n")
- file.write(" accuracy Accuracy\n")
- file.write(" }\n")
- file.write("#end\n")
- # ---
- tab_write(
- "#declare %s = object{ Supertorus( %.4g,%.4g,%.4g,%.4g,%.4g,%.4g)\n"
- % (povdataname, rad_maj, rad_min, ring, cross, accuracy, gradient)
- )
- if ob.active_material:
- # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
- try:
- material = ob.active_material
- write_object_material_interior(material, ob, tab_write)
- except IndexError:
- print(me)
- # tab_write("texture {%s}\n"%pov_mat_name)
- write_object_modifiers(scene, ob, file)
- tab_write("rotate x*90\n")
- tab_write("}\n")
- continue # Don't render proxy mesh, skip to next object
-
- if ob.pov.object_as == 'PLANE':
- tab_write("#declare %s = plane{ <0,0,1>,1\n" % povdataname)
- if ob.active_material:
- # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
- try:
- material = ob.active_material
- write_object_material_interior(material, ob, tab_write)
- except IndexError:
- print(me)
- # tab_write("texture {%s}\n"%pov_mat_name)
- write_object_modifiers(scene, ob, file)
- # tab_write("rotate x*90\n")
- tab_write("}\n")
- continue # Don't render proxy mesh, skip to next object
- if ob.pov.object_as == 'BOX':
- tab_write("#declare %s = box { -1,1\n" % povdataname)
- if ob.active_material:
- # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
- try:
- material = ob.active_material
- write_object_material_interior(material, ob, tab_write)
- except IndexError:
- print(me)
- # tab_write("texture {%s}\n"%pov_mat_name)
- write_object_modifiers(scene, ob, file)
- # tab_write("rotate x*90\n")
- tab_write("}\n")
- continue # Don't render proxy mesh, skip to next object
-
- if ob.pov.object_as == 'CONE':
- br = ob.pov.cone_base_radius
- cr = ob.pov.cone_cap_radius
- bz = ob.pov.cone_base_z
- cz = ob.pov.cone_cap_z
- tab_write(
- "#declare %s = cone { <0,0,%.4f>,%.4f,<0,0,%.4f>,%.4f\n"
- % (povdataname, bz, br, cz, cr)
- )
- if ob.active_material:
- # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
- try:
- material = ob.active_material
- write_object_material_interior(material, ob, tab_write)
- except IndexError:
- print(me)
- # tab_write("texture {%s}\n"%pov_mat_name)
- write_object_modifiers(scene, ob, file)
- # tab_write("rotate x*90\n")
- tab_write("}\n")
- continue # Don't render proxy mesh, skip to next object
-
- if ob.pov.object_as == 'CYLINDER':
- r = ob.pov.cylinder_radius
- x2 = ob.pov.cylinder_location_cap[0]
- y2 = ob.pov.cylinder_location_cap[1]
- z2 = ob.pov.cylinder_location_cap[2]
- tab_write(
- "#declare %s = cylinder { <0,0,0>,<%6f,%6f,%6f>,%6f\n"
- % (povdataname, x2, y2, z2, r)
- )
- if ob.active_material:
- # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
- try:
- material = ob.active_material
- write_object_material_interior(material, ob, tab_write)
- except IndexError:
- print(me)
- # tab_write("texture {%s}\n"%pov_mat_name)
- # cylinders written at origin, translated below
- write_object_modifiers(scene, ob, file)
- # tab_write("rotate x*90\n")
- tab_write("}\n")
- continue # Don't render proxy mesh, skip to next object
-
- if ob.pov.object_as == 'HEIGHT_FIELD':
- data = ""
- filename = ob.pov.hf_filename
- data += '"%s"' % filename
- gamma = ' gamma %.4f' % ob.pov.hf_gamma
- data += gamma
- if ob.pov.hf_premultiplied:
- data += ' premultiplied on'
- if ob.pov.hf_smooth:
- data += ' smooth'
- if ob.pov.hf_water > 0:
- data += ' water_level %.4f' % ob.pov.hf_water
- # hierarchy = ob.pov.hf_hierarchy
- tab_write('#declare %s = height_field { %s\n' % (povdataname, data))
- if ob.active_material:
- # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
- try:
- material = ob.active_material
- write_object_material_interior(material, ob, tab_write)
- except IndexError:
- print(me)
- # tab_write("texture {%s}\n"%pov_mat_name)
- write_object_modifiers(scene, ob, file)
- tab_write("rotate x*90\n")
- tab_write("translate <-0.5,0.5,0>\n")
- tab_write("scale <0,-1,0>\n")
- tab_write("}\n")
- continue # Don't render proxy mesh, skip to next object
-
- if ob.pov.object_as == 'SPHERE':
-
- tab_write(
- "#declare %s = sphere { 0,%6f\n" % (povdataname, ob.pov.sphere_radius)
- )
- if ob.active_material:
- # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
- try:
- material = ob.active_material
- write_object_material_interior(material, ob, tab_write)
- except IndexError:
- print(me)
- # tab_write("texture {%s}\n"%pov_mat_name)
- write_object_modifiers(scene, ob, file)
- # tab_write("rotate x*90\n")
- tab_write("}\n")
- continue # Don't render proxy mesh, skip to next object
-
- if ob.pov.object_as == 'TORUS':
- tab_write(
- "#declare %s = torus { %.4f,%.4f\n"
- % (povdataname, ob.pov.torus_major_radius, ob.pov.torus_minor_radius)
- )
- if ob.active_material:
- # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name))
- try:
- material = ob.active_material
- write_object_material_interior(material, ob, tab_write)
- except IndexError:
- print(me)
- # tab_write("texture {%s}\n"%pov_mat_name)
- write_object_modifiers(scene, ob, file)
- tab_write("rotate x*90\n")
- tab_write("}\n")
- continue # Don't render proxy mesh, skip to next object
-
- if ob.pov.object_as == 'PARAMETRIC':
- tab_write("#declare %s = parametric {\n" % povdataname)
- tab_write("function { %s }\n" % ob.pov.x_eq)
- tab_write("function { %s }\n" % ob.pov.y_eq)
- tab_write("function { %s }\n" % ob.pov.z_eq)
- tab_write(
- "<%.4f,%.4f>, <%.4f,%.4f>\n"
- % (ob.pov.u_min, ob.pov.v_min, ob.pov.u_max, ob.pov.v_max)
- )
- # Previous to 3.8 default max_gradient 1.0 was too slow
- tab_write("max_gradient 0.001\n")
- if ob.pov.contained_by == "sphere":
- tab_write("contained_by { sphere{0, 2} }\n")
- else:
- tab_write("contained_by { box{-2, 2} }\n")
- tab_write("max_gradient %.6f\n" % ob.pov.max_gradient)
- tab_write("accuracy %.6f\n" % ob.pov.accuracy)
- tab_write("precompute 10 x,y,z\n")
- tab_write("}\n")
- continue # Don't render proxy mesh, skip to next object
-
- if ob.pov.object_as == 'POLYCIRCLE':
- # TODO write below macro Once:
- # if write_polytocircle_macro_once == 0:
- file.write("/****************************\n")
- file.write("This macro was written by 'And'.\n")
- file.write("Link:(http://news.povray.org/povray.binaries.scene-files/)\n")
- file.write("****************************/\n")
- file.write("//from math.inc:\n")
- file.write("#macro VPerp_Adjust(V, Axis)\n")
- file.write(" vnormalize(vcross(vcross(Axis, V), Axis))\n")
- file.write("#end\n")
- file.write("//Then for the actual macro\n")
- file.write("#macro Shape_Slice_Plane_2P_1V(point1, point2, clip_direct)\n")
- file.write("#local p1 = point1 + <0,0,0>;\n")
- file.write("#local p2 = point2 + <0,0,0>;\n")
- file.write("#local clip_v = vnormalize(clip_direct + <0,0,0>);\n")
- file.write("#local direct_v1 = vnormalize(p2 - p1);\n")
- file.write("#if(vdot(direct_v1, clip_v) = 1)\n")
- file.write(' #error "Shape_Slice_Plane_2P_1V error: Can\'t decide plane"\n')
- file.write("#end\n\n")
- file.write(
- "#local norm = -vnormalize(clip_v - direct_v1*vdot(direct_v1,clip_v));\n"
- )
- file.write("#local d = vdot(norm, p1);\n")
- file.write("plane{\n")
- file.write("norm, d\n")
- file.write("}\n")
- file.write("#end\n\n")
- file.write("//polygon to circle\n")
- file.write(
- "#macro Shape_Polygon_To_Circle_Blending(_polygon_n, _side_face, _polygon_circumscribed_radius, _circle_radius, _height)\n"
- )
- file.write("#local n = int(_polygon_n);\n")
- file.write("#if(n < 3)\n")
- file.write(" #error " "\n")
- file.write("#end\n\n")
- file.write("#local front_v = VPerp_Adjust(_side_face, z);\n")
- file.write("#if(vdot(front_v, x) >= 0)\n")
- file.write(" #local face_ang = acos(vdot(-y, front_v));\n")
- file.write("#else\n")
- file.write(" #local face_ang = -acos(vdot(-y, front_v));\n")
- file.write("#end\n")
- file.write("#local polyg_ext_ang = 2*pi/n;\n")
- file.write("#local polyg_outer_r = _polygon_circumscribed_radius;\n")
- file.write("#local polyg_inner_r = polyg_outer_r*cos(polyg_ext_ang/2);\n")
- file.write("#local cycle_r = _circle_radius;\n")
- file.write("#local h = _height;\n")
- file.write("#if(polyg_outer_r < 0 | cycle_r < 0 | h <= 0)\n")
- file.write(' #error "error: each side length must be positive"\n')
- file.write("#end\n\n")
- file.write("#local multi = 1000;\n")
- file.write("#local poly_obj =\n")
- file.write("polynomial{\n")
- file.write("4,\n")
- file.write("xyz(0,2,2): multi*1,\n")
- file.write("xyz(2,0,1): multi*2*h,\n")
- file.write("xyz(1,0,2): multi*2*(polyg_inner_r-cycle_r),\n")
- file.write("xyz(2,0,0): multi*(-h*h),\n")
- file.write("xyz(0,0,2): multi*(-pow(cycle_r - polyg_inner_r, 2)),\n")
- file.write("xyz(1,0,1): multi*2*h*(-2*polyg_inner_r + cycle_r),\n")
- file.write("xyz(1,0,0): multi*2*h*h*polyg_inner_r,\n")
- file.write("xyz(0,0,1): multi*2*h*polyg_inner_r*(polyg_inner_r - cycle_r),\n")
- file.write("xyz(0,0,0): multi*(-pow(polyg_inner_r*h, 2))\n")
- file.write("sturm\n")
- file.write("}\n\n")
- file.write("#local mockup1 =\n")
- file.write("difference{\n")
- file.write(" cylinder{\n")
- file.write(" <0,0,0.0>,<0,0,h>, max(polyg_outer_r, cycle_r)\n")
- file.write(" }\n\n")
- file.write(" #for(i, 0, n-1)\n")
- file.write(" object{\n")
- file.write(" poly_obj\n")
- file.write(" inverse\n")
- file.write(" rotate <0, 0, -90 + degrees(polyg_ext_ang*i)>\n")
- file.write(" }\n")
- file.write(" object{\n")
- file.write(
- " Shape_Slice_Plane_2P_1V(<polyg_inner_r,0,0>,<cycle_r,0,h>,x)\n"
- )
- file.write(" rotate <0, 0, -90 + degrees(polyg_ext_ang*i)>\n")
- file.write(" }\n")
- file.write(" #end\n")
- file.write("}\n\n")
- file.write("object{\n")
- file.write("mockup1\n")
- file.write("rotate <0, 0, degrees(face_ang)>\n")
- file.write("}\n")
- file.write("#end\n")
- # Use the macro
- ngon = ob.pov.polytocircle_ngon
- ngonR = ob.pov.polytocircle_ngonR
- circleR = ob.pov.polytocircle_circleR
- tab_write(
- "#declare %s = object { Shape_Polygon_To_Circle_Blending(%s, z, %.4f, %.4f, 2) rotate x*180 translate z*1\n"
- % (povdataname, ngon, ngonR, circleR)
- )
- tab_write("}\n")
- continue # Don't render proxy mesh, skip to next object
-
- # Implicit else-if (as not skipped by previous "continue") Keep this last.
+ # Implicit else-if (as not skipped by previous "continue")
+ # which itself has no "continue" (to combine custom pov code)?, so Keep this last.
# For originals, but not their instances, attempt to export mesh:
if not ob.is_instancer:
# except duplis which should be instances groups for now but all duplis later
if ob.type == 'EMPTY':
# XXX Should we only write this once and instantiate the same for every
- # empty in the final matrix writing, or even no marix and just a comment
+ # empty in the final matrix writing, or even no matrix and just a comment
# with empty object transforms ?
tab_write("\n//dummy sphere to represent Empty location\n")
tab_write(
@@ -730,7 +374,7 @@ def export_meshes(
)
continue # Don't render empty object but this is later addition, watch it.
- ob_eval = ob # not sure this is needed in case to_mesh_clear could damage ob ?
+ ob_eval = ob # not sure this is needed in case to_mesh_clear could damage obj ?
try:
me = ob_eval.to_mesh()
@@ -886,7 +530,7 @@ def export_meshes(
print('An exception occurred: {}'.format(e))
material = None
if (
- material
+ material
): # and material.use_vertex_color_paint: #Always use vertex color when there is some for now
cols = [vcol_layer[loop_index].color[:] for loop_index in f.loops]
@@ -953,7 +597,7 @@ def export_meshes(
cols = [vcol_layer[loop_index].color[:] for loop_index in f.loops]
if (
- not me_materials or me_materials[material_index] is None
+ not me_materials or me_materials[material_index] is None
): # No materials
if linebreaksinlists:
file.write(",\n")
@@ -1085,21 +729,7 @@ def export_meshes(
tab_write("}\n")
# XXX BOOLEAN
- onceCSG = 0
- for mod in ob.modifiers:
- if onceCSG == 0:
- if mod:
- if mod.type == 'BOOLEAN':
- if ob.pov.boolean_mod == "POV":
- file.write(
- "\tinside_vector <%.6g, %.6g, %.6g>\n"
- % (
- ob.pov.inside_vector[0],
- ob.pov.inside_vector[1],
- ob.pov.inside_vector[2],
- )
- )
- onceCSG = 1
+ write_object_csg_inside_vector(ob, file)
if me.materials:
try:
@@ -1110,7 +740,7 @@ def export_meshes(
# POV object modifiers such as
# hollow / sturm / double_illuminate etc.
- write_object_modifiers(scene, ob, file)
+ write_object_modifiers(ob, file)
# Importance for radiosity sampling added here:
tab_write("radiosity { \n")
@@ -1128,7 +758,7 @@ def export_meshes(
for i, material in enumerate(me_materials):
if (
- material and material.pov.material_use_nodes is False
+ material and material.pov.material_use_nodes is False
): # WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# Multiply diffuse with SSS Color
if material.pov_subsurface_scattering.use:
@@ -1157,7 +787,7 @@ def export_meshes(
vertCols[key] = [-1]
idx = 0
- local_material_names = [] #XXX track and revert
+ local_material_names = [] # XXX track and revert
material_finish = None
for col, index in vertCols.items():
# if me_materials:
@@ -1194,7 +824,7 @@ def export_meshes(
else:
file.write(tab_str + "%s" % (len(vertCols))) # vert count
- # below "material" alias, added check ob.active_material
+ # below "material" alias, added check obj.active_material
# to avoid variable referenced before assignment error
try:
material = ob.active_material
@@ -1204,9 +834,9 @@ def export_meshes(
# WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (
- material
- and ob.active_material is not None
- and not material.pov.material_use_nodes
+ material
+ and ob.active_material is not None
+ and not material.pov.material_use_nodes
):
if material.pov.replacement_text != "":
file.write("\n")
@@ -1243,7 +873,7 @@ def export_meshes(
cols = [vcol_layer[loop_index].color[:] for loop_index in f.loops]
if (
- not me_materials or me_materials[material_index] is None
+ not me_materials or me_materials[material_index] is None
): # No materials
if linebreaksinlists:
file.write(",\n")
@@ -1377,22 +1007,7 @@ def export_meshes(
tab_write("}\n")
# XXX BOOLEAN
- onceCSG = 0
- for mod in ob.modifiers:
- if onceCSG == 0:
- if mod:
- if mod.type == 'BOOLEAN':
- if ob.pov.boolean_mod == "POV":
- file.write(
- "\tinside_vector <%.6g, %.6g, %.6g>\n"
- % (
- ob.pov.inside_vector[0],
- ob.pov.inside_vector[1],
- ob.pov.inside_vector[2],
- )
- )
- onceCSG = 1
-
+ write_object_csg_inside_vector(ob, file)
if me.materials:
try:
material = me.materials[0] # dodgy
@@ -1402,7 +1017,7 @@ def export_meshes(
# POV object modifiers such as
# hollow / sturm / double_illuminate etc.
- write_object_modifiers(scene, ob, file)
+ write_object_modifiers(ob, file)
# Importance for radiosity sampling added here:
tab_write("radiosity { \n")
@@ -1412,15 +1027,426 @@ def export_meshes(
tab_write("}\n") # End of mesh block
ob_eval.to_mesh_clear()
+ continue
+ # ------------ Povray Primitives ------------ #
+ # Also implicit elif (continue) clauses and sorted after mesh
+ # as less often used.
+ if ob.pov.object_as == 'PLANE':
+ tab_write("#declare %s = plane{ <0,0,1>,0\n" % povdataname)
+ if ob.active_material:
+ # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(obj.active_material.name))
+ try:
+ material = ob.active_material
+ write_object_material_interior(material, ob, tab_write)
+ except IndexError:
+ print(me)
+ # tab_write("texture {%s}\n"%pov_mat_name)
+ write_object_modifiers(ob, file)
+ # tab_write("rotate x*90\n")
+ tab_write("}\n")
+ continue # Don't render proxy mesh, skip to next object
+
+ if ob.pov.object_as == 'SPHERE':
+
+ tab_write(
+ "#declare %s = sphere { 0,%6f\n" % (povdataname, ob.pov.sphere_radius)
+ )
+ if ob.active_material:
+ # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(obj.active_material.name))
+ try:
+ material = ob.active_material
+ write_object_material_interior(material, ob, tab_write)
+ except IndexError:
+ print(me)
+ # tab_write("texture {%s}\n"%pov_mat_name)
+ write_object_modifiers(ob, file)
+ # tab_write("rotate x*90\n")
+ tab_write("}\n")
+ continue # Don't render proxy mesh, skip to next object
+
+ if ob.pov.object_as == 'BOX':
+ tab_write("#declare %s = box { -1,1\n" % povdataname)
+ if ob.active_material:
+ # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(obj.active_material.name))
+ try:
+ material = ob.active_material
+ write_object_material_interior(material, ob, tab_write)
+ except IndexError:
+ print(me)
+ # tab_write("texture {%s}\n"%pov_mat_name)
+ write_object_modifiers(ob, file)
+ # tab_write("rotate x*90\n")
+ tab_write("}\n")
+ continue # Don't render proxy mesh, skip to next object
+
+ if ob.pov.object_as == 'CONE':
+ br = ob.pov.cone_base_radius
+ cr = ob.pov.cone_cap_radius
+ bz = ob.pov.cone_base_z
+ cz = ob.pov.cone_cap_z
+ tab_write(
+ "#declare %s = cone { <0,0,%.4f>,%.4f,<0,0,%.4f>,%.4f\n"
+ % (povdataname, bz, br, cz, cr)
+ )
+ if ob.active_material:
+ # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(obj.active_material.name))
+ try:
+ material = ob.active_material
+ write_object_material_interior(material, ob, tab_write)
+ except IndexError:
+ print(me)
+ # tab_write("texture {%s}\n"%pov_mat_name)
+ write_object_modifiers(ob, file)
+ # tab_write("rotate x*90\n")
+ tab_write("}\n")
+ continue # Don't render proxy mesh, skip to next object
+
+ if ob.pov.object_as == 'CYLINDER':
+ r = ob.pov.cylinder_radius
+ x2 = ob.pov.cylinder_location_cap[0]
+ y2 = ob.pov.cylinder_location_cap[1]
+ z2 = ob.pov.cylinder_location_cap[2]
+ tab_write(
+ "#declare %s = cylinder { <0,0,0>,<%6f,%6f,%6f>,%6f\n"
+ % (povdataname, x2, y2, z2, r)
+ )
+ if ob.active_material:
+ # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(obj.active_material.name))
+ try:
+ material = ob.active_material
+ write_object_material_interior(material, ob, tab_write)
+ except IndexError:
+ print(me)
+ # tab_write("texture {%s}\n"%pov_mat_name)
+ # cylinders written at origin, translated below
+ write_object_modifiers(ob, file)
+ # tab_write("rotate x*90\n")
+ tab_write("}\n")
+ continue # Don't render proxy mesh, skip to next object
+
+ if ob.pov.object_as == 'HEIGHT_FIELD':
+ data = ""
+ filename = ob.pov.hf_filename
+ data += '"%s"' % filename
+ gamma = ' gamma %.4f' % ob.pov.hf_gamma
+ data += gamma
+ if ob.pov.hf_premultiplied:
+ data += ' premultiplied on'
+ if ob.pov.hf_smooth:
+ data += ' smooth'
+ if ob.pov.hf_water > 0:
+ data += ' water_level %.4f' % ob.pov.hf_water
+ # hierarchy = obj.pov.hf_hierarchy
+ tab_write('#declare %s = height_field { %s\n' % (povdataname, data))
+ if ob.active_material:
+ # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(obj.active_material.name))
+ try:
+ material = ob.active_material
+ write_object_material_interior(material, ob, tab_write)
+ except IndexError:
+ print(me)
+ # tab_write("texture {%s}\n"%pov_mat_name)
+ write_object_modifiers(ob, file)
+ tab_write("rotate x*90\n")
+ tab_write("translate <-0.5,0.5,0>\n")
+ tab_write("scale <0,-1,0>\n")
+ tab_write("}\n")
+ continue # Don't render proxy mesh, skip to next object
+
+ if ob.pov.object_as == 'TORUS':
+ tab_write(
+ "#declare %s = torus { %.4f,%.4f\n"
+ % (povdataname, ob.pov.torus_major_radius, ob.pov.torus_minor_radius)
+ )
+ if ob.active_material:
+ # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(obj.active_material.name))
+ try:
+ material = ob.active_material
+ write_object_material_interior(material, ob, tab_write)
+ except IndexError:
+ print(me)
+ # tab_write("texture {%s}\n"%pov_mat_name)
+ write_object_modifiers(ob, file)
+ tab_write("rotate x*90\n")
+ tab_write("}\n")
+ continue # Don't render proxy mesh, skip to next object
+
+ if ob.pov.object_as == 'PARAMETRIC':
+ tab_write("#declare %s = parametric {\n" % povdataname)
+ tab_write("function { %s }\n" % ob.pov.x_eq)
+ tab_write("function { %s }\n" % ob.pov.y_eq)
+ tab_write("function { %s }\n" % ob.pov.z_eq)
+ tab_write(
+ "<%.4f,%.4f>, <%.4f,%.4f>\n"
+ % (ob.pov.u_min, ob.pov.v_min, ob.pov.u_max, ob.pov.v_max)
+ )
+ # Previous to 3.8 default max_gradient 1.0 was too slow
+ tab_write("max_gradient 0.001\n")
+ if ob.pov.contained_by == "sphere":
+ tab_write("contained_by { sphere{0, 2} }\n")
+ else:
+ tab_write("contained_by { box{-2, 2} }\n")
+ tab_write("max_gradient %.6f\n" % ob.pov.max_gradient)
+ tab_write("accuracy %.6f\n" % ob.pov.accuracy)
+ tab_write("precompute 10 x,y,z\n")
+ tab_write("}\n")
+ continue # Don't render proxy mesh, skip to next object
+
+ if ob.pov.object_as == 'ISOSURFACE_NODE':
+ tab_write("#declare %s = isosurface{ \n" % povdataname)
+ tab_write("function{ \n")
+ text_name = ob.pov.iso_function_text
+ if text_name:
+ node_tree = bpy.context.scene.node_tree
+ for node in node_tree.nodes:
+ if node.bl_idname == "IsoPropsNode" and node.label == ob.name:
+ for inp in node.inputs:
+ if inp:
+ tab_write(
+ "#declare %s = %.6g;\n" % (inp.name, inp.default_value)
+ )
+
+ text = bpy.data.texts[text_name]
+ for line in text.lines:
+ split = line.body.split()
+ if split[0] != "#declare":
+ tab_write("%s\n" % line.body)
+ else:
+ tab_write("abs(x) - 2 + y")
+ tab_write("}\n")
+ tab_write("threshold %.6g\n" % ob.pov.threshold)
+ tab_write("max_gradient %.6g\n" % ob.pov.max_gradient)
+ tab_write("accuracy %.6g\n" % ob.pov.accuracy)
+ tab_write("contained_by { ")
+ if ob.pov.contained_by == "sphere":
+ tab_write("sphere {0,%.6g}}\n" % ob.pov.container_scale)
+ else:
+ tab_write(
+ "box {-%.6g,%.6g}}\n" % (ob.pov.container_scale, ob.pov.container_scale)
+ )
+ if ob.pov.all_intersections:
+ tab_write("all_intersections\n")
+ else:
+ if ob.pov.max_trace > 1:
+ tab_write("max_trace %.6g\n" % ob.pov.max_trace)
+ if ob.active_material:
+ # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(obj.active_material.name))
+ try:
+ material = ob.active_material
+ write_object_material_interior(material, ob, tab_write)
+ except IndexError:
+ print(me)
+ # tab_write("texture {%s}\n"%pov_mat_name)
+ tab_write("scale %.6g\n" % (1 / ob.pov.container_scale))
+ tab_write("}\n")
+ continue # Don't render proxy mesh, skip to next object
+
+ if ob.pov.object_as == 'ISOSURFACE_VIEW':
+ simple_isosurface_function = ob.pov.isosurface_eq
+ if simple_isosurface_function:
+ tab_write("#declare %s = isosurface{ \n" % povdataname)
+ tab_write("function{ \n")
+ tab_write(simple_isosurface_function)
+ tab_write("}\n")
+ tab_write("threshold %.6g\n" % ob.pov.threshold)
+ tab_write("max_gradient %.6g\n" % ob.pov.max_gradient)
+ tab_write("accuracy %.6g\n" % ob.pov.accuracy)
+ tab_write("contained_by { ")
+ if ob.pov.contained_by == "sphere":
+ tab_write("sphere {0,%.6g}}\n" % ob.pov.container_scale)
+ else:
+ tab_write(
+ "box {-%.6g,%.6g}}\n" % (ob.pov.container_scale, ob.pov.container_scale)
+ )
+ if ob.pov.all_intersections:
+ tab_write("all_intersections\n")
+ else:
+ if ob.pov.max_trace > 1:
+ tab_write("max_trace %.6g\n" % ob.pov.max_trace)
+ if ob.active_material:
+ # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(obj.active_material.name))
+ try:
+ material = ob.active_material
+ write_object_material_interior(material, ob, tab_write)
+ except IndexError:
+ print(me)
+ # tab_write("texture {%s}\n"%pov_mat_name)
+ tab_write("scale %.6g\n" % (1 / ob.pov.container_scale))
+ tab_write("}\n")
+ continue # Don't render proxy mesh, skip to next object
+
+ if ob.pov.object_as == 'SUPERELLIPSOID':
+ tab_write(
+ "#declare %s = superellipsoid{ <%.4f,%.4f>\n"
+ % (povdataname, ob.pov.se_n2, ob.pov.se_n1)
+ )
+ if ob.active_material:
+ # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(obj.active_material.name))
+ try:
+ material = ob.active_material
+ write_object_material_interior(material, ob, tab_write)
+ except IndexError:
+ print(me)
+ # tab_write("texture {%s}\n"%pov_mat_name)
+ write_object_modifiers(ob, file)
+ tab_write("}\n")
+ continue # Don't render proxy mesh, skip to next object
+
+ if ob.pov.object_as == 'SUPERTORUS':
+ rad_maj = ob.pov.st_major_radius
+ rad_min = ob.pov.st_minor_radius
+ ring = ob.pov.st_ring
+ cross = ob.pov.st_cross
+ accuracy = ob.pov.st_accuracy
+ gradient = ob.pov.st_max_gradient
+ # --- Inline Supertorus macro
+ file.write(
+ "#macro Supertorus(RMj, RMn, MajorControl, MinorControl, Accuracy, MaxGradient)\n"
+ )
+ file.write(" #local CP = 2/MinorControl;\n")
+ file.write(" #local RP = 2/MajorControl;\n")
+ file.write(" isosurface {\n")
+ file.write(
+ " function { pow( pow(abs(pow(pow(abs(x),RP) + pow(abs(z),RP), 1/RP) - RMj),CP) + pow(abs(y),CP) ,1/CP) - RMn }\n"
+ )
+ file.write(" threshold 0\n")
+ file.write(
+ " contained_by {box {<-RMj-RMn,-RMn,-RMj-RMn>, < RMj+RMn, RMn, RMj+RMn>}}\n"
+ )
+ file.write(" #if(MaxGradient >= 1)\n")
+ file.write(" max_gradient MaxGradient\n")
+ file.write(" #else\n")
+ file.write(" evaluate 1, 10, 0.1\n")
+ file.write(" #end\n")
+ file.write(" accuracy Accuracy\n")
+ file.write(" }\n")
+ file.write("#end\n")
+ # ---
+ tab_write(
+ "#declare %s = object{ Supertorus( %.4g,%.4g,%.4g,%.4g,%.4g,%.4g)\n"
+ % (povdataname, rad_maj, rad_min, ring, cross, accuracy, gradient)
+ )
+ if ob.active_material:
+ # pov_mat_name = string_strip_hyphen(bpy.path.clean_name(obj.active_material.name))
+ try:
+ material = ob.active_material
+ write_object_material_interior(material, ob, tab_write)
+ except IndexError:
+ print(me)
+ # tab_write("texture {%s}\n"%pov_mat_name)
+ write_object_modifiers(ob, file)
+ tab_write("rotate x*90\n")
+ tab_write("}\n")
+ continue # Don't render proxy mesh, skip to next object
+
+ if ob.pov.object_as == 'POLYCIRCLE':
+ # TODO write below macro Once:
+ # if write_polytocircle_macro_once == 0:
+ file.write("/****************************\n")
+ file.write("This macro was written by 'And'.\n")
+ file.write("Link:(http://news.povray.org/povray.binaries.scene-files/)\n")
+ file.write("****************************/\n")
+ file.write("//from math.inc:\n")
+ file.write("#macro VPerp_Adjust(V, Axis)\n")
+ file.write(" vnormalize(vcross(vcross(Axis, V), Axis))\n")
+ file.write("#end\n")
+ file.write("//Then for the actual macro\n")
+ file.write("#macro Shape_Slice_Plane_2P_1V(point1, point2, clip_direct)\n")
+ file.write("#local p1 = point1 + <0,0,0>;\n")
+ file.write("#local p2 = point2 + <0,0,0>;\n")
+ file.write("#local clip_v = vnormalize(clip_direct + <0,0,0>);\n")
+ file.write("#local direct_v1 = vnormalize(p2 - p1);\n")
+ file.write("#if(vdot(direct_v1, clip_v) = 1)\n")
+ file.write(' #error "Shape_Slice_Plane_2P_1V error: Can\'t decide plane"\n')
+ file.write("#end\n\n")
+ file.write(
+ "#local norm = -vnormalize(clip_v - direct_v1*vdot(direct_v1,clip_v));\n"
+ )
+ file.write("#local d = vdot(norm, p1);\n")
+ file.write("plane{\n")
+ file.write("norm, d\n")
+ file.write("}\n")
+ file.write("#end\n\n")
+ file.write("//polygon to circle\n")
+ file.write(
+ "#macro Shape_Polygon_To_Circle_Blending(_polygon_n, _side_face, _polygon_circumscribed_radius, _circle_radius, _height)\n"
+ )
+ file.write("#local n = int(_polygon_n);\n")
+ file.write("#if(n < 3)\n")
+ file.write(" #error " "\n")
+ file.write("#end\n\n")
+ file.write("#local front_v = VPerp_Adjust(_side_face, z);\n")
+ file.write("#if(vdot(front_v, x) >= 0)\n")
+ file.write(" #local face_ang = acos(vdot(-y, front_v));\n")
+ file.write("#else\n")
+ file.write(" #local face_ang = -acos(vdot(-y, front_v));\n")
+ file.write("#end\n")
+ file.write("#local polyg_ext_ang = 2*pi/n;\n")
+ file.write("#local polyg_outer_r = _polygon_circumscribed_radius;\n")
+ file.write("#local polyg_inner_r = polyg_outer_r*cos(polyg_ext_ang/2);\n")
+ file.write("#local cycle_r = _circle_radius;\n")
+ file.write("#local h = _height;\n")
+ file.write("#if(polyg_outer_r < 0 | cycle_r < 0 | h <= 0)\n")
+ file.write(' #error "error: each side length must be positive"\n')
+ file.write("#end\n\n")
+ file.write("#local multi = 1000;\n")
+ file.write("#local poly_obj =\n")
+ file.write("polynomial{\n")
+ file.write("4,\n")
+ file.write("xyz(0,2,2): multi*1,\n")
+ file.write("xyz(2,0,1): multi*2*h,\n")
+ file.write("xyz(1,0,2): multi*2*(polyg_inner_r-cycle_r),\n")
+ file.write("xyz(2,0,0): multi*(-h*h),\n")
+ file.write("xyz(0,0,2): multi*(-pow(cycle_r - polyg_inner_r, 2)),\n")
+ file.write("xyz(1,0,1): multi*2*h*(-2*polyg_inner_r + cycle_r),\n")
+ file.write("xyz(1,0,0): multi*2*h*h*polyg_inner_r,\n")
+ file.write("xyz(0,0,1): multi*2*h*polyg_inner_r*(polyg_inner_r - cycle_r),\n")
+ file.write("xyz(0,0,0): multi*(-pow(polyg_inner_r*h, 2))\n")
+ file.write("sturm\n")
+ file.write("}\n\n")
+ file.write("#local mockup1 =\n")
+ file.write("difference{\n")
+ file.write(" cylinder{\n")
+ file.write(" <0,0,0.0>,<0,0,h>, max(polyg_outer_r, cycle_r)\n")
+ file.write(" }\n\n")
+ file.write(" #for(i, 0, n-1)\n")
+ file.write(" object{\n")
+ file.write(" poly_obj\n")
+ file.write(" inverse\n")
+ file.write(" rotate <0, 0, -90 + degrees(polyg_ext_ang*i)>\n")
+ file.write(" }\n")
+ file.write(" object{\n")
+ file.write(
+ " Shape_Slice_Plane_2P_1V(<polyg_inner_r,0,0>,<cycle_r,0,h>,x)\n"
+ )
+ file.write(" rotate <0, 0, -90 + degrees(polyg_ext_ang*i)>\n")
+ file.write(" }\n")
+ file.write(" #end\n")
+ file.write("}\n\n")
+ file.write("object{\n")
+ file.write("mockup1\n")
+ file.write("rotate <0, 0, degrees(face_ang)>\n")
+ file.write("}\n")
+ file.write("#end\n")
+ # Use the macro
+ ngon = ob.pov.polytocircle_ngon
+ ngonR = ob.pov.polytocircle_ngonR
+ circleR = ob.pov.polytocircle_circleR
+ tab_write(
+ "#declare %s = object { Shape_Polygon_To_Circle_Blending(%s, z, %.4f, %.4f, 2) rotate x*180 translate z*1\n"
+ % (povdataname, ngon, ngonR, circleR)
+ )
+ tab_write("}\n")
+ continue # Don't render proxy mesh, skip to next object
if csg:
duplidata_ref = []
_dupnames_seen = dict() # avoid duplicate output during introspection
for ob in sel:
- # matrix = global_matrix @ ob.matrix_world
+ # matrix = global_matrix @ obj.matrix_world
if ob.is_instancer:
tab_write("\n//--DupliObjects in %s--\n\n" % ob.name)
- # ob.dupli_list_create(scene) #deprecated in 2.8
+ # obj.dupli_list_create(scene) #deprecated in 2.8
dup = ""
if ob.is_modified(scene, 'RENDER'):
# modified object always unique so using object name rather than data name
@@ -1433,7 +1459,7 @@ def export_meshes(
)
for eachduplicate in depsgraph.object_instances:
if (
- eachduplicate.is_instance
+ eachduplicate.is_instance
): # Real dupli instance filtered because original included in list since 2.8
_dupname = eachduplicate.object.name
_dupobj = bpy.data.objects[_dupname]
@@ -1450,7 +1476,7 @@ def export_meshes(
% (_dupname, _thing, getattr(_dupobj, _thing))
)
_dupnames_seen[_dupname] = 1
- print("''=> Unparseable objects so far: %s" % (_dupnames_seen))
+ print("''=> Unparseable objects so far: %s" % _dupnames_seen)
else:
_dupnames_seen[_dupname] += 1
continue # don't try to parse data objects with no name attribute
@@ -1467,19 +1493,21 @@ def export_meshes(
)
# add object to a list so that it is not rendered for some instance_types
if (
- ob.instance_type not in {'COLLECTION'}
- and duplidataname not in duplidata_ref
+ ob.instance_type not in {'COLLECTION'}
+ and duplidataname not in duplidata_ref
):
duplidata_ref.append(
duplidataname
- ) # older key [string_strip_hyphen(bpy.path.clean_name("OB"+ob.name))]
+ ) # older key [string_strip_hyphen(bpy.path.clean_name("OB"+obj.name))]
dup += "}\n"
- # ob.dupli_list_clear()# just do not store any reference to instance since 2.8
+ # obj.dupli_list_clear()# just do not store any reference to instance since 2.8
tab_write(dup)
else:
continue
- print("WARNING: Unparseable objects in current .blend file:\n''=> %s" % (_dupnames_seen))
- print("duplidata_ref = %s" % (duplidata_ref))
+ if _dupnames_seen:
+ print("WARNING: Unparseable objects in current .blend file:\n''--> %s" % _dupnames_seen)
+ if duplidata_ref:
+ print("duplidata_ref = %s" % duplidata_ref)
for data_name, inst in data_ref.items():
for ob_name, matrix_str in inst:
if ob_name not in duplidata_ref: # .items() for a dictionary