This is bounds.c in view mode; [Download] [Up]
/* * bounds.c * * Copyright (C) 1989, 1991, Craig E. Kolb * All rights reserved. * * This software may be freely copied, modified, and redistributed * provided that this copyright notice is preserved on all copies. * * You may not distribute this software, in whole or in part, as part of * any commercial product without the express consent of the authors. * * There is no warranty or other guarantee of fitness of this software * for any purpose. It is provided solely "as is". * * $Id$ * * $Log$ */ #include "object.h" /* * Check for intersection between bounding box and the given ray. * If there is an intersection between mindist and *maxdist along * the ray, *maxdist is replaced with the distance to the point of * intersection, and TRUE is returned. Otherwise, FALSE is returned. * * If this routine is used to check for intersection with a volume * rather than a "hollow" box, one should first determine if * (ray->pos + mindist * ray->dir) is inside the bounding volume, and * call BoundsIntersect() only if it is not. */ int BoundsIntersect(ray, bounds, mindist, maxdist) Ray *ray; Float bounds[2][3], mindist, *maxdist; { Float t, tmin, tmax; Float dir, pos; tmax = *maxdist; tmin = mindist; dir = ray->dir.x; pos = ray->pos.x; if (dir < 0) { t = (bounds[LOW][X] - pos) / dir; if (t < tmin) return FALSE; if (t <= tmax) tmax = t; t = (bounds[HIGH][X] - pos) / dir; if (t >= tmin) { if (t > tmax) return FALSE; tmin = t; } } else if (dir > 0.) { t = (bounds[HIGH][X] - pos) / dir; if (t < tmin) return FALSE; if (t <= tmax) tmax = t; t = (bounds[LOW][X] - pos) / dir; if (t >= tmin) { if (t > tmax) return FALSE; tmin = t; } } else if (pos < bounds[LOW][X] || pos > bounds[HIGH][X]) return FALSE; dir = ray->dir.y; pos = ray->pos.y; if (dir < 0) { t = (bounds[LOW][Y] - pos) / dir; if (t < tmin) return FALSE; if (t <= tmax) tmax = t; t = (bounds[HIGH][Y] - pos) / dir; if (t >= tmin) { if (t > tmax) return FALSE; tmin = t; } } else if (dir > 0.) { t = (bounds[HIGH][Y] - pos) / dir; if (t < tmin) return FALSE; if (t <= tmax) tmax = t; t = (bounds[LOW][Y] - pos) / dir; if (t >= tmin) { if (t > tmax) return FALSE; tmin = t; } } else if (pos < bounds[LOW][Y] || pos > bounds[HIGH][Y]) return FALSE; dir = ray->dir.z; pos = ray->pos.z; if (dir < 0) { t = (bounds[LOW][Z] - pos) / dir; if (t < tmin) return FALSE; if (t <= tmax) tmax = t; t = (bounds[HIGH][Z] - pos) / dir; if (t >= tmin) { if (t > tmax) return FALSE; tmin = t; } } else if (dir > 0.) { t = (bounds[HIGH][Z] - pos) / dir; if (t < tmin) return FALSE; if (t <= tmax) tmax = t; t = (bounds[LOW][Z] - pos) / dir; if (t >= tmin) { if (t > tmax) return FALSE; tmin = t; } } else if (pos < bounds[LOW][Z] || pos > bounds[HIGH][Z]) return FALSE; if (tmin == mindist) { if (tmax < *maxdist) { *maxdist = tmax; return TRUE; } } else { if (tmin < *maxdist) { *maxdist = tmin; return TRUE; } } return FALSE; /* hit, but not closer than maxdist */ } /* * Transform an object's bounding box by the given transformation * matrix. */ void BoundsTransform(trans, objbounds) Matrix *trans; Float objbounds[2][3]; { Vector tmp; Float bounds[2][3]; int x, y, z; /* * Can't (and shouldn't) do anything with unbounded objects. */ if (objbounds[LOW][X] > objbounds[HIGH][X]) return; BoundsInit(bounds); /* * Find bounding box of transformed corners of bounding box. */ for (x = 0 ; x < 2; x++) { for (y = 0; y < 2; y++) { for (z = 0; z < 2; z++) { tmp.x = objbounds[x][X]; tmp.y = objbounds[y][Y]; tmp.z = objbounds[z][Z]; PointTransform(&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; } } } BoundsCopy(bounds, objbounds); } void BoundsInit(bounds) Float 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; } void BoundsCopy(from, into) Float into[2][3], from[2][3]; { into[LOW][X] = from[LOW][X]; into[LOW][Y] = from[LOW][Y]; into[LOW][Z] = from[LOW][Z]; into[HIGH][X] = from[HIGH][X]; into[HIGH][Y] = from[HIGH][Y]; into[HIGH][Z] = from[HIGH][Z]; } #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. */ void BoundsEnlarge(old, new) Float 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]); } void BoundsPrint(box, fp) Float box[2][3]; FILE *fp; { fprintf(fp,"\tX: %f to %f\n",box[LOW][X], box[HIGH][X]); fprintf(fp,"\tY: %f to %f\n",box[LOW][Y], box[HIGH][Y]); fprintf(fp,"\tZ: %f to %f\n",box[LOW][Z], box[HIGH][Z]); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.