made annotations more consistent
parent
568baf1c89
commit
a5bbad3ace
|
@ -27,6 +27,7 @@
|
|||
\usepackage{ifthen}
|
||||
\usepackage{longtable}
|
||||
\usepackage{wrapfig}
|
||||
\usepackage{footnote} % savenotes environment
|
||||
|
||||
% Make sure that ligatures remain searchable in the PDF
|
||||
\input glyphtounicode
|
||||
|
|
|
@ -58,7 +58,7 @@ extern MTS_EXPORT_CORE std::string formatString(const char *pFmt, ...);
|
|||
extern MTS_EXPORT_CORE std::string timeString(Float time, bool precise = false);
|
||||
|
||||
/// Turn a memory size into a human-readable string
|
||||
extern MTS_EXPORT_CORE std::string memString(size_t size);
|
||||
extern MTS_EXPORT_CORE std::string memString(size_t size, bool precise = false);
|
||||
|
||||
/// Return a string representation of a list of objects
|
||||
template<class Iterator> std::string containerToString(const Iterator &start, const Iterator &end) {
|
||||
|
|
|
@ -45,7 +45,6 @@ using std::endl;
|
|||
#include <mitsuba/core/constants.h>
|
||||
#include <mitsuba/core/fwd.h>
|
||||
#include <mitsuba/render/fwd.h>
|
||||
#include <mitsuba/core/stl.h>
|
||||
#include <mitsuba/core/math.h>
|
||||
#include <mitsuba/core/object.h>
|
||||
#include <mitsuba/core/ref.h>
|
||||
|
|
|
@ -75,48 +75,68 @@ void annotate(const Scene *scene, const Properties &properties,
|
|||
if (!(strt = strchr((char *) value.c_str(), '$')))
|
||||
break;
|
||||
|
||||
if (strncasecmp(strt, "$rendertime", 11) == 0) {
|
||||
value.replace(strt-value.c_str(), 11, timeString(renderTime));
|
||||
} else if (strncasecmp(strt, "$memusage", 11) == 0) {
|
||||
value.replace(strt-value.c_str(), 11, memString(getPrivateMemoryUsage()));
|
||||
} else {
|
||||
char *par1, *par2;
|
||||
if (!(par1 = strchr(strt, '[')))
|
||||
break;
|
||||
if (!(par2 = strchr(par1, ']')))
|
||||
break;
|
||||
char *par1, *par2;
|
||||
if (!(par1 = strchr(strt, '[')))
|
||||
break;
|
||||
if (!(par2 = strchr(par1, ']')))
|
||||
break;
|
||||
|
||||
std::string propSource = value.substr(strt-value.c_str()+1, par1-strt-1);
|
||||
std::string propKey = value.substr(par1-value.c_str()+1, par2-par1-1);
|
||||
propSource.erase(std::remove_if(propSource.begin(), propSource.end(), ::isspace), propSource.end());
|
||||
propKey.erase(std::remove_if(propKey.begin(), propKey.end(), ::isspace), propKey.end());
|
||||
std::string propSource = value.substr(strt-value.c_str()+1, par1-strt-1);
|
||||
std::string propKey = value.substr(par1-value.c_str()+1, par2-par1-1);
|
||||
propSource.erase(std::remove_if(propSource.begin(), propSource.end(), ::isspace), propSource.end());
|
||||
propKey.erase(std::remove_if(propKey.begin(), propKey.end(), ::isspace), propKey.end());
|
||||
|
||||
if (!boost::starts_with(propKey, "'") || !boost::ends_with(propKey, "'"))
|
||||
SLog(EError, "Encountered invalid key '%s'", propKey.c_str());
|
||||
if (!boost::starts_with(propKey, "'") || !boost::ends_with(propKey, "'"))
|
||||
SLog(EError, "Encountered invalid key '%s'", propKey.c_str());
|
||||
|
||||
propKey = propKey.substr(1, propKey.length()-2);
|
||||
propKey = propKey.substr(1, propKey.length()-2);
|
||||
|
||||
const ConfigurableObject *source = NULL;
|
||||
if (propSource == "film")
|
||||
source = scene->getFilm();
|
||||
else if (propSource == "sampler")
|
||||
source = scene->getSampler();
|
||||
else if (propSource == "sensor")
|
||||
source = scene->getSensor();
|
||||
else if (propSource == "integrator")
|
||||
source = scene->getIntegrator();
|
||||
else
|
||||
SLog(EError, "Unknown data source '%s' (must be film/sampler/sensor/integrator)", propSource.c_str());
|
||||
const ConfigurableObject *source = NULL;
|
||||
if (propSource == "scene")
|
||||
source = scene;
|
||||
else if (propSource == "film")
|
||||
source = scene->getFilm();
|
||||
else if (propSource == "sampler")
|
||||
source = scene->getSampler();
|
||||
else if (propSource == "sensor")
|
||||
source = scene->getSensor();
|
||||
else if (propSource == "integrator")
|
||||
source = scene->getIntegrator();
|
||||
else
|
||||
SLog(EError, "Unknown data source '%s' (must be film/sampler/sensor/integrator)", propSource.c_str());
|
||||
|
||||
std::string replacement;
|
||||
std::string replacement;
|
||||
|
||||
if (source == scene) {
|
||||
if (propKey == "renderTime") {
|
||||
replacement = timeString(renderTime);
|
||||
} else if (propKey == "renderTimePrecise") {
|
||||
replacement = timeString(renderTime, true);
|
||||
} else if (propKey == "memUsage") {
|
||||
replacement = memString(getPrivateMemoryUsage());
|
||||
} else if (propKey == "memUsagePrecise") {
|
||||
replacement = memString(getPrivateMemoryUsage(), true);
|
||||
} else if (propKey == "coreCount") {
|
||||
replacement = formatString("%i", Scheduler::getInstance()->getCoreCount());
|
||||
} else if (propKey == "blockSize") {
|
||||
replacement = formatString("%i", scene->getBlockSize());
|
||||
} else if (propKey == "sourceFile") {
|
||||
replacement = scene->getSourceFile().string();
|
||||
} else if (propKey == "destFile") {
|
||||
replacement = scene->getDestinationFile().string();
|
||||
}
|
||||
}
|
||||
|
||||
if (replacement.empty()) {
|
||||
if (propKey == "type")
|
||||
replacement = source->getProperties().getPluginName();
|
||||
else
|
||||
replacement = source->getProperties().getAsString(propKey);
|
||||
|
||||
value.replace(strt-value.c_str(), par2-strt+1, replacement);
|
||||
}
|
||||
|
||||
value.replace(strt-value.c_str(), par2-strt+1, replacement);
|
||||
}
|
||||
|
||||
if (labelAnnotation) {
|
||||
Vector2i size = font->getSize(value);
|
||||
bitmap->fillRect(offset-Vector2i(4, 4), size + Vector2i(8, 8), Spectrum(0.0f));
|
||||
|
|
|
@ -117,33 +117,64 @@ MTS_NAMESPACE_BEGIN
|
|||
* </film>
|
||||
* \end{xml}
|
||||
*
|
||||
* \subsubsection*{Annotations:}
|
||||
* \subsubsection*{Render-time annotations:}
|
||||
* \label{sec:film-annotations}
|
||||
* The \pluginref{ldrfilm} and \pluginref{hdrfilm} plugins support an additional
|
||||
* feature referred to as \emph{annotations}, which can be quite useful under
|
||||
* certain circumstances.
|
||||
*
|
||||
* The \pluginref{ldrfilm} and \pluginref{hdrfilm} plugins support a
|
||||
* feature referred to as \emph{render-time annotations} to facilitate
|
||||
* record keeping.
|
||||
* Annotations are used to embed useful information inside a rendered image so
|
||||
* that this information is later available to anyone viewing the image.
|
||||
* Exemplary uses of this feature might be to store the frame or take number,
|
||||
* camera parameters, or other relevant scene information.
|
||||
*
|
||||
* Annotations can either be created by means of a \emph{tag}, which is an entry
|
||||
* in the metadata table of the image file (does not modify the actual image data),
|
||||
* or a \emph{text} label which is ``burned'' into the image.
|
||||
* rendering time, memory usage, camera parameters, or other relevant scene
|
||||
* information.
|
||||
*
|
||||
* Currently, two different types are supported: a \code{metadata} annotation
|
||||
* creates an entry in the metadata table of the image, which is preferable
|
||||
* when the image contents should not be touched. Alternatively, a \code{label}
|
||||
* annotation creates a line of text that is overlaid on top of the image. Note
|
||||
* that this is only visible when opening the output file (i.e. the line is not
|
||||
* shown in the interactive viewer).
|
||||
* The syntax of this looks as follows:
|
||||
*
|
||||
* \begin{xml}
|
||||
* <film type="ldrfilm">
|
||||
* <!-- Create a new metadata entry 'my_tag_name' and set it to the value 'my_tag_value' -->
|
||||
* <string name="tag('my_tag_name')" value="my_tag_value"/>
|
||||
* <film type="hdrfilm">
|
||||
* <!-- Create a new metadata entry 'my_tag_name' and set it to the
|
||||
* value 'my_tag_value' -->
|
||||
* <string name="metadata['key_name']" value="Hello!"/>
|
||||
*
|
||||
* <!-- Add the label 'Hello' at the image position X=50, Y=80 -->
|
||||
* <string name="text(50,80)" value="Hello!"/>
|
||||
* <string name="label[50, 80]" value="Hello!"/>
|
||||
* </film>
|
||||
* \end{xml}
|
||||
*
|
||||
* The \code{value="..."} argument may also include certain identifiers that will be
|
||||
* evaluated and substituted when the rendered image is written to disk. These include
|
||||
* \begin{center}
|
||||
* \begin{savenotes}
|
||||
* \begin{tabular}{ll}
|
||||
* \toprule
|
||||
* \code{\$scene['renderTime']}& Render time of the image, \code{renderTimePrecise} for more digits.\\
|
||||
* \code{\$scene['memUsage']}& Mitsuba memory usage\footnote{The definition of this quantity unfortunately
|
||||
* varies a bit from platform to platform. On Linux and Windows, it denotes the total
|
||||
* amount of allocated RAM and disk-based memory that is private to the process (i.e. not
|
||||
* shared or shareable), which most intuitively captures the amount of memory required for
|
||||
* rendering. On OSX, it denotes the working set size---roughly speaking, this is the
|
||||
* amount of RAM apportioned to the process (i.e. excluding disk-based memory).}.
|
||||
* Use \code{memUsagePrecise} for more digits.\\
|
||||
* \code{\$scene['coreCount']}& Number of local and remote cores working on the rendering job\\
|
||||
* \code{\$scene['blockSize']}& Block size used to parallelize up the rendering workload\\
|
||||
* \code{\$scene['sourceFile']}& Source file name\\
|
||||
* \code{\$scene['destFile']}& Destination file name\\
|
||||
* \code{\$integrator['..']}& Copy a named integrator parameter\\
|
||||
* \code{\$sensor['..']}& Copy a named sensor parameter\\
|
||||
* \code{\$sampler['..']}& Copy a named sampler parameter\\
|
||||
* \code{\$film['..']}& Copy a named film parameter\\
|
||||
* \bottomrule
|
||||
* \end{tabular}
|
||||
* \end{savenotes}
|
||||
* \end{center}
|
||||
*/
|
||||
|
||||
class HDRFilm : public Film {
|
||||
public:
|
||||
HDRFilm(const Properties &props) : Film(props) {
|
||||
|
|
|
@ -123,19 +123,6 @@ std::string indent(const std::string &string, int amount) {
|
|||
return oss.str();
|
||||
}
|
||||
|
||||
std::string memString(size_t size) {
|
||||
Float value = (Float) size;
|
||||
const char *prefixes[] = {
|
||||
"B", "KiB", "MiB", "GiB", "TiB", "PiB"
|
||||
};
|
||||
int prefix = 0;
|
||||
while (prefix < 5 && value > 1024.0f) {
|
||||
value /= 1024.0f; ++prefix;
|
||||
}
|
||||
return formatString(prefix == 0 ?
|
||||
"%.0f %s" : "%.2f %s", value, prefixes[prefix]);
|
||||
}
|
||||
|
||||
void * __restrict allocAligned(size_t size) {
|
||||
#if defined(__WINDOWS__)
|
||||
return _aligned_malloc(size, L1_CACHE_LINE_SIZE);
|
||||
|
@ -809,8 +796,6 @@ Float fresnelDiffuseReflectance(Float eta, bool fast) {
|
|||
}
|
||||
|
||||
std::string timeString(Float time, bool precise) {
|
||||
std::ostringstream os;
|
||||
|
||||
if (std::isnan(time) || std::isinf(time))
|
||||
return "inf";
|
||||
|
||||
|
@ -825,12 +810,31 @@ std::string timeString(Float time, bool precise) {
|
|||
}
|
||||
}
|
||||
|
||||
std::ostringstream os;
|
||||
os << std::setprecision(precise ? 4 : 1)
|
||||
<< std::fixed << time << suffix;
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string memString(size_t size, bool precise) {
|
||||
Float value = (Float) size;
|
||||
const char *suffixes[] = {
|
||||
"B", "KiB", "MiB", "GiB", "TiB", "PiB"
|
||||
};
|
||||
int suffix = 0;
|
||||
while (suffix < 5 && value > 1024.0f) {
|
||||
value /= 1024.0f; ++suffix;
|
||||
}
|
||||
|
||||
std::ostringstream os;
|
||||
os << std::setprecision(suffix == 0 ? 0 : (precise ? 4 : 1))
|
||||
<< std::fixed << value << suffixes[suffix];
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
Float hypot2(Float a, Float b) {
|
||||
Float r;
|
||||
if (std::abs(a) > std::abs(b)) {
|
||||
|
|
|
@ -37,7 +37,7 @@ MTS_NAMESPACE_BEGIN
|
|||
* A visualization of a fractal surface by Irving and Segerman.
|
||||
* (a 2D Gospel curve developed up to level 5 along the third
|
||||
* dimension). This scene makes use of instancing to replicate
|
||||
* similar structures to cheaply render a structure that effectively
|
||||
* similar structures to cheaply render a shape that effectively
|
||||
* consists of several hundred millions of triangles.
|
||||
* }
|
||||
* }
|
||||
|
|
Loading…
Reference in New Issue