home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
GRAPHICS
/
rayshade.lzh
/
bounds.c
< prev
next >
Wrap
Text File
|
1990-05-08
|
6KB
|
265 lines
/*
* bounds.c
*
* Copyright (C) 1989, Craig E. Kolb
*
* This software may be freely copied, modified, and redistributed,
* provided that this copyright notice is preserved on all copies.
*
* There is no warranty or other guarantee of fitness for this software,
* it is provided solely . Bug reports or fixes may be sent
* to the author, who may or may not act on them as he desires.
*
* You may not include this software in a program or other software product
* without supplying the source, or without informing the end-user that the
* source is available for no extra charge.
*
* If you modify this software, you should include a notice giving the
* name of the person performing the modification, the date of modification,
* and the reason for such modification.
*
* $Id: bounds.c,v 3.0.1.1 90/04/04 19:03:47 craig Exp $
*
* $Log: bounds.c,v $
* Revision 3.0.1.1 90/04/04 19:03:47 craig
* patch5: Substituded FAR_AWAY for HUGE in bounds initialization routines.
*
* Revision 3.0 89/10/27 02:05:46 craig
* Baseline for first official release.
*
*/
#include <stdio.h>
#include <math.h>
#include "constants.h"
#include "typedefs.h"
#include "funcdefs.h"
/*
* Ray-bounding box intersection test.
*/
double
IntBounds(ray, bounds)
Ray *ray;
double bounds[2][3];
{
double t, tmin, tmax, bmin, bmax;
double dir, pos;
extern unsigned long BVTests;
BVTests++;
tmin = 0.;
tmax = FAR_AWAY;
dir = ray->dir.x;
pos = ray->pos.x;
if (dir < 0) {
bmin = bounds[HIGH][X];
bmax = bounds[LOW][X];
} else {
bmax = bounds[HIGH][X];
bmin = bounds[LOW][X];
}
if (dir != 0.) { /* check x-faces */
t = (bmax - pos) / dir;
if (t < 0.)
return 0.;
if (t <= tmax)
tmax = t;
t = (bmin - pos) / dir;
if (t >= 0.) {
if (t > tmax)
return 0.;
tmin = t;
}
} else if (pos < bmin || pos > bmax)
return 0.;
dir = ray->dir.y;
pos = ray->pos.y;
if (dir < 0) {
bmin = bounds[HIGH][Y];
bmax = bounds[LOW][Y];
} else {
bmax = bounds[HIGH][Y];
bmin = bounds[LOW][Y];
}
if (dir != 0.) { /* check y-faces */
t = (bmax - pos) / dir;
if (t < 0.)
return 0.;
if (t <= tmax) {
if (t < tmin)
return 0.;
tmax = t;
}
t = (bmin - pos) / dir;
if (t >= tmin) {
if (t > tmax)
return 0.;
tmin = t;
}
} else if (pos < bmin || pos > bmax)
return 0.;
dir = ray->dir.z;
pos = ray->pos.z;
if (dir < 0) {
bmin = bounds[HIGH][Z];
bmax = bounds[LOW][Z];
} else {
bmax = bounds[HIGH][Z];
bmin = bounds[LOW][Z];
}
if (dir != 0.) { /* check z-faces */
t = (bmax - pos) / dir;
if (t < 0.)
return 0.;
if (t <= tmax) {
if (t < tmin)
return 0.;
tmax = t;
}
t = (bmin - pos) / dir;
if (t >= tmin) {
if (t > tmax)
return 0.;
tmin = t;
}
} else if (pos < bmin || pos > bmax)
return 0.;
return tmin;
}
/*
* Transform an object's bounding box by the given transformation
* matrix.
*/
transform_bounds(trans, objbounds)
TransInfo *trans;
double objbounds[2][3];
{
Vector v, tmp;
double bounds[2][3];
int x, y, z;
init_bounds(bounds);
/*
* Find bounding box of transformed corners of bounding box.
*/
for (x = 0 ; x < 2; x++) {
v.x = objbounds[x][X];
for (y = 0; y < 2; y++) {
v.y = objbounds[y][Y];
for (z = 0; z < 2; z++) {
v.z = objbounds[z][Z];
tmp = v;
transform_point(&tmp, trans);
if (tmp.x < bounds[LOW][X])
bounds[LOW][X] = tmp.x;
if (tmp.x > bounds[HIGH][X])
bounds[HIGH][X] = tmp.x;
if (tmp.y < bounds[LOW][Y])
bounds[LOW][Y] = tmp.y;
if (tmp.y > bounds[HIGH][Y])
bounds[HIGH][Y] = tmp.y;
if (tmp.z < bounds[LOW][Z])
bounds[LOW][Z] = tmp.z;
if (tmp.z > bounds[HIGH][Z])
bounds[HIGH][Z] = tmp.z;
}
}
}
for (x = 0; x < 3; x++) {
objbounds[LOW][x] = bounds[LOW][x];
objbounds[HIGH][x] = bounds[HIGH][x];
}
}
init_bounds(bounds)
double bounds[2][3];
{
bounds[LOW][X] = bounds[LOW][Y] = bounds[LOW][Z] = FAR_AWAY;
bounds[HIGH][X] = bounds[HIGH][Y] = bounds[HIGH][Z] = -FAR_AWAY;
}
/*
* Walk through a linked-list of objects. If the object is unbounded,
* unlink it it from the list and add it to the 'unbounded' list.
* If the object is bounded, enlarge the given bounding box if
* necessary. Return pointer to unbounded list.
*/
ObjList *
find_bounds(list, bounds)
ObjList **list;
double bounds[2][3];
{
ObjList *ltmp, *prev, *oltmp;
ObjList *unbounded;
Object *otmp;
init_bounds(bounds);
prev = unbounded = (ObjList *)0;
for (ltmp = *list; ltmp; ltmp = ltmp->next) {
otmp = ltmp->data;
if (otmp->bounds[LOW][X] > otmp->bounds[HIGH][X]) {
/*
* Object is unbounded -- unlink it...
*/
if (prev)
prev->next = ltmp->next;
else
*list = ltmp->next;
/*
* And add it to unbounded object list.
*/
oltmp = (ObjList *)Malloc(sizeof(ObjList));
oltmp->data = otmp;
oltmp->next = unbounded;
unbounded = oltmp;
} else {
/*
* Object is bounded.
*/
enlarge_bounds(bounds, otmp->bounds);
prev = ltmp;
}
}
return unbounded;
}
#define SetIfLess(a, b) (a = (a) < (b) ? (a) : (b))
#define SetIfGreater(a, b) (a = (a) > (b) ? (a) : (b))
/*
* Find bounding box of the union of two bounding boxes.
*/
enlarge_bounds(old, new)
double old[2][3], new[2][3];
{
SetIfLess(old[LOW][X], new[LOW][X]);
SetIfLess(old[LOW][Y], new[LOW][Y]);
SetIfLess(old[LOW][Z], new[LOW][Z]);
SetIfGreater(old[HIGH][X], new[HIGH][X]);
SetIfGreater(old[HIGH][Y], new[HIGH][Y]);
SetIfGreater(old[HIGH][Z], new[HIGH][Z]);
}
print_bounds(box)
double box[2][3];
{
extern FILE *fstats;
fprintf(fstats,"\tX: %f to %f\n",box[LOW][X], box[HIGH][X]);
fprintf(fstats,"\tY: %f to %f\n",box[LOW][Y], box[HIGH][Y]);
fprintf(fstats,"\tZ: %f to %f\n",box[LOW][Z], box[HIGH][Z]);
}