/* PhBSchlickPhaseFunction.C: PhBSchlickPhaseFunction nodes (public source) */
//
// Taken from C.Schlick "Divers éléments pour une synthèse d'image réalistes" PhD 1992
//

#include "PhBSchlickPhaseFunction.H"

namespace xrml {
void PhBSchlickPhaseFunction::render(void)
{
  // nothing needs to be done
}

float PhBSchlickPhaseFunction::albedo(const Vec3& inDir,
	     int modes)
{
  return(-k / M_PI);
}

Vec3 PhBSchlickPhaseFunction::sample(const Vec3& inDir,
	    float xi1, float xi2,
	    int modes)
{
  double cosj = (2*xi1 + k - 1) / (2*xi1*k - k + 1);
  double sinj = sqrt(1 - cosj*cosj);
  double cosDelta = cos(2 * M_PI * xi2);
  double sinDelta = sin(2 * M_PI * xi2);
  double cosTheta = inDir.z;
  double sinTheta = sqrt(1 - cosTheta*cosTheta),   isinTheta = 1 / sinTheta;
  Vec3 t;

  if(sinTheta > EPSILON) {
    t = Vec3( (inDir.x * cosDelta * cosTheta - inDir.y * sinDelta) * isinTheta,
		   (inDir.y * cosDelta * cosTheta + inDir.x * sinDelta) * isinTheta,
		   sinTheta);
  }
  else t = Vec3(cosDelta, sinDelta, 0);      // inDir == Z-axis

  return Vec3(inDir * cosj + t * sinj);
}

float PhBSchlickPhaseFunction::eval(const Vec3& inDir,
				    const Vec3& outDir,
				    int modes, 
				    float *pdf)
{
  double cosj = inDir & outDir;
  double value = 1 - k*k;
  double diff = 1 - k*cosj;
  
  value /= (diff * diff);

  if (pdf) *pdf = -k * value / M_PI;

  return(value);
}
  
}  // namespace xrml
