[Bf-extensions-cvs] [ad66193] master: Render Cube Maps addon

Dalai Felinto noreply at git.blender.org
Fri Nov 11 10:49:45 CET 2016


Commit: ad66193aa09e00596108e6e92646d986156c7541
Author: Dalai Felinto
Date:   Fri Nov 11 10:47:29 2016 +0100
Branches: master
https://developer.blender.org/rBACad66193aa09e00596108e6e92646d986156c7541

Render Cube Maps addon

This addon is originally aimed at VR artists wanting to make cubemaps
for VR rendering. A cubemap is supposed to have a considerable lower
rendertime compared to a panorama. It also fix poles artifact issues.

Thanks BlendFX for funding the development of this addon.

===================================================================

A	render_cube_map.py

===================================================================

diff --git a/render_cube_map.py b/render_cube_map.py
new file mode 100644
index 0000000..d12c5c6
--- /dev/null
+++ b/render_cube_map.py
@@ -0,0 +1,613 @@
+# ====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ======================= END GPL LICENSE BLOCK ========================
+
+# <pep8 compliant>
+
+# ########################################
+# Render Cube Map
+#
+# Dalai Felinto
+# --
+# blendernetwork.org/dalai-felinto
+# www.dalaifelinto.com
+#
+# Original code:
+# Rio de Janeiro, September 2015
+#
+# Latest update:
+# Rio de Janeiro, July 2016
+# ########################################
+
+import bpy
+
+from bpy.app.handlers import persistent
+
+from bpy.types import (
+        Operator,
+        Panel,
+        )
+
+from bpy.props import (
+        BoolProperty,
+        )
+
+bl_info = {
+    "name": "Cube Map",
+    "author": "Dalai Felinto",
+    "version": (1, 0),
+    "blender": (2, 7, 7),
+    "location": "Render Panel",
+    "description": "",
+    "warning": "",
+    "wiki_url": "https://github.com/dfelinto/render_cube_map",
+    "tracker_url": "",
+    "category": "Render"}
+
+
+# ############################################################
+# Global Check
+# ############################################################
+
+def do_run(cube_map, use_force):
+    if not (cube_map.use_cube_map or use_force):
+        return False
+
+    if cube_map.is_enabled and not use_force:
+        return False
+
+    return True
+
+
+# ############################################################
+# Callbacks
+# ############################################################
+
+class NodeTree:
+    def __init__(self, scene):
+        self._use_nodes = scene.use_nodes
+        self._use_compositing = scene.render.use_compositing
+
+        self._nodes_mute = {}
+        self._scene = scene
+
+        self._scene.render.use_compositing = True
+
+        if not self._use_nodes:
+            scene.use_nodes = True
+            self._muteNodes()
+        else:
+            self._storeNodes()
+            self._muteNodes()
+
+    def _storeNodes(self):
+        """
+        store the existent nodes and if they are muted
+        """
+        nodes = self._scene.node_tree.nodes
+        for node in nodes:
+            self._nodes_mute[hash(node)] = node.mute
+
+    def _muteNodes(self):
+        """
+        mute all the existent nodes
+        """
+        nodes = self._scene.node_tree.nodes
+        for node in nodes:
+            node.mute = True
+
+    def cleanupScene(self):
+        """
+        remove all the new nodes, and unmute original ones
+        """
+        scene = self._scene
+        scene.use_nodes = self._use_nodes
+        scene.render.use_compositing = self._use_compositing
+
+        self._cleanNodes()
+        self._unMuteNodes()
+
+    def _cleanNodes(self):
+        """
+        remove all the nodes created temporarily
+        """
+        nodes = self._scene.node_tree.nodes
+        to_del = []
+        keys = self._nodes_mute.keys()
+
+        for node in nodes:
+            if hash(node) not in keys:
+                to_del.append(node)
+
+        for node in to_del:
+            nodes.remove(node)
+
+    def _unMuteNodes(self):
+        """
+        unmute all the existent nodes
+        """
+        nodes = self._scene.node_tree.nodes
+        for node in nodes:
+            node.mute = self._nodes_mute[hash(node)]
+
+
+class View:
+    def __init__(self, name, euler_rotation):
+        self._name = name
+        self._scene = None
+        self._scene_camera = None
+        self._node = None
+        self._camera = None
+        self._euler_rotation = euler_rotation
+
+    def setScene(self, scene):
+        scene.name = self._name
+        self._scene = scene
+
+        scene.cube_map.use_cube_map = False
+        scene.render.use_compositing = False
+
+        self._setFilepath()
+
+    def _setFilepath(self):
+        import os
+
+        filepath = self._scene.render.filepath
+
+        dirname = os.path.dirname(filepath)
+        basename = os.path.basename(filepath)
+
+        path = os.path.join(dirname, "{0}{1}".format(self._name, basename))
+        self._scene.render.filepath = path
+
+    def setNode(self, node, links, node_output):
+        node.name = self._name
+        node.label = self._name
+        node.scene = self._scene
+        self._node = node
+
+        # TODO if there were nodetrees, duplicate them here
+
+        # connect to output
+        _input = node_output.layer_slots.new(self._name)
+        links.new(node.outputs[0], _input)
+
+    def setCamera(self, data, loc, zed):
+        self._scene_camera = self._scene.camera
+
+        self._camera = bpy.data.objects.new(self._name, data)
+        self._scene.objects.link(self._camera)
+
+        rotation = self._euler_rotation.copy()
+        rotation.z += zed
+
+        self._camera.rotation_euler = rotation
+        self._camera.location = loc
+
+        # change scene camera
+        self._scene.camera = self._camera
+
+    def resetCamera(self):
+        self._scene.objects.unlink(self._camera)
+        bpy.data.objects.remove(self._camera)
+        self._camera = None
+
+    @property
+    def scene(self):
+        return self._scene
+
+    @property
+    def name(self):
+        return self._name
+
+
+ at persistent
+def cube_map_render_init(scene, use_force=False):
+    """
+    setup the cube map settings for all the render frames
+    """
+    from mathutils import Euler
+    from math import pi
+    half_pi = pi * 0.5
+
+    cube_map = scene.cube_map
+
+    if not do_run(cube_map, use_force):
+        return
+
+    main_scene = scene
+    hashes = [hash(scene) for scene in bpy.data.scenes]
+
+    views_raw = (
+            (
+                'NORTH_',
+                Euler((half_pi, 0.0,  0.0)),
+                cube_map.use_view_north,
+                ),
+            (
+                'SOUTH_',
+                Euler((half_pi, 0.0, pi)),
+                cube_map.use_view_south,
+                ),
+            (
+                'WEST_',
+                Euler((half_pi, 0.0, half_pi)),
+                cube_map.use_view_west,
+                ),
+            (
+                'EAST_',
+                Euler((half_pi, 0.0, -half_pi)),
+                cube_map.use_view_east,
+                ),
+            (
+                'ZENITH_',
+                Euler((pi, 0.0, 0.0)),
+                cube_map.use_view_zenith,
+                ),
+            (
+                'NADIR_',
+                Euler((0.0, 0.0, 0.0)),
+                cube_map.use_view_nadir,
+                ),
+            )
+
+    views = [
+            View(name, euler) for (name, euler, use) in views_raw
+            if use or not cube_map.is_advanced]
+
+    for view in views:
+        # create a scene per view
+        bpy.ops.scene.new(type='LINK_OBJECTS')
+        scene = [
+                scene for scene in bpy.data.scenes if
+                hash(scene) not in hashes][0]
+
+        # mark the scene to remove it afterwards
+        scene.cube_map.is_temporary = True
+
+        hashes.append(hash(scene))
+        view.setScene(scene)
+
+    # create a scene from scratch
+    node_tree_data = NodeTree(main_scene)
+
+    # created the necessary nodetrees there
+    node_tree = main_scene.node_tree
+
+    # output node
+    node_output = node_tree.nodes.new('CompositorNodeOutputFile')
+    node_output.inputs.clear()
+
+    for view in views:
+        node = node_tree.nodes.new('CompositorNodeRLayers')
+        view.setNode(node, node_tree.links, node_output)
+
+    # globals
+    bpy.cube_map_node_tree_data = node_tree_data
+    bpy.cube_map_views = views
+
+
+# ############################################################
+# Cameras Setup
+# ############################################################
+
+ at persistent
+def cube_map_render_pre(scene, use_force=False):
+
+    if not do_run(scene.cube_map, use_force):
+        return
+
+    from math import radians
+
+    camera = scene.camera
+    data = camera.data.copy()
+
+    data.lens_unit = 'FOV'
+    data.angle = radians(90)
+    data.type = 'PERSP'
+
+    mat = camera.matrix_world
+
+    loc = mat.to_translation()
+    rot = mat.to_euler()
+    zed = rot.z
+
+    views = bpy.cube_map_views
+
+    for view in views:
+        view.setCamera(data, loc, zed)
+
+
+ at persistent
+def cube_map_render_post(scene, use_force=False):
+
+    if not do_run(scene.cube_map, use_force):
+        return
+
+    views = bpy.cube_map_views
+
+    for view in views:
+        view.resetCamera()
+
+
+# ############################################################
+# Clean-Up
+# ############################################################
+
+ at persistent
+def cube_map_render_cancel(scene):
+    cube_map_cleanup(scene)
+
+
+ at persistent
+def cube_map_render_complete(scene):
+    cube_map_cleanup(scene)
+
+
+def cube_map_cleanup(scene, use_force=False):
+    """
+    remove all the temporary data created for the cube map
+    """
+
+    if not do_run(scene.cube_map, use_force):
+        return
+
+    bpy.cube_map_node_tree_data.cleanupScene()
+    del bpy.cube_map_node_tree_data
+    del bpy.cube_map_views
+
+    bpy.app.handlers.scene_update_post.append(cube_map_post_update_cleanup)
+
+
+def cube_map_post_update_cleanup(scene):
+    """
+    delay removal of scenes (otherwise we get a crash)
+    """
+    scenes_temp = [
+            scene for scene in bpy.data.scenes if
+            scene.cub

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list