home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
gondwana.ecr.mu.oz.au/pub/
/
Graphics.tar
/
Graphics
/
atomart.tar.gz
/
atomart.tar
/
split.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-06-14
|
4KB
|
171 lines
#include <stdio.h>
#include <math.h>
#include "atomart.h"
#include "macro.h"
extern object *oblist;
extern light *lights;
extern hlist *fhlist;
extern int maxhitlevel;
extern pixel backcol;
extern colour ambient;
extern double power();
extern float tolerance;
/*
* splitleaf
*
* split a leaf along the middle of an axis.
*/
splitleaf(axis, leaf, val)
int axis;
stree *leaf;
float val;
{
olist *objs, *nxtobj, *tmpobj;
stree *left, *right;
int leftcount, rightcount, totcount;
float min, max;
sphere *s;
if (leaf->type != SPLITABLELEAF)
return;
left = (stree *)smalloc(sizeof(stree));
right = (stree *)smalloc(sizeof(stree));
leftcount = rightcount = totcount = 0;
left->u.leaf.oblist = right->u.leaf.oblist = (olist *)NULL;
for (objs = leaf->u.leaf.oblist; objs != (olist *)NULL; objs = nxtobj) {
nxtobj = objs->nxt;
totcount++;
s = objs->obj->u.sph;
switch (axis) {
case X:
min = s->cent.x - s->rad;
max = s->cent.x + s->rad;
break;
case Y:
min = s->cent.y - s->rad;
max = s->cent.y + s->rad;
break;
case Z:
min = s->cent.z - s->rad;
max = s->cent.z + s->rad;
break;
default:
fatal("atomart: bad axis in splitleaf.\n");
}
if (max < val) { /* to the left */
leftcount++;
objs->nxt = left->u.leaf.oblist;
left->u.leaf.oblist = objs;
} else if (min > val) { /* to the right */
rightcount++;
objs->nxt = right->u.leaf.oblist;
right->u.leaf.oblist = objs;
} else { /* in both (sigh) */
tmpobj = (olist *)smalloc(sizeof(olist));
tmpobj->obj = objs->obj;
leftcount++;
tmpobj->nxt = left->u.leaf.oblist;
left->u.leaf.oblist = tmpobj;
rightcount++;
objs->nxt = right->u.leaf.oblist;
right->u.leaf.oblist = objs;
}
}
left->u.leaf.depth = right->u.leaf.depth = leaf->u.leaf.depth + 1;
left->type = (leftcount < MAXOBJS || leaf->u.leaf.depth == 13) ? LEAF : SPLITABLELEAF;
right->type = (rightcount < MAXOBJS || leaf->u.leaf.depth == 13) ? LEAF : SPLITABLELEAF;
left->bb = right->bb = leaf->bb;
left->bb.max[axis] = val;
right->bb.min[axis] = val;
leaf->type = axis;
leaf->splitval = val;
leaf->u.branch.left = left;
leaf->u.branch.right = right;
}
/*
* split
*
* split a splittable leaf into two nodes.
*/
void
split(root)
stree *root;
{
int i, total, left[3], right[3];
float vals[3], min, max;
olist *ol;
sphere *s;
total = 0;
vals[X] = (root->bb.max[X] + root->bb.min[X]) / 2;
vals[Y] = (root->bb.max[Y] + root->bb.min[Y]) / 2;
vals[Z] = (root->bb.max[Z] + root->bb.min[Z]) / 2;
left[X] = right[X] = 0;
left[Y] = right[Y] = 0;
left[Z] = right[Z] = 0;
for (ol = root->u.leaf.oblist; ol != (olist *)NULL; ol = ol->nxt) {
s = ol->obj->u.sph;
min = s->cent.x - s->rad; /* check for x */
max = s->cent.x + s->rad;
if (max < vals[X]) /* to the left */
left[X]++;
else if (min > vals[X]) /* to the right */
right[X]++;
else { /* in both (sigh) */
left[X]++;
right[X]++;
}
min = s->cent.y - s->rad; /* check for y */
max = s->cent.y + s->rad;
if (max < vals[Y]) /* to the left */
left[Y]++;
else if (min > vals[Y]) /* to the right */
right[Y]++;
else { /* in both (sigh) */
left[Y]++;
right[Y]++;
}
min = s->cent.z - s->rad; /* check for z */
max = s->cent.z + s->rad;
if (max < vals[Z]) /* to the left */
left[Z]++;
else if (min > vals[Z]) /* to the right */
right[Z]++;
else { /* in both (sigh) */
left[Z]++;
right[Z]++;
}
}
if ((left[X] + right[X]) < (left[Y] + right[Y]))
if ((left[X] + right[X]) < (left[Z] + right[Z]))
splitleaf(X, root, vals[X]);
else
splitleaf(Z, root, vals[Z]);
else
if ((left[Y] + right[Y]) < (left[Z] + right[Z]))
splitleaf(Y, root, vals[Y]);
else
splitleaf(Z, root, vals[Z]);
}