FreeWRL / FreeX3D 4.3.0
Children.c
1/*
2
3
4Render the children of nodes.
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 "quaternion.h"
39
40#include "Children.h"
41#include "Collision.h"
42#include "../opengl/OpenGL_Utils.h"
43#include "RenderFuncs.h"
44#include "../opengl/Frustum.h"
45
46#define DJ_KEEP_COMPILER_WARNING 0
47
48#if DJ_KEEP_COMPILER_WARNING
49#define VF_localLight 0x0004
50#endif
51
52/* this grouping node has a local light for a child, render this first */
53void localLightChildren(struct Multi_Node ch) {
54 int i;
55 for(i=0; i<ch.n; i++) {
56 struct X3D_Node *p = X3D_NODE(ch.p[i]);
57 if (p != NULL) {
58 if ((p->_nodeType == NODE_DirectionalLight) ||
59 (p->_nodeType == NODE_PointLight) ||
60 (p->_nodeType == NODE_SpotLight))
61 render_node(p);
62 }
63 }
64}
65
66/* render all children, except the directionalight ones */
67void normalChildren(struct Multi_Node ch) {
68 int i;
69 struct X3D_Node *p;
70
71 for(i=0; i<ch.n; i++) {
72 p = X3D_NODE(ch.p[i]); //ATOMIC OP -if it bombs here with .n valid and .p junk, then addRemoveChildren has just expanded .p and FREEd the old one
73 //ConsoleMessage("NC, ch %d is %p",i,p);
74 if (p != NULL) {
75 /* printf ("child %d of %d is a %s\n",i,ch.n,stringNodeType(p->_nodeType)); */
76 /* as long as this is not a local light... if it is, it will be handled by
77 the localLightChildren function, above */
78 if (p->_nodeType == NODE_DirectionalLight) {
79 if (X3D_DIRECTIONALLIGHT(p)->global == TRUE) render_node(p);
80 } else if (p->_nodeType == NODE_SpotLight) {
81 if (X3D_SPOTLIGHT(p)->global == TRUE) render_node(p);
82 } else if (p->_nodeType == NODE_PointLight) {
83 if (X3D_POINTLIGHT(p)->global == TRUE)
84 render_node(p);
85 } else if (p->_nodeType == NODE_TextureProjector) {
86 if (X3D_TEXTUREPROJECTOR(p)->global == TRUE)
87 render_node(p);
88 } else if (p->_nodeType == NODE_TextureProjectorParallel) {
89 if (X3D_TEXTUREPROJECTORPARALLEL(p)->global == TRUE)
90 render_node(p);
91 } else if (p->_nodeType == NODE_TextureProjectorPoint) {
92 if (X3D_TEXTUREPROJECTORPOINT(p)->global == TRUE)
93 render_node(p);
94 } else
95 render_node(p);
96 }
97 }
98}
99
100/* propagate flags up the scene graph */
101/* used to tell the rendering pass that, there is/used to be nodes
102 * of interest down the branch. Eg, Transparent nodes - no sense going
103 * through it all when rendering only for nodes. */
104int is_vp_new_way();
105
106/* void update_renderFlag (struct X3D_Node *p, int flag) { */
107//void update_renderFlagB (struct X3D_Node *p, int flag, char *fi, int li) {
108void update_renderFlagB (struct X3D_Node *p, int flag, int li) {
109 int i;
110 static int depth = 0;
111 /* send notification up the chain */
112
113 #ifdef VERBOSE
114 printf ("start of update_renderFlag from %d for %p (%s) flag %x parents %d\n",li,p, stringNodeType(p->_nodeType),
115 flag, vectorSize(p->_parentVector));
116 if (p->_nodeType == NODE_Shape) {
117 printf ("... and this one is our Shape...\n");
118 for (i = 0; i < vectorSize(p->_parentVector); i++) {
119 struct X3D_Node *me = vector_get(struct X3D_Node *,p->_parentVector, i);
120 printf ("Shape parent %d is %p, type %s\n",i,me,stringNodeType(me->_nodeType));
121 }
122 }
123 #endif //VERBOSE
124
125
126
127//JAS if (vectorSize(p->_parentVector) <=0) {
128 //printf ("update_renderFlag, for node %p (%s), parentVector is zero, returning...\n",p,stringNodeType(p->_nodeType));
129//JAS return;
130//JAS }
131
132 //if (p==NULL) {
133 // ConsoleMessage ("update_renderFlag, p NULL from %s:%d\n",fi,li);
134 // return;
135 //}
136 p->_renderFlags = p->_renderFlags | flag;
137
138 if (p->_parentVector == NULL) {
139 //ConsoleMessage ("update_renderFlag, %p->parentVector NULL refcount %d (%s) from %s:%d\n",p,p->referenceCount,stringNodeType(p->_nodeType),fi,li);
140 return;
141 }
142
143 for (i = 0; i < vectorSize(p->_parentVector); i++) {
144 struct X3D_Node *me = vector_get(struct X3D_Node *,p->_parentVector, i);
145
146 // JAS printf ("update_renderFlagB, reference count for parent %p is %d\n",me,me->referenceCount);
147 if (me->referenceCount > 0) {
148
149 // JAS printf ("update_renderFlagB, line %d node type %p %s\n",__LINE__,me,stringNodeType(me->_nodeType));
150
151 if (me==NULL) {
152 ConsoleMessage ("update_renderFlag, me NULL for child %d",i);
153 markForDispose(p, TRUE);
154 return;
155 }
156
157 if (me->_parentVector == NULL) {
158
159 // JAS printf ("update_renderFlagB, warning, for node %p (%s), pv %d, child has null parentVector\n",p,stringNodeType(p->_nodeType),i);
160 ConsoleMessage ("warning, for node %p (%s), pv %d, child has null parentVector\n",p,stringNodeType(p->_nodeType),i);
161 markForDispose(p, TRUE);
162 return;
163 }
164 depth++;
165 if(depth < 50){
166 // printf ("node %d type %s has node %d type %s for a parent\n",p,stringNodeType(p->_nodeType),me,stringNodeType(me->_nodeType));
167 switch (me->_nodeType) {
168
169 case NODE_Switch:
170 if (is_Switchchild_inrange(X3D_SWITCH(me),p)) {
171 /* printf ("switch, this is the chosen node\n"); */
172 update_renderFlagB(me,flag, __LINE__);
173 }
174 break;
175
176 case NODE_LOD:
177 /* works for both X3D and VRML syntax; compare with the "_selected" field */
178 if (is_vp_new_way() || p == X3D_LODNODE(me)->_selected) {
179 update_renderFlagB(me,flag, __LINE__);
180 }
181 break;
182
183 case NODE_GeoLOD:
184 if (is_GeoLODchild_inrange(X3D_GEOLOD(me),p)) {
185 /* printf ("switch, this is the chosen node\n"); */
186 update_renderFlagB(me,flag, __LINE__);
187 }
188 break;
189
190 //case NODE_CADLayer:
191 // if (is_CADLayerchild_inrange(X3D_CADLAYER(me),p)) {
192 // update_renderFlagB(me,flag, __LINE__);
193 // }
194 // break;
195
196 default:
197
198 update_renderFlagB(me,flag, __LINE__);
199 }
200 }
201 depth--;
202 } // referenceCount check
203 }
204 /* printf ("finished update_RenderFlag for %d\n",p); */
205}
206int update_renderFlagC(struct X3D_Node* p, int flag, int setaction) {
207 int i;
208 static int depth = 0;
209 // send notification up the chain
210 // just for vp and vp_new_way for LOD proposed spec change:
211 // when user choses a VP (viewpoint) under an LOD child that's unchosen,
212 // the VP will be chosen and bound, and the LOD choice will change to match
213 // that means 2 changes: 1) user requested VP under LOD must succeed in binding
214 // and 2) the LOD choice must change
215 // here we attempt both.
216 // setaction = 0 clear = 1 set
217 // -- allows us to unset a path for the last bound vp, so we can try again with different vp
218 int iret = 0; //0 - unsuccessful/did not reach rootNode() 1= successful / reached rootNode
219
220 if (setaction)
221 p->_renderFlags = p->_renderFlags | flag; //unconditionally set flag
222 else
223 p->_renderFlags = p->_renderFlags & (0xFFFF ^ flag); //unconditionally unset flag
224
225
226 if (p->_parentVector == NULL || vectorSize(p->_parentVector) == 0) {
227 //ConsoleMessage ("update_renderFlag, %p->parentVector NULL refcount %d (%s) from %s:%d\n",p,p->referenceCount,stringNodeType(p->_nodeType),fi,li);
228 if (p == rootNode()) iret = 1;
229 return iret;
230 }
231
232 for (i = 0; i < vectorSize(p->_parentVector); i++) {
233 struct X3D_Node* me = vector_get(struct X3D_Node*, p->_parentVector, i);
234
235 // JAS printf ("update_renderFlagB, reference count for parent %p is %d\n",me,me->referenceCount);
236 if (me->referenceCount > 0) {
237
238 // JAS printf ("update_renderFlagB, line %d node type %p %s\n",__LINE__,me,stringNodeType(me->_nodeType));
239
240 if (me == NULL) {
241 ConsoleMessage("update_renderFlag, me NULL for child %d", i);
242 markForDispose(p, TRUE);
243 return iret;
244 }
245
246 if (me->_parentVector == NULL) {
247
248 // JAS printf ("update_renderFlagB, warning, for node %p (%s), pv %d, child has null parentVector\n",p,stringNodeType(p->_nodeType),i);
249 ConsoleMessage("warning, for node %p (%s), pv %d, child has null parentVector\n", p, stringNodeType(p->_nodeType), i);
250 markForDispose(p, TRUE);
251 return iret;
252 }
253 depth++;
254 if (depth < 50) {
255 // printf ("node %d type %s has node %d type %s for a parent\n",p,stringNodeType(p->_nodeType),me,stringNodeType(me->_nodeType));
256 switch (me->_nodeType) {
257
258 case NODE_Switch:
259 if (is_Switchchild_inrange(X3D_SWITCH(me), p)) {
260 /* printf ("switch, this is the chosen node\n"); */
261 iret = update_renderFlagC(me, flag, setaction);
262 }
263 break;
264
265 case NODE_LOD:
266 /* works for both X3D and VRML syntax; compare with the "_selected" field */
267 if (is_vp_new_way() || p == X3D_LODNODE(me)->_selected) {
268 iret = update_renderFlagC(me, flag, setaction);
269 if (iret && setaction) {
270 X3D_LODNODE(me)->_selected = p; //vp_new_way proposed by Don: user selecting a VP under an unchosen LOD child would set that child as selected
271 X3D_LODNODE(me)->_lastMethod = 1; //tells proximity_LOD to skip distance tests till viewpoint finishes slerping
272 //printf("updateRenderflagsC setting LOD_selected = %p\n", p);
273 }
274 }
275 break;
276
277 case NODE_GeoLOD:
278 if (is_GeoLODchild_inrange(X3D_GEOLOD(me), p)) {
279 /* printf ("switch, this is the chosen node\n"); */
280 iret = update_renderFlagC(me, flag, setaction);
281 }
282 break;
283
284 //case NODE_CADLayer:
285 // if (is_CADLayerchild_inrange(X3D_CADLAYER(me),p)) {
286 // update_renderFlagC(me,flag, setaction);
287 // }
288 // break;
289
290 default:
291 iret = update_renderFlagC(me, flag, setaction);
292 }
293 }
294 depth--;
295 } // referenceCount check
296 }
297 /* printf ("finished update_RenderFlag for %d\n",p); */
298 return iret;
299}
300void UPDATE_RENDERFLAG (struct X3D_Node *p, int flag, char *fi, int li){
301 if (p==NULL) {
302 ConsoleMessage ("update_renderFlag, p NULL from %s:%d\n",fi,li);
303 return;
304 }
305 //profile_start("update_rendrflg");
306 update_renderFlagB (p, flag, __LINE__);
307 //profile_end("update_rendrflg");
308 return;
309}
310