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

#include "PhBDiffuseRefractor.H"

namespace xrml {

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

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

// pdf is proportional cosine of angle w.r.t. Z-axis.
Vec3 PhBDiffuseRefractor::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 other side of the surface
  // as inDir.
  return Vec3(cos_phi * sin_theta,
	      sin_phi * sin_theta,
	      cos_theta * (inDir.z >= 0. ? -1. : 1.));
}

float PhBDiffuseRefractor::eval(const Vec3& inDir,
				const Vec3& outDir,
				const complex& IndexIn,
				const complex& IndexOut,
				int modes,
				float *pdf)
{
  if (pdf) *pdf = 0.;
  if (!(modes & SM_DIFFUSE_REFRACTION))
    return 0.;

  if ((outDir.z > 0.) == (inDir.z > 0.))
    // reflected direction
    return 0.;

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

}  // namespace xrml
