//----------------------------------------------------------------------------
// William Baxter III's Ray Tracer
//
//     Project for Comp 238, Raster Graphics
//     University of North Carolina at Chapel Hill
//     
// $Id:$
//----------------------------------------------------------------------------

#include "wb3TextureImage.hpp"

using namespace Colosseum;

static const float One255th = 1.0f/255.0f;


//----------------------------------------------------------------------------
wb3TextureImage::wb3TextureImage()
{
}
//----------------------------------------------------------------------------
wb3TextureImage::~wb3TextureImage()
{
}
//----------------------------------------------------------------------------
inline int round(float f)
{
  return int(f+0.5f);
}
inline int floor(float f)
{
  return int(f);
}
inline int ceil(float f)
{
  /// don't want to round 1.0 to 2.0!
  if (float(int(float(f))) == f) return int(f);
  else return int(f+1.0f);
}

Vec3f& wb3TextureImage::GetValue(Vec3f& ret, const Vec2f& UV, bool bilerp)
{
  float u = fmod(UV.x, 1.0);
  float v = fmod(UV.y, 1.0);
  if (u<0) u = 1.0+u;
  if (v<0) v = 1.0+v;

  if (bilerp) {
    // Get 4 closest pixels and bi-linearly interpolate
    float x = u * (float(m_img.getWidth())-0.5f);
    float y = v * (float(m_img.getHeight())-0.5f);
    UBYTE1 r1,g1,b1, r2,b2,g2;
    ret = Vec3f::ZERO;
    int fx = floor(x);
    int fy = floor(y);
    int cx = ceil(x);
    int cy = ceil(y);

    // Clamp if we went too far
    if (fx < 0) fx = 0;
    if (fy < 0) fy = 0;
    if (cx >= m_img.getWidth()) cx = m_img.getWidth();
    if (cy >= m_img.getHeight()) cy = m_img.getHeight();
    
    float s, t;

    // Lerp first, upper u pair
    m_img.getRgb(cy,fx,r1,g1,b1);
    m_img.getRgb(cy,cx,r2,g2,b2);
    s = float(cx) - x;
    t = 1.0f - s;
    Vec3f tmp(s*r1+t*r2, s*g1+t*g2, s*b1+t*b2);

    // Lerp second, lower u pair (same s,t)
    m_img.getRgb(fy,fx,r1,g1,b1);
    m_img.getRgb(fy,cx,r2,g2,b2);
    ret.Set(s*r1+t*r2, s*g1+t*g2, s*b1+t*b2);

    // Lerp the lerps
    s = float(cy) - y;
    t = 1.0f - s;
    ret *= s;
    ret += t*tmp;
    ret *= One255th;
  }
  else {
    // Pick the pixel whose center we are closest to
    int col = round(u * (float(m_img.getWidth())-0.5f));
    int row = round(v * (float(m_img.getHeight())-0.5f));
    UBYTE1 r,g,b;
    m_img.getRgb(row,col,r,g,b); // 
    ret.Set(r,g,b);
    ret *= One255th;
  }

  return ret;
}


