1 /*
2 Copyright (c) 2005-2021 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 /*
18 The original source for this example is
19 Copyright (c) 1994-2008 John E. Stone
20 All rights reserved.
21
22 Redistribution and use in source and binary forms, with or without
23 modification, are permitted provided that the following conditions
24 are met:
25 1. Redistributions of source code must retain the above copyright
26 notice, this list of conditions and the following disclaimer.
27 2. Redistributions in binary form must reproduce the above copyright
28 notice, this list of conditions and the following disclaimer in the
29 documentation and/or other materials provided with the distribution.
30 3. The name of the author may not be used to endorse or promote products
31 derived from this software without specific prior written permission.
32
33 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
34 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
37 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 SUCH DAMAGE.
44 */
45
46 /*
47 * bndbox.cpp - This file contains the functions for dealing with bounding boxes.
48 */
49
50 #include "machine.hpp"
51 #include "types.hpp"
52 #include "macros.hpp"
53 #include "vector.hpp"
54 #include "intersect.hpp"
55 #include "util.hpp"
56
57 #define BNDBOX_PRIVATE
58 #include "bndbox.hpp"
59
60 static object_methods bndbox_methods = { (void (*)(void *, void *))(bndbox_intersect),
61 (void (*)(void *, void *, void *, void *))(nullptr),
62 bndbox_bbox,
63 free_bndbox };
64
newbndbox(vector min,vector max)65 bndbox *newbndbox(vector min, vector max) {
66 bndbox *b;
67
68 b = (bndbox *)rt_getmem(sizeof(bndbox));
69 memset(b, 0, sizeof(bndbox));
70 b->min = min;
71 b->max = max;
72 b->methods = &bndbox_methods;
73
74 b->objlist = nullptr;
75 b->tex = nullptr;
76 b->nextobj = nullptr;
77 return b;
78 }
79
bndbox_bbox(void * obj,vector * min,vector * max)80 static int bndbox_bbox(void *obj, vector *min, vector *max) {
81 bndbox *b = (bndbox *)obj;
82
83 *min = b->min;
84 *max = b->max;
85
86 return 1;
87 }
88
free_bndbox(void * v)89 static void free_bndbox(void *v) {
90 bndbox *b = (bndbox *)v;
91
92 free_objects(b->objlist);
93
94 free(b);
95 }
96
bndbox_intersect(bndbox * bx,ray * ry)97 static void bndbox_intersect(bndbox *bx, ray *ry) {
98 flt a, tx1, tx2, ty1, ty2, tz1, tz2;
99 flt tnear, tfar;
100 object *obj;
101 ray newray;
102
103 /* eliminate bounded rays whose bounds do not intersect */
104 /* the bounds of the box.. */
105 if (ry->flags & RT_RAY_BOUNDED) {
106 if ((ry->s.x > bx->max.x) && (ry->e.x > bx->max.x))
107 return;
108 if ((ry->s.x < bx->min.x) && (ry->e.x < bx->min.x))
109 return;
110
111 if ((ry->s.y > bx->max.y) && (ry->e.y > bx->max.y))
112 return;
113 if ((ry->s.y < bx->min.y) && (ry->e.y < bx->min.y))
114 return;
115
116 if ((ry->s.z > bx->max.z) && (ry->e.z > bx->max.z))
117 return;
118 if ((ry->s.z < bx->min.z) && (ry->e.z < bx->min.z))
119 return;
120 }
121
122 tnear = -FHUGE;
123 tfar = FHUGE;
124
125 if (ry->d.x == 0.0) {
126 if ((ry->o.x < bx->min.x) || (ry->o.x > bx->max.x))
127 return;
128 }
129 else {
130 tx1 = (bx->min.x - ry->o.x) / ry->d.x;
131 tx2 = (bx->max.x - ry->o.x) / ry->d.x;
132 if (tx1 > tx2) {
133 a = tx1;
134 tx1 = tx2;
135 tx2 = a;
136 }
137 if (tx1 > tnear)
138 tnear = tx1;
139 if (tx2 < tfar)
140 tfar = tx2;
141 }
142 if (tnear > tfar)
143 return;
144 if (tfar < 0.0)
145 return;
146
147 if (ry->d.y == 0.0) {
148 if ((ry->o.y < bx->min.y) || (ry->o.y > bx->max.y))
149 return;
150 }
151 else {
152 ty1 = (bx->min.y - ry->o.y) / ry->d.y;
153 ty2 = (bx->max.y - ry->o.y) / ry->d.y;
154 if (ty1 > ty2) {
155 a = ty1;
156 ty1 = ty2;
157 ty2 = a;
158 }
159 if (ty1 > tnear)
160 tnear = ty1;
161 if (ty2 < tfar)
162 tfar = ty2;
163 }
164 if (tnear > tfar)
165 return;
166 if (tfar < 0.0)
167 return;
168
169 if (ry->d.z == 0.0) {
170 if ((ry->o.z < bx->min.z) || (ry->o.z > bx->max.z))
171 return;
172 }
173 else {
174 tz1 = (bx->min.z - ry->o.z) / ry->d.z;
175 tz2 = (bx->max.z - ry->o.z) / ry->d.z;
176 if (tz1 > tz2) {
177 a = tz1;
178 tz1 = tz2;
179 tz2 = a;
180 }
181 if (tz1 > tnear)
182 tnear = tz1;
183 if (tz2 < tfar)
184 tfar = tz2;
185 }
186 if (tnear > tfar)
187 return;
188 if (tfar < 0.0)
189 return;
190
191 /* intersect all of the enclosed objects */
192 newray = *ry;
193 newray.flags |= RT_RAY_BOUNDED;
194
195 RAYPNT(newray.s, (*ry), tnear);
196 RAYPNT(newray.e, (*ry), (tfar + EPSILON));
197
198 obj = bx->objlist;
199 while (obj != nullptr) {
200 obj->methods->intersect(obj, &newray);
201 obj = (object *)obj->nextobj;
202 }
203 }
204