done with the python integration (for now)
parent
38b1337788
commit
94fd78d0a5
|
@ -190,6 +190,7 @@ might start the with parameters such as the following
|
|||
$\texttt{\$}$ mitsuba -xj 2 -c machine1;machine2;... animation/frame_*.xml
|
||||
\end{shell}
|
||||
\subsection{Direct connection server}
|
||||
\label{sec:mtssrv}
|
||||
A Mitsuba compute node can be created using the \code{mtssrv} executable. By default,
|
||||
it will listen on port 7554:
|
||||
\begin{shell}
|
||||
|
|
|
@ -8,7 +8,7 @@ software construction tool. There are some differences between the different ope
|
|||
more details, please refer to one of the next sections depending on which one you use.
|
||||
|
||||
\subsection{Common steps}
|
||||
To get started, you will need to download a recent version of Mitsuba. Make sure that you have the Mercurial (\url{http://mercurial.selenic.com/}) versioning system installed\footnote{On Windows, you might also want the convenient TortoiseHG shell extension (\url{http://tortoisehg.bitbucket.org/}) to run the subsequent steps directly from the Explorer.} and enter the following at the command prompt:
|
||||
To get started, you will need to download a recent version of Mitsuba. Make sure that you have the Mercurial (\url{http://mercurial.selenic.com/}) versioning system installed\footnote{On Windows, you might want to use the convenient TortoiseHG shell extension (\url{http://tortoisehg.bitbucket.org/}) to run the subsequent steps directly from the Explorer.} and enter the following at the command prompt:
|
||||
\begin{shell}
|
||||
$\texttt{\$}$ hg clone https://www.mitsuba-renderer.org/hg/mitsuba
|
||||
\end{shell}
|
||||
|
@ -199,7 +199,7 @@ $\text{\$}$ rpmbuild -bb mitsuba-$\code{\MitsubaVersion}$/data/linux/fedora/mits
|
|||
\end{shell}
|
||||
After this command finishes, its output can be found in the directory \code{rpmbuild/RPMS}.
|
||||
\subsection{Building on Arch Linux}
|
||||
You'll first need to install a number of dependencies: run
|
||||
You'll first need to install a number of dependencies:
|
||||
\begin{shell}
|
||||
$\text{\$}$ sudo pacman -S gcc xerces-c glew openexr boost libpng libjpeg qt scons mercurial python
|
||||
\end{shell}
|
||||
|
|
|
@ -81,6 +81,8 @@
|
|||
% Listings settings
|
||||
\lstset{
|
||||
basicstyle = \small\ttfamily\raggedright,
|
||||
commentstyle=\color{lstcomment}\itshape,
|
||||
stringstyle=\color{lstattrib},
|
||||
mathescape = true,
|
||||
frame = lrtb,
|
||||
backgroundcolor = \color{lstshade},
|
||||
|
@ -111,6 +113,7 @@
|
|||
},
|
||||
}
|
||||
|
||||
|
||||
% Set up textpos
|
||||
\TPGrid{68}{108}
|
||||
|
||||
|
@ -125,7 +128,7 @@
|
|||
{}
|
||||
\lstnewenvironment{cpp}[1][]{\lstset{language=c++, #1}}
|
||||
{}
|
||||
\lstnewenvironment{python}[1][]{\lstset{language=python, #1}}
|
||||
\lstnewenvironment{python}[1][]{\lstset{language=Python, #1}}
|
||||
{}
|
||||
\lstnewenvironment{xml}[1][]{\lstset{language=xml, #1}}
|
||||
{}
|
||||
|
@ -156,8 +159,8 @@
|
|||
\IfFileExists{plugins_generated.tex}{\include{plugins_generated}}{}
|
||||
%\include{import}
|
||||
\include{development}
|
||||
%\include{integrator}
|
||||
%\include{parallelization}
|
||||
\include{integrator}
|
||||
\include{parallelization}
|
||||
\include{python}
|
||||
\include{acknowledgements}
|
||||
|
||||
|
|
242
doc/python.tex
242
doc/python.tex
|
@ -2,7 +2,7 @@
|
|||
\label{sec:python}
|
||||
A recent feature of Mitsuba is a simple Python interface to the renderer API.
|
||||
While the interface is still limited at this point, it can already be
|
||||
used for simple automation purposes. To access the API, start your Python
|
||||
used for many useful purposes. To access the API, start your Python
|
||||
interpreter and enter
|
||||
\begin{python}
|
||||
import mitsuba
|
||||
|
@ -10,7 +10,7 @@ import mitsuba
|
|||
For this to work on MacOS X, you will first have to run the ``\emph{Apple
|
||||
Menu}$\to$\emph{Command-line access}'' menu item from within Mitsuba.
|
||||
On Windows and non-packaged Linux builds, you may have to update the extension
|
||||
search path before issuing the \code{import} command:
|
||||
search path before issuing the \code{import} command, e.g.:
|
||||
\begin{python}
|
||||
import sys
|
||||
|
||||
|
@ -20,26 +20,242 @@ sys.path.append('dist/python')
|
|||
|
||||
import mitsuba
|
||||
\end{python}
|
||||
For an overview of the currently exposed API subset, refer
|
||||
For an overview of the currently exposed API subset, please refer
|
||||
to the following page: \url{http://www.mitsuba-renderer.org/api/group__libpython.html}.
|
||||
|
||||
\subsection{Fundamentals}
|
||||
All
|
||||
\subsection{Basics}
|
||||
Generally, the Python API tries to mimic the C++ API as closely as possible.
|
||||
Where applicable, the Python classes and methods replicate overloaded operators,
|
||||
overridable virtual function calls, and default arguments. Under rare circumstances,
|
||||
some features are inherently non-portable due to fundamental differences between the
|
||||
two programming languages. In this case, the API documentation will contain further
|
||||
information.
|
||||
|
||||
Where applicable, the Python wrapper supports operator overloading,
|
||||
default arguments, and
|
||||
Mitsuba's linear algebra-related classes are usable with essentially the
|
||||
same syntax as their C++ versions --- for example, the following snippet
|
||||
creates and rotates a unit vector.
|
||||
\begin{python}
|
||||
import mitsuba
|
||||
from mitsuba.core import *
|
||||
|
||||
# Create a normalized direction vector
|
||||
myVector = normalize(Vector(1.0, 2.0, 3.0))
|
||||
|
||||
print(myVector * 2)
|
||||
# 90 deg. rotation around the Y axis
|
||||
trafo = Transform.rotate(Vector(0, 1, 0), 90)
|
||||
|
||||
Log(EInfo, "" +)
|
||||
# Apply the rotation and display the result
|
||||
print(trafo * myVector)
|
||||
\end{python}
|
||||
|
||||
\subsection{Taking control of the logging system}
|
||||
\subsection{Recipes}
|
||||
The following section contains a series of ``recipes'' on how to do
|
||||
certain things with the help of the Python bindings.
|
||||
|
||||
\subsubsection{Loading a scene}
|
||||
The following script demonstrates how to use the
|
||||
\code{FileResolver} and \code{SceneHandler} classes to
|
||||
load a Mitsuba scene from an XML file:
|
||||
\begin{python}
|
||||
import mitsuba
|
||||
|
||||
from mitsuba.core import *
|
||||
from mitsuba.render import SceneHandler
|
||||
|
||||
# Get a reference to the thread's file resolver
|
||||
fileResolver = Thread.getThread().getFileResolver()
|
||||
|
||||
# Add the search path needed to load plugins
|
||||
fileResolver.addPath('<path to mitsuba directory>')
|
||||
|
||||
# Add the search path needed to load scene resources
|
||||
fileResolver.addPath('<path to scene directory>')
|
||||
|
||||
# Optional: supply parameters that can be accessed
|
||||
# by the scene (e.g. as $\text{\color{lstcomment}\itshape\texttt{\$}}$myParameter)
|
||||
paramMap = StringMap()
|
||||
paramMap['myParameter'] = 'value'
|
||||
|
||||
# Load the scene from an XML file
|
||||
scene = SceneHandler.loadScene(fileResolver, paramMap)
|
||||
|
||||
# Display a textual summary of the scene's contents
|
||||
print(scene)
|
||||
\end{python}
|
||||
|
||||
\subsubsection{Rendering a loaded scene}
|
||||
Once a scene has been loaded, it can be rendered as follows:
|
||||
\begin{python}
|
||||
from mitsuba.core import *
|
||||
from mitsuba.render import RenderQueue, RenderJob
|
||||
import multiprocessing
|
||||
|
||||
scheduler = Scheduler.getInstance()
|
||||
|
||||
# Start up the scheduling system with one worker per local core
|
||||
for i in range(0, multiprocessing.cpu_count()):
|
||||
scheduler.registerWorker(LocalWorker('wrk%i' % i))
|
||||
scheduler.start()
|
||||
|
||||
# Create a queue for tracking render jobs
|
||||
queue = RenderQueue()
|
||||
|
||||
scene.setDestinationFile('renderedResult')
|
||||
|
||||
# Create a render job and insert it into the queue
|
||||
job = RenderJob('myRenderJob', scene, queue)
|
||||
job.start()
|
||||
|
||||
# Wait for all jobs to finish and release resources
|
||||
queue.waitLeft(0)
|
||||
queue.join()
|
||||
|
||||
# Print some statistics about the rendering process
|
||||
print(Statistics.getInstance().getStats())
|
||||
\end{python}
|
||||
|
||||
\subsubsection{Rendering over the network}
|
||||
To render over the network, you must first set up one or
|
||||
more machines that run the \code{mtssrv} server (see \secref{mtssrv}).
|
||||
A network node can then be registered with the scheduler as follows:
|
||||
\begin{python}
|
||||
# Connect to a socket on a named host or IP address
|
||||
# 7554 is the default port of 'mtssrv'
|
||||
stream = SocketStream('128.84.103.222', 7554)
|
||||
|
||||
# Create a remote worker instance that communicates over the stream
|
||||
remoteWorker = RemoteWorker('netWorker', stream)
|
||||
|
||||
scheduler = Scheduler.getInstance()
|
||||
# Register the remote worker (and any other potential workers)
|
||||
scheduler.registerWorker(remoteWorker)
|
||||
scheduler.start()
|
||||
\end{python}
|
||||
|
||||
\subsubsection{Constructing custom scenes from Python}
|
||||
Dynamically constructing Mitsuba scenes entails loading a series of external
|
||||
plugins, instantiating them with custom parameters, and finally assembling
|
||||
them into an object graph.
|
||||
For instance, the following snippet shows how to create a basic
|
||||
perspective camera with a film that writes PNG images:
|
||||
\begin{python}
|
||||
from mitsuba.core import *
|
||||
pmgr = PluginManager.getInstance()
|
||||
|
||||
# Encodes parameters on how to instantiate the 'perspective' plugin
|
||||
cameraProps = Properties('perspective')
|
||||
cameraProps['toWorld'] = Transform.lookAt(
|
||||
Point(0, 0, -10), # Camera origin
|
||||
Point(0, 0, 0), # Camera target
|
||||
Vector(0, 1, 0) # 'up' vector
|
||||
)
|
||||
cameraProps['fov'] = 45.0
|
||||
|
||||
# Encodes parameters on how to instantiate the 'pngfilm' plugin
|
||||
filmProps = Properties('pngfilm')
|
||||
filmProps['width'] = 1920
|
||||
filmProps['height'] = 1080
|
||||
|
||||
# Load and instantiate the plugins
|
||||
camera = pmgr.createObject(cameraProps)
|
||||
film = pmgr.createObject(filmProps)
|
||||
|
||||
# First configure the film and then add it to the camera
|
||||
film.configure()
|
||||
camera.addChild('film', film)
|
||||
|
||||
# Now, the camera can be configured
|
||||
camera.configure()
|
||||
\end{python}
|
||||
The above code fragment uses the plugin manager to construct a
|
||||
\code{Camera} instance from an external plugin named
|
||||
\texttt{perspective.so/dll/dylib} and adds a child object
|
||||
named \texttt{film}, which is a \texttt{Film} instance loaded from the
|
||||
plugin \texttt{pngfilm.so/dll/dylib}.
|
||||
Each time after instantiating a plugin, all child objects are added, and
|
||||
finally the plugin's \code{configure()} method must be called.
|
||||
|
||||
Creating scenes in this manner ends up being rather laborious.
|
||||
Since Python comes with a powerful dynamically-typed dictionary
|
||||
primitive, Mitsuba additionally provides a more ``pythonic''
|
||||
alternative that makes use of this facility:
|
||||
\begin{python}
|
||||
from mitsuba.core import *
|
||||
|
||||
pmgr = PluginManager.getInstance()
|
||||
camera = pmgr.create({
|
||||
'type' : 'perspective',
|
||||
'toWorld' : Transform.lookAt(
|
||||
Point(0, 0, -10),
|
||||
Point(0, 0, 0),
|
||||
Vector(0, 1, 0)
|
||||
),
|
||||
'film' : {
|
||||
'type' : 'pngfilm',
|
||||
'width' : 1920,
|
||||
'height' : 1080
|
||||
}
|
||||
})
|
||||
\end{python}
|
||||
This code does exactly the same as the previous snippet.
|
||||
By the time \code{PluginManager.create} returns, the object
|
||||
hierarchy has already been assembled, and the
|
||||
\code{configure()} method of every object
|
||||
has been called.
|
||||
|
||||
Finally, here is an full example that creates a basic scene
|
||||
which can be rendered. It describes a sphere lit by a point
|
||||
light, rendered using the direct illumination integrator.
|
||||
\begin{python}
|
||||
from mitsuba.core import *
|
||||
from mitsuba.render import Scene
|
||||
|
||||
scene = Scene()
|
||||
|
||||
# Create a camera, film & sample generator
|
||||
scene.addChild(pmgr.create({
|
||||
'type' : 'perspective',
|
||||
'toWorld' : Transform.lookAt(
|
||||
Point(0, 0, -10),
|
||||
Point(0, 0, 0),
|
||||
Vector(0, 1, 0)
|
||||
),
|
||||
'film' : {
|
||||
'type' : 'pngfilm',
|
||||
'width' : 1920,
|
||||
'height' : 1080
|
||||
},
|
||||
'sampler' : {
|
||||
'type' : 'ldsampler',
|
||||
'sampleCount' : 2
|
||||
}
|
||||
}))
|
||||
|
||||
# Set the integrator
|
||||
scene.addChild(pmgr.create({
|
||||
'type' : 'direct'
|
||||
}))
|
||||
|
||||
# Add a light source
|
||||
scene.addChild(pmgr.create({
|
||||
'type' : 'point',
|
||||
'position' : Point(5, 0, -10),
|
||||
'intensity' : Spectrum(100)
|
||||
}))
|
||||
|
||||
# Add a shape
|
||||
scene.addChild(pmgr.create({
|
||||
'type' : 'sphere',
|
||||
'center' : Point(0, 0, 0),
|
||||
'radius' : 1.0,
|
||||
'bsdf' : {
|
||||
'type' : 'diffuse',
|
||||
'reflectance' : Spectrum(0.4)
|
||||
}
|
||||
}))
|
||||
\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,
|
||||
which may be undesirable. Similar to the C++ side, it is possible to define
|
||||
|
@ -57,7 +273,7 @@ from mitsuba.core import *
|
|||
|
||||
class MyFormatter(Formatter):
|
||||
def format(self, logLevel, sourceClass, sourceThread, message, filename, line):
|
||||
return "%s (log level: %s, thread: %s, class %s, file %s, line %i)" % \
|
||||
return '%s (log level: %s, thread: %s, class %s, file %s, line %i)' % \
|
||||
(message, str(logLevel), sourceThread.getName(), sourceClass,
|
||||
filename, line)
|
||||
|
||||
|
@ -66,7 +282,7 @@ class MyAppender(Appender):
|
|||
print(message)
|
||||
|
||||
def logProgress(self, progress, name, formatted, eta):
|
||||
print("Progress message: " + formatted)
|
||||
print('Progress message: ' + formatted)
|
||||
|
||||
# Get the logger associated with the current thread
|
||||
logger = Thread.getThread().getLogger()
|
||||
|
@ -75,5 +291,5 @@ logger.clearAppenders()
|
|||
logger.addAppender(MyAppender())
|
||||
logger.setLogLevel(EDebug)
|
||||
|
||||
Log(EInfo, "Test message")
|
||||
Log(EInfo, 'Test message')
|
||||
\end{python}
|
||||
|
|
|
@ -23,13 +23,16 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/** \brief Abstract interface for objects that reference shared network resources.
|
||||
/** \brief Abstract interface for objects that reference shared network
|
||||
* resources.
|
||||
*
|
||||
* When a networked object is serialized as part of a parallel process executed on
|
||||
* multiple machines, the object is first given the opportunity to bind named resources
|
||||
* to the process (by a call to <tt>\ref bindUsedResources()</tt>). These will then be
|
||||
* distributed to all participating compute servers. Once unserialized on the remote side,
|
||||
* <tt>\ref wakeup()</tt> is called to let the object re-associate with the shared resources.
|
||||
* When a networked object is serialized as part of a parallel process
|
||||
* executed on multiple machines, the object is first given the
|
||||
* opportunity to bind named resources to the process (by a call to
|
||||
* \ref bindUsedResources()). These will then be distributed to all
|
||||
* participating compute servers. Once unserialized on the remote side,
|
||||
* \ref wakeup() is called to let the object re-associate with the
|
||||
* shared resources.
|
||||
*
|
||||
* \ingroup libcore
|
||||
*/
|
||||
|
|
|
@ -30,8 +30,8 @@ MTS_NAMESPACE_BEGIN
|
|||
* \brief Abstract plugin class -- represents loadable configurable objects
|
||||
* and utilities.
|
||||
*
|
||||
* Please see the <tt>\ref ConfigurableObject</tt> and
|
||||
* <tt>\ref Utility</tt> classes for details
|
||||
* Please see the \ref ConfigurableObject and \ref Utility classes for
|
||||
* details.
|
||||
*
|
||||
* \ingroup libcore
|
||||
*/
|
||||
|
@ -86,6 +86,44 @@ private:
|
|||
* \brief The plugin manager is responsible for resolving and
|
||||
* loading external plugins.
|
||||
*
|
||||
* Ordinarily, this class will be used by making repeated calls to
|
||||
* the \ref createObject() methods. The generated instances are then
|
||||
* assembled into a final object graph, such as a scene. One such
|
||||
* examples is the \ref SceneHandler class, which parses an XML
|
||||
* scene file by esentially translating the XML elements into calls
|
||||
* to \ref createObject().
|
||||
*
|
||||
* Since this kind of construction method can be tiresome when
|
||||
* dynamically building scenes from Python, this class has an
|
||||
* additional Python-only method \c create(), which works as follows:
|
||||
*
|
||||
* \code
|
||||
* from mitsuba.core import *
|
||||
*
|
||||
* pmgr = PluginManager.getInstance()
|
||||
* camera = pmgr.create({
|
||||
* "type" : "perspective",
|
||||
* "toWorld" : Transform.lookAt(
|
||||
* Point(0, 0, -10),
|
||||
* Point(0, 0, 0),
|
||||
* Vector(0, 1, 0)
|
||||
* ),
|
||||
* "film" : {
|
||||
* "type" : "pngfilm",
|
||||
* "width" : 1920,
|
||||
* "height" : 1080
|
||||
* }
|
||||
* })
|
||||
* \endcode
|
||||
*
|
||||
* The above snippet constructs a \ref Camera instance from a
|
||||
* plugin named \c perspective.so/dll/dylib and adds a child object
|
||||
* named \c film, which is a \ref Film instance loaded from the
|
||||
* plugin \c pngfilm.so/dll/dylib. By the time the function
|
||||
* returns, the object hierarchy has already been assembled, and the
|
||||
* \ref ConfigurableObject::configure() methods of every object
|
||||
* has been called.
|
||||
*
|
||||
* \ingroup libcore
|
||||
* \ingroup libpython
|
||||
*/
|
||||
|
|
|
@ -340,10 +340,10 @@ public:
|
|||
*/
|
||||
static void rotation(const Transform &t, SHRotation &rot);
|
||||
|
||||
/** \brief Precomputes normalization coefficients for the first few bands */
|
||||
/// Precomputes normalization coefficients for the first few bands
|
||||
static void staticInitialization();
|
||||
|
||||
/// Free the memory taken by staticInitialization()
|
||||
/// Free the memory taken up by staticInitialization()
|
||||
static void staticShutdown();
|
||||
protected:
|
||||
/// Helper function for rotation() -- computes a diagonal block based on the previous level
|
||||
|
|
|
@ -41,6 +41,7 @@ MTS_NAMESPACE_BEGIN
|
|||
* Note: SSH streams are set to use network byte order by default.
|
||||
*
|
||||
* \ingroup libcore
|
||||
* \ingroup libpython
|
||||
*/
|
||||
class MTS_EXPORT_CORE SSHStream : public Stream {
|
||||
public:
|
||||
|
@ -49,10 +50,11 @@ public:
|
|||
// =============================================================
|
||||
|
||||
/**
|
||||
* Create a new SSH stream. The timeout parameter specifies specifies
|
||||
* the maximum amount of time that can be spent before failing to
|
||||
* create the initial connection. This feature is unsupported
|
||||
* (and ignored) on Windows.
|
||||
* \brief Create a new SSH stream.
|
||||
*
|
||||
* The timeout parameter specifies specifies the maximum amount of
|
||||
* time that can be spent before failing to create the initial
|
||||
* connection. This feature is unsupported (and ignored) on Windows.
|
||||
*
|
||||
* \param userName Username to use for the authentication
|
||||
* \param hostName Destination host name
|
||||
|
|
|
@ -36,6 +36,7 @@ MTS_NAMESPACE_BEGIN
|
|||
* order (= big endian).
|
||||
*
|
||||
* \ingroup libcore
|
||||
* \ingroup libpython
|
||||
*/
|
||||
class MTS_EXPORT_CORE SocketStream : public Stream {
|
||||
public:
|
||||
|
@ -43,7 +44,10 @@ public:
|
|||
//! @{ \name Constructors
|
||||
// =============================================================
|
||||
|
||||
/// Create a stream from an existing socket
|
||||
/**
|
||||
* \brief Create a stream from an existing socket
|
||||
* \remark This function is not exposed in the Python bindings
|
||||
*/
|
||||
#if defined(WIN32)
|
||||
SocketStream(SOCKET socket);
|
||||
#else
|
||||
|
|
|
@ -257,7 +257,11 @@ private:
|
|||
/** \brief Collects various rendering statistics and presents them
|
||||
* in a human-readable form.
|
||||
*
|
||||
* \remark Only the \ref getInstance(), \ref getStats(), and
|
||||
* \ref printStats() functions are implemented in the Python bindings.
|
||||
*
|
||||
* \ingroup libcore
|
||||
* \ingroup libpython
|
||||
*/
|
||||
class MTS_EXPORT_CORE Statistics : public Object {
|
||||
public:
|
||||
|
|
|
@ -26,30 +26,54 @@
|
|||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* Render job - coordinates the process of rendering a single
|
||||
* image. Implemented as a thread so that multiple jobs can
|
||||
* \brief Coordinates the process of rendering a single image.
|
||||
*
|
||||
* Implemented as a thread so that multiple jobs can
|
||||
* be executed concurrently.
|
||||
*
|
||||
* \ingroup librender
|
||||
* \ingroup libpython
|
||||
*/
|
||||
class MTS_EXPORT_RENDER RenderJob : public Thread {
|
||||
public:
|
||||
/**
|
||||
* Create a new render job for the given scene. When the
|
||||
* scene, sampler or camera are already registered with the scheduler,
|
||||
* the last parameters can optionally be specified (that way
|
||||
* they do not have to be re-sent to network rendering servers).
|
||||
* \brief Create a new render job for the given scene.
|
||||
*
|
||||
* When the Resource ID parameters (\c sceneResID, \c cameraResID, ..) are
|
||||
* set to \c -1, the implementation will automatically register the
|
||||
* associated objects (scene, camera, sampler) with the scheduler and
|
||||
* forward copies to all involved network rendering workers. When some
|
||||
* of these resources have already been registered with
|
||||
* the scheduler, their IDs can be provided to avoid this extra
|
||||
* communication cost.
|
||||
*
|
||||
* \param threadName
|
||||
* Thread name identifier for this render job
|
||||
* \param scene
|
||||
* Scene to be rendered
|
||||
* \param queue
|
||||
* Pointer to a queue, to which this job should be added
|
||||
* \param sceneResID
|
||||
* Resource ID of \c scene (or \c -1)
|
||||
* \param cameraResID
|
||||
* Resource ID of \c scene->getCamera() (or \c -1)
|
||||
* \param samplerResID
|
||||
* Resource ID of the sample generator (or \c -1)
|
||||
* \param threadIsCritical
|
||||
* When set to \c true, the entire program will terminate
|
||||
* if this thread fails unexpectedly.
|
||||
* \param testSupervisor
|
||||
* When this image is being rendered as part of a test suite,
|
||||
* this parameter points to the associated \ref TestSupervisor
|
||||
* instance.
|
||||
*/
|
||||
RenderJob(const std::string &threadName,
|
||||
Scene *scene, RenderQueue *queue,
|
||||
TestSupervisor *testSupervisor,
|
||||
int sceneResID = -1,
|
||||
int cameraResID = -1,
|
||||
int samplerResID = -1,
|
||||
bool threadIsCritical = true,
|
||||
bool visualFeedback = false);
|
||||
|
||||
/// Should visual feedback be provided (true when rendering using the GUI)
|
||||
inline bool hasVisualFeedback() const { return m_visualFeedback; }
|
||||
TestSupervisor *testSupervisor = NULL);
|
||||
|
||||
/// Write out the current (partially rendered) image
|
||||
inline void flush() { m_scene->flush(); }
|
||||
|
@ -74,7 +98,6 @@ private:
|
|||
bool m_ownsSceneResource;
|
||||
bool m_ownsCameraResource;
|
||||
bool m_ownsSamplerResource;
|
||||
bool m_visualFeedback;
|
||||
bool m_cancelled;
|
||||
};
|
||||
|
||||
|
|
|
@ -53,9 +53,12 @@ protected:
|
|||
};
|
||||
|
||||
/**
|
||||
* Render queue - used to keep track of a number of scenes
|
||||
* that are simultaneously being rendered. Also distributes
|
||||
* events regarding these scenes to registered listeners.
|
||||
* \brief Render queue - used to keep track of a number of scenes
|
||||
* that are simultaneously being rendered.
|
||||
*
|
||||
* This class is also responsible for distributing events about
|
||||
* in-progress renderings to registered listeners.
|
||||
*
|
||||
* \ingroup librender
|
||||
*/
|
||||
class MTS_EXPORT_RENDER RenderQueue : public Object {
|
||||
|
|
|
@ -39,10 +39,12 @@ MTS_NAMESPACE_BEGIN
|
|||
/**
|
||||
* \brief Principal scene data structure
|
||||
*
|
||||
* Holds information on surfaces, luminaires and participating media and
|
||||
* coordinates rendering jobs. This class also provides useful query routines
|
||||
* that are mostly used by the \ref Integrator implementations.
|
||||
* This class holds information on surfaces, luminaires and participating media
|
||||
* and coordinates rendering jobs. It also provides useful query routines that
|
||||
* are mostly used by the \ref Integrator implementations.
|
||||
*
|
||||
* \ingroup librender
|
||||
* \ingroup libpython
|
||||
*/
|
||||
class MTS_EXPORT_RENDER Scene : public NetworkedObject {
|
||||
public:
|
||||
|
@ -64,6 +66,9 @@ public:
|
|||
// =============================================================
|
||||
//! @{ \name Initialization and rendering
|
||||
// =============================================================
|
||||
|
||||
/// Construct a new, empty scene (with the default properties)
|
||||
Scene();
|
||||
|
||||
/// Construct a new, empty scene
|
||||
Scene(const Properties &props);
|
||||
|
@ -85,7 +90,7 @@ public:
|
|||
* before rendering the scene. This might do a variety of things,
|
||||
* such as constructing photon maps or executing distributed overture
|
||||
* passes. Progress is tracked by sending status messages to a provided
|
||||
* render queue. The parameter <tt>job</tt> is required to discern
|
||||
* render queue. The parameter \c job is required to discern
|
||||
* multiple render jobs occurring in parallel. The last three parameters
|
||||
* are resource IDs of the associated scene, camera and sample generator,
|
||||
* which have been made available to all local and remote workers.
|
||||
|
@ -97,14 +102,14 @@ public:
|
|||
/**
|
||||
* Render the scene as seen by the scene's main camera. Progress is tracked
|
||||
* by sending status messages to a provided render queue. The parameter
|
||||
* <tt>job</tt> is required to discern multiple render jobs occurring in
|
||||
* \c job is required to discern multiple render jobs occurring in
|
||||
* parallel. The last three parameters are resource IDs of the associated
|
||||
* scene, camera and sample generator, which have been made available to
|
||||
* all local and remote workers. Returns true upon successful completion.
|
||||
*/
|
||||
bool render(RenderQueue *queue, const RenderJob *job,
|
||||
int sceneResID, int cameraResID, int samplerResID);
|
||||
|
||||
|
||||
/// Post-process step after rendering. Parameters are explained above
|
||||
void postprocess(RenderQueue *queue, const RenderJob *job,
|
||||
int sceneResID, int cameraResID, int samplerResID);
|
||||
|
@ -428,12 +433,14 @@ public:
|
|||
inline Float getTestThreshold() const { return m_testThresh; }
|
||||
|
||||
/**
|
||||
* Set the scene's camera. Note that the camera is not included
|
||||
* when this Scene instance is serialized -- the camera field
|
||||
* will be <tt>NULL</tt> after unserialization. This is intentional
|
||||
* so that the camera can be changed without having to re-transmit
|
||||
* the whole scene. Hence, the camera needs to be submitted separately
|
||||
* and re-attached on the remote side using <tt>setCamera</tt>.
|
||||
* \brief Set the scene's camera.
|
||||
*
|
||||
* Note that the camera is not included when this Scene instance
|
||||
* is serialized -- the camera field will be \c NULL after
|
||||
* unserialization. This is intentional so that the camera can
|
||||
* be changed without having to re-transmit the whole scene.
|
||||
* Hence, the camera needs to be submitted separately
|
||||
* and re-attached on the remote side using \ref setCamera().
|
||||
**/
|
||||
inline void setCamera(Camera *camera) { m_camera = camera; }
|
||||
/// Return the scene's camera
|
||||
|
@ -442,12 +449,14 @@ public:
|
|||
inline const Camera *getCamera() const { return m_camera.get(); }
|
||||
|
||||
/**
|
||||
* Set the scene's integrator. Note that the integrator is not included
|
||||
* when this Scene instance is serialized -- the integrator field
|
||||
* will be <tt>NULL</tt> after unserialization. This is intentional
|
||||
* so that the integrator can be changed without having to re-transmit
|
||||
* the whole scene. Hence, the integrator needs to be submitted separately
|
||||
* and re-attached on the remote side using <tt>setIntegrator</tt>.
|
||||
* \brief Set the scene's integrator.
|
||||
*
|
||||
* Note that the integrator is not included when this Scene instance
|
||||
* is serialized -- the integrator field will be \c NULL after
|
||||
* unserialization. This is intentional so that the integrator can
|
||||
* be changed without having to re-transmit the whole scene. Hence,
|
||||
* the integrator needs to be submitted separately and re-attached
|
||||
* on the remote side using \ref setIntegrator().
|
||||
**/
|
||||
inline void setIntegrator(Integrator *integrator) { m_integrator = integrator; }
|
||||
/// Return the scene's integrator
|
||||
|
@ -456,22 +465,26 @@ public:
|
|||
inline const Integrator *getIntegrator() const { return m_integrator.get(); }
|
||||
|
||||
/**
|
||||
* Set the scene's sampler. Note that the sampler is not included
|
||||
* when this Scene instance is serialized -- the sampler field
|
||||
* will be <tt>NULL</tt> after unserialization. This is intentional
|
||||
* so that the sampler can be changed without having to re-transmit
|
||||
* the whole scene. Hence, the sampler needs to be submitted separately
|
||||
* and re-attached on the remote side using <tt>setSampler</tt>.
|
||||
* \brief Set the scene's sampler.
|
||||
*
|
||||
* Note that the sampler is not included when this Scene instance
|
||||
* is serialized -- the sampler field will be \c NULL after
|
||||
* unserialization. This is intentional so that the sampler can
|
||||
* be changed without having to re-transmit the whole scene.
|
||||
* Hence, the sampler needs to be submitted separately
|
||||
* and re-attached on the remote side using \ref setSampler().
|
||||
**/
|
||||
inline void setSampler(Sampler *sampler) { m_sampler = sampler; }
|
||||
|
||||
/**
|
||||
* Return the scene's sampler. Note that when rendering using multiple
|
||||
* different threads, each thread will be passed a shallow copy of the
|
||||
* scene, which has a different sampler instance. This helps to avoid
|
||||
* locking/contention issues and ensures that different threads render
|
||||
* with different random number sequences. The sampler instance provided
|
||||
* here is a clone of the original sampler specified in the camera.
|
||||
* \brief Return the scene's sampler.
|
||||
*
|
||||
* Note that when rendering using multiple different threads, each
|
||||
* thread will be passed a shallow copy of the scene, which has a
|
||||
* different sampler instance. This helps to avoid locking/contention
|
||||
* issues and ensures that different threads render with different
|
||||
* random number sequences. The sampler instance provided here is a
|
||||
* clone of the original sampler specified in the camera.
|
||||
*/
|
||||
inline Sampler *getSampler() { return m_sampler; }
|
||||
/// Return the scene's sampler
|
||||
|
|
|
@ -50,8 +50,12 @@ private:
|
|||
|
||||
/**
|
||||
* \brief XML parser for Mitsuba scene files. To be used with the
|
||||
* SAX interface Xerces-C++.
|
||||
* SAX interface of Xerces-C++.
|
||||
*
|
||||
* \remark In the Python bindings, only the static function
|
||||
* \ref loadScene() is exposed.
|
||||
* \ingroup librender
|
||||
* \ingroup libpython
|
||||
*/
|
||||
class MTS_EXPORT_RENDER SceneHandler : public HandlerBase {
|
||||
public:
|
||||
|
@ -62,6 +66,16 @@ public:
|
|||
NamedObjectMap *objects = NULL, bool isIncludedFile = false);
|
||||
virtual ~SceneHandler();
|
||||
|
||||
/// Convenience method -- load a scene from a given filename
|
||||
static ref<Scene> loadScene(const fs::path &filename,
|
||||
const ParameterMap ¶ms= ParameterMap());
|
||||
|
||||
/// Initialize Xerces-C++ (needs to be called once at program startup)
|
||||
static void staticInitialization();
|
||||
|
||||
/// Free the memory taken up by staticInitialization()
|
||||
static void staticShutdown();
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Implementation of the SAX DocumentHandler interface
|
||||
// -----------------------------------------------------------------------
|
||||
|
|
|
@ -204,7 +204,7 @@ SerializableObject *Scheduler::getResource(int id, int coreIndex) {
|
|||
m_mutex->unlock();
|
||||
Log(EError, "getResource(): tried to look up manifold resource %i without specifying a core index!", id);
|
||||
}
|
||||
result = rec->resources[coreIndex];
|
||||
result = rec->resources.at(coreIndex);
|
||||
} else {
|
||||
result = rec->resources[0];
|
||||
}
|
||||
|
|
|
@ -13,4 +13,4 @@ if pythonEnv.has_key('PYTHONLIB'):
|
|||
pythonEnv.Prepend(LIBS=pythonEnv['PYTHONLIB'])
|
||||
|
||||
if hasPython:
|
||||
libpython = pythonEnv.SharedLibrary('mitsuba', ['core.cpp']);
|
||||
libpython = pythonEnv.SharedLibrary('mitsuba', ['core.cpp', 'render.cpp']);
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(__MTSPY_H)
|
||||
#define __MTSPY_H
|
||||
#if !defined(__PYTHON_BASE_H)
|
||||
#define __PYTHON_BASE_H
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
|
||||
|
@ -151,5 +151,8 @@ typedef std::vector<std::string> StringVector;
|
|||
typedef std::vector<mitsuba::SerializableObject *> SerializableObjectVector;
|
||||
typedef std::map<std::string, std::string> StringMap;
|
||||
|
||||
#endif /* __MTSPY_H */
|
||||
extern void export_core();
|
||||
extern void export_render();
|
||||
|
||||
#endif /* __PYTHON_BASE_H */
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "core.h"
|
||||
#include "base.h"
|
||||
#include <mitsuba/core/plugin.h>
|
||||
#include <mitsuba/core/shvector.h>
|
||||
#include <mitsuba/core/fstream.h>
|
||||
|
@ -13,6 +13,10 @@
|
|||
#include <mitsuba/core/aabb.h>
|
||||
#include <mitsuba/core/frame.h>
|
||||
#include <mitsuba/core/sched_remote.h>
|
||||
#include <mitsuba/core/netobject.h>
|
||||
#include <mitsuba/core/sstream.h>
|
||||
#include <mitsuba/core/sshstream.h>
|
||||
#include <mitsuba/render/scenehandler.h>
|
||||
|
||||
using namespace mitsuba;
|
||||
|
||||
|
@ -26,10 +30,12 @@ void initializeFramework() {
|
|||
Spectrum::staticInitialization();
|
||||
Scheduler::staticInitialization();
|
||||
SHVector::staticInitialization();
|
||||
SceneHandler::staticInitialization();
|
||||
}
|
||||
|
||||
void shutdownFramework() {
|
||||
/* Shutdown the core framework */
|
||||
SceneHandler::staticShutdown();
|
||||
SHVector::staticShutdown();
|
||||
Scheduler::staticShutdown();
|
||||
Spectrum::staticShutdown();
|
||||
|
@ -282,6 +288,40 @@ Point transform_mul_point(Transform *transform, const Point &point) { return tra
|
|||
Ray transform_mul_ray(Transform *transform, const Ray &ray) { return transform->operator()(ray); }
|
||||
Transform transform_mul_transform(Transform *transform, const Transform &other) { return *transform * other; }
|
||||
|
||||
ConfigurableObject *pluginmgr_create(PluginManager *manager, bp::dict dict) {
|
||||
Properties properties;
|
||||
bp::list list = dict.items();
|
||||
std::map<std::string, ConfigurableObject *> children;
|
||||
|
||||
for (int i=0; i<bp::len(list); ++i) {
|
||||
bp::tuple tuple = bp::extract<bp::tuple>(list[i]);
|
||||
std::string name = bp::extract<std::string>(tuple[0]);
|
||||
bp::extract<bp::dict> extractDict(tuple[1]);
|
||||
bp::extract<std::string> extractString(tuple[1]);
|
||||
bp::extract<ConfigurableObject *> extractConfigurableObject(tuple[1]);
|
||||
|
||||
if (name == "type") {
|
||||
if (!extractString.check())
|
||||
SLog(EError, "'type' property must map to a string!");
|
||||
else
|
||||
properties.setPluginName(extractString());
|
||||
} else if (extractDict.check()) {
|
||||
children[name] = pluginmgr_create(manager, extractDict());
|
||||
} else if (extractConfigurableObject.check()) {
|
||||
children[name] = extractConfigurableObject();
|
||||
} else {
|
||||
properties_wrapper::set(properties, name, tuple[1]);
|
||||
}
|
||||
}
|
||||
|
||||
ConfigurableObject *object = manager->createObject(properties);
|
||||
for (std::map<std::string, ConfigurableObject *>::iterator it = children.begin();
|
||||
it != children.end(); ++it)
|
||||
object->addChild(it->first, it->second);
|
||||
object->configure();
|
||||
return object;
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(fromLinearRGB_overloads, fromLinearRGB, 3, 4)
|
||||
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(fromXYZ_overloads, fromXYZ, 3, 4)
|
||||
|
||||
|
@ -296,6 +336,12 @@ void export_core() {
|
|||
|
||||
BP_SETSCOPE(coreModule);
|
||||
|
||||
/* Basic STL containers */
|
||||
bp::class_<StringVector>("StringVector")
|
||||
.def(bp::vector_indexing_suite<StringVector>());
|
||||
bp::class_<StringMap>("StringMap")
|
||||
.def(bp::map_indexing_suite<StringMap>());
|
||||
|
||||
bp::enum_<ELogLevel>("ELogLevel")
|
||||
.value("ETrace", ETrace)
|
||||
.value("EDebug", EDebug)
|
||||
|
@ -381,6 +427,19 @@ void export_core() {
|
|||
.def("close", &FileStream::close)
|
||||
.def("remove", &FileStream::remove);
|
||||
|
||||
BP_CLASS(SocketStream, Stream, (bp::init<std::string, int>()))
|
||||
.def("getPeer", &SocketStream::getPeer, BP_RETURN_CONSTREF)
|
||||
.def("getReceivedBytes", &SocketStream::getReceivedBytes)
|
||||
.def("getSentBytes", &SocketStream::getSentBytes);
|
||||
|
||||
BP_CLASS(SSHStream, Stream, (bp::init<std::string, std::string, const StringVector &>()))
|
||||
.def(bp::init<std::string, std::string, const StringVector &, int>())
|
||||
.def(bp::init<std::string, std::string, const StringVector &, int, int>())
|
||||
.def("getUserName", &SSHStream::getUserName, BP_RETURN_CONSTREF)
|
||||
.def("getHostName", &SSHStream::getHostName, BP_RETURN_CONSTREF)
|
||||
.def("getReceivedBytes", &SSHStream::getReceivedBytes)
|
||||
.def("getSentBytes", &SSHStream::getSentBytes);
|
||||
|
||||
BP_SETSCOPE(FileStream_class);
|
||||
bp::enum_<FileStream::EFileMode>("EFileMode")
|
||||
.value("EReadOnly", FileStream::EReadOnly)
|
||||
|
@ -394,7 +453,7 @@ void export_core() {
|
|||
|
||||
BP_CLASS(SerializableObject, Object, bp::no_init)
|
||||
.def("serialize", &SerializableObject::serialize);
|
||||
|
||||
|
||||
ConfigurableObject *(ConfigurableObject::*cobject_get_parent)() = &ConfigurableObject::getParent;
|
||||
void (ConfigurableObject::*cobject_add_child_1)(ConfigurableObject *) = &ConfigurableObject::addChild;
|
||||
void (ConfigurableObject::*cobject_add_child_2)(const std::string &, ConfigurableObject *) = &ConfigurableObject::addChild;
|
||||
|
@ -406,6 +465,9 @@ void export_core() {
|
|||
.def("addChild", cobject_add_child_2)
|
||||
.def("configure", &ConfigurableObject::configure);
|
||||
|
||||
BP_CLASS(NetworkedObject, ConfigurableObject, bp::no_init)
|
||||
.def("bindUsedResources", &NetworkedObject::bindUsedResources);
|
||||
|
||||
Thread *(Thread::*thread_get_parent)() = &Thread::getParent;
|
||||
BP_CLASS(Thread, Object, bp::no_init)
|
||||
.def("getID", &Thread::getID)
|
||||
|
@ -538,11 +600,18 @@ void export_core() {
|
|||
BP_CLASS(PluginManager, Object, bp::no_init)
|
||||
.def("ensurePluginLoaded", &PluginManager::ensurePluginLoaded)
|
||||
.def("getLoadedPlugins", &PluginManager::getLoadedPlugins)
|
||||
.def("create", pluginmgr_create, BP_RETURN_VALUE)
|
||||
.def("createObject", pluginmgr_createobject_1, BP_RETURN_VALUE)
|
||||
.def("createObject", pluginmgr_createobject_2, BP_RETURN_VALUE)
|
||||
.def("getInstance", &PluginManager::getInstance, BP_RETURN_VALUE)
|
||||
.staticmethod("getInstance");
|
||||
|
||||
BP_CLASS(Statistics, Object, bp::no_init)
|
||||
.def("getStats", &Statistics::getStats, BP_RETURN_VALUE)
|
||||
.def("printStats", &Statistics::printStats)
|
||||
.def("getInstance", &Statistics::getInstance, BP_RETURN_VALUE)
|
||||
.staticmethod("getInstance");
|
||||
|
||||
BP_CLASS(WorkUnit, Object, bp::no_init)
|
||||
.def("set", &WorkUnit::set)
|
||||
.def("load", &WorkUnit::load)
|
||||
|
@ -999,16 +1068,11 @@ BOOST_PYTHON_MODULE(mitsuba) {
|
|||
bp::object package = bp::scope();
|
||||
package.attr("__path__") = "mitsuba";
|
||||
|
||||
/* Basic STL containers */
|
||||
bp::class_<StringVector>("StringVector")
|
||||
.def(bp::vector_indexing_suite<StringVector>());
|
||||
bp::class_<StringMap>("StringMap")
|
||||
.def(bp::map_indexing_suite<StringMap>());
|
||||
|
||||
/* Automatically take care of the framework
|
||||
initialization / shutdown */
|
||||
initializeFramework();
|
||||
atexit(shutdownFramework);
|
||||
|
||||
export_core();
|
||||
export_render();
|
||||
}
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
RenderJob::RenderJob(const std::string &threadName,
|
||||
Scene *scene, RenderQueue *queue, TestSupervisor *testSupervisor,
|
||||
int sceneResID, int cameraResID, int samplerResID, bool threadIsCritical,
|
||||
bool visualFeedback) : Thread(threadName), m_scene(scene), m_queue(queue),
|
||||
m_testSupervisor(testSupervisor), m_visualFeedback(visualFeedback) {
|
||||
Scene *scene, RenderQueue *queue, int sceneResID, int cameraResID,
|
||||
int samplerResID, bool threadIsCritical, TestSupervisor *supervisor)
|
||||
: Thread(threadName), m_scene(scene), m_queue(queue),
|
||||
m_testSupervisor(supervisor) {
|
||||
|
||||
/* Optional: bring the process down when this thread crashes */
|
||||
setCritical(threadIsCritical);
|
||||
|
|
|
@ -20,10 +20,20 @@
|
|||
#include <mitsuba/render/renderjob.h>
|
||||
#include <mitsuba/core/plugin.h>
|
||||
|
||||
#define DEFAULT_BLOCKSIZE 32
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
Scene::Scene()
|
||||
: NetworkedObject(Properties()), m_blockSize(DEFAULT_BLOCKSIZE) {
|
||||
m_kdtree = new ShapeKDTree();
|
||||
m_testType = ENone;
|
||||
m_testThresh = 0.0f;
|
||||
m_importanceSampleLuminaires = true;
|
||||
}
|
||||
|
||||
Scene::Scene(const Properties &props)
|
||||
: NetworkedObject(props), m_blockSize(32) {
|
||||
: NetworkedObject(props), m_blockSize(DEFAULT_BLOCKSIZE) {
|
||||
m_kdtree = new ShapeKDTree();
|
||||
/* When test case mode is active (Mitsuba is started with the -t parameter),
|
||||
this specifies the type of test performed. Mitsuba will expect a reference
|
||||
|
@ -44,7 +54,7 @@ Scene::Scene(const Properties &props)
|
|||
Log(EError, "Unknown test mode \"%s\" specified (must be \"t-test\" or \"relerr\")",
|
||||
testType.c_str());
|
||||
/* Error threshold for use with <tt>testType</tt> */
|
||||
m_testThresh = props.getFloat("testThresh", 0.01);
|
||||
m_testThresh = props.getFloat("testThresh", 0.01f);
|
||||
/* By default, luminaire sampling chooses a luminaire with a probability
|
||||
dependent on the emitted power. Setting this parameter to false switches
|
||||
to uniform sampling. */
|
||||
|
|
|
@ -556,4 +556,48 @@ void SceneHandler::fatalError(const SAXParseException& e) {
|
|||
transcode(e.getMessage()).c_str());
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
ref<Scene> SceneHandler::loadScene(const fs::path &filename, const ParameterMap ¶ms) {
|
||||
/* Prepare for parsing scene descriptions */
|
||||
FileResolver *resolver = Thread::getThread()->getFileResolver();
|
||||
SAXParser* parser = new SAXParser();
|
||||
fs::path schemaPath = resolver->resolveAbsolute("data/schema/scene.xsd");
|
||||
SLog(EDebug, "Loading scene \"%s\" ..", filename.file_string().c_str());
|
||||
|
||||
/* Check against the 'scene.xsd' XML Schema */
|
||||
parser->setDoSchema(true);
|
||||
parser->setValidationSchemaFullChecking(true);
|
||||
parser->setValidationScheme(SAXParser::Val_Always);
|
||||
parser->setExternalNoNamespaceSchemaLocation(schemaPath.file_string().c_str());
|
||||
parser->setCalculateSrcOfs(true);
|
||||
|
||||
SceneHandler *handler = new SceneHandler(parser, params);
|
||||
parser->setDoNamespaces(true);
|
||||
parser->setDocumentHandler(handler);
|
||||
parser->setErrorHandler(handler);
|
||||
|
||||
parser->parse(filename.file_string().c_str());
|
||||
ref<Scene> scene = handler->getScene();
|
||||
|
||||
delete parser;
|
||||
delete handler;
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
void SceneHandler::staticInitialization() {
|
||||
/* Initialize Xerces-C */
|
||||
try {
|
||||
XMLPlatformUtils::Initialize();
|
||||
} catch(const XMLException &toCatch) {
|
||||
SLog(EError, "Error during Xerces initialization: %s",
|
||||
XMLString::transcode(toCatch.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
void SceneHandler::staticShutdown() {
|
||||
XMLPlatformUtils::Terminate();
|
||||
}
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
|
|
@ -26,31 +26,7 @@ MTS_NAMESPACE_BEGIN
|
|||
|
||||
ref<Scene> Utility::loadScene(const std::string &filename,
|
||||
const ParameterMap ¶ms) {
|
||||
/* Prepare for parsing scene descriptions */
|
||||
FileResolver *resolver = Thread::getThread()->getFileResolver();
|
||||
SAXParser* parser = new SAXParser();
|
||||
fs::path schemaPath = resolver->resolveAbsolute("data/schema/scene.xsd");
|
||||
Log(EDebug, "Loading scene \"%s\" ..", filename.c_str());
|
||||
|
||||
/* Check against the 'scene.xsd' XML Schema */
|
||||
parser->setDoSchema(true);
|
||||
parser->setValidationSchemaFullChecking(true);
|
||||
parser->setValidationScheme(SAXParser::Val_Always);
|
||||
parser->setExternalNoNamespaceSchemaLocation(schemaPath.file_string().c_str());
|
||||
parser->setCalculateSrcOfs(true);
|
||||
|
||||
SceneHandler *handler = new SceneHandler(parser, params);
|
||||
parser->setDoNamespaces(true);
|
||||
parser->setDocumentHandler(handler);
|
||||
parser->setErrorHandler(handler);
|
||||
|
||||
parser->parse(filename.c_str());
|
||||
ref<Scene> scene = handler->getScene();
|
||||
|
||||
delete parser;
|
||||
delete handler;
|
||||
|
||||
return scene;
|
||||
return SceneHandler::loadScene(filename, params);
|
||||
}
|
||||
|
||||
MTS_IMPLEMENT_CLASS(Utility, true, Object)
|
||||
|
|
|
@ -27,6 +27,12 @@ class PointLuminaire : public Luminaire {
|
|||
public:
|
||||
PointLuminaire(const Properties &props) : Luminaire(props) {
|
||||
m_intensity = props.getSpectrum("intensity", Spectrum(1));
|
||||
if (props.hasProperty("position")) {
|
||||
if (props.hasProperty("toWorld"))
|
||||
Log(EError, "Please specify either 'toWorld' or 'position'");
|
||||
m_luminaireToWorld = Transform::translate(Vector(props.getPoint("position")));
|
||||
m_worldToLuminaire = m_luminaireToWorld.inverse();
|
||||
}
|
||||
m_position = m_luminaireToWorld(Point(0,0,0));
|
||||
m_type = EDeltaPosition | EDiffuseDirection;
|
||||
}
|
||||
|
|
|
@ -362,8 +362,7 @@ int mts_main(int argc, char **argv) {
|
|||
continue;
|
||||
|
||||
ref<RenderJob> thr = new RenderJob(formatString("ren%i", jobIdx++),
|
||||
scene, renderQueue, testSupervisor, -1, -1, -1, true,
|
||||
flushTimer > 0);
|
||||
scene, renderQueue, -1, -1, -1, true, testSupervisor);
|
||||
thr->start();
|
||||
|
||||
renderQueue->waitLeft(numParallelScenes-1);
|
||||
|
@ -403,6 +402,7 @@ int main(int argc, char **argv) {
|
|||
Spectrum::staticInitialization();
|
||||
Scheduler::staticInitialization();
|
||||
SHVector::staticInitialization();
|
||||
SceneHandler::staticInitialization();
|
||||
|
||||
#ifdef WIN32
|
||||
/* Initialize WINSOCK2 */
|
||||
|
@ -418,20 +418,10 @@ int main(int argc, char **argv) {
|
|||
setlocale(LC_NUMERIC, "C");
|
||||
#endif
|
||||
|
||||
/* Initialize Xerces-C */
|
||||
try {
|
||||
XMLPlatformUtils::Initialize();
|
||||
} catch(const XMLException &toCatch) {
|
||||
SLog(EError, "Error during Xerces initialization: %s",
|
||||
XMLString::transcode(toCatch.getMessage()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
int retval = mts_main(argc, argv);
|
||||
|
||||
XMLPlatformUtils::Terminate();
|
||||
|
||||
/* Shutdown the core framework */
|
||||
SceneHandler::staticShutdown();
|
||||
SHVector::staticShutdown();
|
||||
Scheduler::staticShutdown();
|
||||
Spectrum::staticShutdown();
|
||||
|
|
|
@ -373,6 +373,7 @@ int mts_main(int argc, char **argv) {
|
|||
Spectrum::staticInitialization();
|
||||
Scheduler::staticInitialization();
|
||||
SHVector::staticInitialization();
|
||||
SceneHandler::staticInitialization();
|
||||
|
||||
#ifdef WIN32
|
||||
/* Initialize WINSOCK2 */
|
||||
|
@ -388,20 +389,10 @@ int mts_main(int argc, char **argv) {
|
|||
setlocale(LC_NUMERIC, "C");
|
||||
#endif
|
||||
|
||||
/* Initialize Xerces-C */
|
||||
try {
|
||||
XMLPlatformUtils::Initialize();
|
||||
} catch(const XMLException &toCatch) {
|
||||
SLog(EError, "Error during Xerces initialization: %s",
|
||||
XMLString::transcode(toCatch.getMessage()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
int retval = mtsutil(argc, argv);
|
||||
|
||||
XMLPlatformUtils::Terminate();
|
||||
|
||||
/* Shutdown the core framework */
|
||||
SceneHandler::staticShutdown();
|
||||
SHVector::staticShutdown();
|
||||
Scheduler::staticShutdown();
|
||||
Spectrum::staticShutdown();
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <xercesc/parsers/SAXParser.hpp>
|
||||
#include <QtGui/QtGui>
|
||||
#include <mitsuba/core/shvector.h>
|
||||
#include <mitsuba/core/sched.h>
|
||||
|
@ -24,6 +23,7 @@
|
|||
#include <mitsuba/core/fresolver.h>
|
||||
#include <mitsuba/core/appender.h>
|
||||
#include <mitsuba/core/statistics.h>
|
||||
#include <mitsuba/render/scenehandler.h>
|
||||
#if defined(__OSX__)
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#endif
|
||||
|
@ -88,15 +88,6 @@ void collect_zombies(int s) {
|
|||
int main(int argc, char *argv[]) {
|
||||
int retval;
|
||||
|
||||
/* Initialize Xerces-C */
|
||||
try {
|
||||
XMLPlatformUtils::Initialize();
|
||||
} catch(const XMLException &toCatch) {
|
||||
fprintf(stderr, "Error during Xerces initialization: %s",
|
||||
XMLString::transcode(toCatch.getMessage()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize the core framework */
|
||||
Class::staticInitialization();
|
||||
PluginManager::staticInitialization();
|
||||
|
@ -107,6 +98,7 @@ int main(int argc, char *argv[]) {
|
|||
Spectrum::staticInitialization();
|
||||
Scheduler::staticInitialization();
|
||||
SHVector::staticInitialization();
|
||||
SceneHandler::staticInitialization();
|
||||
|
||||
#if defined(__LINUX__)
|
||||
XInitThreads();
|
||||
|
@ -191,7 +183,6 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
Statistics::getInstance()->printStats();
|
||||
|
||||
XMLPlatformUtils::Terminate();
|
||||
|
||||
#ifdef WIN32
|
||||
/* Shut down WINSOCK2 */
|
||||
|
@ -199,6 +190,7 @@ int main(int argc, char *argv[]) {
|
|||
#endif
|
||||
|
||||
/* Shutdown the core framework */
|
||||
SceneHandler::staticShutdown();
|
||||
SHVector::staticShutdown();
|
||||
Scheduler::staticShutdown();
|
||||
Spectrum::staticShutdown();
|
||||
|
|
|
@ -1242,8 +1242,8 @@ void MainWindow::on_actionRender_triggered() {
|
|||
|
||||
Scene *scene = context->scene;
|
||||
scene->setBlockSize(m_blockSize);
|
||||
context->renderJob = new RenderJob("rend", scene, m_renderQueue, NULL,
|
||||
context->sceneResID, -1, -1, false, true);
|
||||
context->renderJob = new RenderJob("rend", scene, m_renderQueue,
|
||||
context->sceneResID, -1, -1, false);
|
||||
context->cancelMode = ERender;
|
||||
if (context->mode != ERender)
|
||||
ui->glView->downloadFramebuffer();
|
||||
|
|
Loading…
Reference in New Issue