#include <stdio.h>
#include <gl/gl.h>
#include <device.h>
#include <math.h>
/* #include <UTILITY.h>
*/

#define GREEN1	9

Matrix	rotmat ;

#define	NUMP	4
double	lpos[NUMP][3] ;
double	avpos[3] ;

struct	linkrec {
	double	x, y, z ;
	double	r00, r01, r02 ;
	double	r10, r11, r12 ;
	double	r20, r21, r22 ;
	double	cx, cy, cz ;
	}	jrnpos[5] ;


extern	int	threeview ;

int	mode ;
int	mx, my, mz ;
double	mvx, mvy, mvz ;
double	vx, vy, vz ;
double	bvx, bvy, bvz ;
extern	int	numlinks ;
long window_id;

#define	NUMFACES  8		/* number of faces on tube  */
#define	NUMARENAFACES  32	/* number of faces on arena */

FILE	*jrnfp ;

jrngraphinit()
{
double	inc, angle, radius ;
double	x, x1, y, y1 ;
double	x2, x3, y2, y3 ;
int	j, i, colr ;
long    xpmax, ypmax;

/* void make_bleacher_obj (); */

    keepaspect(1, 1);
    xpmax = getgdesc(GD_XPMAX);
    ypmax = getgdesc(GD_YPMAX);
    prefposition(xpmax/2 - xpmax/4, xpmax/2 + xpmax/4,
                 ypmax/2 - ypmax/4, ypmax/2 + ypmax/4);
    window_id = winopen("worm");
    doublebuffer();
    gconfig();
    cursoff();
    qdevice( KEYBD );
    qdevice( LEFTMOUSE );
    qdevice( MIDDLEMOUSE );
    qdevice( RIGHTMOUSE );

/*  mapcolor( BLUE,      0,   0, 100 );
    mapcolor( RED,     150,   0,   0 );
    mapcolor( GREEN,     0, 150,   0 );
    mapcolor( GREEN1,    0, 100,   0 );
    mapcolor( CYAN,      0, 150, 150 );
    mapcolor( MAGENTA, 150,   0, 150 );
    mapcolor( YELLOW,  150, 150,   0 );
    mapcolor( WHITE,   140, 140, 140 );
*/
    frontbuffer(TRUE);
    color(BLACK);
    clear();
    frontbuffer(FALSE);
    backface(TRUE);
    swapinterval(6); /* Minimum time between buffer swaps is 6 (/60?) s */

    bvx = 0.0 ;
    bvy = 0.0 ;
    bvz = 15.0 ;
    mvx = 0.0 ;
    mvy = 0.0 ;
    mvz = 0.0 ;

/*  for( i = 0 ; i < 20 ; i++ )  */
    for( i = 0 ; i < 20 ; i++ )
    {
	mapcolor( i+10,    0, i*10, i*10 ); /* 10..29 are turquoises */
	mapcolor( i+30, i*10, i*10,    0 ); /* 30..49 are yellows */
	mapcolor( i+50, i*10, i*10, i*10 ); /* 50..69 are greys */
    }

    radius = 0.1 ;
    inc = (2.0 * M_PI) / (double)NUMFACES ;

    /* make_bleacher_obj (radius, inc); */

    for( j = 1 ; j <= numlinks ; j++ )
    {
	angle = 5.0 * M_PI/4.0 ;
	makeobj( j );
	colr = 69 ;
	for( i = 0 ; i < NUMFACES ; i++ )
	{
	    x  = cos( angle )	* radius ;
	    x1 = cos( angle + inc ) * radius ;
	    y  = sin( angle )	* radius ;
	    y1 = sin( angle + inc ) * radius ;
	    color( colr );
	    pmv( x1, y1, 0.0 );
	    pdr( x1, y1, 0.35 );
	    pdr( x, y, 0.35 );
	    pdr( x, y, 0.0 );
	    pclos();
	    color( j );
	    pmv( x1, y1, 0.35 );
	    pdr( x1, y1, 0.65);
	    pdr( x, y, 0.65);
	    pdr( x, y, 0.35 );
	    pclos();
	    color( colr );
	    pmv( x1, y1, 0.65);
	    pdr( x1, y1, 1.0 );
	    pdr( x, y, 1.0 );
	    pdr( x, y, 0.65);
	    pclos();
	    if( i >= NUMFACES/6 )
		colr = 40 ;
	    angle += inc ;
	}
	closeobj( j );
	angle = 5.0 * M_PI/4.0 ;
	makeobj( j+10 );
	colr = 69 ;
	for( i = 0 ; i < NUMFACES ; i++ )
	{
	    x  = cos( angle )	    * radius ;
	    x1 = cos( angle + inc ) * radius ;
	    x2 = cos( angle )       * (radius * 0.7071) ;
	    x3 = cos( angle + inc ) * (radius * 0.7071) ;

	    y  = sin( angle )	    * radius ;
	    y1 = sin( angle + inc ) * radius ;
	    y2 = sin( angle )       * (radius * 0.7071) ;
	    y3 = sin( angle + inc ) * (radius * 0.7071) ;

	    color( colr );
	    pmv(  x1,  y1, 1.0 );
	    pdr(  x3,  y3, 1.07071 );
	    pdr(  x2,  y2, 1.07071 );
	    pdr(   x,   y, 1.0 );
	    pclos();

	    pmv(  x3,  y3, 1.07071 );
	    pdr( 0.0, 0.0, 1.10 );
	    pdr(  x2,  y2, 1.07071 );
	    pclos();

	    pmv(   x,   y,  0.0 );
	    pdr(  x2,  y2, -0.07071 );
	    pdr(  x3,  y3, -0.07071 );
	    pdr(  x1,  y1,  0.0 );
	    pclos();

	    pmv(  x2,  y2, -0.07071 );
	    pdr( 0.0, 0.0, -0.10 );
	    pdr(  x3,  y3, -0.07071 );
	    pclos();

	    if( i >= NUMFACES/6 )
		colr = 40 ;
	    angle += inc ;
	}
	closeobj( j+10 );
    }
    rotmat[0][3] = 0.0 ;
    rotmat[1][3] = 0.0 ;
    rotmat[2][3] = 0.0 ;
    rotmat[3][0] = 0.0 ;
    rotmat[3][1] = 0.0 ;
    rotmat[3][2] = 0.0 ;
    rotmat[3][3] = 1.0 ;
}

jrngraphend()
{
/***textinit();  *** removed Oct 10 90 */
/***gexit();     *** removed Oct 10 90 */
    curson();
    winclose(window_id);
    system("makemap"); /* Added Oct 6 90 */
}



drawjournal( name )
char	*name ;
{
int	rdd, j, i, link;
double   pos[3] ;

    if( name )
	jrnfp = fopen( name, "r" );
    else
	jrnfp = fopen( "journal", "r" );
    rdd = 1 ;
    while( 1 )
    {
	for( i = 0 ; i < 3; i++ )
	    pos[i] = 0.0 ;
	for( link = 1 ; link <= numlinks ; link++ )
	{
	    if(!fread((char *)&jrnpos[link], sizeof(struct linkrec), 1, jrnfp ))
	    {
		fclose( jrnfp );
		return ;
	    }
	    pos[0] += jrnpos[link].cx ;
	    pos[1] += jrnpos[link].cy ;
	    pos[2] += jrnpos[link].cz ;
	}
	if( rdd )
	{
	  for( i = 0 ; i < NUMP ; i++ )
	    for( j = 0 ; j < 3 ; j++ )
		lpos[i][j] = pos[j] ;
	  rdd = 0 ;
	}
	if( draw_bkgrnd1( 1, pos ) )
	    drawjournal1();
	if( draw_bkgrnd1( 2, pos ) )
	    drawjournal1();
	if( draw_bkgrnd1( 3, pos ) )
	    drawjournal1();

	swapbuffers();
    }
}


drawjournal1()
{
int	i, j, link;
double	dist[5] ;
int	order[5] ;
double	dfx, dfy, dfz ;

    for( link = 1 ; link <= numlinks ; link++ )
    {
	order[link] = link ;
	dfx = ( jrnpos[link].cx - vx ) * ( jrnpos[link].cx - vx ) ;
	dfy = ( jrnpos[link].cy - vy ) * ( jrnpos[link].cy - vy ) ;
	dfz = ( jrnpos[link].cz - vz ) * ( jrnpos[link].cz - vz ) ;
	dist[link] = sqrt( dfx + dfy + dfz );
    }

    for( link = 1 ; link < numlinks ; link++ )
    {
	if( dist[link] < dist[link+1] )
	{
	    dfx = dist[link] ; dist[link] = dist[link+1] ; dist[link+1] = dfx ;
	    i = order[link] ; order[link] = order[link+1] ; order[link+1] = i ;
	}
    }
    
    for( link = 1 ; link < numlinks ; link++ )
    {
	if( dist[link] < dist[link+1] )
	{
	    dfx = dist[link] ; dist[link] = dist[link+1] ; dist[link+1] = dfx ;
	    i = order[link] ; order[link] = order[link+1] ; order[link+1] = i ;
	}
    }
    for( link = 1 ; link <= numlinks ; link++ )
    {
	j = order[link] ;
	pushmatrix();
	translate( jrnpos[j].x, jrnpos[j].y, jrnpos[j].z );
	dorotjrn( j );
	multmatrix(rotmat);
	callobj( j + 10 );
	callobj( j );
	popmatrix();
/*
	sginap(1);
*/
    }
}


dorotjrn( link )
int	link ;
{
    rotmat[0][0] = jrnpos[link].r00 ;
    rotmat[0][1] = jrnpos[link].r10 ;
    rotmat[0][2] = jrnpos[link].r20 ;

    rotmat[1][0] = jrnpos[link].r01 ;
    rotmat[1][1] = jrnpos[link].r11 ;
    rotmat[1][2] = jrnpos[link].r21 ;

    rotmat[2][0] = jrnpos[link].r02 ;
    rotmat[2][1] = jrnpos[link].r12 ;
    rotmat[2][2] = jrnpos[link].r22 ;
}



draw_bkgrnd1( arg, pos )
int	arg ;
double	pos[3] ;
{
short	val ;
int	j, i ;
double	dist;

  if( !threeview )
  {
    if( arg != 1 )
	return(0);
    if( qtest() )
    {
        switch( qread( &val ) )
	{
	case LEFTMOUSE :
	    if( val == 1 )
	    {
		mx = getvaluator( MOUSEX );
		mode = LEFTMOUSE ;
	    }
	    else
	    {
		bvx = bvx + mvx ;
		mvx = 0.0 ;
	        mode = 0 ;
	    }
	    break ;
	case MIDDLEMOUSE :
	    if( val == 1 )
	    {
		my = getvaluator( MOUSEX );
		mode = MIDDLEMOUSE ;
	    }
	    else
	    {
		bvy = bvy + mvy ;
		mvy = 0.0 ;
	        mode = 0 ;
	    }
	    break ;
	case RIGHTMOUSE :
	    if( val == 1 )
	    {
		mz = getvaluator( MOUSEX );
		mode = RIGHTMOUSE ;
	    }
	    else
	    {
		bvz = bvz + mvz ;
		mvz = 0.0 ;
	        mode = 0 ;
	    }
	    break ;
	}
    }
    switch( mode )
    {
    case 0 :
    break ;
    case LEFTMOUSE :
    	mvx = (getvaluator( MOUSEX ) - mx) /20.0 ; 
	break ;
    case MIDDLEMOUSE :
	mvy = (getvaluator( MOUSEX ) - my) /20.0 ; 
	break ;
    case RIGHTMOUSE :
	mvz = (getvaluator( MOUSEX ) - mz) /20.0 ; 
	break ;
    }
/*  viewport(0,1023,0,767); */
    vx = bvx + mvx ;
    vy = bvy + mvy ;
    vz = bvz + mvz ;
    dist = sqrt( vx * vx + vy * vy + vz * vz );
    if( dist > 20.0 )
    {
	dist /= 20.0 ;
	if( mode )
	{
	    vx /= dist ;
	    vy /= dist ;
	    vz /= dist ;
	}
	else
	{
	    bvx /= dist ;
	    bvy /= dist ;
	    bvz /= dist ;
	}
    }

/*  window(  -5.5, 5.5, -2.0, 9.0, 10.0, 400.0 );
*/
    window( -5.0, 5.0, -5.0, 5.0, 10.0, 400.0 );
    lookat( vx, vy, vz,   0.0, 0.0, 0.0,  0 );
/*    rotate( -900, 'x' );	/* no isotrak */
/*    rotate( -900, 'z' );	/* no isotrak */
  }
  else
  {
    switch( arg )
    {	
    case 1 :
	for( i = 0 ; i < 3 ; i++ )
	    pos[i] /= 3.0 ;
	for( i = NUMP-1 ; i > 0 ; i-- )
	    for( j = 0 ; j < 3 ; j++ )
		lpos[i][j] = lpos[i-1][j] ;

	for( i = 0 ; i < 3 ; i++ )
	    lpos[0][i] = pos[i] ;
	for( i = 0 ; i < 3 ; i++ )
	{
	    avpos[i] = 0.0 ;
	    for( j = 0 ; j < NUMP ; j++ )
		avpos[i] += lpos[j][i] ;
	}
	for( i = 0 ; i < 3 ; i++ )
	    avpos[i] /= NUMP.0 ;
	vx = avpos[0] +5.0 ;
	vy = avpos[1] -2.0 ;
	vz = avpos[2] +7.0 ;
	viewport( 0, 400, 8, 484 );
	perspective(  400, 400.0 / (484.0 -8.0), 2.0, 400.0 );
	lookat( vx, vy, vz,   avpos[0], avpos[1], avpos[2],  600 );
	break ;
    case 2 :
	vx = 0.0 ;
	vy = 0.0 ;
	vz = 15.0 ;
	viewport( 401, 640, 8, 246 );
	perspective(  400, (640.0 -401.0) / (264.0 -8.0), 2.0, 400.0 );
	lookat( vx, vy, vz,   0.0, 0.0, 0.0,  0 );
	break ;
    case 3 :
	vx = avpos[0] ;
	vy = -6.0 ;
	vz = avpos[2] +1.0 ;
	viewport( 401, 640, 247, 484 );
	perspective(  400, (640.0 -401.0)/(484.0 -247.0), 2.0, 400.0 );
/*
	lookat( vx, vy, vz,   0.0, 0.0, 0.0,  0 );
*/
	lookat( vx, vy, vz,   avpos[0], 0.0, avpos[2],  0 );
	break ;
    }
  }
  drawarena();
  return(1);
}


drawarena()
{
int	i ;
double	radius, angle, inc, x, y ;

    color(BLACK);
    clear();
    angle = 0.0 ;
    radius = 5.0 ;
    inc = (2.0 * M_PI) / (double)NUMARENAFACES ;
    color( BLUE );
    pmv( radius, 0.0, 0.0 ) ;
    for( i = 1 ; i < NUMARENAFACES ; i++ )
    {
	angle += inc ;
	x  = cos( angle ) * radius ;
	y  = sin( angle ) * radius ;
	pdr( x, y, 0.0 );
    }
    pclos ();

    move (radius, 0.0, 0.5);
    color (WHITE);
    angle = 0.0;
    for( i = 1 ; i <= NUMARENAFACES ; i++ )
    {
	angle += inc ;
	x  = cos( angle ) * radius ;
	y  = sin( angle ) * radius ;
        draw (x, y, 0.5);
    }

    move (radius, 0.0, 1.0);
    angle = 0;
    for( i = 1 ; i <= NUMARENAFACES ; i++ )
    {
	angle += inc ;
	x  = cos( angle ) * radius ;
	y  = sin( angle ) * radius ;
        draw (x, y, 1.0);
    }


    color( GREEN1 );
    for( angle = 0.0, i = 1 ; i <= NUMARENAFACES ; i++ )
    {
	angle += inc ;
	x  = cos( angle ) * radius ;
	y  = sin( angle ) * radius ;
	move( x, y, 0.0 );
	draw( x, y, 1.0 );
    }


    color( GREEN );
    move( 0.0, 0.0, 0.0 );
    draw( 1.0, 0.0, 0.0 );
    cmov( 1.0, 0.0, 0.0 );
    charstr( "x" );
    move( 0.0, 0.0, 0.0  );
    draw( 0.0, 1.0, 0.0  );
    cmov( 0.0, 1.0, 0.0  );
    charstr( "y" );
    move( 0.0, 0.0, 0.0  );
    draw( 0.0, 0.0, 1.0  );
    cmov( 0.0, 0.0, 1.0  );
    charstr( "z" );
}


/*
void make_bleacher_obj (arena_radius, arena_angle) {
double arena_radius, arena_angle;
{
int nbr_rows;
double bleacher_angle;
int cntr;
double x, y, z;
double bleacher_width, bleacher_depth;
double end_radius, start_radius, radius;
double start_angle, end_angle, angle;

bleacher_angle = arena_angle - 10;
bleacher_width = bleacher_depth = 0.01;

nbr_rows = 10;

for (cntr = nbr_rows; cntr >= 1; cntr--) {
   z = cntr * bleacher_depth;
   color (cntr);

   start_radius = arena_radius + bleacher_width + (cntr - 1) * bleacher_width;
   end_radius = arena_radius + bleacher_width + cntr * bleacher_width;

   for (radius = start_radius; radius <= end_radius; radius += 0.1) {
      
      start_angle = 0 - bleacher_angle / 2;
      end_angle = -1 * start_angle;

      for (angle = start_angle, angle <= end_angle; angle++) {
         x = cos (angle) * radius;
         y = sin (angle) * radius;
         pnt (x, y, z);
      }
   }
}
}
*/
