documentation & python binding improvements
parent
a3896c0f89
commit
139d0d5073
|
@ -1,12 +1,30 @@
|
||||||
\section{Development Guide}
|
\part{Development guide}
|
||||||
This chapter and the subsequent ones will provide an overview
|
This chapter and the subsequent ones will provide an overview
|
||||||
of the the coding conventions and general architecture of Mitsuba.
|
of the the coding conventions and general architecture of Mitsuba.
|
||||||
You should only read them if if you wish to interface with the API
|
You should only read them if if you wish to interface with the API
|
||||||
in some way (e.g. by developing your own plugins). The coding style
|
in some way (e.g. by developing your own plugins). The coding style
|
||||||
section is only relevant if you plan to submit patches, which should
|
section is only relevant if you plan to submit patches that are meant
|
||||||
go into the main codebase.
|
to become part of the main codebase.
|
||||||
|
|
||||||
\subsection{Coding style}
|
\section{Code structure}
|
||||||
|
Mitsuba is split into four basic support libraries:
|
||||||
|
\begin{itemize}
|
||||||
|
\item The core library (\code{libcore}) implements basic functionality such as
|
||||||
|
cross-platform file and bitmap I/O, data structures, scheduling, as well as logging and plugin management.
|
||||||
|
\item The rendering library (\code{librender}) contains abstractions
|
||||||
|
needed to load and represent scenes containing light sources, shapes, materials, and participating media.
|
||||||
|
\item The hardware acceleration library (\code{libhw})
|
||||||
|
implements a cross-platform display library, an object-oriented OpenGL
|
||||||
|
wrapper, as well as support for rendering interactive previews of scenes.
|
||||||
|
\item Finally, the bidirectional library (\code{libbidir})
|
||||||
|
contains a support layer that is used to implement bidirectional rendering algorithms such as
|
||||||
|
Bidirectional Path Tracing and Metropolis Light Transport.
|
||||||
|
\end{itemize}
|
||||||
|
A detailed reference of these APIs is available at
|
||||||
|
\url{http://www.mitsuba-renderer.org/api}. The next sections
|
||||||
|
present a few basic examples to get familiar with them.
|
||||||
|
|
||||||
|
\section{Coding style}
|
||||||
\paragraph{Indentation:} The Mitsuba codebase uses tabs for indentation,
|
\paragraph{Indentation:} The Mitsuba codebase uses tabs for indentation,
|
||||||
which expand to \emph{four} spaces. Please make sure that you configure your editor
|
which expand to \emph{four} spaces. Please make sure that you configure your editor
|
||||||
this way, otherwise the source code layout will look garbled.
|
this way, otherwise the source code layout will look garbled.
|
||||||
|
@ -74,10 +92,10 @@ However, anything pertaining to the API should go into the header file.
|
||||||
\paragraph{Boost:} Use the boost libraries whenever this helps to save
|
\paragraph{Boost:} Use the boost libraries whenever this helps to save
|
||||||
time or write more compact code.
|
time or write more compact code.
|
||||||
|
|
||||||
\paragraph{Classes vs structures:}In Mitsuba, classes \emph{always} go onto the heap,
|
\paragraph{Classes vs structures:}In Mitsuba, classes usually go onto the heap,
|
||||||
whereas structures may be allocated both on the stack and the heap.
|
whereas structures may be allocated both on the stack and the heap.
|
||||||
|
|
||||||
Classes that derive from \code{Object} usually implement a protected virtual
|
Classes that derive from \code{Object} implement a protected virtual
|
||||||
deconstructor, which explicitly prevents them from being allocated on the stack.
|
deconstructor, which explicitly prevents them from being allocated on the stack.
|
||||||
The only way they can be deallocated is using the built-in reference
|
The only way they can be deallocated is using the built-in reference
|
||||||
counting. This is done using the \code{ref<>} template, e.g.
|
counting. This is done using the \code{ref<>} template, e.g.
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
\section{Introduction}
|
\part{Using Mitsuba}
|
||||||
\textbf{Disclaimer:} This is manual documents the usage, file format, and
|
\textbf{Disclaimer:} This is manual documents the usage, file format, and
|
||||||
internal design of the Mitsuba rendering system. It is currently a work
|
internal design of the Mitsuba rendering system. It is currently a work
|
||||||
in progress, hence some parts may still be incomplete or missing.
|
in progress, hence some parts may still be incomplete or missing.
|
||||||
|
|
||||||
\subsection{About Mitsuba}
|
\section{About Mitsuba}
|
||||||
Mitsuba is a research-oriented rendering system in the style of PBRT
|
Mitsuba is a research-oriented rendering system in the style of PBRT
|
||||||
(\url{www.pbrt.org}), from which it derives much inspiration.
|
(\url{www.pbrt.org}), from which it derives much inspiration.
|
||||||
It is written in portable C++, implements unbiased as well
|
It is written in portable C++, implements unbiased as well
|
||||||
|
@ -55,7 +55,7 @@ viewpoint has been found, it is straightforward to perform renderings using any
|
||||||
implemented rendering techniques, while tweaking their parameters to find the most suitable
|
implemented rendering techniques, while tweaking their parameters to find the most suitable
|
||||||
settings. Experimental integration into Blender 2.5 is also available.
|
settings. Experimental integration into Blender 2.5 is also available.
|
||||||
|
|
||||||
\subsection{License}
|
\section{License}
|
||||||
Mitsuba is free software and can be redistributed and modified under the terms of the GNU General
|
Mitsuba is free software and can be redistributed and modified under the terms of the GNU General
|
||||||
Public License (Version 3) as provided by the Free Software Foundation.
|
Public License (Version 3) as provided by the Free Software Foundation.
|
||||||
|
|
||||||
|
|
|
@ -155,7 +155,7 @@
|
||||||
\include{format}
|
\include{format}
|
||||||
\IfFileExists{plugins_generated.tex}{\include{plugins_generated}}{}
|
\IfFileExists{plugins_generated.tex}{\include{plugins_generated}}{}
|
||||||
%\include{import}
|
%\include{import}
|
||||||
%\include{development}
|
\include{development}
|
||||||
%\include{integrator}
|
%\include{integrator}
|
||||||
%\include{parallelization}
|
%\include{parallelization}
|
||||||
\include{python}
|
\include{python}
|
||||||
|
|
|
@ -2,15 +2,15 @@
|
||||||
\label{sec:python}
|
\label{sec:python}
|
||||||
A recent feature of Mitsuba is a simple Python interface to the renderer API.
|
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
|
While the interface is still limited at this point, it can already be
|
||||||
used for simple automation tasks. To access the API, start your Python
|
used for simple automation purposes. To access the API, start your Python
|
||||||
interpreter and run
|
interpreter and enter
|
||||||
\begin{python}
|
\begin{python}
|
||||||
import mitsuba
|
import mitsuba
|
||||||
\end{python}
|
\end{python}
|
||||||
For this to work on MacOS X, you will first have to run the ``\emph{Apple
|
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.
|
Menu}$\to$\emph{Command-line access}'' menu item from within Mitsuba.
|
||||||
On Windows and non-packaged Linux builds, you must update the extension
|
On Windows and non-packaged Linux builds, you may have to update the extension
|
||||||
search path before the \code{import} command is issued:
|
search path before issuing the \code{import} command:
|
||||||
\begin{python}
|
\begin{python}
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
@ -20,4 +20,23 @@ sys.path.append('dist/python')
|
||||||
|
|
||||||
import mitsuba
|
import mitsuba
|
||||||
\end{python}
|
\end{python}
|
||||||
|
For an overview of the currently exposed API subset, refer
|
||||||
|
to the following page: \url{http://www.mitsuba-renderer.org/api/group__libpython.html}.
|
||||||
|
|
||||||
|
\subsection{Fundamentals}
|
||||||
|
All
|
||||||
|
|
||||||
|
Where applicable, the Python wrapper supports operator overloading,
|
||||||
|
default arguments, and
|
||||||
|
\begin{python}
|
||||||
|
import mitsuba
|
||||||
|
from mitsuba.core import *
|
||||||
|
|
||||||
|
myVector = normalize(Vector(1.0, 2.0, 3.0))
|
||||||
|
|
||||||
|
print(myVector * 2)
|
||||||
|
|
||||||
|
Log(EInfo, "" +)
|
||||||
|
\end{python}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -152,6 +152,9 @@ public:
|
||||||
/// Remove an appender from this logger
|
/// Remove an appender from this logger
|
||||||
void removeAppender(Appender *appender);
|
void removeAppender(Appender *appender);
|
||||||
|
|
||||||
|
/// Remove all appenders from this logger
|
||||||
|
void clearAppenders();
|
||||||
|
|
||||||
/// Return the number of registered appenders
|
/// Return the number of registered appenders
|
||||||
inline size_t getAppenderCount() const { return m_appenders.size(); }
|
inline size_t getAppenderCount() const { return m_appenders.size(); }
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ Logger::Logger(ELogLevel level)
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::~Logger() {
|
Logger::~Logger() {
|
||||||
for (unsigned int i=0; i<m_appenders.size(); ++i)
|
for (size_t i=0; i<m_appenders.size(); ++i)
|
||||||
m_appenders[i]->decRef();
|
m_appenders[i]->decRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ void Logger::log(ELogLevel level, const Class *theClass,
|
||||||
m_mutex->lock();
|
m_mutex->lock();
|
||||||
if (level >= EWarn)
|
if (level >= EWarn)
|
||||||
m_warningCount++;
|
m_warningCount++;
|
||||||
for (unsigned int i=0; i<m_appenders.size(); ++i)
|
for (size_t i=0; i<m_appenders.size(); ++i)
|
||||||
m_appenders[i]->append(level, text);
|
m_appenders[i]->append(level, text);
|
||||||
m_mutex->unlock();
|
m_mutex->unlock();
|
||||||
} else {
|
} else {
|
||||||
|
@ -141,7 +141,7 @@ void Logger::log(ELogLevel level, const Class *theClass,
|
||||||
void Logger::logProgress(Float progress, const std::string &name,
|
void Logger::logProgress(Float progress, const std::string &name,
|
||||||
const std::string &formatted, const std::string &eta, const void *ptr) {
|
const std::string &formatted, const std::string &eta, const void *ptr) {
|
||||||
m_mutex->lock();
|
m_mutex->lock();
|
||||||
for (unsigned int i=0; i<m_appenders.size(); ++i)
|
for (size_t i=0; i<m_appenders.size(); ++i)
|
||||||
m_appenders[i]->logProgress(
|
m_appenders[i]->logProgress(
|
||||||
progress, name, formatted, eta, ptr);
|
progress, name, formatted, eta, ptr);
|
||||||
m_mutex->unlock();
|
m_mutex->unlock();
|
||||||
|
@ -162,6 +162,14 @@ void Logger::removeAppender(Appender *appender) {
|
||||||
appender->decRef();
|
appender->decRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Logger::clearAppenders() {
|
||||||
|
m_mutex->lock();
|
||||||
|
for (size_t i=0; i<m_appenders.size(); ++i)
|
||||||
|
m_appenders[i]->decRef();
|
||||||
|
m_appenders.clear();
|
||||||
|
m_mutex->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
void Logger::staticInitialization() {
|
void Logger::staticInitialization() {
|
||||||
Logger *logger = new Logger(EInfo);
|
Logger *logger = new Logger(EInfo);
|
||||||
ref<Appender> appender = new StreamAppender(&std::cout);
|
ref<Appender> appender = new StreamAppender(&std::cout);
|
||||||
|
|
|
@ -159,25 +159,30 @@ void mts_log(ELogLevel level, const std::string &msg) {
|
||||||
bp::object extract_stack(traceback.attr("extract_stack"));
|
bp::object extract_stack(traceback.attr("extract_stack"));
|
||||||
bp::object stack = extract_stack();
|
bp::object stack = extract_stack();
|
||||||
bp::object top(stack[bp::len(stack)-1]);
|
bp::object top(stack[bp::len(stack)-1]);
|
||||||
|
std::string module = bp::extract<std::string>(top[2]);
|
||||||
Thread::getThread()->getLogger()->log(level,
|
Thread::getThread()->getLogger()->log(level,
|
||||||
NULL, bp::extract<const char *>(top[0]),
|
NULL, bp::extract<const char *>(top[0]),
|
||||||
bp::extract<int>(top[1]), "%s(): %s",
|
bp::extract<int>(top[1]), "%s%s: %s",
|
||||||
(const char *) bp::extract<const char *>(top[2]),
|
module.c_str(), module[0] == '<' ? "" : "()",
|
||||||
msg.c_str());
|
msg.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppenderWrapper : public Appender, public bp::wrapper<Appender> {
|
class AppenderWrapper : public Appender {
|
||||||
public:
|
public:
|
||||||
AppenderWrapper(PyObject *self) : m_self(self) { }
|
AppenderWrapper(PyObject *self) : m_self(self) { Py_INCREF(m_self); }
|
||||||
|
|
||||||
void append(ELogLevel level, const std::string &text) {
|
void append(ELogLevel level, const std::string &text) {
|
||||||
get_override("append")(level, text);
|
bp::call_method<void>(m_self, "append", level, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void logProgress(Float progress, const std::string &name,
|
void logProgress(Float progress, const std::string &name,
|
||||||
const std::string &formatted, const std::string &eta,
|
const std::string &formatted, const std::string &eta,
|
||||||
const void *ptr) {
|
const void *ptr) {
|
||||||
get_override("logProgress")(progress, name, formatted, eta);
|
bp::call_method<void>(m_self, "logProgress", name, formatted, eta);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~AppenderWrapper() {
|
||||||
|
Py_DECREF(m_self);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
PyObject *m_self;
|
PyObject *m_self;
|
||||||
|
@ -221,6 +226,7 @@ void export_core() {
|
||||||
bp::class_<Object, ref<Object>, boost::noncopyable>("Object", bp::no_init)
|
bp::class_<Object, ref<Object>, boost::noncopyable>("Object", bp::no_init)
|
||||||
.def("getRefCount", &Object::getRefCount)
|
.def("getRefCount", &Object::getRefCount)
|
||||||
.def("__str__", &Object::toString);
|
.def("__str__", &Object::toString);
|
||||||
|
bp::register_ptr_to_python<Object*>();
|
||||||
|
|
||||||
BP_CLASS(Stream, Object, bp::no_init)
|
BP_CLASS(Stream, Object, bp::no_init)
|
||||||
.def("setByteOrder", &Stream::setByteOrder)
|
.def("setByteOrder", &Stream::setByteOrder)
|
||||||
|
@ -341,13 +347,14 @@ void export_core() {
|
||||||
.def("getErrorLevel", &Logger::getErrorLevel)
|
.def("getErrorLevel", &Logger::getErrorLevel)
|
||||||
.def("addAppender", &Logger::addAppender)
|
.def("addAppender", &Logger::addAppender)
|
||||||
.def("removeAppender", &Logger::removeAppender)
|
.def("removeAppender", &Logger::removeAppender)
|
||||||
|
.def("clearAppenders", &Logger::clearAppenders)
|
||||||
.def("getAppenderCount", &Logger::getAppenderCount)
|
.def("getAppenderCount", &Logger::getAppenderCount)
|
||||||
.def("getAppender", logger_get_appender, BP_RETURN_VALUE)
|
.def("getAppender", logger_get_appender, BP_RETURN_VALUE)
|
||||||
.def("getWarningCount", &Logger::getWarningCount);
|
.def("getWarningCount", &Logger::getWarningCount);
|
||||||
|
|
||||||
BP_CLASS(InstanceManager, Object, bp::init<>())
|
BP_CLASS(InstanceManager, Object, bp::init<>())
|
||||||
.def("serialize", &InstanceManager::serialize)
|
.def("serialize", &InstanceManager::serialize)
|
||||||
.def("getInstance", &instance_manager_getinstance);
|
.def("getInstance", &instance_manager_getinstance, BP_RETURN_VALUE);
|
||||||
|
|
||||||
bp::class_<ContinuousSpectrum, boost::noncopyable>("ContinuousSpectrum", bp::no_init)
|
bp::class_<ContinuousSpectrum, boost::noncopyable>("ContinuousSpectrum", bp::no_init)
|
||||||
.def("eval", &ContinuousSpectrum::eval)
|
.def("eval", &ContinuousSpectrum::eval)
|
||||||
|
@ -550,6 +557,27 @@ void export_core() {
|
||||||
BP_IMPLEMENT_POINT_OPS(Point3, Float, 3);
|
BP_IMPLEMENT_POINT_OPS(Point3, Float, 3);
|
||||||
BP_IMPLEMENT_POINT_OPS(Point4, Float, 3);
|
BP_IMPLEMENT_POINT_OPS(Point4, Float, 3);
|
||||||
|
|
||||||
|
Float (*dot2)(const Vector2 &, const Vector2 &) = ˙
|
||||||
|
Float (*dot3)(const Vector3 &, const Vector3 &) = ˙
|
||||||
|
Float (*dot4)(const Vector4 &, const Vector4 &) = ˙
|
||||||
|
Float (*absDot2)(const Vector2 &, const Vector2 &) = &absDot;
|
||||||
|
Float (*absDot3)(const Vector3 &, const Vector3 &) = &absDot;
|
||||||
|
Float (*absDot4)(const Vector4 &, const Vector4 &) = &absDot;
|
||||||
|
Vector2 (*normalize2)(const Vector2 &) = &normalize;
|
||||||
|
Vector3 (*normalize3)(const Vector3 &) = &normalize;
|
||||||
|
Vector4 (*normalize4)(const Vector4 &) = &normalize;
|
||||||
|
Vector3 (*cross3)(const Vector3 &, const Vector3 &) = ✗
|
||||||
|
bp::def("dot", dot2);
|
||||||
|
bp::def("dot", dot3);
|
||||||
|
bp::def("dot", dot4);
|
||||||
|
bp::def("absDot", absDot2);
|
||||||
|
bp::def("absDot", absDot3);
|
||||||
|
bp::def("absDot", absDot4);
|
||||||
|
bp::def("normalize", normalize2);
|
||||||
|
bp::def("normalize", normalize3);
|
||||||
|
bp::def("normalize", normalize4);
|
||||||
|
bp::def("cross", cross3);
|
||||||
|
|
||||||
bp::scope().attr("Vector") = bp::scope().attr("Vector3");
|
bp::scope().attr("Vector") = bp::scope().attr("Vector3");
|
||||||
bp::scope().attr("Point") = bp::scope().attr("Point3");
|
bp::scope().attr("Point") = bp::scope().attr("Point3");
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#define BP_WRAPPED_CLASS(Name, Wrapper, Base, Init) \
|
#define BP_WRAPPED_CLASS(Name, Wrapper, Base, Init) \
|
||||||
bp::class_<Name, ref<Wrapper>, bp::bases<Base>, boost::noncopyable> Name ##_class(#Name, Init); \
|
bp::class_<Name, ref<Wrapper>, bp::bases<Base>, boost::noncopyable> Name ##_class(#Name, Init); \
|
||||||
bp::register_ptr_to_python<Name*>(); \
|
bp::register_ptr_to_python<Name*>(); \
|
||||||
|
bp::implicitly_convertible<ref<Wrapper>, ref<Name> >(); \
|
||||||
Name ##_class
|
Name ##_class
|
||||||
|
|
||||||
#define BP_IMPLEMENT_VECTOR_OPS(Name, Scalar, Size) \
|
#define BP_IMPLEMENT_VECTOR_OPS(Name, Scalar, Size) \
|
||||||
|
|
Loading…
Reference in New Issue