diff --git a/doc/gendoc.py b/doc/gendoc.py index 8e10a5c7..27a2b49e 100755 --- a/doc/gendoc.py +++ b/doc/gendoc.py @@ -69,6 +69,8 @@ f.write('\input{section_media}\n') os.path.walk('../src/medium', traverse, f) f.write('\input{section_phase}\n') os.path.walk('../src/phase', traverse, f) +f.write('\input{section_volumes}\n') +os.path.walk('../src/volume', traverse, f) f.write('\input{section_luminaires}\n') os.path.walk('../src/luminaires', traverse, f) f.write('\input{section_integrators}\n') diff --git a/doc/main.tex b/doc/main.tex index 673d7eec..5f9d3684 100644 --- a/doc/main.tex +++ b/doc/main.tex @@ -109,7 +109,7 @@ string,transform,ref,rgb,srgb,spectrum,blackbody, medium,camera,film,sampler,integrator,luminaire, translate,rotate,scale,lookAt,point,vector,matrix, - include,fscat + include,fscat,volume }, } diff --git a/doc/section_volumes.tex b/doc/section_volumes.tex new file mode 100644 index 00000000..e1763e65 --- /dev/null +++ b/doc/section_volumes.tex @@ -0,0 +1,7 @@ +\newpage +\subsection{Volume data sources} +\label{sec:volumes} +This section covers the different types of volume data sources included with +Mitsuba. These plugins are intended to be used together with the +\pluginref{heterogeneous} medium plugin and provide three-dimensional spatially varying +density, albedo, and orientation fields. diff --git a/src/medium/heterogeneous.cpp b/src/medium/heterogeneous.cpp index 1546cda4..f704713d 100644 --- a/src/medium/heterogeneous.cpp +++ b/src/medium/heterogeneous.cpp @@ -86,10 +86,10 @@ static StatsCounter earlyExits("Heterogeneous volume", * } * } * - * This plugin provides a flexible hheterogeneous medium implementation, which + * This plugin provides a flexible heterogeneous medium implementation, which * acquires its data from nested \code{volume} instances. These can be * constant, use a procedural function, or fetch data from disk, e.g. using a - * memory-mapped density grid. + * memory-mapped density grid. See \secref{volumes} for details. * * Instead of allowing separate volumes to be provided for the scattering * absorption parameters \code{sigmaS} and \code{sigmaA} (as is done in diff --git a/src/volume/constvolume.cpp b/src/volume/constvolume.cpp index 842d027e..f72e0f88 100644 --- a/src/volume/constvolume.cpp +++ b/src/volume/constvolume.cpp @@ -21,6 +21,29 @@ MTS_NAMESPACE_BEGIN +/*!\plugin{constvolume}{Constant-valued volume data source} + * \parameters{ + * \parameter{value}{\Float\Or\Spectrum\Or\Vector}{ + * Specifies the value of the volume + * } + * } + * + * This plugin provides a volume data source that is + * constant throughout its domain. Depending on how it is used, + * its value can either be a scalar, a color spectrum, + * or a 3D vector. + * + * \begin{xml}[caption={Definition of a heterogeneous medium with constant albedo}] + * + * + * + * + * + * + * + * \end{xml} + */ class ConstantDataSource : public VolumeDataSource { public: ConstantDataSource(const Properties &props) diff --git a/src/volume/gridvolume.cpp b/src/volume/gridvolume.cpp index b1356a9f..6c61b089 100644 --- a/src/volume/gridvolume.cpp +++ b/src/volume/gridvolume.cpp @@ -34,49 +34,69 @@ MTS_NAMESPACE_BEGIN -/** - * \brief This class implements access to volume data stored on a +/*!\plugin{gridvolume}{Grid-based volume data source} + * \parameters{ + * \parameter{filename}{\String}{ + * Specifies the filename of the volume data file to be loaded + * } + * \parameter{sendData}{\Boolean}{ + * When this parameter is set to \code{true}, the implementation will + * send all volume data to other network render nodes. Otherwise, they + * are expected to have access to an identical volume data file that can be + * mapped into memory. \default{\code{false}} + * } + * \parameter{toWorld}{\Transform}{ + * Optional linear transformation that should be applied to the data + * } + * \parameter{min, max}{\Point}{ + * Optional parameter that can be used to re-scale the data so that + * it lies in the bounding box between \code{min} and \code{max}. + * } + * } + * + * This class implements access to memory-mapped volume data stored on a * 3D grid using a simple binary exchange format. + * The format uses a little endian encoding and is specified as + * follows:\vspace{3mm} * - * The format uses a little endian encoding and is specified as follows: - * - * Bytes 1-3 : ASCII Bytes 'V', 'O', and 'L' - * Byte 4 : Version identifier (currently 3) - * Bytes 5-8 : Encoding identifier using a double word - * - * 1 => Dense float32-based representation - * - * 2 => Dense float16-based representation - * NOT YET SUPPORTED BY THIS IMPLEMENTATION - * - * 3 => Dense uint8-based representation - * The range 0..255 will be mapped to 0..1. - * - * 4 => Dense quantized directions - * The directions are stored in spherical coordinates, - * with a total storage cost of 16 bit per entry. - * - * Bytes 9-12 : Number of cells along the X axis (double word) - * Bytes 13-16 : Number of cells along the Y axis (double word) - * Bytes 17-20 : Number of cells along the Z axis (double word) - * Bytes 21-24 : Number of channels (double word, supported values: 1 or 3) - * Bytes 25-48 : Axis-aligned bounding box of the data stored in single - * precision (order: xmin, ymin, zmin, xmax, ymax, zmax) - * Bytes 49-* : Binary data of the volume stored in the specified encoding. + * \begin{center} + * \begin{tabular}{>{\bfseries}p{2cm}p{11cm}} + * \toprule + * Position & Content\\ + * \midrule + * Bytes 1-3& ASCII Bytes '\code{V}', '\code{O}', and '\code{L}' \\ + * Byte 4& File format version number (currently 3)\\ + * Bytes 5-8& Encoding identifier using a 32-bit integer + * \begin{enumerate}[(i)] + * \item Dense \code{float32}-based representation + * \item Dense \code{float16}-based representation (\emph{currently not supported by this implementation}) + * \item Dense \code{uint8}-based representation (The range 0..255 will be mapped to 0..1) + * \item Dense quantized directions. The directions are stored in spherical + * coordinates with a total storage cost of 16 bit per entry. + * \end{enumerate}\\ + * Bytes 9-12 & Number of cells along the X axis (32 bit integer)\\ + * Bytes 13-16 & Number of cells along the Y axis (32 bit integer)\\ + * Bytes 17-20 & Number of cells along the Z axis (32 bit integer)\\ + * Bytes 21-24 & Number of channels (32 bit integer, supported values: 1 or 3)\\ + * Bytes 25-48 & Axis-aligned bounding box of the data stored in single + * precision (order: xmin, ymin, zmin, xmax, ymax, zmax)\\ + * Bytes 49-* & Binary data of the volume stored in the specified encoding. * The data are ordered so that the following C-style indexing - * operation makes sense after the file has been mapped into memory: - * "data[((zpos*yres + ypos)*xres + xpos)*channels + chan]" - * where (xpos, ypos, zpos, chan) denotes the lookup location. + * operation makes sense after the file has been mapped into memory:\newline + * \ \ \code{data[((zpos*yres + ypos)*xres + xpos)*channels + chan]}\newline + * where \code{(xpos, ypos, zpos, chan)} denotes the lookup location.\\ + * + * \bottomrule + * \end{tabular} + * \end{center} * * Note that Mitsuba expects that entries in direction volumes are either * zero or valid unit vectors. * * When using this data source to represent floating point density volumes, * please ensure that the values are all normalized to lie in the - * range [0, 1] -- otherwise, the Woocock-Tracking integration method in - * heterogeneous.cpp will produce incorrect results. You can use - * the 'densityMultiplier' parameter of that class to re-scale the - * densities if neccessary. + * range $[0, 1]$---otherwise, the Woocock-Tracking integration method in + * \pluginref{heterogeneous} will produce incorrect results. */ class GridDataSource : public VolumeDataSource { public: diff --git a/src/volume/volcache.cpp b/src/volume/volcache.cpp index b85c6325..035caad9 100644 --- a/src/volume/volcache.cpp +++ b/src/volume/volcache.cpp @@ -43,10 +43,37 @@ struct Vector3iKeyOrder : public std::binary_function } }; -/** - * This class sits in between the renderer and another data source, for which - * it caches all data lookups using a LRU scheme. This is useful if the nested - * volume data source is expensive to evaluate. +/*!\plugin{volcache}{Caching volume data source} + * \parameters{ + * \parameter{blockSize}{\Integer}{ + * Size of the individual cache blocks + * \default{8, i.e. $8\times8\times 8$} + * } + * \parameter{voxelWidth}{\Float}{ + * Width of a voxel (in a cache block) expressed in + * world-space units. \default{automatic} + * } + * \parameter{memoryLimit}{\Integer}{ + * Max. allowed memory usage in MiB. \default{1024, i.e. 1 GiB} + * } + * \parameter{toWorld}{\Transform}{ + * Optional linear transformation that should be applied to the data + * } + * \parameter{\Unnamed}{\Volume}{ + * A nested volume data source + * } + * } + * + * This plugin can be added between the renderer and another + * data source, for which it caches all data lookups using a + * LRU scheme. This is useful when the nested volume data source + * is expensive to evaluate. + * + * The cache works by performing on-demand rasterization of subregions + * of the nested volume into blocks ($8\times 8 \times 8$ by default). + * These are kept in memory until a user-specifiable threshold is exeeded, + * after which point a \emph{least recently used} (LRU) policy removes + * records that haven't been accessed in a long time. */ class CachingDataSource : public VolumeDataSource { public: @@ -55,7 +82,7 @@ public: CachingDataSource(const Properties &props) : VolumeDataSource(props) { /// Size of an individual block (must be a power of 2) - m_blockSize = props.getInteger("blockSize", 4); + m_blockSize = props.getInteger("blockSize", 8); if (!isPowerOfTwo(m_blockSize)) Log(EError, "Block size must be a power of two!"); @@ -65,7 +92,7 @@ public: m_voxelWidth = props.getFloat("voxelWidth", -1); /* Permissible memory usage in MiB. Default: 1GiB */ - m_memoryLimit = (size_t) props.getLong("memoryLimit", 32) * 1024 * 1024; + m_memoryLimit = (size_t) props.getLong("memoryLimit", 1024) * 1024 * 1024; m_stepSizeMultiplier = (Float) props.getFloat("stepSizeMultiplier", 1.0f);