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

#include <math.h>

#include "PhBImageTextureBase.H"
#include "ReadImage.H"
#include "Float.H"
#include "file.H"
#include "world.H"

namespace xrml {

void PhBImageTextureBase::render(void)
{
  if (!image.map) {
    // load texture map
    image.load(url, world);

    // create a black "outside texture" pixel
    blackpixel = new float[image.channels];
    for(int i = 0; i < image.channels; i++) blackpixel[i] = 0;
  }
  //  DumpTexture("/home/pieterp/Test.ppm", 255, 255);
}

float *PhBImageTextureBase::getpixel(long i, long j)
{
  if (!image.map) return 0;

  float *res = &(image.map[(j * image.width + i) * image.channels]);
  return res;
}

float *PhBImageTextureBase::values(double u, double v, int *nrChannels)
{
  // return number of channels
  if (nrChannels) *nrChannels = image.channels;

  // handle clamping and repeating
  // U
  if(u < 0) {                        // < 0
    if (repeating) u -= floor(u);    // REPEAT
    else if (clamping) u = 0;        // CLAMP
    else return blackpixel;
  }
  else if (u >= 1) {                 // > 1
    if (repeating) u -= floor(u);    // REPEAT
    else if (clamping) u = 1-EPSILON;// CLAMP
    else return blackpixel;
  }

  // V
  if(v < 0) {                        // < 0
    if (repeating) v -= floor(v);    // REPEAT
    else if (clamping) v = 0;        // CLAMP
    else return blackpixel;
  }
  else if (v >= 1) {                 // > 1
    if (repeating) v -= floor(v);    // REPEAT
    else if (clamping) v = 1-EPSILON;// CLAMP
    else return blackpixel;
  }

  return getpixel((long)(u * image.width), (long)(v * image.height));
}

void PhBImageTextureBase::Dvalues(double u, double v, 
				  float *dX, 
				  float *dY, 
				  float *dZ)
{
  double u1 = ((u * image.width) + 1) / image.width;
  double v1 = ((v * image.height) + 1) / image.height;
   
  // get pixel values
  float *u0v0 = values(u, v, NULL);
  float *u1v0 = values(u1, v, NULL);
  float *u0v1 = values(u, v1, NULL);

  // calc d for every component and every channel
  for(int i = 0; i < image.channels; i++)
    {
      dX[i] = u1v0[i] - u0v0[i];
      dY[i] = u0v1[i] - u0v0[i];
      dZ[i] = 0;
    }
}

}  // namespace xrml
