documentation for the sphere shape
parent
ae962dccac
commit
0d203940a1
|
@ -336,7 +336,7 @@
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
<xsd:complexType name="blackbody">
|
<xsd:complexType name="blackbody">
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||||
<xsd:attribute name="temperature" type="doubleType" use="required"/>
|
<xsd:attribute name="temperature" type="xsd:string" use="required"/>
|
||||||
<xsd:attribute name="multiplier" type="doubleType" use="optional"/>
|
<xsd:attribute name="multiplier" type="doubleType" use="optional"/>
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
</xsd:schema>
|
</xsd:schema>
|
||||||
|
|
|
@ -148,6 +148,11 @@
|
||||||
</xsl:copy>
|
</xsl:copy>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
|
<!-- Update the parameters of the sphere plugin -->
|
||||||
|
<xsl:template match="shape[@type='sphere']/boolean[@name='inverted']/@name">
|
||||||
|
<xsl:attribute name="name">flipNormals</xsl:attribute>
|
||||||
|
</xsl:template>
|
||||||
|
|
||||||
<!-- Update the name of the lambertian plugin -->
|
<!-- Update the name of the lambertian plugin -->
|
||||||
<xsl:template match="bsdf[@type='lambertian']/@type">
|
<xsl:template match="bsdf[@type='lambertian']/@type">
|
||||||
<xsl:attribute name="type">diffuse</xsl:attribute>
|
<xsl:attribute name="type">diffuse</xsl:attribute>
|
||||||
|
|
|
@ -211,7 +211,7 @@ are allowed. Here is an example:
|
||||||
|
|
||||||
Finally, it is also possible to specify the spectral distribution of a black body emitter, where the temperature is given in Kelvin.
|
Finally, it is also possible to specify the spectral distribution of a black body emitter, where the temperature is given in Kelvin.
|
||||||
\begin{xml}
|
\begin{xml}
|
||||||
<blackbody name="spectrumProperty" temperature="5000"/>
|
<blackbody name="spectrumProperty" temperature="5000K"/>
|
||||||
\end{xml}
|
\end{xml}
|
||||||
Note that attaching a black body spectrum to the \texttt{intensity} property
|
Note that attaching a black body spectrum to the \texttt{intensity} property
|
||||||
of a luminaire introduces physical units into the rendering process of
|
of a luminaire introduces physical units into the rendering process of
|
||||||
|
@ -230,7 +230,7 @@ If these units are inconsistent with your scene, you may use the
|
||||||
optional \texttt{multiplier} attribute:
|
optional \texttt{multiplier} attribute:
|
||||||
\begin{xml}
|
\begin{xml}
|
||||||
<!-- Oops, the scene is modeled in centimeters, not meters -->
|
<!-- Oops, the scene is modeled in centimeters, not meters -->
|
||||||
<blackbody name="spectrumProperty" temperature="5000" multiplier="0.01"/>
|
<blackbody name="spectrumProperty" temperature="5000K" multiplier="0.01"/>
|
||||||
\end{xml}
|
\end{xml}
|
||||||
|
|
||||||
\subsubsection{Vectors, Positions}
|
\subsubsection{Vectors, Positions}
|
||||||
|
|
|
@ -57,6 +57,8 @@ def traverse(target, dirname, files):
|
||||||
os.chdir(os.path.dirname(__file__))
|
os.chdir(os.path.dirname(__file__))
|
||||||
f = open('plugins_generated.tex', 'w')
|
f = open('plugins_generated.tex', 'w')
|
||||||
f.write('\section{Plugin reference}\n')
|
f.write('\section{Plugin reference}\n')
|
||||||
|
f.write('\input{section_shapes}\n')
|
||||||
|
os.path.walk('../src/shapes', traverse, f)
|
||||||
f.write('\input{section_bsdf}\n')
|
f.write('\input{section_bsdf}\n')
|
||||||
os.path.walk('../src/bsdfs', traverse, f)
|
os.path.walk('../src/bsdfs', traverse, f)
|
||||||
f.write('\input{section_phase}\n')
|
f.write('\input{section_phase}\n')
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 76 KiB |
Binary file not shown.
After Width: | Height: | Size: 98 KiB |
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
Binary file not shown.
After Width: | Height: | Size: 96 KiB |
20
doc/main.bib
20
doc/main.bib
|
@ -206,10 +206,18 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@inproceedings{Jensen2001Practical,
|
@inproceedings{Jensen2001Practical,
|
||||||
title={A practical model for subsurface light transport},
|
title={A practical model for subsurface light transport},
|
||||||
author={Jensen, H.W. and Marschner, S.R. and Levoy, M. and Hanrahan, P.},
|
author={Jensen, H.W. and Marschner, S.R. and Levoy, M. and Hanrahan, P.},
|
||||||
booktitle={Proceedings of the 28th annual conference on Computer graphics and interactive techniques},
|
booktitle={Proceedings of the 28th annual conference on Computer graphics and interactive techniques},
|
||||||
pages={511--518},
|
pages={511--518},
|
||||||
year={2001},
|
year={2001},
|
||||||
organization={ACM}
|
organization={ACM}
|
||||||
|
}
|
||||||
|
@inproceedings{Shirley91Direct,
|
||||||
|
author = {Peter Shirley and Changyaw Wang},
|
||||||
|
title = {Direct Lighting Calculation by Monte Carlo Integration},
|
||||||
|
booktitle = {In proceedings of the second EUROGRAPHICS workshop on rendering},
|
||||||
|
year = {1991},
|
||||||
|
pages = {54--59},
|
||||||
|
publisher = {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
\newpage
|
||||||
\subsection{Surface scattering models}
|
\subsection{Surface scattering models}
|
||||||
\begin{figure}[h!]
|
\begin{figure}[h!]
|
||||||
\centering
|
\centering
|
||||||
|
|
|
@ -293,8 +293,9 @@ void Scene::initialize() {
|
||||||
if (!m_luminairePDF.isReady()) {
|
if (!m_luminairePDF.isReady()) {
|
||||||
if (m_luminaires.size() == 0) {
|
if (m_luminaires.size() == 0) {
|
||||||
Log(EWarn, "No luminaires found -- adding a sky luminaire");
|
Log(EWarn, "No luminaires found -- adding a sky luminaire");
|
||||||
Properties skyProps("sky");
|
Properties skyProps("sunsky");
|
||||||
skyProps.setFloat("intensityScale", 0.1f);
|
skyProps.setFloat("skyScale", 0.1f);
|
||||||
|
skyProps.setFloat("sunScale", 0.1f);
|
||||||
skyProps.setBoolean("extend", true);
|
skyProps.setBoolean("extend", true);
|
||||||
ref<Luminaire> luminaire = static_cast<Luminaire *>(
|
ref<Luminaire> luminaire = static_cast<Luminaire *>(
|
||||||
PluginManager::getInstance()->createObject(MTS_CLASS(Luminaire), skyProps));
|
PluginManager::getInstance()->createObject(MTS_CLASS(Luminaire), skyProps));
|
||||||
|
|
|
@ -398,11 +398,14 @@ void SceneHandler::endElement(const XMLCh* const xmlName) {
|
||||||
context.parent->properties.setSpectrum(context.attributes["name"],
|
context.parent->properties.setSpectrum(context.attributes["name"],
|
||||||
specValue);
|
specValue);
|
||||||
} else if (name == "blackbody") {
|
} else if (name == "blackbody") {
|
||||||
Float temperature = parseFloat(name, context.attributes["temperature"]);
|
std::string temperature = trim(context.attributes["temperature"]);
|
||||||
|
if (temperature.length() > 0 && std::toupper(temperature[temperature.length()-1] == 'K'))
|
||||||
|
temperature = temperature.substr(0, temperature.length()-1);
|
||||||
|
Float temperatureValue = parseFloat(name, temperature);
|
||||||
Float multiplier = 1;
|
Float multiplier = 1;
|
||||||
if (context.attributes.find("multiplier") != context.attributes.end())
|
if (context.attributes.find("multiplier") != context.attributes.end())
|
||||||
multiplier = parseFloat(name, context.attributes["multiplier"]);
|
multiplier = parseFloat(name, context.attributes["multiplier"]);
|
||||||
BlackBodySpectrum bb(temperature);
|
BlackBodySpectrum bb(temperatureValue);
|
||||||
Spectrum discrete;
|
Spectrum discrete;
|
||||||
discrete.fromContinuousSpectrum(bb);
|
discrete.fromContinuousSpectrum(bb);
|
||||||
context.parent->properties.setSpectrum(context.attributes["name"], discrete * multiplier);
|
context.parent->properties.setSpectrum(context.attributes["name"], discrete * multiplier);
|
||||||
|
|
|
@ -25,35 +25,105 @@
|
||||||
|
|
||||||
MTS_NAMESPACE_BEGIN
|
MTS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
/**
|
/*!\plugin{sphere}{Sphere intersection primitive}
|
||||||
* Sphere primitive.
|
* \order{1}
|
||||||
|
* \parameters{
|
||||||
|
* \parameter{center}{\Point}{
|
||||||
|
* Center of the sphere in object-space \default{(0, 0, 0)}
|
||||||
|
* }
|
||||||
|
* \parameter{radius}{\Float}{
|
||||||
|
* Radius of the sphere in object-space units \default{1}
|
||||||
|
* }
|
||||||
|
* \parameter{toWorld}{\Transform}{
|
||||||
|
* Specifies an optional linear object-to-world transformation.
|
||||||
|
* Note that non-uniform scales are not permitted!
|
||||||
|
* \default{none (i.e. object space $=$ world space)}
|
||||||
|
* }
|
||||||
|
* \parameter{flipNormals}{\Boolean}{
|
||||||
|
* Is the sphere inverted, i.e. should the normal vectors
|
||||||
|
* be flipped? \default{\code{false}, i.e. the normals point outside}
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
|
||||||
|
* \renderings{
|
||||||
|
* \rendering{Basic example, see \lstref{sphere-basic}}
|
||||||
|
* {shape_sphere_basic}
|
||||||
|
* \rendering{A textured sphere with the default parameterization}
|
||||||
|
* {shape_sphere_parameterization}
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* This shape plugin describes a simple sphere intersection primitive. It should
|
||||||
|
* always be preferred over sphere approximations modeled using triangles.
|
||||||
|
*
|
||||||
|
* When using a sphere as the base object of an \pluginref{area} luminaire,
|
||||||
|
* Mitsuba will switch to a special sphere luminaire sampling strategy
|
||||||
|
* \cite{Shirley91Direct} that works much better than the default approach.
|
||||||
|
* The resulting variance reduction makes it preferable to model most light
|
||||||
|
* sources as sphere luminaires (\figref{spherelight}).
|
||||||
|
*
|
||||||
|
* \begin{xml}[caption={A sphere can either be configured using a linear
|
||||||
|
* \code{toWorld} transformation or the \code{center} and \code{radius} parameters (or both).
|
||||||
|
* The above two declarations are equivalent.}, label=lst:sphere-basic]
|
||||||
|
* <shape type="sphere">
|
||||||
|
* <transform name="toWorld">
|
||||||
|
* <scale value="2"/>
|
||||||
|
* <translate x="1" y="0" z="0"/>
|
||||||
|
* </transform>
|
||||||
|
* <bsdf type="diffuse"/>
|
||||||
|
* </shape>
|
||||||
|
*
|
||||||
|
* <shape type="sphere">
|
||||||
|
* <point name="center" x="1" y="0" z="0"/>
|
||||||
|
* <float name="radius" value="2"/>
|
||||||
|
* <bsdf type="diffuse"/>
|
||||||
|
* </shape>
|
||||||
|
* \end{xml}
|
||||||
|
*
|
||||||
|
* \renderings{
|
||||||
|
* \rendering{Spherical area light modeled using triangles}
|
||||||
|
* {shape_sphere_arealum_tri}
|
||||||
|
* \rendering{Spherical area light modeled using the \pluginref{sphere} plugin}
|
||||||
|
* {shape_sphere_arealum_analytic}
|
||||||
|
*
|
||||||
|
* \caption{
|
||||||
|
* \label{fig:spherelight}
|
||||||
|
* Area lights built from the combination of the \pluginref{area}
|
||||||
|
* and \pluginref{sphere} plugins produce renderings that have an
|
||||||
|
* overall lower variance.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* \begin{xml}[caption=Instantiation of a sphere luminaire]
|
||||||
|
* <shape type="sphere">
|
||||||
|
* <point name="center" x="0" y="1" z="0"/>
|
||||||
|
* <float name="radius" value="1"/>
|
||||||
|
|
||||||
|
* <luminaire type="area">
|
||||||
|
* <blackbody name="intensity" temperature="7000K"/>
|
||||||
|
* </luminaire>
|
||||||
|
* </shape>
|
||||||
|
* \end{xml}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Sphere : public Shape {
|
class Sphere : public Shape {
|
||||||
public:
|
public:
|
||||||
Sphere(const Properties &props) : Shape(props) {
|
Sphere(const Properties &props) : Shape(props) {
|
||||||
/**
|
m_objectToWorld =
|
||||||
* There are two ways of instantiating spheres: either,
|
Transform::translate(Vector(props.getPoint("center", Point(0.0f))));
|
||||||
* one can specify a linear transformation to from the
|
m_radius = props.getFloat("radius", 1.0f);
|
||||||
* unit sphere using the 'toWorld' parameter, or one
|
|
||||||
* can explicitly specify a radius and center.
|
if (props.hasProperty("toWorld")) {
|
||||||
*/
|
Transform objectToWorld = props.getTransform("toWorld");
|
||||||
if (props.hasProperty("toWorld") && (props.hasProperty("center") || props.hasProperty("radius"))) {
|
Float radius = objectToWorld(Vector(1,0,0)).length();
|
||||||
Log(EError, "Deprecation error: the format for specifying spheres has changed. Please either provide "
|
// Remove the scale from the object-to-world transform
|
||||||
"an object-to-world transformation (including scaling) or a radius and a center");
|
|
||||||
} else if (props.hasProperty("center") && props.hasProperty("radius")) {
|
|
||||||
m_objectToWorld =
|
m_objectToWorld =
|
||||||
Transform::translate(Vector(props.getPoint("center")));
|
objectToWorld
|
||||||
m_radius = props.getFloat("radius");
|
* Transform::scale(Vector(1/radius))
|
||||||
} else {
|
* m_objectToWorld;
|
||||||
Transform objectToWorld = props.getTransform("toWorld", Transform());
|
m_radius *= radius;
|
||||||
m_radius = objectToWorld(Vector(1,0,0)).length();
|
|
||||||
// Remove the scale from the object-to-world trasnsform
|
|
||||||
m_objectToWorld = objectToWorld * Transform::scale(Vector(1/m_radius));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Are the sphere normals pointing inwards? default: no
|
/// Are the sphere normals pointing inwards? default: no
|
||||||
m_inverted = props.getBoolean("inverted", false);
|
m_flipNormals = props.getBoolean("flipNormals", false);
|
||||||
m_center = m_objectToWorld(Point(0,0,0));
|
m_center = m_objectToWorld(Point(0,0,0));
|
||||||
m_worldToObject = m_objectToWorld.inverse();
|
m_worldToObject = m_objectToWorld.inverse();
|
||||||
m_invSurfaceArea = 1/(4*M_PI*m_radius*m_radius);
|
m_invSurfaceArea = 1/(4*M_PI*m_radius*m_radius);
|
||||||
|
@ -64,7 +134,7 @@ public:
|
||||||
m_objectToWorld = Transform(stream);
|
m_objectToWorld = Transform(stream);
|
||||||
m_radius = stream->readFloat();
|
m_radius = stream->readFloat();
|
||||||
m_center = Point(stream);
|
m_center = Point(stream);
|
||||||
m_inverted = stream->readBool();
|
m_flipNormals = stream->readBool();
|
||||||
m_worldToObject = m_objectToWorld.inverse();
|
m_worldToObject = m_objectToWorld.inverse();
|
||||||
m_invSurfaceArea = 1/(4*M_PI*m_radius*m_radius);
|
m_invSurfaceArea = 1/(4*M_PI*m_radius*m_radius);
|
||||||
}
|
}
|
||||||
|
@ -74,7 +144,7 @@ public:
|
||||||
m_objectToWorld.serialize(stream);
|
m_objectToWorld.serialize(stream);
|
||||||
stream->writeFloat(m_radius);
|
stream->writeFloat(m_radius);
|
||||||
m_center.serialize(stream);
|
m_center.serialize(stream);
|
||||||
stream->writeBool(m_inverted);
|
stream->writeBool(m_flipNormals);
|
||||||
}
|
}
|
||||||
|
|
||||||
AABB getAABB() const {
|
AABB getAABB() const {
|
||||||
|
@ -163,7 +233,7 @@ public:
|
||||||
coordinateSystem(its.geoFrame.n, its.geoFrame.s, its.geoFrame.t);
|
coordinateSystem(its.geoFrame.n, its.geoFrame.s, its.geoFrame.t);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_inverted)
|
if (m_flipNormals)
|
||||||
its.geoFrame.n *= -1;
|
its.geoFrame.n *= -1;
|
||||||
|
|
||||||
its.shFrame = its.geoFrame;
|
its.shFrame = its.geoFrame;
|
||||||
|
@ -351,7 +421,7 @@ private:
|
||||||
Point m_center;
|
Point m_center;
|
||||||
Float m_radius;
|
Float m_radius;
|
||||||
Float m_invSurfaceArea;
|
Float m_invSurfaceArea;
|
||||||
bool m_inverted;
|
bool m_flipNormals;
|
||||||
};
|
};
|
||||||
|
|
||||||
MTS_IMPLEMENT_CLASS_S(Sphere, false, Shape)
|
MTS_IMPLEMENT_CLASS_S(Sphere, false, Shape)
|
||||||
|
|
Loading…
Reference in New Issue