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

#include "PhBLandscapePhotoBackground.H"

namespace xrml {
void PhBLandscapePhotoBackground::render(void)
{
  // do nothing
}

Vec3 PhBLandscapePhotoBackground::direction2surface(const Vec3& direction)
{
  double u, v;
  Vec3 H;

  // surface coord are
  if ((1 - fabs(direction.z)) < EPSILON) u = 0;
  else u = -((atan2(direction.x, direction.y) / (2 * M_PI)) + .5);
  v = -acos(direction.z) / M_PI;

  // If direction is (0, 0, 1) pick a pixel that is near this direction
  if ((1 - direction.z) < EPSILON) H = Vec3(1, 0, 0);
  // otherwise calculate half-vector
  else H = Vec3(direction.x, direction.y, direction.z + 1).normalize(); 

  return Vec3(u, v, 0.);
}

Vec3 PhBLandscapePhotoBackground::surface2direction(const Vec3& surfaceCoord)
{
  double theta = 2. * M_PI * (surfaceCoord.x +.25);
  double cos_theta = cos(theta);
  double sin_theta = sin(theta);
  double phi = -surfaceCoord.y * M_PI;
  double cos_phi = cos(phi);
  double sin_phi = sin(phi);
    
  return Vec3(cos_theta * sin_phi,
	      sin_theta * sin_phi,
	      cos_phi);
}

Vec3 PhBLandscapePhotoBackground::start(const Vec3& /*surfaceCoord*/)
{
  return Vec3(0., 0., 0.);
}

Vec3  PhBLandscapePhotoBackground::size(const Vec3& /* surfaceCoord */)
{
  return Vec3(1., 1., 0.);
}

float PhBLandscapePhotoBackground::area(const Vec3& upleft,
					const Vec3& upright,
					const Vec3& downleft,
					const Vec3& downright)
{
  double height = fabs( cos(upright.y * M_PI) - cos(downright.y * M_PI) );
  double width = fabs( upright.x - upleft.x );
  if (width < EPSILON) width = fabs( downright.x - downleft.x );

  return float(2. * M_PI * height * width);
}

float PhBLandscapePhotoBackground::jacobian(const Vec3& surfaceCoord)
{
  double phi = M_PI * surfaceCoord.y;
  double sinPhi = fabs(sin(phi));


  if(sinPhi < EPSILON) return 0.;

  return (float)(1. / (2. * M_PI * M_PI * sinPhi));
}


}  // namespace xrml
