added XML/PluginManager instantiation example to documentation

metadata
Wenzel Jakob 2014-03-26 21:54:48 +01:00
parent 2ce74299df
commit b2f3d3f1dc
1 changed files with 124 additions and 0 deletions

View File

@ -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,