/****************************************************************************/
/*                                                                          */
/*  VolVis is a volume visualization system for investigating, manipulating */
/*  and rendering geometric and volumetric data.                            */
/*                                                                          */
/*  Copyright (C) 1993 by the Research Foundation of the State University   */
/*                            of New York                                   */
/*                                                                          */
/*  This program is free software; you can redistribute it and/or modify    */
/*  it under the terms of the GNU General Public License as published by    */
/*  the Free Software Foundation; either version 1, or (at your option)     */
/*  any later version.                                                      */
/*                                                                          */
/*  This program is distributed in the hope that it will be useful,         */
/*  but WITHOUT ANY WARRANTY; without even the implied warranty of          */
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           */
/*  GNU General Public License for more details.                            */
/*                                                                          */
/*  You should have received a copy of the GNU General Public License       */
/*  along with this program; if not, write to the Free Software             */
/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
/*                                                                          */
/*  For information on VolVis, contact us at:                               */
/*                                                                          */
/*                volvis@cs.sunysb.edu                         (email)      */
/*                                                                          */
/*                Lisa Sobierajski & Ricardo Avila             (US Mail)    */
/*                Department of Computer Science                            */
/*                State University of New York at Stony Brook               */
/*                Stony Brook, New York  11794-4400                         */
/*                                                                          */
/****************************************************************************/




/*
 *			File: MOTIF_xgrph_nav_proj.c
 *		      Author: Lisa Sobierajski 
 *			Date: 07/12/93
 *		 Description: MOTIF/X Drawing Routines For The Navigator 
 *			      Projection Drawing Areas
 *	Modification History:
 *
 *		Who?		When?		Why?
 *	--------------------------------------------------------------------
 *
 */

#include <stdio.h>
#include <math.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/keysym.h>
#include <Xm/Xm.h>
#include <Xm/DrawingA.h>

#include "C_volvis.h"
#include "MOTIF_windefs.h"
#include "C_navigator.h"
#include "C_nav_draw.h"



Widget create_pj_drawing_area( parent )
Widget parent;
{
	extern	C_NavInfo	nav_info;

	void			nav_key_press();
	Arg			args[20];	/* Argument List */
	int			n;
	int			image_size;
	extern C_View		view;
	extern void		nav_pj_expose_CB();
	extern void		nav_pj_resize_CB();
	extern void		nav_pj_input_CB();

	/********************************************************/
	/*      Create a Drawing Area For Wireframe Projection  */
	/********************************************************/
	n=0;
	XtSetArg( args[n], XmNx, 0 );
	XtSetArg( args[n], XmNy, 0 );
	XtSetArg( args[n], XmNwidth, view.width_pixels ); n++;
	XtSetArg( args[n], XmNheight, view.height_pixels ); n++;
	XtSetArg( args[n], XmNsensitive, True ); n++;
	nav_info.pj_win_info.drawing_area = 
		XmCreateDrawingArea( parent, "nav_drawing_area", args, n );

	XtManageChild( nav_info.pj_win_info.drawing_area );

	XtAddCallback( nav_info.pj_win_info.drawing_area, 
			XmNexposeCallback, nav_pj_expose_CB, NULL );

	XtAddCallback( nav_info.pj_win_info.drawing_area, 
			XmNresizeCallback, nav_pj_resize_CB, NULL );

	nav_info.pj_win_info.gc = NULL;
	nav_info.pj_win_info.pixmap = NULL;

	return( nav_info.pj_win_info.drawing_area );
}

Widget create_wf_drawing_area( parent )
Widget	parent;
{
	extern	C_NavInfo	nav_info;

	void			nav_key_press();
	Arg			args[20];	/* Argument List */
	int			n;
	int			image_size;
	extern C_View		view;
	extern void		nav_wf_expose_CB();
	extern void		nav_wf_resize_CB();


	/********************************************************/
	/*      Create a Drawing Area For Wireframe Projection  */
	/********************************************************/
	n=0;
	XtSetArg( args[n], XmNx, 0 );
	XtSetArg( args[n], XmNy, 0 );
	XtSetArg( args[n], XmNwidth, nav_info.wf_win_info.view.width_pixels ); 
	n++;
	XtSetArg( args[n], XmNheight, nav_info.wf_win_info.view.height_pixels); 	n++;
	XtSetArg( args[n], XmNsensitive, True ); n++;
	nav_info.wf_win_info.drawing_area = 
		XmCreateDrawingArea( parent, "nav_drawing_area", args, n );

	XtManageChild( nav_info.wf_win_info.drawing_area );

	XtAddCallback( nav_info.wf_win_info.drawing_area, 
			XmNexposeCallback, nav_wf_expose_CB, NULL );

	XtAddCallback( nav_info.wf_win_info.drawing_area, 
			XmNresizeCallback, nav_wf_resize_CB, NULL );


	nav_info.wf_win_info.gc = NULL;
	nav_info.wf_win_info.pixmap = NULL;

	return( nav_info.wf_win_info.drawing_area );
}

Widget create_wf_key_drawing_area( parent )
Widget	parent;
{
	extern	C_NavInfo	nav_info;

	void			nav_key_press();
	Arg			args[20];	/* Argument List */
	int			n;
	int			image_size;
	extern C_View		view;
	extern void		nav_wf_key_expose_CB();
	extern void		nav_wf_key_resize_CB();


	/********************************************************/
	/*      Create a Drawing Area For Wireframe Projection  */
	/********************************************************/
	n=0;
	XtSetArg( args[n], XmNx, 0 );
	XtSetArg( args[n], XmNy, 0 );
	XtSetArg( args[n], XmNwidth, nav_info.wf_key_win_info.width_pixels ); 
	n++;
	XtSetArg( args[n], XmNheight, nav_info.wf_key_win_info.height_pixels ); 	n++;
	XtSetArg( args[n], XmNsensitive, True ); n++;
	nav_info.wf_key_win_info.drawing_area = 
		XmCreateDrawingArea( parent, "nav_drawing_area", args, n );

	XtManageChild( nav_info.wf_key_win_info.drawing_area );

	XtAddCallback( nav_info.wf_key_win_info.drawing_area, 
			XmNexposeCallback, nav_wf_key_expose_CB, NULL );

	XtAddCallback( nav_info.wf_key_win_info.drawing_area, 
			XmNresizeCallback, nav_wf_key_resize_CB, NULL );


	nav_info.wf_key_win_info.gc = NULL;
	nav_info.wf_key_win_info.pixmap = NULL;

	return( nav_info.wf_key_win_info.drawing_area );
}


/************************************************************************/
/*									*/
/*			Navigator Projection Routines			*/
/*									*/
/************************************************************************/
void nav_pj_init()
{
	extern	C_NavInfo	nav_info;
	extern	C_World		world;
	extern  C_WindowDefs	window_defs;

	XGCValues		gcvalues;
	int			pixel;
	XColor			background_color;

	/**************************************/
	/* Create the GC for the drawing area */
	/**************************************/

	background_color.red = world.world_shade.bkgrnd_color.red;
	background_color.green = world.world_shade.bkgrnd_color.green;
	background_color.blue = world.world_shade.bkgrnd_color.blue;

        if ( window_defs.depth == 24 )
        {
                background_color.red *= 256;
                background_color.green *= 256;
                background_color.blue *= 256;
                pixel = C_Get_Pixel( background_color );
        }
        else if ( window_defs.depth == 8 )
        {
                pixel = window_defs.first_color_index +
                    C_Round(((float)(background_color.red)/63.75))*25 +
                    C_Round(((float)(background_color.green)/63.75))*5 +
                    C_Round(((float)(background_color.blue)/63.75));
        }

	if ( nav_info.pj_win_info.gc )
		XFreeGC( XtDisplay( nav_info.pj_win_info.drawing_area ),
			 nav_info.pj_win_info.gc );

	if ( nav_info.pj_win_info.pixmap )
		XFreePixmap( XtDisplay( nav_info.pj_win_info.drawing_area ),
			     nav_info.pj_win_info.pixmap );

	gcvalues.foreground = pixel;

	nav_info.pj_win_info.gc = XCreateGC(
		XtDisplay( nav_info.pj_win_info.drawing_area ),
		XtWindow( nav_info.pj_win_info.drawing_area ),
		GCForeground, &gcvalues );
	
	nav_info.pj_win_info.pixmap = XCreatePixmap(
		XtDisplay( nav_info.pj_win_info.drawing_area ),
                XtWindow( nav_info.pj_win_info.drawing_area ),
		nav_info.pj_win_info.width_pixels,
		nav_info.pj_win_info.height_pixels,
		window_defs.depth );

	/**************************/
	/* Clear The Color Buffer */
	/**************************/

	XFillRectangle(
		XtDisplay( nav_info.pj_win_info.drawing_area ),
		XtWindow( nav_info.pj_win_info.drawing_area ),
		nav_info.pj_win_info.gc,
		0, 0, nav_info.pj_win_info.width_pixels,
		nav_info.pj_win_info.height_pixels );


	
}

void nav_wf_init()
{
	extern	C_NavInfo	nav_info;
	extern	C_World		world;
	extern  C_WindowDefs	window_defs;

	XGCValues		gcvalues;
	int			pixel;
	XColor			background_color;

	/**************************************/
	/* Create the GC for the drawing area */
	/**************************************/
printf("in init\n");

	background_color.red = 0;
	background_color.green = 0; 
	background_color.blue = 0;

        if ( window_defs.depth == 24 )
        {
                background_color.red *= 256;
                background_color.green *= 256;
                background_color.blue *= 256;
                pixel = C_Get_Pixel( background_color );
        }
        else if ( window_defs.depth == 8 )
        {
                pixel = window_defs.first_color_index +
                    C_Round(((float)(background_color.red)/63.75))*25 +
                    C_Round(((float)(background_color.green)/63.75))*5 +
                    C_Round(((float)(background_color.blue)/63.75));
        }

	if ( nav_info.wf_win_info.gc )
		XFreeGC( XtDisplay( nav_info.wf_win_info.drawing_area ),
			 nav_info.wf_win_info.gc );

	if ( nav_info.wf_win_info.pixmap )
		XFreePixmap( XtDisplay( nav_info.wf_win_info.drawing_area ),
			     nav_info.wf_win_info.pixmap );

	gcvalues.foreground = pixel;

	nav_info.wf_win_info.gc = XCreateGC(
		XtDisplay( nav_info.wf_win_info.drawing_area ),
		XtWindow( nav_info.wf_win_info.drawing_area ),
		GCForeground, &gcvalues );
	
	nav_info.wf_win_info.pixmap = XCreatePixmap(
		XtDisplay( nav_info.wf_win_info.drawing_area ),
                XtWindow( nav_info.wf_win_info.drawing_area ),
		nav_info.wf_win_info.view.width_pixels,
		nav_info.wf_win_info.view.height_pixels,
		window_defs.depth );
printf("outta init\n");
}

void nav_wf_key_init()
{
	extern	C_NavInfo	nav_info;

	/************************************************/
	/*						*/
	/* 	Initialize The Wireframe Key Area 	*/
	/*						*/
	/************************************************/

printf("in wf init\n");
	/**************************************/
	/* Create the GC for the drawing area */
	/**************************************/

	/**************************/
	/* Clear The Color Buffer */
	/**************************/
printf("outta wf init\n");
}

void nav_clear_buffers( proj_type )
C_NavProjectionType	proj_type;	/* Selects Projection Type */
{
	extern	C_NavInfo	nav_info;
	extern	C_World		world;
	extern  C_WindowDefs	window_defs;
	
	GC			gc;
	Display			*display;
	Drawable		drawable;
	XGCValues		gcvalues;
	int			pixel;
	XColor			background_color;
	int			width;
	int			height;


	switch( proj_type )
	{
	  case C_NAV_PROJECTION:
	  case C_PARC_FRONT_PROJECTION:
	  case C_PARC_BACK_PROJECTION:
		gc = nav_info.pj_win_info.gc;
		display = XtDisplay( nav_info.pj_win_info.drawing_area );
		drawable = nav_info.pj_win_info.pixmap;
		width = nav_info.pj_win_info.width_pixels;
		height = nav_info.pj_win_info.height_pixels;
		break;
	  case C_NAV_WIREFRAME:
		gc = nav_info.wf_win_info.gc;
		display = XtDisplay( nav_info.wf_win_info.drawing_area );
		drawable = nav_info.wf_win_info.pixmap;
		width = nav_info.wf_win_info.view.width_pixels;
		height = nav_info.wf_win_info.view.height_pixels;
		break;
	  case C_NAV_WIREFRAME_KEY:
		break;
	}

	/**************************/
	/* Clear Color & Z Buffer */
	/**************************/
	switch( proj_type )
	{
		case C_NAV_PROJECTION:
			background_color.red = 
				world.world_shade.bkgrnd_color.red;
			background_color.green = 
				world.world_shade.bkgrnd_color.green;
			background_color.blue = 
				world.world_shade.bkgrnd_color.blue;
			break;
		case C_NAV_WIREFRAME:
		case C_NAV_WIREFRAME_KEY:
		case C_PARC_FRONT_PROJECTION:
		case C_PARC_BACK_PROJECTION:
			background_color.red = 0;
			background_color.green = 0;
			background_color.blue = 0;
			break;
	}


        if ( window_defs.depth == 24 )
        {
                background_color.red *= 256;
                background_color.green *= 256;
                background_color.blue *= 256;
                pixel = C_Get_Pixel( background_color );
        }
        else if ( window_defs.depth == 8 )
        {
                pixel = window_defs.first_color_index +
                    C_Round(((float)(background_color.red)/63.75))*25 +
                    C_Round(((float)(background_color.green)/63.75))*5 +
                    C_Round(((float)(background_color.blue)/63.75));
        }


	gcvalues.foreground = pixel;

	XChangeGC( display, gc, GCForeground, &gcvalues );
	

	/**************************/
	/* Clear The Color Buffer */
	/**************************/

	XFillRectangle( display, drawable, gc, 0, 0, width, height );


}

void nav_set_viewing( proj_type, nav_info, volume_num )
C_NavProjectionType	proj_type;	/* Selects Projection Type */
C_NavInfo		*nav_info;	/* Navigator Structure */
int			volume_num;	/* Volume Being Projected */
{
	extern	C_World		world;

	int 		i,j;
	long		xsize;
	long		ysize;
	float		aspect;
	float		near_plane;
	float		far_plane;
	float		closest;
	float		farthest;
	float		temp_close;
	float		temp_far;
	float		extra_dist;
	float		view_width;
	float		view_height;
	C_View		*view_ptr;
	C_Light		*light;
	C_FPosition	v_pos;
	C_FPosition	new_v_pos;
	C_Matrix	temp_matrix;
	C_Matrix	translate_matrix;
	C_Matrix	scale_matrix;
	


	extern C_View	view;
	extern void	C_distance_to_view();

	switch( proj_type )
	{
	   case C_NAV_PROJECTION:
	   case C_PARC_FRONT_PROJECTION:
	   case C_PARC_BACK_PROJECTION:
		aspect = (float)(nav_info->pj_win_info.width_pixels) / 
			 (float)(nav_info->pj_win_info.height_pixels);
		view_ptr = &view;
		break;
	   case C_NAV_WIREFRAME:
		view_ptr = &(nav_info->wf_win_info.view);
		break;
	   case C_NAV_WIREFRAME_KEY:
		view_ptr = NULL;
		break;
	}

	

	/************************************************************/
	/* Compute Distances To Near & Far Plane For Any Projection */
	/************************************************************/
	switch( proj_type )
	{
	   case C_NAV_WIREFRAME_KEY:
		closest  = 0.1;
		farthest = 2.0;
		break;
	   case C_NAV_PROJECTION:
	   case C_NAV_WIREFRAME:
		closest = C_BIG_FLOAT;
		farthest = -C_BIG_FLOAT;
		for( i=0; i<world.num_volumes; i++ )
		{
			C_distance_to_view( view_ptr, i, 
					    &temp_close, &temp_far);

			/* Computes Average Side Distance Divided By 4 */
			extra_dist = 
				(world.volume[i]->x_size_units +
				 world.volume[i]->y_size_units +
				 world.volume[i]->y_size_units)/12.0;

			temp_close = temp_close - extra_dist;
			temp_far = temp_far + extra_dist;

			if( temp_close < closest )
				closest = temp_close;

			if( temp_far > farthest )
				farthest = temp_far;
		}
		
		if( world.num_volumes == 0 )
		{
			closest  = 0.1;
			farthest = 2.0;
		}

		break;
	   case C_PARC_FRONT_PROJECTION:
	   case C_PARC_BACK_PROJECTION:
		C_distance_to_view( view_ptr, volume_num, &closest, &farthest );

		/* Comutes Average Side Distance Divided By 4 */
		extra_dist = 
			(world.volume[volume_num]->x_size_units +
			 world.volume[volume_num]->y_size_units +
			 world.volume[volume_num]->y_size_units)/12.0;

		closest = closest - extra_dist;
		farthest = farthest + extra_dist;
		break;
	}

	/********************************************************/
	/* Add Light And View Distances To Near & Far Plane For */
	/* Wireframe Projection 				*/
	/********************************************************/
	switch( proj_type )
	{
	   case C_NAV_WIREFRAME:

		/***********************/
		/* Get Light Distances */
		/***********************/
		extra_dist = 50.0;	/* Should Not Clip Light Jack */

		for( i=0; i<world.num_lights; i++ )
		{
			light = world.light[i];

			switch( light->light_type )
			{
			  case C_POINT_LIGHT:
			    v_pos.x = light->light.light_point->light_pos.x;
			    v_pos.y = light->light.light_point->light_pos.y;
			    v_pos.z = light->light.light_point->light_pos.z;
			    break;
			  case C_VOLUME_LIGHT:
			    v_pos.x = light->light.light_volume->c_sys.origin.x;
			    v_pos.y = light->light.light_volume->c_sys.origin.y;
			    v_pos.z = light->light.light_volume->c_sys.origin.z;
			}

	   		/* Transform Vertex Into Current View C_Sys */
			C_transform_fposition(  &v_pos, &new_v_pos, 
						&(view_ptr->wtol_units));

			temp_close = new_v_pos.z - extra_dist;
			temp_far = new_v_pos.z + extra_dist;

			if( temp_close < closest )
				closest = temp_close;

			if( temp_far > farthest )
				farthest = temp_far;
		}

		/**********************/
		/* Get View Distances */
		/**********************/
		if( view.fov == 0.0 )
		{
		    view_width = view.width_units;
		    view_height = view.height_units;
		}
		else
		{
		    view_width  = view.width_units  * C_PERSPECTIVE_VIEW_SCALE;
		    view_height = view.height_units * C_PERSPECTIVE_VIEW_SCALE;
		}

		for( i=0; i<4; i++ )
		{
		   /* Compute Bounding Vertices Of Wireframe View */
		   switch( i )
		   {
			case 0:
			   v_pos.x = view.c_sys.origin.x;
			   v_pos.y = view.c_sys.origin.y;
			   v_pos.z = view.c_sys.origin.z;
			   break;
			case 1:
			   v_pos.x += (view_width * view.c_sys.x_axis.x);
			   v_pos.y += (view_width * view.c_sys.x_axis.y);
			   v_pos.z += (view_width * view.c_sys.x_axis.z);
			   break;
			case 2:
			   v_pos.x += (view_height * view.c_sys.y_axis.x);
			   v_pos.y += (view_height * view.c_sys.y_axis.y);
			   v_pos.z += (view_height * view.c_sys.y_axis.z);
			   break;
			case 3:
			   v_pos.x -= (view_width * view.c_sys.x_axis.x);
			   v_pos.y -= (view_width * view.c_sys.x_axis.y);
			   v_pos.z -= (view_width * view.c_sys.x_axis.z);
		   }

		   /* Transform Vertex Into Current View C_Sys */
		   C_transform_fposition(  &v_pos, &new_v_pos,
					   &(view_ptr->wtol_units));

		   temp_close = new_v_pos.z - extra_dist;
		   temp_far = new_v_pos.z + extra_dist;

		   if( temp_close < closest )
			closest = temp_close;

		   if( temp_far > farthest )
			farthest = temp_far;
		}
		break;
	   case C_NAV_PROJECTION:
	   case C_PARC_FRONT_PROJECTION:
	   case C_PARC_BACK_PROJECTION:
	   case C_NAV_WIREFRAME_KEY:
		break;
	}

	if( farthest < 2.0 )
		farthest = 2.0;

	if( closest < 0.1 )
		closest = 0.1;

	/* Store Closest And Farthest Information */
	switch( proj_type )
	{
	   case C_NAV_PROJECTION:
	   case C_NAV_WIREFRAME:
	   case C_NAV_WIREFRAME_KEY:
	     near_plane = closest;
	     far_plane  = farthest;
	     break;
	   case C_PARC_FRONT_PROJECTION:
	   case C_PARC_BACK_PROJECTION:
	     near_plane = nav_info->pj_win_info.near_plane[volume_num] =closest;
	     far_plane  = nav_info->pj_win_info.far_plane[volume_num] =farthest;
	}

	switch( proj_type )
	{
	  case C_NAV_PROJECTION:
	  case C_PARC_FRONT_PROJECTION:
	  case C_PARC_BACK_PROJECTION:
		if( (view.fov != 0.0) && (world.num_volumes > 0) )
		{
		    C_make_perspective_matrix( view_ptr, 
			&(nav_info->pj_win_info.projection_matrix ), 
			near_plane, far_plane );


		    C_translate3D( 1.0, -1.0, 
				   0.0, &translate_matrix );
		    C_scale3D( (float)(nav_info->pj_win_info.width_pixels)/2.0,
		              -(float)(nav_info->pj_win_info.height_pixels)/2.0,
			      1.0, &scale_matrix );
			
		    C_matrix_multiply( C_POST_MULTIPLY, 
			&(nav_info->pj_win_info.projection_matrix ),
			&translate_matrix );

		    C_matrix_multiply( C_POST_MULTIPLY, 
			&(nav_info->pj_win_info.projection_matrix ),
			&scale_matrix );


		    C_copy_matrix(  &(view_ptr->wtol_units),
			&(nav_info->pj_win_info.vol_to_view_matrix) );

		    C_matrix_multiply( C_PRE_MULTIPLY, 
			&(nav_info->pj_win_info.vol_to_view_matrix ),
			&(world.volume[volume_num]->ltow_units) );

		}
		else
		{
		}
		break;
	  case C_NAV_WIREFRAME:
		C_make_perspective_matrix( view_ptr, 
			&(nav_info->wf_win_info.projection_matrix ), 
			near_plane, far_plane );


		C_translate3D( 1.0, -1.0, 
				   0.0, &translate_matrix );
		C_scale3D( 
			(float)(nav_info->wf_win_info.view.width_pixels)/2.0,
		       -(float)(nav_info->wf_win_info.view.height_pixels)/2.0,
			      1.0, &scale_matrix );
			
		C_matrix_multiply( C_POST_MULTIPLY, 
			&(nav_info->wf_win_info.projection_matrix ),
			&translate_matrix );

		C_matrix_multiply( C_POST_MULTIPLY, 
			&(nav_info->wf_win_info.projection_matrix ),
			&scale_matrix );


		C_copy_matrix(  &(view_ptr->wtol_units),
			&(nav_info->wf_win_info.vol_to_view_matrix) );

		if( world.num_volumes > 0 && volume_num >= 0 )
		{
		    C_matrix_multiply( C_PRE_MULTIPLY, 
			&(nav_info->wf_win_info.vol_to_view_matrix ),
			&(world.volume[volume_num]->ltow_units) );

		}

		break;
	  case C_NAV_WIREFRAME_KEY:
		near_plane = -1.0;
		far_plane = 1.0;
		break;
	}

	switch( proj_type )
	{
	   case C_NAV_PROJECTION:
	   case C_PARC_FRONT_PROJECTION:
	   case C_PARC_BACK_PROJECTION:
	   case C_NAV_WIREFRAME:
		break;
	   case C_NAV_WIREFRAME_KEY:
		break;
	}

	/************************************/
	/* Use Appropriate Zbuffer Function */
	/************************************/
	switch( proj_type )
	{
		case C_NAV_PROJECTION:
			break;
		case C_NAV_WIREFRAME:
			break;
		case C_NAV_WIREFRAME_KEY:
			break;
		case C_PARC_FRONT_PROJECTION:
			break;
		case C_PARC_BACK_PROJECTION:
			break;
	}
}

void nav_set_lighting( proj_type )
C_NavProjectionType	proj_type;	/* Selects Projection Type */
{
	extern	C_NavInfo	nav_info;
	extern	C_World		world;

	unsigned long	gl_color;	/* GL Color Representation */
	float		gl_light[C_MAX_LIGHTS][20];
	float		gl_material[20];
	float		gl_light_model[20];
	C_PointLight	*light_ptr;
	C_Color		*color_ptr;
	int		light_num;


	/*************************************************/
	/* Lighting Is Not Necessary For PARC Projections */
	/*************************************************/
	switch( proj_type )
	{
		case C_PARC_FRONT_PROJECTION:
		case C_PARC_BACK_PROJECTION:
			return;
	}

	/* Setup light sources and light properties */
	for( light_num = 0; light_num<world.num_lights; light_num++ )
	{
		if( world.light[light_num]->visible )
		{
		   light_ptr = world.light[light_num]->light.light_point;
		}
	}

	/**************************************/
	/* Set GL Light Model Definition Here */
	/**************************************/
	color_ptr = &(world.world_shade.ambient_color);
}

void nav_set_shading( proj_type, volume )
C_NavProjectionType	proj_type;	/* Selects Projection Type */
C_Volume		*volume;
{
	extern	C_NavInfo	nav_info;
	extern	C_World		world;
	extern  C_WindowDefs    window_defs;

	XColor		color;
	int		pixel;
	XGCValues	gcvalues;


	/***************************************************************/
	/* Shading Is Not Necessary For PARC Projections - Use 1 Color */
	/***************************************************************/
	switch( proj_type )
	{
		case C_PARC_FRONT_PROJECTION:
		case C_PARC_BACK_PROJECTION:
			return;
	}

	/*********************************/
	/* Set  Material Properties Here */
	/*********************************/

	if ( volume->color_type  == C_SINGLE_COLOR )
	{
		color.red = world.world_shade.ambient_color.red *
			    world.world_shade.ambient_coef +
			    volume->color_data.single_color->red;
		if ( color.red > 255 ) color.red = 255;
		color.green = world.world_shade.ambient_color.green *
			    world.world_shade.ambient_coef +
			    volume->color_data.single_color->green;
		if ( color.green > 255 ) color.green = 255;
		color.blue = world.world_shade.ambient_color.blue *
			    world.world_shade.ambient_coef +
			    volume->color_data.single_color->blue;
		if ( color.blue > 255 ) color.blue = 255;
	}
	else
	{
		if ( (world.world_shade.bkgrnd_color.red +
		      world.world_shade.bkgrnd_color.green +
		      world.world_shade.bkgrnd_color.blue) > 128*3 ) 
		{
			color.red = 0;
			color.green = 0;
			color.blue = 0;
		}		
		else
		{
			color.red = 255;
			color.green = 255;
			color.blue = 255;
		}
	}

        if ( window_defs.depth == 24 )
        {
                color.red *= 256;
                color.green *= 256;
                color.blue *= 256;
                pixel = C_Get_Pixel( color );
        }
        else if ( window_defs.depth == 8 )
        {
                pixel = window_defs.first_color_index +
                    C_Round(((float)(color.red)/63.75))*25 +
                    C_Round(((float)(color.green)/63.75))*5 +
                    C_Round(((float)(color.blue)/63.75));
        }


	gcvalues.foreground = pixel;

	XChangeGC( XtDisplay( nav_info.pj_win_info.drawing_area), 
	           nav_info.pj_win_info.gc, GCForeground, &gcvalues );
}

void nav_get_zbuffer( proj_type, volume_num )
C_NavProjectionType	proj_type;	/* Selects Projection Type */
int			volume_num;
{
	extern	C_NavInfo	nav_info;

	/* Read The Z Values From Zbuffer */

	switch( proj_type )
	{
	  case C_PARC_FRONT_PROJECTION:

	    break;
	  case C_PARC_BACK_PROJECTION:
	    break;
	}
}

void nav_unset_shading( proj_type )
C_NavProjectionType	proj_type;	/* Selects Projection Type */
{
	extern	C_NavInfo	nav_info;


	/***************************************************************/
	/* Shading Is Not Necessary For PARC Projections - Use 1 Color */
	/***************************************************************/
	switch( proj_type )
	{
		case C_PARC_FRONT_PROJECTION:
		case C_PARC_BACK_PROJECTION:
			return;
	}

}

void nav_unset_lighting( proj_type )
C_NavProjectionType	proj_type;	/* Selects Projection Type */
{
	extern	C_NavInfo	nav_info;
	extern	C_World		world;

	int light_num;

	/*************************************************/
	/* Lighting Is Not Necessary For PARC Projections */
	/*************************************************/
	switch( proj_type )
	{
		case C_PARC_FRONT_PROJECTION:
		case C_PARC_BACK_PROJECTION:
			return;
	}

	/****************************/
	/* Unbind Each Light Source */
	/****************************/
	for( light_num = 0; light_num<world.num_lights; light_num++ )
	{
	}
}

/* Provides The Smallest And Largest Distance From The Volumes */
/* Vertices To The View - Note: The Smallest May Be Negative! */
void C_distance_to_view( view, volume_num, smallest, largest )
C_View	*view;
int	volume_num;
float	*smallest;
float	*largest;
{
	extern	C_NavInfo	nav_info;
	extern	C_World		world;

	int		i;
	C_Volume	*volume;	/* Volume Pointer */
	float		x_units;	/* X Unit Distance Of Volume */
	float		y_units;	/* Y Unit Distance Of Volume */
	float		z_units;	/* Z Unit Distance Of Volume */
	C_FPosition	v_pos;		/* Volume Vertex Position */
	C_FPosition	new_v_pos;	/* New Volume Vertex Position */
	C_FPosition	orig;		/* Volume Origin */
	C_FVector	x_vec;
	C_FVector	y_vec;
	C_FVector	z_vec;
	float		closest_vertex;
	float		farthest_vertex;

	extern		C_transform_fposition();

	volume = world.volume[volume_num];

	orig.x = volume->c_sys.origin.x;
	orig.y = volume->c_sys.origin.y;
	orig.z = volume->c_sys.origin.z;

	x_units = volume->x_size_units;
	y_units = volume->y_size_units;
	z_units = volume->z_size_units;

	x_vec.x = x_units*volume->c_sys.x_axis.x;
	x_vec.y = x_units*volume->c_sys.x_axis.y;
	x_vec.z = x_units*volume->c_sys.x_axis.z;

	y_vec.x = y_units*volume->c_sys.y_axis.x;
	y_vec.y = y_units*volume->c_sys.y_axis.y;
	y_vec.z = y_units*volume->c_sys.y_axis.z;

	z_vec.x = z_units*volume->c_sys.z_axis.x;
	z_vec.y = z_units*volume->c_sys.z_axis.y;
	z_vec.z = z_units*volume->c_sys.z_axis.z;

	closest_vertex = C_BIG_FLOAT;
	farthest_vertex = -C_BIG_FLOAT;

	/* Transform The Volume Vertices Into View C_Sys */
	for( i=0; i<8; i++ )
	{
	   /* Start Vertex With Origin */
	   v_pos.x = orig.x;
	   v_pos.y = orig.y;
	   v_pos.z = orig.z;

	   switch( i )
	   {
		case 0:
		   /* Leave Position At Origin */
		   break;
		case 1:	/* Move To Positive X */
		   v_pos.x += x_vec.x;
		   v_pos.y += x_vec.y;
		   v_pos.z += x_vec.z;
		   break;
		case 2:/* Move To Positive X,Y */
		   v_pos.x += x_vec.x + y_vec.x;
		   v_pos.y += x_vec.y + y_vec.y;
		   v_pos.z += x_vec.z + y_vec.z;
		   break;
		case 3: /* Move To Positive Y */
		   v_pos.x += y_vec.x;
		   v_pos.y += y_vec.y;
		   v_pos.z += y_vec.z;
		   break;
		case 4: /* Move To Positive Z */
		   v_pos.x += z_vec.x;
		   v_pos.y += z_vec.y;
		   v_pos.z += z_vec.z;
		   break;
		case 5: /* Move To Positive X,Z */
		   v_pos.x += z_vec.x + x_vec.x;
		   v_pos.y += z_vec.y + x_vec.y;
		   v_pos.z += z_vec.z + x_vec.z;
		   break;
		case 6: /* Move To Positive X,Y,Z */
		   v_pos.x += z_vec.x + x_vec.x + y_vec.x;
		   v_pos.y += z_vec.y + x_vec.y + y_vec.y;
		   v_pos.z += z_vec.z + x_vec.z + y_vec.z;
		   break;
		case 7:
		   v_pos.x += z_vec.x + y_vec.x;
		   v_pos.y += z_vec.y + y_vec.y;
		   v_pos.z += z_vec.z + y_vec.z;
	   }

	   /* v_pos Now Contains One Of 8 Vertex Coordinates */

	   /* Transform Vertex Into View C_Sys */
	   C_transform_fposition( &v_pos, &new_v_pos,
			&(view->wtol_units) );

	   /* Look For Closest Vertex */
	   if( new_v_pos.z < closest_vertex )
		closest_vertex = new_v_pos.z;
	
	   /* Look For Farthest Vertex */
	   if( new_v_pos.z > farthest_vertex )
		farthest_vertex = new_v_pos.z;
	}

	*smallest = closest_vertex;
	*largest = farthest_vertex;
}

C_xgrph_draw_shaded_rect( extra_draw_info, vertices, v1, v2, v3, v4 )
C_ExtraDrawInfo	extra_draw_info;
float		vertices[8][3];
int		v1, v2, v3, v4;
{
	extern C_NavInfo	nav_info;


	C_FPosition	vert[4];
	C_FPosition	transformed_vert[4];
	C_FPosition	temp_vert[4];
	
	
	vert[0].x = vertices[v1][0];
	vert[0].y = vertices[v1][1];
	vert[0].z = vertices[v1][2];

	vert[1].x = vertices[v2][0];
	vert[1].y = vertices[v2][1];
	vert[1].z = vertices[v2][2];

	vert[2].x = vertices[v3][0];
	vert[2].y = vertices[v3][1];
	vert[2].z = vertices[v3][2];

	vert[3].x = vertices[v4][0];
	vert[3].y = vertices[v4][1];
	vert[3].z = vertices[v4][2];

	C_transform_fposition( &(vert[0]), &(temp_vert[0]),
		&(extra_draw_info.vol_to_view_matrix) );
	C_transform_fposition( &(vert[1]), &(temp_vert[1]),
		&(extra_draw_info.vol_to_view_matrix) );
	C_transform_fposition( &(vert[2]), &(temp_vert[2]),
		&(extra_draw_info.vol_to_view_matrix) );
	C_transform_fposition( &(vert[3]), &(temp_vert[3]),
		&(extra_draw_info.vol_to_view_matrix) );

	if ( temp_vert[0].z <= extra_draw_info.near_plane ||
	     temp_vert[1].z <= extra_draw_info.near_plane ||
	     temp_vert[2].z <= extra_draw_info.near_plane ||
	     temp_vert[3].z <= extra_draw_info.near_plane ) 
	{
	}
	else
	{ 

	    C_transform_hg_fposition( &(temp_vert[0]), &(transformed_vert[0]),
		&(extra_draw_info.projection_matrix) );
	    C_transform_hg_fposition( &(temp_vert[1]), &(transformed_vert[1]),
		&(extra_draw_info.projection_matrix) );
	    C_transform_hg_fposition( &(temp_vert[2]), &(transformed_vert[2]),
		&(extra_draw_info.projection_matrix) );
	    C_transform_hg_fposition( &(temp_vert[3]), &(transformed_vert[3]),
		&(extra_draw_info.projection_matrix) );


	    XDrawLine( extra_draw_info.display,
		   extra_draw_info.pixmap, extra_draw_info.gc, 
		   (int)(transformed_vert[0].x), (int)(transformed_vert[0].y),
		   (int)(transformed_vert[1].x), (int)(transformed_vert[1].y) );

	    XDrawLine( extra_draw_info.display,
		   extra_draw_info.pixmap, extra_draw_info.gc, 
		   (int)(transformed_vert[1].x), (int)(transformed_vert[1].y),
		   (int)(transformed_vert[2].x), (int)(transformed_vert[2].y) );

	    XDrawLine( extra_draw_info.display,
		   extra_draw_info.pixmap, extra_draw_info.gc, 
		   (int)(transformed_vert[2].x), (int)(transformed_vert[2].y),
		   (int)(transformed_vert[3].x), (int)(transformed_vert[3].y) );

	    XDrawLine( extra_draw_info.display,
		   extra_draw_info.pixmap, extra_draw_info.gc, 
		   (int)(transformed_vert[3].x), (int)(transformed_vert[3].y),
		   (int)(transformed_vert[0].x), (int)(transformed_vert[0].y) );
	}
}

C_xgrph_draw_line( extra_draw_info, vertices, v1, v2 )
C_ExtraDrawInfo	extra_draw_info;
float		vertices[8][3];
int		v1, v2;
{
	extern C_NavInfo	nav_info;


	C_FPosition	vert[2];
	C_FPosition	transformed_vert[2];
	C_FPosition	temp_vert[2];
	
	
	vert[0].x = vertices[v1][0];
	vert[0].y = vertices[v1][1];
	vert[0].z = vertices[v1][2];

	vert[1].x = vertices[v2][0];
	vert[1].y = vertices[v2][1];
	vert[1].z = vertices[v2][2];

	C_transform_fposition( &(vert[0]), &(temp_vert[0]),
		&(extra_draw_info.vol_to_view_matrix) );
	C_transform_fposition( &(vert[1]), &(temp_vert[1]),
		&(extra_draw_info.vol_to_view_matrix) );

	if ( temp_vert[0].z <= extra_draw_info.near_plane ||
	     temp_vert[1].z <= extra_draw_info.near_plane ) 
	{
printf("near, far: %f %f\n", extra_draw_info.near_plane, extra_draw_info.far_plane );
	}
	else
	{ 

	    C_transform_hg_fposition( &(temp_vert[0]), &(transformed_vert[0]),
		&(extra_draw_info.projection_matrix) );
	    C_transform_hg_fposition( &(temp_vert[1]), &(transformed_vert[1]),
		&(extra_draw_info.projection_matrix) );


	    XDrawLine( extra_draw_info.display,
		   extra_draw_info.pixmap, extra_draw_info.gc, 
		   (int)(transformed_vert[0].x), (int)(transformed_vert[0].y),
		   (int)(transformed_vert[1].x), (int)(transformed_vert[1].y) );
printf("drawing a line: (%d, %d) - (%d, %d)\n",
	(int)(transformed_vert[0].x), (int)(transformed_vert[0].y),
        (int)(transformed_vert[1].x), (int)(transformed_vert[1].y) );

	}
}
