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

#include "PhBHomogeneousBackground.H"
#include "utils.H"
#include "renderer.H"
#include "world.H"

namespace xrml {
void PhBHomogeneousBackground::set_bind(const SFBool& set)
{
  Bindable::set_bind(set);
}

void PhBHomogeneousBackground::render(void)
{
  for(int i=0; i < spectralBasis.size; i++) { 
    spectralBasis[i]->render();
  }

  // render background
  world->renderer->phbHomogeneousBackground(this);
}

Spectrum PhBHomogeneousBackground::eval(const Vec3& /*position*/, 
					const Vec3& direction, 
					const Spectrum& specWeight, 
					float *pdf)
{
  Spectrum spectrum(0.);

  for (int i=0; i < spectralBasis.size; i++)
      spectrum += (spectralBasis[i]->value) * spectralWeights[i];

  // pdf
  if (pdf) *pdf = 1. / (4 * M_PI);

  // return
  return spectrum;
}

Vec3 PhBHomogeneousBackground::sample(const Spectrum& specWeight,
				      const Vec3& /*position*/, 
				      const float xi1, const float xi2,
				      Spectrum *value, float *pdf)
{
  double phi = 2. * M_PI * xi1;
  double xi21 = fabs(2 * (xi2 - .5));
  double xi22 = (xi2 < .5) ? -1. : +1;  // -1 is lower hemisphere, +1 is upper hemisphere
  double cos_phi = cos(phi);
  double sin_phi = sin(phi);
  double cos_theta = 1 - xi21;
  double sin_theta = sqrt(1 - xi21*xi21);

  if(pdf) *pdf = 1. / (4 * M_PI);

  return Vec3(cos_phi * sin_theta,
	      sin_phi * sin_theta,
	      xi22 * cos_theta);
}

Spectrum PhBHomogeneousBackground::power(const Vec3& /*position*/)
{
  Spectrum spectrum(0.);

  for (int i=0; i < spectralBasis.size; i++)
      spectrum += (spectralBasis[i]->value) * spectralWeights[i];

  return spectrum * 4 * M_PI;
}

}  // namespace xrml
