FreeWRL / FreeX3D 4.3.0
Frustum.c
1/*
2
3
4???
5
6*/
7
8
9/****************************************************************************
10 This file is part of the FreeWRL/FreeX3D Distribution.
11
12 Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
13
14 FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
15 it under the terms of the GNU Lesser Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 FreeWRL/FreeX3D is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
26****************************************************************************/
27
28
29
30#include <config.h>
31#include <system.h>
32#include <display.h>
33#include <internal.h>
34
35#include <libFreeWRL.h>
36
37#include "../vrml_parser/Structs.h"
38#include "../main/headers.h"
39#include "../scenegraph/quaternion.h"
40#include "../scenegraph/Viewer.h"
41#include "Frustum.h"
42#include "../opengl/OpenGL_Utils.h"
43#include "../scenegraph/LinearAlgebra.h"
44
45
46#include "Textures.h"
47#include <float.h>
48
49//#define FRUSTUMVERBOSE
50
51static void quaternion_multi_rotation(struct point_XYZ *ret, const Quaternion *quat, const struct point_XYZ * v, int count);
52static void add_translation (struct point_XYZ *arr, float x, float y, float z, int count);
53static void multiply_in_scale(struct point_XYZ *arr, float x, float y, float z, int count);
54
55
56
57/*********************************************************************
58 * OLD - NOW USE Occlusion tests
59 * Frustum calculations. Definitive work (at least IMHO) is thanks to
60 * Steven Baker - look at http://sjbaker.org/steve/omniv/frustcull.html/
61 *
62 * Thanks Steve!
63 *
64 */
65
66
67#undef OCCLUSIONVERBOSE
68
69#ifdef OCCLUSION
70
71 /* if we have a visible Shape node, how long should we wait until we try to determine
72 if it is still visible? */
73 #define OCCWAIT 20
74
75 /* we have a visibility sensor, we want to really see when it becomes invis. */
76 #define OCCCHECKNEXTLOOP 1
77
78 /* we are invisible - don't let it go too long before we try to see visibility */
79 #define OCCCHECKSOON 4
80
81 /* how many samples of a Shape are needed before it becomes visible? If it is too
82 small, don't worry about displaying it If this number is too large, "flashing"
83 will occur, as the shape is dropped, while still displaying (the number) of pixels
84 on the screen */
85 #define OCCSHAPESAMPLESIZE 1
86#endif //OCCLUSION
87
88typedef struct pFrustum{
89 /* Occlusion VisibilitySensor code */
90 GLuint *OccQueries;// = NULL;
91
92 /* newer occluder code */
93 GLuint potentialOccluderCount;// = 0;
94 void ** occluderNodePointer;// = NULL;
95
96 /* older occluder code */
97 #ifdef OCCLUSION
98 int maxOccludersFound;// = 0;
99 int QueryCount;// = 0;
100 int OccInitialized;// = FALSE;
101 #endif
102
103 GLuint OccQuerySize;//=0;
104
105 // #ifdef OCCLUSIONVERBOSE
106 // GLint queryCounterBits;
107 // #endif
108
109 GLuint OccResultsAvailable;// = FALSE;
110
111}* ppFrustum;
112void *Frustum_constructor(){
113 void *v = MALLOCV(sizeof(struct pFrustum));
114 memset(v,0,sizeof(struct pFrustum));
115 return v;
116}
117void Frustum_init(struct tFrustum *t){
118 //public
119 t->OccFailed = FALSE;
120 //private
121 t->prv = Frustum_constructor();
122 {
123 ppFrustum p = (ppFrustum)t->prv;
124 /* Occlusion VisibilitySensor code */
125 p->OccQueries = NULL;
126
127 /* newer occluder code */
128 p->potentialOccluderCount = 0;
129 p->occluderNodePointer = NULL;
130
131 /* older occluder code */
132 #ifdef OCCLUSION
133 p->maxOccludersFound = 0;
134 p->QueryCount = 0;
135 p->OccInitialized = FALSE;
136 #endif
137
138 p->OccQuerySize=0;
139
140 p->OccResultsAvailable = FALSE;
141 }
142}
143
144void beginOcclusionQuery(struct X3D_VisibilitySensor* node, int render_geometry)
145{
146 ppFrustum p = (ppFrustum)gglobal()->Frustum.prv;
147 if (render_geometry) {
148 if (p->potentialOccluderCount < p->OccQuerySize) {
149 TRACE_MSG ("beginOcclusionQuery, potoc %d occQ %d\n",p->potentialOccluderCount, p->OccQuerySize);
150 if (node->__occludeCheckCount < 0) {
151 TRACE_MSG ("beginOcclusionQuery, query %u, node %s\n",p->potentialOccluderCount, stringNodeType(node->_nodeType));
152#if !defined(GL_ES_VERSION_2_0)
153//void glBeginQuery(GLenum, GLuint);
154
155 FW_GL_BEGIN_QUERY(GL_SAMPLES_PASSED, p->OccQueries[p->potentialOccluderCount]);
156#endif
157 p->occluderNodePointer[p->potentialOccluderCount] = (void *)node;
158 }
159 }
160 }
161}
162
163void endOcclusionQuery(struct X3D_VisibilitySensor* node, int render_geometry)
164{
165 ppFrustum p = (ppFrustum)gglobal()->Frustum.prv;
166 if (render_geometry) {
167 if (p->potentialOccluderCount < p->OccQuerySize) {
168 if (node->__occludeCheckCount < 0) {
169 TRACE_MSG ("glEndQuery node %p\n",node);
170#if !defined( GL_ES_VERSION_2_0 )
171 FW_GL_END_QUERY(GL_SAMPLES_PASSED);
172#endif
173 p->potentialOccluderCount++;
174 }
175 }
176 }
177}
178
179#define PROP_EXTENT_CHECK \
180 if (maxx > geomParent->EXTENT_MAX_X) {geomParent->EXTENT_MAX_X = maxx; touched = TRUE;} \
181 if (minx < geomParent->EXTENT_MIN_X) {geomParent->EXTENT_MIN_X = minx; touched = TRUE;} \
182 if (maxy > geomParent->EXTENT_MAX_Y) {geomParent->EXTENT_MAX_Y = maxy; touched = TRUE;} \
183 if (miny < geomParent->EXTENT_MIN_Y) {geomParent->EXTENT_MIN_Y = miny; touched = TRUE;} \
184 if (maxz > geomParent->EXTENT_MAX_Z) {geomParent->EXTENT_MAX_Z = maxz; touched = TRUE;} \
185 if (minz < geomParent->EXTENT_MIN_Z) {geomParent->EXTENT_MIN_Z = minz; touched = TRUE;}
186
187#define FRUSTUM_TRANS(myNodeType) \
188 if (me->_nodeType == NODE_##myNodeType) { \
189 /* have we actually done a propagateExtent on this one? Because we look at ALL points in a boundingBox, \
190 because of rotations, we HAVE to ensure that the default values are not there, otherwise we will \
191 take the "inside out" boundingBox as being correct! */ \
192 \
193 /* has this node actually been extented away from the default? */ \
194 \
195 if (!APPROX(me->EXTENT_MAX_X,-10000.0)) { \
196 struct X3D_##myNodeType *node; \
197 Quaternion rq; \
198 struct point_XYZ inxyz[8]; struct point_XYZ outxyz[8]; \
199 node = (struct X3D_##myNodeType *)me; \
200 \
201 /* make up a "cube" with vertexes being our bounding box */ \
202 BBV(0,MAX_X,MAX_Y,MAX_Z); \
203 BBV(1,MAX_X,MAX_Y,MIN_Z); \
204 BBV(2,MAX_X,MIN_Y,MAX_Z); \
205 BBV(3,MAX_X,MIN_Y,MIN_Z); \
206 BBV(4,MIN_X,MAX_Y,MAX_Z); \
207 BBV(5,MIN_X,MAX_Y,MIN_Z); \
208 BBV(6,MIN_X,MIN_Y,MAX_Z); \
209 BBV(7,MIN_X,MIN_Y,MIN_Z); \
210 \
211 /* 1: REVERSE CENTER */ \
212 if (node->__do_center) { \
213 add_translation(inxyz,-node->center.c[0],-node->center.c[1],-node->center.c[2],8); \
214 } \
215 \
216 /* 2: REVERSE SCALE ORIENTATION */ \
217 if (node->__do_scaleO) { \
218 vrmlrot_to_quaternion(&rq,node->scaleOrientation.c[0], node->scaleOrientation.c[1], node->scaleOrientation.c[2], -node->scaleOrientation.c[3]); \
219 quaternion_multi_rotation(outxyz,&rq,inxyz,8); \
220 \
221 /* copy these points back out */ \
222 memcpy (inxyz,outxyz,8*sizeof(struct point_XYZ)); \
223 } \
224 \
225 /* 3: SCALE */ \
226 if (node->__do_scale) { \
227 /* FW_GL_SCALE_F(node->scale.c[0],node->scale.c[1],node->scale.c[2]); */ \
228 multiply_in_scale(inxyz,node->scale.c[0],node->scale.c[1],node->scale.c[2],8); \
229 } \
230 \
231 /* 4: SCALEORIENTATION */ \
232 if (node->__do_scaleO) { \
233 vrmlrot_to_quaternion(&rq,node->scaleOrientation.c[0], node->scaleOrientation.c[1], node->scaleOrientation.c[2], -node->scaleOrientation.c[3]); \
234 quaternion_multi_rotation(outxyz,&rq,inxyz,8); \
235 \
236 /* copy these points back out */ \
237 memcpy (inxyz,outxyz,8*sizeof(struct point_XYZ)); \
238 } \
239 \
240 /* 5: ROTATION */ \
241 if (node->__do_rotation) { \
242 /* FW_GL_ROTATE_F(my_rotation, node->rotation.c[0],node->rotation.c[1],node->rotation.c[2]); */ \
243 vrmlrot_to_quaternion(&rq,node->rotation.c[0], node->rotation.c[1], node->rotation.c[2], node->rotation.c[3]); \
244 quaternion_multi_rotation(outxyz,&rq,inxyz,8); \
245 \
246 /* copy these points back out */ \
247 memcpy (inxyz,outxyz,8*sizeof(struct point_XYZ)); \
248 } \
249 \
250 /* 6: CENTER */ \
251 if (node->__do_center) { \
252 /* FW_GL_TRANSLATE_F(node->center.c[0],node->center.c[1],node->center.c[2]); */ \
253 add_translation(inxyz,node->center.c[0],node->center.c[1],node->center.c[2],8); \
254 } \
255\
256 /* 7: TRANSLATION */ \
257 if (node->__do_trans) { \
258 /* FW_GL_TRANSLATE_F(node->translation.c[0],node->translation.c[1],node->translation.c[2]); */ \
259 add_translation(inxyz,node->translation.c[0],node->translation.c[1],node->translation.c[2],8); \
260 } \
261 \
262 \
263 /* work changes into extent */ \
264 /* because we have materially moved this Transform, the WHOLE Bounding Box has moved, too, \
265 thus we do not bother to test against OLD max/min values */ \
266 maxx = -FLT_MAX; maxy = -FLT_MAX; maxz = -FLT_MAX; \
267 minx = FLT_MAX; miny = FLT_MAX; minz = FLT_MAX; \
268 for (i=0; i<8; i++) { \
269 if (inxyz[i].x > maxx) maxx = (float)inxyz[i].x; \
270 if (inxyz[i].y > maxy) maxy = (float)inxyz[i].y; \
271 if (inxyz[i].z > maxz) maxz = (float)inxyz[i].z; \
272 if (inxyz[i].x < minx) minx = (float)inxyz[i].x; \
273 if (inxyz[i].y < miny) miny = (float)inxyz[i].y; \
274 if (inxyz[i].z < minz) minz = (float)inxyz[i].z; \
275 } \
276 } \
277 }
278
279
280#define FRUSTUM_GEOLOCATION \
281 if (me->_nodeType == NODE_GeoLocation) { \
282 /* have we actually done a propagateExtent on this one? Because we look at ALL points in a boundingBox, \
283 because of rotations, we HAVE to ensure that the default values are not there, otherwise we will \
284 take the "inside out" boundingBox as being correct! */ \
285 \
286 /* has this node actually been extented away from the default? */ \
287 \
288 if (!APPROX(me->EXTENT_MAX_X,-10000.0)) { \
289 struct X3D_GeoLocation *node; \
290 Quaternion rq; \
291 struct point_XYZ inxyz[8]; struct point_XYZ outxyz[8]; \
292 node = (struct X3D_GeoLocation *)me; \
293 \
294 /* make up a "cube" with vertexes being our bounding box */ \
295 BBV(0,MAX_X,MAX_Y,MAX_Z); \
296 BBV(1,MAX_X,MAX_Y,MIN_Z); \
297 BBV(2,MAX_X,MIN_Y,MAX_Z); \
298 BBV(3,MAX_X,MIN_Y,MIN_Z); \
299 BBV(4,MIN_X,MAX_Y,MAX_Z); \
300 BBV(5,MIN_X,MAX_Y,MIN_Z); \
301 BBV(6,MIN_X,MIN_Y,MAX_Z); \
302 BBV(7,MIN_X,MIN_Y,MIN_Z); \
303 \
304\
305 /* 5: ROTATION */ \
306 vrmlrot_to_quaternion(&rq,node->__localOrient.c[0], node->__localOrient.c[1], node->__localOrient.c[2], node->__localOrient.c[3]); \
307 quaternion_multi_rotation(outxyz,&rq,inxyz,8); \
308 \
309 /* copy these points back out */ \
310 memcpy (inxyz,outxyz,8*sizeof(struct point_XYZ)); \
311 \
312 /* 7: TRANSLATION */ \
313 /* FW_GL_TRANSLATE_F(node->translation.c[0],node->translation.c[1],node->translation.c[2]); */ \
314 /*printf ("doing translation %f %f %f\n", node->__movedCoords.c[0],node->__movedCoords.c[1],node->__movedCoords.c[2]); */ \
315 add_translation(inxyz,(float) node->__movedCoords.c[0],(float) node->__movedCoords.c[1],(float) node->__movedCoords.c[2],8); \
316 \
317 \
318 \
319 /* work changes into extent */ \
320 /* because we have materially moved this Transform, the WHOLE Bounding Box has moved, too, \
321 thus we do not bother to test against OLD max/min values */ \
322 maxx = -FLT_MAX; maxy = -FLT_MAX; maxz = -FLT_MAX; \
323 minx = FLT_MAX; miny = FLT_MAX; minz = FLT_MAX; \
324 for (i=0; i<8; i++) { \
325 if (inxyz[i].x > maxx) maxx = (float) inxyz[i].x; \
326 if (inxyz[i].y > maxy) maxy = (float) inxyz[i].y; \
327 if (inxyz[i].z > maxz) maxz = (float) inxyz[i].z; \
328 if (inxyz[i].x < minx) minx = (float) inxyz[i].x; \
329 if (inxyz[i].y < miny) miny = (float) inxyz[i].y; \
330 if (inxyz[i].z < minz) minz = (float) inxyz[i].z; \
331 } \
332 } \
333 }
334
335#define FRUSTUM_GEOTRANS \
336 if (me->_nodeType == NODE_GeoTransform) { \
337 /* have we actually done a propagateExtent on this one? Because we look at ALL points in a boundingBox, \
338 because of rotations, we HAVE to ensure that the default values are not there, otherwise we will \
339 take the "inside out" boundingBox as being correct! */ \
340 \
341 /* has this node actually been extented away from the default? */ \
342 \
343 if (!APPROX(me->EXTENT_MAX_X,-10000.0)) { \
344 struct X3D_GeoTransform *node; \
345 Quaternion rq; \
346 struct point_XYZ inxyz[8]; struct point_XYZ outxyz[8]; \
347 node = (struct X3D_GeoTransform *)me; \
348 \
349 /* make up a "cube" with vertexes being our bounding box */ \
350 BBV(0,MAX_X,MAX_Y,MAX_Z); \
351 BBV(1,MAX_X,MAX_Y,MIN_Z); \
352 BBV(2,MAX_X,MIN_Y,MAX_Z); \
353 BBV(3,MAX_X,MIN_Y,MIN_Z); \
354 BBV(4,MIN_X,MAX_Y,MAX_Z); \
355 BBV(5,MIN_X,MAX_Y,MIN_Z); \
356 BBV(6,MIN_X,MIN_Y,MAX_Z); \
357 BBV(7,MIN_X,MIN_Y,MIN_Z); \
358 \
359 /* 1: REVERSE CENTER */ \
360 if (node->__do_center) { \
361 add_translation(inxyz,(float) (-node->geoCenter.c[0]), (float) (-node->geoCenter.c[1]),(float)(-node->geoCenter.c[2]),8); \
362 } \
363 \
364 /* 2: REVERSE SCALE ORIENTATION */ \
365 if (node->__do_scaleO) { \
366 vrmlrot_to_quaternion(&rq,node->scaleOrientation.c[0], node->scaleOrientation.c[1], node->scaleOrientation.c[2], -node->scaleOrientation.c[3]); \
367 quaternion_multi_rotation(outxyz,&rq,inxyz,8); \
368 memcpy (inxyz,outxyz,8*sizeof(struct point_XYZ)); \
369 } \
370 \
371 /* 3: SCALE */ \
372 if (node->__do_scale) { \
373 multiply_in_scale(inxyz,node->scale.c[0],node->scale.c[1],node->scale.c[2],8); \
374 } \
375 \
376 /* 4: SCALEORIENTATION */ \
377 if (node->__do_scaleO) { \
378 vrmlrot_to_quaternion(&rq,node->scaleOrientation.c[0], node->scaleOrientation.c[1], node->scaleOrientation.c[2], -node->scaleOrientation.c[3]); \
379 quaternion_multi_rotation(outxyz,&rq,inxyz,8); \
380 memcpy (inxyz,outxyz,8*sizeof(struct point_XYZ)); \
381 } \
382 \
383 /* 5: ROTATION */ \
384 if (node->__do_rotation) { \
385 vrmlrot_to_quaternion(&rq,node->rotation.c[0], node->rotation.c[1], node->rotation.c[2], node->rotation.c[3]); \
386 quaternion_multi_rotation(outxyz,&rq,inxyz,8); \
387 memcpy (inxyz,outxyz,8*sizeof(struct point_XYZ)); \
388 } \
389 \
390 /* 6: CENTER */ \
391 if (node->__do_center) { \
392 add_translation(inxyz,(float)node->geoCenter.c[0],(float)node->geoCenter.c[1],(float)node->geoCenter.c[2],8); \
393 } \
394 add_translation (inxyz,(float) X3D_GEOTRANSFORM(node)->__movedCoords.c[0], (float) X3D_GEOTRANSFORM(node)->__movedCoords.c[1], (float) X3D_GEOTRANSFORM(node)->__movedCoords.c[2],8); \
395\
396 vrmlrot_to_quaternion(&rq,X3D_GEOTRANSFORM(node)->__localOrient.c[0], X3D_GEOTRANSFORM(node)->__localOrient.c[1], X3D_GEOTRANSFORM(node)->__localOrient.c[2], X3D_GEOTRANSFORM(node)->__localOrient.c[3]); \
397 quaternion_multi_rotation(outxyz,&rq,inxyz,8); \
398 memcpy (inxyz,outxyz,8*sizeof(struct point_XYZ)); \
399 /* 7: TRANSLATION */ \
400 if (node->__do_trans) { \
401 add_translation(inxyz,node->translation.c[0],node->translation.c[1],node->translation.c[2],8); \
402 } \
403 \
404 \
405 /* work changes into extent */ \
406 /* because we have materially moved this Transform, the WHOLE Bounding Box has moved, too, \
407 thus we do not bother to test against OLD max/min values */ \
408 maxx = -FLT_MAX; maxy = -FLT_MAX; maxz = -FLT_MAX; \
409 minx = FLT_MAX; miny = FLT_MAX; minz = FLT_MAX; \
410 for (i=0; i<8; i++) { \
411 if (inxyz[i].x > maxx) maxx = (float) inxyz[i].x; \
412 if (inxyz[i].y > maxy) maxy = (float) inxyz[i].y; \
413 if (inxyz[i].z > maxz) maxz = (float) inxyz[i].z; \
414 if (inxyz[i].x < minx) minx = (float) inxyz[i].x; \
415 if (inxyz[i].y < miny) miny = (float) inxyz[i].y; \
416 if (inxyz[i].z < minz) minz = (float) inxyz[i].z; \
417 } \
418 } \
419 }
420
421#define BBV(num,XX,YY,ZZ) \
422 inxyz[num].x= (double) (me->EXTENT_##XX); \
423 inxyz[num].y= (double) (me->EXTENT_##YY); \
424 inxyz[num].z= (double) (me->EXTENT_##ZZ);
425
426//#define FRUSTUM_GEOTRANS
427void FRUSTUM_GEOTRANSB(struct X3D_Node *me,float *minx, float *miny, float *minz, float *maxx, float *maxy, float *maxz){
428 int i;
429 if (me->_nodeType == NODE_GeoTransform) {
430 /* have we actually done a propagateExtent on this one? Because we look at ALL points in a boundingBox,
431 because of rotations, we HAVE to ensure that the default values are not there, otherwise we will
432 take the "inside out" boundingBox as being correct! */
433
434 /* has this node actually been extented away from the default? */
435
436 if (!APPROX(me->EXTENT_MAX_X,-10000.0)) {
437 struct X3D_GeoTransform *node;
438 Quaternion rq;
439 struct point_XYZ inxyz[8]; struct point_XYZ outxyz[8];
440 node = (struct X3D_GeoTransform *)me;
441
442 /* make up a "cube" with vertexes being our bounding box */
443 BBV(0,MAX_X,MAX_Y,MAX_Z);
444 BBV(1,MAX_X,MAX_Y,MIN_Z);
445 BBV(2,MAX_X,MIN_Y,MAX_Z);
446 BBV(3,MAX_X,MIN_Y,MIN_Z);
447 BBV(4,MIN_X,MAX_Y,MAX_Z);
448 BBV(5,MIN_X,MAX_Y,MIN_Z);
449 BBV(6,MIN_X,MIN_Y,MAX_Z);
450 BBV(7,MIN_X,MIN_Y,MIN_Z);
451
452 /* 1: REVERSE CENTER */
453 if (node->__do_center) {
454 add_translation(inxyz,(float) (-node->geoCenter.c[0]), (float) (-node->geoCenter.c[1]),(float)(-node->geoCenter.c[2]),8);
455 }
456
457 /* 2: REVERSE SCALE ORIENTATION */
458 if (node->__do_scaleO) {
459 vrmlrot_to_quaternion(&rq,node->scaleOrientation.c[0], node->scaleOrientation.c[1], node->scaleOrientation.c[2], -node->scaleOrientation.c[3]);
460 quaternion_multi_rotation(outxyz,&rq,inxyz,8);
461 memcpy (inxyz,outxyz,8*sizeof(struct point_XYZ));
462 }
463
464 /* 3: SCALE */
465 if (node->__do_scale) {
466 multiply_in_scale(inxyz,node->scale.c[0],node->scale.c[1],node->scale.c[2],8);
467 }
468
469 /* 4: SCALEORIENTATION */
470 if (node->__do_scaleO) {
471 vrmlrot_to_quaternion(&rq,node->scaleOrientation.c[0], node->scaleOrientation.c[1], node->scaleOrientation.c[2], -node->scaleOrientation.c[3]);
472 quaternion_multi_rotation(outxyz,&rq,inxyz,8);
473 memcpy (inxyz,outxyz,8*sizeof(struct point_XYZ));
474 }
475
476 /* 5: ROTATION */
477 if (node->__do_rotation) {
478 vrmlrot_to_quaternion(&rq,node->rotation.c[0], node->rotation.c[1], node->rotation.c[2], node->rotation.c[3]);
479 quaternion_multi_rotation(outxyz,&rq,inxyz,8);
480 memcpy (inxyz,outxyz,8*sizeof(struct point_XYZ));
481 }
482
483 /* 6: CENTER */
484 if (node->__do_center) {
485 add_translation(inxyz,(float)node->geoCenter.c[0],(float)node->geoCenter.c[1],(float)node->geoCenter.c[2],8);
486 }
487 add_translation (inxyz,(float) X3D_GEOTRANSFORM(node)->__movedCoords.c[0], (float) X3D_GEOTRANSFORM(node)->__movedCoords.c[1], (float) X3D_GEOTRANSFORM(node)->__movedCoords.c[2],8);
488
489 vrmlrot_to_quaternion(&rq,X3D_GEOTRANSFORM(node)->__localOrient.c[0], X3D_GEOTRANSFORM(node)->__localOrient.c[1], X3D_GEOTRANSFORM(node)->__localOrient.c[2], X3D_GEOTRANSFORM(node)->__localOrient.c[3]);
490 quaternion_multi_rotation(outxyz,&rq,inxyz,8);
491 memcpy (inxyz,outxyz,8*sizeof(struct point_XYZ));
492 /* 7: TRANSLATION */
493 if (node->__do_trans) {
494 add_translation(inxyz,node->translation.c[0],node->translation.c[1],node->translation.c[2],8);
495 }
496
497
498 /* work changes into extent */
499 /* because we have materially moved this Transform, the WHOLE Bounding Box has moved, too,
500 thus we do not bother to test against OLD max/min values */
501 *maxx = -FLT_MAX; *maxy = -FLT_MAX; *maxz = -FLT_MAX;
502 *minx = FLT_MAX; *miny = FLT_MAX; *minz = FLT_MAX;
503 for (i=0; i<8; i++) {
504 if (inxyz[i].x > *maxx) *maxx = (float) inxyz[i].x;
505 if (inxyz[i].y > *maxy) *maxy = (float) inxyz[i].y;
506 if (inxyz[i].z > *maxz) *maxz = (float) inxyz[i].z;
507 if (inxyz[i].x < *minx) *minx = (float) inxyz[i].x;
508 if (inxyz[i].y < *miny) *miny = (float) inxyz[i].y;
509 if (inxyz[i].z < *minz) *minz = (float) inxyz[i].z;
510 }
511 }
512 }
513}
514void extent6f_setParentExtentB(float *extent6, struct X3D_Node *me);
515void FRUSTUM_GEO(struct X3D_Node *me){
516 int i;
517 if (me->_nodeType == NODE_GeoTransform || me->_nodeType == NODE_GeoLocation || me->_nodeType == NODE_EspduTransform) {
518 if( extent6f_isSet(me->_extent)) {
519 float e[6];
520 double mat[16];
521
522 //push idenity
523 FW_GL_PUSH_MATRIX();
524 FW_GL_LOAD_IDENTITY();
525 //call prep
526 virtTable[me->_nodeType]->prep(me);
527 //scrape mat
528 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, mat);
529 //call fin to pop
530 virtTable[me->_nodeType]->fin(me);
531 //pop to whatever was before identity
532 FW_GL_POP_MATRIX();
533 //transform extent with mat
534 extent6f_mattransform4d(e,me->_extent,mat);
535 extent6f_setParentExtentB(e,me);
536 //extent6f_setNodeExtentB(ef6,me);
537 }
538 }
539}
540
541
542//extent6f {xmax,xmin,ymax,ymin,zmax,zmin}
543float *extent6f_constructor(float *extent6, float xmin,float xmax, float ymin,float ymax, float zmin,float zmax){
544 float *e = extent6;
545 e[0]=xmax; e[1] = xmin; e[2]=ymax; e[3]=ymin; e[4]=zmax; e[5]=zmin;
546 return e;
547}
548float *extent6f_clear(float *extent6){
549 float *e = extent6;
550 e[0]=-10000.0; e[1]=10000.0; e[2]=-10000.0; e[3]=10000.0; e[4]=-10000.0; e[5]=10000.0;
551 return e;
552}
553int extent6f_isSet(float *extent6){
554 //extents are set with min > max, so a way to tell
555 // if they are set is to check if min <= max or max >= min
556 int iret;
557 float *e = extent6;
558 //is max >= min for any dimensions? if so, then is set.
559 //iret = (e[0] >= e[1] && e[2] >= e[3] && e[4] >= e[5]) ? TRUE : FALSE;
560 //iret = (e[0] >= e[1] || e[2] >= e[3] || e[4] >= e[5]) ? TRUE : FALSE;
561 iret = (e[0] >= e[1] && e[2] >= e[3] && e[4] >= e[5]) ? TRUE : FALSE;
562 return iret;
563}
564float *extent6f_copy(float *eout6, float *ein6){
565 memcpy(eout6,ein6,6*sizeof(float));
566 return eout6;
567}
568void extent6f_to_vec3f(float *extent6, float *pmin, float *pmax){
569 int i;
570 for(i=0;i<3;i++){
571 pmin[i] = extent6[i*2 + 1];
572 pmax[i] = extent6[i*2 + 0];
573 }
574}
575void extent6f_from_vec3f2(float *extent6, float *pmin, float *pmax){
576 int i;
577 for(i=0;i<3;i++){
578 extent6[i*2 + 1] = pmin[i];
579 extent6[i*2 + 0] = pmax[i];
580 }
581}
582
583
584float *extent6f_union_extent6f(float *extent6, float *ein6){
585 int i,isa,isb;
586 isa = extent6f_isSet(extent6);
587 isb = extent6f_isSet(ein6);
588 if(isa && isb)
589 for(i=0;i<3;i++){
590 extent6[i*2 + 1] = min(extent6[i*2 + 1], ein6[i*2 + 1]);
591 extent6[i*2 + 0] = max(extent6[i*2 + 0], ein6[i*2 + 0]);
592 }
593 else if(isb) extent6f_copy(extent6,ein6);
594 return extent6;
595}
596float *extent6f_intersect_extent6f(float *extent6, float *eina, float *einb){
597 int i,isa,isb;
598 extent6f_clear(extent6);
599 isa = extent6f_isSet(eina);
600 isb = extent6f_isSet(einb);
601 if(isa && isb)
602 for(i=0;i<3;i++){
603 extent6[i*2 + 1] = max(eina[i*2 + 1], einb[i*2 + 1]);
604 extent6[i*2 + 0] = min(eina[i*2 + 0], einb[i*2 + 0]);
605 }
606 return extent6;
607}
608float *extent6f_union_vec3f(float *extent6, float *p3){
609 int i,isa,isb;
610 isa = extent6f_isSet(extent6);
611 if(!isa)
612 for(i=0;i<3;i++){
613 extent6[i*2 + 1] = p3[i];
614 extent6[i*2 + 0] = p3[i];
615 }
616 for(i=0;i<3;i++){
617 extent6[i*2 + 1] = min(extent6[i*2 + 1], p3[i]);
618 extent6[i*2 + 0] = max(extent6[i*2 + 0], p3[i]);
619 }
620 return extent6;
621}
622void extent6f_to_box3f8(float *extent6, float *p3f8){
623 //generate 8 points from extent
624 int i,j,k,n;
625 n = 0;
626 //extent6f_printf(extent6);printf(" extent\n box:\n");
627 for(k=0;k<2;k++)
628 for(j=0;j<2;j++)
629 for(i=0;i<2;i++){
630 p3f8[n*3 + 0] = extent6[0 + i];
631 p3f8[n*3 + 1] = extent6[2 + j];
632 p3f8[n*3 + 2] = extent6[4 + k];
633 //printf("%d %f %f %f\n",n,p3f8[n*3 + 0],p3f8[n*3 + 1],p3f8[n*3 + 2]);
634 n++;
635 }
636 //printf("\n");
637}
638float * extent6f_from_box3fn(float *extent6,float *p, int n){
639 int i,j;
640 extent6f_clear(extent6);
641 for(i=0;i<n;i++)
642 extent6f_union_vec3f(extent6,&p[i*3]);
643 return extent6;
644}
645float *extent6f_scale3f(float *eout6, float *ein6, float *s3){
646 int i;
647 for(i=0;i<3;i++){
648 eout6[i*2 + 0] *= s3[i];
649 eout6[i*2 + 1] *= s3[i];
650 }
651 return eout6;
652}
653float *extent6f_translate3f(float *eout6, float *ein6, float *p3){
654 int i;
655 for(i=0;i<3;i++){
656 eout6[i*2 + 0] += p3[i];
657 eout6[i*2 + 1] += p3[i];
658 }
659 return eout6;
660}
661float *extent6f_translate3d(float *eout6, float *ein6, double *p3){
662 int i;
663 for(i=0;i<3;i++){
664 eout6[i*2 + 0] += p3[i];
665 eout6[i*2 + 1] += p3[i];
666 }
667 return eout6;
668}
669float *extent6f_get_center3f(float *extent6, float *center3){
670 int i;
671 for(i=0;i<3;i++){
672 center3[i] = .5f*(extent6[i*2 + 0] + extent6[i*2 + 1]);
673 }
674 return center3;
675}
676float extent6f_get_maxsize(float *extent6){
677 float msize;
678 int i;
679 msize = 0.0f;
680 for(i=0;i<3;i++){
681 msize = max(msize,extent6[i*2 + 0] - extent6[i*2 + 1]);
682 }
683 return msize;
684}
685float extent6f_get_maxradius(float *extent6){
686
687 float radius, p3f8[8][3], pc[3], pd[3];
688 int i;
689 radius = 0.0f;
690 extent6f_get_center3f(extent6,pc);
691 extent6f_to_box3f8(extent6, p3f8[0]);
692 for(i=0;i<8;i++){
693 vecdif3f(pd,p3f8[i],pc);
694 radius = max(radius, veclength3f(pd));
695 }
696 return radius;
697}
698float *extent6f_rotate4f(float *eout6, float *ein6, float *vrot4){
699 int i;
700 float p3f[8][3];
701 double p3d[8][3];
702 Quaternion rq;
703
704 extent6f_to_box3f8(ein6,p3f[0]);
705 float2double(p3d[0],p3f[0],24);
706 vrmlrot_to_quaternion(&rq,vrot4[0],vrot4[1], vrot4[2], vrot4[3]);
707 for(i=0;i<8;i++){
708 quaternion_rotationd(p3d[i],&rq,p3d[i]);
709 }
710 double2float(p3f[0],p3d[0],24);
711 extent6f_from_box3fn(eout6,p3f[0],8);
712 return eout6;
713}
714
715float *extent6f_rotate4d(float *eout6, float *ein6, double *vrot4){
716 int i;
717 float p3f[8][3];
718 double p3d[8][3];
719 Quaternion rq;
720
721 extent6f_to_box3f8(ein6,p3f[0]);
722 float2double(p3d[0],p3f[0],24);
723 vrmlrot_to_quaternion(&rq,vrot4[0],vrot4[1], vrot4[2], vrot4[3]);
724 for(i=0;i<8;i++){
725 quaternion_rotationd(p3d[i],&rq,p3d[i]);
726 }
727 double2float(p3f[0],p3d[0],24);
728 extent6f_from_box3fn(eout6,p3f[0],8);
729 return eout6;
730}
731float *extent6f_mattransform4d(float *eout6,float *ein6, double *mat4){
732 int i;
733 float p3f[8][3];
734 double p3d[8][3];
735 Quaternion rq;
736
737 extent6f_to_box3f8(ein6,p3f[0]);
738 float2double(p3d[0],p3f[0],24);
739 for(i=0;i<8;i++){
740 transformAFFINEd(p3d[i],p3d[i],mat4);
741 }
742 double2float(p3f[0],p3d[0],24);
743 extent6f_from_box3fn(eout6,p3f[0],8);
744 return eout6;
745
746}
747void extent6f_printf(float *extent6){
748 float *e = extent6;
749 printf("min,max x:%lf,%lf y:%f,%f z:%f,%f ",e[1],e[0],e[3],e[2],e[5],e[4]);
750}
751void extent6f_setNodeExtentB(float *extent6, struct X3D_Node *me){
752 int i,j;
753 struct X3D_Node *shapeParent;
754 struct X3D_Node *groupParent;
755 float *e = extent6;
756
757 #ifdef FRUSTUMVERBOSE
758 extent6f_printf(e);
759 printf(" extent6f_setNodeExtentB me %p nt %s\n",me,stringNodeType(me->_nodeType));
760 #endif
761
762 /* record this for ME for sorting purposes for sorting children fields */
763 extent6f_copy(me->_extent,e);
764
765 if (me->_parentVector == NULL) {
766 #ifdef FRUSTUMVERBOSE
767 printf ("setExtent, parentVector NULL for node %p type %s\n",
768 me,stringNodeType(me->_nodeType));
769 #endif
770 return;
771 }
772
773 for (i=0; i<vectorSize(me->_parentVector); i++) {
774 shapeParent = vector_get(struct X3D_Node *, me->_parentVector,i);
775 extent6f_copy(shapeParent->_extent,e);
776 for (j=0; j<vectorSize(shapeParent->_parentVector); j++) {
777 groupParent = vector_get(struct X3D_Node *, shapeParent->_parentVector,j);
778
779 //extent6f_printf(e); printf(" e\n");
780 //extent6f_printf(groupParent->_extent); printf(" gp before\n");
781 extent6f_union_extent6f(groupParent->_extent,e);
782 //extent6f_printf(groupParent->_extent); printf(" gp after union\n");
783 }
784 }
785}
786void extent6f_setParentExtentB(float *extent6, struct X3D_Node *me){
787 int i,j;
788 struct X3D_Node *shapeParent;
789 struct X3D_Node *groupParent;
790 float *e = extent6;
791
792 #ifdef FRUSTUMVERBOSE
793 extent6f_printf(e);
794 printf(" extent6f_setNodeExtentB me %p nt %s\n",me,stringNodeType(me->_nodeType));
795 #endif
796
797 /* record this for ME for sorting purposes for sorting children fields */
798
799 if (me->_parentVector == NULL) {
800 #ifdef FRUSTUMVERBOSE
801 printf ("setExtent, parentVector NULL for node %p type %s\n",
802 me,stringNodeType(me->_nodeType));
803 #endif
804 return;
805 }
806
807 for (i=0; i<vectorSize(me->_parentVector); i++) {
808 shapeParent = vector_get(struct X3D_Node *, me->_parentVector,i);
809 extent6f_copy(shapeParent->_extent,e);
810 for (j=0; j<vectorSize(shapeParent->_parentVector); j++) {
811 groupParent = vector_get(struct X3D_Node *, shapeParent->_parentVector,j);
812
813 //extent6f_printf(e); printf(" e\n");
814 //extent6f_printf(groupParent->_extent); printf(" gp before\n");
815 extent6f_union_extent6f(groupParent->_extent,e);
816 //extent6f_printf(groupParent->_extent); printf(" gp after union\n");
817 }
818 }
819}
820void FRUSTUM_GEOELEVATIONGRID(struct X3D_Node *me){
821 int i;
822 if (me->_nodeType == NODE_GeoElevationGrid) {
823 if( extent6f_isSet(me->_extent)) {
824 float ef6[6];
825 struct X3D_GeoElevationGrid *node = (struct X3D_GeoElevationGrid *)me;
826 extent6f_rotate4d(ef6, me->_extent, node->__localOrient.c);
827 extent6f_translate3d(ef6,ef6,node->__autoOffset.c);
828 extent6f_setNodeExtentB(ef6,me);
829 }
830 }
831}
832
833
834
835/* does this current node actually fit in the Switch rendering scheme? */
836int is_Switchchild_inrange(struct X3D_Switch *node, struct X3D_Node *me) {
837 int wc = node->whichChoice;
838
839 /* is this VRML, or X3D?? */
840 if (node->__isX3D == 0) {
841 if(wc >= 0 && wc < ((node->choice).n)) {
842 void *p = ((node->choice).p[wc]);
843 return (X3D_NODE(p)==me);
844 }
845 } else {
846 if(wc >= 0 && wc < ((node->children).n)) {
847 void *p = ((node->children).p[wc]);
848 return (X3D_NODE(p)==me);
849 }
850 }
851 return FALSE;
852}
853
854
855/* does this current node actually display, according to the CADLayer scheme? */
856int is_CADLayerchild_inrange(struct X3D_CADLayer *node, struct X3D_Node *me) {
857 int i;
858 for (i=0; i<node->children.n; i++) {
859
860 /* if we have more children than we have indexes into visible field, just return TRUE */
861 if ((i >= node->visible.n) && (node->children.p[i] == me)) return TRUE;
862
863 /* if not, if it is in the visible field, return true */
864 else if ((node->visible.p[i]) && (node->children.p[i] == me)) return TRUE;
865 }
866 /* not visible, so return false */
867 return FALSE;
868}
869
870/* does this current node actually fit in the GeoLOD rendering scheme? */
871int is_GeoLODchild_inrange (struct X3D_GeoLOD* gpnode, struct X3D_Node *me) {
872 /* is this node part of the active path for rendering? */
873 int x,y;
874 y = FALSE;
875
876 for (x=0; x<gpnode->rootNode.n; x++) {
877 /* printf ("comparing %u:%u %d of %d, types me %s rootNodeField: %s\n",
878 me, X3D_NODE(gpnode->rootNode.p[x]),
879 x, gpnode->rootNode.n,
880 stringNodeType (me->_nodeType),
881 stringNodeType( X3D_NODE(gpnode->rootNode.p[x])->_nodeType)
882 );
883 */
884
885 if (me == X3D_NODE(gpnode->rootNode.p[x])) {
886 y=TRUE;
887 break;
888 }
889 }
890
891/*
892 if (y) printf ("GeoLOD, found child in rootNode "); else printf ("GeoLOD, child NOT part of ROOT ");
893 if (X3D_GEOLOD(geomParent)->__inRange) printf ("INRANGE "); else printf ("NOT inrange ");
894*/
895 /* is this one actually being rendered? */
896 return (y ^ gpnode->__inRange);
897}
898
899
900/* take the measurements of a geometry (eg, box), and save it. Note
901 * that what is given is a Shape, the values get pushed up to the
902 * Geometries grouping node parent. */
903
904
905/* this is used for collision in transformChildren - don't bother going through
906 children of a transform if there is nothing close... */
907
908void setExtent_OLD(float maxx, float minx, float maxy, float miny, float maxz, float minz, struct X3D_Node *me) {
909 int c,d;
910 struct X3D_Node *shapeParent;
911 struct X3D_Node *geomParent;
912 int touched;
913
914 UNUSED(touched); //compiler warning mitigation
915
916 #ifdef FRUSTUMVERBOSE
917 printf ("setExtent maxx %f minx %f maxy %f miny %f maxz %f minz %f me %p nt %s\n",
918 maxx, minx, maxy, miny, maxz, minz, me, stringNodeType(me->_nodeType));
919 #endif
920
921 /* record this for ME for sorting purposes for sorting children fields */
922 me->EXTENT_MAX_X = maxx; me->EXTENT_MIN_X = minx;
923 me->EXTENT_MAX_Y = maxy; me->EXTENT_MIN_Y = miny;
924 me->EXTENT_MAX_Z = maxz; me->EXTENT_MIN_Z = minz;
925
926 if (me->_parentVector == NULL) {
927 #ifdef FRUSTUMVERBOSE
928 printf ("setExtent, parentVector NULL for node %p type %s\n",
929 me,stringNodeType(me->_nodeType));
930 #endif
931 return;
932 }
933
934 for (c=0; c<vectorSize(me->_parentVector); c++) {
935 shapeParent = vector_get(struct X3D_Node *, me->_parentVector,c);
936
937 /* record this for ME for sorting purposes for sorting children fields */
938 shapeParent->EXTENT_MAX_X = maxx; shapeParent->EXTENT_MIN_X = minx;
939 shapeParent->EXTENT_MAX_Y = maxy; shapeParent->EXTENT_MIN_Y = miny;
940 shapeParent->EXTENT_MAX_Z = maxz; shapeParent->EXTENT_MIN_Z = minz;
941
942 #ifdef FRUSTUMVERBOSE
943 if (shapeParent == NULL)
944 printf ("parent %u of %u is %p, is null\n",c,vectorSize(me->_parentVector),shapeParent);
945 else
946 printf ("parent %u of %u is %p, type %s\n",c,vectorSize(me->_parentVector),shapeParent,stringNodeType(shapeParent->_nodeType));
947 #endif
948
949 for (d=0; d<vectorSize(shapeParent->_parentVector); d++) {
950 geomParent = vector_get(struct X3D_Node *, shapeParent->_parentVector,d);
951
952 #ifdef FRUSTUMVERBOSE
953 printf ("setExtent in loop, parent %u of shape %s is %s\n",c,stringNodeType(shapeParent->_nodeType),
954 stringNodeType(geomParent->_nodeType));
955
956 /* is there a problem with this geomParent? */
957 if (!checkNode(geomParent, __FILE__, __LINE__)) printf ("problem here with checkNode\n");
958 #endif
959
960
961 /* note, maxz is positive, minz is negative, distance should be negative, so we take a negative distance,
962 and subtract the "positive" z value to get the closest point, then take the negative distance,
963 and subtract the "negative" z value to get the far distance */
964
965 PROP_EXTENT_CHECK;
966
967 #ifdef FRUSTUMVERBOSE
968 printf ("setExtent - now I am %p (%s) has extent maxx %f minx %f maxy %f miny %f maxz %f minz %f\n",
969 me, stringNodeType(me->_nodeType),
970 me->EXTENT_MAX_X ,
971 me->EXTENT_MIN_X ,
972 me->EXTENT_MAX_Y ,
973 me->EXTENT_MIN_Y ,
974 me->EXTENT_MAX_Z ,
975 me->EXTENT_MIN_Z);
976 printf ("setExtent - now parent %p (%s) has extent maxx %f minx %f maxy %f miny %f maxz %f minz %f\n",
977 geomParent, stringNodeType(geomParent->_nodeType),
978 geomParent->EXTENT_MAX_X ,
979 geomParent->EXTENT_MIN_X ,
980 geomParent->EXTENT_MAX_Y ,
981 geomParent->EXTENT_MIN_Y ,
982 geomParent->EXTENT_MAX_Z ,
983 geomParent->EXTENT_MIN_Z);
984 #endif
985
986 }
987 }
988}
989
990
991void setExtentA(float maxx, float minx, float maxy, float miny, float maxz, float minz, struct X3D_Node *me) {
992 float e[6];
993 extent6f_constructor(e,minx,maxx,miny,maxy,minz,maxz);
994 extent6f_setNodeExtentB(e,me);
995}
996
997void setExtent(float maxx, float minx, float maxy, float miny, float maxz, float minz, struct X3D_Node *me) {
998 float e[6];
999 extent6f_constructor(e,minx,maxx,miny,maxy,minz,maxz);
1000 extent6f_setNodeExtentB(e,me);
1001}
1002
1003static void quaternion_multi_rotation(struct point_XYZ *ret, const Quaternion *quat, const struct point_XYZ * v, int count){
1004 int i;
1005 for (i=0; i<count; i++) {
1006 quaternion_rotation(ret, quat, v);
1007 ret++; v++;
1008 }
1009}
1010
1011
1012
1013static void add_translation (struct point_XYZ *arr, float x, float y, float z, int count) {
1014 int i;
1015 for (i=0; i<count; i++) {
1016 arr->x += (double)x;
1017 arr->y += (double)y;
1018 arr->z += (double)z;
1019 arr++;
1020 }
1021}
1022
1023static void multiply_in_scale(struct point_XYZ *arr, float x, float y, float z, int count) {
1024 int i;
1025 for (i=0; i<count; i++) {
1026 arr->x *= (double)x;
1027 arr->y *= (double)y;
1028 arr->z *= (double)z;
1029 arr++;
1030 }
1031}
1032
1033
1034void printmatrix(GLDOUBLE* mat) {
1035 int i;
1036 for(i = 0; i< 16; i++) {
1037 printf("mat[%d] = %4.3f%s",i,mat[i],i==3 ? "\n" : i==7? "\n" : i==11? "\n" : "");
1038 }
1039 printf ("\n");
1040
1041}
1042
1043
1044/* for children nodes; set the parent grouping nodes extent - we expect the center
1045 * of the group to be passed in in the floats x,y,z */
1046
1047void propagateExtent(struct X3D_Node *me) {
1048 float minx, miny, minz, maxx, maxy, maxz;
1049 int i;
1050 struct X3D_Node *geomParent;
1051 int touched;
1052
1053 if (me==NULL) return;
1054
1055
1056 #ifdef FRUSTUMVERBOSE
1057 printf ("propextent Iam %s, myExtent (%4.2f %4.2f) (%4.2f %4.2f) (%4.2f %4.2f) me %p parents %d\n",
1058 stringNodeType(me->_nodeType),
1059 me->EXTENT_MAX_X, me->EXTENT_MIN_X,
1060 me->EXTENT_MAX_Y, me->EXTENT_MIN_Y,
1061 me->EXTENT_MAX_Z, me->EXTENT_MIN_Z,
1062 me, vectorSize(me->_parentVector));
1063 #endif
1064
1065
1066 if (me->_parentVector == NULL) {
1067 ConsoleMessage ("propagateExtent, parentVector NULL, me %p %s\n",
1068 me,stringNodeType(me->_nodeType));
1069 return;
1070 }
1071
1072 /* calculate the maximum of the current position, and add the previous extent */
1073 /* these MIGHT be overwritten if we have a Transform node here */
1074 /* these values are used in PROP_EXTENT_CHECK */
1075 maxx = me->EXTENT_MAX_X; minx = me->EXTENT_MIN_X;
1076 maxy = me->EXTENT_MAX_Y; miny = me->EXTENT_MIN_Y;
1077 maxz = me->EXTENT_MAX_Z; minz = me->EXTENT_MIN_Z;
1078
1079 /* is this a transform? Should we add in the translated position?? */
1080 FRUSTUM_TRANS(Transform);
1081
1082 //FRUSTUM_GEOTRANS;
1083 //FRUSTUM_GEOTRANSB(me,&minx,&miny,&minz,&maxx,&maxy,&maxz);
1084 FRUSTUM_GEO(me);
1085 //FRUSTUM_GEOLOCATION;
1086 FRUSTUM_TRANS(HAnimSite);
1087 FRUSTUM_TRANS(HAnimJoint);
1088 FRUSTUM_GEOELEVATIONGRID(me);
1089
1090 for (i=0; i<vectorSize(me->_parentVector); i++) {
1091 geomParent = vector_get(struct X3D_Node *, me->_parentVector, i);
1092
1093 /* do we propagate for this parent? */
1094 touched = FALSE;
1095
1096 /* switch nodes - only propagate extent back up if the node is "active" */
1097 switch (geomParent->_nodeType) {
1098 case NODE_GeoLOD:
1099 if (is_GeoLODchild_inrange(X3D_GEOLOD(geomParent), me)) {
1100 PROP_EXTENT_CHECK;
1101 }
1102 break;
1103 case NODE_LOD:
1104 /* works for both X3D and VRML syntax; compare with the "_selected" field */
1105 if (me == X3D_LODNODE(geomParent)->_selected) {
1106 PROP_EXTENT_CHECK;
1107 }
1108 break;
1109
1110 case NODE_Switch:
1111 if (is_Switchchild_inrange(X3D_SWITCH(geomParent), me)) {
1112 PROP_EXTENT_CHECK;
1113 }
1114 break;
1115 case NODE_CADLayer:
1116 if (is_CADLayerchild_inrange(X3D_CADLAYER(geomParent),me)) {
1117 PROP_EXTENT_CHECK;
1118 }
1119 break;
1120 default: {
1121 PROP_EXTENT_CHECK;
1122 }
1123 }
1124
1125
1126 #ifdef FRUSTUMVERBOSE
1127 printf ("after transform calcs me (%p %s) my parent %d is (%p %s) ext %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f\n",
1128 me, stringNodeType(me->_nodeType),i,geomParent, stringNodeType(geomParent->_nodeType),
1129 geomParent->EXTENT_MAX_X, geomParent->EXTENT_MIN_X,
1130 geomParent->EXTENT_MAX_Y, geomParent->EXTENT_MIN_Y,
1131 geomParent->EXTENT_MAX_Z, geomParent->EXTENT_MIN_Z);
1132 #endif
1133
1134 /* now, send these up the line, assuming this child makes the extent larger */
1135 if (touched) propagateExtent(geomParent);
1136 }
1137}
1138
1139/* perform all the viewpoint rotations for a point */
1140/* send in a pointer for the result, the current bounding box point to rotate, and the current ModelView matrix */
1141
1142void moveAndRotateThisPoint(struct point_XYZ *mypt, double x, double y, double z, double *MM) {
1143 float outF[3];
1144 float inF[3];
1145 inF[0] = (float) x; inF[1] = (float) y; inF[2] = (float) z;
1146
1147 /* transform this vertex via the modelview matrix */
1148 transformf (outF,inF,MM);
1149
1150 #ifdef VERBOSE
1151 printf ("transformed %4.2f %4.2f %4.2f, to %4.2f %4.2f %4.2f\n",inF[0], inF[1], inF[2],
1152 outF[0], outF[1], outF[2]);
1153 #endif
1154 mypt->x = outF[0]; mypt->y=outF[1],mypt->z = outF[2];
1155}
1156
1157
1158/**************************************************************************************/
1159
1160/* get the center of the bounding box, rotate it, and find out how far it is Z distance from us.
1161*/
1162
1163
1164void record_ZBufferDistance(struct X3D_Node *node) {
1165 GLDOUBLE modelMatrix[16];
1166 double ex;
1167 double ey;
1168 double ez;
1169 struct point_XYZ movedPt;
1170 double minMovedDist;
1171
1172 minMovedDist = -1000000000;
1173
1174 #ifdef FRUSTUMVERBOSE
1175 printf ("\nrecordDistance for node %p nodeType %s size %4.2f %4.2f %4.2f ",node, stringNodeType (node->_nodeType),
1176 node->EXTENT_MAX_X - node->EXTENT_MIN_X,
1177 node->EXTENT_MAX_Y - node->EXTENT_MIN_Y,
1178 node->EXTENT_MAX_Z - node->EXTENT_MIN_Z
1179 );
1180
1181 if (APPROX(node->EXTENT_MAX_X,-10000.0)) printf ("EXTENT NOT INIT");
1182
1183 printf ("\n");
1184 printf ("recordDistance, max,min %f:%f, %f:%f, %f:%f\n",
1185 node->EXTENT_MAX_X , node->EXTENT_MIN_X,
1186 node->EXTENT_MAX_Y , node->EXTENT_MIN_Y,
1187 node->EXTENT_MAX_Z , node->EXTENT_MIN_Z);
1188 #endif
1189
1190 /* get the current pos in modelMatrix land */
1191 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, modelMatrix);
1192
1193#ifdef TRY_ONLY_ONE_POINT
1194#ifdef TRY_RADIUS
1195 /* get radius of bounding box around its origin */
1196 ex = (node->EXTENT_MAX_X - node->EXTENT_MIN_X) / 2.0;
1197 ey = (node->EXTENT_MAX_Y - node->EXTENT_MIN_Y) / 2.0;
1198 ez = (node->EXTENT_MAX_Z - node->EXTENT_MIN_Z) / 2.0;
1199 printf (" ex %lf ey %lf ez %lf\n",ex,ey,ez);
1200#else
1201 /* get the center of the bounding box */
1202 ex = node->EXTENT_MAX_X + node->EXTENT_MIN_X;
1203 ey = node->EXTENT_MAX_Y + node->EXTENT_MIN_Y;
1204 ez = node->EXTENT_MAX_Z + node->EXTENT_MIN_Z;
1205#endif
1206
1207
1208 /* rotate the center of this point */
1209 moveAndRotateThisPoint (&movedPt, ex,ey,ez,modelMatrix);
1210 printf ("%lf %lf %lf centre is %lf %lf %lf\n",ex,ey,ez,movedPt.x, movedPt.y, movedPt.z);
1211 minMovedDist = movedPt.z;
1212
1213#else
1214
1215 /* printf ("moving all 8 points of this bounding box\n"); */
1216 ex = node->EXTENT_MIN_X;
1217 ey = node->EXTENT_MIN_Y;
1218 ez = node->EXTENT_MIN_Z;
1219 moveAndRotateThisPoint (&movedPt, ex,ey,ez,modelMatrix);
1220 if (movedPt.z > minMovedDist) minMovedDist = movedPt.z;
1221 /* printf ("%lf %lf %lf moved is %lf %lf %lf\n",ex,ey,ez,movedPt.x, movedPt.y, movedPt.z); */
1222
1223 ex = node->EXTENT_MIN_X;
1224 ey = node->EXTENT_MIN_Y;
1225 ez = node->EXTENT_MAX_Z;
1226 moveAndRotateThisPoint (&movedPt, ex,ey,ez,modelMatrix);
1227 if (movedPt.z > minMovedDist) minMovedDist = movedPt.z;
1228 /* printf ("%lf %lf %lf moved is %lf %lf %lf\n",ex,ey,ez,movedPt.x, movedPt.y, movedPt.z); */
1229
1230 ex = node->EXTENT_MIN_X;
1231 ey = node->EXTENT_MAX_Y;
1232 ez = node->EXTENT_MIN_Z;
1233 moveAndRotateThisPoint (&movedPt, ex,ey,ez,modelMatrix);
1234 if (movedPt.z > minMovedDist) minMovedDist = movedPt.z;
1235 /* printf ("%lf %lf %lf moved is %lf %lf %lf\n",ex,ey,ez,movedPt.x, movedPt.y, movedPt.z); */
1236
1237 ex = node->EXTENT_MIN_X;
1238 ey = node->EXTENT_MAX_Y;
1239 ez = node->EXTENT_MAX_Z;
1240 moveAndRotateThisPoint (&movedPt, ex,ey,ez,modelMatrix);
1241 if (movedPt.z > minMovedDist) minMovedDist = movedPt.z;
1242 /* printf ("%lf %lf %lf moved is %lf %lf %lf\n",ex,ey,ez,movedPt.x, movedPt.y, movedPt.z); */
1243
1244 ex = node->EXTENT_MAX_X;
1245 ey = node->EXTENT_MIN_Y;
1246 ez = node->EXTENT_MIN_Z;
1247 moveAndRotateThisPoint (&movedPt, ex,ey,ez,modelMatrix);
1248 if (movedPt.z > minMovedDist) minMovedDist = movedPt.z;
1249 /* printf ("%lf %lf %lf moved is %lf %lf %lf\n",ex,ey,ez,movedPt.x, movedPt.y, movedPt.z); */
1250
1251 ex = node->EXTENT_MAX_X;
1252 ey = node->EXTENT_MIN_Y;
1253 ez = node->EXTENT_MAX_Z;
1254 moveAndRotateThisPoint (&movedPt, ex,ey,ez,modelMatrix);
1255 if (movedPt.z > minMovedDist) minMovedDist = movedPt.z;
1256 /* printf ("%lf %lf %lf moved is %lf %lf %lf\n",ex,ey,ez,movedPt.x, movedPt.y, movedPt.z); */
1257
1258 ex = node->EXTENT_MAX_X;
1259 ey = node->EXTENT_MAX_Y;
1260 ez = node->EXTENT_MIN_Z;
1261 moveAndRotateThisPoint (&movedPt, ex,ey,ez,modelMatrix);
1262 if (movedPt.z > minMovedDist) minMovedDist = movedPt.z;
1263 /* printf ("%lf %lf %lf moved is %lf %lf %lf\n",ex,ey,ez,movedPt.x, movedPt.y, movedPt.z); */
1264
1265 ex = node->EXTENT_MAX_X;
1266 ey = node->EXTENT_MAX_Y;
1267 ez = node->EXTENT_MAX_Z;
1268 moveAndRotateThisPoint (&movedPt, ex,ey,ez,modelMatrix);
1269 if (movedPt.z > minMovedDist) minMovedDist = movedPt.z;
1270 /* printf ("%lf %lf %lf moved is %lf %lf %lf\n",ex,ey,ez,movedPt.x, movedPt.y, movedPt.z); */
1271#endif
1272
1273 node->_dist = minMovedDist;
1274
1275#ifdef FRUSTUMVERBOSE
1276 printf ("I am at %lf %lf %lf\n",Viewer()->currentPosInModel.x, Viewer()->currentPosInModel.y, Viewer()->currentPosInModel.z);
1277 printf ("and distance to the nearest corner of the BB for this node is %lf\n", node->_dist);
1278#endif
1279
1280
1281
1282#undef FRUSTUMVERBOSE
1283
1284}
1285
1286/***************************************************************************/
1287
1288void OcclusionStartofRenderSceneUpdateScene() {
1289
1290#ifdef OCCLUSION /* do we have hardware for occlusion culling? */
1291 int i;
1292 ppFrustum p;
1293 ttglobal tg = gglobal();
1294 p = (ppFrustum)gglobal()->Frustum.prv;
1295 /* each time through the event loop, we count the occluders. Note, that if, say, a
1296 shape was USED 100 times, that would be 100 occlude queries, BUT ONE SHAPE, thus
1297 there is not an implicit 1:1 mapping between shapes and occlude queries */
1298
1299 p->potentialOccluderCount = 0;
1300
1301 /* did we have a failure here ? */
1302 if (tg->Frustum.OccFailed) return;
1303
1304 /* have we been through this yet? */
1305 if (p->OccInitialized == FALSE) {
1306 #ifdef OCCLUSIONVERBOSE
1307 printf ("initializing OcclusionCulling...\n");
1308 #endif
1309 /* do we have an environment variable for this? */
1310 if (gglobal()->internalc.global_occlusion_disable) {
1311 tg->Frustum.OccFailed = TRUE;
1312 } else {
1313 s_renderer_capabilities_t *rdr_caps;
1314 rdr_caps = gglobal()->display.rdr_caps;
1315 if (rdr_caps->av_occlusion_q) {
1316
1317 #ifdef OCCLUSIONVERBOSE
1318 printf ("OcclusionStartofRenderSceneUpdateScene: have OcclusionQuery\n");
1319 #endif
1320
1321 /* we make the OccQuerySize larger than the maximum number of occluders,
1322 so we don't have to realloc too much */
1323 p->OccQuerySize = p->maxOccludersFound + 1000;
1324
1325 p->occluderNodePointer = MALLOC (void **, sizeof (void *) * p->OccQuerySize);
1326 p->OccQueries = MALLOC (GLuint *, sizeof(GLuint) * p->OccQuerySize);
1327 FW_GL_GENQUERIES(p->OccQuerySize,p->OccQueries);
1328 //ConsoleMessage ("generated %d queries, pointer %p",p->OccQuerySize,p->OccQueries);
1329 p->OccInitialized = TRUE;
1330 for (i=0; i<p->OccQuerySize; i++) {
1331 p->occluderNodePointer[i] = 0;
1332 }
1333 p->QueryCount = p->maxOccludersFound; /* for queries - we can do this number */
1334 #ifdef OCCLUSIONVERBOSE
1335 printf ("QueryCount now %d\n",p->QueryCount);
1336 #endif
1337
1338 } else {
1339 #ifdef OCCLUSIONVERBOSE
1340 printf ("OcclusionStartofRenderSceneUpdateScene: DO NOT have OcclusionQuery\n");
1341 #endif
1342
1343 /* we dont seem to have this extension here at runtime! */
1344 /* this happened, eg, on my Core4 AMD64 box with Mesa */
1345 tg->Frustum.OccFailed = TRUE;
1346 return;
1347 }
1348 }
1349
1350 }
1351
1352
1353 /* did we find more shapes than before? */
1354 if (p->maxOccludersFound > p->QueryCount) {
1355 if (p->maxOccludersFound > p->OccQuerySize) {
1356 /* printf ("have to regen queries\n"); */
1357 p->QueryCount = 0;
1358
1359 /* possibly previous had zero occluders, lets just not bother deleting for zero */
1360 if (p->OccQuerySize > 0) {
1361 FW_GL_DELETEQUERIES (p->OccQuerySize, p->OccQueries);
1362 FW_GL_FLUSH();
1363 }
1364
1365 p->OccQuerySize = p->maxOccludersFound + 1000;
1366 p->occluderNodePointer = REALLOC (p->occluderNodePointer,sizeof (void *) * p->OccQuerySize);
1367 p->OccQueries = REALLOC (p->OccQueries,sizeof (GLuint) * p->OccQuerySize);
1368 FW_GL_GENQUERIES(p->OccQuerySize,p->OccQueries);
1369 ConsoleMessage ("reinitialized queries... now %p",p->OccQueries);
1370 for (i=0; i<p->OccQuerySize; i++) {
1371 p->occluderNodePointer[i] = 0;
1372 }
1373 }
1374 p->QueryCount = p->maxOccludersFound; /* for queries - we can do this number */
1375 #ifdef OCCLUSIONVERBOSE
1376 printf ("QueryCount here is %d\n",p->QueryCount);
1377 #endif
1378
1379 }
1380
1381
1382// #ifdef OCCLUSIONVERBOSE
1383// glGetQueryiv(GL_SAMPLES_PASSED, GL_QUERY_COUNTER_BITS, &p->queryCounterBits);
1384// printf ("queryCounterBits %d\n",p->queryCounterBits);
1385// #endif
1386#endif /* OCCLUSION */
1387
1388}
1389
1390void OcclusionCulling () {
1391//non-occlusion visibilitysensor method: __Samples = 0 in startofloopnodeupdates
1392#ifdef OCCLUSION /* do we have hardware for occlusion culling? */
1393 int i;
1394 struct X3D_Shape *shapePtr;
1395 struct X3D_VisibilitySensor *visSenPtr;
1396 int checkCount;
1397 GLuint samples;
1398 ppFrustum p;
1399 ttglobal tg = gglobal();
1400 p = (ppFrustum)tg->Frustum.prv;
1401
1402//#ifdef OCCLUSIONVERBOSE
1403// {
1404// GLint query;
1405// glGetQueryiv(GL_SAMPLES_PASSED, GL_CURRENT_QUERY, &query);
1406// printf ("currentQuery is %d\n",query);
1407// }
1408//#endif
1409
1410 visSenPtr = NULL;
1411 shapePtr = NULL;
1412
1413 /* Step 0. go through list of assigned nodes, and either:
1414 - if we have OcclusionQueries: REMOVE the VF_hasVisibleChildren flag;
1415 - else, set every node to VF_hasVisibleChildren */
1416 zeroVisibilityFlag();
1417
1418 /* Step 1. did we have some problem with Occlusion ? */
1419 if (tg->Frustum.OccFailed) return;
1420
1421 /* Step 2. go through the list of "OccludeCount" nodes, and determine if they are visible.
1422 If they are not, then, we have to, at some point, make them visible, so that we can test again. */
1423 /* note that the potentialOccluderCount is only incremented if the __occludeCheckCount tells us
1424 that it should be checked again - see the interplay between the eventLoop stuff in OpenGLUtils.c
1425 and the OCCLUSION* defines in headers.h - we DO NOT generate a query every time through the loop */
1426
1427 //#ifdef OCCLUSIONVERBOSE
1428 //printf ("OcclusionCulling - potentialOccluderCount %d\n",p->potentialOccluderCount);
1429 //#endif
1430
1431 for (i=0; i<p->potentialOccluderCount; i++) {
1432 #ifdef OCCLUSIONVERBOSE
1433 printf ("checking node %d of %d\n",i, p->potentialOccluderCount);
1434 #endif
1435
1436 checkCount = 0;
1437
1438 /* get the check count field for this node - see if we did a check of this */
1439 shapePtr = X3D_SHAPE(p->occluderNodePointer[i]);
1440 if (shapePtr != NULL) {
1441 if (shapePtr->_nodeType == NODE_Shape) {
1442 visSenPtr = NULL;
1443 checkCount = shapePtr->__occludeCheckCount;
1444 } else if (shapePtr->_nodeType == NODE_VisibilitySensor) {
1445 visSenPtr = X3D_VISIBILITYSENSOR(shapePtr);
1446 shapePtr = NULL;
1447 checkCount = visSenPtr->__occludeCheckCount;
1448 } else {
1449 printf ("OcclusionCulling on node type %s not allowed\n",stringNodeType(shapePtr->_nodeType));
1450 return;
1451 }
1452 }
1453
1454 #ifdef OCCLUSIONVERBOSE
1455 if (shapePtr) printf ("OcclusionCulling, for a %s (index %d ptr %p) checkCount %d\n",stringNodeType(shapePtr->_nodeType),i,shapePtr,checkCount);
1456 else printf ("OcclusionCulling, for a %s (index %d) checkCount %d\n",stringNodeType(visSenPtr->_nodeType),i,checkCount);
1457 #endif
1458
1459 /* an Occlusion test will have been run on this one */
1460
1461 FW_GL_GETQUERYOBJECTUIV(p->OccQueries[i],GL_QUERY_RESULT_AVAILABLE,&p->OccResultsAvailable);
1462 PRINT_GL_ERROR_IF_ANY("FW_GL_GETQUERYOBJECTUIV::QUERY_RESULTS_AVAIL");
1463
1464 #define SLEEP_FOR_QUERY_RESULTS
1465 #ifdef SLEEP_FOR_QUERY_RESULTS
1466 /* for now, lets loop to see when we get results */
1467 while (p->OccResultsAvailable == GL_FALSE) {
1468 usleep(100);
1469 FW_GL_GETQUERYOBJECTUIV(p->OccQueries[i],GL_QUERY_RESULT_AVAILABLE,&p->OccResultsAvailable);
1470 PRINT_GL_ERROR_IF_ANY("FW_GL_GETQUERYOBJECTUIV::QUERY_RESULTS_AVAIL");
1471 }
1472 #endif
1473
1474
1475 #ifdef OCCLUSIONVERBOSE
1476 if (p->OccResultsAvailable == GL_FALSE) printf ("results not ready for %d\n",i);
1477 #endif
1478
1479
1480 /* if we are NOT ready; we keep the count going, but we do NOT change the results of VisibilitySensors */
1481 if (p->OccResultsAvailable == GL_FALSE) samples = 10000;
1482
1483 FW_GL_GETQUERYOBJECTUIV (p->OccQueries[i], GL_QUERY_RESULT, &samples);
1484 PRINT_GL_ERROR_IF_ANY("FW_GL_GETQUERYOBJECTUIV::QUERY");
1485
1486 #ifdef OCCLUSIONVERBOSE
1487 printf ("i %d checkc %d samples %d\n",i,checkCount,samples);
1488 #endif
1489
1490 if (p->occluderNodePointer[i] != 0) {
1491
1492 /* if this is a VisibilitySensor, record the samples */
1493 if (visSenPtr != NULL) {
1494
1495 #ifdef OCCLUSIONVERBOSE
1496 printf ("OcclusionCulling, found VisibilitySensor at %d, fragments %d active %d\n",i,samples,checkCount);
1497 #endif
1498
1499
1500 /* if this is a DEF/USE, we might already have done this one, as we have same
1501 node pointer used in other places. */
1502 if (checkCount != OCCCHECKNEXTLOOP) {
1503
1504 if (samples > 0) {
1505 visSenPtr->__visible = TRUE;
1506 visSenPtr->__occludeCheckCount = OCCCHECKNEXTLOOP; /* look for this EVERY time through */
1507 visSenPtr->__Samples = samples;
1508 } else {
1509 visSenPtr->__occludeCheckCount = OCCCHECKSOON; /* check again soon */
1510 visSenPtr->__visible =FALSE;
1511 visSenPtr->__Samples = 0;
1512 }
1513
1514 /* } else {
1515 printf ("shape, already have checkCount == OCCCHECKNEXTLOOP, not changing visibility params\n");
1516
1517 */
1518 }
1519 }
1520
1521
1522 /* is this is Shape? */
1523 else if (shapePtr != NULL) {
1524 #ifdef OCCLUSIONVERBOSE
1525 printf ("OcclusionCulling, found Shape %d, fragments %d active %d\n",i,samples,checkCount);
1526 #endif
1527 //if (samples == 0) ConsoleMessage ("invisible shape %d, fragments %d",i,samples);
1528
1529 /* if this is a DEF/USE, we might already have done this one, as we have same
1530 node pointer used in other places. */
1531 if (checkCount != OCCWAIT) {
1532
1533 /* is this node visible? If so, tell the parents! */
1534 if (samples > OCCSHAPESAMPLESIZE) {
1535 TRACE_MSG ("Shape %p is VISIBLE\n",shapePtr);
1536 shapePtr->__visible = TRUE;
1537 shapePtr->__occludeCheckCount= OCCWAIT; /* wait a little while before checking again */
1538 shapePtr->__Samples = samples;
1539 } else {
1540 TRACE_MSG ("Shape %p is NOT VISIBLE\n",shapePtr);
1541 shapePtr->__visible=FALSE;
1542 shapePtr->__occludeCheckCount = OCCCHECKSOON; /* check again soon */
1543 shapePtr->__Samples = 0;
1544 }
1545 /* } else {
1546 printf ("shape, already have checkCount == OCCWAIT, not changing visibility params\n");
1547 */
1548 }
1549 }
1550 }
1551 }
1552#endif /* OCCLUSION */
1553}
1554
1555/* shut down the occlusion stuff */
1556void zeroOcclusion(void) {
1557
1558#ifdef OCCLUSION /* do we have hardware for occlusion culling? */
1559
1560 int i;
1561 ppFrustum p;
1562 ttglobal tg = gglobal();
1563 p= (ppFrustum)tg->Frustum.prv;
1564
1565 if (tg->Frustum.OccFailed) return;
1566
1567 #ifdef OCCLUSIONVERBOSE
1568 printf ("zeroOcclusion - potentialOccluderCount %d\n",p->potentialOccluderCount);
1569 #endif
1570
1571 for (i=0; i<p->potentialOccluderCount; i++) {
1572#ifdef OCCLUSIONVERBOSE
1573 printf ("checking node %d of %d\n",i, p->potentialOccluderCount);
1574#endif
1575
1576 FW_GL_GETQUERYOBJECTUIV(p->OccQueries[i],GL_QUERY_RESULT_AVAILABLE,&p->OccResultsAvailable);
1577 PRINT_GL_ERROR_IF_ANY("FW_GL_GETQUERYOBJECTUIV::QUERY_RESULTS_AVAIL");
1578#ifdef SLEEP_FOR_QUERY_RESULTS
1579 /* for now, lets loop to see when we get results */
1580 while (p->OccResultsAvailable == GL_FALSE) {
1581#ifdef OCCLUSIONVERBOSE
1582 printf ("zero - waiting and looping for results\n");
1583#endif
1584 usleep(1000);
1585 FW_GL_GETQUERYOBJECTUIV(p->OccQueries[i],GL_QUERY_RESULT_AVAILABLE,&p->OccResultsAvailable);
1586 PRINT_GL_ERROR_IF_ANY("FW_GL_GETQUERYOBJECTUIV::QUERY_RESULTS_AVAIL");
1587 }
1588#endif
1589 }
1590#ifdef OCCLUSIONVERBOSE
1591 printf ("zeroOcclusion - done waiting\n");
1592#endif
1593
1594 p->QueryCount = 0;
1595
1596 // debugging
1597 //if (p->OccQueries) {
1598 // ConsoleMessage ("p->OccQueries exists, p->OccQuerySize %p, p->OccQueries %p",p->OccQuerySize, p->OccQueries);
1599 //}
1600 //if(p->OccQueries)
1601 //glDeleteQueries (p->OccQuerySize, p->OccQueries);
1602 //FW_GL_FLUSH();
1603
1604 p->OccQuerySize=0;
1605 p->maxOccludersFound = 0;
1606 p->OccInitialized = FALSE;
1607 p->potentialOccluderCount = 0;
1608 //ConsoleMessage ("freeing OccQueries %p",p->OccQueries);
1609 FREE_IF_NZ(p->OccQueries);
1610 FREE_IF_NZ(p->occluderNodePointer);
1611#endif /* OCCLUSION */
1612}