documentation & python binding improvements

metadata
Wenzel Jakob 2011-08-19 03:13:18 -04:00
parent a3896c0f89
commit 139d0d5073
8 changed files with 103 additions and 26 deletions

View File

@ -1,12 +1,30 @@
\section{Development Guide}
\part{Development guide}
This chapter and the subsequent ones will provide an overview
of the the coding conventions and general architecture of Mitsuba.
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
section is only relevant if you plan to submit patches, which should
go into the main codebase.
section is only relevant if you plan to submit patches that are meant
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,
which expand to \emph{four} spaces. Please make sure that you configure your editor
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
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.
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.
The only way they can be deallocated is using the built-in reference
counting. This is done using the \code{ref<>} template, e.g.

View File

@ -1,9 +1,9 @@
\section{Introduction}
\part{Using Mitsuba}
\textbf{Disclaimer:} This is manual documents the usage, file format, and
internal design of the Mitsuba rendering system. It is currently a work
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
(\url{www.pbrt.org}), from which it derives much inspiration.
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
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
Public License (Version 3) as provided by the Free Software Foundation.

View File

@ -155,7 +155,7 @@
\include{format}
\IfFileExists{plugins_generated.tex}{\include{plugins_generated}}{}
%\include{import}
%\include{development}
\include{development}
%\include{integrator}
%\include{parallelization}
\include{python}

View File

@ -2,15 +2,15 @@
\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 tasks. To access the API, start your Python
interpreter and run
used for simple automation purposes. To access the API, start your Python
interpreter and enter
\begin{python}
import mitsuba
\end{python}
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 must update the extension
search path before the \code{import} command is issued:
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:
\begin{python}
import sys
@ -20,4 +20,23 @@ sys.path.append('dist/python')
import mitsuba
\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}

View File

@ -152,6 +152,9 @@ public:
/// Remove an appender from this logger
void removeAppender(Appender *appender);
/// Remove all appenders from this logger
void clearAppenders();
/// Return the number of registered appenders
inline size_t getAppenderCount() const { return m_appenders.size(); }

View File

@ -33,7 +33,7 @@ Logger::Logger(ELogLevel level)
}
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();
}
@ -99,7 +99,7 @@ void Logger::log(ELogLevel level, const Class *theClass,
m_mutex->lock();
if (level >= EWarn)
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_mutex->unlock();
} else {
@ -141,7 +141,7 @@ void Logger::log(ELogLevel level, const Class *theClass,
void Logger::logProgress(Float progress, const std::string &name,
const std::string &formatted, const std::string &eta, const void *ptr) {
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(
progress, name, formatted, eta, ptr);
m_mutex->unlock();
@ -162,6 +162,14 @@ void Logger::removeAppender(Appender *appender) {
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() {
Logger *logger = new Logger(EInfo);
ref<Appender> appender = new StreamAppender(&std::cout);

View File

@ -159,25 +159,30 @@ void mts_log(ELogLevel level, const std::string &msg) {
bp::object extract_stack(traceback.attr("extract_stack"));
bp::object stack = extract_stack();
bp::object top(stack[bp::len(stack)-1]);
std::string module = bp::extract<std::string>(top[2]);
Thread::getThread()->getLogger()->log(level,
NULL, bp::extract<const char *>(top[0]),
bp::extract<int>(top[1]), "%s(): %s",
(const char *) bp::extract<const char *>(top[2]),
bp::extract<int>(top[1]), "%s%s: %s",
module.c_str(), module[0] == '<' ? "" : "()",
msg.c_str());
}
class AppenderWrapper : public Appender, public bp::wrapper<Appender> {
class AppenderWrapper : public Appender {
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) {
get_override("append")(level, text);
bp::call_method<void>(m_self, "append", level, text);
}
void logProgress(Float progress, const std::string &name,
const std::string &formatted, const std::string &eta,
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:
PyObject *m_self;
@ -221,7 +226,8 @@ void export_core() {
bp::class_<Object, ref<Object>, boost::noncopyable>("Object", bp::no_init)
.def("getRefCount", &Object::getRefCount)
.def("__str__", &Object::toString);
bp::register_ptr_to_python<Object*>();
BP_CLASS(Stream, Object, bp::no_init)
.def("setByteOrder", &Stream::setByteOrder)
.def("getByteOrder", &Stream::getByteOrder)
@ -341,13 +347,14 @@ void export_core() {
.def("getErrorLevel", &Logger::getErrorLevel)
.def("addAppender", &Logger::addAppender)
.def("removeAppender", &Logger::removeAppender)
.def("clearAppenders", &Logger::clearAppenders)
.def("getAppenderCount", &Logger::getAppenderCount)
.def("getAppender", logger_get_appender, BP_RETURN_VALUE)
.def("getWarningCount", &Logger::getWarningCount);
BP_CLASS(InstanceManager, Object, bp::init<>())
.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)
.def("eval", &ContinuousSpectrum::eval)
@ -550,6 +557,27 @@ void export_core() {
BP_IMPLEMENT_POINT_OPS(Point3, Float, 3);
BP_IMPLEMENT_POINT_OPS(Point4, Float, 3);
Float (*dot2)(const Vector2 &, const Vector2 &) = &dot;
Float (*dot3)(const Vector3 &, const Vector3 &) = &dot;
Float (*dot4)(const Vector4 &, const Vector4 &) = &dot;
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 &) = &cross;
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("Point") = bp::scope().attr("Point3");

View File

@ -34,6 +34,7 @@
#define BP_WRAPPED_CLASS(Name, Wrapper, Base, Init) \
bp::class_<Name, ref<Wrapper>, bp::bases<Base>, boost::noncopyable> Name ##_class(#Name, Init); \
bp::register_ptr_to_python<Name*>(); \
bp::implicitly_convertible<ref<Wrapper>, ref<Name> >(); \
Name ##_class
#define BP_IMPLEMENT_VECTOR_OPS(Name, Scalar, Size) \