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

#include "PhBNormalMap.H"

namespace xrml {

void PhBNormalMap::render(void)
{
  if (texture) texture->render();
  if(transform) transform->render();
}

Mat3 PhBNormalMap::distort(const Vec3 point)
{
  int nrChannels = 0;
  Vec3 Xi, X, Yi, Y, Z;

  // get texture value
  Vec3 texco = point;
  if (transform) texco *= transform->xf;
  float *value = (texture) ? texture->values(texco.x, texco.y, &nrChannels) : NULL;

  // need atleast 2 channels (X and Y component of Z-axis)
  if (nrChannels < 2) return Mat3();

  // determine X, Y, Z axis
  float x = value[0]*2 - 1,  y = value[1]*2 - 1;
  double l = x*x + y*y;

  if (l <= 1)   Z = Vec3(x, y,  sqrt(1 - l) );
  else Z = Vec3(x, y, 0).normalize();

  if (fabs(Z.x) < EPSILON) Xi = Vec3(Z.z, 0, -Z.x).normalize();
  else Xi = Vec3(1, 0, 0);
  if (fabs(Z.y) < EPSILON) Yi = Vec3(0, Z.z, -Z.y).normalize();
  else Yi = Vec3(0, 1, 0);

  X = ((Yi ^ Z) + Xi).normalize();
  Y = ((Z ^ Xi) + Yi).normalize();

  return Mat3( X, Y, Z);
}

}  // namespace xrml
