text: /*
      This file is part of Mitsuba, a physically based rendering system.
  
      Copyright (c) 2007-2014 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_RENDER_INTEGRATOR_H_)
  #define __MITSUBA_RENDER_INTEGRATOR_H_
  
  #include <mitsuba/core/netobject.h>
  #include <mitsuba/core/properties.h>
  #include <mitsuba/render/shape.h>
  
  MTS_NAMESPACE_BEGIN
  
  /**
   * \brief Abstract integrator base-class; does not make any assumptions on
   * how radiance is computed.
   *
   * In Mitsuba, the different rendering techniques are collectively referred to as
   * \a integrators, since they perform integration over a high-dimensional
   * space. Each integrator represents a specific approach for solving
   * the light transport equation---usually favored in certain scenarios, but
   * at the same time affected by its own set of intrinsic limitations.
   * Therefore, it is important to carefully select an integrator based on
   * user-specified accuracy requirements and properties of the scene to be
   * rendered.
   *
   * This is the base class of all integrators; it does not make any assumptions on
   * how radiance is computed, which allows for many different kinds of implementations
   * ranging from software-based path tracing and Markov-Chain based techniques such
   * as Metropolis Light Transport up to hardware-accelerated rasterization.
   *
   * \ingroup librender
   */
  class MTS_EXPORT_RENDER Integrator : public NetworkedObject {
  public:
  	/**
  	 * \brief Possibly perform a pre-process task.
  	 *
  	 * This function is called automatically before the main rendering process;
  	 * the default implementation does nothing.
  	 *
  	 * The last three parameters are resource IDs of the associated scene,
  	 * sensor and sample generator, which have been made available to all
  	 * local and remote workers.i
  	 */
  	virtual bool preprocess(const Scene *scene, RenderQueue *queue,
  		const RenderJob *job, int sceneResID, int sensorResID,
  		int samplerResID);
  
  	/**
  	 * \brief Render the scene as seen by the default sensor.
  	 *
  	 * Progress is tracked by sending status messages to a provided render queue.
  	 * The parameter \c job is required to discern multiple render jobs occurring in
  	 * parallel. The last three parameters are resource IDs of the associated
  	 * scene, sensor and sample generator, which have been made available to
  	 * all local and remote workers. Returns true upon successful completion.
  	 */
  	virtual bool render(Scene *scene, RenderQueue *queue, const RenderJob *job,
  		int sceneResID, int sensorResID, int samplerResID) = 0;
  
  	/**
  	 * \brief Cancel a running render job
  	 *
  	 * This function can be called asynchronously to cancel a running render
  	 * job. In this case, \ref render() will quit with a return value of
  	 * \c false.
  	 */
  	virtual void cancel() = 0;
  
  	/**
  	 * \brief Possibly perform a post-process task.
  	 *
  	 * This function is called automatically before the main rendering process;
  	 * the default implementation does nothing.
  	 *
  	 * The last three parameters are resource IDs of the associated scene,
  	 * sensor and sample generator, which have been made available to all
  	 * local and remote workers.i
  	 */
  	virtual void postprocess(const Scene *scene, RenderQueue *queue,
  		const RenderJob *job, int sceneResID, int sensorResID,
  		int samplerResID);
  
  	/**
  	 * \brief Configure the sample generator for use with this integrator
  	 *
  	 * This function is called once after instantiation and can be used to
  	 * inform the sampler implementation about specific sample requirements
  	 * of this integrator.
  	 */
  	virtual void configureSampler(const Scene *scene, Sampler *sampler);
  
  	/**
  	 * \brief Return the nested integrator (if any)
  	 *
  	 * When the integrator contains a nested integrator, this function can
  	 * be used to query for it
  	 */
  	virtual const Integrator *getSubIntegrator(int index) const;
  
  	/// Serialize this integrator to a binary data stream
  	void serialize(Stream *stream, InstanceManager *manager) const;
  
  	MTS_DECLARE_CLASS()
  protected:
  	/// Create a integrator
  	Integrator(const Properties &props);
  
  	/// Unserialize an integrator
  	Integrator(Stream *stream, InstanceManager *manager);
  
  	/// Virtual destructor
  	virtual ~Integrator() { }
  };
  
  /**
   * \brief Radiance query record data structure used by \ref SamplingIntegrator
   * \ingroup librender
   */
  struct MTS_EXPORT_RENDER RadianceQueryRecord {
  public:
  	/// List of suported query types. These can be combined by a binary OR.
  	enum ERadianceQuery {
  		/// Emitted radiance from a luminaire intersected by the ray
  		EEmittedRadiance          = 0x0001,
  
  		/// Emitted radiance from a subsurface integrator */
  		ESubsurfaceRadiance       = 0x0002,
  
  		/// Direct (surface) radiance */
  		EDirectSurfaceRadiance    = 0x0004,
  
  		/*! \brief Indirect (surface) radiance, where the last bounce did not go
  		    through a Dirac delta BSDF */
  		EIndirectSurfaceRadiance  = 0x0008,
  
  		/*! \brief Indirect (surface) radiance, where the last bounce went
  		   through a Dirac delta BSDF */
  		ECausticRadiance          = 0x0010,
  
  		/// In-scattered radiance due to volumetric scattering (direct)
  		EDirectMediumRadiance     = 0x0020,
  
  		/// In-scattered radiance due to volumetric scattering (indirect)
  		EIndirectMediumRadiance   = 0x0040,
  
  		/// Distance to the next surface intersection
  		EDistance                 = 0x0080,
  
  		/*! \brief Store an opacity value, which is equal to 1 when a shape
  		   was intersected and 0 when the ray passes through empty space.
  		   When there is a participating medium, it can also take on fractional
  		   values. */
  		EOpacity                  = 0x0100,
  
  		/*! \brief A ray intersection may need to be performed. This can be set to
  		   zero if the caller has already provided the intersection */
  		EIntersection             = 0x0200,
  
  		/* Radiance from volumes */
  		EVolumeRadiance           = EDirectMediumRadiance | EIndirectMediumRadiance,
  
  		/// Radiance query without emitted radiance, ray intersection required
  		ERadianceNoEmission       = ESubsurfaceRadiance | EDirectSurfaceRadiance
  			| EIndirectSurfaceRadiance | ECausticRadiance | EDirectMediumRadiance
  			| EIndirectMediumRadiance | EIntersection,
  
  		/// Default radiance query, ray intersection required
  		ERadiance                 = ERadianceNoEmission | EEmittedRadiance,
  
  		/// Radiance + opacity
  		ESensorRay                = ERadiance | EOpacity
  	};
  
  	/// Additional flags that can be specified in the \ref extra field
  	enum EExtraFlags {
  		/// This is a query by an irradiance cache
  		ECacheQuery    = 0x01,
  		/// This is a query by an adaptive integrator
  		EAdaptiveQuery = 0x02
  	};
  
  	/// Construct an invalid radiance query record
  	inline RadianceQueryRecord()
  	 : type(0), scene(NULL), sampler(NULL), medium(NULL),
  	   depth(0), alpha(0), dist(-1), extra(0) {
  	}
  
  	/// Construct a radiance query record for the given scene and sampler
  	inline RadianceQueryRecord(const Scene *scene, Sampler *sampler)
  	 : type(0), scene(scene), sampler(sampler), medium(NULL),
  	   depth(0), alpha(0), dist(-1), extra(0) {
  	}
  
  	/// Copy constructor
  	inline RadianceQueryRecord(const RadianceQueryRecord &rRec)
  	 : type(rRec.type), scene(rRec.scene), sampler(rRec.sampler), medium(rRec.medium),
  	   depth(rRec.depth), alpha(rRec.alpha), dist(rRec.dist), extra(rRec.extra) {
  	}
  
  	/// Begin a new query of the given type
  	inline void newQuery(int _type, const Medium *_medium) {
  		type = _type;
  		medium = _medium;
  		depth = 1;
  		extra = 0;
  		alpha = 1;
  	}
  
  	/// Initialize the query record for a recursive query
  	inline void recursiveQuery(const RadianceQueryRecord &parent, int _type) {
  		type = _type;
  		scene = parent.scene;
  		sampler = parent.sampler;
  		depth = parent.depth+1;
  		medium = parent.medium;
  		extra = parent.extra;
  	}
  
  	/// Initialize the query record for a recursive query
  	inline void recursiveQuery(const RadianceQueryRecord &parent) {
  		type = parent.type | EIntersection;
  		scene = parent.scene;
  		sampler = parent.sampler;
  		depth = parent.depth+1;
  		medium = parent.medium;
  		extra = parent.extra;
  	}
  
  	/**
  	 * \brief Search for a ray intersection
  	 *
  	 * This function does several things at once: if the
  	 * intersection has already been provided, it returns.
  	 *
  	 * Otherwise, it
  	 * 1. performs the ray intersection
  	 * 2. computes the transmittance due to participating media
  	 *   and stores it in \c transmittance.
  	 * 3. sets the alpha value (if \c EAlpha is set in \c type)
  	 * 4. sets the distance value (if \c EDistance is set in \c type)
  	 * 5. clears the \c EIntersection flag in \c type
  	 *
  	 * \return \c true if there is a valid intersection.
  	 */
  	inline bool rayIntersect(const RayDifferential &ray);
  
  	/// Retrieve a 2D sample
  	inline Point2 nextSample2D();
  
  	/// Retrieve a 1D sample
  	inline Float nextSample1D();
  
  	/// Return a string representation
  	std::string toString() const;
  public:
  	// An asterisk (*) marks entries, which may be overwritten
  	// by the callee.
  
  	/// Query type (*)
  	int type;
  
  	/// Pointer to the associated scene
  	const Scene *scene;
  
  	/// Sample generator
  	Sampler *sampler;
  
  	/// Pointer to the current medium (*)
  	const Medium *medium;
  
  	/// Current depth value (# of light bounces) (*)
  	int depth;
  
  	/// Surface interaction data structure (*)
  	Intersection its;
  
  	/// Opacity value of the associated pixel (*)
  	Float alpha;
  
  	/**
  	 * Ray distance to the first surface interaction
  	 * (if requested by the query type EDistance) (*)
  	 */
  	Float dist;
  
  	/**
  	 * Internal flag, which can be used to pass additional information
  	 * amonst recursive calls inside an integrator. The use
  	 * is dependent on the particular integrator implementation. (*)
  	 */
  	int extra;
  };
  
  /** \brief Abstract base class, which describes integrators
   * capable of computing samples of the scene's radiance function.
   * \ingroup librender
   */
  class MTS_EXPORT_RENDER SamplingIntegrator : public Integrator {
  public:
  	/**
  	 * \brief Sample the incident radiance along a ray. Also requires
  	 * a radiance query record, which makes this request more precise.
  	 */
  	virtual Spectrum Li(const RayDifferential &ray,
  		RadianceQueryRecord &rRec) const = 0;
  
  	/**
  	 * \brief Estimate the irradiance at a given surface point
  	 *
  	 * The default implementation simply samples the hemisphere using
  	 * cosine-weighted sampling and a configurable number of rays.
  	 * An integrator such as irradiance caching will provide something
  	 * smarter.
  	 *
  	 * \param scene
  	 *     Const pointer to the underlying scene
  	 * \param its
  	 *     Describes the surface location where the irradiance is to be computed
  	 * \param medium
  	 *     Const pointer to the medium that encloses the ray
  	 *     <tt>(its.p, its.shFrame.n)</tt>. A value of \c NULL corresponds
  	 *     to vacuum.
  	 * \param sampler
  	 *     A pointer to a sample generator
  	 * \param nSamples
  	 *     How many samples should be taken
  	 * \param includeIndirect
  	 *     Include indirect illumination in the estimate?
  	 */
  	virtual Spectrum E(const Scene *scene, const Intersection &its,
  		const Medium *medium, Sampler *sampler, int nSamples,
  		bool includeIndirect) const;
  
  	/**
  	 * \brief Perform the main rendering task
  	 *
  	 * The work is automatically parallelized to multiple cores and
  	 * remote machines. The default implementation uniformly generates
  	 * samples on the sensor aperture and image plane as specified by
  	 * the used sampler. The average of the estimated radiance along the
  	 * associated rays in a pixel region is then taken as an approximation
  	 * of that pixel's radiance value. For adaptive strategies, have a look at
  	 * the \c adaptive plugin, which is an extension of this class.
  	 */
  	bool render(Scene *scene, RenderQueue *queue, const RenderJob *job,
  		int sceneResID, int sensorResID, int samplerResID);
  
  	/**
  	 * This can be called asynchronously to cancel a running render job.
  	 * In this case, <tt>render()</tt> will quit with a return value of
  	 * <tt>false</tt>.
  	 */
  	void cancel();
  
  	/**
  	 * This method does the main work of <tt>render()</tt> and
  	 * runs in parallel for a series of image blocks, which are
  	 * being processed at a time.
  	 *
  	 * \param scene
  	 *    Pointer to the underlying scene
  	 * \param sensor
  	 *    Pointer to the sensor used to render the image
  	 * \param sampler
  	 *    Pointer to the sampler used to render the image
  	 * \param block
  	 *    Pointer to the image block to be filled
  	 * \param points
  	 *    Specifies the traversal order, i.e. using a space-filling
  	 *    curve. To limit the size of the array, it is currently assumed
  	 *    that the block size is smaller than 256x256
  	 * \param stop
  	 *    Reference to a boolean, which will be set to true when
  	 *    the user has requested that the program be stopped
  	 */
  	virtual void renderBlock(const Scene *scene, const Sensor *sensor,
  		Sampler *sampler, ImageBlock *block, const bool &stop,
  		const std::vector< TPoint2<uint8_t> > &points) const;
  
  	/**
  	 * <tt>NetworkedObject</tt> implementation:
  	 * When a parallel rendering process starts, the integrator is
  	 * given the opportunity to attach globally shared resources to
  	 * the process. This is useful for distributing heavy data
  	 * structures (e.g. photon maps) without having to re-transmit
  	 * them every time an image is rendered.
  	 */
  	virtual void bindUsedResources(ParallelProcess *proc) const;
  
  	/**
  	 * <tt>NetworkedObject</tt> implementation:
  	 * Called once just before this integrator instance is asked
  	 * to process an image block. In comparison to <tt>preprocess()</tt>
  	 * this will be executed on _every_ instance of this class, which is
  	 * useful for connecting to globally shared resources (photon maps,
  	 * irradiance caches, ..) after having been unserialized on a
  	 * remote machine. A list of resources bound to the associated
  	 * parallel process is given as a parameter.
  	 */
  	virtual void wakeup(ConfigurableObject *parent,
  		std::map<std::string, SerializableObject *> &params);
  
  	/// Serialize this integrator to a binary data stream
  	void serialize(Stream *stream, InstanceManager *manager) const;
  
  	MTS_DECLARE_CLASS()
  protected:
  	/// Create a integrator
  	SamplingIntegrator(const Properties &props);
  
  	/// Unserialize an integrator
  	SamplingIntegrator(Stream *stream, InstanceManager *manager);
  
  	/// Virtual destructor
  	virtual ~SamplingIntegrator() { }
  protected:
  	/// Used to temporarily cache a parallel process while it is in operation
  	ref<ParallelProcess> m_process;
  
  	int m_seed;                 // Note: This should be in MonteCarloIntegrator or PathTracer!
  	Point2i m_seedShift;		// shift of seeds, used for PSS GPT.
  };
  
  /*
   * \brief Base class of all recursive Monte Carlo integrators, which compute
   * unbiased solutions to the rendering equation (and optionally
   * the radiative transfer equation).
   * \ingroup librender
   */
  class MTS_EXPORT_RENDER MonteCarloIntegrator : public SamplingIntegrator {
  public:
  	/// Serialize this integrator to a binary data stream
  	void serialize(Stream *stream, InstanceManager *manager) const;
  
  	MTS_DECLARE_CLASS()
  protected:
  	/// Create a integrator
  	MonteCarloIntegrator(const Properties &props);
  	/// Unserialize an integrator
  	MonteCarloIntegrator(Stream *stream, InstanceManager *manager);
  	/// Virtual destructor
  	virtual ~MonteCarloIntegrator() { }
  protected:
      int m_maxDepth;
      int m_rrDepth;
  	bool m_strictNormals;
  	bool m_hideEmitters;
  };
  
  MTS_NAMESPACE_END
  
  #endif /* __MITSUBA_RENDER_INTEGRATOR_H_ */
  