
/*
 *                  File: SB_nav_projection.c
 *                Author: Hui Chen 
 *                  Date: 02/06/92
 *           Description: 
 *  Modification History:
 *
 *         who?         when?           why?
 *    -----------------------------------------------------------
 *
 */

# include <stdio.h>
# include <math.h>
# include <fcntl.h>

#define _HP_FAST_MACROS 1
# include <starbase.c.h>
# include <X11/Xlib.h>
# include <X11/Xutil.h>
# include <X11/XHPlib.h>

# include "C_volvis.h"

extern C_World world;
extern C_View view;

pj_setup_view_window(fildes) 
int fildes;
{
	float	screen_xmin, screen_ymin, screen_zmin;
	float	screen_xmax, screen_ymax, screen_zmax;

	camera_arg      camera;

/*
	screen_xmin = view.c_sys.origin.x - 
			(view.c_sys.x_axis.x * view.width_units
                       + view.c_sys.y_axis.x * view.height_units)/2.;

	screen_xmax = view.c_sys.origin.x + 
			(view.c_sys.x_axis.x * view.width_units
                       + view.c_sys.y_axis.x * view.height_units)/2.;

	screen_ymin = view.c_sys.origin.y -
                     (view.c_sys.x_axis.y * view.width_units
                     + view.c_sys.y_axis.y * view.height_units)/2.;

	screen_ymax = view.c_sys.origin.y +
                     (view.c_sys.x_axis.y * view.width_units
                     + view.c_sys.y_axis.y * view.height_units)/2.;

	screen_zmin = view.c_sys.origin.z -
                     (view.c_sys.x_axis.z * view.width_units
                     + view.c_sys.y_axis.z * view.height_units)/2.;

	screen_zmax = view.c_sys.origin.z +
                     (view.c_sys.x_axis.z * view.width_units
                     + view.c_sys.y_axis.z * view.height_units)/2. + 128.0;

	vdc_extent( fildes, screen_xmin, screen_ymin, screen_zmin,
			    screen_xmax, screen_ymax, screen_zmax );

	shade_mode( fildes, CMAP_FULL | INIT, TRUE );

	buffer_mode( fildes, TRUE );
*/

	camera.camx = view.c_sys.origin.x; 
	camera.camy = view.c_sys.origin.y;
	camera.camz = view.c_sys.origin.z;

	camera.refx = view.c_sys.origin.x + view.c_sys.z_axis.x;
	camera.refy = view.c_sys.origin.y + view.c_sys.z_axis.y;
	camera.refz = view.c_sys.origin.z + view.c_sys.z_axis.z;

	camera.front = camera.back = 0.0;

	camera.upx = view.c_sys.y_axis.x;
	camera.upy = view.c_sys.y_axis.y;
	camera.upz = view.c_sys.y_axis.z;

	camera.field_of_view = 45.0;
	camera.projection = CAM_PERSPECTIVE;

	view_camera( fildes, &camera );	

}


void C_setup_voxel_light( fildes, nav_light )
int		fildes;
int		nav_light;
{
	int i, index, power, mask;
/*
	shader.ambient = 0.9;

        shader.light.x = 0.0;
        shader.light.y = 0.0;
        shader.light.z = 1.0;

	light_ambient( fildes, shader.ambient, 
			       shader.ambient, 
			       shader.ambient ); 

	light_source( fildes, 1, DIRECTIONAL, 1.0, 1.0, 1.0, 
		      shader.light.x, shader.light.y, shader.light.z );
*/
/*
	light_ambient( fildes, 0.9, 0.9, 0.9); 
	light_source( fildes, 1, DIRECTIONAL, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0); 
*/
	light_ambient( fildes, 
		      (float)(world.world_shade.ambient_color.red)/255.0, 
		      (float)(world.world_shade.ambient_color.green)/255.0, 
		      (float)(world.world_shade.ambient_color.blue)/255.0);

	switch (nav_light) {
	case C_NAV_SINGLE_LIGHT :
	    light_source( fildes, 1, DIRECTIONAL, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0);
	    light_switch( fildes, 3 );
	    break;
	case C_NAV_WHOLE_LIGHT :
	    index = 1;
	    power = 1;
	    mask = 1;
	    for (i=0; i<world.num_lights; i++) {
	      if (world.light[i]->light_type == C_POINT_LIGHT) {	
	        light_source(fildes, index, POSITIONAL, 
	    (float)(world.light[i]->light.light_point->light_color.red)/255.0,
	    (float)(world.light[i]->light.light_point->light_color.green)/255.0,
	    (float)(world.light[i]->light.light_point->light_color.blue)/255.0,
		    world.light[i]->light.light_point->light_pos.x,
		    world.light[i]->light.light_point->light_pos.y,
		    world.light[i]->light.light_point->light_pos.z);
		index ++;
	        power = power * 2;
	        mask = mask + power;
	      }
	    }
	    light_switch( fildes, mask );
	    break;
	}
}


pj_display( fildes, vlist, block_size )
int		fildes;
C_VoxelList	*vlist;
int		block_size;
{
	register C_VoxelList	*vlptr;
	register int		loop;
	register float		front[5][3];
	register float		top[5][3];
	register float		side[5][3];

	int i;

	vlptr = vlist;

	while (vlptr)
	{
		for (loop = 0; loop < vlptr->voxel_count; loop++)
		{
			front[0][0] = 
			  top[0][0] =
			 side[0][0] = vlptr->voxel[loop].normal.dx;
			front[0][1] = 
			  top[0][1] =
 			 side[0][1] = vlptr->voxel[loop].normal.dy;
			front[0][2] = 
			  top[0][2] = 
			 side[0][2] = vlptr->voxel[loop].normal.dz;

		    if (view.c_sys.z_axis.x < 0)
		    {
                        side[1][0] = side[2][0] =
                        side[3][0] = side[4][0] = vlptr->voxel[loop].xend;
		    }
		    else
		    {
                        side[1][0] = side[2][0] =
                        side[3][0] = side[4][0] =
                                     vlptr->voxel[loop].position.x;
		    }

		    if (view.c_sys.z_axis.y < 0)
		    {
                        top[1][1] = top[2][1] =
                        top[3][1] = top[4][1] =
                                    vlptr->voxel[loop].position.y + block_size;
		    }
		    else
		    {
                        top[1][1] = top[2][1] =
                        top[3][1] = top[4][1] =
                                    vlptr->voxel[loop].position.y;
		    }

		    if (view.c_sys.z_axis.z < 0)
		    {
                        front[1][2] = front[2][2] =
                        front[3][2] = front[4][2] =
                                     vlptr->voxel[loop].position.z + block_size;
		    }
		    else
		    {
                        front[1][2] = front[2][2] =
                        front[3][2] = front[4][2] =
                                      vlptr->voxel[loop].position.z;
		    }

			front[1][0] = 
			front[4][0] = vlptr->voxel[loop].position.x;
			front[2][0] = front[3][0] = vlptr->voxel[loop].xend;

			front[1][1] = 
			front[2][1] = vlptr->voxel[loop].position.y;
			front[3][1] = front[4][1] = front[1][1] + block_size;

			
			top[1][2] = 
			top[4][2] = vlptr->voxel[loop].position.z;
			top[2][2] = top[3][2] = top[1][2] + block_size;


			top[1][0] = 
			top[2][0] = vlptr->voxel[loop].position.x;
			top[3][0] = top[4][0] = vlptr->voxel[loop].xend;


			side[1][1] = 
			side[4][1] = vlptr->voxel[loop].position.y;
			side[2][1] = side[3][1] = side[1][1] + block_size;


			side[1][2] = 
			side[2][2] = vlptr->voxel[loop].position.z;
			side[3][2] = side[4][2] = side[1][2] + block_size;

			polygon3d(fildes, front, 4, FALSE);
			polygon3d(fildes, top,   4, FALSE);
			polygon3d(fildes, side,  4, FALSE);
			
		}
		vlptr = vlptr->next_voxel_list;
	}
}

void pj_display_world(fildes)
int fildes;
{
	extern int pj_level;

	int i, j, k;
	float	M[4][4];

	clear_view_surface(fildes);
	await_retrace(fildes);

	for (i=0; i<world.num_volumes; i++) {
	   if (world.volume[i]->visible == TRUE) {
	      switch (world.volume[i]->shade_type) {
	      case C_SIMPLE_SHADE :
		surface_coefficients(fildes, 
		  world.world_shade.ambient_coef,
		  world.volume[i]->local_shade.simple_shade->diffuse_coef,
		  world.volume[i]->local_shade.simple_shade->specular_coef);
		surface_model(fildes, TRUE, 
		(int)world.volume[i]->local_shade.simple_shade->specular_power,
		  world.volume[i]->local_shade.simple_shade->specular_coef,
		  world.volume[i]->local_shade.simple_shade->specular_coef,
		  world.volume[i]->local_shade.simple_shade->specular_coef);
    		break;
	      case C_ARRAY_SHADE :
		printf("Volume local shade is C_ARRAY_SHADE!!!\n");
    		break;
	      }

	      switch (world.volume[i]->color_type) {
	      case C_SINGLE_COLOR :
	  	fill_color(fildes,
		 (float)(world.volume[i]->color_data.single_color->red)/255.0,
		 (float)(world.volume[i]->color_data.single_color->green)/255.0,
		 (float)(world.volume[i]->color_data.single_color->blue)/255.0);
    		break;
	      default :
		fill_color(fildes, 0.9, 0.5, 0.3 );
    		break;
	      }

	      switch (world.volume[i]->data_type) {
              case C_SCANNED_DATA :
		for (j=0; j<4; j++)
		    for (k=0; k<4; k++)
			M[j][k] = world.volume[i]->ltow_voxels.matrix[k][j];
                concat_transformation3d(fildes, M, PRE, PUSH);
                pj_display(fildes,
                        world.volume[i]->nav_object[pj_level]->visible_surface,
                        world.volume[i]->nav_object[pj_level]->block_size);
                pop_matrix(fildes);
/*
                pop_matrix3d(fildes, world.volume[i]->ltow_voxels);
*/
    		break;
              case C_GEOMETRIC_DATA :
            	printf("Volume data type is C_GEOMETRIC_DATA!!!\n");
            	break;
              }
	   }
	}
        flush_buffer(fildes);
}

