/* PhBPhongEmitter.C: PhBPhongEmitter nodes (public source) */

#include "PhBPhongEmitter.H"

namespace xrml {

float PhBPhongEmitter::glossy_threshold = 20;

void PhBPhongEmitter::render(void)
{
  //
}

float PhBPhongEmitter::emittance(int range)
{
  if ((sharpness == 0. && (range & GR_DIFFUSE)) ||
      (sharpness <= glossy_threshold && (range & GR_GLOSSY)) ||
      (sharpness > glossy_threshold && (range & GR_SPECULAR)))
    return 1.;
  else
    return 0.;
}

Vec3 PhBPhongEmitter::sample(float xi1, float xi2, int range)
{
  double phi = 2. * M_PI * xi1;
  double cos_phi = cos(phi);
  double sin_phi = sin(phi);
  double cos_theta = pow(xi2, 1./(sharpness+1.));
  double sin_theta = sqrt(1. - cos_theta*cos_theta);
  return Vec3(cos_phi * sin_theta,
	      sin_phi * sin_theta,
	      cos_theta);
}

float PhBPhongEmitter::eval(const Vec3& dir, int range, float *pdf)
{
  if (pdf) *pdf = 0.;

  if (!((sharpness == 0. && (range & GR_DIFFUSE)) ||
	(sharpness <= glossy_threshold && (range & GR_GLOSSY)) ||
	(sharpness > glossy_threshold && (range & GR_SPECULAR)))) {
    return 0.;
  }

  if (dir.z <= 0.)	// direction points inside surface
    return 0.;

  double val = pow(dir.z, sharpness);
  if (pdf) *pdf = val * (sharpness+1.) / (2. * M_PI);
  return val * (sharpness+2.) / (2. * M_PI);
}

}  // namespace xrml
