Mitsuba Renderer  0.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
path.h
Go to the documentation of this file.
1 /*
2  This file is part of Mitsuba, a physically based rendering system.
3 
4  Copyright (c) 2007-2014 by Wenzel Jakob and others.
5 
6  Mitsuba is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License Version 3
8  as published by the Free Software Foundation.
9 
10  Mitsuba is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #pragma once
20 #if !defined(__MITSUBA_BIDIR_PATH_H_)
21 #define __MITSUBA_BIDIR_PATH_H_
22 
23 #include <mitsuba/bidir/vertex.h>
24 #include <mitsuba/bidir/edge.h>
25 #include <mitsuba/bidir/mempool.h>
26 
28 
29 /**
30  * \brief Bidirectional path data structure
31  *
32  * In the path-space light transport framework, a path is represented as a
33  * linear sequence of interactions (expressed using vertices) and transport
34  * (expressed using edges).
35  *
36  * The \ref Path data structure is responsible for the storage of this
37  * information. It also contains useful utility functions, for instance
38  * to perform a random walk, or to splice and connect path segments.
39  *
40  * \sa PathVertex
41  * \sa PathEdge
42  *
43  * \author Wenzel Jakob
44  * \ingroup libbidir
45  */
47 public:
48  typedef PathEdge * PathEdgePtr;
50 
51  /* ==================================================================== */
52  //! @{ \name Path construction
53  /* ==================================================================== */
54 
55  /// Create a new, empty path
56  inline Path() { }
57 
58  /// Create a new path of the specified size
59  inline Path(size_t size) : m_vertices(size) { }
60 
61  /// Copy constructor
62  inline Path(const Path &path) : m_vertices(path.m_vertices),
63  m_edges(path.m_edges) { }
64 
65  /**
66  * \brief Initialize the path with an endpoint vertex
67  *
68  * This function clears the path and initializes it with a single
69  * endpoint vertex of the type implied by the \c mode parameter.
70  *
71  * \param scene
72  * Pointer to the underlying scene
73  * \param time
74  * Specifies the time value to be associated with the path.
75  * \param mode
76  * Specifies the desired endpoint type
77  * \param pool
78  * Reference to a memory pool that will be used to release
79  * and allocate edges and vertices.
80  */
81  void initialize(const Scene *scene, Float time,
82  ETransportMode mode, MemoryPool &pool);
83 
84  /**
85  * \brief Perform/continue a random walk starting from the current endpoint
86  *
87  * \param scene
88  * Pointer to the underlying scene
89  * \param sampler
90  * Pointer to a sample generator
91  * \param nSteps
92  * Desired number of random walk steps (<tt>-1</tt>=infinite)
93  * \param rrStart
94  * Depth to start using russian roulette
95  * (<tt>-1</tt>=never, <tt>0</tt>=starting at the first
96  * bounce, and so on)
97  * \param mode
98  * Denotes whether radiance or importance are being transported
99  * \param pool
100  * Reference to a memory pool that will be used to allocate
101  * edges and vertices.
102  * \return The number of successful steps performed by the random walk.
103  */
104  int randomWalk(const Scene *scene, Sampler *sampler,
105  int nSteps, int rrStart, ETransportMode mode,
106  MemoryPool &pool);
107 
108  /**
109  * \brief Perform a random walk starting at a specified
110  * pixel on the sensor
111  *
112  * \param scene
113  * Pointer to the underlying scene
114  * \param sampler
115  * Pointer to a sample generator
116  * \param nSteps
117  * Desired number of random walk steps (<tt>-1</tt>=infinite)
118  * \param pixelPosition
119  * Pixel position associated with the newly created
120  * sensor subpath
121  * \param rrStart
122  * Depth to start using russian roulette
123  * (<tt>-1</tt>=never, <tt>0</tt>=starting at the first
124  * bounce, and so on)
125  * \param pool
126  * Reference to a memory pool that will be used to allocate
127  * edges and vertices.
128  * \return The number of successful steps performed by the random walk.
129  */
130  int randomWalkFromPixel(const Scene *scene, Sampler *sampler,
131  int nSteps, const Point2i &pixelPosition, int rrStart,
132  MemoryPool &pool);
133 
134  /**
135  * \brief Perform two random walks on an emitter and sensor subpath
136  *
137  * This function is almost identical to calling \ref randomWalk() twice
138  * in sequence. The main difference is that it performs the random
139  * walk steps in a staggered order (i.e. one step on the emitter subpath,
140  * one step on the sensor subpath, and so on..), which is important for
141  * obtaining good results with QMC random number sequences.
142  * Additinally, it ensures that the sensor path passes through a specified
143  * pixel instead of sampling it uniformly.
144  *
145  * Used by bidirectional path tracing.
146  *
147  * \param scene
148  * Pointer to the underlying scene
149  * \param sampler
150  * Pointer to a sample generator
151  * \param emitterPath
152  * Reference to the emitter subpath to be filled
153  * \param nEmitterSteps
154  * Desired number of random walk steps on the emitter subpath
155  * (<tt>-1</tt>=infinite)
156  * \param sensorPath
157  * Reference to the sensor subpath to be filled
158  * \param nSensorSteps
159  * Desired number of random walk steps on the sensor subpath
160  * (<tt>-1</tt>=infinite)
161  * \param pixelPosition
162  * Pixel position associated with the newly created
163  * sensor subpath
164  * \param rrStart
165  * Depth to start using russian roulette
166  * (<tt>-1</tt>=never, <tt>0</tt>=starting at the first
167  * bounce, and so on)
168  * \param pool
169  * Reference to a memory pool that will be used to allocate
170  * edges and vertices.
171  * \return The number of successful steps performed by the random walk
172  * on the emitter and sensor subpath, respectively.
173  */
174  static std::pair<int, int> alternatingRandomWalkFromPixel(const Scene *scene,
175  Sampler *sampler, Path &emitterPath, int nEmitterSteps,
176  Path &sensorPath, int nSensorSteps, const Point2i &pixelPosition,
177  int rrStart, MemoryPool &pool);
178 
179  /**
180  * \brief Verify the cached values stored in this path
181  *
182  * This function re-evaluates a series of quantities associated with
183  * each vertex and edge and compares them to locally cached values.
184  * If any mismatch is found, the function sends debug output to a
185  * specified output stream and returns \c false.
186  *
187  * \param scene
188  * Pointer to the underlying scene
189  * \param mode
190  * Disambiguates the order of the vertices in this path
191  * \param os
192  * Target output stream for error messages
193  */
194  bool verify(const Scene *scene, ETransportMode mode, std::ostream &os) const;
195 
196  //! @}
197  /* ==================================================================== */
198 
199  /* ==================================================================== */
200  //! @{ \name Accessors
201  /* ==================================================================== */
202 
203  /**
204  * \brief Return the number of vertices stored in this path
205  *
206  * For a nonempty path, the number of vertices is always equal
207  * To \ref edgeCount()+1.
208  */
209  inline size_t vertexCount() const {
210  return m_vertices.size();
211  }
212 
213  /**
214  * \brief Return the number of edges stored in this path
215  *
216  * For a nonempty path, the number of vertices is always equal
217  * To \ref vertexCount()-1.
218  */
219  inline size_t edgeCount() const {
220  return m_edges.size();
221  }
222 
223  /**
224  * \brief Return the length of the path. This is just the
225  * number of edges.
226  */
227  inline int length() const {
228  return (int) m_edges.size();
229  }
230 
231  /// Return an vertex by its index
232  inline PathVertexPtr &vertex(size_t index) {
233  #if MTS_BD_DEBUG == 1
234  if (index >= m_vertices.size())
235  SLog(EError, "Path vertex index " SIZE_T_FMT
236  " is out of bounds, array size: " SIZE_T_FMT,
237  index, m_vertices.size());
238  #endif
239  return m_vertices[index];
240  }
241 
242  /// Return an vertex by its index (const version)
243  inline const PathVertexPtr &vertex(size_t index) const {
244  #if MTS_BD_DEBUG == 1
245  if (index >= m_vertices.size())
246  SLog(EError, "Path vertex index " SIZE_T_FMT
247  " is out of bounds, array size: " SIZE_T_FMT,
248  index, m_vertices.size());
249  #endif
250  return m_vertices[index];
251  }
252 
253  /// Return an vertex by its index (or NULL if out of bounds)
254  inline PathVertexPtr vertexOrNull(size_t index) {
255  if (index >= m_vertices.size())
256  return NULL;
257  return m_vertices[index];
258  }
259 
260  /// Return an vertex by its index (or NULL if out of bounds, const version)
261  inline PathVertexPtr vertexOrNull(size_t index) const {
262  if (index >= m_vertices.size())
263  return NULL;
264  return m_vertices[index];
265  }
266 
267  /// Return an edge by its index
268  inline PathEdgePtr &edge(size_t index) {
269  #if MTS_BD_DEBUG == 1
270  if (index >= m_edges.size())
271  SLog(EError, "Path edge index " SIZE_T_FMT
272  " is out of bounds, array size: " SIZE_T_FMT,
273  index, m_edges.size());
274  #endif
275  return m_edges[index];
276  }
277 
278  /// Return an edge by its index (const version)
279  inline const PathEdgePtr &edge(size_t index) const {
280  #if MTS_BD_DEBUG == 1
281  if (index >= m_edges.size())
282  SLog(EError, "Path edge index " SIZE_T_FMT
283  " is out of bounds, array size: " SIZE_T_FMT,
284  index, m_edges.size());
285  #endif
286  return m_edges[index];
287  }
288 
289  /// Return an edge by its index (or \c NULL if out of bounds)
290  inline PathEdgePtr edgeOrNull(size_t index) {
291  if (index >= m_edges.size())
292  return NULL;
293  return m_edges[index];
294  }
295 
296  /// Return an edge by its index (or \c NULL if out of bounds, const version)
297  inline PathEdgePtr edgeOrNull(size_t index) const {
298  if (index >= m_edges.size())
299  return NULL;
300  return m_edges[index];
301  }
302 
303 
304  //! @}
305  /* ==================================================================== */
306 
307  /* ==================================================================== */
308  //! @{ \name Miscellaneous
309  /* ==================================================================== */
310 
311  /**
312  * \brief Return the spectrally varying path weight that corresponds to
313  * a prefix of length \c l and a suffix of length \c m.
314  *
315  * This operation is used by path mutation strategies that operate
316  * by cutting out a pice of a path and replacing it with something else.
317  * In that case, it is necessary know about the effects of vertices
318  * and edges \a outside of the modified range.
319  */
320  inline Spectrum getPrefixSuffixWeight(int l, int m) const {
321  Spectrum weight(1.0f);
322 
323  for (int s=0; s<l; ++s)
324  weight *= m_vertices[s]->weight[EImportance]
325  * m_edges[s]->weight[EImportance];
326 
327  for (int t=length(); t>m; --t)
328  weight *= m_vertices[t]->weight[ERadiance]
329  * m_edges[t-1]->weight[ERadiance];
330 
331  return weight;
332  }
333 
334  /**
335  * \brief Determine whether another path of the same length
336  * matches the configuration of this path
337  *
338  * More specifically, this function verifies that the length matches,
339  * that all vertices are of the same type, and that the paths have
340  * identical values of \ref isConnectable() for each vertex.
341  */
342  inline bool matchesConfiguration(const Path &p) const {
343  if (p.length() != length())
344  return false;
345 
346  for (size_t i=0; i<m_vertices.size(); ++i) {
347  if (m_vertices[i]->type != p.vertex(i)->type ||
348  m_vertices[i]->isConnectable() != p.vertex(i)->isConnectable())
349  return false;
350  }
351 
352  return true;
353  }
354 
355  /**
356  * \brief Return the relative spectrally varying path weight associated
357  * with this path
358  *
359  * This function computes the product of all the importance weights
360  * (see the \ref weight field) along the path, and the result is
361  * normalized so that it has luminance 1. This quantity is required
362  * by the sample splatting implementation in Veach-MLT.
363  */
364  inline Spectrum getRelativeWeight() const {
365  Spectrum weight(1.0f);
366  int k = length();
367 
368  for (int s=0; s<k-1; ++s)
369  weight *= m_vertices[s]->weight[EImportance]
370  * m_edges[s]->weight[EImportance];
371 
372  weight = weight
373  * m_vertices[k]->weight[ERadiance]
374  * m_vertices[k-1]->weight[ERadiance]
375  * m_edges[k-1]->weight[ERadiance];
376 
377  Float lum = weight.getLuminance();
378  return lum != 0.0f ? (weight / lum) : Spectrum(0.0f);
379  }
380 
381  /**
382  * \brief Compute the multiple importance sampling weight of the <tt>(s,t)</tt>
383  * sampling strategy in BDPT.
384  *
385  * This implementation uses the power heuristic with exponent 2 and
386  * repeatedly evaluates equation (10.9) from Eric Veach's PhD thesis to
387  * compute the weight in an efficient and numerically stable manner.
388  *
389  * The function completely ignores the effects of russian roulette, since
390  * this allows for a more efficient implementation. The resulting estimator
391  * is still unbiased despite this apparent inaccuracy.
392  *
393  * \param scene
394  * Pointer to the underlying scene
395  * \param emitterSubpath
396  * Reference to the emitter subpath
397  * \param connectionEdge
398  * Pointer to an edge data structure associated with the
399  * transport between <tt>emitterSubpath[s]</tt> and
400  * <tt>sensorSubpath[t]</tt>.
401  * \param sensorSubpath
402  * Reference to the sensor subpath
403  * \param s
404  * Number of steps to take along the emitter subpath
405  * \param t
406  * Number of steps to take along the sensor subpath
407  * \param direct
408  * When the parameter \c direct is set to \c true, the implementation
409  * accounts for the fact that specialized direct sampling strategies
410  * are used for paths with <tt>s==1</tt> and <tt>t==1</tt>.
411  * \param lightImage
412  * Denotes whether or not rendering strategies that require a 'light image'
413  * (specifically, those with <tt>t==0</tt> or <tt>t==1</tt>) are included
414  * in the rendering process.
415  */
416  static Float miWeight(const Scene *scene,
417  const Path &emitterSubpath,
418  const PathEdge *connectionEdge,
419  const Path &sensorSubpath, int s, int t,
420  bool direct, bool lightImage);
421 
422  /**
423  * \brief Collapse a path into an entire edge that summarizes the aggregate
424  * transport and sampling densities
425  *
426  * This is only allowed when the path only consists of \ref BSDF::ENull
427  * surface scattering events (e.g. index-matched medium transitions)
428  */
429  void collapseTo(PathEdge &edge) const;
430 
431  /// Reverse a path
432  void reverse();
433 
434  /// Swap the two endpoint vertices of a path with the provided values
435  inline void swapEndpoints(PathVertexPtr &supernode, PathEdgePtr &edge, PathVertexPtr &sample) {
436  std::swap(supernode, m_vertices[0]);
437  std::swap(sample, m_vertices[1]);
438  std::swap(edge, m_edges[0]);
439  }
440 
441  /// \brief Append a vertex to this path
442  inline void append(PathVertex *vertex) { m_vertices.push_back(vertex); }
443 
444  /// \brief Append an edge to this path
445  inline void append(PathEdge *edge) { m_edges.push_back(edge); }
446 
447  /**
448  * \brief Append an edge and a vertex to this path
449  *
450  * \param edge
451  * And edge from <tt>vertex(vertexCount()-1)</tt> to \c vertex.
452  * \param vertex
453  * A vertex to be appended at the end of the path
454  */
455  inline void append(PathEdge *edge, PathVertex *vertex) {
456  m_edges.push_back(edge);
457  m_vertices.push_back(vertex);
458  }
459 
460  /// Append an entire path to this path
461  void append(const Path &path);
462 
463  /**
464  * \brief Append the vertex range <tt>[start, end)</tt> of \c path
465  * (and all intermediate edges) to the current path.
466  *
467  * \param path
468  * Source of vertices and edges to be added
469  * \param l
470  * Specifies the start of the range <tt>[start, end)</tt>.
471  * \param m
472  * Specifies the end of the range <tt>[start, end)</tt>.
473  * \param reverse
474  * Should the vertices and edges be added in \a reverse order?
475  */
476  void append(const Path &path, size_t start, size_t end, bool reverse = false);
477 
478  /// Clear the path and release all elements to the memory pool
479  void release(MemoryPool &pool);
480 
481  /// Release a certain subpath [start, end) to the memory pool
482  void release(size_t start, size_t end, MemoryPool &pool);
483 
484  /// Return the sample position associated with the path
485  inline const Point2 &getSamplePosition() const {
486  return m_vertices[length()-1]->getSamplePosition();
487  }
488 
489  /// Clear the path
490  inline void clear() {
491  m_vertices.clear();
492  m_edges.clear();
493  }
494 
495  /// Compare this path against another path
496  bool operator==(const Path &path) const;
497 
498  /// Compare this path against another path
499  inline bool operator!=(const Path &path) const {
500  return !operator==(path);
501  }
502 
503  /// Create a deep copy of this path
504  void clone(Path &target, MemoryPool &pool) const;
505 
506  /// Return a string representation of the path
507  std::string toString() const;
508 
509  /// Return a basic string summary of the path
510  std::string summarize() const;
511 
512  //! @}
513  /* ==================================================================== */
514 private:
515  std::vector<PathVertexPtr> m_vertices;
516  std::vector<PathEdgePtr> m_edges;
517 };
518 
520 
521 #endif /* __MITSUBA_BIDIR_PATH_H_ */
bool matchesConfiguration(const Path &p) const
Determine whether another path of the same length matches the configuration of this path...
Definition: path.h:342
#define MTS_EXPORT_BIDIR
Definition: platform.h:119
Bidirectional path vertex data structure.
Definition: vertex.h:48
const PathEdgePtr & edge(size_t index) const
Return an edge by its index (const version)
Definition: path.h:279
Spectrum getPrefixSuffixWeight(int l, int m) const
Return the spectrally varying path weight that corresponds to a prefix of length l and a suffix of le...
Definition: path.h:320
void append(PathVertex *vertex)
Append a vertex to this path.
Definition: path.h:442
Path(const Path &path)
Copy constructor.
Definition: path.h:62
int length() const
Return the length of the path. This is just the number of edges.
Definition: path.h:227
void append(PathEdge *edge)
Append an edge to this path.
Definition: path.h:445
const PathVertexPtr & vertex(size_t index) const
Return an vertex by its index (const version)
Definition: path.h:243
PathVertexPtr vertexOrNull(size_t index)
Return an vertex by its index (or NULL if out of bounds)
Definition: path.h:254
Spectrum getRelativeWeight() const
Return the relative spectrally varying path weight associated with this path.
Definition: path.h:364
void clear()
Clear the path.
Definition: path.h:490
Principal scene data structure.
Definition: scene.h:49
#define SLog(level, fmt,...)
Write a Log message to the console (static version - to be used outside of classes that derive from O...
Definition: logger.h:49
Base class of all sample generators.
Definition: sampler.h:66
bool operator!=(const Path &path) const
Compare this path against another path.
Definition: path.h:499
void append(PathEdge *edge, PathVertex *vertex)
Append an edge and a vertex to this path.
Definition: path.h:455
Bidirectional path data structure.
Definition: path.h:46
#define MTS_NAMESPACE_BEGIN
Definition: platform.h:137
size_t vertexCount() const
Return the number of vertices stored in this path.
Definition: path.h:209
Path(size_t size)
Create a new path of the specified size.
Definition: path.h:59
PathVertex * PathVertexPtr
Definition: path.h:49
PathEdgePtr edgeOrNull(size_t index) const
Return an edge by its index (or NULL if out of bounds, const version)
Definition: path.h:297
Importance transport.
Definition: common.h:40
Float getLuminance() const
Return the luminance in candelas.
void swapEndpoints(PathVertexPtr &supernode, PathEdgePtr &edge, PathVertexPtr &sample)
Swap the two endpoint vertices of a path with the provided values.
Definition: path.h:435
Definition: fwd.h:99
Path()
Create a new, empty path.
Definition: path.h:56
#define SIZE_T_FMT
Definition: platform.h:92
PathEdgePtr & edge(size_t index)
Return an edge by its index.
Definition: path.h:268
EVertexType type
Specifies one of several possible path vertex types.
Definition: vertex.h:94
size_t edgeCount() const
Return the number of edges stored in this path.
Definition: path.h:219
Bidirectional path edge data structure.
Definition: edge.h:46
Error message, causes an exception to be thrown.
Definition: formatter.h:33
PathEdge * PathEdgePtr
Definition: path.h:48
PathVertexPtr vertexOrNull(size_t index) const
Return an vertex by its index (or NULL if out of bounds, const version)
Definition: path.h:261
bool isConnectable() const
Returns whether or not this vertex can be deterministically connected to other vertices.
Definition: vertex.h:740
Discrete spectral power distribution based on a number of wavelength bins over the 360-830 nm range...
Definition: spectrum.h:663
PathVertexPtr & vertex(size_t index)
Return an vertex by its index.
Definition: path.h:232
Definition: mempool.h:29
Radiance transport.
Definition: common.h:38
#define MTS_NAMESPACE_END
Definition: platform.h:138
PathEdgePtr edgeOrNull(size_t index)
Return an edge by its index (or NULL if out of bounds)
Definition: path.h:290
ETransportMode
Specifies the transport mode when sampling or evaluating a scattering function.
Definition: common.h:33
const Point2 & getSamplePosition() const
Return the sample position associated with the path.
Definition: path.h:485