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

#include "PhBDiffuseReflector.H"

namespace xrml {

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


float PhBDiffuseReflector::albedo(const Vec3& inDir,
				  const complex& IndexIn,
				  const complex& IndexOut,
				  int modes)
{
  return (modes & SM_DIFFUSE_REFLECTION)
    ? 1.
    : 0.;
}

// pdf is proportional cosine of angle w.r.t. Z-axis.
Vec3 PhBDiffuseReflector::sample(const Vec3& inDir,
				 const complex& IndexIn,
				 const complex& IndexOut,
				 float xi1, float xi2,
				 int modes)
{
  double phi = 2. * M_PI * xi1;
  double cos_phi = cos(phi);
  double sin_phi = sin(phi);
  double cos_theta = sqrt(1.0-xi2);
  double sin_theta = sqrt(xi2);

  // generate outDir on the same side of the surface
  // as inDir.
  return Vec3(cos_phi * sin_theta,
	      sin_phi * sin_theta,
	      cos_theta * (inDir.z >= 0. ? 1. : -1.));
}

float PhBDiffuseReflector::eval(const Vec3& inDir,
				const Vec3& outDir,
				const complex& IndexIn,
				const complex& IndexOut,
				int modes,
				float *pdf)
{
  if (pdf) *pdf = 0.;   // initialisation

  if (!(modes & SM_DIFFUSE_REFLECTION))
    // no contribution in requested scattering mode
    return 0.;

  if ((outDir.z > 0.) != (inDir.z > 0.))
    // refracted direction
    // also pdf is 0: the sampling routine above cannot yield such
    // directions.
    return 0.;

  if (pdf) *pdf = fabs(outDir.z) / M_PI;
  return 1. / M_PI;
}





}  // namespace xrml
