text:  
  
  
  
  
  
  /*************************************************************************/
  /*                                                                       */
  /*  Copyright (c) 1994 Stanford University                               */
  /*                                                                       */
  /*  All rights reserved.                                                 */
  /*                                                                       */
  /*  Permission is given to use, copy, and modify this software for any   */
  /*  non-commercial purpose as long as this copyright notice is not       */
  /*  removed.  All other uses, including redistribution in whole or in    */
  /*  part, are forbidden without prior written permission.                */
  /*                                                                       */
  /*  This software is provided with absolutely no warranty and no         */
  /*  support.                                                             */
  /*                                                                       */
  /*************************************************************************/
  
  
  /*
   * NAME
   *	husetup.c
   *
   * DESCRIPTION
   *	This file contains routines that initialize, build, traverse, and
   *	intersect the hierarchical uniform grid (HUG) representation of the scene.
   *
   */
  
  
  #include <stdio.h>
  #include <math.h>
  #include "rt.h"
  
  
  
  /*
   * NAME
   *	Huniform_defaults - setup the five HUG parameter defaults
   *
   * SYNOPSIS
   *	VOID	Huniform_defaults()
   *
   * RETURNS
   *	Nothing.
   */
  
  VOID	Huniform_defaults()
  	{
  	hu_max_prims_cell   = 2;
  	hu_gridsize	    = 5;
  	hu_numbuckets	    = 23;
  	hu_max_subdiv_level = 1;
  	hu_lazy 	    = 0;
  	}
  
  
  
  /*
   * NAME
   *	BuildHierarchy_Uniform - build HU grid from model
   *
   * SYNOPSIS
   *	VOID	BuildHierarchy_Uniform()
   *
   * RETURNS
   *	Nothing.
   *
   */
  
  VOID	BuildHierarchy_Uniform()
  	{
  	INT	i;
  	INT	num;
  	INT	num_pe;
  	INT	status;
  	REAL	den;
  	GRID	*g;
  	GRID	*gr;
  	GRID	*ng;
  	GRID	testgrid;
  	VOXEL	*v;
  	RAY	r;
  	RAYINFO *rinfo;
  	ELEMENT **pepa;
  
  	init_masks();
  
  
  	pepa = MakeElementArray(&num_pe);
  
  	v = init_world_voxel(pepa,num_pe);
  
  	gm->world_level_grid = init_world_grid(v, pepa, num_pe);
  	g = gm->world_level_grid;
  
  	ng = create_grid(v, g, num_pe);
  
  	fprintf(stderr, "Uniform Hierarchy built.\n");
  	}
  
  
  
  /*
   * NAME
   *	IntersectHuniformPrimlist - intersect ray with objects in HU cell
   *
   * SYNOPSIS
   *	VOID	IntersectHuniformPrimlist(intersectPrim, hit, plist, r, pid)
   *	BOOL	*intersectPrim; 	// Primitive hit?
   *	IRECORD *hit;			// Intersection record.
   *	ELEMENT **plist;		// Primitive element list.
   *	RAY	*r;			// Original ray.
   *	INT	pid;			// Process id.
   *
   * RETURNS
   *	Nothing.
   *
   */
  
  VOID	IntersectHuniformPrimlist(intersectPrim, hit, v, r, pid)
  INT *intersectPrim;
  IRECORD *hit;
  VOXEL *v;
  RAY	*r;
  INT	pid;
  	{
  	ELEMENT **pptr; 		/* Primitive element list ptr.	     */
  	OBJECT	*peParent;		/* Ptr to parent object.	     */
  	ELEMENT *pe;			/* Primitive element ptr.	     */
  	IRECORD newhit[ISECT_MAX];	/* Hit recorder.		     */
  	INT	hitcode,i;
  	REAL	t_out;
  
  	t_out = r->ri->t_out;
  	hit[0].t = HUGE_REAL;
  	pptr = (ELEMENT**)v->cell;
  
  	for (i = 0; i < v->numelements; i++)
  		{
  		pe	 = pptr[i];
  		peParent = pe->parent;
  		hitcode  = (*peParent->procs->pe_intersect)(r, pe, newhit);
  
  		if (hitcode)
  			if (newhit[0].t < hit[0].t && newhit[0].t < t_out)
  				hit[0] = newhit[0];
  		}
  
  	if (hit[0].t < HUGE_REAL)
  		*intersectPrim = TRUE;
  	else
  		*intersectPrim = FALSE;
  	}
  
  
  
  /*
   * NAME
   *	HuniformShadowIntersect - intersect shadow ray with objects in HU cell
   *
   * SYNOPSIS
   *	REAL	HuniformShadowIntersect(r, lightlength, pe, pid)
   *	RAY	*r;			// Incident ray.
   *	REAL	lightlength;		// Distance to light.
   *	ELEMENT *pe;			// Primitive element of shadow ray origin.
   *	INT	pid;			// Process number.
   *
   * RETURNS
   *	Transparency value along ray to light.
   *
   */
  
  REAL	HuniformShadowIntersect(r, lightlength, pe, pid)
  RAY	*r;
  REAL	lightlength;
  ELEMENT *pe;
  INT	pid;
  	{
  	INT	status;
  	INT	hitcode,i;
  	REAL	trans;			/* Transparency factor. 	     */
  	OBJECT	*peParent;		/* Ptr to parent object.	     */
  	ELEMENT **pptr; 		/* Primitive element list ptr.	     */
  	ELEMENT *pe2;			/* Ptr to element.		     */
  	IRECORD newhit[ISECT_MAX];	/* Hit record.			     */
  	VOXEL	*v;
  
  	trans = 1.0;
  
  	/* Now try uniform hierarchy. */
  
  	r->ri = NULL;
  	v = init_ray(r, gm->world_level_grid);
  
  	if (v == NULL)
  		{
  		reset_rayinfo(r);
  		return(trans);
  		}
  
  	newhit[0].t = HUGE_REAL;
  	status	    = IN_WORLD;
  
  	while (trans > 0.0 && status != EXITED_WORLD)
  		{
  		/* Intersect primitives in cell. */
  
  		pptr = (ELEMENT**)v->cell;
  
  		for (i = 0; (i < v->numelements) && (trans > 0.0); i++)
  			{
  			pe2	 = pptr[i];
  			peParent = pe2->parent;
  			hitcode  = (*peParent->procs->pe_intersect)(r, pe2, newhit);
  
  			if (hitcode && newhit[0].pelem != pe && newhit[0].t < lightlength)
  				trans *= newhit[0].pelem->parent->surf->ktran;
  
  			}
  
  		if (trans > 0.0)
  			v = next_nonempty_leaf(r, STEP, &status);
  		}
  
  	reset_rayinfo(r);
  	return (trans);
  	}
  
  
  
  /*
   * NAME
   *	TraverseHierarchyUniform - walk the HU grid to intersect a ray
   *
   * SYNOPSIS
   *	BOOL	TraverseHierarchyUniform(r, hit, pid)
   *	RAY	*r;
   *	IRECORD *hit;
   *	INT	pid;
   *
   * RETURNS
   *	TRUE if the ray hit something, FALSE otherwise.
   *
   */
  
  BOOL	TraverseHierarchyUniform(r, hit, pid)
  RAY	*r;
  IRECORD *hit;
  INT	pid;
  	{
  	INT	status;
  	INT	intersectPrim;
  	VOXEL	*v;
  
  	r->ri = NULL;
  	v = init_ray(r, gm->world_level_grid);
  
  	if (v == NULL)
  		{
  		reset_rayinfo(r);
  		return (FALSE);
  		}
  
  	intersectPrim = FALSE;
  	hit[0].t      = HUGE_REAL;
  	status	      = IN_WORLD;
  
  	while (!intersectPrim && status != EXITED_WORLD)
  		{
  		IntersectHuniformPrimlist(&intersectPrim, hit, v, r, pid);
  
  		if (!intersectPrim)
  			v = next_nonempty_leaf(r, STEP, &status);
  		}
  
  	reset_rayinfo(r);
  	return (intersectPrim);
  	}
  
  