mitsuba/include/mitsuba/bidir/edge.h

432 lines
16 KiB
C++

/*
This file is part of Mitsuba, a physically based rendering system.
Copyright (c) 2007-2012 by Wenzel Jakob and others.
Mitsuba is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License Version 3
as published by the Free Software Foundation.
Mitsuba is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#if !defined(__MITSUBA_BIDIR_EDGE_H_)
#define __MITSUBA_BIDIR_EDGE_H_
#include <mitsuba/bidir/common.h>
MTS_NAMESPACE_BEGIN
/**
* \brief Bidirectional path edge data structure
*
* The path edge data structure is responsible for representing the transport of
* light between pairs of scattering or emission events.
* Amongst other things, it keeps track of the medium that fills the space between
* adjacent vertices of a \ref Path. Furthermore, it can be used to evaluate and
* sample the visibility and transmittance functions of the scene.
*
* Although they do not correspond to any real transport, this implementation
* also places edges next to "supernode" vertices (see \ref PathVertex for a
* description), which simplifies the implementations of various rendering
* algorithms that make use of this framework.
*
* \sa PathVertex
*
* \author Wenzel Jakob
* \ingroup libbidir
*/
struct MTS_EXPORT_BIDIR PathEdge {
/* ==================================================================== */
//! @{ \name Enumerations and Fields
/* ==================================================================== */
/// Pointer to the medium that contains this edge (where \c NULL is vacuum)
const Medium *medium;
/**
* \brief Normalized direction vector associated with this edge
*/
Vector d;
/**
* \brief Length of this edge in world-space distance units
*
* Note that edges adjacent to supernodes have length zero to
* mark them as such.
*/
Float length;
/**
* \brief Measurement contribution weight
*
* This field stores the terms of the path-space measurement contribution
* function that are coupled to this specific edge divided by the
* associated density function.
*
* More specifically, it stores the transmittance of the medium across
* this edge divided by the density per unit length of the adjacent
* vertices int the radiance and importance transport directions (hence,
* it is an array with two entries).
*
* Note that this field only accounts for medium-related terms. The
* interactions with vertices are captured by \ref PathVertex::weight.
*/
Spectrum weight[ETransportModes];
/**
* \brief Medium sampling density of the adjacent vertices
*
* This field stores the probability of sampling the preceding and
* successive path vertices using the sampling technique implemented by
* the function \ref PathEdge::sampleNext(). Depending on whether or not
* they are medium interactions, this eintries either store a density per
* unit length or a discrete probability.
*/
Float pdf[ETransportModes];
//! @}
/* ==================================================================== */
/* ==================================================================== */
//! @{ \name Sampling-related functions
/* ==================================================================== */
/**
* \brief Given a ray \c ray, sample a distance in this direction and
* fill the edge data structure, as well as its target vertex with content.
*
* \param scene
* Pointer to the underlying scene
* \param sampler
* Pointer to a sample generator
* \param pred
* Pointer to the preceding vertex
* \param ray
* Specifies the direction and origin associated with one
* endpoint of the edge. The sampling routine will then determine
* the other endpoint.
* \param succ
* Pointer to an unused vertex data structure, which will be filled
* with information about the successor vertex
* \param mode
* Specifies whether radiance or importance is being transported
* \return \c true on success
*/
bool sampleNext(const Scene *scene, Sampler *sampler,
const PathVertex *pred, const Ray &ray, PathVertex *next,
ETransportMode mode);
/**
* \brief Create a perturbed successor vertex and edge
*
* This function behaves similar to \ref sampleNext() in that it
* generates a successor edge and vertex.
*
* The main difference is that the desired direction, distance, and
* type of the successor vertex are all specified, which makes the
* sampling process completely deterministic. This is useful for
* implementing path-space perturbation strategies.
*
* \param scene
* Pointer to the underlying scene
* \param pred
* Pointer to the preceding vertex
* \param ray
* Specifies the direction and origin associated with one
* endpoint of the edge. The sampling routine will then determine
* the other endpoint.
* \param dist
* Specifies the desired distance between the current vertex and \c succ
* (this only applies when <tt>desiredType=EMediumInteraction</tt>)
* \param desiredType
* Specifies the desired vertex type of \c succ.
* \param succ
* Pointer to an unused vertex data structure, which will be filled
* with information about the successor vertex
* \param mode
* Specifies whether radiance or importance is being transported
* \return \c true on success
*/
bool perturbDirection(const Scene *scene, const PathVertex *pred,
const Ray &ray, Float dist, PathVertex::EVertexType desiredType,
PathVertex *next, ETransportMode mode);
//! @}
/* ==================================================================== */
/* ==================================================================== */
//! @{ \name Query functions
/* ==================================================================== */
enum ECachedValues {
EValueImp = 0x01,
EValueRad = 0x02,
ECosineImp = 0x04,
ECosineRad = 0x08,
EValue = EValueImp | EValueRad,
ECosine = ECosineImp | ECosineRad,
EValueCosineImp = EValueImp | ECosineImp,
EValueCosineRad = EValueRad | ECosineRad,
EInverseSquareFalloff = 0x10,
ETransmittance = 0x20,
EGeometricTerm = ECosine | EInverseSquareFalloff,
EGeneralizedGeometricTerm = EGeometricTerm | ETransmittance,
EEverything = EValue | EGeneralizedGeometricTerm
};
/**
* \brief Evaluate cached quantities associated with this edge
*
* This function computes the product of certain terms that are cached
* in this edge and its adjacent vertices. The \c what parameter specifies
* the terms to be included; it must be a combination of the flags
* in the enumeration \ref ECachedValues.
*
* \remark This function assumes that \c pred and \c succ are the
* vertices associated with this edge, and that they have not been
* modified since the edge was created.
*
* \param pred
* The predecessor vertex of this edge
* \param succ
* The successor vertex of this edge
*/
Spectrum evalCached(const PathVertex *pred, const PathVertex *succ,
unsigned int what) const;
/**
* \brief Compute the density of a successor node
*
* This function computes the hypothetical transport-related sampling density
* of a given successor node conditioned on a specified predecessor when
* using the sampling technique implemented by \ref sampleNext(). Depending
* on whether or not the successor node is a medium interaction, the returned
* value is either a density per unit length or a discrete probability.
*
* Note: this function only computes terms associated with the transport
* between vertices -- to account for the vertices themselves,
* refer to \ref PathEdge::evalPdf.
*
* \param scene
* Pointer to the underlying scene
* \param pred
* Pointer to the preceding vertex
* \param succ
* Pointer to the successor vertex
*
* \return The computed probability density
*/
Float evalPdf(const PathVertex *pred, const PathVertex *succ) const;
/**
* \brief Compute the transmittance between an arbitrary
* pair of vertices
*
* This function queries the medium associated with this edge for the
* transmittance between an arbitrary pair of nodes, \c pred and \c succ.
*
* \param pred
* Pointer to the preceding vertex
* \param succ
* Pointer to the successor vertex
*
* \return A spectrally varying transmittance value
*/
Spectrum evalTransmittance(const PathVertex *pred, const PathVertex *succ) const;
/**
* \brief Return the transmittance value associated with this edge
*
* \param pred
* Pointer to the preceding vertex
* \param succ
* Pointer to the successor vertex
*
* \return A spectrally varying transmittance value
*/
Spectrum evalTransmittance() const;
/**
* \brief Evaluate the one of the cosine factors associated with the geometric
* term over an edge
*/
Float evalCosine(const PathVertex *pred, const PathVertex *succ, const PathVertex *base) const;
//! @}
/* ==================================================================== */
/* ==================================================================== */
//! @{ \name Miscellaneous
/* ==================================================================== */
/**
* \brief Verify the cached values stored in this path vertex
* for consistency
*
* This function re-evaluates a series of quantities associated with
* this edge and compares them to locally cached values.
* If any mismatch is found, the function sends debug output to a
* specified output stream and returns \c false.
*
* \param scene
* Pointer to the underlying scene
* \param pred
* Pointer to the vertex adjacent in the emitter direction or \c NULL
* \param succ
* Pointer to the vertex adjacent in the sensor direction or \c NULL
* \param mode
* Transport mode -- disambiguates the meaning of \c pred and \c succ.
* \param os
* Target output stream for error messages
*/
bool verify(const Scene *scene, const PathVertex *adjL,
const PathVertex *adjE, ETransportMode mode, std::ostream &os) const;
/**
* \brief Create a connection edge between two vertices
*
* This function can be used to create an edge data structure
* when connecting two separately sampled path vertices. This
* involves checking that they are mutually visible and computing
* the attenuation caused by the medium in between (if any).
*
* \param scene
* Pointer to the underlying scene
* \param predEdge
* Pointer to an edge between \c vs and its predecessor
* (which is not needed by this function)
* \param vs
* First path vertex to be connected.
* \param vt
* Second path vertex to be connected.
* \param succEdge
* Pointer to an edge between \c vt and its successor
* (which is not needed by this function)
* \return \c true upon success, \c false when there is no
* throughput or an inconsistency has been detected.
*/
bool connect(const Scene *scene, const PathEdge *predEdge,
const PathVertex *vs, const PathVertex *vt,
const PathEdge *succEdge);
/**
* \brief Create a connection path between two vertices
*
* This function is conceptually similar to \ref connect().
* However, instead of a single edge, it potentially generates
* an entire connection path, where intermediate vertices are
* either index-matched medium transitions or other surface
* scattering events of type \ref BSDF::ENull.
*
* This is important to support efficient direct illumination sampling
* through such surfaces (e.g. a heterogeneous medium or a leaf with
* textured alpha transparency).
*
* \param scene
* Pointer to the underlying scene
* \param predEdge
* Pointer to an edge between \c vs and its predecessor
* (which is not needed by this function)
* \param vs
* First path vertex to be connected.
* \param result
* A path data structure that will be filled with the
* created vertices and edges
* \param vt
* Second path vertex to be connected.
* \param succEdge
* Pointer to an edge between \c vt and its successor
* (which is not needed by this function)
* \param maxInteractions
* Specifies the maximum permissible number of intermediate
* vertices (-1 == arbitrarily many)
* \param pool
* Reference to memory pool that will be used to allocate
* edges and vertices.
* \return \c true upon success, \c false when there is no
* throughput or an inconsistency has been detected.
*/
static bool pathConnect(const Scene *scene, const PathEdge *predEdge,
const PathVertex *vs, Path &result, const PathVertex *vt,
const PathEdge *succEdge, int maxInteractions, MemoryPool &pool);
/**
* \brief Create a connection path between two vertices and
* collapse it into a single edge that summarizes its properties
*
* This function can be thought of as being half-way in between
* \c connect() and \c pathConnect(). Like \c pathConnect(), it
* potentially generates an entire connection path between the
* specified endpoints, where intermediate vertices are
* either index-matched medium transitions or other surface
* scattering events of type \ref BSDF::ENull.
*
* This is important to support efficient direct illumination sampling
* through such surfaces (e.g. a heterogeneous medium or a leaf with
* textured alpha transparency).
*
* However, this variant does not return the intermediate vertices
* and edges -- instead, everything is collapsed into a single
* edge that captures the aggregate weight and probability densities.
*
* This function is used by bidirectional path tracing, since it creates
* connections through index-matched boundaries but does not require
* explicit knowledge about the associated path vertices.
*
* \param scene
* Pointer to the underlying scene
* \param predEdge
* Pointer to an edge between \c vs and its predecessor
* (which is not needed by this function)
* \param vs
* First path vertex to be connected.
* \param vt
* Second path vertex to be connected.
* \param succEdge
* Pointer to an edge between \c vt and its successor
* (which is not needed by this function)
* \param interactions
* Specifies the maximum permissible number of index-matched medium
* transitions or \ref BSDF::ENull scattering events on the way
* to the light source. (<tt>interactions<0</tt> means arbitrarily many).
* When the function is successful, this parameter will
* additionally be used to return the actual number of intermediate
* interactions.
* \return \c true upon success, \c false when there is no
* throughput or an inconsistency has been detected.
*/
bool pathConnectAndCollapse(const Scene *scene, const PathEdge *predEdge,
const PathVertex *vs, const PathVertex *vt,
const PathEdge *succEdge, int &interactions);
/// Create a deep copy of this edge
PathEdge *clone(MemoryPool &pool) const;
/// Compare this edge against another edge
bool operator==(const PathEdge &edge) const;
/// Compare this edge against another edge
inline bool operator!=(const PathEdge &edge) const {
return !operator==(edge);
}
/// Return a string representation of the information stored in this vertex
std::string toString() const;
//! @}
/* ==================================================================== */
};
MTS_NAMESPACE_END
#endif /* __MITSUBA_BIDIR_EDGE_H_ */