#define MODULE_TXR

#include "graf.h"

void (*TXR_texture_lookup_function)();

int TXR_TextureNU, TXR_TextureNV;

CVALUE *TXR_TextureR;
CVALUE *TXR_TextureG;
CVALUE *TXR_TextureB;

void txr_texture_lookup( FLOAT *P, int LightEvaluated )
{
   int i,j,index;

   FLOAT u,v,r,g,b;

   if ( TXR_texture_lookup_function )
   {
       (*TXR_texture_lookup_function)(P,LightEvaluated);
       return;
   }        

   if ( !TXR_TextureR ) return;

   if ( LMD_Lmodel != LMD_LMODEL_PHONG && !LightEvaluated ) return;
   if ( LMD_Lmodel == LMD_LMODEL_PHONG &&  LightEvaluated ) return;

   u = P[VERTEX_TEXTURE_U];
   v = P[VERTEX_TEXTURE_V];

#define CLAMP
#ifdef CLAMP
   if ( u < 0.0 ) u = 0.0;
   else if ( u > 1 ) u = 1.0;

   if ( v < 0.0 ) v = 0.0;
   else if ( v > 1.0 ) v = 1.0;

#endif
   u = (int)(u*(TXR_TextureNU-1) + 0.5);
   v = (int)(v*(TXR_TextureNV-1) + 0.5);

#ifndef CLAMP
   u = ((int)u) % TXR_TextureNU;
   v = ((int)v) % TXR_TextureNV;
#endif


#ifdef  SMOOTH
#define SMOOTH

   k = 0;
   r = g = b = 0.0;
   for( i  = -1; i <= 1; i++ )
       for( j  = -1; j <= 1; j++ )
       {
           if ( i + v  < 0 ) continue;
           if ( i + v  > TXR_TextureNV-1 ) continue;

           if ( j + u  < 0 ) continue;
           if ( j + u  > TXR_TextureNU-1 ) continue;

           index = (((int)v)+i) * TXR_TextureNU + (((int)u)+j);

           r += TXR_TextureR[index];
           g += TXR_TextureG[index];
           b += TXR_TextureB[index];

           k++;
       }
       
   r /= k*255.0;
   g /= k*255.0;
   b /= k*255.0;

#else

   index = ((int)v)*TXR_TextureNU + (int)u;
   r = TXR_TextureR[index]/255.0;
   g = TXR_TextureG[index]/255.0;
   b = TXR_TextureB[index]/255.0;

#endif

   if ( !LightEvaluated )
   {
       P[VERTEX_MATERIAL_DIFFUSE+0] *= r;
       P[VERTEX_MATERIAL_DIFFUSE+1] *= g;
       P[VERTEX_MATERIAL_DIFFUSE+2] *= b;
       P[VERTEX_MATERIAL_AMBIENT+0] *= r;
       P[VERTEX_MATERIAL_AMBIENT+1] *= g;
       P[VERTEX_MATERIAL_AMBIENT+2] *= b;
   } else
   {
       P[VERTEX_COLOR_R] *= r;
       P[VERTEX_COLOR_G] *= g;
       P[VERTEX_COLOR_B] *= b;
   }

   return;
}

void txr_load_texture( int NU, int NV, CVALUE *R, CVALUE *G, CVALUE *B )
{
    TXR_TextureR = R;
    TXR_TextureG = G;
    TXR_TextureB = B;

    TXR_TextureNU = NU;
    TXR_TextureNV = NV;

    if (  R != (CVALUE *)0 )
    {
        if (NU>1) lmd_add_lmodel_interpolant( VERTEX_TEXTURE_U );
        if (NV>1) lmd_add_lmodel_interpolant( VERTEX_TEXTURE_V );
    }
}

void txr_set_function( void (*function)() )
{
    TXR_texture_lookup_function = function;
}
