home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************
- * *
- * Copyright (c) 1988, David B. Wecker *
- * All Rights Reserved *
- * *
- * This file is part of DBW_uRAY *
- * *
- * DBW_uRAY is distributed in the hope that it will be useful, but *
- * WITHOUT ANY WARRANTY. No author or distributor accepts *
- * responsibility to anyone for the consequences of using it or for *
- * whether it serves any particular purpose or works at all, unless *
- * he says so in writing. Refer to the DBW_uRAY General Public *
- * License for full details. *
- * *
- * Everyone is granted permission to copy, modify and redistribute *
- * DBW_uRAY, but only under the conditions described in the *
- * DBW_uRAY General Public License. A copy of this license is *
- * supposed to have been given to you along with DBW_uRAY so you *
- * can know your rights and responsibilities. It should be in a file *
- * named COPYING. Among other things, the copyright notice and this *
- * notice must be preserved on all copies. *
- ************************************************************************
- * *
- * Authors: *
- * DBW - David B. Wecker *
- * *
- * Versions: *
- * V1.0 881023 DBW - First released version *
- * V1.1 881110 DBW - Fixed scan coherence code *
- * V1.2 881125 DBW - Removed ALL scan coherence code (useless) *
- * added "fat" extent boxes *
- * *
- ************************************************************************/
-
- #include "uray.h"
-
-
- /**************************************************************************/
- /* This module builds a hierarchy of oct-tree extents to speed up tracing */
- /**************************************************************************/
-
-
- /* union an extent and a vector. (min of the mins and max of the maxs) */
- void unionvector( re, v, nre )
- EXTENT *re,*nre;
- VEC v;
- {
- int i;
-
- for (i = 0; i < 3; i++) {
- nre->min[i] = MIN(re->min[i], v[i] );
- nre->max[i] = MAX(re->max[i], v[i] );
- }
- }
-
- /* union 2 extents. (min of the mins and max of the maxs) */
- void unionextent( e1, e2, ne )
- EXTENT *e1,*e2,*ne;
- {
- int i;
-
- for (i = 0; i < 3; i++) {
- ne->min[i] = MIN(e1->min[i], e2->min[i] );
- ne->max[i] = MAX(e1->max[i], e2->max[i] );
- }
- }
-
- /* build all extents */
- void getextent(np,e)
- NODE *np;
- EXTENT *e;
- {
- EXTENT newe;
- EXTENT *ext;
- SPHERE *sph;
- RING *flat;
- int i;
- VEC v1,v2;
- FLTDBL rad;
-
- /* initialize the extent */
- for (i=0; i<3; i++) {
- e->min[i] = MYHUGE;
- e->max[i] = -MYHUGE;
- }
-
- while (np) {
- switch (np->typ) {
-
- /* if an extent, build all children, then return result */
- case TYP_E:
- ext = (EXTENT *)np;
- getextent(ext->child,&newe);
- for (i = 0; i < 3; i++) {
- ext->min[i] = newe.min[i];
- ext->max[i] = newe.max[i];
- }
- break;
-
- /* if a sphere, build the extent for this one object */
- case TYP_S:
- sph = (SPHERE *)np;
- rad = sqrt(sph->rad);
- for (i = 0; i < 3; i++) {
- newe.min[i] = sph->cen[i] - (rad + TOL);
- newe.max[i] = sph->cen[i] + (rad + TOL);
- }
- break;
-
- /* if a planar, build the extent for this one object */
- case TYP_T:
- case TYP_Q:
- case TYP_R:
- flat = (RING *)np;
- for (i=0; i<3; i++) {
- newe.min[i] = MYHUGE;
- newe.max[i] = -MYHUGE;
- }
-
- /* do ring specific calculations */
- if (np->typ == TYP_R) {
- rad = sqrt(flat->rad2);
- vcomb(rad,flat->v1,flat->p0,v1);
- vcomb(rad,flat->v2,v1,v2);
- unionvector(&newe,v2,&newe);
- vcomb(-rad,flat->v2,v1,v2);
- unionvector(&newe,v2,&newe);
- vcomb(-rad,flat->v1,flat->p0,v1);
- vcomb(rad,flat->v2,v1,v2);
- unionvector(&newe,v2,&newe);
- vcomb(-rad,flat->v2,v1,v2);
- unionvector(&newe,v2,&newe);
- }
- else {
- vcomb(1.0,flat->p0,flat->v1,v1);
- vcomb(1.0,flat->p0,flat->v2,v2);
- unionvector(&newe,flat->p0,&newe);
- unionvector(&newe,v1,&newe);
- unionvector(&newe,v2,&newe);
- }
-
- /* pad the extent (so no round off errors) */
- for (i=0; i<3; i++) {
- newe.min[i] -= TOL;
- newe.max[i] += TOL;
- }
- break;
- }
-
- /* unionextent for next level up */
- unionextent(e,&newe,e);
-
- /* get next node */
- np = np->next;
- }
- }
-
-
- /* this is the actual routine that builds the extent hierarchy */
- /* The tree can have upto SRTMAX nodes in each bucket and can be upto */
- /* SRTLEV levels deep. These have been tuned for optimal results */
-
- #define SRTMAX 8 /* maximum allowed in one bucket */
- #define SRTLEV 16 /* sort recursion level */
-
- NODE *sortext(ext,lev)
- int lev;
- EXTENT *ext;
- {
- int i,j,x,y,z;
- EXTENT *tmp,*tmp2,*curr,*next;
- FLTDBL cen,ave[3],min[3],max[3];
- struct {
- int count;
- EXTENT *bkt;
- } cube[2][2][2], *cp = &cube[0][0][0];
-
- /* init the 8 extents (to build) */
- for (i=0; i< 8; i++) {
- cp[i].bkt = NULL;
- cp[i].count = 0;
- }
- for (i=0; i<3; i++) {
- min[i] = MYHUGE;
- max[i] = -MYHUGE;
- }
-
- /* compute the extent range */
- curr = ext;
- while (curr) {
- for (i=0; i < 3; i++) {
- if (curr->min[i]<min[i]) min[i] = curr->min[i];
- if (curr->max[i]>max[i]) max[i] = curr->max[i];
- }
- curr = (EXTENT *)curr->next;
- }
-
- /* now compute centers of buckets */
- for (i=0; i<3; i++) ave[i] = 0.5 * (min[i] + max[i]);
-
- /* now place eveybody in buckets */
- curr = ext;
- while (curr) {
- next = (EXTENT *)curr->next;
- for (i=0; i<3; i++) {
- cen = 0.5 * (curr->max[i] + curr->min[i]);
- if (cen >= ave[i]) j = 1;
- else j = 0;
- switch (i) {
- case 0: x = j; break;
- case 1: y = j; break;
- case 2: z = j; break;
- }
- }
- curr->next = (NODE *)cube[x][y][z].bkt;
- cube[x][y][z].bkt = curr;
- cube[x][y][z].count++;
- curr = next;
- }
-
- /* put the buckets back together */
- curr = NULL;
- for (x=0; x<2; x++)
- for (y=0; y<2; y++)
- for (z=0; z<2; z++) {
- if (!cube[x][y][z].count) continue;
-
- /* do we need to split up this bucket */
- if (cube[x][y][z].count > SRTMAX && lev < SRTLEV) {
- cube[x][y][z].bkt = tmp =
- (EXTENT *)sortext(cube[x][y][z].bkt,lev+1);
- cube[x][y][z].count = 0;
- while (tmp) {
- cube[x][y][z].count++;
- tmp = (EXTENT *)tmp->next;
- }
- }
- if (cube[x][y][z].count != 1) {
- tmp = (EXTENT *)doalloc(TYP_E);
- tmp->child = (NODE *)cube[x][y][z].bkt;
- for (i=0; i<3; i++) {
- tmp->min[i] = MYHUGE;
- tmp->max[i] = -MYHUGE;
- }
- tmp2 = (EXTENT *)tmp->child;
- while (tmp2) {
- unionextent(tmp,tmp2,tmp);
- tmp2 = (EXTENT *)tmp2->next;
- }
- cube[x][y][z].bkt = tmp;
- }
- cube[x][y][z].bkt->next = (NODE *)curr;
- curr = cube[x][y][z].bkt;
- }
-
- return((NODE *)curr);
- }
-
- /* top level extent building routine */
- void doextents() {
- VEC scr_v;
- EXTENT e;
-
- /* Get all the leafs of the extent hierarchy */
- printf("Creating object extents\n");
- getextent(nodes,&e);
-
- /* now sort objects (building extent tree) */
- printf("Creating extent tree\n");
- nodes = sortext(nodes,0);
-
- printf("Using %d extents for %d objects\n\n",extcnt,objcnt);
- }
-
-