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


int C_rt_geo_polygon( world, rt_info, iptr, closest_distance,
		      shade_info )
C_World				*world;
C_RayTraceInfo			*rt_info;
C_IntersectionList		*iptr;
float				*closest_distance;
C_ShadeInfo			*shade_info;
{
	extern C_transform_fposition(); 
	extern C_transform_fvector(); 

	int			loop;
	C_Volume		*volume;
	float			dot_product;	
	float			t, distance;
	C_FPosition		new_ray_origin;
	C_FPosition		point_one;
	C_FPosition		intersection_point;
	C_FPosition		junk_point;
	C_FVector		new_ray_direction;
	C_FVector		normal;
	C_FVector		world_normal;
	float			current_intersection;
	float			diffx, diffy, diffz;

	C_GeoData		*table_entry;

	C_Polygon		*polygon;

	C_FPosition		*vertex_ptr1, *vertex_ptr2;
	int			cross_count;

	volume = world->volume[iptr->volume];

	C_transform_fvector( &(rt_info->ray_direction), 
			     &(rt_info->ray_origin), 
			     &(new_ray_direction), &(new_ray_origin),
	 		     &(volume->wtol_voxels) );


	table_entry = volume->data.geo_data;

	polygon = table_entry->geo_object.polygon;

	/****    Intersect the ray with the plane    ****/
	/****    equation for this polygon to find   ****/
	/****	 the point at which they cross.	     ****/

	dot_product = new_ray_direction.x * polygon->plane.a +
		      new_ray_direction.y * polygon->plane.b +
		      new_ray_direction.z * polygon->plane.c;

	if ( dot_product != 0.0 )
	{

	    if ( dot_product < 0.0 )
	    {
		polygon->plane.a = -polygon->plane.a;
		polygon->plane.b = -polygon->plane.b;
		polygon->plane.c = -polygon->plane.c;
		polygon->plane.d = -polygon->plane.d;

		dot_product = -dot_product;
	    }
				
	    t = -1.0 * (polygon->plane.a * new_ray_origin.x + 
			polygon->plane.b * new_ray_origin.y + 
			polygon->plane.c * new_ray_origin.z +
			polygon->plane.d) / dot_product; 

	    if ( t >= 0.0  && 
		(rt_info->ray_type == C_PRIMARY_RAY ||
		 t >= 0.0001))
	    {
		point_one.x = new_ray_direction.x*t + 
				new_ray_origin.x;
		point_one.y = new_ray_direction.y*t + 
				new_ray_origin.y;
		point_one.z = new_ray_direction.z*t + 
				new_ray_origin.z;

		vertex_ptr1 = polygon->vertices +
			      polygon->num_vertices - 1;

		vertex_ptr2 = polygon->vertices;

		cross_count = 0;	

		if ((fabs((double)polygon->plane.a) >= 
		     fabs((double)polygon->plane.b)) &&
		    (fabs((double)polygon->plane.a) >= 
		     fabs((double)polygon->plane.c)))
		{
		  for (loop=0; loop<polygon->num_vertices; 
		       loop++)
		  {
		    if ((C_Sign((vertex_ptr1->y-point_one.y)))!=
		        (C_Sign((vertex_ptr2->y-point_one.y))))
		    {
		      if ( (vertex_ptr1->z - point_one.z) > 0 &&
			 (vertex_ptr2->z - point_one.z) > 0 )
		      {
			cross_count++;
		      }
		      else if ((vertex_ptr1->z-point_one.z)>0 ||
			     (vertex_ptr2->z-point_one.z)>0 )
		      {
			if (( (vertex_ptr1->z-point_one.z) -
			      (vertex_ptr1->y-point_one.y)*
			     ((vertex_ptr2->z-vertex_ptr1->z)/
			      (vertex_ptr2->y-vertex_ptr1->y)))
			     > 0 )
			{
			  	cross_count++;
			}
		      }
		    }
		    vertex_ptr1 = vertex_ptr2;
		    vertex_ptr2++;
		  }
		} 
		else if ((fabs((double)polygon->plane.b) >= 
			  fabs((double)polygon->plane.a))
		     && (fabs((double)polygon->plane.b) >= 
			 fabs((double)polygon->plane.c)))
		{
		  for (loop=0; loop<polygon->num_vertices; 
		       loop++)
		  {
		    if ((C_Sign((vertex_ptr1->z-point_one.z)))!=
		        (C_Sign((vertex_ptr2->z-point_one.z))))
		    {
		      if ( (vertex_ptr1->x - point_one.x) > 0 &&
			 (vertex_ptr2->x - point_one.x) > 0 )
		      {
			cross_count++;
		      }
		      else if ((vertex_ptr1->x-point_one.x)>0 ||
			     (vertex_ptr2->x-point_one.x)>0 )
		      {
			if (( (vertex_ptr1->x-point_one.x) -
			      (vertex_ptr1->z-point_one.z)*
			     ((vertex_ptr2->x-vertex_ptr1->x)/
			      (vertex_ptr2->z-vertex_ptr1->z)))
			     > 0 )
			{
			  	cross_count++;
			}
		      }
		    }
		    vertex_ptr1 = vertex_ptr2;
		    vertex_ptr2++;
		  }
		}
		else
		{
		  for (loop=0; loop<polygon->num_vertices; 
		       loop++)
		  {
		    if ((C_Sign((vertex_ptr1->y-point_one.y)))!=
		        (C_Sign((vertex_ptr2->y-point_one.y))))
		    {
		      if ( (vertex_ptr1->x - point_one.x) > 0 &&
			 (vertex_ptr2->x - point_one.x) > 0 )
		      {
			cross_count++;
		      }
		      else if ((vertex_ptr1->x-point_one.x)>0 ||
			     (vertex_ptr2->x-point_one.x)>0 )
		      {
			if (( (vertex_ptr1->x-point_one.x) -
			      (vertex_ptr1->y-point_one.y)*
			     ((vertex_ptr2->x-vertex_ptr1->x)/
			      (vertex_ptr2->y-vertex_ptr1->y)))
			     > 0 )
			{
			  	cross_count++;
			}
		      }
		    }
		    vertex_ptr1 = vertex_ptr2;
		    vertex_ptr2++;
		  }
		}

		
		if ( (cross_count%2) )
		{

		    C_transform_fposition( &point_one,
			&intersection_point, 
			&(volume->ltow_voxels) );

		    diffx = intersection_point.x - 
					rt_info->ray_origin.x;
		    diffy = intersection_point.y - 
					rt_info->ray_origin.y;
		    diffz = intersection_point.z - 
					rt_info->ray_origin.z;

        	    current_intersection = (float) sqrt ( 
	    		C_Square( diffx ) +
	    		C_Square( diffy ) +
			C_Square( diffz ) );


		    if ( current_intersection < *closest_distance &&
			 current_intersection < iptr->max_distance )
		    {
		        *closest_distance = current_intersection;

			normal.x = polygon->plane.a; 
			normal.y = polygon->plane.b; 
			normal.z = polygon->plane.c; 

			C_transform_fvector( 
			  &(normal), &(intersection_point),
			  &(world_normal), 
			  &(junk_point),
			  &(volume->ltow_units));

		 	  shade_info->world_distance = current_intersection;
		 	  shade_info->volume_num = iptr->volume;
		 	  shade_info->world_point.x = intersection_point.x;
		 	  shade_info->world_point.y = intersection_point.y;
		 	  shade_info->world_point.z = intersection_point.z;
		 	  shade_info->local_point.x = point_one.x;
		 	  shade_info->local_point.y = point_one.y;
		 	  shade_info->local_point.z = point_one.z;
		       	  shade_info->world_normal.x = world_normal.x;
			  shade_info->world_normal.y = world_normal.y;
			  shade_info->world_normal.z = world_normal.z;
		    }
		}
	    }
	}
}


