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