/****************************************************************************/
/*                                                                          */
/*  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                         */
/*                                                                          */
/****************************************************************************/



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

# include "C_volvis.h"
# include "C_raytrace.h"

# define debug(x) 




void C_shade_point( world, view, shade_info, color ) 
C_World			*world;
C_View			*view;
C_ShadeInfo		*shade_info;
C_Color			*color;

{
	extern C_transform_fposition(); 
	extern C_transform_fvector(); 
	extern void C_rt_normal();
/***
	extern void C_rt_find_virtual_lights();
***/

	int			loop;
	C_Volume		*volume;
	C_Voxel_8bit		*dptr;
	float			dot_product;	
	float			t, distance;
	float			light_distance;
	float			xratio, yratio, zratio;
	C_FPosition		new_point;
	C_FPosition		point_one;
	C_FPosition		junk_point;
	C_FVector		reflect_ray_direction;
	C_FVector		transmit_ray_direction;
	C_FVector		normal;
	C_FVector		world_normal;
	C_FVector		shadow_ray_direction;
	C_FVector		halfway;
	float			light_coefficient;
	int			xstep, ystep, zstep;

	register float		A, B, C, D, E, F, G, H;
	float 			value1, value2,
				xnormal_step_size,
				ynormal_step_size,
				znormal_step_size,
				normal_step_size;
	float			spec_part, diff_red, diff_green, diff_blue;
	C_Color			current_intensity;
	C_Color			reflect_color;
	float			total_intensity_red,
				total_intensity_green,
				total_intensity_blue;
	C_PointLight		*plight;
	int			light;

	C_FPosition		texture_pos;
	C_VolTexture		*texture;
	C_Byte			*text_rptr, *text_gptr, *text_bptr;
	C_Color			objcolor;

	float			diffuse_coef,
				transmit_coef,
				specular_coef,
				specular_power;
	float			radical_term;
	C_GeoData		*table_entry;

	C_Polygon		*polygon;

	C_GeoData		*geo_data;	

	int			idx;

	float			index_of_refraction;
	float			transmissitivity;

	int			vol;

	C_RayTraceInfo		rt_info;
	C_IntersectInfo		intersect_info;

	int			virtual_lights;


C_FVector			temp_norm;
float				temp_dot_product;
float				temp_radical_term;

float				min_k, max_k;

	if ( view->projection_type == C_VOLRAD )
	{
	        volume = world->volume[shade_info->volume_num];
	  	texture = volume->texture.radtex;

	  	texture_pos.x = shade_info->local_point.x *
				((float)texture->xres / 
				(float)volume->x_size_voxels);

	  	texture_pos.y = shade_info->local_point.y *
				((float)texture->yres / 
				(float)volume->y_size_voxels);

	  	texture_pos.z = shade_info->local_point.z *
				((float)texture->zres / 
				(float)volume->z_size_voxels);


	  	xstep = 1;
	  	ystep = texture->xres;
	  	zstep = texture->xres * texture->yres;

	  	text_rptr = texture->red + 
		    	((int)(texture_pos.x)*xstep) + 
		    	((int)(texture_pos.y)*ystep) + 
		    	((int)(texture_pos.z)*zstep);

	  	text_gptr = texture->green + 
		    	((int)(texture_pos.x)*xstep) + 
		    	((int)(texture_pos.y)*ystep) + 
		    	((int)(texture_pos.z)*zstep);

	  	text_bptr = texture->blue + 
		    	((int)(texture_pos.x)*xstep) + 
		    	((int)(texture_pos.y)*ystep) + 
		    	((int)(texture_pos.z)*zstep);

	  	color->red =  C_Trilin(
				(texture_pos.x - 
				 (int)(texture_pos.x)),
				(texture_pos.y - 
				 (int)(texture_pos.y)),
				(texture_pos.z - 
				 (int)(texture_pos.z)),
				*(text_rptr),
				*(text_rptr+xstep),
				*(text_rptr+ystep),
				*(text_rptr+xstep+ystep),
				*(text_rptr+zstep),
				*(text_rptr+xstep+zstep),
				*(text_rptr+ystep+zstep), 
				*(text_rptr+xstep+ystep+zstep));

	  	color->green = C_Trilin( 
				(texture_pos.x - 
				 (int)(texture_pos.x)),
				(texture_pos.y - 
				 (int)(texture_pos.y)),
				(texture_pos.z - 
				 (int)(texture_pos.z)),
				*(text_gptr),
				*(text_gptr+xstep),
				*(text_gptr+ystep),
				*(text_gptr+xstep+ystep),
				*(text_gptr+zstep),
				*(text_gptr+xstep+zstep),
				*(text_gptr+ystep+zstep), 
				*(text_gptr+xstep+ystep+zstep));

	  	color->blue = C_Trilin( 
				(texture_pos.x - 
				 (int)(texture_pos.x)),
				(texture_pos.y - 
				 (int)(texture_pos.y)),
				(texture_pos.z - 
				 (int)(texture_pos.z)),
				*(text_bptr),
				*(text_bptr+xstep),
				*(text_bptr+ystep),
				*(text_bptr+xstep+ystep),
				*(text_bptr+zstep),
				*(text_bptr+xstep+zstep),
				*(text_bptr+ystep+zstep), 
				*(text_bptr+xstep+ystep+zstep));

		return;

	}

if ( shade_info->start_on_cut == TRUE )
{
	color->red = 255;
	color->blue = 0;
	color->green = 0;
}
	switch ( shade_info->ray_type )
	{
	    case C_PRIMARY_RAY:
	    case C_REFLECT_RAY:
	    case C_TRANSMIT_RAY:
	    case C_PARC_RAY:

	      volume = world->volume[shade_info->volume_num];

	      if ( volume->shade_type != C_NO_SHADE )
	      	C_rt_normal( volume, shade_info );

/*
	      C_rt_gaussian_curvature( volume, shade_info, &min_k, &max_k );

if ( min_k < 0 && max_k < 0 ) 
{
	color->red = 255;
	color->green = 0;
	color->blue = 0;
} 
else if ( min_k > 0 && max_k > 0 )
{
	color->red = 0;
	color->green = 255;
	color->blue = 0;
}
else if ( min_k < 0 && max_k > 0 )
{
	color->red = 0;
	color->green = 0;
	color->blue = 255;
}
else if ( min_k > 0 && max_k < 0 )
{
	color->red = 255;
	color->green = 0;
	color->blue = 255;
}
else
{
	color->red = 255;
	color->green = 255;
	color->blue = 0;
}
return;
*/


	      world_normal.x = shade_info->world_normal.x;
	      world_normal.y = shade_info->world_normal.y;
	      world_normal.z = shade_info->world_normal.z;

	      switch( volume->color_type )
	      {
	        case C_SINGLE_COLOR: 

	          objcolor.red = 
			volume->color_data.single_color->red;
		  objcolor.green = 
			volume->color_data.single_color->green;
		  objcolor.blue = 
			volume->color_data.single_color->blue;

		  break;

		case C_TEXTURE_COLOR:

		  if ( volume->shade_type == C_NO_SHADE )
		  {
			C_error_message("Can't have a texture with opacity\n");
			return;
		  }

		  switch ( volume->texture_type )
		  {

		    case C_VOLUME_TEXTURE:

		  	texture = volume->texture.voltex;

		  	texture_pos.x = shade_info->local_point.x *
				((float)texture->xres / 
				(float)volume->x_size_voxels);

		  	texture_pos.y = shade_info->local_point.y *
				((float)texture->yres / 
				(float)volume->y_size_voxels);

		  	texture_pos.z = shade_info->local_point.z *
				((float)texture->zres / 
				(float)volume->z_size_voxels);


		  	xstep = 1;
		  	ystep = texture->xres;
		  	zstep = texture->xres * texture->yres;


		  	text_rptr = texture->red + 
		    	((int)(texture_pos.x)*xstep) + 
		    	((int)(texture_pos.y)*ystep) + 
		    	((int)(texture_pos.z)*zstep);

		  	text_gptr = texture->green + 
		    	((int)(texture_pos.x)*xstep) + 
		    	((int)(texture_pos.y)*ystep) + 
		    	((int)(texture_pos.z)*zstep);

		  	text_bptr = texture->blue + 
		    	((int)(texture_pos.x)*xstep) + 
		    	((int)(texture_pos.y)*ystep) + 
		    	((int)(texture_pos.z)*zstep);

		  	objcolor.red =  C_Trilin(
				(texture_pos.x - 
				 (int)(texture_pos.x)),
				(texture_pos.y - 
				 (int)(texture_pos.y)),
				(texture_pos.z - 
				 (int)(texture_pos.z)),
				*(text_rptr),
				*(text_rptr+xstep),
				*(text_rptr+ystep),
				*(text_rptr+xstep+ystep),
				*(text_rptr+zstep),
				*(text_rptr+xstep+zstep),
				*(text_rptr+ystep+zstep), 
				*(text_rptr+xstep+ystep+zstep));

		  	objcolor.green = C_Trilin( 
				(texture_pos.x - 
				 (int)(texture_pos.x)),
				(texture_pos.y - 
				 (int)(texture_pos.y)),
				(texture_pos.z - 
				 (int)(texture_pos.z)),
				*(text_gptr),
				*(text_gptr+xstep),
				*(text_gptr+ystep),
				*(text_gptr+xstep+ystep),
				*(text_gptr+zstep),
				*(text_gptr+xstep+zstep),
				*(text_gptr+ystep+zstep), 
				*(text_gptr+xstep+ystep+zstep));

		  	objcolor.blue = C_Trilin( 
				(texture_pos.x - 
				 (int)(texture_pos.x)),
				(texture_pos.y - 
				 (int)(texture_pos.y)),
				(texture_pos.z - 
				 (int)(texture_pos.z)),
				*(text_bptr),
				*(text_bptr+xstep),
				*(text_bptr+ystep),
				*(text_bptr+xstep+ystep),
				*(text_bptr+zstep),
				*(text_bptr+xstep+zstep),
				*(text_bptr+ystep+zstep), 
				*(text_bptr+xstep+ystep+zstep));

			break;

		    case C_RAD_TEXTURE:

		  	texture = volume->texture.radtex;

		  	texture_pos.x = shade_info->local_point.x *
				((float)texture->xres / 
				(float)volume->x_size_voxels);

		  	texture_pos.y = shade_info->local_point.y *
				((float)texture->yres / 
				(float)volume->y_size_voxels);

		  	texture_pos.z = shade_info->local_point.z *
				((float)texture->zres / 
				(float)volume->z_size_voxels);


		  	xstep = 1;
		  	ystep = texture->xres;
		  	zstep = texture->xres * texture->yres;


		  	text_rptr = texture->red + 
		    	((int)(texture_pos.x)*xstep) + 
		    	((int)(texture_pos.y)*ystep) + 
		    	((int)(texture_pos.z)*zstep);

		  	text_gptr = texture->green + 
		    	((int)(texture_pos.x)*xstep) + 
		    	((int)(texture_pos.y)*ystep) + 
		    	((int)(texture_pos.z)*zstep);

		  	text_bptr = texture->blue + 
		    	((int)(texture_pos.x)*xstep) + 
		    	((int)(texture_pos.y)*ystep) + 
		    	((int)(texture_pos.z)*zstep);

		  	objcolor.red =  C_Trilin(
				(texture_pos.x - 
				 (int)(texture_pos.x)),
				(texture_pos.y - 
				 (int)(texture_pos.y)),
				(texture_pos.z - 
				 (int)(texture_pos.z)),
				*(text_rptr),
				*(text_rptr+xstep),
				*(text_rptr+ystep),
				*(text_rptr+xstep+ystep),
				*(text_rptr+zstep),
				*(text_rptr+xstep+zstep),
				*(text_rptr+ystep+zstep), 
				*(text_rptr+xstep+ystep+zstep));

		  	objcolor.green = C_Trilin( 
				(texture_pos.x - 
				 (int)(texture_pos.x)),
				(texture_pos.y - 
				 (int)(texture_pos.y)),
				(texture_pos.z - 
				 (int)(texture_pos.z)),
				*(text_gptr),
				*(text_gptr+xstep),
				*(text_gptr+ystep),
				*(text_gptr+xstep+ystep),
				*(text_gptr+zstep),
				*(text_gptr+xstep+zstep),
				*(text_gptr+ystep+zstep), 
				*(text_gptr+xstep+ystep+zstep));

		  	objcolor.blue = C_Trilin( 
				(texture_pos.x - 
				 (int)(texture_pos.x)),
				(texture_pos.y - 
				 (int)(texture_pos.y)),
				(texture_pos.z - 
				 (int)(texture_pos.z)),
				*(text_bptr),
				*(text_bptr+xstep),
				*(text_bptr+ystep),
				*(text_bptr+xstep+ystep),
				*(text_bptr+zstep),
				*(text_bptr+xstep+zstep),
				*(text_bptr+ystep+zstep), 
				*(text_bptr+xstep+ystep+zstep));

			break;

		    }


		  break;

		case C_COLOR_ARRAY:

		  break;

		default:
			
		  fprintf(stderr,"Unknown Color Type!!!\n");
		  exit(C_ERROR);
		  break;
	      }

	      switch (volume->shade_type)
	      {
	        case C_SIMPLE_SHADE:
	      	  diffuse_coef = 
		    volume->local_shade.simple_shade->diffuse_coef;
 	      	  specular_coef = 
		    volume->local_shade.simple_shade->specular_coef;
	      	  specular_power = 
		    volume->local_shade.simple_shade->specular_power;
		  transmit_coef = 
		    volume->local_shade.simple_shade->transmit_coef;
		  transmissitivity = 
		    volume->local_shade.simple_shade->transmissitivity;
		  index_of_refraction = 
		    volume->local_shade.simple_shade->index_of_refraction;

		  break;

		case C_ARRAY_SHADE:
		  idx = (objcolor.red&C_RED_SHADE_MASK) |
		     ((objcolor.green&C_GREEN_SHADE_MASK)>>3) |
		     ((objcolor.blue&C_BLUE_SHADE_MASK)>>6);

		  diffuse_coef = 
		    volume->local_shade.array_shade->diff_coef_array[idx];
		  specular_coef = 
		    volume->local_shade.array_shade->spec_coef_array[idx];
		  specular_power = 
		    volume->local_shade.array_shade->spec_pow_array[idx];
		  transmit_coef = 
		    volume->local_shade.array_shade->tran_coef_array[idx];
		  transmissitivity = 
		    volume->local_shade.array_shade->transmiss_array[idx];
		  index_of_refraction = 
		    volume->local_shade.array_shade->ref_index_array[idx];

		  break;

		case C_NO_SHADE:

		  specular_coef = 0.0;
		  transmit_coef = 0.0;

		  break;

		default:
		  fprintf(stderr,"No Such Shade Type!!!\n");
		  exit(C_ERROR);

		  break;
	      }

	      if ( volume->texture_type == C_RAD_TEXTURE )
	      {
		total_intensity_red = 
		total_intensity_green = 
		total_intensity_blue = 0.0;
	      }
	      else if ( volume->shade_type == C_NO_SHADE )
	      {
		total_intensity_red =  shade_info->opacity_red;
		total_intensity_green =  shade_info->opacity_green;
		total_intensity_blue =  shade_info->opacity_blue;
/*
printf("intensity passed in: %f %f %f\n", total_intensity_red,
		total_intensity_green, total_intensity_blue );
*/

	        rt_info.ray_origin.x = shade_info->world_point.x;
	        rt_info.ray_origin.y = shade_info->world_point.y;
	        rt_info.ray_origin.z = shade_info->world_point.z;
	        rt_info.ray_direction.x = shade_info->ray_direction.x;
	        rt_info.ray_direction.y = shade_info->ray_direction.y;
	        rt_info.ray_direction.z = shade_info->ray_direction.z;
	        rt_info.ray_level = shade_info->ray_level;
	        rt_info.ray_type = C_PRIMARY_RAY,
	        rt_info.max_distance = C_BIG_FLOAT;
                C_trace_ray( &rt_info, world, view, &intersect_info );

		current_intensity.red = intersect_info.intersect_color.red; 
		current_intensity.green = intersect_info.intersect_color.green; 
		current_intensity.blue = intersect_info.intersect_color.blue; 

		total_intensity_red += (1.0 - shade_info->opacity) *
					(float)(current_intensity.red)/255.0;
		total_intensity_green += (1.0 - shade_info->opacity) *
					(float)(current_intensity.green)/255.0;
		total_intensity_blue += (1.0 - shade_info->opacity) *
					(float)(current_intensity.blue)/255.0;
/*
printf("intensity passed out: %f %f %f\n", total_intensity_red,
		total_intensity_green, total_intensity_blue );
*/
	      }
	      else
	      {
	      	total_intensity_red =   
			  (float)
			  (world->world_shade.ambient_color.red)/255.0 *
			  (world->world_shade.ambient_coef) * 
			  (float)
			  (objcolor.red)/255.0 *
			  diffuse_coef;
				

	      	total_intensity_green =   
			  (float)
			  (world->world_shade.ambient_color.green)/255.0 *
			  (world->world_shade.ambient_coef) * 
			  (float)
			  (objcolor.green)/255.0 *
			  diffuse_coef;

	      	total_intensity_blue =   
			  (float)
			  (world->world_shade.ambient_color.blue)/255.0 *
			  (world->world_shade.ambient_coef) * 
			  (float)
			  (objcolor.blue)/255.0 *
			  diffuse_coef;
	      }


	      if ( volume->shade_type != C_NO_SHADE )
	      {
	        for (light = 0; light < world->num_lights; light++)
	        {
		  if ( world->light[light]->visible )
		  {
		    switch ( world->light[light]->light_type )
		    {
		      case C_POINT_LIGHT:
			plight = 
			    world->light[light]->light.light_point;	
	
			shadow_ray_direction.x = plight->light_pos.x
				- shade_info->world_point.x;
			shadow_ray_direction.y = plight->light_pos.y
				- shade_info->world_point.y;
			shadow_ray_direction.z = plight->light_pos.z
				- shade_info->world_point.z;

			C_Normalize( shadow_ray_direction.x,
				     shadow_ray_direction.y,
				     shadow_ray_direction.z, light_distance );

                	light_coefficient =
                       		shadow_ray_direction.x*world_normal.x +
                       		shadow_ray_direction.y*world_normal.y +
                       		shadow_ray_direction.z*world_normal.z;

			if ( light_coefficient <= 0.0 && 
			     volume->texture_type == C_RAD_TEXTURE )
			{
			   	total_intensity_red =
			     	    (((float) (objcolor.red))/255.0);

			    	total_intensity_green =
			     	    (((float) (objcolor.green))/255.0);

			    	total_intensity_blue =
			     	    (((float) (objcolor.blue))/255.0);

			}

			if ( (light_coefficient > 0.0))
			{

			  if ( view->shadows_enabled ) 
			  {
			    rt_info.ray_origin.x = shade_info->world_point.x;
			    rt_info.ray_origin.y = shade_info->world_point.y;
			    rt_info.ray_origin.z = shade_info->world_point.z;
			    rt_info.ray_direction.x = shadow_ray_direction.x;
			    rt_info.ray_direction.y = shadow_ray_direction.y;
			    rt_info.ray_direction.z = shadow_ray_direction.z;
			    rt_info.ray_level = shade_info->ray_level;
			    rt_info.ray_type = C_SHADOW_RAY,
			    rt_info.max_distance = light_distance;
                       	    C_trace_ray( &rt_info, world, view, 
					 &intersect_info );

			    current_intensity.red = 
					intersect_info.intersect_color.red; 
			    current_intensity.green = 
					intersect_info.intersect_color.green; 
			    current_intensity.blue = 
					intersect_info.intersect_color.blue; 
			  }
			  else
			  {
			    current_intensity.red = 
			    current_intensity.green = 
			    current_intensity.blue = 255;
			  }

			  if ( view->max_indirect_light_level > 0 &&
			       shade_info->volume_num > 0 )
			  {
/***
				C_rt_find_virtual_lights( world, view, 
					&(shade_info->world_point),
					&virtual_lights );
****/

				color->red = virtual_lights;
				color->green = 0;
				color->blue = 0;

				return;
				
				if ( virtual_lights == 1 )
				{
					total_intensity_red = 1.0;
					total_intensity_green = 0.0;
					total_intensity_blue = 0.0;
				}
				if ( virtual_lights == 2 )
				{
					total_intensity_red = 0.0;
					total_intensity_green = 0.0;
					total_intensity_blue = 1.0;
				}
			  }

			  if ( volume->texture_type == C_RAD_TEXTURE )
			  {
				light_coefficient = 1.0;
				diffuse_coef = 1.0;
				if (current_intensity.red  == 0 &&
				    current_intensity.green == 0 &&
				    current_intensity.blue == 0 )
				{
			    		total_intensity_red =
			     		    (((float) (objcolor.red))/255.0);

			    		total_intensity_green =
			     		    (((float) (objcolor.green))/255.0);

			    		total_intensity_blue =
			     		    (((float) (objcolor.blue))/255.0);

				}
			  }


			  if (  current_intensity.red > 0 ||
				current_intensity.green > 0 ||
				current_intensity.blue > 0  )
			  {
			    diff_red =
			     diffuse_coef *
			     (((float) (objcolor.red))/255.0) *
			     (((float) (current_intensity.red))/ 255.0) *
			     light_coefficient;

			    diff_green =
			     diffuse_coef *
			     (((float) (objcolor.green))/255.0) *
			     (((float) (current_intensity.green))/ 255.0) *
			     light_coefficient;

			    diff_blue =
			     diffuse_coef *
			     (((float) (objcolor.blue))/255.0) *
			     (((float) (current_intensity.blue))/ 255.0) *
			     light_coefficient;


			    if (specular_coef>0.0)
			    {

			      halfway.x = shadow_ray_direction.x - 
					  shade_info->ray_direction.x;

			      halfway.y = shadow_ray_direction.y - 
					  shade_info->ray_direction.y;

			      halfway.z = shadow_ray_direction.z - 
					  shade_info->ray_direction.z;

			      C_Normalize( halfway.x, 
					   halfway.y,
					   halfway.z, t );

			      dot_product = 
				world_normal.x * halfway.x + 
				world_normal.y * halfway.y + 
				world_normal.z * halfway.z;
				      
			      if (dot_product > 0.0)
			      {
				spec_part = (float) ( 
				  pow((double)dot_product, (double)
				  specular_power)*
				  specular_coef);

			        total_intensity_red += 
				  ((diff_red+spec_part)*(float)
				  (plight->light_color.red)/255.0) *
				  (plight->light_intensity) * 
				  (1.0 / light_distance );

			        total_intensity_green += 
				  ((diff_green+spec_part)*(float)
				  (plight->light_color.green)/255.0) *
				  (plight->light_intensity) *
				  (1.0 / light_distance );

			        total_intensity_blue += 
				  ((diff_blue+spec_part)*(float)
				  (plight->light_color.blue)/255.0) *
				  (plight->light_intensity) *
				  (1.0 / light_distance );
					
			      }
			      else
			      {
			        total_intensity_red += 
				  (diff_red*(float)
				  (plight->light_color.red)/255.0) *
				  (plight->light_intensity) *
				  (1.0 / light_distance );

			        total_intensity_green += 
				  (diff_green*(float)
				  (plight->light_color.green)/255.0) *
				  (plight->light_intensity) *
				  (1.0 / light_distance );

			        total_intensity_blue += 
				  (diff_blue*(float)
				  (plight->light_color.blue)/255.0) *
				  (plight->light_intensity) *
				  (1.0 / light_distance );
			      }
			    }
			    else
			    {
			      total_intensity_red += 
				(diff_red*(float)
				(plight->light_color.red)/255.0) *
				(plight->light_intensity) *
				(1.0 / light_distance );

			      total_intensity_green += 
				(diff_green*(float)
				(plight->light_color.green)/255.0) *
				(plight->light_intensity) *
				(1.0 / light_distance );

			      total_intensity_blue += 
				(diff_blue*(float)
				(plight->light_color.blue)/255.0) *
				(plight->light_intensity) *
				(1.0 / light_distance );

			    }


			  }
			}


			break;


		      
		      default:
		 	fprintf(stderr,"Unknown Light Source!!!\n");
			exit(C_ERROR);
			break;
		    }
		  }
		}
	      }

	      if ( ( specular_coef > 0.0 && 
			shade_info->ray_level < view->max_reflect_ray_level ) ||
		   ( transmit_coef > 0.0 && 
			shade_info->ray_level < view->max_transmit_ray_level ) )
	      {
	      	    dot_product = -1.0 * (world_normal.x * 
						shade_info->ray_direction.x + 
			                  world_normal.y * 
						shade_info->ray_direction.y +
			                  world_normal.z * 
						shade_info->ray_direction.z);

	      }


	      if ( specular_coef > 0.0 &&
			shade_info->ray_level < view->max_reflect_ray_level ) 
	      {
	      	    if (dot_product > 0.0 )
	      	    {

	      		reflect_ray_direction.x = 
				2.0*dot_product* world_normal.x + 
				shade_info->ray_direction.x;

	      		reflect_ray_direction.y = 
				2.0*dot_product* world_normal.y + 
				shade_info->ray_direction.y;

	      		reflect_ray_direction.z = 
				2.0*dot_product* world_normal.z + 
				shade_info->ray_direction.z;
	
debug(("about to send a reflection ray!\n"));
debug(("origin: %f, %f, %f\n", shade_info->world_point.x, 
	shade_info->world_point.y, shade_info->world_point.z ));
debug(("direction: %f, %f, %f\n", reflect_ray_direction.x, 
	reflect_ray_direction.y, reflect_ray_direction.z ));
debug(("level: %f\n", shade_info->ray_level )); 

			rt_info.ray_origin.x = shade_info->world_point.x;
			rt_info.ray_origin.y = shade_info->world_point.y;
			rt_info.ray_origin.z = shade_info->world_point.z;
			rt_info.ray_direction.x = reflect_ray_direction.x;
			rt_info.ray_direction.y = reflect_ray_direction.y;
			rt_info.ray_direction.z = reflect_ray_direction.z;
			rt_info.ray_level = shade_info->ray_level + 1;
			rt_info.ray_type = C_REFLECT_RAY,
			rt_info.max_distance = C_BIG_FLOAT;
                	C_trace_ray( &rt_info, world, view, &intersect_info );

			reflect_color.red = 
				intersect_info.intersect_color.red;
			reflect_color.green = 
				intersect_info.intersect_color.green;
			reflect_color.blue = 
				intersect_info.intersect_color.blue;
			distance = intersect_info.intersect_distance;

debug(("the reflected color is: %d %d %d\n",reflect_color.red, 
reflect_color.green, reflect_color.blue));

			if ( !shade_info->exiting_volume )
			{

		      	    total_intensity_red +=
				specular_coef*
				(float)reflect_color.red / 255.0;

		      	    total_intensity_green +=
				specular_coef*
				(float)reflect_color.green / 255.0;

		      	    total_intensity_blue +=
				specular_coef*
				(float)reflect_color.blue / 255.0;
			}
			else
			{
		      	    total_intensity_red +=
				specular_coef*
				(float)reflect_color.red / 255.0 *
				pow((double)transmissitivity, (double)distance);

		      	    total_intensity_green +=
				specular_coef*
				(float)reflect_color.green / 255.0 *
				pow((double)transmissitivity, (double)distance);

		      	    total_intensity_blue +=
				specular_coef*
				(float)reflect_color.blue / 255.0 *
				pow((double)transmissitivity, (double)distance);
			}
		    }
	      }

	      if ( transmit_coef > 0.0 && 
			shade_info->ray_level < view->max_transmit_ray_level )
	      {
		if ( !shade_info->exiting_volume )
		{
			radical_term = 1.0 - 
				C_Square(((1.0)/(index_of_refraction)))*(
				1.0 - C_Square(dot_product));
			if (radical_term >= 0.0 )
			{
			    t = (1.0)/(index_of_refraction) * dot_product - 
			   	 sqrt( (double) ( radical_term ) );

			    transmit_ray_direction.x = 
			     t * world_normal.x + (1.0)/(index_of_refraction) * 
				shade_info->ray_direction.x;

			    transmit_ray_direction.y = 
			     t * world_normal.y + (1.0)/(index_of_refraction) * 
				shade_info->ray_direction.y;

			    transmit_ray_direction.z = 
			     t * world_normal.z + (1.0)/(index_of_refraction) * 
				shade_info->ray_direction.z;
			}
			else
{
total_intensity_green = 1.0;
			    transmit_coef = 0.0;
}

			
		}
		else
		{
			radical_term = 1.0 - 
				C_Square(index_of_refraction)*(
				1.0 - C_Square(dot_product));

			if (radical_term >= 0.0)
			{

			    t = (index_of_refraction) * (dot_product) - 
			        sqrt( (double) ( radical_term ) );

			    transmit_ray_direction.x = 
				t * world_normal.x + 
				(index_of_refraction) * 
				shade_info->ray_direction.x;

			    transmit_ray_direction.y = 
				t * world_normal.y + 
				(index_of_refraction) * 
				shade_info->ray_direction.y;

			    transmit_ray_direction.z = 
				t * world_normal.z + 
				(index_of_refraction) * 
				shade_info->ray_direction.z;
			}
			else
{
/*
temp_norm.x = 31.0 - shade_info->local_point.x;
temp_norm.y = 31.0 - shade_info->local_point.y;
temp_norm.z = 31.0 - shade_info->local_point.z;
C_Normalize( temp_norm.x, temp_norm.y, temp_norm.z, t );
temp_dot_product = 
	-1.0*(temp_norm.x *
	shade_info->ray_direction.x + 
        temp_norm.y * 
	shade_info->ray_direction.y +
        temp_norm.z * 
	shade_info->ray_direction.z);
temp_radical_term = 1.0 - 
	C_Square(index_of_refraction)*(
	1.0 - C_Square(temp_dot_product));
printf("\n\n");
printf("The radical term is: %f\n", radical_term);
printf("but should have been: %f\n", temp_radical_term);
printf("because the dot product is: %f\n", dot_product);
printf("but should have been: %f\n", temp_dot_product);
printf("because the world normal is: %f, %f, %f\n",
	world_normal.x, world_normal.y, world_normal.z );
printf("but it should be: %f, %f, %f\n",
	temp_norm.x, temp_norm.y, temp_norm.z );
printf("and the ray direction is: %f, %f, %f\n",
	shade_info->ray_direction.x,
	shade_info->ray_direction.y,
	shade_info->ray_direction.z );
*/
				transmit_coef = 0.0;
}
		}

		if ( transmit_coef > 0.0 )
		{
debug(("about to send a transmission ray!\n"));
debug(("origin: %f, %f, %f\n", shade_info->world_point.x, 
	shade_info->world_point.y, shade_info->world_point.z ));
debug(("direction: %f, %f, %f\n", transmit_ray_direction.x, 
	transmit_ray_direction.y, transmit_ray_direction.z ));
debug(("level: %f\n", shade_info->ray_level )); 
			rt_info.ray_origin.x = shade_info->world_point.x;
			rt_info.ray_origin.y = shade_info->world_point.y;
			rt_info.ray_origin.z = shade_info->world_point.z;
			rt_info.ray_direction.x = transmit_ray_direction.x;
			rt_info.ray_direction.y = transmit_ray_direction.y;
			rt_info.ray_direction.z = transmit_ray_direction.z;
			rt_info.ray_level = shade_info->ray_level + 1;
			rt_info.ray_type = C_TRANSMIT_RAY,
			rt_info.max_distance = C_BIG_FLOAT;
/*
printf("about to send a transmit ray from: %f, %f, %f\n",
		rt_info.ray_origin.x, rt_info.ray_origin.y, 
		rt_info.ray_origin.z );
*/
                	C_trace_ray( &rt_info, world, view, &intersect_info );

			reflect_color.red = 
				intersect_info.intersect_color.red;
			reflect_color.green = 
				intersect_info.intersect_color.green;
			reflect_color.blue = 
				intersect_info.intersect_color.blue;
			distance = intersect_info.intersect_distance;
/*
printf("return color (red) = %d\n", reflect_color.red );
if (reflect_color.red == 0) sleep (5);
*/

			if ( shade_info->exiting_volume )
			{

		      	    total_intensity_red +=
				transmit_coef*
				(float)reflect_color.red / 255.0;

		      	    total_intensity_green +=
				transmit_coef*
				(float)reflect_color.green / 255.0;

		      	    total_intensity_blue +=
				transmit_coef*
				(float)reflect_color.blue / 255.0;
			}
			else
			{
		      	    total_intensity_red +=
				transmit_coef*
				(float)reflect_color.red / 255.0 *
				pow((double)transmissitivity, (double)distance);

		      	    total_intensity_green +=
				transmit_coef*
				(float)reflect_color.green / 255.0 *
				pow((double)transmissitivity, (double)distance);

		      	    total_intensity_blue +=
				transmit_coef*
				(float)reflect_color.blue / 255.0 *
				pow((double)transmissitivity, (double)distance);
			}
		}

	      }


	      if (total_intensity_red > 1.0)
			color->red =  255;
	      else
			color->red = 255.0*total_intensity_red; 		

	      if (total_intensity_green > 1.0)
			color->green =  255;
	      else
			color->green = 255.0*total_intensity_green; 		

	      if (total_intensity_blue > 1.0)
			color->blue =  255;
	      else
			color->blue = 255.0*total_intensity_blue; 		


debug(("Final color is: %d %d %d\n",color->red, color->green, color->blue));

		
	      break;

	    case C_SHADOW_RAY:
debug(("We are in a shadow!!!\n"));
	      
	      break;
	}
debug(("Done!!!\n")); 
}


