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
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)
-rwxr-xr-xrender_povray/__init__.py114
-rwxr-xr-xrender_povray/base_ui.py323
-rw-r--r--render_povray/icons/pov.add.blobcapsule.datbin0 -> 8072 bytes
-rw-r--r--render_povray/icons/pov.add.blobcube.datbin0 -> 10880 bytes
-rw-r--r--render_povray/icons/pov.add.blobellipsoid.datbin0 -> 11654 bytes
-rw-r--r--render_povray/icons/pov.add.blobplane.datbin0 -> 9404 bytes
-rw-r--r--render_povray/icons/pov.add.blobsphere.datbin0 -> 8756 bytes
-rw-r--r--render_povray/icons/pov.add.box.datbin0 -> 4346 bytes
-rw-r--r--render_povray/icons/pov.add.cone.datbin0 -> 4742 bytes
-rw-r--r--render_povray/icons/pov.add.cylinder.datbin0 -> 5858 bytes
-rw-r--r--render_povray/icons/pov.add.heightfield.datbin0 -> 58112 bytes
-rw-r--r--render_povray/icons/pov.add.infinite_plane.datbin0 -> 8090 bytes
-rw-r--r--render_povray/icons/pov.add.isosurface.datbin0 -> 9422 bytes
-rw-r--r--render_povray/icons/pov.add.isosurfacebox.datbin0 -> 7262 bytes
-rw-r--r--render_povray/icons/pov.add.isosurfacesphere.datbin0 -> 14156 bytes
-rw-r--r--render_povray/icons/pov.add.isosurfacesupertorus.datbin0 -> 8306 bytes
-rw-r--r--render_povray/icons/pov.add.lathe.datbin0 -> 8576 bytes
-rw-r--r--render_povray/icons/pov.add.loft.datbin0 -> 17810 bytes
-rw-r--r--render_povray/icons/pov.add.parametric.datbin0 -> 9800 bytes
-rw-r--r--render_povray/icons/pov.add.polytocircle.datbin0 -> 5192 bytes
-rw-r--r--render_povray/icons/pov.add.prism.datbin0 -> 4382 bytes
-rw-r--r--render_povray/icons/pov.add.rainbow.datbin0 -> 9422 bytes
-rw-r--r--render_povray/icons/pov.add.sphere.datbin0 -> 11402 bytes
-rw-r--r--render_povray/icons/pov.add.spheresweep.datbin0 -> 9062 bytes
-rw-r--r--render_povray/icons/pov.add.superellipsoid.datbin0 -> 6092 bytes
-rw-r--r--render_povray/icons/pov.add.torus.datbin0 -> 5390 bytes
-rwxr-xr-xrender_povray/object_curve_topology.py22
-rwxr-xr-xrender_povray/object_gui.py553
-rwxr-xr-xrender_povray/object_mesh_topology.py1104
-rwxr-xr-xrender_povray/object_particles.py4
-rwxr-xr-xrender_povray/object_primitives.py287
-rwxr-xr-xrender_povray/object_properties.py8
-rwxr-xr-xrender_povray/render.py1584
-rwxr-xr-xrender_povray/render_gui.py53
-rwxr-xr-xrender_povray/render_properties.py13
-rwxr-xr-xrender_povray/scenography.py87
-rwxr-xr-xrender_povray/scripting.py6
-rwxr-xr-xrender_povray/scripting_gui.py18
-rwxr-xr-xrender_povray/scripting_properties.py2
-rwxr-xr-xrender_povray/shading.py42
-rwxr-xr-xrender_povray/shading_gui.py37
-rwxr-xr-xrender_povray/shading_nodes.py66
-rwxr-xr-xrender_povray/shading_properties.py26
-rwxr-xr-xrender_povray/texturing.py113
-rwxr-xr-xrender_povray/texturing_gui.py5
-rwxr-xr-xrender_povray/texturing_properties.py4
46 files changed, 2648 insertions, 1823 deletions
diff --git a/render_povray/__init__.py b/render_povray/__init__.py
index fe0de21f..47291895 100755
--- a/render_povray/__init__.py
+++ b/render_povray/__init__.py
@@ -33,8 +33,8 @@ base_ui.py :
scenography_properties.py
Initialize properties for translating Blender cam/light/environment parameters to pov
-scenography_gui.py
- Display cam/light/environment properties from situation_properties.py for user to change them
+scenography_gui.py :
+ Display cam/light/environment properties from scenography_properties.py for user to change them
scenography.py
Translate cam/light/environment properties to corresponding pov features
@@ -57,25 +57,25 @@ object_particles.py :
object_gui.py :
Display properties from object_properties.py for user to change them
-shading_properties.py
+shading_properties.py :
Initialize properties for translating Blender materials parameters to pov
-shading_nodes.py
+shading_nodes.py :
Translate node trees to the pov file
-shading_gui.py
+shading_gui.py :
Display properties from shading_properties.py for user to change them
shading.py
Translate shading properties to declared textures at the top of a pov file
-texturing_properties.py
+texturing_properties.py :
Initialize properties for translating Blender materials /world... texture influences to pov
-texturing_gui.py
+texturing_gui.py :
Display properties from texturing_properties.py for user to change them
-texturing.py
+texturing.py :
Translate blender texture influences into POV
render_properties.py :
@@ -96,10 +96,10 @@ scripting_gui.py :
scripting.py :
Insert POV native scene description elements into blender scene or to exported POV file
-df3_library.py
+df3_library.py :
Render smoke to *.df3 files
-update_files.py
+update_files.py :
Update new variables to values from older API. This file needs an update
@@ -151,8 +151,8 @@ Blender stand up to other POV IDEs such as povwin or QTPOV
bl_info = {
- "name": "Persistence of Vision",
- "author": "Campbell Barton, "
+ 'name': "Persistence of Vision",
+ 'author': "Campbell Barton, "
"Maurice Raybaud, "
"Leonid Desyatkov, "
"Bastien Montagne, "
@@ -160,12 +160,12 @@ bl_info = {
"Silvio Falcinelli,"
"Paco GarcĂ­a",
"version": (0, 1, 2),
- "blender": (2, 81, 0),
- "location": "Render Properties > Render Engine > Persistence of Vision",
- "description": "Persistence of Vision integration for blender",
- "doc_url": "{BLENDER_MANUAL_URL}/addons/render/povray.html",
- "category": "Render",
- "warning": "Co-maintainers welcome",
+ 'blender': (2, 81, 0),
+ 'location': "Render Properties > Render Engine > Persistence of Vision",
+ 'description': "Persistence of Vision integration for blender",
+ 'doc_url': "{BLENDER_MANUAL_URL}/addons/render/povray.html",
+ 'category': "Render",
+ 'warning': "Co-maintainers welcome",
}
# Other occasional contributors, more or less in chronological order:
@@ -222,7 +222,7 @@ else:
class POV_OT_update_addon(bpy.types.Operator):
- """Update this add-on to the latest version"""
+ """Update this addon to the latest version"""
bl_idname = "pov.update_addon"
bl_label = "Update POV addon"
@@ -250,8 +250,8 @@ class POV_OT_update_addon(bpy.types.Operator):
else:
shutil.copyfile(src, dest)
- print('-' * 20)
- print('Updating POV addon...')
+ print("-" * 20)
+ print("Updating POV addon...")
with tempfile.TemporaryDirectory() as temp_dir_path:
temp_zip_path = os.path.join(temp_dir_path, 'master.zip')
@@ -261,19 +261,19 @@ class POV_OT_update_addon(bpy.types.Operator):
# switch this URL back to the BF hosted one as soon as gitweb snapshot gets fixed
url = 'https://github.com/blender/blender-addons/archive/refs/heads/master.zip'
try:
- print('Downloading', url)
+ print("Downloading", url)
with urllib.request.urlopen(url, timeout=60) as url_handle, open(
temp_zip_path, 'wb'
) as file_handle:
file_handle.write(url_handle.read())
except urllib.error.URLError as err:
- self.report({'ERROR'}, 'Could not download: %s' % err)
+ self.report({'ERROR'}, "Could not download: %s" % err)
# Extract the zip
- print('Extracting ZIP archive')
- with zipfile.ZipFile(temp_zip_path) as zip:
- for member in zip.namelist():
+ print("Extracting ZIP archive")
+ with zipfile.ZipFile(temp_zip_path) as zip_archive:
+ for member in zip_archive.namelist():
if 'blender-addons-master/render_povray' in member:
# Remove the first directory and the filename
# e.g. blender-addons-master/render_povray/shading_nodes.py
@@ -291,7 +291,7 @@ class POV_OT_update_addon(bpy.types.Operator):
if not os.path.exists(target_path):
os.makedirs(target_path)
- source = zip.open(member)
+ source = zip_archive.open(member)
target = open(os.path.join(target_path, filename), "wb")
with source, target:
@@ -301,26 +301,26 @@ class POV_OT_update_addon(bpy.types.Operator):
extracted_render_povray_path = os.path.join(temp_dir_path, 'render_povray')
if not os.path.exists(extracted_render_povray_path):
- self.report({'ERROR'}, 'Could not extract ZIP archive! Aborting.')
+ self.report({'ERROR'}, "Could not extract ZIP archive! Aborting.")
return {'FINISHED'}
# Find the old POV addon files
render_povray_dir = os.path.abspath(os.path.dirname(__file__))
- print('POV addon addon folder:', render_povray_dir)
+ print("POV addon addon folder:", render_povray_dir)
# TODO: Create backup
# Delete old POV addon files
# (only directories and *.py files, user might have other stuff in there!)
- print('Deleting old POV addon files')
+ print("Deleting old POV addon files")
# remove __init__.py
os.remove(os.path.join(render_povray_dir, '__init__.py'))
# remove all folders
DIRNAMES = 1
- for dir in next(os.walk(render_povray_dir))[DIRNAMES]:
- shutil.rmtree(os.path.join(render_povray_dir, dir))
+ for directory in next(os.walk(render_povray_dir))[DIRNAMES]:
+ shutil.rmtree(os.path.join(render_povray_dir, directory))
- print('Copying new POV addon files')
+ print("Copying new POV addon files")
# copy new POV addon files
# copy __init__.py
shutil.copy2(
@@ -330,9 +330,9 @@ class POV_OT_update_addon(bpy.types.Operator):
recursive_overwrite(extracted_render_povray_path, render_povray_dir)
bpy.ops.preferences.addon_refresh()
- print('POV addon update finished, restart Blender for the changes to take effect.')
- print('-' * 20)
- self.report({'WARNING'}, 'Restart Blender!')
+ print("POV addon update finished, restart Blender for the changes to take effect.")
+ print("-" * 20)
+ self.report({'WARNING'}, "Restart Blender!")
return {'FINISHED'}
@@ -342,33 +342,33 @@ class POV_OT_update_addon(bpy.types.Operator):
class PovrayPreferences(bpy.types.AddonPreferences):
- """Declare preference variables to set up POV binary."""
+ """Declare preference variables to set up POV binary"""
bl_idname = __name__
branch_feature_set_povray: EnumProperty(
- name="Feature Set",
- description="Choose between official (POV-Ray) or (UberPOV) "
- "development branch features to write in the pov file",
+ name='Feature Set',
+ description='Choose between official (POV-Ray) or (UberPOV) '
+ 'development branch features to write in the pov file',
items=(
- ("povray", "Official POV-Ray", "", "PLUGIN", 0),
- ("uberpov", "Unofficial UberPOV", "", "PLUGIN", 1),
+ ('povray', 'Official POV-Ray', '', 'PLUGIN', 0),
+ ('uberpov', 'Unofficial UberPOV', '', 'PLUGIN', 1),
),
- default="povray",
+ default='povray',
)
filepath_povray: StringProperty(
- name="Binary Location", description="Path to renderer executable", subtype="FILE_PATH"
+ name='Binary Location', description='Path to renderer executable', subtype='FILE_PATH'
)
docpath_povray: StringProperty(
- name="Includes Location", description="Path to Insert Menu files", subtype="FILE_PATH"
+ name='Includes Location', description='Path to Insert Menu files', subtype='FILE_PATH'
)
use_sounds: BoolProperty(
- name="Use Sound",
- description="Signaling end of the render process at various"
- "stages can help if you're away from monitor",
+ name='Use Sound',
+ description='Signaling end of the render process at various'
+ 'stages can help if you\'re away from monitor',
default=False,
)
@@ -376,21 +376,21 @@ class PovrayPreferences(bpy.types.AddonPreferences):
# And implement the three cases, left uncommented for a dummy
# interface in case some doc screenshots get made for that area
filepath_complete_sound: StringProperty(
- name="Finish Render Sound",
- description="Path to finished render sound file",
- subtype="FILE_PATH",
+ name='Finish Render Sound',
+ description='Path to finished render sound file',
+ subtype='FILE_PATH',
)
filepath_parse_error_sound: StringProperty(
- name="Parse Error Sound",
- description="Path to parsing time error sound file",
- subtype="FILE_PATH",
+ name='Parse Error Sound',
+ description='Path to parsing time error sound file',
+ subtype='FILE_PATH',
)
filepath_cancel_sound: StringProperty(
- name="Cancel Render Sound",
- description="Path to cancelled or render time error sound file",
- subtype="FILE_PATH",
+ name='Cancel Render Sound',
+ description='Path to cancelled or render time error sound file',
+ subtype='FILE_PATH',
)
def draw(self, context):
diff --git a/render_povray/base_ui.py b/render_povray/base_ui.py
index 967080fa..e0bbd929 100755
--- a/render_povray/base_ui.py
+++ b/render_povray/base_ui.py
@@ -23,9 +23,10 @@
# import addon_utils
# from time import sleep
import bpy
-
+import os
from bpy.app.handlers import persistent
+from pathlib import Path
# from bpy.utils import register_class, unregister_class
# from bpy.types import (
@@ -70,169 +71,182 @@ def pov_centric_moray_like_workspace(dummy):
# we put all within a Try... Except AttributeErrors ? Any better solution ?
# Should it simply not run when opening existing file? be a preferences operator to create
# Moray like workspace
- if 'Scripting' in bpy.data.workspaces:
-
- wsp = bpy.data.workspaces.get('Scripting')
- context = bpy.context
- if context.scene.render.engine == 'POVRAY_RENDER' and wsp is not None:
- bpy.ops.workspace.duplicate({'workspace': wsp})
- bpy.data.workspaces['Scripting.001'].name = 'POV'
- # Already done it would seem, but explicitly make this workspace the active one
- context.window.workspace = bpy.data.workspaces['POV']
- pov_screen = bpy.data.workspaces['POV'].screens[0]
- pov_workspace = pov_screen.areas
- pov_window = context.window
- try:
- # Already outliners but invert both types
- pov_workspace[1].spaces[0].display_mode = 'LIBRARIES'
- pov_workspace[3].spaces[0].display_mode = 'VIEW_LAYER'
- except AttributeError:
- # But not necessarily outliners in existing blend files
- pass
- override = bpy.context.copy()
-
- for area in pov_workspace:
- if area.type == 'VIEW_3D':
- for region in [r for r in area.regions if r.type == 'WINDOW']:
- for space in area.spaces:
- if space.type == 'VIEW_3D':
- # override['screen'] = pov_screen
- override['area'] = area
- override['region'] = region
- # bpy.data.workspaces['POV'].screens[0].areas[6].spaces[0].width = 333 # Read only,
- # how do we set ?
- # This has a glitch:
- # bpy.ops.screen.area_move(override, x=(area.x + area.width), y=(area.y + 5), delta=100)
- # bpy.ops.screen.area_move(override, x=(area.x + 5), y=area.y, delta=-100)
-
- bpy.ops.screen.space_type_set_or_cycle(
- override, space_type='TEXT_EDITOR'
- )
- space.show_region_ui = True
- # bpy.ops.screen.region_scale(override)
- # bpy.ops.screen.region_scale()
- break
-
- elif area.type == 'CONSOLE':
- for region in [r for r in area.regions if r.type == 'WINDOW']:
- for space in area.spaces:
- if space.type == 'CONSOLE':
- override['screen'] = pov_screen
- override['window'] = pov_window
- override['area'] = area
- override['region'] = region
-
- # area_x = area.x + (area.width / 2)
- # area_y = area.y + area.height
- bpy.ops.screen.space_type_set_or_cycle(override, space_type='INFO')
- try:
- if area == pov_workspace[6] and bpy.ops.screen.area_move.poll(
- override
- ):
- # bpy.ops.screen.area_move(override, x = area_x, y = area_y, delta = -300)
- pass
- # pov_window.cursor_warp(area_x, area_y-300) # Is manual move emulation necessary
- # despite the delta?
- except IndexError:
- # Not necessarily so many areas in existing blend files
- pass
-
- break
-
- elif area.type == 'INFO':
- for region in [r for r in area.regions if r.type == 'WINDOW']:
- for space in area.spaces:
- if space.type == 'INFO':
- # override['screen'] = pov_screen
- override['area'] = area
- override['region'] = region
- bpy.ops.screen.space_type_set_or_cycle(
- override, space_type='CONSOLE'
- )
-
- break
-
- elif area.type == 'TEXT_EDITOR':
- for region in [r for r in area.regions if r.type == 'WINDOW']:
- for space in area.spaces:
- if space.type == 'TEXT_EDITOR':
- # override['screen'] = pov_screen
- override['area'] = area
- override['region'] = region
- # bpy.ops.screen.space_type_set_or_cycle(space_type='VIEW_3D')
- # space.type = 'VIEW_3D'
- bpy.ops.screen.space_type_set_or_cycle(
- override, space_type='VIEW_3D'
- )
-
- # bpy.ops.screen.area_join(override, cursor=(area.x, area.y + area.height))
-
- break
-
- if area.type == 'VIEW_3D':
- for region in [r for r in area.regions if r.type == 'WINDOW']:
- for space in area.spaces:
- if space.type == 'VIEW_3D':
- # override['screen'] = pov_screen
- override['area'] = area
- override['region'] = region
- bpy.ops.screen.region_quadview(override)
- space.region_3d.view_perspective = 'CAMERA'
- # bpy.ops.screen.space_type_set_or_cycle(override, space_type = 'TEXT_EDITOR')
- # bpy.ops.screen.region_quadview(override)
-
- elif area.type == 'OUTLINER':
- for region in [
- r for r in area.regions if r.type == 'HEADER' and (r.y - area.y)
- ]:
- for space in area.spaces:
- if space.display_mode == 'LIBRARIES':
- override['area'] = area
- override['region'] = region
- override['window'] = pov_window
- bpy.ops.screen.region_flip(override)
-
- bpy.data.workspaces.update()
-
- '''
- for window in bpy.context.window_manager.windows:
- for area in [a for a in window.screen.areas if a.type == 'VIEW_3D']:
- for region in [r for r in area.regions if r.type == 'WINDOW']:
- context_override = {
- 'window': window,
- 'screen': window.screen,
- 'area': area,
- 'region': region,
- 'space_data': area.spaces.active,
- 'scene': bpy.context.scene
- }
- bpy.ops.view3d.camera_to_view(context_override)
- '''
-
- else:
+
+ available_workspaces = bpy.data.workspaces
+
+ if all(tabs in available_workspaces for tabs in ['POV-Mo', 'POV-Ed']):
+ print("\nPOV-Mo and POV-Ed tabs respectively provide GUI and TEXT\n"
+ "oriented POV workspaces akin to Moray and POVWIN")
+ else:
+ if 'POV-Ed'not in available_workspaces:
print(
- "\nPOV centric workspace available if you set render option\n"
- "and save it in default file with CTRL+U"
+ "\nTo use POV centric workspaces you can set POV render option\n"
+ "and save it with File > Defaults > Save Startup File menu"
)
+ try:
+ if all(othertabs not in available_workspaces for othertabs in ['Geometry Nodes', 'POV-Ed']):
+ bpy.ops.workspace.append_activate(
+ idname='Geometry Nodes',
+ filepath=os.path.join(bpy.utils.user_resource('CONFIG'), 'startup.blend')
+ )
+ except BaseException as e:
+ print(e.__doc__)
+ print('An exception occurred: {}'.format(e))
+ try:
+ # Last resort: try to import from the blender templates
+ for p in Path(next(bpy.utils.app_template_paths())).rglob("startup.blend"):
+ bpy.ops.workspace.append_activate(
+ idname=self.targetWorkspace,
+ filepath=str(p))
+ except BaseException as e:
+ print(e.__doc__)
+ print('An exception occurred: {}'.format(e))
+ # Giving up as prerequisites can't be found
+ print(
+ "\nFactory Geometry Nodes workspace needed for POV text centric"
+ "\nworkspace to activate when POV is set as default renderer"
+ )
+ finally:
+ # Create POVWIN like editor (text oriented editing)
+ if 'POV-Ed' not in available_workspaces and 'Geometry Nodes' in available_workspaces:
+ wsp = available_workspaces.get('Geometry Nodes')
+ context = bpy.context
+ if context.scene.render.engine == 'POVRAY_RENDER' and wsp is not None:
+ bpy.ops.workspace.duplicate({'workspace': wsp})
+ available_workspaces['Geometry Nodes.001'].name = 'POV-Ed'
+ # May be already done, but explicitly make this workspace the active one
+ context.window.workspace = available_workspaces['POV-Ed']
+ pov_screen = available_workspaces['POV-Ed'].screens[0]
+ pov_workspace = pov_screen.areas
+ pov_window = context.window
+ # override = bpy.context.copy() # crashes
+ override = {}
+ properties_area = pov_workspace[0]
+ nodes_to_3dview_area = pov_workspace[1]
+ view3d_to_text_area = pov_workspace[2]
+ spreadsheet_to_console_area = pov_workspace[3]
+
+ try:
+ nodes_to_3dview_area.ui_type = 'VIEW_3D'
+ override['window'] = pov_window
+ override['screen'] = bpy.context.screen
+ override['area'] = nodes_to_3dview_area
+ override['region'] = nodes_to_3dview_area.regions[-1]
+ bpy.ops.screen.space_type_set_or_cycle(
+ override, 'INVOKE_DEFAULT', space_type='VIEW_3D'
+ )
+ space = nodes_to_3dview_area.spaces.active
+ space.region_3d.view_perspective = 'CAMERA'
+
+ override['window'] = pov_window
+ override['screen'] = bpy.context.screen
+ override['area'] = view3d_to_text_area
+ override['region'] = view3d_to_text_area .regions[-1]
+ override['scene'] = bpy.context.scene
+ override['space_data'] = view3d_to_text_area .spaces.active
+ bpy.ops.screen.space_type_set_or_cycle(
+ override, 'INVOKE_DEFAULT', space_type='TEXT_EDITOR'
+ )
+ view3d_to_text_area.spaces.active.show_region_ui = True
+
+ spreadsheet_to_console_area.ui_type = 'CONSOLE'
+ override['window'] = pov_window
+ override['screen'] = bpy.context.screen
+ override['area'] = spreadsheet_to_console_area
+ override['region'] = spreadsheet_to_console_area.regions[-1]
+ bpy.ops.screen.space_type_set_or_cycle(
+ override, 'INVOKE_DEFAULT', space_type='CONSOLE'
+ )
+ space = properties_area.spaces.active
+ space.context = 'RENDER'
+ bpy.ops.workspace.reorder_to_front({'workspace': available_workspaces['POV-Ed']})
+ except AttributeError:
+ # In case necessary area types lack in existing blend files
+ pass
+
+ if 'POV-Mo'not in available_workspaces:
+ try:
+ if all(tab not in available_workspaces for tab in ['Rendering', 'POV-Mo']):
+ bpy.ops.workspace.append_activate(
+ idname='Rendering',
+ filepath=os.path.join(bpy.utils.user_resource('CONFIG'), 'startup.blend')
+ )
+ except BaseException as e:
+ print(e.__doc__)
+ print('An exception occurred: {}'.format(e))
+ try:
+ # Last resort: try to import from the blender templates
+ for p in Path(next(bpy.utils.app_template_paths())).rglob("startup.blend"):
+ bpy.ops.workspace.append_activate(
+ idname=self.targetWorkspace,
+ filepath=str(p))
+ except BaseException as e:
+ print(e.__doc__)
+ print('An exception occurred: {}'.format(e))
+ # Giving up
+ print(
+ "\nFactory 'Rendering' workspace needed for POV GUI centric"
+ "\nworkspace to activate when POV is set as default renderer"
+ )
+ finally:
+ # Create Moray like workspace (GUI oriented editing)
+ if 'POV-Mo' not in available_workspaces and 'Rendering' in available_workspaces:
+ wsp1 = available_workspaces.get('Rendering')
+ context = bpy.context
+ if context.scene.render.engine == 'POVRAY_RENDER' and wsp1 is not None:
+ bpy.ops.workspace.duplicate({'workspace': wsp1})
+ available_workspaces['Rendering.001'].name = 'POV-Mo'
+ # Already done it would seem, but explicitly make this workspace the active one
+ context.window.workspace = available_workspaces['POV-Mo']
+ pov_screen = available_workspaces['POV-Mo'].screens[0]
+ pov_workspace = pov_screen.areas
+ pov_window = context.window
+ # override = bpy.context.copy() # crashes
+ override = {}
+ properties_area = pov_workspace[0]
+ image_editor_to_view3d_area = pov_workspace[2]
+
+ try:
+ image_editor_to_view3d_area.ui_type = 'VIEW_3D'
+ override['window'] = pov_window
+ override['screen'] = bpy.context.screen
+ override['area'] = image_editor_to_view3d_area
+ override['region'] = image_editor_to_view3d_area.regions[-1]
+ bpy.ops.screen.space_type_set_or_cycle(
+ override, 'INVOKE_DEFAULT', space_type='VIEW_3D'
+ )
+ space = image_editor_to_view3d_area.spaces.active # Uncomment For non quad view
+ space.region_3d.view_perspective = 'CAMERA' # Uncomment For non quad view
+ space.show_region_toolbar = True
+ # bpy.ops.view3d.camera_to_view(override) # Uncomment For non quad view ?
+ for num, reg in enumerate(image_editor_to_view3d_area.regions):
+ if reg.type != 'view3d':
+ override['region'] = image_editor_to_view3d_area.regions[num]
+ bpy.ops.screen.region_quadview(override) # Comment out for non quad
+ propspace = properties_area.spaces.active
+ propspace.context = 'MATERIAL'
+ bpy.ops.workspace.reorder_to_front({'workspace': available_workspaces['POV-Mo']})
+ except (AttributeError, TypeError):
+ # In case necessary types lack in existing blend files
+ pass
+ # available_workspaces.update()
- else:
- print(
- "\nThe factory 'Scripting' workspace is needed before POV centric "
- "\nworkspace may activate when POV is set as your default renderer"
- )
# -----------------------------------UTF-8---------------------------------- #
# Check and fix all strings in current .blend file to be valid UTF-8 Unicode
# sometimes needed for old, 2.4x / 2.6x area files
- bpy.ops.wm.blend_strings_utf8_validate()
+ try:
+ bpy.ops.wm.blend_strings_utf8_validate()
+ except BaseException as e:
+ print(e.__doc__)
+ print('An exception occurred: {}'.format(e))
+ pass
def check_material(mat):
"""Allow use of material properties buttons rather than nodes."""
if mat is not None:
if mat.use_nodes:
- if not mat.node_tree: # FORMERLY : #mat.active_node_material is not None:
- return True
- return False
+ return not mat.node_tree
return True
return False
@@ -242,7 +256,7 @@ def simple_material(mat):
return (mat is not None) and (not mat.use_nodes)
-def pov_context_tex_datablock(context):
+def pov_context_texblock(context):
"""Recreate texture context type as deprecated in blender 2.8."""
idblock = context.brush
if idblock and context.scene.texture_context == 'OTHER':
@@ -263,8 +277,7 @@ def pov_context_tex_datablock(context):
if context.particle_system and context.scene.texture_context == 'PARTICLES':
idblock = context.particle_system.settings
-
- return idblock
+ return idblock
idblock = context.line_style
if idblock and context.scene.texture_context == 'LINESTYLE':
diff --git a/render_povray/icons/pov.add.blobcapsule.dat b/render_povray/icons/pov.add.blobcapsule.dat
new file mode 100644
index 00000000..212b20c2
--- /dev/null
+++ b/render_povray/icons/pov.add.blobcapsule.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.blobcube.dat b/render_povray/icons/pov.add.blobcube.dat
new file mode 100644
index 00000000..8860b9f7
--- /dev/null
+++ b/render_povray/icons/pov.add.blobcube.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.blobellipsoid.dat b/render_povray/icons/pov.add.blobellipsoid.dat
new file mode 100644
index 00000000..6fb52834
--- /dev/null
+++ b/render_povray/icons/pov.add.blobellipsoid.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.blobplane.dat b/render_povray/icons/pov.add.blobplane.dat
new file mode 100644
index 00000000..9de03c0f
--- /dev/null
+++ b/render_povray/icons/pov.add.blobplane.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.blobsphere.dat b/render_povray/icons/pov.add.blobsphere.dat
new file mode 100644
index 00000000..a9ba7317
--- /dev/null
+++ b/render_povray/icons/pov.add.blobsphere.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.box.dat b/render_povray/icons/pov.add.box.dat
new file mode 100644
index 00000000..c6d27a5f
--- /dev/null
+++ b/render_povray/icons/pov.add.box.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.cone.dat b/render_povray/icons/pov.add.cone.dat
new file mode 100644
index 00000000..cf193bc2
--- /dev/null
+++ b/render_povray/icons/pov.add.cone.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.cylinder.dat b/render_povray/icons/pov.add.cylinder.dat
new file mode 100644
index 00000000..9820412a
--- /dev/null
+++ b/render_povray/icons/pov.add.cylinder.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.heightfield.dat b/render_povray/icons/pov.add.heightfield.dat
new file mode 100644
index 00000000..d3c8fe3d
--- /dev/null
+++ b/render_povray/icons/pov.add.heightfield.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.infinite_plane.dat b/render_povray/icons/pov.add.infinite_plane.dat
new file mode 100644
index 00000000..932e0128
--- /dev/null
+++ b/render_povray/icons/pov.add.infinite_plane.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.isosurface.dat b/render_povray/icons/pov.add.isosurface.dat
new file mode 100644
index 00000000..c7dd1443
--- /dev/null
+++ b/render_povray/icons/pov.add.isosurface.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.isosurfacebox.dat b/render_povray/icons/pov.add.isosurfacebox.dat
new file mode 100644
index 00000000..62f1f87e
--- /dev/null
+++ b/render_povray/icons/pov.add.isosurfacebox.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.isosurfacesphere.dat b/render_povray/icons/pov.add.isosurfacesphere.dat
new file mode 100644
index 00000000..47b71fab
--- /dev/null
+++ b/render_povray/icons/pov.add.isosurfacesphere.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.isosurfacesupertorus.dat b/render_povray/icons/pov.add.isosurfacesupertorus.dat
new file mode 100644
index 00000000..dfbd98bd
--- /dev/null
+++ b/render_povray/icons/pov.add.isosurfacesupertorus.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.lathe.dat b/render_povray/icons/pov.add.lathe.dat
new file mode 100644
index 00000000..0fcdb2b2
--- /dev/null
+++ b/render_povray/icons/pov.add.lathe.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.loft.dat b/render_povray/icons/pov.add.loft.dat
new file mode 100644
index 00000000..e340425a
--- /dev/null
+++ b/render_povray/icons/pov.add.loft.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.parametric.dat b/render_povray/icons/pov.add.parametric.dat
new file mode 100644
index 00000000..dfe8c0cf
--- /dev/null
+++ b/render_povray/icons/pov.add.parametric.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.polytocircle.dat b/render_povray/icons/pov.add.polytocircle.dat
new file mode 100644
index 00000000..bc8df737
--- /dev/null
+++ b/render_povray/icons/pov.add.polytocircle.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.prism.dat b/render_povray/icons/pov.add.prism.dat
new file mode 100644
index 00000000..0459bdd3
--- /dev/null
+++ b/render_povray/icons/pov.add.prism.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.rainbow.dat b/render_povray/icons/pov.add.rainbow.dat
new file mode 100644
index 00000000..fd72b434
--- /dev/null
+++ b/render_povray/icons/pov.add.rainbow.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.sphere.dat b/render_povray/icons/pov.add.sphere.dat
new file mode 100644
index 00000000..b202e5ca
--- /dev/null
+++ b/render_povray/icons/pov.add.sphere.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.spheresweep.dat b/render_povray/icons/pov.add.spheresweep.dat
new file mode 100644
index 00000000..67551166
--- /dev/null
+++ b/render_povray/icons/pov.add.spheresweep.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.superellipsoid.dat b/render_povray/icons/pov.add.superellipsoid.dat
new file mode 100644
index 00000000..0c04fdfb
--- /dev/null
+++ b/render_povray/icons/pov.add.superellipsoid.dat
Binary files differ
diff --git a/render_povray/icons/pov.add.torus.dat b/render_povray/icons/pov.add.torus.dat
new file mode 100644
index 00000000..cc514dc1
--- /dev/null
+++ b/render_povray/icons/pov.add.torus.dat
Binary files differ
diff --git a/render_povray/object_curve_topology.py b/render_povray/object_curve_topology.py
index a51ef83e..1b30c618 100755
--- a/render_povray/object_curve_topology.py
+++ b/render_povray/object_curve_topology.py
@@ -30,8 +30,15 @@ from .shading import write_object_material_interior
# -------- LOFT, ETC.
-def export_curves(file, ob, string_strip_hyphen, global_matrix, tab_write):
- """write all curves based POV primitives to exported file """
+def export_curves(file, ob, string_strip_hyphen, tab_write):
+ """write all curves based POV primitives to exported file
+
+ Args:
+ file: The POV file being written
+ ob: The current curve object to export from Blender
+ string_strip_hyphen: Function to clean up names
+ tab_write: Function to write to POV file
+ """
# name_orig = "OB" + ob.name # XXX Unused, check instantiation
dataname_orig = "DATA" + ob.data.name
@@ -174,7 +181,7 @@ def export_curves(file, ob, string_strip_hyphen, global_matrix, tab_write):
tab_write('#declare %s%s=spline {\n' % (dataname, n))
tab_write('cubic_spline\n')
lp = len(spline.points)
- delta = 1 / (lp)
+ delta = 1 / lp
d = -delta
point = spline.points[lp - 1]
x, y, z, w = point.co[:]
@@ -196,8 +203,8 @@ def export_curves(file, ob, string_strip_hyphen, global_matrix, tab_write):
tab_write('spline{%s%s},\n' % (dataname, n))
for i in range(n):
tab_write('spline{%s%s},\n' % (dataname, (i + 1)))
- tab_write('spline{%s1},\n' % (dataname))
- tab_write('spline{%s2}\n' % (dataname))
+ tab_write('spline{%s1},\n' % dataname)
+ tab_write('spline{%s2}\n' % dataname)
tab_write('}\n')
# Use some of the Meshmaker.inc macro, here inlined
file.write('#macro CheckFileName(FileName)\n')
@@ -796,7 +803,9 @@ def export_curves(file, ob, string_strip_hyphen, global_matrix, tab_write):
tab_write("\n//dummy sphere to represent empty curve location\n")
tab_write("#declare %s =\n" % dataname)
tab_write(
- "sphere {<%.6g, %.6g, %.6g>,0 pigment{rgbt 1} no_image no_reflection no_radiosity photons{pass_through collect off} hollow}\n\n"
+ "sphere {<%.6g, %.6g, %.6g>,0 pigment{rgbt 1} "
+ "no_image no_reflection no_radiosity "
+ "photons{pass_through collect off} hollow}\n\n"
% (ob.location.x, ob.location.y, ob.location.z)
) # ob.name > povdataname)
# And non empty curves
@@ -943,6 +952,7 @@ def export_curves(file, ob, string_strip_hyphen, global_matrix, tab_write):
)
tab_write("}\n")
if len(ob.data.splines) == 1:
+ p = 1
tab_write('#declare %s = object{\n' % dataname)
tab_write(
' Shape_Bezierpoints_Sphere_Sweep(yes,%s, %s_points_%s, %s_radii_%s) \n'
diff --git a/render_povray/object_gui.py b/render_povray/object_gui.py
index fa33fc65..ffedb650 100755
--- a/render_povray/object_gui.py
+++ b/render_povray/object_gui.py
@@ -21,14 +21,21 @@
import bpy
-from bpy.utils import register_class, unregister_class
+import os
+
+from bpy.utils import (
+ register_class,
+ unregister_class,
+ register_tool,
+ unregister_tool
+)
from bpy.types import (
# Operator,
Menu,
Panel,
+ WorkSpaceTool,
)
-
# Example of wrapping every class 'as is'
from bl_ui import properties_data_modifier
@@ -97,7 +104,8 @@ class PovDataButtonsPanel(properties_data_mesh.MeshButtonsPanel):
'CONE',
'TORUS',
'BLOB',
- 'ISOSURFACE',
+ 'ISOSURFACE_NODE',
+ 'ISOSURFACE_VIEW',
'SUPERELLIPSOID',
'SUPERTORUS',
'HEIGHT_FIELD',
@@ -170,7 +178,6 @@ class MODIFIERS_PT_POV_modifiers(ModifierButtonsPanel, Panel):
"""Use this class to define pov modifier buttons. (For booleans)"""
bl_label = "POV-Ray"
- COMPAT_ENGINES = {'POVRAY_RENDER'}
# def draw_header(self, context):
# scene = context.scene
@@ -180,15 +187,14 @@ class MODIFIERS_PT_POV_modifiers(ModifierButtonsPanel, Panel):
# scene = context.scene
layout = self.layout
ob = context.object
- mod = ob.modifiers
col = layout.column()
# Find Boolean Modifiers for displaying CSG option
- onceCSG = 0
+ once_csg = 0
for mod in ob.modifiers:
- if onceCSG == 0 and mod:
+ if once_csg == 0 and mod:
if mod.type == 'BOOLEAN':
col.prop(ob.pov, "boolean_mod")
- onceCSG = 1
+ once_csg = 1
if ob.pov.boolean_mod == "POV":
# split = layout.split() # better ?
@@ -201,7 +207,6 @@ class OBJECT_PT_POV_obj_parameters(ObjectButtonsPanel, Panel):
"""Use this class to define pov specific object level options buttons."""
bl_label = "POV"
- COMPAT_ENGINES = {'POVRAY_RENDER'}
@classmethod
def poll(cls, context):
@@ -531,11 +536,33 @@ class OBJECT_PT_POV_obj_supertorus(PovDataButtonsPanel, Panel):
col.prop(obj.pov, "st_max_gradient")
+class OBJECT_PT_POV_obj_isosurface(PovDataButtonsPanel, Panel):
+ """Use this class to define pov generic isosurface primitive function user field."""
+
+ bl_label = "POV Isosurface"
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+ # bl_options = {'HIDE_HEADER'}
+
+ @classmethod
+ def poll(cls, context):
+ engine = context.scene.render.engine
+ obj = context.object
+ return obj and obj.pov.object_as == 'ISOSURFACE_VIEW' and (engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+
+ obj = context.object
+
+ col = layout.column()
+
+ if obj.pov.object_as == 'ISOSURFACE_VIEW':
+ col.prop(obj.pov, "isosurface_eq")
+
class OBJECT_PT_POV_obj_parametric(PovDataButtonsPanel, Panel):
"""Use this class to define pov parametric surface primitive parameters buttons."""
bl_label = "POV Parametric surface"
- COMPAT_ENGINES = {'POVRAY_RENDER'}
# bl_options = {'HIDE_HEADER'}
@classmethod
@@ -607,9 +634,7 @@ def check_add_mesh_extra_objects():
This addon is currently used to generate the proxy for POV parametric
surface which is almost the same principle as its Math xyz surface
"""
- if "add_mesh_extra_objects" in bpy.context.preferences.addons.keys():
- return True
- return False
+ return "add_mesh_extra_objects" in bpy.context.preferences.addons.keys()
def menu_func_add(self, context):
@@ -651,7 +676,7 @@ class VIEW_MT_POV_Basic_Shapes(Menu):
layout.operator("pov.addbox", text="Box", icon='MESH_CUBE')
layout.operator("pov.addsphere", text="Sphere", icon='SHADING_RENDERED')
layout.operator("pov.addcylinder", text="Cylinder", icon="MESH_CYLINDER")
- layout.operator("pov.cone_add", text="Cone", icon="MESH_CONE")
+ layout.operator("pov.addcone", text="Cone", icon="MESH_CONE")
layout.operator("pov.addtorus", text="Torus", icon='MESH_TORUS')
layout.separator()
layout.operator("pov.addrainbow", text="Rainbow", icon="COLOR")
@@ -690,6 +715,463 @@ class VIEW_MT_POV_Basic_Shapes(Menu):
return
layout.operator("pov.addparametric", text="Parametric", icon='SCRIPTPLUGINS')
+# ------------ Tool bar button------------ #
+icon_path = (os.path.join(os.path.dirname(__file__), "icons"))
+class VIEW_WT_POV_plane_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addplane"
+ bl_label = "Add POV plane"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a plane of infinite dimension for POV"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.infinite_plane")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addplane", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_box_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addbox"
+ bl_label = "Add POV box"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV box solid primitive"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.box")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addbox", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_sphere_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addsphere"
+ bl_label = "Add POV sphere"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add an untesselated sphere for POV"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.sphere")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addsphere", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_cylinder_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addcylinder"
+ bl_label = "Add POV cylinder"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add an untesselated cylinder for POV"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.cylinder")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addcylinder", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_cone_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addcone"
+ bl_label = "Add POV cone"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add an untesselated cone for POV"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.cone")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addcone", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_torus_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addtorus"
+ bl_label = "Add POV torus"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add an untesselated torus for POV"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.torus")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addtorus", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_rainbow_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addrainbow"
+ bl_label = "Add POV rainbow"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV rainbow primitive"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.rainbow")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addrainbow", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_lathe_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addlathe"
+ bl_label = "Add POV lathe"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV lathe primitive"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.lathe")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addlathe", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_prism_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addprism"
+ bl_label = "Add POV prism"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV prism primitive"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.prism")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addprism", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_heightfield_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addheightfield"
+ bl_label = "Add POV heightfield"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV heightfield primitive"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.heightfield")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addheightfield", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_superellipsoid_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addsuperellipsoid"
+ bl_label = "Add POV superquadric ellipsoid"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV superquadric ellipsoid primitive"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.superellipsoid")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addsuperellipsoid", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_spheresweep_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addspheresweep"
+ bl_label = "Add POV spheresweep"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV spheresweep primitive"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.spheresweep")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addspheresweep", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_loft_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addloft"
+ bl_label = "Add POV loft macro"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV loft macro between editable spline cross sections"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.loft")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addloft", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_polytocircle_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addpolytocircle"
+ bl_label = "Add POV poly to circle macro"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV regular polygon to circle blending macro"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.polytocircle")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addpolytocircle", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_parametric_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addparametric"
+ bl_label = "Add POV parametric surface"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV parametric surface primitive shaped from three equations (for x, y, z directions)"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.parametric")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addparametric", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_isosurface_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addisosurface"
+ bl_label = "Add POV generic isosurface"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV generic shaped isosurface primitive"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.isosurface")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addisosurface", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_isosurfacebox_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addisosurfacebox"
+ bl_label = "Add POV isosurface box"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV box shaped isosurface primitive"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.isosurfacebox")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addisosurfacebox", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_isosurfacesphere_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addisosurfacesphere"
+ bl_label = "Add POV isosurface sphere"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV sphere shaped isosurface primitive"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.isosurfacesphere")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addisosurfacesphere", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_isosurfacesupertorus_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addsupertorus"
+ bl_label = "Add POV isosurface supertorus"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV torus shaped isosurface primitive"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.isosurfacesupertorus")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addsupertorus", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_blobsphere_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addblobsphere"
+ bl_label = "Add POV blob sphere"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV sphere shaped blob primitive"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.blobsphere")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addblobsphere", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_blobcapsule_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addblobcapsule"
+ bl_label = "Add POV blob capsule"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV capsule shaped blob primitive"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.blobcapsule")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addblobcapsule", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_blobplane_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addblobplane"
+ bl_label = "Add POV blob plane"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV plane shaped blob primitive"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.blobplane")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addblobplane", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_blobellipsoid_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addblobellipsoid"
+ bl_label = "Add POV blob ellipsoid"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV ellipsoid shaped blob primitive"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.blobellipsoid")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addblobellipsoid", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
+
+class VIEW_WT_POV_blobcube_add(WorkSpaceTool):
+ bl_space_type='VIEW_3D'
+ bl_context_mode='OBJECT'
+
+ # The prefix of the idname should be your add-on name.
+ bl_idname = "pov.addsblobcube"
+ bl_label = "Add POV blob cube"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_description = (
+ "add a POV cube shaped blob primitive"
+ )
+ bl_icon = os.path.join(icon_path, "pov.add.blobcube")
+ bl_widget = None
+ bl_keymap = (
+ ("pov.addblobcube", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": None}),
+ )
+
classes = (
# ObjectButtonsPanel,
@@ -709,21 +1191,53 @@ classes = (
OBJECT_PT_POV_obj_superellipsoid,
OBJECT_PT_POV_obj_torus,
OBJECT_PT_POV_obj_supertorus,
+ OBJECT_PT_POV_obj_isosurface,
OBJECT_PT_POV_obj_parametric,
OBJECT_PT_povray_replacement_text,
VIEW_MT_POV_primitives_add,
VIEW_MT_POV_Basic_Shapes,
)
-
+tool_classes = (
+ VIEW_WT_POV_plane_add,
+ VIEW_WT_POV_box_add,
+ VIEW_WT_POV_sphere_add,
+ VIEW_WT_POV_cylinder_add,
+ VIEW_WT_POV_cone_add,
+ VIEW_WT_POV_torus_add,
+ VIEW_WT_POV_prism_add,
+ VIEW_WT_POV_lathe_add,
+ VIEW_WT_POV_spheresweep_add,
+ VIEW_WT_POV_heightfield_add,
+ VIEW_WT_POV_superellipsoid_add,
+ VIEW_WT_POV_rainbow_add,
+ VIEW_WT_POV_loft_add,
+ VIEW_WT_POV_polytocircle_add,
+ VIEW_WT_POV_parametric_add,
+ VIEW_WT_POV_isosurface_add,
+ VIEW_WT_POV_isosurfacebox_add,
+ VIEW_WT_POV_isosurfacesphere_add,
+ VIEW_WT_POV_isosurfacesupertorus_add,
+ VIEW_WT_POV_blobsphere_add,
+ VIEW_WT_POV_blobcapsule_add,
+ VIEW_WT_POV_blobplane_add,
+ VIEW_WT_POV_blobellipsoid_add,
+ VIEW_WT_POV_blobcube_add,
+)
def register():
for cls in classes:
register_class(cls)
- bpy.types.VIEW3D_MT_add.prepend(menu_func_add)
+ # Register tools
+ last_tool = {"builtin.measure"}
+ for index, wtl in enumerate(tool_classes):
+ # Only separate first and 12th tools and hide subtools only in 8th (isosurfaces)
+ register_tool(wtl, after=last_tool, separator=index in [0,7,11,12,14,19], group=index == 15)
+ last_tool = {wtl.bl_idname}
- # was used for parametric objects but made the other addon unreachable on
- # unregister for other tools to use created a user action call instead
+ bpy.types.VIEW3D_MT_add.prepend(menu_func_add)
+ # Below was used for parametric objects but made the other addon unreachable on
+ # unregister for other tools to use. Created a user action call instead
# addon_utils.enable("add_mesh_extra_objects", default_set=False, persistent=True)
@@ -731,5 +1245,8 @@ def unregister():
# addon_utils.disable("add_mesh_extra_objects", default_set=False)
bpy.types.VIEW3D_MT_add.remove(menu_func_add)
+ for wtl in reversed(tool_classes):
+ unregister_tool(wtl)
+
for cls in reversed(classes):
unregister_class(cls)
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
diff --git a/render_povray/object_particles.py b/render_povray/object_particles.py
index 4949af21..215a6f15 100755
--- a/render_povray/object_particles.py
+++ b/render_povray/object_particles.py
@@ -111,7 +111,7 @@ def export_hair(file, ob, mod, p_sys, global_matrix, write_matrix):
) # +2 because the first point needs tripling to be more than a handle in POV
else:
file.write('linear_spline ')
- file.write('%i,\n' % (steps))
+ file.write('%i,\n' % steps)
# changing world coordinates to object local coordinates by
# multiplying with inverted matrix
init_coord = ob.matrix_world.inverted() @ (p_sys.co_hair(ob, particle_no=pindex, step=0))
@@ -160,6 +160,8 @@ def export_hair(file, ob, mod, p_sys, global_matrix, write_matrix):
elif step == 0:
hair_strand_diameter = strand_start
else:
+ # still initialize variable
+ hair_strand_diameter = strand_start
if strand_shape != 0.0:
if strand_shape < 0.0:
fac = pow(step, (1.0 + strand_shape))
diff --git a/render_povray/object_primitives.py b/render_povray/object_primitives.py
index abbba148..d906f665 100755
--- a/render_povray/object_primitives.py
+++ b/render_povray/object_primitives.py
@@ -42,24 +42,15 @@ from mathutils import Vector, Matrix
# import collections
-def write_object_modifiers(scene, ob, File):
+def write_object_modifiers(ob, File):
"""Translate some object level POV statements from Blender UI
to POV syntax and write to exported file """
# Maybe return that string to be added instead of directly written.
'''XXX WIP
- 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
+ # import .object_mesh_topology.write_object_csg_inside_vector
+ write_object_csg_inside_vector(ob, file)
'''
if ob.pov.hollow:
@@ -126,9 +117,9 @@ class POVRAY_OT_lathe_add(Operator):
bl_idname = "pov.addlathe"
bl_label = "Lathe"
- bl_options = {'REGISTER', 'UNDO'}
bl_description = "adds lathe"
-
+ bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
def execute(self, context):
# ayers=[False]*20
# layers[0]=True
@@ -195,13 +186,13 @@ def pov_superellipsoid_define(context, op, ob):
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
+ if (cos(angRing) < 0 < cos(angSegment)) or (
+ cos(angRing) > 0 > cos(angSegment)
):
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
+ if (cos(angRing) < 0 < sin(angSegment)) or (
+ cos(angRing) > 0 > sin(angSegment)
):
y = -y
z = r * (abs(sin(angRing)) ** n1)
@@ -287,6 +278,7 @@ class POVRAY_OT_superellipsoid_add(Operator):
# Keep in sync within object_properties.py section Superellipsoid
# as this allows interactive update
# If someone knows how to define operators' props from a func, I'd be delighted to learn it!
+ # 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)
se_param2: FloatProperty(name="Parameter 2", description="", min=0.00, max=10.0, default=0.04)
@@ -704,11 +696,12 @@ class POVRAY_OT_plane_add(Operator):
bl_label = "Plane"
bl_description = "Add Plane"
bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
def execute(self, context):
# layers = 20*[False]
# layers[0] = True
- bpy.ops.mesh.primitive_plane_add(size=100000)
+ bpy.ops.mesh.primitive_plane_add(size=10000)
ob = context.object
ob.name = ob.data.name = 'PovInfinitePlane'
bpy.ops.object.mode_set(mode="EDIT")
@@ -732,6 +725,7 @@ class POVRAY_OT_box_add(Operator):
bl_label = "Box"
bl_description = "Add Box"
bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
def execute(self, context):
# layers = 20*[False]
@@ -797,6 +791,7 @@ class POVRAY_OT_cylinder_add(Operator):
bl_label = "Cylinder"
bl_description = "Add Cylinder"
bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
# Keep in sync within object_properties.py section Cylinder
# as this allows interactive update
@@ -821,13 +816,12 @@ class POVRAY_OT_cylinder_add(Operator):
LOC = ob.pov.imported_cyl_loc
if ob.pov.imported_cyl_loc_cap:
LOC_CAP = ob.pov.imported_cyl_loc_cap
+ elif not props.imported_cyl_loc:
+ LOC_CAP = LOC = bpy.context.scene.cursor.location
+ LOC_CAP[2] += 2.0
else:
- if not props.imported_cyl_loc:
- LOC_CAP = LOC = bpy.context.scene.cursor.location
- LOC_CAP[2] += 2.0
- else:
- LOC = props.imported_cyl_loc
- LOC_CAP = props.imported_cyl_loc_cap
+ LOC = props.imported_cyl_loc
+ LOC_CAP = props.imported_cyl_loc_cap
self.report(
{'INFO'},
"This native POV-Ray primitive " "won't have any vertex to show in edit mode",
@@ -928,6 +922,7 @@ class POVRAY_OT_sphere_add(Operator):
bl_label = "Sphere"
bl_description = "Add Sphere Shape"
bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
# Keep in sync within object_properties.py section Sphere
# as this allows interactive update
@@ -945,16 +940,15 @@ class POVRAY_OT_sphere_add(Operator):
if ob:
if ob.pov.imported_loc:
LOC = ob.pov.imported_loc
- else:
- if not props.imported_loc:
- LOC = bpy.context.scene.cursor.location
+ elif not props.imported_loc:
+ LOC = bpy.context.scene.cursor.location
- else:
- LOC = props.imported_loc
- self.report(
- {'INFO'},
- "This native POV-Ray primitive " "won't have any vertex to show in edit mode",
- )
+ else:
+ LOC = props.imported_loc
+ self.report(
+ {'INFO'},
+ "This native POV-Ray primitive " "won't have any vertex to show in edit mode",
+ )
pov_sphere_define(context, self, None, LOC)
return {'FINISHED'}
@@ -1067,7 +1061,7 @@ def pov_cone_define(context, op, ob):
class POVRAY_OT_cone_add(Operator):
"""Add the representation of POV cone using pov_cone_define() function."""
- bl_idname = "pov.cone_add"
+ bl_idname = "pov.addcone"
bl_label = "Cone"
bl_description = "Add Cone"
bl_options = {'REGISTER', 'UNDO'}
@@ -1147,6 +1141,109 @@ class POVRAY_OT_cone_update(Operator):
# ----------------------------------- ISOSURFACES ----------------------------------- #
+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)
+ 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)
+ 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'
+ bpy.ops.object.mode_set(mode="OBJECT")
+
+class POVRAY_OT_isosurface_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."""
+
+ bl_idname = "pov.addisosurface"
+ bl_label = "Generic Isosurface"
+ bl_description = "Add Isosurface"
+ bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+ # Keep in sync within object_properties.py section Sphere
+ # 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
+ ob = context.object
+ if ob:
+ 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
+ pov_isosurface_view_define(context, self, None, LOC)
+ self.report(
+ {'INFO'}, "This native POV-Ray primitive " "is only an abstract proxy in Blender"
+ )
+ return {'FINISHED'}
+
+
+
+class POVRAY_OT_isosurface_update(Operator):
+ """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'}
+
+ @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
+
+ def execute(self, context):
+
+ pov_isosurface_view_define(context, None, context.object, context.object.location)
+
+ return {'FINISHED'}
+
+
class POVRAY_OT_isosurface_box_add(Operator):
"""Add the representation of POV isosurface box using also just a Blender mesh cube.
@@ -1157,6 +1254,7 @@ class POVRAY_OT_isosurface_box_add(Operator):
bl_label = "Isosurface Box"
bl_description = "Add Isosurface contained by Box"
bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
def execute(self, context):
# layers = 20*[False]
@@ -1169,7 +1267,7 @@ class POVRAY_OT_isosurface_box_add(Operator):
)
bpy.ops.mesh.hide(unselected=False)
bpy.ops.object.mode_set(mode="OBJECT")
- ob.pov.object_as = "ISOSURFACE"
+ ob.pov.object_as = "ISOSURFACE_NODE"
ob.pov.contained_by = 'box'
ob.name = 'PovIsosurfaceBox'
return {'FINISHED'}
@@ -1185,6 +1283,7 @@ class POVRAY_OT_isosurface_sphere_add(Operator):
bl_label = "Isosurface Sphere"
bl_description = "Add Isosurface contained by Sphere"
bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
def execute(self, context):
# layers = 20*[False]
@@ -1198,7 +1297,7 @@ class POVRAY_OT_isosurface_sphere_add(Operator):
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.object_as = "ISOSURFACE_NODE"
ob.pov.contained_by = 'sphere'
ob.name = 'PovIsosurfaceSphere'
return {'FINISHED'}
@@ -1214,6 +1313,7 @@ class POVRAY_OT_sphere_sweep_add(Operator):
bl_label = "Sphere Sweep"
bl_description = "Create Sphere Sweep along curve"
bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
def execute(self, context):
# layers = 20*[False]
@@ -1230,7 +1330,7 @@ class POVRAY_OT_sphere_sweep_add(Operator):
return {'FINISHED'}
-class POVRAY_OT_blob_add(Operator):
+class POVRAY_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
@@ -1240,6 +1340,7 @@ class POVRAY_OT_blob_add(Operator):
bl_label = "Blob Sphere"
bl_description = "Add Blob Sphere"
bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
def execute(self, context):
# layers = 20*[False]
@@ -1250,6 +1351,89 @@ class POVRAY_OT_blob_add(Operator):
return {'FINISHED'}
+class POVRAY_OT_blobcapsule_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."""
+
+ bl_idname = "pov.addblobcapsule"
+ bl_label = "Blob Capsule"
+ bl_description = "Add Blob Capsule"
+ bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+ def execute(self, context):
+ # layers = 20*[False]
+ # layers[0] = True
+ bpy.ops.object.metaball_add(type='CAPSULE')
+ ob = context.object
+ ob.name = "PovBlob"
+ return {'FINISHED'}
+
+
+class POVRAY_OT_blobplane_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."""
+
+ bl_idname = "pov.addblobplane"
+ bl_label = "Blob Plane"
+ bl_description = "Add Blob Plane"
+ bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+ def execute(self, context):
+ # layers = 20*[False]
+ # layers[0] = True
+ bpy.ops.object.metaball_add(type='PLANE')
+ ob = context.object
+ ob.name = "PovBlob"
+ return {'FINISHED'}
+
+
+class POVRAY_OT_blobellipsoid_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."""
+
+ bl_idname = "pov.addblobellipsoid"
+ bl_label = "Blob Ellipsoid"
+ bl_description = "Add Blob Ellipsoid"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ def execute(self, context):
+ # layers = 20*[False]
+ # layers[0] = True
+ bpy.ops.object.metaball_add(type='ELLIPSOID')
+ ob = context.object
+ ob.name = "PovBlob"
+ return {'FINISHED'}
+
+
+class POVRAY_OT_blobcube_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."""
+
+ bl_idname = "pov.addblobcube"
+ bl_label = "Blob Cube"
+ bl_description = "Add Blob Cube"
+ bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+ def execute(self, context):
+ # layers = 20*[False]
+ # layers[0] = True
+ bpy.ops.object.metaball_add(type='CUBE')
+ ob = context.object
+ ob.name = "PovBlob"
+ return {'FINISHED'}
+
+
class POVRAY_OT_rainbow_add(Operator):
"""Add the representation of POV rainbow using a Blender spot light.
@@ -1264,6 +1448,7 @@ class POVRAY_OT_rainbow_add(Operator):
bl_label = "Rainbow"
bl_description = "Add Rainbow"
bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
def execute(self, context):
cam = context.scene.camera
@@ -1302,6 +1487,7 @@ class POVRAY_OT_height_field_add(bpy.types.Operator, ImportHelper):
bl_label = "Height Field"
bl_description = "Add Height Field"
bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
# Keep in sync within object_properties.py section HeightFields
# as this allows interactive update
@@ -1431,6 +1617,7 @@ class POVRAY_OT_torus_add(Operator):
bl_label = "Torus"
bl_description = "Add Torus"
bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
# Keep in sync within object_properties.py section Torus
# as this allows interactive update
@@ -1487,6 +1674,7 @@ class POVRAY_OT_prism_add(Operator):
bl_label = "Prism"
bl_description = "Create Prism"
bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
prism_n: IntProperty(name="Sides", description="Number of sides", default=5, min=3, max=720)
prism_r: FloatProperty(name="Radius", description="Radius", default=1.0)
@@ -1617,6 +1805,7 @@ class POVRAY_OT_parametric_add(Operator):
bl_label = "Parametric"
bl_description = "Add Paramertic"
bl_options = {'REGISTER', 'UNDO'}
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
# Keep in sync within object_properties.py section Parametric primitive
# as this allows interactive update
@@ -1637,11 +1826,15 @@ class POVRAY_OT_parametric_add(Operator):
x_eq = props.x_eq
y_eq = props.y_eq
z_eq = props.z_eq
-
- pov_parametric_define(context, self, None)
- self.report(
- {'INFO'}, "This native POV-Ray primitive " "won't have any vertex to show in edit mode"
- )
+ try:
+ pov_parametric_define(context, self, None)
+ self.report(
+ {'INFO'}, "This native POV-Ray primitive " "won't have any vertex to show in edit mode"
+ )
+ except AttributeError:
+ self.report(
+ {'INFO'}, "Please enable Add Mesh: Extra Objects addon"
+ )
return {'FINISHED'}
@@ -1748,10 +1941,16 @@ classes = (
POVRAY_OT_sphere_update,
POVRAY_OT_cone_add,
POVRAY_OT_cone_update,
+ POVRAY_OT_isosurface_add,
+ POVRAY_OT_isosurface_update,
POVRAY_OT_isosurface_box_add,
POVRAY_OT_isosurface_sphere_add,
POVRAY_OT_sphere_sweep_add,
- POVRAY_OT_blob_add,
+ POVRAY_OT_blobsphere_add,
+ POVRAY_OT_blobcapsule_add,
+ POVRAY_OT_blobplane_add,
+ POVRAY_OT_blobellipsoid_add,
+ POVRAY_OT_blobcube_add,
POVRAY_OT_rainbow_add,
POVRAY_OT_height_field_add,
POVRAY_OT_torus_add,
diff --git a/render_povray/object_properties.py b/render_povray/object_properties.py
index f599da9b..752df203 100755
--- a/render_povray/object_properties.py
+++ b/render_povray/object_properties.py
@@ -283,7 +283,13 @@ class RenderPovSettingsObject(PropertyGroup):
cone_base_z: FloatProperty()
cone_cap_z: FloatProperty()
-
+ # -------- Generic isosurface
+ 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",
+ )
# -------- Parametric
def prop_update_parametric(self, context):
diff --git a/render_povray/render.py b/render_povray/render.py
index 25e0697c..929e6e01 100755
--- a/render_povray/render.py
+++ b/render_povray/render.py
@@ -106,7 +106,7 @@ def is_renderable(ob):
return not ob.hide_render and ob not in csg_list
-def renderable_objects(scene):
+def renderable_objects():
"""test for non hidden, non boolean operands objects to render"""
return [ob for ob in bpy.data.objects if is_renderable(ob)]
@@ -141,24 +141,15 @@ smoke_path = os.path.join(preview_dir, "smoke.df3")
'''
-# def write_object_modifiers(scene, ob, File):
+# def write_object_modifiers(ob, File):
# """Translate some object level POV statements from Blender UI
# to POV syntax and write to exported file """
# # Maybe return that string to be added instead of directly written.
# '''XXX WIP
-# 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
+# import .object_mesh_topology.write_object_csg_inside_vector
+# write_object_csg_inside_vector(ob, file)
# '''
# if ob.pov.hollow:
@@ -209,541 +200,670 @@ def write_pov(filename, scene=None, info_callback=None):
import mathutils
- # file = filename
- file = open(filename, "w")
+ with open(filename, "w") as file:
+ # Only for testing
+ if not scene:
+ scene = bpy.data.scenes[0]
+
+ render = scene.render
+ world = scene.world
+ global_matrix = mathutils.Matrix.Rotation(-pi / 2.0, 4, 'X')
+ comments = scene.pov.comments_enable and not scene.pov.tempfiles_enable
+ linebreaksinlists = scene.pov.list_lf_enable and not scene.pov.tempfiles_enable
+ feature_set = bpy.context.preferences.addons[__package__].preferences.branch_feature_set_povray
+ using_uberpov = feature_set == 'uberpov'
+ pov_binary = PovrayRender._locate_binary()
- # Only for testing
- if not scene:
- scene = bpy.data.scenes[0]
+ if using_uberpov:
+ print("Unofficial UberPOV feature set chosen in preferences")
+ else:
+ print("Official POV-Ray 3.7 feature set chosen in preferences")
+ if 'uber' in pov_binary:
+ print("The name of the binary suggests you are probably rendering with Uber POV engine")
+ else:
+ print("The name of the binary suggests you are probably rendering with standard POV engine")
- render = scene.render
- world = scene.world
- global_matrix = mathutils.Matrix.Rotation(-pi / 2.0, 4, 'X')
- comments = scene.pov.comments_enable and not scene.pov.tempfiles_enable
- linebreaksinlists = scene.pov.list_lf_enable and not scene.pov.tempfiles_enable
- feature_set = bpy.context.preferences.addons[__package__].preferences.branch_feature_set_povray
- using_uberpov = feature_set == 'uberpov'
- pov_binary = PovrayRender._locate_binary()
-
- if using_uberpov:
- print("Unofficial UberPOV feature set chosen in preferences")
- else:
- print("Official POV-Ray 3.7 feature set chosen in preferences")
- if 'uber' in pov_binary:
- print("The name of the binary suggests you are probably rendering with Uber POV engine")
- else:
- print("The name of the binary suggests you are probably rendering with standard POV engine")
-
- def set_tab(tabtype, spaces):
- tab_str = ""
- if tabtype == 'NONE':
+ def set_tab(tabtype, spaces):
tab_str = ""
- elif tabtype == 'TAB':
- tab_str = "\t"
- elif tabtype == 'SPACE':
- tab_str = spaces * " "
- return tab_str
-
- tab = set_tab(scene.pov.indentation_character, scene.pov.indentation_spaces)
- if not scene.pov.tempfiles_enable:
-
- def tab_write(str_o):
- """Indent POV syntax from brackets levels and write to exported file """
- global tab_level
- brackets = str_o.count("{") - str_o.count("}") + str_o.count("[") - str_o.count("]")
- if brackets < 0:
- tab_level = tab_level + brackets
- if tab_level < 0:
- print("Indentation Warning: tab_level = %s" % tab_level)
- tab_level = 0
- if tab_level >= 1:
- file.write("%s" % tab * tab_level)
- file.write(str_o)
- if brackets > 0:
- tab_level = tab_level + brackets
-
- else:
-
- def tab_write(str_o):
- """write directly to exported file if user checked autonamed temp files (faster)."""
-
- file.write(str_o)
-
- def unique_name(name, name_seq):
- """Increment any generated POV name that could get identical to avoid collisions"""
-
- if name not in name_seq:
+ if tabtype == 'NONE':
+ tab_str = ""
+ elif tabtype == 'TAB':
+ tab_str = "\t"
+ elif tabtype == 'SPACE':
+ tab_str = spaces * " "
+ return tab_str
+
+ tab = set_tab(scene.pov.indentation_character, scene.pov.indentation_spaces)
+ if not scene.pov.tempfiles_enable:
+
+ def tab_write(str_o):
+ """Indent POV syntax from brackets levels and write to exported file """
+ global tab_level
+ brackets = str_o.count("{") - str_o.count("}") + str_o.count("[") - str_o.count("]")
+ if brackets < 0:
+ tab_level = tab_level + brackets
+ if tab_level < 0:
+ print("Indentation Warning: tab_level = %s" % tab_level)
+ tab_level = 0
+ if tab_level >= 1:
+ file.write("%s" % tab * tab_level)
+ file.write(str_o)
+ if brackets > 0:
+ tab_level = tab_level + brackets
+
+ else:
+
+ def tab_write(str_o):
+ """write directly to exported file if user checked autonamed temp files (faster)."""
+
+ file.write(str_o)
+
+ def unique_name(name, name_seq):
+ """Increment any generated POV name that could get identical to avoid collisions"""
+
+ if name not in name_seq:
+ name = string_strip_hyphen(name)
+ return name
+
+ name_orig = name
+ i = 1
+ while name in name_seq:
+ name = "%s_%.3d" % (name_orig, i)
+ i += 1
name = string_strip_hyphen(name)
return name
- name_orig = name
- i = 1
- while name in name_seq:
- name = "%s_%.3d" % (name_orig, i)
- i += 1
- name = string_strip_hyphen(name)
- return name
-
- def write_matrix(matrix):
- """Translate some transform matrix from Blender UI
- to POV syntax and write to exported file """
- tab_write(
- "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_matrix(matrix):
+ """Translate some transform matrix from Blender UI
+ to POV syntax and write to exported file """
+ tab_write(
+ "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],
+ )
)
- )
- material_names_dictionary = {}
- DEF_MAT_NAME = "" # or "Default"?
-
- # -----------------------------------------------------------------------------
-
- def export_meta(metas):
- """write all POV blob primitives and Blender Metas to exported file """
- # TODO - blenders 'motherball' naming is not supported.
-
- if comments and len(metas) >= 1:
- file.write("//--Blob objects--\n\n")
- # Get groups of metaballs by blender name prefix.
- meta_group = {}
- meta_elems = {}
- for ob in metas:
- prefix = ob.name.split(".")[0]
- if prefix not in meta_group:
- meta_group[prefix] = ob # .data.threshold
- elems = [
- (elem, ob)
- for elem in ob.data.elements
- if elem.type in {'BALL', 'ELLIPSOID', 'CAPSULE', 'CUBE', 'PLANE'}
- ]
- if prefix in meta_elems:
- meta_elems[prefix].extend(elems)
- else:
- meta_elems[prefix] = elems
-
- # empty metaball
- if len(elems) == 0:
- tab_write("\n//dummy sphere to represent empty meta location\n")
- tab_write(
- "sphere {<%.6g, %.6g, %.6g>,0 pigment{rgbt 1} "
- "no_image no_reflection no_radiosity "
- "photons{pass_through collect off} hollow}\n\n"
- % (ob.location.x, ob.location.y, ob.location.z)
- ) # ob.name > povdataname)
- # other metaballs
- else:
- for mg, mob in meta_group.items():
- if len(meta_elems[mg]) != 0:
- tab_write("blob{threshold %.4g // %s \n" % (mob.data.threshold, mg))
- for elems in meta_elems[mg]:
- elem = elems[0]
- loc = elem.co
- stiffness = elem.stiffness
- if elem.use_negative:
- stiffness = -stiffness
- if elem.type == 'BALL':
- tab_write(
- "sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g "
- % (loc.x, loc.y, loc.z, elem.radius, stiffness)
- )
- write_matrix(global_matrix @ elems[1].matrix_world)
- tab_write("}\n")
- elif elem.type == 'ELLIPSOID':
- tab_write(
- "sphere{ <%.6g, %.6g, %.6g>,%.4g,%.4g "
- % (
- loc.x / elem.size_x,
- loc.y / elem.size_y,
- loc.z / elem.size_z,
- elem.radius,
- stiffness,
+ material_names_dictionary = {}
+ DEF_MAT_NAME = "" # or "Default"?
+
+ # -----------------------------------------------------------------------------
+
+ def export_meta(metas):
+ """write all POV blob primitives and Blender Metas to exported file """
+ # TODO - blenders 'motherball' naming is not supported.
+
+ if comments and len(metas) >= 1:
+ file.write("//--Blob objects--\n\n")
+ # Get groups of metaballs by blender name prefix.
+ meta_group = {}
+ meta_elems = {}
+ for meta_ob in metas:
+ prefix = meta_ob.name.split(".")[0]
+ if prefix not in meta_group:
+ meta_group[prefix] = meta_ob # .data.threshold
+ elems = [
+ (elem, meta_ob)
+ for elem in meta_ob.data.elements
+ if elem.type in {'BALL', 'ELLIPSOID', 'CAPSULE', 'CUBE', 'PLANE'}
+ ]
+ if prefix in meta_elems:
+ meta_elems[prefix].extend(elems)
+ else:
+ meta_elems[prefix] = elems
+
+ # empty metaball
+ if len(elems) == 0:
+ tab_write("\n//dummy sphere to represent empty meta location\n")
+ tab_write(
+ "sphere {<%.6g, %.6g, %.6g>,0 pigment{rgbt 1} "
+ "no_image no_reflection no_radiosity "
+ "photons{pass_through collect off} hollow}\n\n"
+ % (meta_ob.location.x, meta_ob.location.y, meta_ob.location.z)
+ ) # meta_ob.name > povdataname)
+ # other metaballs
+ else:
+ for mg, mob in meta_group.items():
+ if len(meta_elems[mg]) != 0:
+ tab_write("blob{threshold %.4g // %s \n" % (mob.data.threshold, mg))
+ for elems in meta_elems[mg]:
+ elem = elems[0]
+ loc = elem.co
+ stiffness = elem.stiffness
+ if elem.use_negative:
+ stiffness = -stiffness
+ if elem.type == 'BALL':
+ tab_write(
+ "sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g "
+ % (loc.x, loc.y, loc.z, elem.radius, stiffness)
)
- )
- tab_write(
- "scale <%.6g, %.6g, %.6g>"
- % (elem.size_x, elem.size_y, elem.size_z)
- )
- write_matrix(global_matrix @ elems[1].matrix_world)
- tab_write("}\n")
- elif elem.type == 'CAPSULE':
- tab_write(
- "cylinder{ <%.6g, %.6g, %.6g>,<%.6g, %.6g, %.6g>,%.4g,%.4g "
- % (
- (loc.x - elem.size_x),
- (loc.y),
- (loc.z),
- (loc.x + elem.size_x),
- (loc.y),
- (loc.z),
- elem.radius,
- stiffness,
+ write_matrix(global_matrix @ elems[1].matrix_world)
+ tab_write("}\n")
+ elif elem.type == 'ELLIPSOID':
+ tab_write(
+ "sphere{ <%.6g, %.6g, %.6g>,%.4g,%.4g "
+ % (
+ loc.x / elem.size_x,
+ loc.y / elem.size_y,
+ loc.z / elem.size_z,
+ elem.radius,
+ stiffness,
+ )
)
- )
- # tab_write("scale <%.6g, %.6g, %.6g>" % (elem.size_x, elem.size_y, elem.size_z))
- write_matrix(global_matrix @ elems[1].matrix_world)
- tab_write("}\n")
-
- elif elem.type == 'CUBE':
- tab_write(
- "cylinder { -x*8, +x*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1/4,1,1> scale <%.6g, %.6g, %.6g>\n"
- % (
- elem.radius * 2.0,
- stiffness / 4.0,
- loc.x,
- loc.y,
- loc.z,
- elem.size_x,
- elem.size_y,
- elem.size_z,
+ tab_write(
+ "scale <%.6g, %.6g, %.6g>"
+ % (elem.size_x, elem.size_y, elem.size_z)
)
- )
- write_matrix(global_matrix @ elems[1].matrix_world)
- tab_write("}\n")
- tab_write(
- "cylinder { -y*8, +y*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1/4,1> scale <%.6g, %.6g, %.6g>\n"
- % (
- elem.radius * 2.0,
- stiffness / 4.0,
- loc.x,
- loc.y,
- loc.z,
- elem.size_x,
- elem.size_y,
- elem.size_z,
+ write_matrix(global_matrix @ elems[1].matrix_world)
+ tab_write("}\n")
+ elif elem.type == 'CAPSULE':
+ tab_write(
+ "cylinder{ <%.6g, %.6g, %.6g>,<%.6g, %.6g, %.6g>,%.4g,%.4g "
+ % (
+ (loc.x - elem.size_x),
+ loc.y,
+ loc.z,
+ (loc.x + elem.size_x),
+ loc.y,
+ loc.z,
+ elem.radius,
+ stiffness,
+ )
)
- )
- write_matrix(global_matrix @ elems[1].matrix_world)
- tab_write("}\n")
- tab_write(
- "cylinder { -z*8, +z*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1,1/4> scale <%.6g, %.6g, %.6g>\n"
- % (
- elem.radius * 2.0,
- stiffness / 4.0,
- loc.x,
- loc.y,
- loc.z,
- elem.size_x,
- elem.size_y,
- elem.size_z,
+ # tab_write("scale <%.6g, %.6g, %.6g>" % (elem.size_x, elem.size_y, elem.size_z))
+ write_matrix(global_matrix @ elems[1].matrix_world)
+ tab_write("}\n")
+
+ elif elem.type == 'CUBE':
+ tab_write(
+ "cylinder { -x*8, +x*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1/4,1,1> scale <%.6g, %.6g, %.6g>\n"
+ % (
+ elem.radius * 2.0,
+ stiffness / 4.0,
+ loc.x,
+ loc.y,
+ loc.z,
+ elem.size_x,
+ elem.size_y,
+ elem.size_z,
+ )
)
- )
- write_matrix(global_matrix @ elems[1].matrix_world)
- tab_write("}\n")
-
- elif elem.type == 'PLANE':
- tab_write(
- "cylinder { -x*8, +x*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1/4,1,1> scale <%.6g, %.6g, %.6g>\n"
- % (
- elem.radius * 2.0,
- stiffness / 4.0,
- loc.x,
- loc.y,
- loc.z,
- elem.size_x,
- elem.size_y,
- elem.size_z,
+ write_matrix(global_matrix @ elems[1].matrix_world)
+ tab_write("}\n")
+ tab_write(
+ "cylinder { -y*8, +y*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1/4,1> scale <%.6g, %.6g, %.6g>\n"
+ % (
+ elem.radius * 2.0,
+ stiffness / 4.0,
+ loc.x,
+ loc.y,
+ loc.z,
+ elem.size_x,
+ elem.size_y,
+ elem.size_z,
+ )
)
- )
- write_matrix(global_matrix @ elems[1].matrix_world)
- tab_write("}\n")
+ write_matrix(global_matrix @ elems[1].matrix_world)
+ tab_write("}\n")
+ tab_write(
+ "cylinder { -z*8, +z*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1,1/4> scale <%.6g, %.6g, %.6g>\n"
+ % (
+ elem.radius * 2.0,
+ stiffness / 4.0,
+ loc.x,
+ loc.y,
+ loc.z,
+ elem.size_x,
+ elem.size_y,
+ elem.size_z,
+ )
+ )
+ write_matrix(global_matrix @ elems[1].matrix_world)
+ tab_write("}\n")
+
+ elif elem.type == 'PLANE':
+ tab_write(
+ "cylinder { -x*8, +x*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1/4,1,1> scale <%.6g, %.6g, %.6g>\n"
+ % (
+ elem.radius * 2.0,
+ stiffness / 4.0,
+ loc.x,
+ loc.y,
+ loc.z,
+ elem.size_x,
+ elem.size_y,
+ elem.size_z,
+ )
+ )
+ write_matrix(global_matrix @ elems[1].matrix_world)
+ tab_write("}\n")
+ tab_write(
+ "cylinder { -y*8, +y*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1/4,1> scale <%.6g, %.6g, %.6g>\n"
+ % (
+ elem.radius * 2.0,
+ stiffness / 4.0,
+ loc.x,
+ loc.y,
+ loc.z,
+ elem.size_x,
+ elem.size_y,
+ elem.size_z,
+ )
+ )
+ write_matrix(global_matrix @ elems[1].matrix_world)
+ tab_write("}\n")
+
+ try:
+ one_material = elems[1].data.materials[
+ 0
+ ] # lame! - blender cant do enything else.
+ except BaseException as e:
+ print(e.__doc__)
+ print('An exception occurred: {}'.format(e))
+ one_material = None
+ if one_material:
+ diffuse_color = one_material.diffuse_color
+ trans = 1.0 - one_material.pov.alpha
+ if (
+ one_material.use_transparency
+ and one_material.transparency_method == 'RAYTRACE'
+ ):
+ pov_filter = one_material.pov_raytrace_transparency.filter * (
+ 1.0 - one_material.alpha
+ )
+ trans = (1.0 - one_material.pov.alpha) - pov_filter
+ else:
+ pov_filter = 0.0
+ material_finish = material_names_dictionary[one_material.name]
tab_write(
- "cylinder { -y*8, +y*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1/4,1> scale <%.6g, %.6g, %.6g>\n"
+ "pigment {srgbft<%.3g, %.3g, %.3g, %.3g, %.3g>} \n"
% (
- elem.radius * 2.0,
- stiffness / 4.0,
- loc.x,
- loc.y,
- loc.z,
- elem.size_x,
- elem.size_y,
- elem.size_z,
+ diffuse_color[0],
+ diffuse_color[1],
+ diffuse_color[2],
+ pov_filter,
+ trans,
)
)
- write_matrix(global_matrix @ elems[1].matrix_world)
- tab_write("}\n")
-
- try:
- material = elems[1].data.materials[
- 0
- ] # lame! - blender cant do enything else.
- except BaseException as e:
- print(e.__doc__)
- print('An exception occurred: {}'.format(e))
- material = None
- if material:
- diffuse_color = material.diffuse_color
- trans = 1.0 - material.pov.alpha
- if (
- material.use_transparency
- and material.transparency_method == 'RAYTRACE'
- ):
- pov_filter = material.pov_raytrace_transparency.filter * (
- 1.0 - material.alpha
- )
- trans = (1.0 - material.pov.alpha) - pov_filter
+ tab_write("finish{%s} " % safety(material_finish, ref_level_bound=2))
else:
- pov_filter = 0.0
- material_finish = material_names_dictionary[material.name]
- tab_write(
- "pigment {srgbft<%.3g, %.3g, %.3g, %.3g, %.3g>} \n"
- % (
- diffuse_color[0],
- diffuse_color[1],
- diffuse_color[2],
- pov_filter,
- trans,
+ material_finish = DEF_MAT_NAME
+ trans = 0.0
+ tab_write(
+ "pigment{srgbt<1,1,1,%.3g>} finish{%s} "
+ % (trans, safety(material_finish, ref_level_bound=2))
)
- )
- tab_write("finish{%s} " % safety(material_finish, ref_level_bound=2))
- else:
- material_finish = DEF_MAT_NAME
- trans = 0.0
- tab_write(
- "pigment{srgbt<1,1,1,%.3g} finish{%s} "
- % (trans, safety(material_finish, ref_level_bound=2))
- )
-
- write_object_material_interior(material, mob, tab_write)
- # write_object_material_interior(material, elems[1])
- tab_write("radiosity{importance %3g}\n" % mob.pov.importance_value)
- tab_write("}\n\n") # End of Metaball block
-
- '''
- meta = ob.data
-
- # important because no elements will break parsing.
- elements = [elem for elem in meta.elements if elem.type in {'BALL', 'ELLIPSOID'}]
-
- if elements:
- tab_write("blob {\n")
- tab_write("threshold %.4g\n" % meta.threshold)
- importance = ob.pov.importance_value
- try:
- material = meta.materials[0] # lame! - blender cant do enything else.
- except:
- material = None
-
- for elem in elements:
- loc = elem.co
-
- stiffness = elem.stiffness
- if elem.use_negative:
- stiffness = - stiffness
-
- if elem.type == 'BALL':
-
- tab_write("sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g }\n" %
- (loc.x, loc.y, loc.z, elem.radius, stiffness))
-
- # After this wecould do something simple like...
- # "pigment {Blue} }"
- # except we'll write the color
-
- elif elem.type == 'ELLIPSOID':
- # location is modified by scale
- tab_write("sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g }\n" %
- (loc.x / elem.size_x,
- loc.y / elem.size_y,
- loc.z / elem.size_z,
- elem.radius, stiffness))
- tab_write("scale <%.6g, %.6g, %.6g> \n" %
- (elem.size_x, elem.size_y, elem.size_z))
-
- if material:
- diffuse_color = material.diffuse_color
- trans = 1.0 - material.pov.alpha
- if material.use_transparency and material.transparency_method == 'RAYTRACE':
- pov_filter = material.pov_raytrace_transparency.filter * (1.0 - material.alpha)
- trans = (1.0 - material.pov.alpha) - pov_filter
+ write_object_material_interior(one_material, mob, tab_write)
+ # write_object_material_interior(one_material, elems[1])
+ tab_write("radiosity{importance %3g}\n" % mob.pov.importance_value)
+ tab_write("}\n\n") # End of Metaball block
+
+ '''
+ meta = ob.data
+
+ # important because no elements will break parsing.
+ elements = [elem for elem in meta.elements if elem.type in {'BALL', 'ELLIPSOID'}]
+
+ if elements:
+ tab_write("blob {\n")
+ tab_write("threshold %.4g\n" % meta.threshold)
+ importance = ob.pov.importance_value
+
+ try:
+ material = meta.materials[0] # lame! - blender cant do enything else.
+ except:
+ material = None
+
+ for elem in elements:
+ loc = elem.co
+
+ stiffness = elem.stiffness
+ if elem.use_negative:
+ stiffness = - stiffness
+
+ if elem.type == 'BALL':
+
+ tab_write("sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g }\n" %
+ (loc.x, loc.y, loc.z, elem.radius, stiffness))
+
+ # After this wecould do something simple like...
+ # "pigment {Blue} }"
+ # except we'll write the color
+
+ elif elem.type == 'ELLIPSOID':
+ # location is modified by scale
+ tab_write("sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g }\n" %
+ (loc.x / elem.size_x,
+ loc.y / elem.size_y,
+ loc.z / elem.size_z,
+ elem.radius, stiffness))
+ tab_write("scale <%.6g, %.6g, %.6g> \n" %
+ (elem.size_x, elem.size_y, elem.size_z))
+
+ if material:
+ diffuse_color = material.diffuse_color
+ trans = 1.0 - material.pov.alpha
+ if material.use_transparency and material.transparency_method == 'RAYTRACE':
+ pov_filter = material.pov_raytrace_transparency.filter * (1.0 - material.alpha)
+ trans = (1.0 - material.pov.alpha) - pov_filter
+ else:
+ pov_filter = 0.0
+
+ material_finish = material_names_dictionary[material.name]
+
+ tab_write("pigment {srgbft<%.3g, %.3g, %.3g, %.3g, %.3g>} \n" %
+ (diffuse_color[0], diffuse_color[1], diffuse_color[2],
+ pov_filter, trans))
+ tab_write("finish {%s}\n" % safety(material_finish, ref_level_bound=2))
+
else:
- pov_filter = 0.0
-
- material_finish = material_names_dictionary[material.name]
-
- tab_write("pigment {srgbft<%.3g, %.3g, %.3g, %.3g, %.3g>} \n" %
- (diffuse_color[0], diffuse_color[1], diffuse_color[2],
- pov_filter, trans))
- tab_write("finish {%s}\n" % safety(material_finish, ref_level_bound=2))
-
- else:
- tab_write("pigment {srgb 1} \n")
- # Write the finish last.
- tab_write("finish {%s}\n" % (safety(DEF_MAT_NAME, ref_level_bound=2)))
-
- write_object_material_interior(material, elems[1])
-
- write_matrix(global_matrix @ ob.matrix_world)
- # Importance for radiosity sampling added here
- tab_write("radiosity { \n")
- # importance > ob.pov.importance_value
- tab_write("importance %3g \n" % importance)
+ tab_write("pigment {srgb 1} \n")
+ # Write the finish last.
+ tab_write("finish {%s}\n" % (safety(DEF_MAT_NAME, ref_level_bound=2)))
+
+ write_object_material_interior(material, elems[1])
+
+ write_matrix(global_matrix @ ob.matrix_world)
+ # Importance for radiosity sampling added here
+ tab_write("radiosity { \n")
+ # importance > ob.pov.importance_value
+ tab_write("importance %3g \n" % importance)
+ tab_write("}\n")
+
+ tab_write("}\n") # End of Metaball block
+
+ if comments and len(metas) >= 1:
+ file.write("\n")
+ '''
+
+ def export_global_settings(scene):
+ """write all POV global settings to exported file """
+ # Imperial units warning
+ if scene.unit_settings.system == "IMPERIAL":
+ print("Warning: Imperial units not supported")
+
+ tab_write("global_settings {\n")
+ tab_write("assumed_gamma 1.0\n")
+ tab_write("max_trace_level %d\n" % scene.pov.max_trace_level)
+
+ if scene.pov.global_settings_advanced:
+ if not scene.pov.radio_enable:
+ file.write(" adc_bailout %.6f\n" % scene.pov.adc_bailout)
+ file.write(" ambient_light <%.6f,%.6f,%.6f>\n" % scene.pov.ambient_light[:])
+ file.write(" irid_wavelength <%.6f,%.6f,%.6f>\n" % scene.pov.irid_wavelength[:])
+ file.write(" number_of_waves %s\n" % scene.pov.number_of_waves)
+ file.write(" noise_generator %s\n" % scene.pov.noise_generator)
+ if scene.pov.radio_enable:
+ tab_write("radiosity {\n")
+ tab_write("adc_bailout %.4g\n" % scene.pov.radio_adc_bailout)
+ tab_write("brightness %.4g\n" % scene.pov.radio_brightness)
+ tab_write("count %d\n" % scene.pov.radio_count)
+ tab_write("error_bound %.4g\n" % scene.pov.radio_error_bound)
+ tab_write("gray_threshold %.4g\n" % scene.pov.radio_gray_threshold)
+ tab_write("low_error_factor %.4g\n" % scene.pov.radio_low_error_factor)
+ tab_write("maximum_reuse %.4g\n" % scene.pov.radio_maximum_reuse)
+ tab_write("minimum_reuse %.4g\n" % scene.pov.radio_minimum_reuse)
+ tab_write("nearest_count %d\n" % scene.pov.radio_nearest_count)
+ tab_write("pretrace_start %.3g\n" % scene.pov.radio_pretrace_start)
+ tab_write("pretrace_end %.3g\n" % scene.pov.radio_pretrace_end)
+ tab_write("recursion_limit %d\n" % scene.pov.radio_recursion_limit)
+ tab_write("always_sample %d\n" % scene.pov.radio_always_sample)
+ tab_write("normal %d\n" % scene.pov.radio_normal)
+ tab_write("media %d\n" % scene.pov.radio_media)
+ tab_write("subsurface %d\n" % scene.pov.radio_subsurface)
tab_write("}\n")
+ once_sss = 1
+ once_ambient = 1
+ once_photons = 1
+ for material in bpy.data.materials:
+ if material.pov_subsurface_scattering.use and once_sss:
+ # In pov, the scale has reversed influence compared to blender. these number
+ # should correct that
+ tab_write(
+ "mm_per_unit %.6f\n" % (material.pov_subsurface_scattering.scale * 1000.0)
+ )
+ # 1000 rather than scale * (-100.0) + 15.0))
+
+ # In POV-Ray, the scale factor for all subsurface shaders needs to be the same
+
+ # formerly sslt_samples were multiplied by 100 instead of 10
+ sslt_samples = (11 - material.pov_subsurface_scattering.error_threshold) * 10
+
+ tab_write("subsurface { samples %d, %d }\n" % (sslt_samples, sslt_samples / 10))
+ once_sss = 0
+
+ if world and once_ambient:
+ tab_write("ambient_light rgb<%.3g, %.3g, %.3g>\n" % world.pov.ambient_color[:])
+ once_ambient = 0
+
+ if scene.pov.photon_enable:
+ if once_photons and (
+ material.pov.refraction_type == "2" or material.pov.photons_reflection
+ ):
+ tab_write("photons {\n")
+ tab_write("spacing %.6f\n" % scene.pov.photon_spacing)
+ tab_write("max_trace_level %d\n" % scene.pov.photon_max_trace_level)
+ tab_write("adc_bailout %.3g\n" % scene.pov.photon_adc_bailout)
+ tab_write(
+ "gather %d, %d\n"
+ % (scene.pov.photon_gather_min, scene.pov.photon_gather_max)
+ )
+ if scene.pov.photon_map_file_save_load in {'save'}:
+ ph_file_name = 'Photon_map_file.ph'
+ if scene.pov.photon_map_file != '':
+ ph_file_name = scene.pov.photon_map_file + '.ph'
+ ph_file_dir = tempfile.gettempdir()
+ path = bpy.path.abspath(scene.pov.photon_map_dir)
+ if os.path.exists(path):
+ ph_file_dir = path
+ full_file_name = os.path.join(ph_file_dir, ph_file_name)
+ tab_write('save_file "%s"\n' % full_file_name)
+ scene.pov.photon_map_file = full_file_name
+ if scene.pov.photon_map_file_save_load in {'load'}:
+ full_file_name = bpy.path.abspath(scene.pov.photon_map_file)
+ if os.path.exists(full_file_name):
+ tab_write('load_file "%s"\n' % full_file_name)
+ tab_write("}\n")
+ once_photons = 0
- tab_write("}\n") # End of Metaball block
-
- if comments and len(metas) >= 1:
- file.write("\n")
- '''
-
- def export_global_settings(scene):
- """write all POV global settings to exported file """
- tab_write("global_settings {\n")
- tab_write("assumed_gamma 1.0\n")
- tab_write("max_trace_level %d\n" % scene.pov.max_trace_level)
-
- if scene.pov.global_settings_advanced:
- if not scene.pov.radio_enable:
- file.write(" adc_bailout %.6f\n" % scene.pov.adc_bailout)
- file.write(" ambient_light <%.6f,%.6f,%.6f>\n" % scene.pov.ambient_light[:])
- file.write(" irid_wavelength <%.6f,%.6f,%.6f>\n" % scene.pov.irid_wavelength[:])
- file.write(" number_of_waves %s\n" % scene.pov.number_of_waves)
- file.write(" noise_generator %s\n" % scene.pov.noise_generator)
- if scene.pov.radio_enable:
- tab_write("radiosity {\n")
- tab_write("adc_bailout %.4g\n" % scene.pov.radio_adc_bailout)
- tab_write("brightness %.4g\n" % scene.pov.radio_brightness)
- tab_write("count %d\n" % scene.pov.radio_count)
- tab_write("error_bound %.4g\n" % scene.pov.radio_error_bound)
- tab_write("gray_threshold %.4g\n" % scene.pov.radio_gray_threshold)
- tab_write("low_error_factor %.4g\n" % scene.pov.radio_low_error_factor)
- tab_write("maximum_reuse %.4g\n" % scene.pov.radio_maximum_reuse)
- tab_write("minimum_reuse %.4g\n" % scene.pov.radio_minimum_reuse)
- tab_write("nearest_count %d\n" % scene.pov.radio_nearest_count)
- tab_write("pretrace_start %.3g\n" % scene.pov.radio_pretrace_start)
- tab_write("pretrace_end %.3g\n" % scene.pov.radio_pretrace_end)
- tab_write("recursion_limit %d\n" % scene.pov.radio_recursion_limit)
- tab_write("always_sample %d\n" % scene.pov.radio_always_sample)
- tab_write("normal %d\n" % scene.pov.radio_normal)
- tab_write("media %d\n" % scene.pov.radio_media)
- tab_write("subsurface %d\n" % scene.pov.radio_subsurface)
tab_write("}\n")
- once_sss = 1
- once_ambient = 1
- once_photons = 1
- for material in bpy.data.materials:
- if material.pov_subsurface_scattering.use and once_sss:
- # In pov, the scale has reversed influence compared to blender. these number
- # should correct that
- tab_write(
- "mm_per_unit %.6f\n" % (material.pov_subsurface_scattering.scale * 1000.0)
- )
- # 1000 rather than scale * (-100.0) + 15.0))
- # In POV-Ray, the scale factor for all subsurface shaders needs to be the same
+ # sel = renderable_objects() #removed for booleans
+ if comments:
+ file.write(
+ "//----------------------------------------------\n"
+ "//--Exported with POV-Ray exporter for Blender--\n"
+ "//----------------------------------------------\n\n"
+ )
+ file.write("#version 3.7;\n") # Switch below as soon as 3.8 beta gets easy linked
+ # file.write("#version 3.8;\n")
+ file.write(
+ "#declare Default_texture = texture{pigment {rgb 0.8} " "finish {brilliance 3.8} }\n\n"
+ )
+ if comments:
+ file.write("\n//--Global settings--\n\n")
+
+ export_global_settings(scene)
+
+ if comments:
+ file.write("\n//--Custom Code--\n\n")
+ scripting.export_custom_code(file)
+
+ if comments:
+ file.write("\n//--Patterns Definitions--\n\n")
+ local_pattern_names = []
+ for texture in bpy.data.textures: # ok?
+ if texture.users > 0:
+ current_pat_name = string_strip_hyphen(bpy.path.clean_name(texture.name))
+ # string_strip_hyphen(patternNames[texture.name]) #maybe instead of the above
+ local_pattern_names.append(current_pat_name)
+ # use above list to prevent writing texture instances several times and assign in mats?
+ if (
+ texture.type not in {'NONE', 'IMAGE'} and texture.pov.tex_pattern_type == 'emulator'
+ ) or (texture.type in {'NONE', 'IMAGE'} and texture.pov.tex_pattern_type != 'emulator'):
+ file.write("\n#declare PAT_%s = \n" % current_pat_name)
+ file.write(shading.export_pattern(texture))
+ file.write("\n")
+ if comments:
+ file.write("\n//--Background--\n\n")
+
+ scenography.export_world(scene.world, scene, global_matrix, tab_write)
+
+ if comments:
+ file.write("\n//--Cameras--\n\n")
+
+ scenography.export_camera(scene, global_matrix, render, tab_write)
+
+ if comments:
+ file.write("\n//--Lamps--\n\n")
+
+ for ob in bpy.data.objects:
+ if ob.type == 'MESH':
+ for mod in ob.modifiers:
+ if mod.type == 'BOOLEAN' and mod.object not in csg_list:
+ csg_list.append(mod.object)
+ if csg_list:
+ csg = False
+ sel = no_renderable_objects()
+ # export non rendered boolean objects operands
+ object_mesh_topology.export_meshes(
+ preview_dir,
+ file,
+ scene,
+ sel,
+ csg,
+ string_strip_hyphen,
+ safety,
+ write_object_modifiers,
+ material_names_dictionary,
+ write_object_material_interior,
+ scenography.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,
+ )
- # formerly sslt_samples were multiplied by 100 instead of 10
- sslt_samples = (11 - material.pov_subsurface_scattering.error_threshold) * 10
+ csg = True
+ sel = renderable_objects()
- tab_write("subsurface { samples %d, %d }\n" % (sslt_samples, sslt_samples / 10))
- once_sss = 0
+ scenography.export_lights(
+ [L for L in sel if (L.type == 'LIGHT' and L.pov.object_as != 'RAINBOW')],
+ file,
+ scene,
+ global_matrix,
+ write_matrix,
+ tab_write,
+ )
- if world and once_ambient:
- tab_write("ambient_light rgb<%.3g, %.3g, %.3g>\n" % world.pov.ambient_color[:])
- once_ambient = 0
+ if comments:
+ file.write("\n//--Rainbows--\n\n")
+ scenography.export_rainbows(
+ [L for L in sel if (L.type == 'LIGHT' and L.pov.object_as == 'RAINBOW')],
+ file,
+ scene,
+ global_matrix,
+ write_matrix,
+ tab_write,
+ )
- if scene.pov.photon_enable:
- if once_photons and (
- material.pov.refraction_type == "2" or material.pov.photons_reflection
- ):
- tab_write("photons {\n")
- tab_write("spacing %.6f\n" % scene.pov.photon_spacing)
- tab_write("max_trace_level %d\n" % scene.pov.photon_max_trace_level)
- tab_write("adc_bailout %.3g\n" % scene.pov.photon_adc_bailout)
- tab_write(
- "gather %d, %d\n"
- % (scene.pov.photon_gather_min, scene.pov.photon_gather_max)
+ if comments:
+ file.write("\n//--Special Curves--\n\n")
+ for c in sel:
+ if c.is_modified(scene, 'RENDER'):
+ continue # don't export as pov curves objects with modifiers, but as mesh
+ # Implicit else-if (as not skipped by previous "continue")
+ if c.type == 'CURVE' and (c.pov.curveshape in {'lathe', 'sphere_sweep', 'loft', 'birail'}):
+ object_curve_topology.export_curves(file, c, string_strip_hyphen, tab_write)
+
+ if comments:
+ file.write("\n//--Material Definitions--\n\n")
+ # write a default pigment for objects with no material (comment out to show black)
+ file.write("#default{ pigment{ color srgb 0.8 }}\n")
+ # Convert all materials to strings we can access directly per vertex.
+ # exportMaterials()
+ shading.write_material(
+ using_uberpov,
+ DEF_MAT_NAME,
+ tab_write,
+ safety,
+ comments,
+ unique_name,
+ material_names_dictionary,
+ None,
+ ) # default material
+ for material in bpy.data.materials:
+ if material.users > 0:
+ r, g, b, a = material.diffuse_color[:]
+ pigment_color = "pigment {rgbt <%.4g,%.4g,%.4g,%.4g>}" % (r, g, b, 1 - a)
+ if material.pov.material_use_nodes:
+ # Also make here other pigment_color fallback using BSDF node main color ?
+ ntree = material.node_tree
+ pov_mat_name = string_strip_hyphen(bpy.path.clean_name(material.name))
+ if len(ntree.nodes) == 0:
+ file.write('#declare %s = texture {%s}\n' % (pov_mat_name, pigment_color))
+ else:
+ shading.write_nodes(pov_mat_name, ntree, file)
+
+ for node in ntree.nodes:
+ if node:
+ if node.bl_idname == "PovrayOutputNode":
+ if node.inputs["Texture"].is_linked:
+ for link in ntree.links:
+ if link.to_node.bl_idname == "PovrayOutputNode":
+ pov_mat_name = (
+ string_strip_hyphen(
+ bpy.path.clean_name(link.from_node.name)
+ )
+ + "_%s" % pov_mat_name
+ )
+ else:
+ file.write(
+ '#declare %s = texture {%s}\n' % (pov_mat_name, pigment_color)
+ )
+ else:
+ shading.write_material(
+ using_uberpov,
+ DEF_MAT_NAME,
+ tab_write,
+ safety,
+ comments,
+ unique_name,
+ material_names_dictionary,
+ material,
)
- if scene.pov.photon_map_file_save_load in {'save'}:
- ph_file_name = 'Photon_map_file.ph'
- if scene.pov.photon_map_file != '':
- ph_file_name = scene.pov.photon_map_file + '.ph'
- ph_file_dir = tempfile.gettempdir()
- path = bpy.path.abspath(scene.pov.photon_map_dir)
- if os.path.exists(path):
- ph_file_dir = path
- full_file_name = os.path.join(ph_file_dir, ph_file_name)
- tab_write('save_file "%s"\n' % full_file_name)
- scene.pov.photon_map_file = full_file_name
- if scene.pov.photon_map_file_save_load in {'load'}:
- full_file_name = bpy.path.abspath(scene.pov.photon_map_file)
- if os.path.exists(full_file_name):
- tab_write('load_file "%s"\n' % full_file_name)
- tab_write("}\n")
- once_photons = 0
-
- tab_write("}\n")
-
- # sel = renderable_objects(scene) #removed for booleans
- if comments:
- file.write(
- "//----------------------------------------------\n"
- "//--Exported with POV-Ray exporter for Blender--\n"
- "//----------------------------------------------\n\n"
- )
- file.write("#version 3.7;\n") # Switch below as soon as 3.8 beta gets easy linked
- # file.write("#version 3.8;\n")
- file.write(
- "#declare Default_texture = texture{pigment {rgb 0.8} " "finish {brilliance 3.8} }\n\n"
- )
- if comments:
- file.write("\n//--Global settings--\n\n")
-
- export_global_settings(scene)
-
- if comments:
- file.write("\n//--Custom Code--\n\n")
- scripting.export_custom_code(file)
-
- if comments:
- file.write("\n//--Patterns Definitions--\n\n")
- local_pattern_names = []
- for texture in bpy.data.textures: # ok?
- if texture.users > 0:
- current_pat_name = string_strip_hyphen(bpy.path.clean_name(texture.name))
- # string_strip_hyphen(patternNames[texture.name]) #maybe instead of the above
- local_pattern_names.append(current_pat_name)
- # use above list to prevent writing texture instances several times and assign in mats?
- if (
- texture.type not in {'NONE', 'IMAGE'} and texture.pov.tex_pattern_type == 'emulator'
- ) or (texture.type in {'NONE', 'IMAGE'} and texture.pov.tex_pattern_type != 'emulator'):
- file.write("\n#declare PAT_%s = \n" % current_pat_name)
- file.write(shading.export_pattern(texture))
+ # attributes are all the variables needed by the other python file...
+ if comments:
file.write("\n")
- if comments:
- file.write("\n//--Background--\n\n")
-
- scenography.export_world(scene.world, scene, global_matrix, tab_write)
- if comments:
- file.write("\n//--Cameras--\n\n")
+ export_meta([m for m in sel if m.type == 'META'])
- scenography.export_camera(scene, global_matrix, render, tab_write)
+ if comments:
+ file.write("//--Mesh objects--\n")
- if comments:
- file.write("\n//--Lamps--\n\n")
-
- for ob in bpy.data.objects:
- if ob.type == 'MESH':
- for mod in ob.modifiers:
- if mod.type == 'BOOLEAN' and mod.object not in csg_list:
- csg_list.append(mod.object)
- if csg_list != []:
- csg = False
- sel = no_renderable_objects()
- #export non rendered boolean objects operands
+ # tbefore = time.time()
object_mesh_topology.export_meshes(
preview_dir,
file,
@@ -772,150 +892,21 @@ def write_pov(filename, scene=None, info_callback=None):
tab_write,
info_callback,
)
+ # totime = time.time() - tbefore
+ # print("export_meshes took" + str(totime))
- csg = True
- sel = renderable_objects(scene)
-
- scenography.export_lights(
- [L for L in sel if (L.type == 'LIGHT' and L.pov.object_as != 'RAINBOW')],
- file,
- scene,
- global_matrix,
- write_matrix,
- tab_write,
- )
-
- if comments:
- file.write("\n//--Rainbows--\n\n")
- scenography.export_rainbows(
- [L for L in sel if (L.type == 'LIGHT' and L.pov.object_as == 'RAINBOW')],
- file,
- scene,
- global_matrix,
- write_matrix,
- tab_write,
- )
-
- if comments:
- file.write("\n//--Special Curves--\n\n")
- for c in sel:
- if c.is_modified(scene, 'RENDER'):
- continue # don't export as pov curves objects with modifiers, but as mesh
- # Implicit else-if (as not skipped by previous "continue")
- if c.type == 'CURVE' and (c.pov.curveshape in {'lathe', 'sphere_sweep', 'loft', 'birail'}):
- object_curve_topology.export_curves(file, c, string_strip_hyphen, global_matrix, tab_write)
-
- if comments:
- file.write("\n//--Material Definitions--\n\n")
- # write a default pigment for objects with no material (comment out to show black)
- file.write("#default{ pigment{ color srgb 0.8 }}\n")
- # Convert all materials to strings we can access directly per vertex.
- # exportMaterials()
- shading.write_material(
- using_uberpov,
- DEF_MAT_NAME,
- tab_write,
- safety,
- comments,
- unique_name,
- material_names_dictionary,
- None,
- ) # default material
- for material in bpy.data.materials:
- if material.users > 0:
- r, g, b, a = material.diffuse_color[:]
- pigment_color = "pigment {rgbt <%.4g,%.4g,%.4g,%.4g>}" % (r, g, b, 1 - a)
- if material.pov.material_use_nodes:
- # Also make here other pigment_color fallback using BSDF node main color ?
- ntree = material.node_tree
- pov_mat_name = string_strip_hyphen(bpy.path.clean_name(material.name))
- if len(ntree.nodes) == 0:
- file.write('#declare %s = texture {%s}\n' % (pov_mat_name, pigment_color))
- else:
- shading.write_nodes(scene, pov_mat_name, ntree, file)
-
- for node in ntree.nodes:
- if node:
- if node.bl_idname == "PovrayOutputNode":
- if node.inputs["Texture"].is_linked:
- for link in ntree.links:
- if link.to_node.bl_idname == "PovrayOutputNode":
- pov_mat_name = (
- string_strip_hyphen(
- bpy.path.clean_name(link.from_node.name)
- )
- + "_%s" % pov_mat_name
- )
- else:
- file.write(
- '#declare %s = texture {%s}\n' % (pov_mat_name, pigment_color)
- )
- else:
- shading.write_material(
- using_uberpov,
- DEF_MAT_NAME,
- tab_write,
- safety,
- comments,
- unique_name,
- material_names_dictionary,
- material,
- )
- # attributes are all the variables needed by the other python file...
- if comments:
- file.write("\n")
-
- export_meta([m for m in sel if m.type == 'META'])
-
- if comments:
- file.write("//--Mesh objects--\n")
-
- # tbefore = time.time()
- object_mesh_topology.export_meshes(
- preview_dir,
- file,
- scene,
- sel,
- csg,
- string_strip_hyphen,
- safety,
- write_object_modifiers,
- material_names_dictionary,
- write_object_material_interior,
- scenography.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,
- )
- # totime = time.time() - tbefore
- # print("export_meshes took" + str(totime))
-
- # What follow used to happen here:
- # export_camera()
- # scenography.export_world(scene.world, scene, global_matrix, tab_write)
- # export_global_settings(scene)
- # MR:..and the order was important for implementing pov 3.7 baking
- # (mesh camera) comment for the record
- # CR: Baking should be a special case than. If "baking", than we could change the order.
-
- # print("pov file closed %s" % file.closed)
- file.close()
- # print("pov file closed %s" % file.closed)
-
-
-def write_pov_ini(scene, filename_ini, filename_log, filename_pov, filename_image):
+ # What follow used to happen here:
+ # export_camera()
+ # scenography.export_world(scene.world, scene, global_matrix, tab_write)
+ # export_global_settings(scene)
+ # MR:..and the order was important for implementing pov 3.7 baking
+ # (mesh camera) comment for the record
+ # CR: Baking should be a special case than. If "baking", than we could change the order.
+
+ if not file.closed:
+ file.close()
+
+def write_pov_ini(filename_ini, filename_log, filename_pov, filename_image):
"""Write ini file."""
feature_set = bpy.context.preferences.addons[__package__].preferences.branch_feature_set_povray
using_uberpov = feature_set == 'uberpov'
@@ -926,67 +917,66 @@ def write_pov_ini(scene, filename_ini, filename_log, filename_pov, filename_imag
x = int(render.resolution_x * render.resolution_percentage * 0.01)
y = int(render.resolution_y * render.resolution_percentage * 0.01)
- file = open(filename_ini, "w")
- file.write("Version=3.7\n")
- # write povray text stream to temporary file of same name with _log suffix
- # file.write("All_File='%s'\n" % filename_log)
- # DEBUG.OUT log if none specified:
- file.write("All_File=1\n")
-
- file.write("Input_File_Name='%s'\n" % filename_pov)
- file.write("Output_File_Name='%s'\n" % filename_image)
-
- file.write("Width=%d\n" % x)
- file.write("Height=%d\n" % y)
-
- # Border render.
- if render.use_border:
- file.write("Start_Column=%4g\n" % render.border_min_x)
- file.write("End_Column=%4g\n" % (render.border_max_x))
-
- file.write("Start_Row=%4g\n" % (1.0 - render.border_max_y))
- file.write("End_Row=%4g\n" % (1.0 - render.border_min_y))
-
- file.write("Bounding_Method=2\n") # The new automatic BSP is faster in most scenes
-
- # Activated (turn this back off when better live exchange is done between the two programs
- # (see next comment)
- file.write("Display=1\n")
- file.write("Pause_When_Done=0\n")
- # PNG, with POV-Ray 3.7, can show background color with alpha. In the long run using the
- # POV-Ray interactive preview like bishop 3D could solve the preview for all formats.
- file.write("Output_File_Type=N\n")
- # file.write("Output_File_Type=T\n") # TGA, best progressive loading
- file.write("Output_Alpha=1\n")
-
- if scene.pov.antialias_enable:
- # method 2 (recursive) with higher max subdiv forced because no mipmapping in POV-Ray
- # needs higher sampling.
- # aa_mapping = {"5": 2, "8": 3, "11": 4, "16": 5}
- if using_uberpov:
- method = {"0": 1, "1": 2, "2": 3}
- else:
- method = {"0": 1, "1": 2, "2": 2}
- file.write("Antialias=on\n")
- file.write("Antialias_Depth=%d\n" % scene.pov.antialias_depth)
- file.write("Antialias_Threshold=%.3g\n" % scene.pov.antialias_threshold)
- if using_uberpov and scene.pov.antialias_method == '2':
- file.write("Sampling_Method=%s\n" % method[scene.pov.antialias_method])
- file.write("Antialias_Confidence=%.3g\n" % scene.pov.antialias_confidence)
- else:
- file.write("Sampling_Method=%s\n" % method[scene.pov.antialias_method])
- file.write("Antialias_Gamma=%.3g\n" % scene.pov.antialias_gamma)
- if scene.pov.jitter_enable:
- file.write("Jitter=on\n")
- file.write("Jitter_Amount=%3g\n" % scene.pov.jitter_amount)
- else:
- file.write("Jitter=off\n") # prevent animation flicker
+ with open(filename_ini, "w") as file:
+ file.write("Version=3.7\n")
+ # write povray text stream to temporary file of same name with _log suffix
+ # file.write("All_File='%s'\n" % filename_log)
+ # DEBUG.OUT log if none specified:
+ file.write("All_File=1\n")
+
+ file.write("Input_File_Name='%s'\n" % filename_pov)
+ file.write("Output_File_Name='%s'\n" % filename_image)
+
+ file.write("Width=%d\n" % x)
+ file.write("Height=%d\n" % y)
+
+ # Border render.
+ if render.use_border:
+ file.write("Start_Column=%4g\n" % render.border_min_x)
+ file.write("End_Column=%4g\n" % render.border_max_x)
+
+ file.write("Start_Row=%4g\n" % (1.0 - render.border_max_y))
+ file.write("End_Row=%4g\n" % (1.0 - render.border_min_y))
+
+ file.write("Bounding_Method=2\n") # The new automatic BSP is faster in most scenes
+
+ # Activated (turn this back off when better live exchange is done between the two programs
+ # (see next comment)
+ file.write("Display=1\n")
+ file.write("Pause_When_Done=0\n")
+ # PNG, with POV-Ray 3.7, can show background color with alpha. In the long run using the
+ # POV-Ray interactive preview like bishop 3D could solve the preview for all formats.
+ file.write("Output_File_Type=N\n")
+ # file.write("Output_File_Type=T\n") # TGA, best progressive loading
+ file.write("Output_Alpha=1\n")
+
+ if scene.pov.antialias_enable:
+ # method 2 (recursive) with higher max subdiv forced because no mipmapping in POV-Ray
+ # needs higher sampling.
+ # aa_mapping = {"5": 2, "8": 3, "11": 4, "16": 5}
+ if using_uberpov:
+ method = {"0": 1, "1": 2, "2": 3}
+ else:
+ method = {"0": 1, "1": 2, "2": 2}
+ file.write("Antialias=on\n")
+ file.write("Antialias_Depth=%d\n" % scene.pov.antialias_depth)
+ file.write("Antialias_Threshold=%.3g\n" % scene.pov.antialias_threshold)
+ if using_uberpov and scene.pov.antialias_method == '2':
+ file.write("Sampling_Method=%s\n" % method[scene.pov.antialias_method])
+ file.write("Antialias_Confidence=%.3g\n" % scene.pov.antialias_confidence)
+ else:
+ file.write("Sampling_Method=%s\n" % method[scene.pov.antialias_method])
+ file.write("Antialias_Gamma=%.3g\n" % scene.pov.antialias_gamma)
+ if scene.pov.jitter_enable:
+ file.write("Jitter=on\n")
+ file.write("Jitter_Amount=%3g\n" % scene.pov.jitter_amount)
+ else:
+ file.write("Jitter=off\n") # prevent animation flicker
- else:
- file.write("Antialias=off\n")
- # print("ini file closed %s" % file.closed)
- file.close()
- # print("ini file closed %s" % file.closed)
+ else:
+ file.write("Antialias=off\n")
+ if not file.closed:
+ file.close()
class PovrayRender(bpy.types.RenderEngine):
@@ -1096,7 +1086,7 @@ class PovrayRender(bpy.types.RenderEngine):
return False
write_pov_ini(
- scene, self._temp_file_ini, self._temp_file_log, self._temp_file_in, self._temp_file_out
+ self._temp_file_ini, self._temp_file_log, self._temp_file_in, self._temp_file_out
)
print("***-STARTING-***")
@@ -1222,12 +1212,13 @@ class PovrayRender(bpy.types.RenderEngine):
'''
print(scene.pov.text_block)
text = bpy.data.texts[scene.pov.text_block]
- file = open("%s" % self._temp_file_in, "w")
- # Why are the newlines needed?
- file.write("\n")
- file.write(text.as_string())
- file.write("\n")
- file.close()
+ with open(self._temp_file_in, "w") as file:
+ # Why are the newlines needed?
+ file.write("\n")
+ file.write(text.as_string())
+ file.write("\n")
+ if not file.closed:
+ file.close()
# has to be called to update the frame on exporting animations
scene.frame_set(scene.frame_current)
@@ -1242,7 +1233,6 @@ class PovrayRender(bpy.types.RenderEngine):
self.update_stats("", "POV-Ray 3.7: Exporting ini options from Blender")
write_pov_ini(
- scene,
self._temp_file_ini,
self._temp_file_log,
self._temp_file_in,
@@ -1585,23 +1575,22 @@ class PovrayRender(bpy.types.RenderEngine):
scr = win.screen
for area in scr.areas:
if area.type == 'CONSOLE':
- # pass # XXX temp override
- # context override
- # ctx = {'window': win, 'screen': scr, 'area':area}#bpy.context.copy()
try:
- ctx = {}
- ctx['area'] = area
- ctx['region'] = area.regions[-1]
- ctx['space_data'] = area.spaces.active
- ctx['screen'] = scr # C.screen
- ctx['window'] = win
+ # context override
+ ctx = {
+ 'area': area,
+ 'screen': scr,
+ 'window': win
+ }
# bpy.ops.console.banner(ctx, text = "Hello world")
bpy.ops.console.clear_line(ctx)
- stdmsg = msg.split('\n') # XXX todo , test and see segfault crash?
- for i in stdmsg:
- # Crashes if no Terminal displayed on Windows
- bpy.ops.console.scrollback_append(ctx, text=i, type='INFO')
+ for i in msg.split('\n'):
+ bpy.ops.console.scrollback_append(
+ ctx,
+ text=i,
+ type='INFO'
+ )
# bpy.ops.console.insert(ctx, text=(i + "\n"))
except BaseException as e:
print(e.__doc__)
@@ -1614,7 +1603,7 @@ class PovrayRender(bpy.types.RenderEngine):
self._cleanup()
sound_on = bpy.context.preferences.addons[__package__].preferences.use_sounds
- finished_render_message = "\'Render completed\'"
+ finished_render_message = "\'Et VoilĂ !\'"
if platform.startswith('win') and sound_on:
# Could not find tts Windows command so playing beeps instead :-)
@@ -1666,14 +1655,27 @@ class PovrayRender(bpy.types.RenderEngine):
elif platform == "darwin":
# We don't want the say command to block Python,
# so we add an ampersand after the message
- os.system("say %s &" % (finished_render_message))
-
+ # but if the os TTS package isn't up to date it
+ # still does thus, the try except clause
+ try:
+ os.system("say %s &" % finished_render_message)
+ except BaseException as e:
+ print(e.__doc__)
+ print("your Mac may need an update, try to restart computer")
+ pass
# While Linux frequently has espeak installed or at least can suggest
# Maybe windows could as well ?
elif platform == "linux":
- # We don't want the say command to block Python,
+ # We don't want the espeak command to block Python,
# so we add an ampersand after the message
- os.system("echo %s | espeak &" % (finished_render_message))
+ # but if the espeak TTS package isn't installed it
+ # still does thus, the try except clause
+ try:
+ os.system("echo %s | espeak &" % finished_render_message)
+ except BaseException as e:
+ print(e.__doc__)
+ pass
+
# --------------------------------------------------------------------------------- #
@@ -1697,54 +1699,56 @@ class RenderPovTexturePreview(Operator):
input_prev_file = os.path.join(preview_dir, "Preview.pov")
output_prev_file = os.path.join(preview_dir, tex_prev_name)
# ---------------------------------- ini ---------------------------------- #
- file_ini = open("%s" % ini_prev_file, "w")
- file_ini.write('Version=3.8\n')
- file_ini.write('Input_File_Name="%s"\n' % input_prev_file)
- file_ini.write('Output_File_Name="%s.png"\n' % output_prev_file)
- file_ini.write('Library_Path="%s"\n' % preview_dir)
- file_ini.write('Width=256\n')
- file_ini.write('Height=256\n')
- file_ini.write('Pause_When_Done=0\n')
- file_ini.write('Output_File_Type=N\n')
- file_ini.write('Output_Alpha=1\n')
- file_ini.write('Antialias=on\n')
- file_ini.write('Sampling_Method=2\n')
- file_ini.write('Antialias_Depth=3\n')
- file_ini.write('-d\n')
- file_ini.close()
+ with open(ini_prev_file, "w") as file_ini:
+ file_ini.write('Version=3.8\n')
+ file_ini.write('Input_File_Name="%s"\n' % input_prev_file)
+ file_ini.write('Output_File_Name="%s.png"\n' % output_prev_file)
+ file_ini.write('Library_Path="%s"\n' % preview_dir)
+ file_ini.write('Width=256\n')
+ file_ini.write('Height=256\n')
+ file_ini.write('Pause_When_Done=0\n')
+ file_ini.write('Output_File_Type=N\n')
+ file_ini.write('Output_Alpha=1\n')
+ file_ini.write('Antialias=on\n')
+ file_ini.write('Sampling_Method=2\n')
+ file_ini.write('Antialias_Depth=3\n')
+ file_ini.write('-d\n')
+ if not file_ini.closed:
+ file_ini.close()
# ---------------------------------- pov ---------------------------------- #
- file_pov = open("%s" % input_prev_file, "w")
- pat_name = "PAT_" + string_strip_hyphen(bpy.path.clean_name(tex.name))
- file_pov.write("#declare %s = \n" % pat_name)
- file_pov.write(shading.export_pattern(tex))
-
- file_pov.write("#declare Plane =\n")
- file_pov.write("mesh {\n")
- file_pov.write(
- " triangle {<-2.021,-1.744,2.021>,<-2.021,-1.744,-2.021>,<2.021,-1.744,2.021>}\n"
- )
- file_pov.write(
- " triangle {<-2.021,-1.744,-2.021>,<2.021,-1.744,-2.021>,<2.021,-1.744,2.021>}\n"
- )
- file_pov.write(" texture{%s}\n" % pat_name)
- file_pov.write("}\n")
- file_pov.write("object {Plane}\n")
- file_pov.write("light_source {\n")
- file_pov.write(" <0,4.38,-1.92e-07>\n")
- file_pov.write(" color rgb<4, 4, 4>\n")
- file_pov.write(" parallel\n")
- file_pov.write(" point_at <0, 0, -1>\n")
- file_pov.write("}\n")
- file_pov.write("camera {\n")
- file_pov.write(" location <0, 0, 0>\n")
- file_pov.write(" look_at <0, 0, -1>\n")
- file_pov.write(" right <-1.0, 0, 0>\n")
- file_pov.write(" up <0, 1, 0>\n")
- file_pov.write(" angle 96.805211\n")
- file_pov.write(" rotate <-90.000003, -0.000000, 0.000000>\n")
- file_pov.write(" translate <0.000000, 0.000000, 0.000000>\n")
- file_pov.write("}\n")
- file_pov.close()
+ with open(input_prev_file, "w") as file_pov:
+ pat_name = "PAT_" + string_strip_hyphen(bpy.path.clean_name(tex.name))
+ file_pov.write("#declare %s = \n" % pat_name)
+ file_pov.write(shading.export_pattern(tex))
+
+ file_pov.write("#declare Plane =\n")
+ file_pov.write("mesh {\n")
+ file_pov.write(
+ " triangle {<-2.021,-1.744,2.021>,<-2.021,-1.744,-2.021>,<2.021,-1.744,2.021>}\n"
+ )
+ file_pov.write(
+ " triangle {<-2.021,-1.744,-2.021>,<2.021,-1.744,-2.021>,<2.021,-1.744,2.021>}\n"
+ )
+ file_pov.write(" texture{%s}\n" % pat_name)
+ file_pov.write("}\n")
+ file_pov.write("object {Plane}\n")
+ file_pov.write("light_source {\n")
+ file_pov.write(" <0,4.38,-1.92e-07>\n")
+ file_pov.write(" color rgb<4, 4, 4>\n")
+ file_pov.write(" parallel\n")
+ file_pov.write(" point_at <0, 0, -1>\n")
+ file_pov.write("}\n")
+ file_pov.write("camera {\n")
+ file_pov.write(" location <0, 0, 0>\n")
+ file_pov.write(" look_at <0, 0, -1>\n")
+ file_pov.write(" right <-1.0, 0, 0>\n")
+ file_pov.write(" up <0, 1, 0>\n")
+ file_pov.write(" angle 96.805211\n")
+ file_pov.write(" rotate <-90.000003, -0.000000, 0.000000>\n")
+ file_pov.write(" translate <0.000000, 0.000000, 0.000000>\n")
+ file_pov.write("}\n")
+ if not file_pov.closed:
+ file_pov.close()
# ------------------------------- end write ------------------------------- #
pov_binary = PovrayRender._locate_binary()
@@ -1799,7 +1803,7 @@ class RunPovTextRender(Operator):
bpy.ops.render.render()
- # empty text name property engain
+ # empty text name property again
scene.pov.text_block = ""
return {'FINISHED'}
diff --git a/render_povray/render_gui.py b/render_povray/render_gui.py
index e527511f..ce842f04 100755
--- a/render_povray/render_gui.py
+++ b/render_povray/render_gui.py
@@ -61,14 +61,14 @@ for member in dir(properties_view_layer):
del properties_view_layer
# Use some of the existing buttons.
-from bl_ui import properties_render
+# from bl_ui import properties_render
# DEPRECATED#properties_render.RENDER_PT_render.COMPAT_ENGINES.add('POVRAY_RENDER')
# DEPRECATED#properties_render.RENDER_PT_format.COMPAT_ENGINES.add('POVRAY_RENDER')
# properties_render.RENDER_PT_antialiasing.COMPAT_ENGINES.add('POVRAY_RENDER')
# TORECREATE##DEPRECATED#properties_render.RENDER_PT_shading.COMPAT_ENGINES.add('POVRAY_RENDER')
# DEPRECATED#properties_render.RENDER_PT_output.COMPAT_ENGINES.add('POVRAY_RENDER')
-del properties_render
+# del properties_render
def check_render_freestyle_svg():
@@ -241,6 +241,29 @@ class RENDER_PT_POV_photons(RenderButtonsPanel, Panel):
# end main photons
+def uberpov_only_qmc_til_pov38release(layout):
+ col = layout.column()
+ col.alignment = 'CENTER'
+ col.label(text="Stochastic Anti Aliasing is")
+ col.label(text="Only Available with UberPOV")
+ col.label(text="Feature Set in User Preferences.")
+ col.label(text="Using Type 2 (recursive) instead")
+
+
+def no_qmc_fallbacks(row, scene, layout):
+ row.prop(scene.pov, "jitter_enable", text="Jitter")
+
+ split = layout.split()
+ col = split.column()
+ col.prop(scene.pov, "antialias_depth", text="AA Depth")
+ sub = split.column()
+ sub.prop(scene.pov, "jitter_amount", text="Jitter Amount")
+ sub.enabled = bool(scene.pov.jitter_enable)
+ row = layout.row()
+ row.prop(scene.pov, "antialias_threshold", text="AA Threshold")
+ row.prop(scene.pov, "antialias_gamma", text="AA Gamma")
+
+
class RENDER_PT_POV_antialias(RenderButtonsPanel, Panel):
"""Use this class to define pov antialiasing buttons."""
@@ -258,27 +281,6 @@ class RENDER_PT_POV_antialias(RenderButtonsPanel, Panel):
else:
self.layout.prop(scene.pov, "antialias_enable", text="", icon='ALIASED')
- def uberpov_only_qmc_til_pov38release(self, layout):
- col = layout.column()
- col.alignment = 'CENTER'
- col.label(text="Stochastic Anti Aliasing is")
- col.label(text="Only Available with UberPOV")
- col.label(text="Feature Set in User Preferences.")
- col.label(text="Using Type 2 (recursive) instead")
-
- def no_qmc_fallbacks(self, row, scene, layout):
- row.prop(scene.pov, "jitter_enable", text="Jitter")
-
- split = layout.split()
- col = split.column()
- col.prop(scene.pov, "antialias_depth", text="AA Depth")
- sub = split.column()
- sub.prop(scene.pov, "jitter_amount", text="Jitter Amount")
- sub.enabled = bool(scene.pov.jitter_enable)
- row = layout.row()
- row.prop(scene.pov, "antialias_threshold", text="AA Threshold")
- row.prop(scene.pov, "antialias_gamma", text="AA Gamma")
-
def draw(self, context):
prefs = bpy.context.preferences.addons[__package__].preferences
layout = self.layout
@@ -290,14 +292,15 @@ class RENDER_PT_POV_antialias(RenderButtonsPanel, Panel):
row.prop(scene.pov, "antialias_method", text="")
if prefs.branch_feature_set_povray != 'uberpov' and scene.pov.antialias_method == '2':
- self.uberpov_only_qmc_til_pov38release(layout)
+ uberpov_only_qmc_til_pov38release(layout)
else:
- self.no_qmc_fallbacks(row, scene, layout)
+ no_qmc_fallbacks(row, scene, layout)
if prefs.branch_feature_set_povray == 'uberpov':
row = layout.row()
row.prop(scene.pov, "antialias_confidence", text="AA Confidence")
row.enabled = scene.pov.antialias_method == '2'
+
class RENDER_PT_POV_radiosity(RenderButtonsPanel, Panel):
"""Use this class to define pov radiosity buttons."""
diff --git a/render_povray/render_properties.py b/render_povray/render_properties.py
index 0fbb60da..3b9c81ef 100755
--- a/render_povray/render_properties.py
+++ b/render_povray/render_properties.py
@@ -21,7 +21,7 @@
import bpy
from bpy.utils import register_class, unregister_class
-from bpy.types import PropertyGroup
+from bpy.types import PropertyGroup, Scene
from bpy.props import (
BoolProperty,
IntProperty,
@@ -32,6 +32,7 @@ from bpy.props import (
PointerProperty,
)
+
# ---------------------------------------------------------------- #
# Scene POV properties.
# ---------------------------------------------------------------- #
@@ -180,7 +181,7 @@ class RenderPovSettingsScene(PropertyGroup):
step=0.00000001,
min=0.000000001,
max=1.0,
- default=(1.0),
+ default=1.0,
)
media_diffusion_color: FloatVectorProperty(
@@ -203,7 +204,7 @@ class RenderPovSettingsScene(PropertyGroup):
step=0.000001,
min=0.000000001,
max=1.0,
- default=(0.00002),
+ default=0.00002,
)
media_absorption_color: FloatVectorProperty(
@@ -229,7 +230,7 @@ class RenderPovSettingsScene(PropertyGroup):
step=0.01,
min=-1.0,
max=1.0,
- default=(0.0),
+ default=0.0,
options={"ANIMATABLE"},
)
@@ -680,10 +681,10 @@ classes = (
def register():
for cls in classes:
register_class(cls)
- bpy.types.Scene.pov = PointerProperty(type=RenderPovSettingsScene)
+ Scene.pov = PointerProperty(type=RenderPovSettingsScene)
def unregister():
- del bpy.types.Scene.pov
+ del Scene.pov
for cls in reversed(classes):
unregister_class(cls)
diff --git a/render_povray/scenography.py b/render_povray/scenography.py
index 6f892b3e..ff08b017 100755
--- a/render_povray/scenography.py
+++ b/render_povray/scenography.py
@@ -34,7 +34,7 @@ from .object_primitives import write_object_modifiers
# -------- find image texture # used for export_world -------- #
-def image_format(imgF):
+def image_format(img_f):
"""Identify input image filetypes to transmit to POV."""
# First use the below explicit extensions to identify image file prospects
ext = {
@@ -50,13 +50,13 @@ def image_format(imgF):
'TIF': "tiff",
'EXR': "exr",
'HDR': "hdr",
- }.get(os.path.splitext(imgF)[-1].upper(), "")
+ }.get(os.path.splitext(img_f)[-1].upper(), "")
# Then, use imghdr to really identify the filetype as it can be different
if not ext:
# maybe add a check for if path exists here?
print(" WARNING: texture image has no extension") # too verbose
- ext = what(imgF) # imghdr is a python lib to identify image file types
+ ext = what(img_f) # imghdr is a python lib to identify image file types
return ext
@@ -267,9 +267,8 @@ def export_lights(lamps, file, scene, global_matrix, write_matrix, tab_write):
# Incremented after each lamp export to declare its target
# currently used for Fresnel diffuse shader as their slope vector:
global exported_lights_count
- exported_lights_count = 0
- # Get all lamps
- for ob in lamps:
+ # Get all lamps and keep their count in a global variable
+ for exported_lights_count, ob in enumerate(lamps, start=1):
lamp = ob.data
matrix = global_matrix @ ob.matrix_world
@@ -374,16 +373,14 @@ def export_lights(lamps, file, scene, global_matrix, write_matrix, tab_write):
tab_write("}\n")
- exported_lights_count += 1
-
# v(A,B) rotates vector A about origin by vector B.
file.write(
"#declare lampTarget%s= vrotate(<%.4g,%.4g,%.4g>,<%.4g,%.4g,%.4g>);\n"
% (
exported_lights_count,
- -(ob.location.x),
- -(ob.location.y),
- -(ob.location.z),
+ -ob.location.x,
+ -ob.location.y,
+ -ob.location.z,
ob.rotation_euler.x,
ob.rotation_euler.y,
ob.rotation_euler.z,
@@ -486,40 +483,39 @@ def export_world(world, scene, global_matrix, tab_write):
% (image_format(textures_blend), textures_blend, img_map_bg(t_blend))
)
tab_write("}\n")
- tab_write("%s\n" % (mapping_blend))
+ tab_write("%s\n" % mapping_blend)
# The following layered pigment opacifies to black over the texture for
# transmit below 1 or otherwise adds to itself
- tab_write("pigment {rgb 0 transmit %s}\n" % (tex.intensity))
+ tab_write("pigment {rgb 0 transmit %s}\n" % tex.intensity)
tab_write("}\n")
# tab_write("scale 2\n")
# tab_write("translate -1\n")
# For only Background gradient
- if world_tex_count == 0:
- if world.pov.use_sky_blend:
- tab_write("sky_sphere {\n")
- tab_write("pigment {\n")
- # maybe Should follow the advice of POV doc about replacing gradient
- # for skysphere..5.5
- tab_write("gradient y\n")
- tab_write("color_map {\n")
- # XXX Does not exists anymore
- # if render.alpha_mode == 'STRAIGHT':
- # tab_write("[0.0 rgbt<%.3g, %.3g, %.3g, 1>]\n" % (world.pov.horizon_color[:]))
- # tab_write("[1.0 rgbt<%.3g, %.3g, %.3g, 1>]\n" % (world.pov.zenith_color[:]))
- if render.alpha_mode == 'TRANSPARENT':
- tab_write("[0.0 rgbt<%.3g, %.3g, %.3g, 0.99>]\n" % (world.pov.horizon_color[:]))
- # aa premult not solved with transmit 1
- tab_write("[1.0 rgbt<%.3g, %.3g, %.3g, 0.99>]\n" % (world.pov.zenith_color[:]))
- else:
- tab_write("[0.0 rgbt<%.3g, %.3g, %.3g, 0>]\n" % (world.pov.horizon_color[:]))
- tab_write("[1.0 rgbt<%.3g, %.3g, %.3g, 0>]\n" % (world.pov.zenith_color[:]))
- tab_write("}\n")
- tab_write("}\n")
- tab_write("}\n")
- # Sky_sphere alpha (transmit) is not translating into image alpha the same
- # way as 'background'
+ if world_tex_count == 0 and world.pov.use_sky_blend:
+ tab_write("sky_sphere {\n")
+ tab_write("pigment {\n")
+ # maybe Should follow the advice of POV doc about replacing gradient
+ # for skysphere..5.5
+ tab_write("gradient y\n")
+ tab_write("color_map {\n")
+ # XXX Does not exists anymore
+ # if render.alpha_mode == 'STRAIGHT':
+ # tab_write("[0.0 rgbt<%.3g, %.3g, %.3g, 1>]\n" % (world.pov.horizon_color[:]))
+ # tab_write("[1.0 rgbt<%.3g, %.3g, %.3g, 1>]\n" % (world.pov.zenith_color[:]))
+ if render.alpha_mode == 'TRANSPARENT':
+ tab_write("[0.0 rgbt<%.3g, %.3g, %.3g, 0.99>]\n" % (world.pov.horizon_color[:]))
+ # aa premult not solved with transmit 1
+ tab_write("[1.0 rgbt<%.3g, %.3g, %.3g, 0.99>]\n" % (world.pov.zenith_color[:]))
+ else:
+ tab_write("[0.0 rgbt<%.3g, %.3g, %.3g, 0>]\n" % (world.pov.horizon_color[:]))
+ tab_write("[1.0 rgbt<%.3g, %.3g, %.3g, 0>]\n" % (world.pov.zenith_color[:]))
+ tab_write("}\n")
+ tab_write("}\n")
+ tab_write("}\n")
+ # Sky_sphere alpha (transmit) is not translating into image alpha the same
+ # way as 'background'
# if world.pov.light_settings.use_indirect_light:
# scene.pov.radio_enable=1
@@ -543,7 +539,7 @@ def export_world(world, scene, global_matrix, tab_write):
tab_write("distance %.6f\n" % ((mist.start + mist.depth) ** 2 * 0.368))
tab_write(
"color rgbt<%.3g, %.3g, %.3g, %.3g>\n"
- % (*world.pov.horizon_color, 1.0 - mist.intensity)
+ % (*world.pov.horizon_color, (1.0 - mist.intensity))
)
# tab_write("fog_offset %.6f\n" % mist.start) #create a pov property to prepend
# tab_write("fog_alt %.6f\n" % mist.height) #XXX right?
@@ -557,7 +553,7 @@ def export_world(world, scene, global_matrix, tab_write):
"scattering { %d, rgb %.12f*<%.4g, %.4g, %.4g>\n"
% (
int(scene.pov.media_scattering_type),
- (scene.pov.media_diffusion_scale),
+ scene.pov.media_diffusion_scale,
*(scene.pov.media_diffusion_color[:]),
)
)
@@ -636,7 +632,7 @@ def export_rainbows(rainbows, file, scene, global_matrix, write_matrix, tab_writ
tab_write("}\n")
# tab_write("texture {%s}\n"%pov_mat_name)
- write_object_modifiers(scene, ob, file)
+ write_object_modifiers(ob, file)
# tab_write("rotate x*90\n")
# matrix = global_matrix @ ob.matrix_world
# write_matrix(matrix)
@@ -684,10 +680,11 @@ def export_smoke(file, smoke_obj_name, smoke_path, comments, global_matrix, writ
# channeldata.append(v.real)
resolution = mod_set.resolution_max
- big_res = []
- big_res.append(mod_set.domain_resolution[0])
- big_res.append(mod_set.domain_resolution[1])
- big_res.append(mod_set.domain_resolution[2])
+ big_res = [
+ mod_set.domain_resolution[0],
+ mod_set.domain_resolution[1],
+ mod_set.domain_resolution[2]
+ ]
if mod_set.use_noise:
big_res[0] = big_res[0] * (mod_set.noise_scale + 1)
@@ -791,7 +788,7 @@ def export_smoke(file, smoke_obj_name, smoke_path, comments, global_matrix, writ
file.write(" scattering{ 1, // Type\n")
file.write(" <1,1,1>*0.1\n")
file.write(" } // end scattering\n")
- file.write(" density{density_file df3 \"%s\"\n" % (smoke_path))
+ file.write(" density{density_file df3 \"%s\"\n" % smoke_path)
file.write(" color_map {\n")
file.write(" [0.00 rgb 0]\n")
file.write(" [0.05 rgb 0]\n")
diff --git a/render_povray/scripting.py b/render_povray/scripting.py
index caa79b8c..5f7a2b6e 100755
--- a/render_povray/scripting.py
+++ b/render_povray/scripting.py
@@ -212,7 +212,7 @@ class ImportPOV(bpy.types.Operator, ImportHelper):
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))
+ bpy.ops.pov.addcone(base=r0, cap=r1, height=(y1 - y0))
ob = context.object
ob.location = (x0, y0, z0)
# ob.scale = (r,r,r)
@@ -327,7 +327,9 @@ class ImportPOV(bpy.types.Operator, ImportHelper):
except ValueError:
pass
- except:
+ except BaseException as e:
+ print(e.__doc__)
+ print('An exception occurred: {}'.format(e))
x = y = z = float(cache[2])
r = float(cache[3])
bpy.ops.pov.addsphere(R=r, imported_loc=(x, y, z))
diff --git a/render_povray/scripting_gui.py b/render_povray/scripting_gui.py
index 0dcdc4f1..60774f29 100755
--- a/render_povray/scripting_gui.py
+++ b/render_povray/scripting_gui.py
@@ -112,12 +112,13 @@ class TEXT_OT_POV_insert(Operator):
def execute(self, context):
if self.filepath and isfile(self.filepath):
- file = open(self.filepath, "r")
- bpy.ops.text.insert(text=file.read())
+ with open(self.filepath, "r") as file:
+ bpy.ops.text.insert(text=file.read())
- # places the cursor at the end without scrolling -.-
- # context.space_data.text.write(file.read())
- file.close()
+ # places the cursor at the end without scrolling -.-
+ # context.space_data.text.write(file.read())
+ if not file.closed:
+ file.close()
return {'FINISHED'}
@@ -137,10 +138,9 @@ class TEXT_MT_POV_insert(Menu):
prop = self.layout.operator("wm.path_open", text="Open folder", icon='FILE_FOLDER')
prop.filepath = pov_documents
self.layout.separator()
-
- pov_insert_items_list = []
- for root, dirs, files in os.walk(pov_documents): # todo: structure submenus by dir
- pov_insert_items_list.append(root)
+
+ # todo: structure submenus by dir
+ pov_insert_items_list = [root for root, dirs, files in os.walk(pov_documents)]
print(pov_insert_items_list)
self.path_menu(
pov_insert_items_list,
diff --git a/render_povray/scripting_properties.py b/render_povray/scripting_properties.py
index d4529c18..f0e61244 100755
--- a/render_povray/scripting_properties.py
+++ b/render_povray/scripting_properties.py
@@ -38,7 +38,7 @@ class RenderPovSettingsText(PropertyGroup):
name="Custom Code",
description="rendered source: Both adds text at the " "top of the exported POV file",
items=(("3dview", "View", ""), ("text", "Text", ""), ("both", "Both", "")),
- default="text",
+ default="3dview",
)
diff --git a/render_povray/shading.py b/render_povray/shading.py
index 985afd34..c0eb3925 100755
--- a/render_povray/shading.py
+++ b/render_povray/shading.py
@@ -221,7 +221,7 @@ def write_material(
material.pov.specular_shader == "COOKTORR"
or material.pov.specular_shader == "PHONG"
):
- tab_write("phong %.3g\n" % (material.pov.specular_intensity))
+ tab_write("phong %.3g\n" % material.pov.specular_intensity)
tab_write("phong_size %.3g\n" % (material.pov.specular_hardness / 3.14))
# POV-Ray 'specular' keyword corresponds to a Blinn model, without the ior.
@@ -259,7 +259,7 @@ def write_material(
material.pov.specular_shader == "COOKTORR"
or material.pov.specular_shader == "PHONG"
):
- tab_write("phong 0\n") #%.3g\n" % (material.pov.specular_intensity/5))
+ tab_write("phong 0\n") # %.3g\n" % (material.pov.specular_intensity/5))
tab_write("phong_size %.3g\n" % (material.pov.specular_hardness / 3.14))
# POV-Ray 'specular' keyword corresponds to a Blinn model, without the ior.
@@ -293,13 +293,20 @@ def write_material(
elif ref_level_bound == 3:
# Spec must be Max at ref_level_bound 3 so that white of mixing texture always shows specularity
# That's why it's multiplied by 255. maybe replace by texture's brightest pixel value?
- tab_write(
- "specular %.3g\n"
- % (
- (material.pov.specular_intensity * material.pov.specular_color.v)
- * (255 * slot.specular_factor)
+ if material.pov_texture_slots:
+ max_spec_factor = (
+ material.pov.specular_intensity
+ * material.pov.specular_color.v
+ * 255
+ * slot.specular_factor
)
- )
+ else:
+ max_spec_factor = (
+ material.pov.specular_intensity
+ * material.pov.specular_color.v
+ * 255
+ )
+ tab_write("specular %.3g\n" % max_spec_factor)
tab_write("roughness %.3g\n" % (1 / material.pov.specular_hardness))
tab_write("diffuse %.3g %.3g\n" % (front_diffuse, back_diffuse))
@@ -328,7 +335,7 @@ def write_material(
tab_write("reflection {\n")
tab_write("rgb <%.3g, %.3g, %.3g>\n" % material.pov.mirror_color[:])
if material.pov.mirror_metallic:
- tab_write("metallic %.3g\n" % (raytrace_mirror.reflect_factor))
+ tab_write("metallic %.3g\n" % raytrace_mirror.reflect_factor)
# Blurry reflections for UberPOV
if using_uberpov and raytrace_mirror.gloss_factor < 1.0:
# tab_write("#ifdef(unofficial) #if(unofficial = \"patch\") #if(patch(\"upov-reflection-roughness\") > 0)\n")
@@ -392,6 +399,7 @@ def write_material(
if material:
special_texture_found = False
tmpidx = -1
+ slot = None
for t in material.pov_texture_slots:
tmpidx += 1
# index = material.pov.active_texture_index
@@ -414,6 +422,7 @@ def write_material(
)
):
special_texture_found = True
+
continue # Some texture found
if special_texture_found or colored_specular_found:
@@ -1048,7 +1057,7 @@ def string_strip_hyphen(name):
# WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-def write_nodes(scene, pov_mat_name, ntree, file):
+def write_nodes(pov_mat_name, ntree, file):
"""Translate Blender node trees to pov and write them to file."""
# such function local inlined import are official guidelines
# of Blender Foundation to lighten addons footprint at startup
@@ -1164,7 +1173,10 @@ def write_nodes(scene, pov_mat_name, ntree, file):
pass
else:
color = link.from_node.inputs["Color"].default_value[:]
- file.write(" <%.4g,%.4g,%.4g>\n" % color)
+ file.write(
+ " <%.4g,%.4g,%.4g>\n"
+ % (color[0], color[1], color[2])
+ )
if link.from_node.inputs["Exponent"].is_linked:
pass
@@ -1255,7 +1267,7 @@ def write_nodes(scene, pov_mat_name, ntree, file):
if node.bl_idname == "PovrayColorImageNode" and node.outputs["Pigment"].is_linked:
declare_nodes.append(node.name)
if node.image == "":
- file.write("#declare %s = pigment { color rgb 0.8}\n" % (pov_node_name))
+ file.write("#declare %s = pigment { color rgb 0.8}\n" % pov_node_name)
else:
im = bpy.data.images[node.image]
if im.filepath and path.exists(bpy.path.abspath(im.filepath)): # (os.path)
@@ -1287,7 +1299,7 @@ def write_nodes(scene, pov_mat_name, ntree, file):
)
file.write(" %s\n" % once)
if node.map_type != "uv_mapping":
- file.write(" map_type %s\n" % (node.map_type))
+ file.write(" map_type %s\n" % node.map_type)
file.write(
" interpolate %s\n filter all %.4g\n transmit all %.4g\n"
% (
@@ -1335,7 +1347,7 @@ def write_nodes(scene, pov_mat_name, ntree, file):
)
file.write(" %s\n" % once)
if node.map_type != "uv_mapping":
- file.write(" map_type %s\n" % (node.map_type))
+ file.write(" map_type %s\n" % node.map_type)
file.write(" interpolate %s\n" % node.interpolate)
file.write(" }\n")
file.write(" %s\n" % transform)
@@ -1369,7 +1381,7 @@ def write_nodes(scene, pov_mat_name, ntree, file):
file.write(' "%s"\n' % filepath)
file.write(" %s\n" % once)
if node.map_type != "uv_mapping":
- file.write(" map_type %s\n" % (node.map_type))
+ file.write(" map_type %s\n" % node.map_type)
bump_size = node.inputs["Normal"].default_value
if node.inputs["Normal"].is_linked:
pass
diff --git a/render_povray/shading_gui.py b/render_povray/shading_gui.py
index 5e563097..3bb0782c 100755
--- a/render_povray/shading_gui.py
+++ b/render_povray/shading_gui.py
@@ -56,6 +56,40 @@ class MaterialButtonsPanel:
return mat and (rd.engine in cls.COMPAT_ENGINES)
+class MATERIAL_PT_POV_shading(MaterialButtonsPanel, Panel):
+ bl_label = "Shading"
+ COMPAT_ENGINES = {'POVRAY_RENDER'}
+
+ @classmethod
+ def poll(cls, context):
+ mat = context.material
+ engine = context.scene.render.engine
+ return check_material(mat) and (mat.pov.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+
+ mat = context.material # FORMERLY : #active_node_mat(context.material)
+
+ if mat.pov.type in {'SURFACE', 'WIRE'}:
+ split = layout.split()
+
+ col = split.column()
+ sub = col.column()
+ sub.active = not mat.pov.use_shadeless
+ sub.prop(mat.pov, "emit")
+ sub.prop(mat.pov, "ambient")
+ sub = col.column()
+ sub.prop(mat.pov, "translucency")
+
+ col = split.column()
+ col.prop(mat.pov, "use_shadeless")
+ sub = col.column()
+ sub.active = not mat.pov.use_shadeless
+ sub.prop(mat.pov, "use_tangent_shading")
+ sub.prop(mat.pov, "use_cubic")
+
+
class MATERIAL_MT_POV_sss_presets(Menu):
"""Use this class to define pov sss preset menu."""
@@ -115,7 +149,7 @@ class MATERIAL_PT_POV_sss(MaterialButtonsPanel, Panel):
mat = context.material # FORMERLY : #active_node_mat(context.material)
sss = mat.pov_subsurface_scattering
- layout.active = (sss.use) and (not mat.pov.use_shadeless)
+ layout.active = sss.use and (not mat.pov.use_shadeless)
row = layout.row().split()
sub = row.row(align=True).split(align=True, factor=0.75)
@@ -635,6 +669,7 @@ class MATERIAL_PT_POV_replacement_text(MaterialButtonsPanel, Panel):
classes = (
+ MATERIAL_PT_POV_shading,
MATERIAL_PT_POV_sss,
MATERIAL_MT_POV_sss_presets,
MATERIAL_OT_POV_sss_add_preset,
diff --git a/render_povray/shading_nodes.py b/render_povray/shading_nodes.py
index eb7c2bd2..55d323e3 100755
--- a/render_povray/shading_nodes.py
+++ b/render_povray/shading_nodes.py
@@ -608,7 +608,7 @@ def menu_func_nodes(self, context):
class ObjectNodeTree(bpy.types.NodeTree):
- '''Povray Material Nodes'''
+ """Povray Material Nodes"""
bl_idname = 'ObjectNodeTree'
bl_label = 'Povray Object Nodes'
@@ -637,7 +637,7 @@ class ObjectNodeTree(bpy.types.NodeTree):
class PovrayOutputNode(Node, ObjectNodeTree):
- '''Output'''
+ """Output"""
bl_idname = 'PovrayOutputNode'
bl_label = 'Output'
@@ -663,7 +663,7 @@ class PovrayOutputNode(Node, ObjectNodeTree):
# -------- material # ---------------------------------------------------------------- #
class PovrayTextureNode(Node, ObjectNodeTree):
- '''Texture'''
+ """Texture"""
bl_idname = 'PovrayTextureNode'
bl_label = 'Simple texture'
@@ -685,7 +685,7 @@ class PovrayTextureNode(Node, ObjectNodeTree):
class PovrayFinishNode(Node, ObjectNodeTree):
- '''Finish'''
+ """Finish"""
bl_idname = 'PovrayFinishNode'
bl_label = 'Finish'
@@ -713,7 +713,7 @@ class PovrayFinishNode(Node, ObjectNodeTree):
class PovrayDiffuseNode(Node, ObjectNodeTree):
- '''Diffuse'''
+ """Diffuse"""
bl_idname = 'PovrayDiffuseNode'
bl_label = 'Diffuse'
@@ -735,7 +735,7 @@ class PovrayDiffuseNode(Node, ObjectNodeTree):
class PovrayPhongNode(Node, ObjectNodeTree):
- '''Phong'''
+ """Phong"""
bl_idname = 'PovrayPhongNode'
bl_label = 'Phong'
@@ -757,7 +757,7 @@ class PovrayPhongNode(Node, ObjectNodeTree):
class PovraySpecularNode(Node, ObjectNodeTree):
- '''Specular'''
+ """Specular"""
bl_idname = 'PovraySpecularNode'
bl_label = 'Specular'
@@ -779,7 +779,7 @@ class PovraySpecularNode(Node, ObjectNodeTree):
class PovrayMirrorNode(Node, ObjectNodeTree):
- '''Mirror'''
+ """Mirror"""
bl_idname = 'PovrayMirrorNode'
bl_label = 'Mirror'
@@ -803,7 +803,7 @@ class PovrayMirrorNode(Node, ObjectNodeTree):
class PovrayAmbientNode(Node, ObjectNodeTree):
- '''Ambient'''
+ """Ambient"""
bl_idname = 'PovrayAmbientNode'
bl_label = 'Ambient'
@@ -820,7 +820,7 @@ class PovrayAmbientNode(Node, ObjectNodeTree):
class PovrayIridescenceNode(Node, ObjectNodeTree):
- '''Iridescence'''
+ """Iridescence"""
bl_idname = 'PovrayIridescenceNode'
bl_label = 'Iridescence'
@@ -841,7 +841,7 @@ class PovrayIridescenceNode(Node, ObjectNodeTree):
class PovraySubsurfaceNode(Node, ObjectNodeTree):
- '''Subsurface'''
+ """Subsurface"""
bl_idname = 'PovraySubsurfaceNode'
bl_label = 'Subsurface'
@@ -871,7 +871,7 @@ class PovraySubsurfaceNode(Node, ObjectNodeTree):
class PovrayMappingNode(Node, ObjectNodeTree):
- '''Mapping'''
+ """Mapping"""
bl_idname = 'PovrayMappingNode'
bl_label = 'Mapping'
@@ -939,7 +939,7 @@ class PovrayMappingNode(Node, ObjectNodeTree):
class PovrayMultiplyNode(Node, ObjectNodeTree):
- '''Multiply'''
+ """Multiply"""
bl_idname = 'PovrayMultiplyNode'
bl_label = 'Multiply'
@@ -983,7 +983,7 @@ class PovrayMultiplyNode(Node, ObjectNodeTree):
class PovrayTransformNode(Node, ObjectNodeTree):
- '''Transform'''
+ """Transform"""
bl_idname = 'PovrayTransformNode'
bl_label = 'Transform'
@@ -1011,7 +1011,7 @@ class PovrayTransformNode(Node, ObjectNodeTree):
class PovrayValueNode(Node, ObjectNodeTree):
- '''Value'''
+ """Value"""
bl_idname = 'PovrayValueNode'
bl_label = 'Value'
@@ -1026,7 +1026,7 @@ class PovrayValueNode(Node, ObjectNodeTree):
class PovrayModifierNode(Node, ObjectNodeTree):
- '''Modifier'''
+ """Modifier"""
bl_idname = 'PovrayModifierNode'
bl_label = 'Modifier'
@@ -1057,7 +1057,7 @@ class PovrayModifierNode(Node, ObjectNodeTree):
class PovrayPigmentNode(Node, ObjectNodeTree):
- '''Pigment'''
+ """Pigment"""
bl_idname = 'PovrayPigmentNode'
bl_label = 'Color'
@@ -1076,7 +1076,7 @@ class PovrayPigmentNode(Node, ObjectNodeTree):
class PovrayColorImageNode(Node, ObjectNodeTree):
- '''ColorImage'''
+ """ColorImage"""
bl_idname = 'PovrayColorImageNode'
bl_label = 'Image map'
@@ -1162,7 +1162,7 @@ class PovrayColorImageNode(Node, ObjectNodeTree):
class PovrayBumpMapNode(Node, ObjectNodeTree):
- '''BumpMap'''
+ """BumpMap"""
bl_idname = 'PovrayBumpMapNode'
bl_label = 'Bump map'
@@ -1242,7 +1242,7 @@ class PovrayBumpMapNode(Node, ObjectNodeTree):
class PovrayImagePatternNode(Node, ObjectNodeTree):
- '''ImagePattern'''
+ """ImagePattern"""
bl_idname = 'PovrayImagePatternNode'
bl_label = 'Image pattern'
@@ -1323,7 +1323,7 @@ class PovrayImagePatternNode(Node, ObjectNodeTree):
class ShaderPatternNode(Node, ObjectNodeTree):
- '''Pattern'''
+ """Pattern"""
bl_idname = 'ShaderPatternNode'
bl_label = 'Other patterns'
@@ -1407,7 +1407,7 @@ class ShaderPatternNode(Node, ObjectNodeTree):
class ShaderTextureMapNode(Node, ObjectNodeTree):
- '''Texture Map'''
+ """Texture Map"""
bl_idname = 'ShaderTextureMapNode'
bl_label = 'Texture map'
@@ -1459,7 +1459,7 @@ class ShaderTextureMapNode(Node, ObjectNodeTree):
class ShaderNormalMapNode(Node, ObjectNodeTree):
- '''Normal Map'''
+ """Normal Map"""
bl_idname = 'ShaderNormalMapNode'
bl_label = 'Normal map'
@@ -1507,7 +1507,7 @@ class ShaderNormalMapNode(Node, ObjectNodeTree):
class ShaderNormalMapEntryNode(Node, ObjectNodeTree):
- '''Normal Map Entry'''
+ """Normal Map Entry"""
bl_idname = 'ShaderNormalMapEntryNode'
bl_label = 'Normal map entry'
@@ -1521,7 +1521,7 @@ class ShaderNormalMapEntryNode(Node, ObjectNodeTree):
class IsoPropsNode(Node, CompositorNodeTree):
- '''ISO Props'''
+ """ISO Props"""
bl_idname = 'IsoPropsNode'
bl_label = 'Iso'
@@ -1546,7 +1546,7 @@ class IsoPropsNode(Node, CompositorNodeTree):
class PovrayFogNode(Node, CompositorNodeTree):
- '''Fog settings'''
+ """Fog settings"""
bl_idname = 'PovrayFogNode'
bl_label = 'Fog'
@@ -1579,7 +1579,7 @@ class PovrayFogNode(Node, CompositorNodeTree):
class PovraySlopeNode(Node, TextureNodeTree):
- '''Output'''
+ """Output"""
bl_idname = 'PovraySlopeNode'
bl_label = 'Slope Map'
@@ -1614,7 +1614,7 @@ class PovraySlopeNode(Node, TextureNodeTree):
# -------- Texture nodes # ---------------------------------------------------------------- #
class TextureOutputNode(Node, TextureNodeTree):
- '''Output'''
+ """Output"""
bl_idname = 'TextureOutputNode'
bl_label = 'Color Map'
@@ -1645,7 +1645,7 @@ class NODE_OT_iso_add(Operator):
def execute(self, context):
ob = bpy.context.object
- if bpy.context.scene.use_nodes == False:
+ if not bpy.context.scene.use_nodes:
bpy.context.scene.use_nodes = True
tree = bpy.context.scene.node_tree
for node in tree.nodes:
@@ -1666,7 +1666,7 @@ class NODE_OT_map_create(Operator):
space = context.space_data
tree = space.edit_tree
for node in tree.nodes:
- if node.select == True:
+ if node.select:
x, y = node.location
node.select = False
tmap = tree.nodes.new('ShaderTextureMapNode')
@@ -1832,7 +1832,7 @@ class PovrayPatternNode(Operator):
tree = space.edit_tree
for node in tree.nodes:
node.select = False
- if self.add == True:
+ if self.add:
tmap = tree.nodes.new('ShaderNodeValToRGB')
tmap.label = "Pattern"
for inp in tmap.inputs:
@@ -1878,7 +1878,7 @@ class PovrayPatternNode(Operator):
class UpdatePreviewMaterial(Operator):
- '''Operator update preview material'''
+ """Operator update preview material"""
bl_idname = "node.updatepreview"
bl_label = "Update preview"
@@ -1904,7 +1904,7 @@ class UpdatePreviewMaterial(Operator):
class UpdatePreviewKey(Operator):
- '''Operator update preview keymap'''
+ """Operator update preview keymap"""
bl_idname = "wm.updatepreviewkey"
bl_label = "Activate RMB"
diff --git a/render_povray/shading_properties.py b/render_povray/shading_properties.py
index 3a3c944d..9add125e 100755
--- a/render_povray/shading_properties.py
+++ b/render_povray/shading_properties.py
@@ -36,9 +36,8 @@ def check_material(mat):
"""Check that material node tree is not empty if use node button is on"""
if mat is not None:
if mat.use_nodes:
- if not mat.node_tree: # FORMERLY : #mat.active_node_material is not None:
- return True
- return False
+ # No active node material
+ return not mat.node_tree
return True
return False
@@ -66,12 +65,13 @@ def pov_context_tex_datablock(context):
if context.particle_system and context.scene.texture_context == 'PARTICLES':
idblock = context.particle_system.settings
- return idblock
idblock = context.line_style
if idblock and context.scene.texture_context == 'LINESTYLE':
return idblock
+ return idblock
+
def active_texture_name_from_uilist(self, context):
"""Name created texture slots the same as created texture"""
@@ -105,7 +105,6 @@ def active_texture_name_from_search(self, context):
except BaseException as e:
print(e.__doc__)
print('An exception occurred: {}'.format(e))
- pass
def brush_texture_update(self, context):
@@ -220,7 +219,7 @@ class RenderPovSettingsMaterial(PropertyGroup):
diffuse_color: FloatVectorProperty(
name="Diffuse color",
- description=("Diffuse color of the material"),
+ description="Diffuse color of the material",
precision=4,
step=0.01,
min=0, # max=inf, soft_max=1,
@@ -367,7 +366,7 @@ class RenderPovSettingsMaterial(PropertyGroup):
mirror_color: FloatVectorProperty(
name="Mirror color",
- description=("Mirror color of the material"),
+ description="Mirror color of the material",
precision=4,
step=0.01,
min=0, # max=inf, soft_max=1,
@@ -392,7 +391,7 @@ class RenderPovSettingsMaterial(PropertyGroup):
line_color: FloatVectorProperty(
name="Line color",
- description=("Line color used for Freestyle line rendering"),
+ description="Line color used for Freestyle line rendering",
precision=4,
step=0.01,
min=0, # max=inf, soft_max=1,
@@ -422,10 +421,11 @@ class RenderPovSettingsMaterial(PropertyGroup):
specular_color: FloatVectorProperty(
name="Specular color",
- description=("Specular color of the material "),
+ description="Specular color of the material ",
precision=4,
step=0.01,
- min=0, # max=inf, soft_max=1,
+ min=0.0,
+ soft_max=1.0,
default=(1.0, 1.0, 1.0),
options={"ANIMATABLE"},
subtype="COLOR",
@@ -1196,7 +1196,7 @@ class MaterialRaytraceMirror(PropertyGroup):
mirror_color: FloatVectorProperty(
name="Mirror color",
- description=("Mirror color of the material"),
+ description="Mirror color of the material",
precision=4,
step=0.01,
default=(1.0, 1.0, 1.0),
@@ -1240,7 +1240,7 @@ class MaterialSubsurfaceScattering(PropertyGroup):
color: FloatVectorProperty(
name="Scattering color",
- description=("Scattering color"),
+ description="Scattering color",
precision=4,
step=0.01,
default=(0.604, 0.604, 0.604),
@@ -1289,7 +1289,7 @@ class MaterialSubsurfaceScattering(PropertyGroup):
radius: FloatVectorProperty(
name="RGB Radius",
- description=("Mean red/green/blue scattering path length"),
+ description="Mean red/green/blue scattering path length",
precision=4,
step=0.01,
min=0.001,
diff --git a/render_povray/texturing.py b/render_povray/texturing.py
index 225c5369..060316be 100755
--- a/render_povray/texturing.py
+++ b/render_povray/texturing.py
@@ -43,10 +43,7 @@ def write_texture_influence(
):
"""Translate Blender texture influences to various POV texture tricks and write to pov file."""
material_finish = material_names_dictionary[mater.name]
- if mater.pov.use_transparency:
- trans = 1.0 - mater.pov.alpha
- else:
- trans = 0.0
+ trans = 1.0 - mater.pov.alpha if mater.pov.use_transparency else 0.0
if (mater.pov.specular_color.s == 0.0) or (mater.pov.diffuse_shader == "MINNAERT"):
# No layered texture because of aoi pattern used for minnaert and pov can't layer patterned
colored_specular_found = False
@@ -79,9 +76,8 @@ def write_texture_influence(
continue # move to next slot
# Implicit else-if (as not skipped by previous "continue")
- # PROCEDURAL
if tex.type != "IMAGE" and tex.type != "NONE":
- procedural_flag = True
+ # PROCEDURAL TEXTURE
image_filename = "PAT_%s" % string_strip_hyphen(bpy.path.clean_name(tex.name))
if image_filename:
if t.use_map_color_diffuse:
@@ -106,10 +102,9 @@ def write_texture_influence(
# textDispName=tex.image.name + ".displ"
# was the above used? --MR
t_alpha = t
-
# RASTER IMAGE
elif tex.type == "IMAGE" and tex.image and tex.pov.tex_pattern_type == "emulator":
- procedural_flag = False
+ # NOT A PROCEDURAL TEXTURE
# PACKED
if tex.image.packed_file:
orig_image_filename = tex.image.filepath_raw
@@ -131,12 +126,14 @@ def write_texture_influence(
else:
image_filename = path_image(tex.image)
# IMAGE SEQUENCE BEGINS
- if image_filename:
- if bpy.data.images[tex.image.name].source == "SEQUENCE":
- korvaa = "." + str(tex.image_user.frame_offset + 1).zfill(3) + "."
- image_filename = image_filename.replace(".001.", korvaa)
- print(" seq debug ")
- print(image_filename)
+ if (
+ image_filename
+ and bpy.data.images[tex.image.name].source == "SEQUENCE"
+ ):
+ korvaa = "." + str(tex.image_user.frame_offset + 1).zfill(3) + "."
+ image_filename = image_filename.replace(".001.", korvaa)
+ print(" seq debug ")
+ print(image_filename)
# IMAGE SEQUENCE ENDS
img_gamma = ""
if image_filename:
@@ -169,7 +166,7 @@ def write_texture_influence(
tab_write("\n")
# THIS AREA NEEDS TO LEAVE THE TEXTURE OPEN UNTIL ALL MAPS ARE WRITTEN DOWN.
- # --MR
+
current_material_name = string_strip_hyphen(material_names_dictionary[mater.name])
local_material_names.append(current_material_name)
tab_write("\n#declare MAT_%s = \ntexture{\n" % current_material_name)
@@ -193,7 +190,7 @@ def write_texture_influence(
c = 1
while c <= exported_lights_count:
- tab_write("slope { lampTarget%s }\n" % (c))
+ tab_write("slope { lampTarget%s }\n" % c)
tab_write("texture_map {\n")
# Diffuse Fresnel value and factor go up to five,
# other kind of values needed: used the number 5 below to remap
@@ -292,18 +289,19 @@ def write_texture_influence(
tab_write("[0 color rgbft<0,0,0,1,1>]\n")
# if texture_alpha and texture_alpha.startswith("PAT_"):
# tab_write("[1 pigment{%s}]\n" %texture_dif)
- if texture_dif and not texture_dif.startswith("PAT_"):
- tab_write(
- '[1 uv_mapping image_map {%s "%s" %s} %s]\n'
- % (
- image_format(texture_dif),
- texture_dif,
- (img_gamma + img_map(t_dif)),
- mapping_dif,
+ if texture_dif:
+ if not texture_dif.startswith("PAT_"):
+ tab_write(
+ '[1 uv_mapping image_map {%s "%s" %s} %s]\n'
+ % (
+ image_format(texture_dif),
+ texture_dif,
+ (img_gamma + img_map(t_dif)),
+ mapping_dif,
+ )
)
- )
- elif texture_dif and texture_dif.startswith("PAT_"):
- tab_write("[1 %s]\n" % texture_dif)
+ elif texture_dif.startswith("PAT_"):
+ tab_write("[1 %s]\n" % texture_dif)
tab_write("}\n")
tab_write("}\n")
if texture_alpha and texture_alpha.startswith("PAT_"):
@@ -452,9 +450,9 @@ def write_texture_influence(
and mater.pov_raytrace_mirror.gloss_factor < 1.0
and not using_uberpov
):
- tab_write("]}}\n")
+ tab_write(r"]}}"+"\n")
else:
- tab_write("]}\n")
+ tab_write(r"}"+"\n")
if texture_spec != "":
tab_write("]\n")
# -------- Second index for mapping specular max value -------- #
@@ -579,7 +577,7 @@ def write_texture_influence(
) # Blurry reflection or not Proceed with user bump in either case...
tab_write(
"uv_mapping bump_map "
- '{%s "%s" %s bump_size %.4g }%s]\n'
+ '{%s "%s" %s bump_size %.4g }%s\n'
% (
image_format(texture_norm),
texture_norm,
@@ -594,7 +592,7 @@ def write_texture_influence(
and mater.pov_raytrace_mirror.gloss_factor < 1.0
and not using_uberpov
):
- tab_write("}}\n")
+ tab_write("]\n}}\n")
else:
tab_write("}\n")
elif colored_specular_found:
@@ -771,7 +769,7 @@ def write_texture_influence(
) # Blurry reflection or not Proceed with user bump in either case...
tab_write(
"uv_mapping bump_map "
- '{%s "%s" %s bump_size %.4g }%s]\n'
+ '{%s "%s" %s bump_size %.4g }%s\n'
% (
image_format(texture_norm),
texture_norm,
@@ -786,7 +784,7 @@ def write_texture_influence(
and mater.pov_raytrace_mirror.gloss_factor < 1.0
and not using_uberpov
):
- tab_write("}}\n")
+ tab_write("]}}\n")
else:
tab_write("}\n")
if texture_spec != "" and mater.pov.replacement_text == "":
@@ -853,7 +851,7 @@ def write_texture_influence(
for t in mater.pov_texture_slots:
if t and tex.pov.tex_pattern_type != "emulator":
- procedural_flag = True
+ # PROCEDURAL TEXTURE
image_filename = string_strip_hyphen(bpy.path.clean_name(tex.name))
if (
t
@@ -865,30 +863,29 @@ def write_texture_influence(
procedural_flag = False
image_filename = path_image(tex.image)
img_gamma = ""
- if image_filename:
- if t.use_map_normal:
- texture_norm = image_filename
- # colvalue = t.normal_factor/10 # UNUSED XXX *-9.5 !
- # textNormName=tex.image.name + ".normal"
- # was the above used? --MR
- t_nor = t
- if procedural_flag:
- tab_write(
- "normal{function"
- "{f%s(x,y,z).grey} bump_size %.4g}\n"
- % (texture_norm, (-t_nor.normal_factor * 9.5))
- )
- else:
- tab_write(
- "normal {uv_mapping bump_map "
- '{%s "%s" %s bump_size %.4g }%s}\n'
- % (
- image_format(texture_norm),
- texture_norm,
- img_map(t_nor),
- (-t_nor.normal_factor * 9.5),
- mapping_normal,
- )
+ if image_filename and t.use_map_normal:
+ texture_norm = image_filename
+ # colvalue = t.normal_factor/10 # UNUSED XXX *-9.5 !
+ # textNormName=tex.image.name + ".normal"
+ # was the above used? --MR
+ t_nor = t
+ if procedural_flag:
+ tab_write(
+ "normal{function"
+ "{f%s(x,y,z).grey} bump_size %.4g}\n"
+ % (texture_norm, (-t_nor.normal_factor * 9.5))
+ )
+ else:
+ tab_write(
+ "normal {uv_mapping bump_map "
+ '{%s "%s" %s bump_size %.4g }%s}\n'
+ % (
+ image_format(texture_norm),
+ texture_norm,
+ img_map(t_nor),
+ (-t_nor.normal_factor * 9.5),
+ mapping_normal,
)
+ )
tab_write("}\n") # THEN IT CAN CLOSE LAST LAYER OF TEXTURE
diff --git a/render_povray/texturing_gui.py b/render_povray/texturing_gui.py
index 8d285383..2e317a6c 100755
--- a/render_povray/texturing_gui.py
+++ b/render_povray/texturing_gui.py
@@ -106,7 +106,7 @@ class WORLD_TEXTURE_SLOTS_UL_POV_layerlist(UIList):
# We use icon_value of label, as our given icon is an integer value, not an enum ID.
# Note "data" names should never be translated!
if slot:
- layout.prop(item, "texture", text="", emboss=False, icon='TEXTURE')
+ layout.prop(slot, "texture", text="", emboss=False, icon='TEXTURE')
else:
layout.label(text="New", translate=False, icon_value=icon)
# 'GRID' layout type should be as compact as possible (typically a single icon!).
@@ -133,7 +133,7 @@ class MATERIAL_TEXTURE_SLOTS_UL_POV_layerlist(UIList):
# We use icon_value of label, as our given icon is an integer value, not an enum ID.
# Note "data" names should never be translated!
if slot:
- layout.prop(item, "texture", text="", emboss=False, icon='TEXTURE')
+ layout.prop(slot, "texture", text="", emboss=False, icon='TEXTURE')
else:
layout.label(text="New", translate=False, icon_value=icon)
# 'GRID' layout type should be as compact as possible (typically a single icon!).
@@ -203,7 +203,6 @@ class TEXTURE_PT_POV_context_texture(TextureButtonsPanel, Panel):
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
- return engine in cls.COMPAT_ENGINES
# if not (hasattr(context, "pov_texture_slot") or hasattr(context, "texture_node")):
# return False
return (
diff --git a/render_povray/texturing_properties.py b/render_povray/texturing_properties.py
index ceb60264..c085cedf 100755
--- a/render_povray/texturing_properties.py
+++ b/render_povray/texturing_properties.py
@@ -203,7 +203,7 @@ class MaterialTextureSlot(PropertyGroup):
offset: FloatVectorProperty(
name="Offset",
- description=("Fine tune of the texture mapping X, Y and Z locations "),
+ description="Fine tune of the texture mapping X, Y and Z locations ",
precision=4,
step=0.1,
soft_min=-100.0,
@@ -507,7 +507,7 @@ class WorldTextureSlot(PropertyGroup):
offset: FloatVectorProperty(
name="Offset",
- description=("Fine tune of the texture mapping X, Y and Z locations "),
+ description="Fine tune of the texture mapping X, Y and Z locations ",
precision=4,
step=0.1,
soft_min=-100.0,