added XML/PluginManager instantiation example to documentation
parent
2ce74299df
commit
b2f3d3f1dc
124
doc/python.tex
124
doc/python.tex
|
@ -303,6 +303,130 @@ scene.addChild(pmgr.create({
|
||||||
scene.configure()
|
scene.configure()
|
||||||
\end{python}
|
\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}
|
\subsubsection{Taking control of the logging system}
|
||||||
Many operations in Mitsuba will print one or more log messages
|
Many operations in Mitsuba will print one or more log messages
|
||||||
during their execution. By default, they will be printed to the console,
|
during their execution. By default, they will be printed to the console,
|
||||||
|
|
Loading…
Reference in New Issue