// ===================================================================
// $Id$
//
// neumann.h
//    Implementation of layered mixture BRDF surface.
//
// Class: CSurfaceCSurfaceLayeredMixture
//
// Initial coding by Jiri Nekola within diploma thesis project, November 2011

// Reference:
//  This model is not based on any original paper, because its empirical model
//  for demonstrating layered surface behaviour. But it is based on idea of
//  Weidlich-Wilkie BRDF : 
//  [1] Weidlich A., Wilkie A. Arbitrarily Layered Microfacet Surface GRAPHITE 2007, pages 171-178, 2007.


#ifndef __SURFACE_LAYERED_MIXTURE_H__
#define __SURFACE_LAYERED_MIXTURE_H__

#include "configh.h"
#include "surface.h"
#include "layered_surface.h"

__BEGIN_BRDFLIB_HEADER

// Forward-declare classes
class CHitPointInfo;
class CTexture;


/**
	This is layered mixture BRDF class.
	This BRDF has only one purpose : demonstrate an usage of layered surface. 
	Basic idea is partially based on the BRDF model Weidlich-Wilkie [1], but 
	with several simplifications. There can be any number of layers, arbitrarily 
	layered, without any assumptions on their type/functionality. Final BRDF is 
	evaluated as sum of first layer BRDF and recursively attenuated BRDFs of layers
	under it. Attenuated factors are thickness and absorbtion coefficients of the 
	layer. Despite this "sum principle" doesnt fulfill energy conservation, results 
	are quite good and such a mixture is fairly flexible model.
*/
class CSurfaceLayeredMixture :
	public CSurfaceLayered
{
public :
	/// Standard constructor.
	CSurfaceLayeredMixture():
		CSurfaceLayered()
	{}

	/// Destructor.
	virtual ~CSurfaceLayeredMixture()
	{}
	
	/// Implements CSurface.
	virtual CSurface *Dup() const;

	/// Implements CSurface.
	virtual bool
	GetAlbedoMax(CValues &albedo,
		const CHitPointInfo &hitInfo,
		EDistributionType   distType = EE_ALL) const;

	/// Implements CSurface.
	virtual bool GetDefaultColor(CValues &defaultColor,
			       const CHitPointInfo &hitInfo) const;


	/// Implements CSurface.
	virtual bool
	EvaluateBSDF(CValues             &result,
	       const CHitPointInfo &hitInfo,
	       const CVector3D     &dirIn,
	       EDistributionType   distType = EE_ALL) const;

	/// Implements CSurface.
	virtual bool
	GetAlbedo(CValues &albedo,
	       const CHitPointInfo &hitInfo,
	       EDistributionType   distType=EE_ALL) const;

	/// Implements CSurface.
	virtual int
	SpawnDeterministicRays(CContributionArray  &carray,
		         const CHitPointInfo &hitInfo,
       		         EDistributionType   distType = EE_ALL) const;

	/// Implements CSurface.
	virtual float GetAverageDiffuseness(void) const;

	/// Implements CSurface.
	virtual float GetDiffuseness(const CHitPointInfo &,
			       EDistributionType distType = EE_ALL) const;

	/// Implements CSurface.
	virtual int
	SpawnStochasticRays(CContributionArray  &carray,
		      const CHitPointInfo &hitInfo,
		      CSamplingInfo       &samplingInfo,
		      EDistributionType    distType = EE_ALL) const;

	/// Implements CSurface.
	virtual const char* GetHelp() const;

protected:
	typedef vector<double> rnd_array;	///< the auxiliary storage of random variable
	static rnd_array diffuse_rnd;		///< the auxiliary storage of random numbers for diffuse rays
	static rnd_array specular_rnd;		///< the auxiliary storage of random numbers for specular rays

	/// Auxiliary method for evaluationg BSDF recursively within the layered surface.
	/**
		Auxiliary method for evaluationg BSDF recursively within the layered surface. Each layer
		evaluates BSDF for all the layers below it, then attenuate this value by its thickness and
		absorption coefficient and add its own BSDF value.
	*/
	virtual bool 
	EvaluateBSDFRecursively(CValues &result,
	       const CHitPointInfo &hitInfo,
	       const CVector3D     &dirIn,
	       EDistributionType   distType,
		   const int layerIndex) const;

};

__END_BRDFLIB_HEADER

#endif // __SURFACE_LAYERED_MIXTURE_H__

