1 /*
2  * box.c
3  *
4  * Copyright (C) 1989, 1991, Craig E. Kolb
5  * All rights reserved.
6  *
7  * This software may be freely copied, modified, and redistributed
8  * provided that this copyright notice is preserved on all copies.
9  *
10  * You may not distribute this software, in whole or in part, as part of
11  * any commercial product without the express consent of the authors.
12  *
13  * There is no warranty or other guarantee of fitness of this software
14  * for any purpose.  It is provided solely "as is".
15  *
16  * $Id: box.c,v 4.0 91/07/17 14:36:32 kolb Exp Locker: kolb $
17  *
18  * $Log:	box.c,v $
19  * Revision 4.0  91/07/17  14:36:32  kolb
20  * Initial version.
21  *
22  */
23 #include "geom.h"
24 #include "box.h"
25 
26 static Methods *iBoxMethods = NULL;
27 static char boxName[] = "box";
28 
29 unsigned long BoxTests, BoxHits;
30 
31 Box *
BoxCreate(v1,v2)32 BoxCreate(v1, v2)
33 Vector *v1, *v2;
34 {
35 	Box *box;
36 	Vector size;
37 
38 	VecSub(*v1, *v2, &size);
39 
40 	if (equal(size.x, 0.) || equal(size.y, 0.) || equal(size.z, 0.)) {
41 		RLerror(RL_WARN, "Degenerate box.\n");
42 		return (Box *)NULL;
43 	}
44 
45 	box = (Box *)share_malloc(sizeof(Box));
46 	box->bounds[LOW][X] = min(v1->x, v2->x);
47 	box->bounds[HIGH][X] = max(v1->x, v2->x);
48 	box->bounds[LOW][Y] = min(v1->y, v2->y);
49 	box->bounds[HIGH][Y] = max(v1->y, v2->y);
50 	box->bounds[LOW][Z] = min(v1->z, v2->z);
51 	box->bounds[HIGH][Z] = max(v1->z, v2->z);
52 	return box;
53 }
54 
55 Methods *
BoxMethods()56 BoxMethods()
57 {
58 	if (iBoxMethods == (Methods *)NULL) {
59 		iBoxMethods = MethodsCreate();
60 		iBoxMethods->create = (GeomCreateFunc *)BoxCreate;
61 		iBoxMethods->methods = BoxMethods;
62 		iBoxMethods->name = BoxName;
63 		iBoxMethods->intersect = BoxIntersect;
64 		iBoxMethods->normal = BoxNormal;
65 		iBoxMethods->enter = BoxEnter;
66 		iBoxMethods->bounds = BoxBounds;
67 		iBoxMethods->stats = BoxStats;
68 		iBoxMethods->checkbounds = FALSE;
69 		iBoxMethods->closed = TRUE;
70 	}
71 	return iBoxMethods;
72 }
73 
74 int
BoxIntersect(box,ray,mindist,maxdist)75 BoxIntersect(box, ray, mindist, maxdist)
76 Box *box;
77 Ray *ray;
78 Float mindist, *maxdist;
79 {
80 	BoxTests++;
81 	if (BoundsIntersect(ray, box->bounds, mindist, maxdist)) {
82 		BoxHits++;
83 		return TRUE;
84 	}
85 	return FALSE;
86 }
87 
88 int
BoxNormal(box,pos,nrm,gnrm)89 BoxNormal(box, pos, nrm, gnrm)
90 Vector *pos, *nrm, *gnrm;	/* point of intersection */
91 Box *box;
92 {
93 	nrm->x = nrm->y = nrm->z = 0.;
94 
95 	if (equal(pos->x, box->bounds[HIGH][X]))
96 		nrm->x = 1.;
97 	else if (equal(pos->x, box->bounds[LOW][X]))
98 		nrm->x = -1.;
99 	else if (equal(pos->y, box->bounds[HIGH][Y]))
100 		nrm->y = 1.;
101 	else if (equal(pos->y, box->bounds[LOW][Y]))
102 		nrm->y = -1.;
103 	else if (equal(pos->z, box->bounds[HIGH][Z]))
104 		nrm->z = 1.;
105 	else if (equal(pos->z, box->bounds[LOW][Z]))
106 		nrm->z = -1.;
107 	else
108 		RLerror(RL_WARN, "Confusion in nrmbox!\n");
109 	*gnrm = *nrm;
110 	return FALSE;
111 }
112 
113 /*
114  * Determine if ray enters (TRUE) or leaves (FALSE) box at pos
115  */
116 int
BoxEnter(box,ray,mind,hitd)117 BoxEnter(box, ray, mind, hitd)
118 Box *box;
119 Ray *ray;
120 Float mind, hitd;
121 {
122 	Vector pos;
123 
124 	VecAddScaled(ray->pos, mind, ray->dir, &pos);
125 	return OutOfBounds(&pos, box->bounds);
126 }
127 
128 void
BoxBounds(box,bounds)129 BoxBounds(box, bounds)
130 Box *box;
131 Float bounds[2][3];
132 {
133 	BoundsCopy(box->bounds, bounds);
134 }
135 
136 char *
BoxName()137 BoxName()
138 {
139 	return boxName;
140 }
141 
142 void
BoxStats(tests,hits)143 BoxStats(tests, hits)
144 unsigned long *tests, *hits;
145 {
146 	*tests = BoxTests;
147 	*hits = BoxHits;
148 }
149 
150 void
BoxMethodRegister(meth)151 BoxMethodRegister(meth)
152 UserMethodType meth;
153 {
154 	if (iBoxMethods)
155 		iBoxMethods->user = meth;
156 }
157