35#include <libFreeWRL.h>
37#include "../vrml_parser/Structs.h"
38#include "../main/headers.h"
39#include "../scenegraph/quaternion.h"
40#include "../scenegraph/Viewer.h"
42#include "../opengl/OpenGL_Utils.h"
43#include "../scenegraph/LinearAlgebra.h"
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);
67#undef OCCLUSIONVERBOSE
76 #define OCCCHECKNEXTLOOP 1
79 #define OCCCHECKSOON 4
85 #define OCCSHAPESAMPLESIZE 1
93 GLuint potentialOccluderCount;
94 void ** occluderNodePointer;
98 int maxOccludersFound;
109 GLuint OccResultsAvailable;
112void *Frustum_constructor(){
113 void *v = MALLOCV(
sizeof(
struct pFrustum));
114 memset(v,0,
sizeof(
struct pFrustum));
117void Frustum_init(
struct tFrustum *t){
119 t->OccFailed = FALSE;
121 t->prv = Frustum_constructor();
125 p->OccQueries = NULL;
128 p->potentialOccluderCount = 0;
129 p->occluderNodePointer = NULL;
133 p->maxOccludersFound = 0;
135 p->OccInitialized = FALSE;
140 p->OccResultsAvailable = FALSE;
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)
155 FW_GL_BEGIN_QUERY(GL_SAMPLES_PASSED, p->OccQueries[p->potentialOccluderCount]);
157 p->occluderNodePointer[p->potentialOccluderCount] = (
void *)node;
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);
173 p->potentialOccluderCount++;
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;}
187#define FRUSTUM_TRANS(myNodeType) \
188 if (me->_nodeType == NODE_##myNodeType) { \
195 if (!APPROX(me->EXTENT_MAX_X,-10000.0)) { \
196 struct X3D_##myNodeType *node; \
198 struct point_XYZ inxyz[8]; struct point_XYZ outxyz[8]; \
199 node = (struct X3D_##myNodeType *)me; \
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); \
212 if (node->__do_center) { \
213 add_translation(inxyz,-node->center.c[0],-node->center.c[1],-node->center.c[2],8); \
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); \
222 memcpy (inxyz,outxyz,8*sizeof(struct point_XYZ)); \
226 if (node->__do_scale) { \
228 multiply_in_scale(inxyz,node->scale.c[0],node->scale.c[1],node->scale.c[2],8); \
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); \
237 memcpy (inxyz,outxyz,8*sizeof(struct point_XYZ)); \
241 if (node->__do_rotation) { \
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); \
247 memcpy (inxyz,outxyz,8*sizeof(struct point_XYZ)); \
251 if (node->__do_center) { \
253 add_translation(inxyz,node->center.c[0],node->center.c[1],node->center.c[2],8); \
257 if (node->__do_trans) { \
259 add_translation(inxyz,node->translation.c[0],node->translation.c[1],node->translation.c[2],8); \
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; \
280#define FRUSTUM_GEOLOCATION \
281 if (me->_nodeType == NODE_GeoLocation) { \
288 if (!APPROX(me->EXTENT_MAX_X,-10000.0)) { \
289 struct X3D_GeoLocation *node; \
291 struct point_XYZ inxyz[8]; struct point_XYZ outxyz[8]; \
292 node = (struct X3D_GeoLocation *)me; \
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); \
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); \
310 memcpy (inxyz,outxyz,8*sizeof(struct point_XYZ)); \
315 add_translation(inxyz,(float) node->__movedCoords.c[0],(float) node->__movedCoords.c[1],(float) node->__movedCoords.c[2],8); \
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; \
335#define FRUSTUM_GEOTRANS \
336 if (me->_nodeType == NODE_GeoTransform) { \
343 if (!APPROX(me->EXTENT_MAX_X,-10000.0)) { \
344 struct X3D_GeoTransform *node; \
346 struct point_XYZ inxyz[8]; struct point_XYZ outxyz[8]; \
347 node = (struct X3D_GeoTransform *)me; \
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); \
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); \
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)); \
372 if (node->__do_scale) { \
373 multiply_in_scale(inxyz,node->scale.c[0],node->scale.c[1],node->scale.c[2],8); \
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)); \
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)); \
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); \
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); \
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)); \
400 if (node->__do_trans) { \
401 add_translation(inxyz,node->translation.c[0],node->translation.c[1],node->translation.c[2],8); \
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; \
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);
427void FRUSTUM_GEOTRANSB(
struct X3D_Node *me,
float *minx,
float *miny,
float *minz,
float *maxx,
float *maxy,
float *maxz){
429 if (me->_nodeType == NODE_GeoTransform) {
436 if (!APPROX(me->EXTENT_MAX_X,-10000.0)) {
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);
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);
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));
465 if (node->__do_scale) {
466 multiply_in_scale(inxyz,node->scale.c[0],node->scale.c[1],node->scale.c[2],8);
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));
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));
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);
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);
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));
493 if (node->__do_trans) {
494 add_translation(inxyz,node->translation.c[0],node->translation.c[1],node->translation.c[2],8);
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;
514void extent6f_setParentExtentB(
float *extent6,
struct X3D_Node *me);
515void FRUSTUM_GEO(
struct X3D_Node *me){
517 if (me->_nodeType == NODE_GeoTransform || me->_nodeType == NODE_GeoLocation || me->_nodeType == NODE_EspduTransform) {
518 if( extent6f_isSet(me->_extent)) {
524 FW_GL_LOAD_IDENTITY();
526 virtTable[me->_nodeType]->prep(me);
528 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, mat);
530 virtTable[me->_nodeType]->fin(me);
534 extent6f_mattransform4d(e,me->_extent,mat);
535 extent6f_setParentExtentB(e,me);
543float *extent6f_constructor(
float *extent6,
float xmin,
float xmax,
float ymin,
float ymax,
float zmin,
float zmax){
545 e[0]=xmax; e[1] = xmin; e[2]=ymax; e[3]=ymin; e[4]=zmax; e[5]=zmin;
548float *extent6f_clear(
float *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;
553int extent6f_isSet(
float *extent6){
561 iret = (e[0] >= e[1] && e[2] >= e[3] && e[4] >= e[5]) ? TRUE : FALSE;
564float *extent6f_copy(
float *eout6,
float *ein6){
565 memcpy(eout6,ein6,6*
sizeof(
float));
568void extent6f_to_vec3f(
float *extent6,
float *pmin,
float *pmax){
571 pmin[i] = extent6[i*2 + 1];
572 pmax[i] = extent6[i*2 + 0];
575void extent6f_from_vec3f2(
float *extent6,
float *pmin,
float *pmax){
578 extent6[i*2 + 1] = pmin[i];
579 extent6[i*2 + 0] = pmax[i];
584float *extent6f_union_extent6f(
float *extent6,
float *ein6){
586 isa = extent6f_isSet(extent6);
587 isb = extent6f_isSet(ein6);
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]);
593 else if(isb) extent6f_copy(extent6,ein6);
596float *extent6f_intersect_extent6f(
float *extent6,
float *eina,
float *einb){
598 extent6f_clear(extent6);
599 isa = extent6f_isSet(eina);
600 isb = extent6f_isSet(einb);
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]);
608float *extent6f_union_vec3f(
float *extent6,
float *p3){
610 isa = extent6f_isSet(extent6);
613 extent6[i*2 + 1] = p3[i];
614 extent6[i*2 + 0] = p3[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]);
622void extent6f_to_box3f8(
float *extent6,
float *p3f8){
630 p3f8[n*3 + 0] = extent6[0 + i];
631 p3f8[n*3 + 1] = extent6[2 + j];
632 p3f8[n*3 + 2] = extent6[4 + k];
638float * extent6f_from_box3fn(
float *extent6,
float *p,
int n){
640 extent6f_clear(extent6);
642 extent6f_union_vec3f(extent6,&p[i*3]);
645float *extent6f_scale3f(
float *eout6,
float *ein6,
float *s3){
648 eout6[i*2 + 0] *= s3[i];
649 eout6[i*2 + 1] *= s3[i];
653float *extent6f_translate3f(
float *eout6,
float *ein6,
float *p3){
656 eout6[i*2 + 0] += p3[i];
657 eout6[i*2 + 1] += p3[i];
661float *extent6f_translate3d(
float *eout6,
float *ein6,
double *p3){
664 eout6[i*2 + 0] += p3[i];
665 eout6[i*2 + 1] += p3[i];
669float *extent6f_get_center3f(
float *extent6,
float *center3){
672 center3[i] = .5f*(extent6[i*2 + 0] + extent6[i*2 + 1]);
676float extent6f_get_maxsize(
float *extent6){
681 msize = max(msize,extent6[i*2 + 0] - extent6[i*2 + 1]);
685float extent6f_get_maxradius(
float *extent6){
687 float radius, p3f8[8][3], pc[3], pd[3];
690 extent6f_get_center3f(extent6,pc);
691 extent6f_to_box3f8(extent6, p3f8[0]);
693 vecdif3f(pd,p3f8[i],pc);
694 radius = max(radius, veclength3f(pd));
698float *extent6f_rotate4f(
float *eout6,
float *ein6,
float *vrot4){
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]);
708 quaternion_rotationd(p3d[i],&rq,p3d[i]);
710 double2float(p3f[0],p3d[0],24);
711 extent6f_from_box3fn(eout6,p3f[0],8);
715float *extent6f_rotate4d(
float *eout6,
float *ein6,
double *vrot4){
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]);
725 quaternion_rotationd(p3d[i],&rq,p3d[i]);
727 double2float(p3f[0],p3d[0],24);
728 extent6f_from_box3fn(eout6,p3f[0],8);
731float *extent6f_mattransform4d(
float *eout6,
float *ein6,
double *mat4){
737 extent6f_to_box3f8(ein6,p3f[0]);
738 float2double(p3d[0],p3f[0],24);
740 transformAFFINEd(p3d[i],p3d[i],mat4);
742 double2float(p3f[0],p3d[0],24);
743 extent6f_from_box3fn(eout6,p3f[0],8);
747void extent6f_printf(
float *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]);
751void extent6f_setNodeExtentB(
float *extent6,
struct X3D_Node *me){
757 #ifdef FRUSTUMVERBOSE
759 printf(
" extent6f_setNodeExtentB me %p nt %s\n",me,stringNodeType(me->_nodeType));
763 extent6f_copy(me->_extent,e);
765 if (me->_parentVector == NULL) {
766 #ifdef FRUSTUMVERBOSE
767 printf (
"setExtent, parentVector NULL for node %p type %s\n",
768 me,stringNodeType(me->_nodeType));
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);
781 extent6f_union_extent6f(groupParent->_extent,e);
786void extent6f_setParentExtentB(
float *extent6,
struct X3D_Node *me){
792 #ifdef FRUSTUMVERBOSE
794 printf(
" extent6f_setNodeExtentB me %p nt %s\n",me,stringNodeType(me->_nodeType));
799 if (me->_parentVector == NULL) {
800 #ifdef FRUSTUMVERBOSE
801 printf (
"setExtent, parentVector NULL for node %p type %s\n",
802 me,stringNodeType(me->_nodeType));
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);
815 extent6f_union_extent6f(groupParent->_extent,e);
820void FRUSTUM_GEOELEVATIONGRID(
struct X3D_Node *me){
822 if (me->_nodeType == NODE_GeoElevationGrid) {
823 if( extent6f_isSet(me->_extent)) {
826 extent6f_rotate4d(ef6, me->_extent, node->__localOrient.c);
827 extent6f_translate3d(ef6,ef6,node->__autoOffset.c);
828 extent6f_setNodeExtentB(ef6,me);
837 int wc = node->whichChoice;
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);
846 if(wc >= 0 && wc < ((node->children).n)) {
847 void *p = ((node->children).p[wc]);
848 return (X3D_NODE(p)==me);
858 for (i=0; i<node->children.n; i++) {
861 if ((i >= node->visible.n) && (node->children.p[i] == me))
return TRUE;
864 else if ((node->visible.p[i]) && (node->children.p[i] == me))
return TRUE;
876 for (x=0; x<gpnode->rootNode.n; x++) {
885 if (me == X3D_NODE(gpnode->rootNode.p[x])) {
896 return (y ^ gpnode->__inRange);
908void setExtent_OLD(
float maxx,
float minx,
float maxy,
float miny,
float maxz,
float minz,
struct X3D_Node *me) {
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));
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;
926 if (me->_parentVector == NULL) {
927 #ifdef FRUSTUMVERBOSE
928 printf (
"setExtent, parentVector NULL for node %p type %s\n",
929 me,stringNodeType(me->_nodeType));
934 for (c=0; c<vectorSize(me->_parentVector); c++) {
935 shapeParent = vector_get(
struct X3D_Node *, me->_parentVector,c);
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;
942 #ifdef FRUSTUMVERBOSE
943 if (shapeParent == NULL)
944 printf (
"parent %u of %u is %p, is null\n",c,vectorSize(me->_parentVector),shapeParent);
946 printf (
"parent %u of %u is %p, type %s\n",c,vectorSize(me->_parentVector),shapeParent,stringNodeType(shapeParent->_nodeType));
949 for (d=0; d<vectorSize(shapeParent->_parentVector); d++) {
950 geomParent = vector_get(
struct X3D_Node *, shapeParent->_parentVector,d);
952 #ifdef FRUSTUMVERBOSE
953 printf (
"setExtent in loop, parent %u of shape %s is %s\n",c,stringNodeType(shapeParent->_nodeType),
954 stringNodeType(geomParent->_nodeType));
957 if (!checkNode(geomParent, __FILE__, __LINE__)) printf (
"problem here with checkNode\n");
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),
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);
991void setExtentA(
float maxx,
float minx,
float maxy,
float miny,
float maxz,
float minz,
struct X3D_Node *me) {
993 extent6f_constructor(e,minx,maxx,miny,maxy,minz,maxz);
994 extent6f_setNodeExtentB(e,me);
997void setExtent(
float maxx,
float minx,
float maxy,
float miny,
float maxz,
float minz,
struct X3D_Node *me) {
999 extent6f_constructor(e,minx,maxx,miny,maxy,minz,maxz);
1000 extent6f_setNodeExtentB(e,me);
1005 for (i=0; i<count; i++) {
1006 quaternion_rotation(ret, quat, v);
1013static void add_translation (
struct point_XYZ *arr,
float x,
float y,
float z,
int count) {
1015 for (i=0; i<count; i++) {
1016 arr->x += (double)x;
1017 arr->y += (double)y;
1018 arr->z += (double)z;
1023static void multiply_in_scale(
struct point_XYZ *arr,
float x,
float y,
float z,
int count) {
1025 for (i=0; i<count; i++) {
1026 arr->x *= (double)x;
1027 arr->y *= (double)y;
1028 arr->z *= (double)z;
1034void printmatrix(GLDOUBLE* mat) {
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" :
"");
1047void propagateExtent(
struct X3D_Node *me) {
1048 float minx, miny, minz, maxx, maxy, maxz;
1053 if (me==NULL)
return;
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));
1066 if (me->_parentVector == NULL) {
1067 ConsoleMessage (
"propagateExtent, parentVector NULL, me %p %s\n",
1068 me,stringNodeType(me->_nodeType));
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;
1080 FRUSTUM_TRANS(Transform);
1086 FRUSTUM_TRANS(HAnimSite);
1087 FRUSTUM_TRANS(HAnimJoint);
1088 FRUSTUM_GEOELEVATIONGRID(me);
1090 for (i=0; i<vectorSize(me->_parentVector); i++) {
1091 geomParent = vector_get(
struct X3D_Node *, me->_parentVector, i);
1097 switch (geomParent->_nodeType) {
1099 if (is_GeoLODchild_inrange(X3D_GEOLOD(geomParent), me)) {
1105 if (me == X3D_LODNODE(geomParent)->_selected) {
1111 if (is_Switchchild_inrange(X3D_SWITCH(geomParent), me)) {
1116 if (is_CADLayerchild_inrange(X3D_CADLAYER(geomParent),me)) {
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);
1135 if (touched) propagateExtent(geomParent);
1142void moveAndRotateThisPoint(
struct point_XYZ *mypt,
double x,
double y,
double z,
double *MM) {
1145 inF[0] = (float) x; inF[1] = (float) y; inF[2] = (float) z;
1148 transformf (outF,inF,MM);
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]);
1154 mypt->x = outF[0]; mypt->y=outF[1],mypt->z = outF[2];
1164void record_ZBufferDistance(
struct X3D_Node *node) {
1165 GLDOUBLE modelMatrix[16];
1170 double minMovedDist;
1172 minMovedDist = -1000000000;
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
1181 if (APPROX(node->EXTENT_MAX_X,-10000.0)) printf (
"EXTENT NOT INIT");
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);
1191 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, modelMatrix);
1193#ifdef TRY_ONLY_ONE_POINT
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);
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
1273 node->_dist = minMovedDist;
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);
1282#undef FRUSTUMVERBOSE
1288void OcclusionStartofRenderSceneUpdateScene() {
1299 p->potentialOccluderCount = 0;
1302 if (tg->Frustum.OccFailed)
return;
1305 if (p->OccInitialized == FALSE) {
1306 #ifdef OCCLUSIONVERBOSE
1307 printf (
"initializing OcclusionCulling...\n");
1310 if (gglobal()->internalc.global_occlusion_disable) {
1311 tg->Frustum.OccFailed = TRUE;
1314 rdr_caps = gglobal()->display.rdr_caps;
1315 if (rdr_caps->av_occlusion_q) {
1317 #ifdef OCCLUSIONVERBOSE
1318 printf (
"OcclusionStartofRenderSceneUpdateScene: have OcclusionQuery\n");
1323 p->OccQuerySize = p->maxOccludersFound + 1000;
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);
1329 p->OccInitialized = TRUE;
1330 for (i=0; i<p->OccQuerySize; i++) {
1331 p->occluderNodePointer[i] = 0;
1333 p->QueryCount = p->maxOccludersFound;
1334 #ifdef OCCLUSIONVERBOSE
1335 printf (
"QueryCount now %d\n",p->QueryCount);
1339 #ifdef OCCLUSIONVERBOSE
1340 printf (
"OcclusionStartofRenderSceneUpdateScene: DO NOT have OcclusionQuery\n");
1345 tg->Frustum.OccFailed = TRUE;
1354 if (p->maxOccludersFound > p->QueryCount) {
1355 if (p->maxOccludersFound > p->OccQuerySize) {
1360 if (p->OccQuerySize > 0) {
1361 FW_GL_DELETEQUERIES (p->OccQuerySize, p->OccQueries);
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;
1374 p->QueryCount = p->maxOccludersFound;
1375 #ifdef OCCLUSIONVERBOSE
1376 printf (
"QueryCount here is %d\n",p->QueryCount);
1390void OcclusionCulling () {
1416 zeroVisibilityFlag();
1419 if (tg->Frustum.OccFailed)
return;
1431 for (i=0; i<p->potentialOccluderCount; i++) {
1432 #ifdef OCCLUSIONVERBOSE
1433 printf (
"checking node %d of %d\n",i, p->potentialOccluderCount);
1439 shapePtr = X3D_SHAPE(p->occluderNodePointer[i]);
1440 if (shapePtr != NULL) {
1441 if (shapePtr->_nodeType == NODE_Shape) {
1443 checkCount = shapePtr->__occludeCheckCount;
1444 }
else if (shapePtr->_nodeType == NODE_VisibilitySensor) {
1445 visSenPtr = X3D_VISIBILITYSENSOR(shapePtr);
1447 checkCount = visSenPtr->__occludeCheckCount;
1449 printf (
"OcclusionCulling on node type %s not allowed\n",stringNodeType(shapePtr->_nodeType));
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);
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");
1464 #define SLEEP_FOR_QUERY_RESULTS
1465 #ifdef SLEEP_FOR_QUERY_RESULTS
1467 while (p->OccResultsAvailable == GL_FALSE) {
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");
1475 #ifdef OCCLUSIONVERBOSE
1476 if (p->OccResultsAvailable == GL_FALSE) printf (
"results not ready for %d\n",i);
1481 if (p->OccResultsAvailable == GL_FALSE) samples = 10000;
1483 FW_GL_GETQUERYOBJECTUIV (p->OccQueries[i], GL_QUERY_RESULT, &samples);
1484 PRINT_GL_ERROR_IF_ANY(
"FW_GL_GETQUERYOBJECTUIV::QUERY");
1486 #ifdef OCCLUSIONVERBOSE
1487 printf (
"i %d checkc %d samples %d\n",i,checkCount,samples);
1490 if (p->occluderNodePointer[i] != 0) {
1493 if (visSenPtr != NULL) {
1495 #ifdef OCCLUSIONVERBOSE
1496 printf (
"OcclusionCulling, found VisibilitySensor at %d, fragments %d active %d\n",i,samples,checkCount);
1502 if (checkCount != OCCCHECKNEXTLOOP) {
1505 visSenPtr->__visible = TRUE;
1506 visSenPtr->__occludeCheckCount = OCCCHECKNEXTLOOP;
1507 visSenPtr->__Samples = samples;
1509 visSenPtr->__occludeCheckCount = OCCCHECKSOON;
1510 visSenPtr->__visible =FALSE;
1511 visSenPtr->__Samples = 0;
1523 else if (shapePtr != NULL) {
1524 #ifdef OCCLUSIONVERBOSE
1525 printf (
"OcclusionCulling, found Shape %d, fragments %d active %d\n",i,samples,checkCount);
1531 if (checkCount != OCCWAIT) {
1534 if (samples > OCCSHAPESAMPLESIZE) {
1535 TRACE_MSG (
"Shape %p is VISIBLE\n",shapePtr);
1536 shapePtr->__visible = TRUE;
1537 shapePtr->__occludeCheckCount= OCCWAIT;
1538 shapePtr->__Samples = samples;
1540 TRACE_MSG (
"Shape %p is NOT VISIBLE\n",shapePtr);
1541 shapePtr->__visible=FALSE;
1542 shapePtr->__occludeCheckCount = OCCCHECKSOON;
1543 shapePtr->__Samples = 0;
1556void zeroOcclusion(
void) {
1565 if (tg->Frustum.OccFailed)
return;
1567 #ifdef OCCLUSIONVERBOSE
1568 printf (
"zeroOcclusion - potentialOccluderCount %d\n",p->potentialOccluderCount);
1571 for (i=0; i<p->potentialOccluderCount; i++) {
1572#ifdef OCCLUSIONVERBOSE
1573 printf (
"checking node %d of %d\n",i, p->potentialOccluderCount);
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
1580 while (p->OccResultsAvailable == GL_FALSE) {
1581#ifdef OCCLUSIONVERBOSE
1582 printf (
"zero - waiting and looping for results\n");
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");
1590#ifdef OCCLUSIONVERBOSE
1591 printf (
"zeroOcclusion - done waiting\n");
1605 p->maxOccludersFound = 0;
1606 p->OccInitialized = FALSE;
1607 p->potentialOccluderCount = 0;
1609 FREE_IF_NZ(p->OccQueries);
1610 FREE_IF_NZ(p->occluderNodePointer);