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
|
||||
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.
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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}
|
||||
|
||||
|
||||
|
|
|
@ -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(); }
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 &) = ˙
|
||||
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("Point") = bp::scope().attr("Point3");
|
||||
|
||||
|
|
|
@ -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) \
|
||||
|
|
Loading…
Reference in New Issue