Path.h

Go to the documentation of this file.
00001 /**<!-------------------------------------------------------------------->
00002    @class  Path
00003    @author Travis Fischer (fisch0920@gmail.com)
00004    @author Matthew Jacobs (jacobs.mh@gmail.com)
00005    @date   Fall 2008
00006    
00007    @brief
00008       Core data structure for manipulating a sequence x0,x1,...,xk of points on 
00009    scene surfaces. Paths are the central unit in the path integral formulation
00010    of light transport, upon which path tracing, bidirectional path tracing, and
00011    MLT are all founded.
00012    
00013    Each Path is assumed to either start at an emitter (light subpath), end at a 
00014    sensor (eye subpath), or both start at an emitter and end at a sensor 
00015    (complete, valid path).
00016    <!-------------------------------------------------------------------->**/
00017 
00018 #ifndef PATH_H_
00019 #define PATH_H_
00020 
00021 #include <renderers/utils/PathVertex.h>
00022 
00023 class Renderer;
00024 
00025 class Path {
00026    public:
00027       ///@name Constructors
00028       //@{-----------------------------------------------------------------
00029       
00030       inline   Path(const PathVertexList &vertices, Renderer *renderer)
00031          : m_vertices(vertices), m_renderer(renderer)
00032       { }
00033       
00034       inline   Path(Renderer *renderer)
00035          : m_renderer(renderer)
00036       { }
00037       
00038       
00039       //@}-----------------------------------------------------------------
00040       ///@name Functionality related to path as a whole
00041       //@{-----------------------------------------------------------------
00042       
00043       /**
00044        * @returns the luminance propagated along this path in the direction 
00045        *    of lightflow (beginning with an emitter)
00046        */
00047       inline real_t   getContribution() const {
00048          return getRadiance().getRGB().luminance();
00049       }
00050       
00051       /**
00052        * @returns the radiance propagated along this path in the direction 
00053        *    of lightflow (beginning with an emitter)
00054        */
00055       inline SpectralSampleSet getRadiance() const {
00056          if (length() > 0)
00057             return back().alphaL;
00058          
00059          return SpectralSampleSet::black(); 
00060       }
00061       
00062       /**
00063        * @returns the unweighted contribution of this path broken up into 
00064        *    a light subpath prefix of length @p s and an eye subpath suffix 
00065        *    of length @p t
00066        * 
00067        * @note this method contains an implicit visibility check between the 
00068        *    connecting edge which will not be performed if (s + t) is equal 
00069        *    to the length of this path (since this path is already assumed 
00070        *    to be 'valid', visibility is therefore guaranteed in this case)
00071        * @note if @p tentative is true, the aforementioned visibility check 
00072        *    will not be evaluated (visibility is assumed)
00073        * @note either this light subpath or the given eye subpath may be 
00074        *    empty, but not both (an empty path is considered invalid), 
00075        *    which implies that (s + t) >= 2
00076        * 
00077        * @see section 10.2 (pgs 302-305) of Veach's thesis for more details
00078        */
00079       SpectralSampleSet getContribution(unsigned s, unsigned t, 
00080                                         bool tentative = false);
00081       
00082       real_t getPdf(unsigned s, unsigned t, bool tentative = false);
00083       
00084       /**
00085        * @returns an array of @p k + 1 probability densities in @p pdfs, 
00086        *    corresponding to all of the @p k + 1 ways in which this path with
00087        *    @p k vertices could be broken up into different length light and 
00088        *    eye subpaths
00089        * 
00090        * @param k denotes the path length of interest (k <= the length of this
00091        *    path)
00092        * @param actualS denotes the length of the actual light path which this 
00093        *    path was generated from (actualS <= the length of this path)
00094        * @param pdfs is an out-array which is assumed to be preallocated to 
00095        *    hold at least @p k + 1 real_ts
00096        * 
00097        * @note probability densities are with respect to a surface area measure
00098        *    on the space of all paths
00099        * 
00100        * @see section 10.2 (pgs 302-305) of Veach's thesis for more details
00101        */
00102       void getPdfs(unsigned k, unsigned actualS, real_t *pdfs);
00103       
00104       /**
00105        * @brief
00106        *    Draws an OpenGL preview of this path by rendering edges between 
00107        * adjacent vertices using a single GL_LINE_STRIP
00108        */
00109       void preview();
00110       
00111       
00112       //@}-----------------------------------------------------------------
00113       ///@name Path deletion operations
00114       //@{-----------------------------------------------------------------
00115       
00116       /**
00117        * @brief
00118        *    Clears this Path of all vertices, resulting in an empty path
00119        */
00120       inline void clear() {
00121          m_vertices.clear();
00122       }
00123       
00124       /**
00125        * @returns a copy of the path formed by the left n + 1 vertices of the 
00126        *    form: x0,x1,...,xn
00127        * @note @p n is inclusive here
00128        */
00129       inline Path left(unsigned n) {
00130          return Path(PathVertexList(m_vertices.begin(), m_vertices.begin() + n),
00131                      m_renderer);
00132       }
00133       
00134       /**
00135        * @returns a copy of the path formed by the right-most vertices 
00136        *    starting at the nth vertex of the form: x(n),x(n+1),...,xk
00137        * @note @p n is inclusive here
00138        */
00139       inline Path right(unsigned n) {
00140          return Path(PathVertexList(m_vertices.begin() + n, m_vertices.end()),
00141                      m_renderer);
00142       }
00143       
00144       /**
00145        * @brief
00146        *    Removes the back vertex (last light vertex) in this Path
00147        */
00148       inline void pop_back() {
00149          ASSERT(length() > 0);
00150          m_vertices.pop_back();
00151       }
00152       
00153       /**
00154        * @brief
00155        *    Removes the front vertex (last eye vertex) in this Path
00156        */
00157       inline void pop_front() {
00158          ASSERT(length() > 0);
00159          m_vertices.pop_front();
00160       }
00161       
00162       
00163       //@}-----------------------------------------------------------------
00164       ///@name Path addition operations
00165       //@{-----------------------------------------------------------------
00166       
00167       /**
00168        * @brief
00169        *    Samples the BSDF at the end of this light path, and attempts to 
00170        * add a new PathVertex corresponding to the first surface intersected 
00171        * in the sampled direction, updating all internal data as necessary.
00172        * 
00173        * @param roulette denotes whether or not to apply standard russian 
00174        *    roulette to the decision of whether or not to add a vertex
00175        * 
00176        * @returns whether or not a vertex was successfully added
00177        * @note may return false if no surface was found in the sampled direction
00178        *    or if @p roulette is true and the random walk is terminated via 
00179        *    russian roulette
00180        */
00181       bool append(bool roulette = false);
00182       
00183       /**
00184        * @brief
00185        *    Samples the BSDF at the end of this eye path, and attempts to 
00186        * add a new PathVertex corresponding to the first surface intersected 
00187        * in the sampled direction, updating all internal data as necessary.
00188        * 
00189        * @param roulette denotes whether or not to apply standard russian 
00190        *    roulette to the decision of whether or not to add a vertex
00191        * 
00192        * @returns whether or not a vertex was successfully added
00193        * @note may return false if no surface was found in the sampled direction
00194        *    or if @p roulette is true and the random walk is terminated via 
00195        *    russian roulette
00196        */
00197       bool prepend(bool roulette = false);
00198       
00199       /**
00200        * @brief
00201        *    Adds the given PathVertex at the end of this eye path
00202        * 
00203        * @note only valid if the current path is empty, and 'v1' is assumed 
00204        *    to be on a sensor
00205        * @returns true if the point was successfully added or false if the 
00206        *    operation would invalidate this path
00207        */
00208       bool prepend(const PathVertex &v1);
00209       
00210       /**
00211        * @brief
00212        *    Appends the given eye subpath onto this light subpath, updating 
00213        * both the cumulative eye and light contributions along the way
00214        * 
00215        * @note either there are no restrictions or edge cases with respect 
00216        *    to path lengths; either or both paths may be empty
00217        * @returns true if the resulting path is valid, false otherwise (the 
00218        *    resulting path will be invalid -- zero contribution -- if the 
00219        *    last light subpath vertex first eye subpath vertex are not 
00220        *    mutually visible)
00221        */
00222       bool append (const Path &path);
00223       
00224       
00225       //@}-----------------------------------------------------------------
00226       ///@name PathVertex accessors
00227       //@{-----------------------------------------------------------------
00228       
00229       inline PathVertex &operator[](unsigned index) {
00230          ASSERT(index < length());
00231          
00232          return m_vertices[index];
00233       }
00234       
00235       inline const PathVertex &operator[](unsigned index) const {
00236          ASSERT(index < length());
00237          
00238          return m_vertices[index];
00239       }
00240       
00241       inline PathVertex &front() {
00242          ASSERT(length() > 0);
00243          
00244          return m_vertices[0];
00245       }
00246       
00247       inline const PathVertex &front() const {
00248          ASSERT(length() > 0);
00249          
00250          return m_vertices[0];
00251       }
00252 
00253       inline PathVertex &back() {
00254          ASSERT(length() > 0);
00255          
00256          return m_vertices[length() - 1];
00257       }
00258       
00259       inline const PathVertex &back() const {
00260          ASSERT(length() > 0);
00261          
00262          return m_vertices[length() - 1];
00263       }
00264       
00265       
00266       //@}-----------------------------------------------------------------
00267       ///@name Size accessors
00268       //@{-----------------------------------------------------------------
00269       
00270       inline unsigned length() const {
00271          return m_vertices.size();
00272       }
00273       
00274       inline unsigned getNoVertices() const {
00275          return m_vertices.size();
00276       }
00277       
00278       inline unsigned getNoEdges() const {
00279          const unsigned noVertices = getNoVertices();
00280          
00281          return (noVertices < 2 ? 0 : noVertices - 1);
00282       }
00283       
00284       
00285       //@}-----------------------------------------------------------------
00286       ///@name Miscellaneous functionality
00287       //@{-----------------------------------------------------------------
00288       
00289       inline Renderer *getRenderer() {
00290          return m_renderer;
00291       }
00292       
00293       inline void setRenderer(Renderer *renderer) {
00294          m_renderer = renderer;
00295       }
00296       
00297       std::string toHeckbertNotation() const;
00298       
00299       
00300       //@}-----------------------------------------------------------------
00301       
00302    protected:
00303       /**
00304        * @brief
00305        *    Samples the BSDF at the end of the path (which end is determined 
00306        * implicitly by the adjoint parameter), and attempts to add a new 
00307        * PathVertex corresponding to the first surface intersected in the 
00308        * sampled direction, updating all internal data as necessary.
00309        * 
00310        * @param roulette denotes whether or not to apply standard russian 
00311        *    roulette to the decision of whether or not to add a vertex
00312        * 
00313        * @returns whether or not a vertex was successfully added
00314        * @note may return false if no surface was found in the sampled direction
00315        *    or if @p roulette is true and the random walk is terminated via 
00316        *    russian roulette
00317        */
00318       bool _samplePathVertex(bool roulette, bool adjoint);
00319       
00320       /**
00321        * @brief
00322        *    Initializes light-path vertex @p y with respect to the point given
00323        * 
00324        * @param roulette denotes whether or not to apply standard russian 
00325        *    roulette to the decision of whether or not to add a vertex
00326        * 
00327        * @note @p y and @p pt are assumed to be mutually visible to each other
00328        * @returns the updated cumulative light subpath contribution (@p alphaL)
00329        *    and the updated cumulative light subpath probability density (@p pL)
00330        *    and whether or not to add the vertex (if russian roulette is 
00331        *    disabled or succeeded)
00332        */
00333       bool _initL(PathVertex &y, const Vector3 &wo, real_t t, SurfacePoint *pt, 
00334                   SpectralSampleSet &alphaL, real_t &pL, bool roulette = false) const;
00335       
00336       /**
00337        * @brief
00338        *    Initializes eye-path vertex @p z with respect to the point given
00339        * 
00340        * @param roulette denotes whether or not to apply standard russian 
00341        *    roulette to the decision of whether or not to add a vertex
00342        * 
00343        * @note @p z and @p pt are assumed to be mutually visible to each other
00344        * @returns the updated cumulative eye subpath contribution (@p alphaE)
00345        *    and the updated cumulative eye subpath probability density (@p pE)
00346        *    and whether or not to add the vertex (if russian roulette is 
00347        *    disabled or succeeded)
00348        */
00349       bool _initE(PathVertex &z, const Vector3 &wo, real_t t, SurfacePoint *pt, 
00350                   SpectralSampleSet &alphaE, real_t &pE, bool roulette = false) const;
00351       
00352    protected:
00353       PathVertexList m_vertices;
00354       Renderer      *m_renderer;
00355 };
00356 
00357 /// Prints a Path to an output stream
00358 std::ostream &operator<<(std::ostream &os, const Path &path);
00359 
00360 #endif // PATH_H_
00361 

Generated on 28 Feb 2009 for Milton by doxygen 1.5.6