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