FreeWRL / FreeX3D 4.3.0
Component_Grouping.c
1/*
2
3
4X3D Grouping Component
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 "../vrml_parser/CRoutes.h"
39#include "../main/headers.h"
40
41#include "../opengl/OpenGL_Utils.h"
42#include "../opengl/Frustum.h"
43#include "../opengl/Material.h"
44
45#include "LinearAlgebra.h"
46#include "Children.h"
47#include "../scenegraph/RenderFuncs.h"
48
49typedef struct extent_type {
50float e[6];
51} extent_t;
52typedef struct mat4x4_type {
53 double mat[16];
54} mat4x4_t;
55typedef struct pComponent_Grouping{
56 Stack *group_visible_stack;
57 Stack *group_extent_stack;
58 Stack *transform_local_stack;
59}* ppComponent_Grouping;
60void *Component_Grouping_constructor(){
61 void *v = MALLOCV(sizeof(struct pComponent_Grouping));
62 memset(v,0,sizeof(struct pComponent_Grouping));
63 return v;
64}
65void Component_Grouping_init(struct tComponent_Grouping *t){
66 //public
67
68 //private
69 t->prv = Component_Grouping_constructor();
70 {
71 ppComponent_Grouping p = (ppComponent_Grouping)t->prv;
72 p->group_visible_stack = newStack(int);
73 stack_push(int,p->group_visible_stack,TRUE); //need something/default to && with at top of stack
74 p->group_extent_stack = newStack(extent_t);
75 p->transform_local_stack = newStack(mat4x4_t);
76 }
77}
78void Component_Grouping_clear(struct tComponent_Grouping *t){
79 ppComponent_Grouping p = (ppComponent_Grouping)t->prv;
80 deleteVector(struct X3D_Node*,p->transform_local_stack);
81 deleteVector(struct X3D_Node*,p->group_extent_stack);
82 deleteVector(struct X3D_Node*,p->group_visible_stack);
83}
84
85
86
87// v4 visibility functions, push & pop (to be) called from all X3DGroupingNode child_ functions
88void push_group_visible(int visible){
89 ppComponent_Grouping p = (ppComponent_Grouping)gglobal()->Component_Grouping.prv;
90 stack_push(int,p->group_visible_stack,visible);
91}
92void pop_group_visible(){
93 ppComponent_Grouping p = (ppComponent_Grouping)gglobal()->Component_Grouping.prv;
94 stack_pop(int,p->group_visible_stack);
95}
96int peek_group_visible(){
97 ppComponent_Grouping p = (ppComponent_Grouping)gglobal()->Component_Grouping.prv;
98 return stack_top(int,p->group_visible_stack);
99}
100
101// v4 bbox functions, push & pop (to be) called from all X3DGroupingNode child_ functions
102// children - geometry - will union their extent with the stack top owned by group with bbox (or scene root)
103void push_group_extent(float *e6){
104 extent_t e;
105 ppComponent_Grouping p = (ppComponent_Grouping)gglobal()->Component_Grouping.prv;
106 memcpy(&e.e,e6,6*sizeof(float));
107 testVector(extent_t, p->group_extent_stack);
108 stack_push(extent_t,p->group_extent_stack,e);
109 testVector(extent_t, p->group_extent_stack);
110}
111void push_group_extent_default(){
112 float extent6[6];
113 extent6f_clear(extent6);
114 push_group_extent(extent6);
115}
116void pop_group_extent(){
117 ppComponent_Grouping p = (ppComponent_Grouping)gglobal()->Component_Grouping.prv;
118 stack_pop(extent_t,p->group_extent_stack);
119}
120float * peek_group_extent(){
121 ppComponent_Grouping p = (ppComponent_Grouping)gglobal()->Component_Grouping.prv;
122 //extent_t* ee = (extent_t*)p->group_extent_stack->data;
123 //int index = p->group_extent_stack->n - 1;
124 //printf("ee[%d]=%p ", index, &ee[index]);
125 //extent_t* en = stack_top_ptr(extent_t, p->group_extent_stack);
126 //float* ef = en->e;
127 //printf("stack_top_ptr= %p en->e %p \n", en, ef);
128 return (stack_top_ptr(extent_t,p->group_extent_stack))->e;
129}
130void union_group_extent(float *e6){
131 ppComponent_Grouping p = (ppComponent_Grouping)gglobal()->Component_Grouping.prv;
132 float *etop = peek_group_extent();
133 testVector(extent_t, p->group_extent_stack);
134 extent6f_union_extent6f(etop,e6);
135 testVector(extent_t, p->group_extent_stack);
136}
137void draw_bbox(float *center, float *size);
138
139
140// v4 bbox functions, push & pop (to be) called from all X3DGroupingNode child_ functions
141// children - geometry - will union their extent with the stack top owned by group with bbox (or scene root)
142void push_transform_local(double *mat){
143 mat4x4_t m4;
144 ppComponent_Grouping p = (ppComponent_Grouping)gglobal()->Component_Grouping.prv;
145 memcpy(&m4.mat,mat,16*sizeof(double));
146 stack_push(mat4x4_t,p->transform_local_stack,m4);
147}
148void push_transform_local_identity(){
149 double m4[16];
150 matidentity4d(m4);
151 push_transform_local(m4);
152}
153void pop_transform_local(){
154 ppComponent_Grouping p = (ppComponent_Grouping)gglobal()->Component_Grouping.prv;
155 stack_pop(mat4x4_t,p->transform_local_stack);
156}
157double * peek_transform_local(){
158 ppComponent_Grouping p = (ppComponent_Grouping)gglobal()->Component_Grouping.prv;
159 return (stack_top_ptr(mat4x4_t,p->transform_local_stack))->mat;
160}
161void reset_transform_local(double *mat){
162 //no push or pop here, assume already pushed
163 double *mattop = peek_transform_local();
164 memcpy(mattop,mat,16*sizeof(double));
165}
166void multiply_transform_local(double *mat){
167 //no push or pop here, assume already pushed
168 double matboth[16];
169 double *mattop = peek_transform_local();
170 matmultiplyAFFINE(matboth,mat,mattop);
171 memcpy(mattop,matboth,16*sizeof(double));
172}
173void compile_Transform (struct X3D_Transform *node) {
174 INITIALIZE_EXTENT;
175
176 /* printf ("changed Transform for node %u\n",node); */
177 node->__do_center = verify_translate ((GLfloat *)node->center.c);
178 node->__do_trans = verify_translate ((GLfloat *)node->translation.c);
179 node->__do_scale = verify_scale ((GLfloat *)node->scale.c);
180 node->__do_rotation = verify_rotate ((GLfloat *)node->rotation.c);
181 node->__do_scaleO = verify_rotate ((GLfloat *)node->scaleOrientation.c);
182
183 node->__do_anything = (node->__do_center ||
184 node->__do_trans ||
185 node->__do_scale ||
186 node->__do_rotation ||
187 node->__do_scaleO);
188
189 REINITIALIZE_SORTED_NODES_FIELD(node->children,node->_sortedChildren);
190 MARK_NODE_COMPILED
191}
192
193
194/* we compile the Group so that children are not continuously sorted */
195void compile_Group(struct X3D_Group *node) {
196 REINITIALIZE_SORTED_NODES_FIELD(node->children,node->_sortedChildren);
197 /*
198 {
199 int i;
200 ConsoleMessage ("compile_Group, rootNode is %p",rootNode());
201 for (i=0; i<node->children.n; i++) ConsoleMessage ("compile_Group %p, c %d is %p",node,i,node->children.p[i]);
202 for (i=0; i<node->_sortedChildren.n; i++) ConsoleMessage ("compile_Group %p, sc %d is %p",node,i,node->_sortedChildren.p[i]);
203 }
204 */
205 MARK_NODE_COMPILED
206}
207
208/* prep_Group - we need this so that distance (and, thus, distance sorting) works for Groups */
209void prep_Group (struct X3D_Group *node) {
210 // printf ("prep_Group start dist %f\n",node->_dist);
211 COMPILE_IF_REQUIRED
212
213/*
214printf ("prepGroup %p (root %p), flags %x children %d ",node,rootNode,node->_renderFlags,node->children.n);
215if ((node->_renderFlags & VF_Viewpoint) == VF_Viewpoint) printf ("VF_Viewpoint ");
216if ((node->_renderFlags & VF_Geom) == VF_Geom) printf ("VF_Geom ");
217if ((node->_renderFlags & VF_localLight) == VF_localLight) printf ("VF_localLight ");
218if ((node->_renderFlags & VF_Sensitive) == VF_Sensitive) printf ("VF_Sensitive ");
219if ((node->_renderFlags & VF_Blend) == VF_Blend) printf ("VF_Blend ");
220if ((node->_renderFlags & VF_Proximity) == VF_Proximity) printf ("VF_Proximity ");
221if ((node->_renderFlags & VF_Collision) == VF_Collision) printf ("VF_Collision ");
222if ((node->_renderFlags & VF_globalLight) == VF_globalLight) printf ("VF_globalLight ");
223if ((node->_renderFlags & VF_hasVisibleChildren) == VF_hasVisibleChildren) printf ("VF_hasVisibleChildren ");
224if ((node->_renderFlags & VF_shouldSortChildren) == VF_shouldSortChildren) printf ("VF_shouldSortChildren ");*/
225/*if ((node->_renderFlags & VF_inPickableGroup) == VF_inPickableGroup) printf ("VF_inPickableGroup "); */
226/* printf ("\n"); */
227
228}
229
230/* do transforms, calculate the distance */
231void prep_Transform (struct X3D_Transform *node) {
232 COMPILE_IF_REQUIRED
233
234 /* rendering the viewpoint means doing the inverse transformations in reverse order (while poping stack),
235 * so we do nothing here in that case -ncoder */
236
237 /* printf ("prep_Transform, render_hier vp %d geom %d light %d sens %d blend %d prox %d col %d\n",
238 render_vp,render_geom,render_light,render_sensitive,render_blend,render_proximity,render_collision); */
239
240 /* do we have any geometry visible, and are we doing anything with geometry? */
241 OCCLUSIONTEST
242
243 if(!renderstate()->render_vp) {
244 /* do we actually have any thing to rotate/translate/scale?? */
245 push_transform_local_identity();
246 if (node->__do_anything) {
247
248 FW_GL_PUSH_MATRIX(); //this one will persist till fin_Transform pops it
249 FW_GL_PUSH_MATRIX(); //this is to get us a separate 4x4 matrix just for the stuff here
250 FW_GL_LOAD_IDENTITY(); // .. wehich we will save for child_Transform to propagate its bbox up to its extent
251
252 /* TRANSLATION */
253 if (node->__do_trans)
254 FW_GL_TRANSLATE_F(node->translation.c[0],node->translation.c[1],node->translation.c[2]);
255
256 /* CENTER */
257 if (node->__do_center)
258 FW_GL_TRANSLATE_F(node->center.c[0],node->center.c[1],node->center.c[2]);
259
260 /* ROTATION */
261 if (node->__do_rotation) {
262 FW_GL_ROTATE_RADIANS(node->rotation.c[3], node->rotation.c[0],node->rotation.c[1],node->rotation.c[2]);
263 }
264
265 /* SCALEORIENTATION */
266 if (node->__do_scaleO) {
267 FW_GL_ROTATE_RADIANS(node->scaleOrientation.c[3], node->scaleOrientation.c[0], node->scaleOrientation.c[1],node->scaleOrientation.c[2]);
268 }
269
270
271 /* SCALE */
272 if (node->__do_scale)
273 FW_GL_SCALE_F(node->scale.c[0],node->scale.c[1],node->scale.c[2]);
274
275 /* REVERSE SCALE ORIENTATION */
276 if (node->__do_scaleO)
277 FW_GL_ROTATE_RADIANS(-node->scaleOrientation.c[3], node->scaleOrientation.c[0], node->scaleOrientation.c[1],node->scaleOrientation.c[2]);
278
279 /* REVERSE CENTER */
280 if (node->__do_center)
281 FW_GL_TRANSLATE_F(-node->center.c[0],-node->center.c[1],-node->center.c[2]);
282 {
283 double mat[16];
284
285 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX,mat); //we got our local transform saved
286 FW_GL_POP_MATRIX();
287 FW_GL_TRANSFORM_D(mat); //now apply the above to prep for child_Tranform
288 reset_transform_local(mat);
289 }
290 }
291 }
292}
293
294
295void fin_Transform (struct X3D_Transform *node) {
296 OCCLUSIONTEST
297
298 if(!renderstate()->render_vp) {
299 pop_transform_local();
300 if (node->__do_anything) {
301 FW_GL_POP_MATRIX();
302 }
303 } else {
304 /*Rendering the viewpoint only means finding it, and calculating the reverse WorldView matrix.*/
305 if((node->_renderFlags & VF_Viewpoint) == VF_Viewpoint)
306 {
307 FW_GL_TRANSLATE_F(((node->center).c[0]),((node->center).c[1]),((node->center).c[2])
308 );
309 FW_GL_ROTATE_RADIANS(((node->scaleOrientation).c[3]),((node->scaleOrientation).c[0]),((node->scaleOrientation).c[1]),((node->scaleOrientation).c[2])
310 );
311 FW_GL_SCALE_F((float)1.0/(((node->scale).c[0])),(float)1.0/(((node->scale).c[1])),(float)1.0/(((node->scale).c[2]))
312 );
313 FW_GL_ROTATE_RADIANS(-(((node->scaleOrientation).c[3])),((node->scaleOrientation).c[0]),((node->scaleOrientation).c[1]),((node->scaleOrientation).c[2])
314 );
315 FW_GL_ROTATE_RADIANS(-(((node->rotation).c[3])),((node->rotation).c[0]),((node->rotation).c[1]),((node->rotation).c[2])
316 );
317 FW_GL_TRANSLATE_F(-(((node->center).c[0])),-(((node->center).c[1])),-(((node->center).c[2]))
318 );
319 FW_GL_TRANSLATE_F(-(((node->translation).c[0])),-(((node->translation).c[1])),-(((node->translation).c[2]))
320 );
321 }
322 }
323}
324
325void child_Switch (struct X3D_Switch *node) {
326 /* exceedingly simple - render only one child */
327 struct X3D_Node **pp;
328 int n;
329 int wc = node->whichChoice;
330
331 /* is this VRML, or X3D?? */
332 n = 0;
333 pp = NULL;
334 //if(node->children.n){
335 //if (node->__isX3D) {
336 int spec = X3D_PROTO(node->_executionContext)->__specversion;
337 if (spec < 300 || node->choice.n){
338 pp = node->choice.p;
339 n = node->choice.n;
340 } else {
341 pp = node->children.p;
342 n = node->children.n;
343 //} else if(node->choice.n){
344 }
345 if(n && pp){
346 if(wc >= 0 && wc < n){
347 void * p = pp[wc];
348
349 prep_BBox((struct BBoxFields*)&node->bboxCenter);
350
351 render_node(p);
352
353 fin_BBox((struct X3D_Node*)node,(struct BBoxFields*)&node->bboxCenter,FALSE);
354 }
355 }
356 //if (node->__isX3D || (node->children).n) {
357 // if(wc >= 0 && wc < (node->children).n) {
358 // void *p = ((node->children).p[wc]);
359 // render_node(p);
360 // }
361 //} else {
362 // if(wc >= 0 && wc < ((node->choice).n)) {
363 // void *p = ((node->choice).p[wc]);
364 // render_node(p);
365 // }
366 //}
367}
368
369
370
371void sib_prep_LocalFog(struct X3D_Node *parent, struct X3D_Node *sibAffector);
372void sib_prep_Light(struct X3D_Node* parent, struct X3D_Node* sibAffector);
373void sib_prep_ClipPlane(struct X3D_Node *parent, struct X3D_Node *sibAffector);
374void sib_prep_Effect(struct X3D_Node *parent, struct X3D_Node *sibAffector);
375void sib_prep_TextureProjector(struct X3D_Node *parent, struct X3D_Node *sibAffector);
376
377void sib_prep(struct X3D_Node *parent, struct X3D_Node *sibAffector){
378 switch(sibAffector->_nodeType){
379 case NODE_DirectionalLight:
380 case NODE_SpotLight:
381 case NODE_PointLight:
382 sib_prep_Light(parent, sibAffector);
383 break;
384 case NODE_LocalFog:
385 sib_prep_LocalFog(parent,sibAffector); break;
386 case NODE_ClipPlane:
387 sib_prep_ClipPlane(parent,sibAffector); break;
388 case NODE_Effect:
389 sib_prep_Effect(parent,sibAffector); break;
390 case NODE_TextureProjector:
391 case NODE_TextureProjectorParallel:
392 case NODE_TextureProjectorPoint:
393 sib_prep_TextureProjector(parent,sibAffector); break;
394 default:
395 break;
396 }
397}
398
399void sib_fin_LocalFog(struct X3D_Node *parent, struct X3D_Node *sibAffector);
400void sib_fin_Light(struct X3D_Node* parent, struct X3D_Node* sibAffector);
401
402void sib_fin_ClipPlane(struct X3D_Node *parent, struct X3D_Node *sibAffector);
403void sib_fin_Effect(struct X3D_Node *parent, struct X3D_Node *sibAffector);
404void sib_fin_TextureProjector(struct X3D_Node *parent, struct X3D_Node *sibAffector);
405
406void sib_fin(struct X3D_Node *parent, struct X3D_Node *sibAffector){
407 switch(sibAffector->_nodeType){
408 case NODE_DirectionalLight:
409 case NODE_SpotLight:
410 case NODE_PointLight:
411 sib_fin_Light(parent, sibAffector);
412 break;
413 case NODE_LocalFog:
414 sib_fin_LocalFog(parent,sibAffector); break;
415 case NODE_ClipPlane:
416 sib_fin_ClipPlane(parent,sibAffector); break;
417 case NODE_Effect:
418 sib_fin_Effect(parent,sibAffector); break;
419 case NODE_TextureProjector:
420 case NODE_TextureProjectorParallel:
421 case NODE_TextureProjectorPoint:
422 sib_fin_TextureProjector(parent,sibAffector); break;
423
424 default:
425 break;
426 }
427}
428void prep_sibAffectors(struct X3D_Node *parent, struct Multi_Node* affectors){
429 if(affectors->n){
430 int j;
431 for(j=0;j<affectors->n;j++){
432 struct X3D_Node *sa = affectors->p[j];
433 sib_prep(parent,sa);
434 }
435 }
436}
437void fin_sibAffectors(struct X3D_Node *parent, struct Multi_Node* affectors){
438 if(affectors->n){
439 int j,jj;
440 for(jj=0;jj<affectors->n;jj++){
441 //we go backwards so any sib_fin popping is in reverse order to any sib_prep pushing,
442 // in case multiple push to same stack, as with multiple Effects
443 struct X3D_Node *sa;
444 j = affectors->n - jj - 1;
445 sa = affectors->p[j];
446 sib_fin(parent,sa);
447 }
448 }
449}
450
451//WARNING all nodes that use prep_childrenBBox /fin_ musht have bbox fields in same order
452// (this is a way to avoid macros, and re-casting lookups)
453//struct BBoxFields {
454// struct SFVec3f bboxCenter;
455// struct SFVec3f bboxSize;
456// int visible;
457// int displayBBox;
458//
459//};
460void prep_BBox(struct BBoxFields *bfields){
461 ttrenderstate rs = renderstate(); //just want pure geom or geom+blend
462 if (rs->render_vp || rs->render_other || rs->render_sensitive || rs->render_depth || rs->render_light || rs->render_cube || rs->render_collision) return;
463 push_group_extent_default();
464 push_group_visible( bfields->visible && peek_group_visible());
465}
466
467//#define VERBOSE
468void fin_BBox(struct X3D_Node *node, struct BBoxFields *bfields, int transtype){
469 ttrenderstate rs = renderstate(); //just want pure geom or geom+blend
470 if (rs->render_vp || rs->render_other || rs->render_sensitive || rs->render_depth || rs->render_light || rs->render_cube || rs->render_collision)
471 return;
472
473 #ifdef VERBOSE
474 printf ("\nstart fin_BBox\n");
475 printf ("... node %p type %s\n",node, stringNodeType(node->_nodeType));
476 printf ("... center %4.3f %4.3f %4.3f, size %4.3f %4.3f %4.3f\n",
477 bfields->bboxCenter.c[0],
478 bfields->bboxCenter.c[1],
479 bfields->bboxCenter.c[2],
480 bfields->bboxSize.c[0],
481 bfields->bboxSize.c[1],
482 bfields->bboxSize.c[2]);
483
484 #endif //VERBOSE
485
486 pop_group_visible();
487 //bbox - in child-space - gets transformed/propagated to Transform parent space and set as Transform._extent
488 extent6f2bbox(peek_group_extent(),bfields->bboxCenter.c,bfields->bboxSize.c);
489
490 #ifdef VERBOSE
491 printf ("step1 fin_BBox\n");
492 printf ("... node %p type %s\n",node, stringNodeType(node->_nodeType));
493 printf ("... center %4.3f %4.3f %4.3f, size %4.3f %4.3f %4.3f\n",
494 bfields->bboxCenter.c[0],
495 bfields->bboxCenter.c[1],
496 bfields->bboxCenter.c[2],
497 bfields->bboxSize.c[0],
498 bfields->bboxSize.c[1],
499 bfields->bboxSize.c[2]);
500 #endif //VERBOSE
501
502 if(renderstate()->render_geom && (bfields->bboxDisplay || fwl_getDrawBoundingBoxes() )) {
503 draw_bbox(bfields->bboxCenter.c,bfields->bboxSize.c);
504 }
505 //propagate bbox up one level
506 if(transtype){
507 //for transform type nodes, we capture a matrix in prep_Transform (and pop it in fin_Transform)
508 //so we can transform the bbox up one level into parent space - so called 'propagating' extent
509 extent6f_mattransform4d(node->_extent,peek_group_extent(),peek_transform_local());
510 }else{
511 //non-transforming grouping nodes - just copy bbox of children into parent space
512 extent6f_copy(node->_extent,peek_group_extent());
513 }
514
515
516 #ifdef VERBOSE
517 printf ("step2 fin_BBox\n");
518 printf ("... node %p type %s\n",node, stringNodeType(node->_nodeType));
519 printf ("... center %4.3f %4.3f %4.3f, size %4.3f %4.3f %4.3f\n",
520 bfields->bboxCenter.c[0],
521 bfields->bboxCenter.c[1],
522 bfields->bboxCenter.c[2],
523 bfields->bboxSize.c[0],
524 bfields->bboxSize.c[1],
525 bfields->bboxSize.c[2]);
526 #endif //VERBOSE
527
528 pop_group_extent(); // up where parents are
529 union_group_extent(node->_extent); //
530
531 record_ZBufferDistance(node,bfields);
532
533 #ifdef VERBOSE
534 printf ("node %p %s extent ",node,stringNodeType(node->_nodeType));
535 int i;
536 for (i=0; i<6; i++) printf ("%4.3f ",node->_extent[i]); printf ("\n");
537 printf ("recording Z_BufferDistance at %s:%d\n",__FILE__,__LINE__);
538 #endif //VERBOSE
539
540 #ifdef VERBOSE
541 printf ("fin fin_BBox nodeType %s\n",stringNodeType(node->_nodeType));
542 #endif //VERBOSE
543}
544#undef VERBOSE
545
546
547void child_StaticGroup (struct X3D_StaticGroup *node) {
548 CHILDREN_COUNT
549 //LOCAL_LIGHT_SAVE
550
551 RETURN_FROM_CHILD_IF_NOT_FOR_ME
552
553 /* did this change? */
554 if NODE_NEEDS_COMPILING {
555 REINITIALIZE_SORTED_NODES_FIELD(node->children,node->_sortedChildren);
556 //ConsoleMessage ("StaticGroup changed");
557 MARK_NODE_COMPILED;
558 }
559
560 /* do we have a local light for a child? */
561 //LOCAL_LIGHT_CHILDREN(node->_sortedChildren);
562 prep_sibAffectors((struct X3D_Node*)node,&node->__sibAffectors);
563
564 /* now, just render the non-directionalLight children */
565 prep_BBox((struct BBoxFields*)&node->bboxCenter);
566 normalChildren(node->_sortedChildren);
567 fin_BBox((struct X3D_Node*)node,(struct BBoxFields*)&node->bboxCenter,FALSE);
568
569 //LOCAL_LIGHT_OFF
570 fin_sibAffectors((struct X3D_Node*)node,&node->__sibAffectors);
571
572}
573
574void child_Group (struct X3D_Group *node) {
575 // UNUSED int renderFirstProtoChildOnlyAsPerSpecs = 1;
576 CHILDREN_COUNT
577// LOCAL_LIGHT_SAVE
578
579 /*
580printf ("chldGroup %p (root %p), flags %x children %d ",node,rootNode,node->_renderFlags,node->children.n);
581if ((node->_renderFlags & VF_Viewpoint) == VF_Viewpoint) printf ("VF_Viewpoint ");
582if ((node->_renderFlags & VF_Geom) == VF_Geom) printf ("VF_Geom ");
583if ((node->_renderFlags & VF_localLight) == VF_localLight) printf ("VF_localLight ");
584if ((node->_renderFlags & VF_Sensitive) == VF_Sensitive) printf ("VF_Sensitive ");
585if ((node->_renderFlags & VF_Blend) == VF_Blend) printf ("VF_Blend ");
586if ((node->_renderFlags & VF_Proximity) == VF_Proximity) printf ("VF_Proximity ");
587if ((node->_renderFlags & VF_Collision) == VF_Collision) printf ("VF_Collision ");
588if ((node->_renderFlags & VF_globalLight) == VF_globalLight) printf ("VF_globalLight ");
589if ((node->_renderFlags & VF_hasVisibleChildren) == VF_hasVisibleChildren) printf ("VF_hasVisibleChildren ");
590if ((node->_renderFlags & VF_shouldSortChildren) == VF_shouldSortChildren) printf ("VF_shouldSortChildren ");
591printf ("\n");
592*/
593
594 RETURN_FROM_CHILD_IF_NOT_FOR_ME
595
596 if(1){
597 //stereoscopic experiments
598 ttrenderstate rs = renderstate();
599 if (rs->render_geom) { //== VF_Geom) {
600 if (node->_renderFlags & VF_HideLeft && (viewer_iside() == 0) ) {
601 return;
602 }
603 if (node->_renderFlags & VF_HideRight && (viewer_iside() == 1) ) {
604 return;
605 }
606 }
607 }
608 prep_sibAffectors((struct X3D_Node*)node,&node->__sibAffectors);
609
610
611#ifdef VERBOSE
612 {
613 int x;
614 struct X3D_Node *xx;
615
616printf ("child_Group, children.n %d sortedChildren.n %d\n",node->children.n, node->_sortedChildren.n);
617
618 printf ("child_Group, this %p rf %x isProto %d\n",node,node->_renderFlags, node->FreeWRL__protoDef);
619// printf (" ..., render_hier vp %d geom %d light %d sens %d blend %d prox %d col %d\n",
620// render_vp,render_geom,render_light,render_sensitive,render_blend,render_proximity,render_collision);
621 for (x=0; x<nc; x++) {
622 xx = X3D_NODE(node->_sortedChildren.p[x]);
623 if (xx)
624 printf (" %d: ch %p type %s dist %f\n",x, node->_sortedChildren.p[x],stringNodeType(xx->_nodeType),xx->_dist);
625 else printf (" chiuld %d null\n",x);
626 }
627 for (x=0; x<nc; x++) {
628 xx = X3D_NODE(node->_sortedChildren.p[x]);
629 if (xx)
630 printf (" %d: sch %p type %s dist %f\n",x, node->_sortedChildren.p[x],stringNodeType(xx->_nodeType),xx->_dist);
631 else printf (" chiuld %d null\n",x);
632 }
633 }
634#endif //VERBOSE
635
636 /* do we have a DirectionalLight for a child? */
637// LOCAL_LIGHT_CHILDREN(node->_sortedChildren);
638
639 /* printf ("chld_Group, for %u, protodef %d and FreeWRL_PROTOInterfaceNodes.n %d\n",
640 node, node->FreeWRL__protoDef, node->FreeWRL_PROTOInterfaceNodes.n); */
641 /* now, just render the non-directionalLight children */
642 // UNUSED renderFirstProtoChildOnlyAsPerSpecs = 0; //flux/vivaty render all children
643 prep_BBox((struct BBoxFields*)&node->bboxCenter);
644 normalChildren(node->_sortedChildren);
645 fin_BBox((struct X3D_Node*)node,(struct BBoxFields*)&node->bboxCenter,FALSE);
646
647 #ifdef VERBOSE
648 printf ("child_Group ");
649 //WARNING all nodes that use prep_childrenBBox /fin_ musht have bbox fields in same order
650 // (this is a way to avoid macros, and re-casting lookups)
651 //struct BBoxFields {
652 // struct SFVec3f bboxCenter;
653 // struct SFVec3f bboxSize;
654 // int visible;
655 // int displayBBox;
656 //
657 //};
658 printf ("bboxCenter %4.3f %4.3f %4.3f ",node->bboxCenter.c[0],node->bboxCenter.c[1],node->bboxCenter.c[2]);
659 printf ("bboxSize %4.3f %4.3f %4.3f ",node->bboxSize.c[0],node->bboxSize.c[1],node->bboxSize.c[2]);
660 printf ("visible %d displayBox %d\n",node->visible,node->bboxDisplay);
661 #endif //VERBOSE
662
663
664
665// LOCAL_LIGHT_OFF
666
667 fin_sibAffectors((struct X3D_Node*)node,&node->__sibAffectors);
668}
669
670
671void child_Transform (struct X3D_Transform *node) {
672 // printf ("start child_Transform, dist %f\n",node->_dist);
673 //LOCAL_LIGHT_SAVE
674 CHILDREN_COUNT
675 OCCLUSIONTEST
676
677 RETURN_FROM_CHILD_IF_NOT_FOR_ME
678
679 if(1){
680 //stereoscopic experiments
681 ttrenderstate rs = renderstate();
682 if (rs->render_geom) { //== VF_Geom) {
683 if (node->_renderFlags & VF_HideLeft && (viewer_iside() == 0) ) {
684 return;
685 }
686 if (node->_renderFlags & VF_HideRight && (viewer_iside() == 1) ) {
687 return;
688 }
689 }
690 }
691
692 /* any children at all? */
693 if (nc==0) return;
694
695 //if(node->__sibAffectors.n)
696 // printf("have transform sibaffectors\n");
697 prep_sibAffectors((struct X3D_Node*)node,&node->__sibAffectors);
698
699
700 //profile_start("local_light_kids");
701 /* do we have a local light for a child? */
702// LOCAL_LIGHT_CHILDREN(node->_sortedChildren);
703 //profile_end("local_light_kids");
704 /* now, just render the non-directionalLight children */
705
706 /* printf ("Transform %d, flags %d, render_sensitive %d\n",
707 node,node->_renderFlags,render_sensitive); */
708
709 #ifdef CHILDVERBOSE
710 printf ("transform - doing normalChildren\n");
711 #endif
712
713 prep_BBox((struct BBoxFields*)&node->bboxCenter);
714 normalChildren(node->_sortedChildren);
715 fin_BBox((struct X3D_Node*)node,(struct BBoxFields*)&node->bboxCenter,TRUE);
716
717 #ifdef CHILDVERBOSE
718 printf ("transform - done normalChildren\n");
719 #endif
720
721// LOCAL_LIGHT_OFF
722 fin_sibAffectors((struct X3D_Node*)node,&node->__sibAffectors);
723 //printf ("fin child_Transform, dist %f\n",node->_dist);
724}
725
726
727/* prep_Proto - this is a ProtoInstance (not declare) */
728/*pack 4 flags into one int, using char */
729char ciflag_get(int flags, int index){
730 char *cflags = (char *)(&flags);
731 return cflags[index];
732}
733int ciflag_set(int flags, char flag, int index ){
734 char *cflags = (char *)(&flags);
735 cflags[index] = flag;
736 return flags;
737}
738void prep_Proto (struct X3D_Proto *node) {
739 if(0)printf("in prep_proto\n");
740 load_externProtoInstance(node);
741 COMPILE_IF_REQUIRED
742 //RECORD_DISTANCE
743}
744/* not sure why we would compile */
745void compile_Proto(struct X3D_Proto *node) {
746 unsigned char pflag;
747 if(0)printf("in compile_proto\n");
748 pflag = ciflag_get(node->__protoFlags,2);
749 if(pflag == 2){
750 //scene
751 REINITIALIZE_SORTED_NODES_FIELD(node->__children,node->_sortedChildren);
752 }
753 MARK_NODE_COMPILED
754}
755
756
757//UNIT statement - applying unit scalefactor during rendering
758int doLengthUnits();
759int isUnitSpecVersionOK(int specversion);
760static int unitoption_scalescene = TRUE; //FALSE is this what specs say, don't scale top scene?
761void prep_unitscale (struct X3D_Proto *ec) {
762 //if(doLengthUnits() && isUnitSpecVersionOK(ec->__specversion)){
763 if(doLengthUnits()){
764 if(!renderstate()->render_vp) {
765 struct X3D_Proto *parent;
766 double factor = 1.0; //default factor applied if current context < v3.3
767 double parentfactor = 1.0; //default factor applied if parent context < v3.3 or no parent
768 parent = X3D_PROTO(ec->_executionContext); //__parentProto); //not sure this is correct. Looking for parent context of Instance, not ProtoDefinition
769 FW_GL_PUSH_MATRIX();
770 // SCALE
771 if(isUnitSpecVersionOK(ec->__specversion)){
772 factor = ec->__unitlengthfactor;
773 }
774 if(parent){
775 if(isUnitSpecVersionOK(parent->__specversion))
776 parentfactor = parent->__unitlengthfactor;
777 }else {
778 //there's no higher level context, which means we are in the top scene
779 if(unitoption_scalescene){
780 parentfactor = 1.0; //scale top scene length to SI base units [m] (not what specs say)
781 }else{
782 parentfactor = factor;
783 //top level scene gets scale of 1 ie if its in feet it stays feet, .3048/.3048=1 as per specs
784 //this is so defaults like Sphere radius=1 will be 1 foot, no need to tinker with defaults
785 }
786 }
787 //printf("( factor %lf / parentfactor= %lf ", factor, parentfactor);
788 factor = factor / parentfactor;
789 //printf(" = %lf)\n",factor);
790 FW_GL_SCALE_D(factor,factor,factor);
791 //RECORD_DISTANCE
792 }
793 }
794}
795
796
797void fin_unitscale (struct X3D_Proto *ec) {
798
799 //if(doLengthUnits() && isUnitSpecVersionOK(ec->__specversion)){
800 if(doLengthUnits()){
801 if(!renderstate()->render_vp) {
802 FW_GL_POP_MATRIX();
803 }
804 /*
805 else {
806 //Rendering the viewpoint only means finding it, and calculating the reverse WorldView matrix.
807 if((ec->_renderFlags & VF_Viewpoint) == VF_Viewpoint) {
808 struct X3D_Proto *parent;
809 double factor = 1.0;
810 double parentfactor = 1.0;
811 parent = X3D_PROTO(ec->__parentProto); //not sure this is correct. Looking for parent context of Instance, not ProtoDefinition
812 if(parent)
813 parentfactor = parent->__unitlengthfactor;
814 FW_GL_PUSH_MATRIX();
815 // SCALE
816 factor = ec->__unitlengthfactor;
817 factor = parentfactor / factor;
818
819 FW_GL_SCALE_D(factor,factor,factor);
820 }
821 }
822 */
823 }
824}
825
826
827/* render the first node only unless scene (see component_networking.c child_inline for scene-similar*/
828void child_Proto (struct X3D_Proto *node) {
829 int nc;
830 unsigned char sceneflag;
831 int renderFirstProtoChildOnlyAsPerSpecs;
832 //LOCAL_LIGHT_SAVE
833 if(0)printf("in child_proto\n");
834 //CHILDREN_COUNT
835 nc = node->__children.n; //_sortedChildren.n;
836/*
837printf ("chldGroup %p (root %p), flags %x children %d ",node,rootNode,node->_renderFlags,node->children.n);
838if ((node->_renderFlags & VF_Viewpoint) == VF_Viewpoint) printf ("VF_Viewpoint ");
839if ((node->_renderFlags & VF_Geom) == VF_Geom) printf ("VF_Geom ");
840if ((node->_renderFlags & VF_localLight) == VF_localLight) printf ("VF_localLight ");
841if ((node->_renderFlags & VF_Sensitive) == VF_Sensitive) printf ("VF_Sensitive ");
842if ((node->_renderFlags & VF_Blend) == VF_Blend) printf ("VF_Blend ");
843if ((node->_renderFlags & VF_Proximity) == VF_Proximity) printf ("VF_Proximity ");
844if ((node->_renderFlags & VF_Collision) == VF_Collision) printf ("VF_Collision ");
845if ((node->_renderFlags & VF_globalLight) == VF_globalLight) printf ("VF_globalLight ");
846if ((node->_renderFlags & VF_hasVisibleChildren) == VF_hasVisibleChildren) printf ("VF_hasVisibleChildren ");
847if ((node->_renderFlags & VF_shouldSortChildren) == VF_shouldSortChildren) printf ("VF_shouldSortChildren ");
848
849printf ("\n");
850*/
851 RETURN_FROM_CHILD_IF_NOT_FOR_ME
852 //if(node->__loadstatus != LOAD_STABLE) return; #define LOAD_STABLE 10
853 push_executionContext(X3D_NODE(node));
854 prep_unitscale(node);
855
856#ifdef VERBOSE
857 {
858 int x;
859 struct X3D_Node *xx;
860
861printf ("child_Group, children.n %d sortedChildren.n %d\n",node->children.n, node->_sortedChildren.n);
862
863 printf ("child_Group, this %p rf %x isProto %d\n",node,node->_renderFlags, node->FreeWRL__protoDef);
864// printf (" ..., render_hier vp %d geom %d light %d sens %d blend %d prox %d col %d\n",
865// render_vp,render_geom,render_light,render_sensitive,render_blend,render_proximity,render_collision);
866 for (x=0; x<nc; x++) {
867 xx = X3D_NODE(node->_sortedChildren.p[x]);
868 if (xx)
869 printf (" %d: ch %p type %s dist %f\n",x, node->_sortedChildren.p[x],stringNodeType(xx->_nodeType),xx->_dist);
870 else printf (" chiuld %d null\n",x);
871 }
872 for (x=0; x<nc; x++) {
873 xx = X3D_NODE(node->_sortedChildren.p[x]);
874 if (xx)
875 printf (" %d: sch %p type %s dist %f\n",x, node->_sortedChildren.p[x],stringNodeType(xx->_nodeType),xx->_dist);
876 else printf (" chiuld %d null\n",x);
877 }
878 }
879#endif //VERBOSE
880
881
882
883 prep_sibAffectors((struct X3D_Node*)node,&node->__sibAffectors);
884 prep_BBox((struct BBoxFields*)&node->bboxCenter);
885
886
887 sceneflag = ciflag_get(node->__protoFlags,2);
888 renderFirstProtoChildOnlyAsPerSpecs = TRUE; //FALSE is like flux / vivaty
889 //I don't think inline.children comes through here, just scene and protoInstance
890 if(sceneflag == 2 ){
891 normalChildren(node->_sortedChildren);
892 }else{
893 if(renderFirstProtoChildOnlyAsPerSpecs && (renderstate()->render_geom || renderstate()->render_blend)) {
894 //H: its just when rendering drawable geometry that we take only the first node
895 (node->__children).n = 1;
896 normalChildren(node->__children);
897 (node->__children).n = nc;
898 } else {
899 //H: else even for Protobodies, we may visit all rootnodes & descendants
900 // in case they need some updating on a non-draw scenegraph pass?
901 normalChildren(node->__children);
902 }
903 }
904
905 fin_BBox((struct X3D_Node*)node,(struct BBoxFields*)&node->bboxCenter,FALSE);
906
907 fin_sibAffectors((struct X3D_Node*)node,&node->__sibAffectors);
908 fin_unitscale(node);
909 pop_executionContext();
910
911}
912