#define IRIS

#include  "graf.h"

TRS_MATRIX VM, PM;

#define V3(x,y,z) usr_pack3f(x,y,z)

CVALUE CM[16][4] =
{
   { 0,   0,   166, 255 },
   { 0,   0,   255, 255 },
   { 0,   83,  255, 255 },
   { 0,   166, 255, 255 },
   { 0,   255, 255, 255 },
   { 0,   83,  0  , 255 },
   { 0,   166, 0  , 255 },
   { 0,   255, 0  , 255 },
   { 255, 255, 0  , 255 },
   { 255, 166, 0  , 255 },
   { 255, 83,  0  , 255 },
   { 255, 0,   0  , 255 },
   { 255, 0,   255, 255 },
   { 255, 83,  255, 255 },
   { 255, 166, 255, 255 },
   { 255, 255, 255, 255 }
};

extern CVALUE *ZBF_R,*ZBF_G,*ZBF_B;
extern ZVALUE *ZBF_Z;
extern int ZBF_NX,ZBF_NY;
static CVALUE R[256*256], G[256*256], B[256*256];
extern int ZBF_Pcount, ZBF_Tcount;

zbf_show()
{
     int i,j,n;
     FILE *fp = fopen("a.ppm","w" );

     n = 0;
     for(i=0; i<ZBF_NY; i++ )
     {
     for(j=0; j<ZBF_NX; j++,n++ )
        fprintf(fp, "%c%c%c",ZBF_R[n],ZBF_G[n],ZBF_B[n]);
     }
     fclose(fp );
}


zbf_zshow()
{
     int i,j,k,n;
     char name[50];
     static int l=0;
     FILE *fp;

     sprintf( name,"z%d.raw", l++);
     fp = fopen(name,"w" );

     n = 0;
     for(i=0; i<ZBF_NY; i++ )
     for(j=0; j<ZBF_NX; j++,n++ )
     {
        k = (int)(255*(ZBF_Z[n]>1?1:ZBF_Z[n]));
        fprintf(fp, "%c%c%c",k,k,k);
     }
     fclose(fp );
}

read_texture()
{
    FILE *fp = fopen("balmoral.ppm","r" );
    int i,r,g,b,nx,ny;
    char str[200];

    fgets( str, 20, fp );
    fgets( str, 20, fp );
    sscanf( str, "%d %d", &nx, &ny );
    fgets( str, 20, fp );

     for( i=0; i<nx*ny; i++ )
     {
        fscanf( fp, "%d %d %d", &r,&g,&b);
        R[i] = r;
        G[i] = g;
        B[i] = b;
    }
    fclose( fp );
}

void bump_mapping( FLOAT *P, int LightEvaluated )
{
     FLOAT r;

     if ( LightEvaluated ) return;

     P[VERTEX_NORMAL_X] += 0.7*drand48()-0.35;
     P[VERTEX_NORMAL_Y] += 0.7*drand48()-0.35;
     P[VERTEX_NORMAL_Z] += 0.7*drand48()-0.35;
     normalize( P[VERTEX_NORMAL_X], P[VERTEX_NORMAL_Y], P[VERTEX_NORMAL_Z] );
}


void main( int argc, char **argv )
{
   FLOAT Xmin, Ymin, Zmin;
   FLOAT Xmax, Ymax, Zmax;
   FLOAT Fmin, Fmax;

   FLOAT xx[10], yy[10], zz[10];

   FLOAT *MP,r,a;
   FLOAT *nx,*ny,*nz;
   FLOAT *x,*y,*z,*f,*md;

   RGBA c0, c1;

   double T, t;

   char str[80];

   int *mat, *index, *E, *N, *Np, *e, *en, *mi;

   int NV,NN,NE,NF,NT;
   int i,j,k,l,n;

   int lmodel,lines,cflag;

   int comp[10];

   TRS_MATRIX ident = { {1.0,0.0,0.0,0.0},
                        {0.0,1.0,0.0,0.0},
                        {0.0,0.0,1.0,0.0},
                        {0.0,0.0,0.0,1.0} };

   if ( argc > 2 ) lines  = atoi( argv[2] );
   if ( argc > 3 ) lmodel = atoi( argv[3] );
   if ( argc > 4 ) cflag  = atoi( argv[4] );

   NV = NN = NE = NF = NT = 0;

   gets( str );
   sscanf( str, "%d %d %d %d %d", &NV, &NN, &NE, &NF, &NT );

   x  = (FLOAT *)malloc( NV * sizeof( FLOAT ) ); 
   y  = (FLOAT *)malloc( NV * sizeof( FLOAT ) ); 
   z  = (FLOAT *)malloc( NV * sizeof( FLOAT ) ); 

   nx = (FLOAT *)malloc( NN * sizeof( FLOAT ) ); 
   ny = (FLOAT *)malloc( NN * sizeof( FLOAT ) ); 
   nz = (FLOAT *)malloc( NN * sizeof( FLOAT ) ); 

   mat = (int *)malloc( NE * sizeof( int ) ); 
   mi = (int *)malloc( NE * sizeof( int ) ); 
   md = (FLOAT *)malloc( NE * sizeof( FLOAT ) ); 

   E = e = (int *)malloc( 10 * NE * sizeof( int ) );
   N = Np = (int *)malloc( 10 * NE * sizeof( int ) );

   en = (int *)malloc( NE * sizeof(int) );
   fprintf( stderr, "Nodes: %d, Elements: %d\n", NV, NE );

   for( i = 0; i < NV; i++ ) {
       gets( str );
       if ( sizeof( float ) == sizeof( FLOAT ) ) {
           sscanf( str, "%f %f %f", &x[i], &y[i], &z[i] );
       } else {
           sscanf( str, "%lf %lf %lf", &x[i], &y[i], &z[i] );
           }
       }

   for( i = 0; i < NN; i++ ) {
       gets( str );
       if ( sizeof( float ) == sizeof( FLOAT ) ) {
           sscanf( str, "%f %f %f", &nx[i], &ny[i], &nz[i] );
       } else {
           sscanf( str, "%lf %lf %lf", &nx[i], &ny[i], &nz[i] );
           }
       }

   for( i = 0; i < NE; i++ ) {
       gets( str );
       n = sscanf( str, "%d %*d %d/%d %d/%d %d/%d %d/%d %d/%d %d/%d %d/%d %d/%d %d/%d %d/%d", 
                         &mat[i],
                         &E[0], &N[0], &E[1], &N[1], &E[2], &N[2], &E[3], &N[3], &E[4], &N[4],
                         &E[5], &N[5], &E[6], &N[6], &E[7], &N[7], &E[8], &N[8], &E[9], &N[9]
                   );
       E  +=  10; N  +=  10;
       en[i] = (n - 1)/2;
       }

   N = Np;

   if ( NF ) {
       f = (FLOAT *)malloc( NV * sizeof( FLOAT ) );
       Fmin = 1.0e20; Fmax = -1.0e20;
       for( i = 0; i < NV; i++ ) {
           gets( str );
           if ( sizeof( float ) == sizeof( FLOAT ) ) {
               sscanf( str, "%f", &f[i] );
           } else {
               sscanf( str, "%lf", &f[i] );
               }
           Fmin =  MIN( Fmin, f[i] );
           Fmax =  MAX( Fmax, f[i] );
           }

       for( i = 0; i < NV; i++ ) {
           f[i] = 15 * ( f[i] - Fmin ) /  ( Fmax - Fmin );
           }
       fprintf( stderr, "%g %g\n", Fmin, Fmax );
       }

   Xmin = Ymin = Zmin =  1.0e20;
   Xmax = Ymax = Zmax = -1.0e20;
   for( i = 0; i < NV; i++ ) {
       Xmin = MIN( Xmin, x[i] );
       Ymin = MIN( Ymin, y[i] );
       Zmin = MIN( Zmin, z[i] );

       Xmax = MAX( Xmax, x[i] );
       Ymax = MAX( Ymax, y[i] );
       Zmax = MAX( Zmax, z[i] );
       }

   r = 2.0 / MAX( MAX( Xmax - Xmin, Ymax - Ymin ), Zmax - Zmin );
   for( i = 0; i < NV; i++ ) {
       x[i] = r*(x[i]-(Xmax + Xmin)/2); 
       y[i] = r*(y[i]-(Ymax + Ymin)/2); 
       z[i] = r*(z[i]-(Zmax + Zmin)/2); 
       }

   Xmin = Ymin = Zmin =  1.0e20;
   Xmax = Ymax = Zmax = -1.0e20;

   for( i = 0; i < NV; i++ ) {
       Xmin = MIN( Xmin, x[i] );
       Ymin = MIN( Ymin, y[i] );
       Zmin = MIN( Zmin, z[i] );

       Xmax = MAX( Xmax, x[i] );
       Ymax = MAX( Ymax, y[i] );
       Zmax = MAX( Zmax, z[i] );
       }
fprintf( stderr, "%g %g %g %g %g %g\n", Xmin,Xmax,Ymin,Ymax,Zmin,Zmax);

/*
   read_texture();
*/

   if ( !zbf_open( 384, 288 ) )
   {
       fprintf( stderr, "jee\n" );
       exit( 0 );
   }

   usr_backface( 1 );

   zbf_zclear( );

   lgt_shadows(TRUE);
   lmd_set_lmodel( LMD_LMODEL_SHADOW_PASS );

   trs_perspective(60.0,1.33,1.0,50.0);
   trs_lookat(0.0,0.0,5.0,0.0,0.0,0.0,0.0);

   lgt_get_matrix_light(0);

   trs_push_matrix();
   trs_rotate(-70.0,'y');

   r=atof(argv[1]);
   trs_scale(r,r,r);
 
   E = e;

    for( i = 0; i < NE; i++ )
    {
        usr_bgnpolygon( );
        n = i;
        for( j = 0; j < en[n]; j++ )
        {
            k = N[10*n+j];
            l = E[10*n+j];
            usr_vertex( V3(x[l],y[l],z[l]) );
         }
        usr_endpolygon( );

        usr_bgnpolygon( );
        n = i;
        for( j = en[n]-1; j >= 0; j-- )
        {
            k = N[10*n+j];
            l = E[10*n+j];
            usr_vertex( V3(x[l],y[l],z[l]) );
        }
        usr_endpolygon( );
    }
    trs_pop_matrix();

    usr_bgnpolygon();
    usr_normal(V3(0.0,0.0,1.0));
    usr_vertex( V3(-10.0,-10.0,-6.0));
    usr_vertex( V3( 10.0,-10.0,-6.0));
    usr_vertex( V3( 10.0, 10.0,-6.0));
    usr_vertex( V3(-10.0, 10.0,-6.0));
    usr_endpolygon();

   lgt_get_shadow_map(0);
   zbf_zshow( );

#ifdef NOTDEF
   zbf_zclear( );

   trs_load_matrix(ident);
   trs_lookat(1.5,4.0,4.0,0.0,0.0,0.0,0.0);

   lgt_get_matrix_light(1);

   trs_push_matrix();
   trs_rotate(-70.0,'y');

   r=atof(argv[1]);
   trs_scale(r,r,r);
 
   E = e;

    for( i = 0; i < NE; i++ )
    {
        usr_bgnpolygon( );
        n = i;
        for( j = 0; j < en[n]; j++ )
        {
            k = N[10*n+j];
            l = E[10*n+j];
            usr_vertex( V3(x[l],y[l],z[l]) );
         }
        usr_endpolygon( );

        usr_bgnpolygon( );
        n = i;
        for( j = en[n]-1; j >= 0; j-- )
        {
            k = N[10*n+j];
            l = E[10*n+j];
            usr_vertex( V3(x[l],y[l],z[l]) );
        }
        usr_endpolygon( );
    }
    trs_pop_matrix();

    usr_bgnpolygon();
    usr_normal(V3(0.0,0.0,1.0));
    usr_vertex( V3(-10.0,-10.0,-6.0));
    usr_vertex( V3( 10.0,-10.0,-6.0));
    usr_vertex( V3( 10.0, 10.0,-6.0));
    usr_vertex( V3(-10.0, 10.0,-6.0));
    usr_endpolygon();

   lgt_get_shadow_map(1);
   zbf_zshow( );

#endif

   lmd_set_lmodel( lmodel );
   lgt_ambient_level(V3(0.2,0.2,0.2));

   usr_color( V3(0.0,0.0,0.0));
   zbf_clear( );
   zbf_zclear( );

/*
   zbf_set_user_functions( NULL, torrance_sparrow );
   zbf_set_user_functions( NULL, bump_mapping );
   atm_linear_fog( -5.0, 17.0, V3(0.7,0.7,0.7) );
*/

   usr_material_alpha(1.0);
   usr_material_ambient(V3(1.0,1.0,0.8));
   usr_material_diffuse(V3(1.0,1.0,0.8));
   usr_material_specular(V3(0.88,0.87,0.87),60.0);

   for( i = 0; i < 16; i++ )
    {
       R[i] = CM[i][0];
       G[i] = CM[i][1];
       B[i] = CM[i][2];
       usr_map_color(i,R[i]/255.0,G[i]/255.0,B[i]/255.0);
   }

   if ( cflag )
   {
       txr_load_texture(128,128,R,G,B);
   }

   trs_load_matrix(ident);
   trs_perspective(32.0,1.33,1.0,50.0);
   trs_lookat(0.0,0.0,8.0,0.0,0.0,0.0,0.0);

   lgt_get_matrix_object(0);
   lgt_get_matrix_object(1);

   lgt_define_light(0,
                     0.0,0.0,5.0,1.0,
                     0.0,0.0,0.0,0.0,
                    V3(0.9,0.9,0.9));
   lgt_light_onoff(0,LGT_LIGHT_ON);

#ifdef NOTDEF
   lgt_define_light(1,
                     1.5,4.0,4.0,1.0,
                     0.0,0.0,0.0,0.0,
                    V3(1.0,1.0,1.0));
   lgt_light_onoff(1,LGT_LIGHT_ON);
#endif

   trs_push_matrix();
   trs_rotate(-70.0,'y');

   r=atof(argv[1]);
   trs_scale(r,r,r);

   trs_matrix_mode( TRS_MATRIX_VIEWING );
   trs_get_matrix( VM );
 
   E = e;

   for( i = 0; i < NE; i++ ) {
       md[i] = 0.0;
       for( j = 0; j < en[i]; j++ ) {
           l = E[10*i+j];
           md[i] +=x[l]*VM[0][2]+y[l]*VM[1][2]+z[l]*VM[2][2]+VM[3][2];
           }
       md[i] /= en[i];
       mi[i] = i;
       }

   sort( NE, md, mi );

   fprintf( stderr, "Read OK! now we go...\n" );

   if ( lines ) {
       usr_material_alpha(1.0);
       fprintf( stderr, " converting lines..." );
       E = e;

       usr_color_index( 0.0 );
       usr_color( V3(1.0, 0.0, 0.0) );

       for( i = 0; i < NE; i++ )
       {
           k = mi[i];
           usr_bgnline( );
           for( j = 0; j < en[k]; j++ ) {
               l = E[10*k+j];
               usr_vertex( V3(x[l],y[l],z[l]) );
               }
           l = E[10*k];
           usr_vertex( V3(x[l],y[l],z[l]) );
           usr_endline( );
       }

       usr_color_index( 15.0 );
       usr_material_alpha(1.0);

   }

#ifdef NOTDEF
   usr_color_index(15.0);
   usr_color(V3(1.0,0.3,0.1));
#endif

   fprintf( stderr, " converting polygons..." );
   T = 0.0;


/*
*/
   lmd_add_lmodel_interpolant( VERTEX_MATERIAL_ALPHA );
   lmd_add_lmodel_interpolant( VERTEX_ORIG_COORD_X );
   lmd_add_lmodel_interpolant( VERTEX_ORIG_COORD_Y );
   lmd_add_lmodel_interpolant( VERTEX_ORIG_COORD_Z );
   usr_color_material(LMD_COLOR_AMBIENT_AND_DIFFUSE);

   for( i = 0; i < NE; i++ )
   {
       usr_bgnpolygon( );

       n = mi[i];
       for( j = 0; j < en[n]; j++ )
       {
           k = N[10*n+j];
           l = E[10*n+j];

#ifdef NOTDEF
           if ( mat[n] == 8 )
           {
               usr_color(V3(0.8,0.8,0.8));
           } else
               usr_color(V3(0.8,0.3,0.2));
#endif

           if ( cflag )
           {
               float xx,yy;
               usr_texture( V3(5*(x[l]/2+0.5),5*(y[l]/2+0.5),0.0) );
           }

           if ( lmodel > LMD_LMODEL_NOLIGHTS )
           {
               usr_normal( V3(nx[k],ny[k],nz[k]) );
           }

           usr_vertex( V3(x[l],y[l],z[l]) );
       }
       usr_endpolygon( );

       usr_bgnpolygon( );

       n = mi[i];
       for( j = en[n]-1; j >= 0; j-- )
       {
           k = N[10*n+j];
           l = E[10*n+j];

           if ( cflag )
           {
               usr_texture( V3(5*(x[l]/2+0.5),5*(y[l]/2+0.5),0.0) );
           }

           if ( lmodel > LMD_LMODEL_NOLIGHTS )
           {
               usr_normal( V3(-nx[k],-ny[k],-nz[k]) );
           }

           usr_vertex( V3(x[l],y[l],z[l]) );
       }
       usr_endpolygon( );
   }

    trs_pop_matrix();

    usr_material_alpha(1.0);
    usr_material_ambient(V3(0.75,0.65,0.45));
    usr_material_diffuse(V3(0.75,0.65,0.45));
    usr_material_specular(V3(0.93,0.69,0.7),0.0);
 
    usr_bgnpolygon();
    usr_normal(V3(0.0,0.0,1.0));
    usr_vertex(V3(-10.0,-10.0,-6.0));
    usr_vertex(V3( 10.0,-10.0,-6.0));
    usr_vertex(V3( 10.0, 10.0,-6.0));
    usr_vertex(V3(-10.0, 10.0,-6.0));
    usr_endpolygon();

    fprintf( stderr, "\npolygons:%d, triangles: %d, %g seconds\n", ZBF_Pcount, ZBF_Tcount, T );

    fprintf( stderr, " gonna show it for ya...\n" );
    zbf_show( );

    zbf_close( );
}

sort( int n, FLOAT *oa, int *ob )
{
    int i;
    int j;
    int l;

    int ir;
    int rb;

    float ra;

    --oa; --ob;  /* sorting uses indexes from 1..n */

    l = ( n >> 1 ) + 1;
    ir = n;

    for( ;; ) {

        if ( l > 1 ) {
            ra = oa[--l];
            rb = ob[l];
        } else {
            ra = oa[ir];
            rb = ob[ir];
            oa[ir] = oa[1];
            ob[ir] = ob[1];
            if ( --ir == 1 ) {
                oa[1] = ra;
                ob[1] = rb;
                return;
                }
            }

        i = l;
        j = l << 1;

        while( j <= ir ) {
            if ( j < ir && oa[j] < oa[j + 1] ) {
                j++;
                }
            if ( ra < oa[j] ) {
                oa[i] = oa[j];
                ob[i] = ob[j];
                j += ( i = j );
            } else {
                j = ir + 1;
                }
            }

        oa[i] = ra;
        ob[i] = rb;
        }
}
