#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include "GraphicsGems.h"
#include "data_structure.h"
#include "objects.h"

#include "raddecl.h"

static get_ray_bound(s,d,t1,t2,b)
Point3 *s;
Vector3 *d;
double t1,t2;
Box3 *b;
{
	Point3 p1,p2;
	point_on_line(*s,*d,t1,p1);
	point_on_line(*s,*d,t2,p2);
	b->min.x = MIN(p1.x,p2.x); b->max.x = MAX(p1.x,p2.x);
	b->min.y = MIN(p1.y,p2.y); b->max.y = MAX(p1.y,p2.y);
	b->min.z = MIN(p1.z,p2.z); b->max.z = MAX(p1.z,p2.z);
}

int get_nearest_object_in_voxel(ray,t_entry,t_exit,vox,min_t,pu,pv)
/*
	Intersects the ray with all the objects intersecting
	the given voxel (vox). In case of a valid intersection returns
	the nearest object with the ray parameter (min_t) and surface 
	parameters (pu,pv), otherwise returns UNDEFINED.

	To speed up the routine :
	1. The mail_box is checked first.
	2. The ray extent and the object extent are checked for overlap.
	   Only if there is any overlap there is a possibility of intersection.
*/
Ray *ray;		/* 
				start		input
				direction	input
				number 		input
				intersections	input & output
			*/
double t_entry,t_exit;	/* Input */
Voxel *vox;		/* Input */
double *min_t,*pu,*pv;	/* Output */
{
	int i;
	int nearest_object = UNDEFINED;
	Box3 ray_bound;
	double u=0.,v=0.;
	double t= -1.0;
	int bounds_overlap();

	*min_t = LARGE;

	get_ray_bound(&(ray->start),&(ray->direction),t_entry,t_exit,&ray_bound);
	/* ray_bound will be used to speed of intersection of ray
   		with object in the voxel list */
	for(i=0 ; i < vox->nobjects; i++){
#if defined (EXTRADEBUG)
	for(i=0; i < number_objects;i++){
#endif
		int object_num = vox->intersecting_object_list[i];
#if defined (EXTRADEBUG)
		int object_num = i;
#endif
		/* Enquire the mail box */
		if (object[object_num].mail_box.ray_num == ray->number){
			t = object[object_num].mail_box.t;
			u = object[object_num].mail_box.u;
			v = object[object_num].mail_box.v;
		}
		else if (bounds_overlap(&(object[object_num].bbox),&(ray_bound))){
#if defined(DEBUG)
			(ray->intersections)++;
#endif
			t  = ofunc[
				object[object_num].surface_geometry_type
			     ].intersect_object
		     		(object[object_num].object_specific_structure,
				&(ray->start),&(ray->direction),&u,&v);
			object[object_num].mail_box.ray_num = ray->number;
			object[object_num].mail_box.t = t;
			object[object_num].mail_box.u = u;
			object[object_num].mail_box.v = v;
		}
		if (t > 0.0) /* If a valid intersection */
			if ((t_entry <= t) && (t_exit >= t))
			     /*If the intersection is within bound*/
				if (t < *min_t){
					nearest_object = object_num;
					*min_t = t; *pu = u; *pv = v;
				}
	}
	return(nearest_object);
}
