/****************************************************************************/
/*                                                                          */
/*  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: C_cast_probe_rays.c
 *                Author: Lisa Sobierajski 
 *                  Date:
 *           Description:
 *  Modification History:
 *
 *         who?         when?           why?
 *    -----------------------------------------------------------
 *
 */

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

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

extern C_transform_fposition(); 
extern C_transform_fvector(); 
extern C_trace_ray();

C_cast_probe_rays( world, view, vol_of_interest, indirect_light_info, index )
C_World			*world;
C_View			*view; 
int			vol_of_interest;
C_IndirectLightInfo	*indirect_light_info;
int			index;
{

	int		image_x, 
			image_y;
	double		ray_origin_x,
			ray_origin_y,
			ray_origin_z,
			eye_point_x,
			eye_point_y,
			eye_point_z,
			upper_left_corner_x,
			upper_left_corner_y,
			upper_left_corner_z,
			width_units,
			height_units;
	C_FVector	ray_direction;
	double		x_spacing,
			y_spacing;
	float  		temp_float,
			distance;
	C_RayTraceInfo	rt_info;
	int		volume;
	C_Color		color;
	C_IntersectInfo intersect_info;
	float		*xptr;
	float		*yptr;
	float		*zptr;
	float		*rxptr;
	float		*ryptr;
	float		*rzptr;
	float		dot_product;


	
	if (view->fov != 0.0)
	{
		width_units = 20.0*tan((double)(view->fov/2.0));
		height_units = width_units *
			((view->height_pixels)/(view->width_pixels));	
		view->width_units = (float) width_units;
		view->height_units = (float) height_units;
printf("width, height in units: %f %f\n", view->width_units, view->height_units );
	}
	else
	{
		width_units = view->width_units;
		height_units = view->height_units;
	}



	x_spacing = width_units /
		    (double)view->width_pixels;

	y_spacing = height_units /
		    (double)view->height_pixels;

	rt_info.ray_type = C_PROBE_RAY;
	rt_info.ray_level = 0;
	rt_info.max_distance = C_BIG_FLOAT;

	xptr = indirect_light_info->x_pos[index];
	yptr = indirect_light_info->y_pos[index];
	zptr = indirect_light_info->z_pos[index];

	rxptr = indirect_light_info->x_refl_dir[index];
	ryptr = indirect_light_info->y_refl_dir[index];
	rzptr = indirect_light_info->z_refl_dir[index];

	if (view->fov == 0.0)
	{
		upper_left_corner_x = view->c_sys.origin.x -
			width_units/2.0 * view->c_sys.x_axis.x +
			height_units/2.0 * view->c_sys.y_axis.x; 
		
		upper_left_corner_y = view->c_sys.origin.y -
			width_units/2.0 * view->c_sys.x_axis.y +
			height_units/2.0 * view->c_sys.y_axis.y; 
		
		upper_left_corner_z = view->c_sys.origin.z -
			width_units/2.0 * view->c_sys.x_axis.z +
			height_units/2.0 * view->c_sys.y_axis.z; 

		ray_direction.x = view->c_sys.z_axis.x;
		ray_direction.y = view->c_sys.z_axis.y;
		ray_direction.z = view->c_sys.z_axis.z;

printf("origin: %f %f %f\n",    view->c_sys.origin.x ,
				view->c_sys.origin.y,
				view->c_sys.origin.z );
printf("x axis: %f %f %f\n",    view->c_sys.x_axis.x ,
				view->c_sys.x_axis.y,
				view->c_sys.x_axis.z );
printf("y axis: %f %f %f\n",    view->c_sys.y_axis.x ,
				view->c_sys.y_axis.y,
				view->c_sys.y_axis.z );
printf("z axis: %f %f %f\n",    view->c_sys.z_axis.x ,
				view->c_sys.z_axis.y,
				view->c_sys.z_axis.z );
printf("spacings: %f %f\n", x_spacing, y_spacing );


	      for (image_y = view->height_pixels - 1; image_y >= 0; image_y--)
	      {
		if ( image_y % 20 == 0 )
 	   		printf("image_y = %d\n",image_y);

		ray_origin_x = upper_left_corner_x - 
			       (view->height_pixels - image_y) * 
			       view->c_sys.y_axis.x * y_spacing;

		ray_origin_y = upper_left_corner_y - 
			       (view->height_pixels - image_y) * 
			       view->c_sys.y_axis.y * y_spacing;
				
		ray_origin_z = upper_left_corner_z - 
			       (view->height_pixels - image_y) * 
			       view->c_sys.y_axis.z * y_spacing;
				

	    	for (image_x = 0; image_x < view->width_pixels; image_x++)	
	    	{

if ( FALSE )
{
printf("Origin: %f %f %f\n",
	ray_origin_x, ray_origin_y, ray_origin_z );
printf("Direction: %f %f %f\n\n",
	ray_direction.x, ray_direction.y, ray_direction.z );
}

			switch ( view->projection_type )
			{
			  case C_RAY_TRACE:
				rt_info.ray_origin.x = ray_origin_x;
				rt_info.ray_origin.y = ray_origin_y;
				rt_info.ray_origin.z = ray_origin_z;
				rt_info.ray_direction.x = ray_direction.x;
				rt_info.ray_direction.y = ray_direction.y;
				rt_info.ray_direction.z = ray_direction.z;
				C_trace_ray( &rt_info, world, view,
					     &intersect_info );
				break;

			  default:
				C_error_message("Internal Error\n");
				break;
			}

			if ( intersect_info.intersect_volume == 
							vol_of_interest )
			{
				*(xptr++) = 
				    intersect_info.intersect_world_position.x;
				*(yptr++) = 
				    intersect_info.intersect_world_position.y;
				*(zptr++) = 
				    intersect_info.intersect_world_position.z;

				dot_product = C_Dot_Product(
					intersect_info.intersect_world_normal,
					ray_direction );

				*(rxptr++) = -2.0 * dot_product *
				    intersect_info.intersect_world_normal.x  +
				    ray_direction.x;
				
				*(ryptr++) = -2.0 * dot_product *
				    intersect_info.intersect_world_normal.y  +
				    ray_direction.y;
				
				*(rzptr++) = -2.0 * dot_product *
				    intersect_info.intersect_world_normal.z  +
				    ray_direction.z;

				
			}
			else
			{
				*(xptr++)  =   C_BIG_FLOAT;
				*(yptr++)  =   C_BIG_FLOAT;
				*(zptr++)  =   C_BIG_FLOAT;
				*(rxptr++) =   C_BIG_FLOAT;
				*(ryptr++) =   C_BIG_FLOAT;
				*(rzptr++) =   C_BIG_FLOAT;
			}


			ray_origin_x += view->c_sys.x_axis.x * x_spacing;
			ray_origin_y += view->c_sys.x_axis.y * x_spacing;
			ray_origin_z += view->c_sys.x_axis.z * x_spacing;
		}
	
  	      }
	}
	else
	{
		upper_left_corner_x = view->c_sys.origin.x +
			10.0 * view->c_sys.z_axis.x - 
			width_units/2.0 * view->c_sys.x_axis.x +
			height_units/2.0 * view->c_sys.y_axis.x; 
		
		upper_left_corner_y = view->c_sys.origin.y +
			10.0 * view->c_sys.z_axis.y -  
			width_units/2.0 * view->c_sys.x_axis.y +
			height_units/2.0 * view->c_sys.y_axis.y; 
		
		upper_left_corner_z = view->c_sys.origin.z +
			10.0 * view->c_sys.z_axis.z - 
			width_units/2.0 * view->c_sys.x_axis.z +
			height_units/2.0 * view->c_sys.y_axis.z; 

printf("origin: %f %f %f\n",    view->c_sys.origin.x ,
				view->c_sys.origin.y,
				view->c_sys.origin.z );
printf("x axis: %f %f %f\n",    view->c_sys.x_axis.x ,
				view->c_sys.x_axis.y,
				view->c_sys.x_axis.z );
printf("y axis: %f %f %f\n",    view->c_sys.y_axis.x ,
				view->c_sys.y_axis.y,
				view->c_sys.y_axis.z );
printf("z axis: %f %f %f\n",    view->c_sys.z_axis.x ,
				view->c_sys.z_axis.y,
				view->c_sys.z_axis.z );
printf("spacings: %f %f\n", x_spacing, y_spacing );

	      eye_point_x = view->c_sys.origin.x; 

	      eye_point_y = view->c_sys.origin.y; 

	      eye_point_z = view->c_sys.origin.z; 

	      for (image_y = view->height_pixels - 1; image_y >= 0; image_y--)
	      {
		if ( image_y % 20 == 0 )
 	   		printf("image_y = %d\n",image_y);

		ray_origin_x = upper_left_corner_x - 
			       (view->height_pixels - image_y) * 
			       view->c_sys.y_axis.x * y_spacing;

		ray_origin_y = upper_left_corner_y - 
			       (view->height_pixels - image_y) * 
			       view->c_sys.y_axis.y * y_spacing;
				
		ray_origin_z = upper_left_corner_z - 
			       (view->height_pixels - image_y) * 
			       view->c_sys.y_axis.z * y_spacing;
				

	    	for (image_x = 0; image_x < view->width_pixels; image_x++)	
	    	{
			ray_direction.x = ray_origin_x - eye_point_x;
			ray_direction.y = ray_origin_y - eye_point_y;
			ray_direction.z = ray_origin_z - eye_point_z;


			C_Normalize( ray_direction.x, ray_direction.y,
				     ray_direction.z, temp_float );
/*
printf("Eye: %f %f %f\n", eye_point_x, eye_point_y, eye_point_z );
printf("Origin: %f %f %f\n",
	ray_origin_x, ray_origin_y, ray_origin_z );
printf("Direction: %f %f %f\n\n",
	ray_direction.x, ray_direction.y, ray_direction.z );
*/
			switch ( view->projection_type )
			{
			  case C_RAY_TRACE:
				rt_info.ray_origin.x = eye_point_x;
				rt_info.ray_origin.y = eye_point_y;
				rt_info.ray_origin.z = eye_point_z;
				rt_info.ray_direction.x = ray_direction.x;
				rt_info.ray_direction.y = ray_direction.y;
				rt_info.ray_direction.z = ray_direction.z;
				C_trace_ray( &rt_info, world, view,
					     &intersect_info );
				break;

			  default:
				C_error_message("Internal Error\n");
				break;
			}

			if ( intersect_info.intersect_volume == 
							vol_of_interest )
			{
				*(xptr++) = 
				    intersect_info.intersect_world_position.x;
				*(yptr++) = 
				    intersect_info.intersect_world_position.y;
				*(zptr++) = 
				    intersect_info.intersect_world_position.z;

				dot_product = C_Dot_Product(
					intersect_info.intersect_world_normal,
					ray_direction );

				*(rxptr++) = -2.0 * dot_product *
				    intersect_info.intersect_world_normal.x  +
				    ray_direction.x;
				
				*(ryptr++) = -2.0 * dot_product *
				    intersect_info.intersect_world_normal.y  +
				    ray_direction.y;
				
				*(rzptr++) = -2.0 * dot_product *
				    intersect_info.intersect_world_normal.z  +
				    ray_direction.z;

				
			}
			else
			{
				*(xptr++)  =   C_BIG_FLOAT;
				*(yptr++)  =   C_BIG_FLOAT;
				*(zptr++)  =   C_BIG_FLOAT;
				*(rxptr++) =   C_BIG_FLOAT;
				*(ryptr++) =   C_BIG_FLOAT;
				*(rzptr++) =   C_BIG_FLOAT;
			}


			ray_origin_x += view->c_sys.x_axis.x * x_spacing;
			ray_origin_y += view->c_sys.x_axis.y * x_spacing;
			ray_origin_z += view->c_sys.x_axis.z * x_spacing;
		}
	
  	      }
	}

}

