/* samp4.c */

# include <stdio.h>
# include <math.h>
# include "nanzan.h"

#define MAX 100
typedef struct {
  int n;
  double z;
} Sort3d;

double theta(int i,double x[][4],double y[][4],double z[][4])
{
    double xc,yc,zc, n1,n2,ret;
    double xl = 10, yl = -10, zl = -10;
    xc=(y[i][1]-y[i][0])*(z[i][3]-z[i][0])-
	(z[i][1]-z[i][0])*(y[i][3]-y[i][0]);
    yc=(z[i][1]-z[i][0])*(x[i][3]-x[i][0])-
	(x[i][1]-x[i][0])*(z[i][3]-z[i][0]);
    zc=(x[i][1]-x[i][0])*(y[i][3]-y[i][0])-
	(y[i][1]-y[i][0])*(x[i][3]-x[i][0]);
    n1 = xl*xc + yl*yc + zl*zc;
    n2 = sqrt(xl*xl + yl*yl + zl*zl) * sqrt(xc*xc + yc*yc + zc*zc);
    if ( n2 < 0.00001 ) return 0;
    ret = n1/n2;
    if ( ret > 1.0 ) return 0;
    if ( ret < -1.0 ) return 3.141592;
    return acos(ret);
}

double lambert(double r)
{
    double ret;
    ret = -cos(r);
    if ( ret <= 0.0 ) ret = 0;
    return ret;
}

void Draw( int max, double x[][4],double y[][4],double z[][4], Sort3d sor[] )
{
    int i, j, n, rgb; double l = -1000; XPoint points[4]; XColor xcol;
    _XSetBlack;
    _XFillRectangle( 0,0, 500,500 );
    for( i=0; i<max; i++) {
	n = sor[i].n;
	for( j=0; j<4; j++) {
	    points[j].x = (short)( x[n][j] * l / (z[n][j]+l) ) + 250;
	    points[j].y = -(short)( y[n][j] * l / (z[n][j]+l) ) + 250;
	}
    	rgb = ((int)( lambert(theta(n,x,y,z)) * 50))*1000+15000;
	xcol.red = xcol.green = xcol.blue = rgb;
	_XAllocColor( &xcol );
	_XSetForeground( xcol.pixel );
	_XFillPolygon( points, 4, Convex, CoordModeOrigin );
    }
}

void Sort(int max, Sort3d sor[], double x[][4], double y[][4], double z[][4])
{
    int i, j, t; double d;
    for( i=0; i<max; i++ ) {
	sor[i].n = i;
	sor[i].z = ( z[i][0] + z[i][1] + z[i][2] + z[i][3] ) / 4;
    }
    for( i=1; i<max; i++ ) {
	for( j = i; j >= 1 && sor[j-1].z > sor[j].z; j-- ) {
	    t = sor[j].n;
	    sor[j].n = sor[j-1].n;
	    sor[j-1].n = t;
	    d = sor[j].z;
	    sor[j].z = sor[j-1].z;
	    sor[j-1].z = d;
	}
    }
}

# define BUNKATSU 3

int MakeData(double x[][4], double y[][4], double z[][4])
{
    int i, j, n; double r, x1,x2, y1,y2, z1,z2;
    static double x2d[8] = { 196, 169, 131, 103, 103, 131, 169, 196 };
    static double y2d[8] = {  19,  46,  46,  19, -19, -46, -46, -19 };
    n = 0; r = 3.14159265*2/BUNKATSU;
    for ( i=0; i<8; i++ ) {
	if ( i == 7 ) {
	    x1 = x2d[i]; y1 = y2d[i]; x2 = x2d[0]; y2 = y2d[0];
	} else {
	    x1 = x2d[i]; y1 = y2d[i]; x2 = x2d[i+1]; y2 = y2d[i+1];
	}
	z1 = z2 = 0;
	for ( j=0; j<BUNKATSU; j++ ) {
	    x[n][0] = x1; y[n][0] = y1; z[n][0] = z1;
	    x[n][3] = x2; y[n][3] = y2; z[n][3] = z2;
	    x[n][2] = x2 * cos(r) + z2 * sin(r); y[n][2] = y2;
	    z[n][2] = -x2 * sin(r) + z2 * cos(r);
	    x[n][1] = x1 * cos(r) + z1 * sin(r); y[n][1] = y1;
	    z[n][1] = -x1 * sin(r) + z1 * cos(r);
	    x1 = x[n][1]; y1 = y[n][1]; z1 = z[n][1];
	    x2 = x[n][2]; y2 = y[n][2]; z2 = z[n][2];
	    n++;
	}
    }
    return(n);
}

main()
{
    int max; double alpha; double beta; double gamma; int i, j;
    double x2, x3, x4, y2, y3, y4, z2, z3, z4;
    double x[MAX][4]; double y[MAX][4]; double z[MAX][4];
    Sort3d sor[MAX];

    _XOpen;
    max = MakeData(x,y,z);
    Sort(max,sor,x,y,z); Draw(max,x,y,z,sor);
    while(1) {
	usleep(100000);
	alpha = (double)3.141592/50; beta = 0; gamma = 0;
	for( i=0; i<max; i++ ) {
	    for( j=0; j<4; j++ ) {
	      x2 = x[i][j];
	      y2 = y[i][j] * cos(alpha) - z[i][j] * sin(alpha);
	      z2 = y[i][j] * sin(alpha) + z[i][j] * cos(alpha);
	      x3 = x2 * cos(beta) + z2 * sin(beta);
	      y3 = y2;
	      z3 = -x2 * sin(beta) + z2 * cos(beta);
	      x4 = x3 * cos(gamma) - y3 * sin(gamma);
	      y4 = x3 * sin(gamma) + y3 * cos(gamma);
	      z4 = z3;
	      x[i][j] = x4; y[i][j] = y4; z[i][j] = z4;
	    }
	}
	Sort(max,sor,x,y,z); Draw(max,x,y,z,sor);
	_XFlush;
    }
}

/* End of file --------------------- */
