1*d86ed7fbStbbdev /*
2*d86ed7fbStbbdev     Copyright (c) 2005-2020 Intel Corporation
3*d86ed7fbStbbdev 
4*d86ed7fbStbbdev     Licensed under the Apache License, Version 2.0 (the "License");
5*d86ed7fbStbbdev     you may not use this file except in compliance with the License.
6*d86ed7fbStbbdev     You may obtain a copy of the License at
7*d86ed7fbStbbdev 
8*d86ed7fbStbbdev         http://www.apache.org/licenses/LICENSE-2.0
9*d86ed7fbStbbdev 
10*d86ed7fbStbbdev     Unless required by applicable law or agreed to in writing, software
11*d86ed7fbStbbdev     distributed under the License is distributed on an "AS IS" BASIS,
12*d86ed7fbStbbdev     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d86ed7fbStbbdev     See the License for the specific language governing permissions and
14*d86ed7fbStbbdev     limitations under the License.
15*d86ed7fbStbbdev */
16*d86ed7fbStbbdev 
17*d86ed7fbStbbdev /*
18*d86ed7fbStbbdev     The original source for this example is
19*d86ed7fbStbbdev     Copyright (c) 1994-2008 John E. Stone
20*d86ed7fbStbbdev     All rights reserved.
21*d86ed7fbStbbdev 
22*d86ed7fbStbbdev     Redistribution and use in source and binary forms, with or without
23*d86ed7fbStbbdev     modification, are permitted provided that the following conditions
24*d86ed7fbStbbdev     are met:
25*d86ed7fbStbbdev     1. Redistributions of source code must retain the above copyright
26*d86ed7fbStbbdev        notice, this list of conditions and the following disclaimer.
27*d86ed7fbStbbdev     2. Redistributions in binary form must reproduce the above copyright
28*d86ed7fbStbbdev        notice, this list of conditions and the following disclaimer in the
29*d86ed7fbStbbdev        documentation and/or other materials provided with the distribution.
30*d86ed7fbStbbdev     3. The name of the author may not be used to endorse or promote products
31*d86ed7fbStbbdev        derived from this software without specific prior written permission.
32*d86ed7fbStbbdev 
33*d86ed7fbStbbdev     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
34*d86ed7fbStbbdev     OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35*d86ed7fbStbbdev     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36*d86ed7fbStbbdev     ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
37*d86ed7fbStbbdev     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38*d86ed7fbStbbdev     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39*d86ed7fbStbbdev     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40*d86ed7fbStbbdev     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41*d86ed7fbStbbdev     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42*d86ed7fbStbbdev     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43*d86ed7fbStbbdev     SUCH DAMAGE.
44*d86ed7fbStbbdev */
45*d86ed7fbStbbdev 
46*d86ed7fbStbbdev /*
47*d86ed7fbStbbdev  * objbound.cpp - This file contains the functions to find bounding boxes
48*d86ed7fbStbbdev  *              for the various primitives
49*d86ed7fbStbbdev  */
50*d86ed7fbStbbdev 
51*d86ed7fbStbbdev #include "machine.hpp"
52*d86ed7fbStbbdev #include "types.hpp"
53*d86ed7fbStbbdev #include "macros.hpp"
54*d86ed7fbStbbdev #include "bndbox.hpp"
55*d86ed7fbStbbdev 
56*d86ed7fbStbbdev #define OBJBOUND_PRIVATE
57*d86ed7fbStbbdev #include "objbound.hpp"
58*d86ed7fbStbbdev 
59*d86ed7fbStbbdev static void globalbound(object **rootlist, vector *gmin, vector *gmax) {
60*d86ed7fbStbbdev     vector min, max;
61*d86ed7fbStbbdev     object *cur;
62*d86ed7fbStbbdev 
63*d86ed7fbStbbdev     if (*rootlist == nullptr) /* don't bound non-existent objects */
64*d86ed7fbStbbdev         return;
65*d86ed7fbStbbdev 
66*d86ed7fbStbbdev     gmin->x = FHUGE;
67*d86ed7fbStbbdev     gmin->y = FHUGE;
68*d86ed7fbStbbdev     gmin->z = FHUGE;
69*d86ed7fbStbbdev     gmax->x = -FHUGE;
70*d86ed7fbStbbdev     gmax->y = -FHUGE;
71*d86ed7fbStbbdev     gmax->z = -FHUGE;
72*d86ed7fbStbbdev 
73*d86ed7fbStbbdev     cur = *rootlist;
74*d86ed7fbStbbdev     while (cur != nullptr) { /* Go! */
75*d86ed7fbStbbdev         min.x = -FHUGE;
76*d86ed7fbStbbdev         min.y = -FHUGE;
77*d86ed7fbStbbdev         min.z = -FHUGE;
78*d86ed7fbStbbdev         max.x = FHUGE;
79*d86ed7fbStbbdev         max.y = FHUGE;
80*d86ed7fbStbbdev         max.z = FHUGE;
81*d86ed7fbStbbdev 
82*d86ed7fbStbbdev         cur->methods->bbox((void *)cur, &min, &max);
83*d86ed7fbStbbdev 
84*d86ed7fbStbbdev         gmin->x = MYMIN(gmin->x, min.x);
85*d86ed7fbStbbdev         gmin->y = MYMIN(gmin->y, min.y);
86*d86ed7fbStbbdev         gmin->z = MYMIN(gmin->z, min.z);
87*d86ed7fbStbbdev 
88*d86ed7fbStbbdev         gmax->x = MYMAX(gmax->x, max.x);
89*d86ed7fbStbbdev         gmax->y = MYMAX(gmax->y, max.y);
90*d86ed7fbStbbdev         gmax->z = MYMAX(gmax->z, max.z);
91*d86ed7fbStbbdev 
92*d86ed7fbStbbdev         cur = (object *)cur->nextobj;
93*d86ed7fbStbbdev     }
94*d86ed7fbStbbdev }
95*d86ed7fbStbbdev 
96*d86ed7fbStbbdev static int objinside(object *obj, vector *min, vector *max) {
97*d86ed7fbStbbdev     vector omin, omax;
98*d86ed7fbStbbdev 
99*d86ed7fbStbbdev     if (obj == nullptr) /* non-existent object, shouldn't get here */
100*d86ed7fbStbbdev         return 0;
101*d86ed7fbStbbdev 
102*d86ed7fbStbbdev     if (obj->methods->bbox((void *)obj, &omin, &omax)) {
103*d86ed7fbStbbdev         if ((min->x <= omin.x) && (min->y <= omin.y) && (min->z <= omin.z) && (max->x >= omax.x) &&
104*d86ed7fbStbbdev             (max->y >= omax.y) && (max->z >= omax.z)) {
105*d86ed7fbStbbdev             return 1;
106*d86ed7fbStbbdev         }
107*d86ed7fbStbbdev     }
108*d86ed7fbStbbdev     return 0;
109*d86ed7fbStbbdev }
110*d86ed7fbStbbdev 
111*d86ed7fbStbbdev static int countobj(object *root) {
112*d86ed7fbStbbdev     object *cur; /* counts the number of objects on a list */
113*d86ed7fbStbbdev     int numobj;
114*d86ed7fbStbbdev 
115*d86ed7fbStbbdev     numobj = 0;
116*d86ed7fbStbbdev     cur = root;
117*d86ed7fbStbbdev 
118*d86ed7fbStbbdev     while (cur != nullptr) {
119*d86ed7fbStbbdev         cur = (object *)cur->nextobj;
120*d86ed7fbStbbdev         numobj++;
121*d86ed7fbStbbdev     }
122*d86ed7fbStbbdev     return numobj;
123*d86ed7fbStbbdev }
124*d86ed7fbStbbdev 
125*d86ed7fbStbbdev static void movenextobj(object *thisobj, object **root) {
126*d86ed7fbStbbdev     object *cur, *tmp;
127*d86ed7fbStbbdev 
128*d86ed7fbStbbdev     /* move the object after thisobj to the front of the object list  */
129*d86ed7fbStbbdev     /* headed by root */
130*d86ed7fbStbbdev     if (thisobj != nullptr) {
131*d86ed7fbStbbdev         if (thisobj->nextobj != nullptr) {
132*d86ed7fbStbbdev             cur = (object *)thisobj->nextobj; /* the object to be moved */
133*d86ed7fbStbbdev             thisobj->nextobj = cur->nextobj; /* link around the moved obj */
134*d86ed7fbStbbdev             tmp = *root; /* store the root node */
135*d86ed7fbStbbdev             cur->nextobj = tmp; /* attach root to cur */
136*d86ed7fbStbbdev             *root = cur; /* make cur, the new root */
137*d86ed7fbStbbdev         }
138*d86ed7fbStbbdev     }
139*d86ed7fbStbbdev }
140*d86ed7fbStbbdev 
141*d86ed7fbStbbdev static void octreespace(object **rootlist, int maxoctnodes) {
142*d86ed7fbStbbdev     object *cur;
143*d86ed7fbStbbdev     vector gmin, gmax, gctr;
144*d86ed7fbStbbdev     vector cmin1, cmin2, cmin3, cmin4, cmin5, cmin6, cmin7, cmin8;
145*d86ed7fbStbbdev     vector cmax1, cmax2, cmax3, cmax4, cmax5, cmax6, cmax7, cmax8;
146*d86ed7fbStbbdev     bndbox *box1, *box2, *box3, *box4;
147*d86ed7fbStbbdev     bndbox *box5, *box6, *box7, *box8;
148*d86ed7fbStbbdev     int skipobj;
149*d86ed7fbStbbdev 
150*d86ed7fbStbbdev     if (*rootlist == nullptr) /* don't subdivide non-existent data */
151*d86ed7fbStbbdev         return;
152*d86ed7fbStbbdev 
153*d86ed7fbStbbdev     skipobj = 0;
154*d86ed7fbStbbdev     globalbound(rootlist, &gmin, &gmax); /* find global min and max */
155*d86ed7fbStbbdev 
156*d86ed7fbStbbdev     gctr.x = ((gmax.x - gmin.x) / 2.0) + gmin.x;
157*d86ed7fbStbbdev     gctr.y = ((gmax.y - gmin.y) / 2.0) + gmin.y;
158*d86ed7fbStbbdev     gctr.z = ((gmax.z - gmin.z) / 2.0) + gmin.z;
159*d86ed7fbStbbdev 
160*d86ed7fbStbbdev     cmin1 = gmin;
161*d86ed7fbStbbdev     cmax1 = gctr;
162*d86ed7fbStbbdev     box1 = newbndbox(cmin1, cmax1);
163*d86ed7fbStbbdev 
164*d86ed7fbStbbdev     cmin2 = gmin;
165*d86ed7fbStbbdev     cmin2.x = gctr.x;
166*d86ed7fbStbbdev     cmax2 = gmax;
167*d86ed7fbStbbdev     cmax2.y = gctr.y;
168*d86ed7fbStbbdev     cmax2.z = gctr.z;
169*d86ed7fbStbbdev     box2 = newbndbox(cmin2, cmax2);
170*d86ed7fbStbbdev 
171*d86ed7fbStbbdev     cmin3 = gmin;
172*d86ed7fbStbbdev     cmin3.y = gctr.y;
173*d86ed7fbStbbdev     cmax3 = gmax;
174*d86ed7fbStbbdev     cmax3.x = gctr.x;
175*d86ed7fbStbbdev     cmax3.z = gctr.z;
176*d86ed7fbStbbdev     box3 = newbndbox(cmin3, cmax3);
177*d86ed7fbStbbdev 
178*d86ed7fbStbbdev     cmin4 = gmin;
179*d86ed7fbStbbdev     cmin4.x = gctr.x;
180*d86ed7fbStbbdev     cmin4.y = gctr.y;
181*d86ed7fbStbbdev     cmax4 = gmax;
182*d86ed7fbStbbdev     cmax4.z = gctr.z;
183*d86ed7fbStbbdev     box4 = newbndbox(cmin4, cmax4);
184*d86ed7fbStbbdev 
185*d86ed7fbStbbdev     cmin5 = gmin;
186*d86ed7fbStbbdev     cmin5.z = gctr.z;
187*d86ed7fbStbbdev     cmax5 = gctr;
188*d86ed7fbStbbdev     cmax5.z = gmax.z;
189*d86ed7fbStbbdev     box5 = newbndbox(cmin5, cmax5);
190*d86ed7fbStbbdev 
191*d86ed7fbStbbdev     cmin6 = gctr;
192*d86ed7fbStbbdev     cmin6.y = gmin.y;
193*d86ed7fbStbbdev     cmax6 = gmax;
194*d86ed7fbStbbdev     cmax6.y = gctr.y;
195*d86ed7fbStbbdev     box6 = newbndbox(cmin6, cmax6);
196*d86ed7fbStbbdev 
197*d86ed7fbStbbdev     cmin7 = gctr;
198*d86ed7fbStbbdev     cmin7.x = gmin.x;
199*d86ed7fbStbbdev     cmax7 = gctr;
200*d86ed7fbStbbdev     cmax7.y = gmax.y;
201*d86ed7fbStbbdev     cmax7.z = gmax.z;
202*d86ed7fbStbbdev     box7 = newbndbox(cmin7, cmax7);
203*d86ed7fbStbbdev 
204*d86ed7fbStbbdev     cmin8 = gctr;
205*d86ed7fbStbbdev     cmax8 = gmax;
206*d86ed7fbStbbdev     box8 = newbndbox(cmin8, cmax8);
207*d86ed7fbStbbdev 
208*d86ed7fbStbbdev     cur = *rootlist;
209*d86ed7fbStbbdev     while (cur != nullptr) {
210*d86ed7fbStbbdev         if (objinside((object *)cur->nextobj, &cmin1, &cmax1)) {
211*d86ed7fbStbbdev             movenextobj(cur, &box1->objlist);
212*d86ed7fbStbbdev         }
213*d86ed7fbStbbdev         else if (objinside((object *)cur->nextobj, &cmin2, &cmax2)) {
214*d86ed7fbStbbdev             movenextobj(cur, &box2->objlist);
215*d86ed7fbStbbdev         }
216*d86ed7fbStbbdev         else if (objinside((object *)cur->nextobj, &cmin3, &cmax3)) {
217*d86ed7fbStbbdev             movenextobj(cur, &box3->objlist);
218*d86ed7fbStbbdev         }
219*d86ed7fbStbbdev         else if (objinside((object *)cur->nextobj, &cmin4, &cmax4)) {
220*d86ed7fbStbbdev             movenextobj(cur, &box4->objlist);
221*d86ed7fbStbbdev         }
222*d86ed7fbStbbdev         else if (objinside((object *)cur->nextobj, &cmin5, &cmax5)) {
223*d86ed7fbStbbdev             movenextobj(cur, &box5->objlist);
224*d86ed7fbStbbdev         }
225*d86ed7fbStbbdev         else if (objinside((object *)cur->nextobj, &cmin6, &cmax6)) {
226*d86ed7fbStbbdev             movenextobj(cur, &box6->objlist);
227*d86ed7fbStbbdev         }
228*d86ed7fbStbbdev         else if (objinside((object *)cur->nextobj, &cmin7, &cmax7)) {
229*d86ed7fbStbbdev             movenextobj(cur, &box7->objlist);
230*d86ed7fbStbbdev         }
231*d86ed7fbStbbdev         else if (objinside((object *)cur->nextobj, &cmin8, &cmax8)) {
232*d86ed7fbStbbdev             movenextobj(cur, &box8->objlist);
233*d86ed7fbStbbdev         }
234*d86ed7fbStbbdev         else {
235*d86ed7fbStbbdev             skipobj++;
236*d86ed7fbStbbdev             cur = (object *)cur->nextobj;
237*d86ed7fbStbbdev         }
238*d86ed7fbStbbdev     }
239*d86ed7fbStbbdev 
240*d86ed7fbStbbdev     /* new scope, for redefinition of cur, and old */
241*d86ed7fbStbbdev     {
242*d86ed7fbStbbdev         bndbox *cur, *old;
243*d86ed7fbStbbdev         old = box1;
244*d86ed7fbStbbdev         cur = box2;
245*d86ed7fbStbbdev         if (countobj(cur->objlist) > 0) {
246*d86ed7fbStbbdev             old->nextobj = cur;
247*d86ed7fbStbbdev             globalbound(&cur->objlist, &cur->min, &cur->max);
248*d86ed7fbStbbdev             old = cur;
249*d86ed7fbStbbdev         }
250*d86ed7fbStbbdev         cur = box3;
251*d86ed7fbStbbdev         if (countobj(cur->objlist) > 0) {
252*d86ed7fbStbbdev             old->nextobj = cur;
253*d86ed7fbStbbdev             globalbound(&cur->objlist, &cur->min, &cur->max);
254*d86ed7fbStbbdev             old = cur;
255*d86ed7fbStbbdev         }
256*d86ed7fbStbbdev         cur = box4;
257*d86ed7fbStbbdev         if (countobj(cur->objlist) > 0) {
258*d86ed7fbStbbdev             old->nextobj = cur;
259*d86ed7fbStbbdev             globalbound(&cur->objlist, &cur->min, &cur->max);
260*d86ed7fbStbbdev             old = cur;
261*d86ed7fbStbbdev         }
262*d86ed7fbStbbdev         cur = box5;
263*d86ed7fbStbbdev         if (countobj(cur->objlist) > 0) {
264*d86ed7fbStbbdev             old->nextobj = cur;
265*d86ed7fbStbbdev             globalbound(&cur->objlist, &cur->min, &cur->max);
266*d86ed7fbStbbdev             old = cur;
267*d86ed7fbStbbdev         }
268*d86ed7fbStbbdev         cur = box6;
269*d86ed7fbStbbdev         if (countobj(cur->objlist) > 0) {
270*d86ed7fbStbbdev             old->nextobj = cur;
271*d86ed7fbStbbdev             globalbound(&cur->objlist, &cur->min, &cur->max);
272*d86ed7fbStbbdev             old = cur;
273*d86ed7fbStbbdev         }
274*d86ed7fbStbbdev         cur = box7;
275*d86ed7fbStbbdev         if (countobj(cur->objlist) > 0) {
276*d86ed7fbStbbdev             old->nextobj = cur;
277*d86ed7fbStbbdev             globalbound(&cur->objlist, &cur->min, &cur->max);
278*d86ed7fbStbbdev             old = cur;
279*d86ed7fbStbbdev         }
280*d86ed7fbStbbdev         cur = box8;
281*d86ed7fbStbbdev         if (countobj(cur->objlist) > 0) {
282*d86ed7fbStbbdev             old->nextobj = cur;
283*d86ed7fbStbbdev             globalbound(&cur->objlist, &cur->min, &cur->max);
284*d86ed7fbStbbdev             old = cur;
285*d86ed7fbStbbdev         }
286*d86ed7fbStbbdev 
287*d86ed7fbStbbdev         old->nextobj = *rootlist;
288*d86ed7fbStbbdev 
289*d86ed7fbStbbdev         if (countobj(box1->objlist) > 0) {
290*d86ed7fbStbbdev             globalbound(&box1->objlist, &box1->min, &box1->max);
291*d86ed7fbStbbdev             *rootlist = (object *)box1;
292*d86ed7fbStbbdev         }
293*d86ed7fbStbbdev         else {
294*d86ed7fbStbbdev             *rootlist = (object *)box1->nextobj;
295*d86ed7fbStbbdev         }
296*d86ed7fbStbbdev 
297*d86ed7fbStbbdev     } /**** end of special cur and old scope */
298*d86ed7fbStbbdev 
299*d86ed7fbStbbdev     if (countobj(box1->objlist) > maxoctnodes) {
300*d86ed7fbStbbdev         octreespace(&box1->objlist, maxoctnodes);
301*d86ed7fbStbbdev     }
302*d86ed7fbStbbdev     if (countobj(box2->objlist) > maxoctnodes) {
303*d86ed7fbStbbdev         octreespace(&box2->objlist, maxoctnodes);
304*d86ed7fbStbbdev     }
305*d86ed7fbStbbdev     if (countobj(box3->objlist) > maxoctnodes) {
306*d86ed7fbStbbdev         octreespace(&box3->objlist, maxoctnodes);
307*d86ed7fbStbbdev     }
308*d86ed7fbStbbdev     if (countobj(box4->objlist) > maxoctnodes) {
309*d86ed7fbStbbdev         octreespace(&box4->objlist, maxoctnodes);
310*d86ed7fbStbbdev     }
311*d86ed7fbStbbdev     if (countobj(box5->objlist) > maxoctnodes) {
312*d86ed7fbStbbdev         octreespace(&box5->objlist, maxoctnodes);
313*d86ed7fbStbbdev     }
314*d86ed7fbStbbdev     if (countobj(box6->objlist) > maxoctnodes) {
315*d86ed7fbStbbdev         octreespace(&box6->objlist, maxoctnodes);
316*d86ed7fbStbbdev     }
317*d86ed7fbStbbdev     if (countobj(box7->objlist) > maxoctnodes) {
318*d86ed7fbStbbdev         octreespace(&box7->objlist, maxoctnodes);
319*d86ed7fbStbbdev     }
320*d86ed7fbStbbdev     if (countobj(box8->objlist) > maxoctnodes) {
321*d86ed7fbStbbdev         octreespace(&box8->objlist, maxoctnodes);
322*d86ed7fbStbbdev     }
323*d86ed7fbStbbdev }
324*d86ed7fbStbbdev 
325*d86ed7fbStbbdev void dividespace(int maxoctnodes, object **toplist) {
326*d86ed7fbStbbdev     bndbox *gbox;
327*d86ed7fbStbbdev     vector gmin, gmax;
328*d86ed7fbStbbdev 
329*d86ed7fbStbbdev     if (countobj(*toplist) > maxoctnodes) {
330*d86ed7fbStbbdev         globalbound(toplist, &gmin, &gmax);
331*d86ed7fbStbbdev 
332*d86ed7fbStbbdev         octreespace(toplist, maxoctnodes);
333*d86ed7fbStbbdev 
334*d86ed7fbStbbdev         gbox = newbndbox(gmin, gmax);
335*d86ed7fbStbbdev         gbox->objlist = nullptr;
336*d86ed7fbStbbdev         gbox->tex = nullptr;
337*d86ed7fbStbbdev         gbox->nextobj = nullptr;
338*d86ed7fbStbbdev         gbox->objlist = *toplist;
339*d86ed7fbStbbdev         *toplist = (object *)gbox;
340*d86ed7fbStbbdev     }
341*d86ed7fbStbbdev }
342