From b2f3d3f1dca03e209120ad484a1e3392a2d22a52 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Wed, 26 Mar 2014 21:54:48 +0100 Subject: [PATCH] added XML/PluginManager instantiation example to documentation --- doc/python.tex | 124 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/doc/python.tex b/doc/python.tex index 1071df20..ce9b9ff7 100644 --- a/doc/python.tex +++ b/doc/python.tex @@ -303,6 +303,130 @@ scene.addChild(pmgr.create({ scene.configure() \end{python} +\subsubsection{Flexible scene generation for rendering in-process and emitting XML} +The following example shows how to construct a scene in a way so that it can +be rendered in-process or alternatively written to an XML file for later processing. +This is the recommended way of integrating Mitsuba into modeling software. +Roughly, the approach is to create an ordered dictionary version of the entire +scene (named \code{scene\_descr} below) that can either be passed to the +\code{PluginManager} or a simple function that turns it into Mitsuba-compatible XML. + +The example below also does instancing via the \pluginref{shapegroup} +and \pluginref{instance} plugins to show how referencing can be implemented +for such an approach. +\begin{python} +import mitsuba +from mitsuba.core import * +from mitsuba.render import * +from collections import OrderedDict + +def rgb_spectrum(r, g, b): + spec = Spectrum() + spec.fromLinearRGB(r, g, b) + return spec + +# Map that explains what functionality different plugins implement +plugin_type_map ={ + 'sphere' : 'shape', + 'instance' : 'shape', + 'shapegroup' : 'shape', + 'diffuse' : 'bsdf', + 'orthographic' : 'sensor' # need to complete +} + +# Scene description as a big dictionary. The outermost layer +# should be ordered so that references can be processed correctly +scene_descr = OrderedDict([ + ('type', 'scene'), + ('shapegroup_0', { + 'type' : 'shapegroup', + 'id' : 'my_shapegroup', + 'some_child_geometry' : { + 'type' : 'sphere', + 'bsdf' : { + 'type' : 'diffuse', + 'reflectance' : rgb_spectrum(0.5, 0.7, 0.1) + } + } + }), + ('instance_0', { + 'type' : 'instance', + # This is how a reference is specified (type='ref') + 'reference_to_shapegroup' : { + 'type' : 'ref', + 'id' : 'my_shapegroup' + }, + 'toWorld' : Transform.translate(Vector(1, 2.5, 3)) + }), + ('sensor_0', { + 'type' : 'orthographic', + 'toWorld' : Transform.lookAt(Point(0, 0, -1), + Point(0, 0, 0), Vector(0, 1, 0)) * Transform.scale(Vector(10, 10, 1)) + + }) +]) + +def scene_descr_to_xml(descr): + import xml.etree.cElementTree as et + from xml.dom import minidom + + def property_to_xml(key, value, parent): + if type(value) is Transform: + el = et.SubElement(parent, 'transform') + el.set('name', key) + el2 = et.SubElement(el, 'matrix') + matrix = value.getMatrix() + matrix_str = "" + for i in range(4): + for j in range(4): + matrix_str += "%.15g " % matrix[(i, j)] + el2.set('value', matrix_str[:-1]) + elif type(value) is Spectrum: + r, g, b = value.toLinearRGB() + el = et.SubElement(parent, 'rgb') + el.set('name', key) + el.set('value', "%.15g %.15g %.15g" % (r, g, b)) + else: + return None # (More kinds of attributes need to be supported here..) + return el + + def dict_to_xml(name, item, parent): + if parent is None: + el = et.Element('scene') + elif item['type'] == 'ref': + el = et.SubElement(parent, 'ref') + el.set('name', name) + el.set('id', item['id']) + else: + el = et.SubElement(parent, plugin_type_map[item['type']]) + el.set('type', item['type']) + + if name: + el.set('name', name) + if 'id' in item: + el.set('id', item['id']) + for key, value in item.items(): + if key == 'id' or key == 'type': + continue + if type(value) is dict: + dict_to_xml(key, value, el) + else: + property_to_xml(key, value, el) + return el + + root = dict_to_xml(None, descr, None) + root.set('version', $\texttt{\MitsubaVersion}$) + + # Indent the ElementTree output (unfortunately this involves re-parsing..) + return minidom.parseString( + et.tostring(root, 'utf-8')).toprettyxml(indent='\t') + +print('Mitsuba version: ') +print(PluginManager.getInstance().create(scene_descr)) +print('XML version: ') +print(scene_descr_to_xml(scene_descr)) +\end{python} + \subsubsection{Taking control of the logging system} Many operations in Mitsuba will print one or more log messages during their execution. By default, they will be printed to the console,