FreeWRL / FreeX3D 4.3.0
Bindable.c
1/*
2
3
4Bindable nodes - Background, TextureBackground, Fog, NavigationInfo, Viewpoint, GeoViewpoint.
5
6*/
7
8/****************************************************************************
9 This file is part of the FreeWRL/FreeX3D Distribution.
10
11 Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
12
13 FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
14 it under the terms of the GNU Lesser Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 FreeWRL/FreeX3D is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
25****************************************************************************/
26
27
28
29#include <config.h>
30#include <system.h>
31#include <display.h>
32#include <internal.h>
33
34#include <libFreeWRL.h>
35
36#include "../vrml_parser/Structs.h"
37#include "../main/headers.h"
38#include "../vrml_parser/CParseGeneral.h"
39#include "../scenegraph/Vector.h"
40#include "../vrml_parser/CFieldDecls.h"
41#include "../vrml_parser/CParseParser.h"
42#include "../vrml_parser/CParseLexer.h"
43#include "../vrml_parser/CRoutes.h"
44#include "../opengl/OpenGL_Utils.h"
45#include "Bindable.h"
46#include "../scenegraph/quaternion.h"
47#include "../scenegraph/Viewer.h"
48#include "../scenegraph/Component_Shape.h"
49#include "../scenegraph/Component_Geospatial.h"
50#include "../scenegraph/RenderFuncs.h"
51#include "../scenegraph/Component_ProgrammableShaders.h"
52#include "../ui/common.h"
53#include "../scenegraph/LinearAlgebra.h"
54
55void setup_projection();
56
57/* for Background spheres */
58struct MyVertex
59 {
60 struct SFVec3f vert; //Vertex
61 struct SFColorRGBA col; //Colour
62 };
63
64
65
66static void saveBGVert (float *colptr, float *pt, int *vertexno, float *col, double dist, double x, double y, double z) ;
67
68void init_bindablestack(bindablestack *bstack, int layerId, int nodetype){
69 bstack->background = newVector(struct X3D_Node*, 2);
70 bstack->viewpoint = newVector(struct X3D_Node*, 2);
71 bstack->fog = newVector(struct X3D_Node*, 2);
72 bstack->navigation = newVector(struct X3D_Node*, 2);
73 bstack->layerId = layerId;
74 loadIdentityMatrix(bstack->screenorientationmatrix);
75 loadIdentityMatrix(bstack->viewtransformmatrix);
76 loadIdentityMatrix(bstack->posorimatrix);
77 loadIdentityMatrix(bstack->stereooffsetmatrix[0]);
78 loadIdentityMatrix(bstack->stereooffsetmatrix[1]);
79 bstack->isStereo = 0;
80 bstack->iside = 0;
81 bstack->viewer = NULL; //X3D_Viewer - navigation is per-layer
82 bstack->nodetype = nodetype;
83 loadIdentityMatrix(bstack->pickraymatrix[0]);
84 loadIdentityMatrix(bstack->pickraymatrix[1]);
85}
86void free_bindablestack(bindablestack *bstack){
87 deleteVector(struct X3D_Node*, bstack->background);
88 deleteVector(struct X3D_Node*, bstack->viewpoint);
89 deleteVector(struct X3D_Node*, bstack->fog);
90 deleteVector(struct X3D_Node*, bstack->navigation);
91 FREE_IF_NZ(bstack->viewer);
92}
93typedef struct pBindable{
94 struct sNaviInfo naviinfo;
95 bindablestack bstack;
96}* ppBindable;
97void *Bindable_constructor(){
98 void *v = MALLOCV(sizeof(struct pBindable));
99 memset(v,0,sizeof(struct pBindable));
100 return v;
101}
102void Bindable_init(struct tBindable *t){
103 //public
104 //these are the binding stacks as descriped in Core Component in the specs which store just the bound bindables
105 //t->background_stack = newVector(struct X3D_Node*, 2);
106 //t->viewpoint_stack = newVector(struct X3D_Node*, 2);
107 //t->fog_stack = newVector(struct X3D_Node*, 2);
108 //t->navigation_stack = newVector(struct X3D_Node*, 2);
109
110 t->prv = Bindable_constructor();
111 t->activeLayer = 0;
112 t->bstacks = newVector(bindablestack*,4);
113 {
114 ppBindable p = (ppBindable)t->prv;
115 init_bindablestack(&p->bstack,0, NODE_Viewpoint); //default binding stacks layer=0
116 vector_pushBack(bindablestack*, t->bstacks, &p->bstack);
117 p->naviinfo.width = 0.25;
118 p->naviinfo.height = 1.6;
119 p->naviinfo.step = 0.75;
120 t->naviinfo = &p->naviinfo;
121 }
122
123}
124void Bindable_clear(struct tBindable *t){
125 int i;
126 //public
127 //deleteVector(struct X3D_Node*, t->background_stack);
128 //deleteVector(struct X3D_Node*, t->viewpoint_stack);
129 //deleteVector(struct X3D_Node*, t->fog_stack);
130 //deleteVector(struct X3D_Node*, t->navigation_stack);
131 for(i=0;i<vectorSize(t->bstacks);i++){
132 bindablestack* bstack = vector_get(bindablestack*,t->bstacks,i);
133 free_bindablestack(bstack);
134 if(i>0) FREE_IF_NZ(bstack); //the first bstack is &something_not_malloced
135 }
136 deleteVector(bindablestack*,t->bstacks);
137}
138bindablestack* getBindableStacksByLayer(ttglobal tg, int layerId )
139{
140 int i;
141 bindablestack* bstack, *bstacktmp;
142 bstack = NULL; // vector_get(bindablestack*,tg->Bindable.bstacks,0); //default
143 for(i=0;i<vectorSize(tg->Bindable.bstacks);i++){
144 bstacktmp = vector_get(bindablestack*,tg->Bindable.bstacks,i);
145 if(bstacktmp->layerId == layerId){
146 bstack = bstacktmp;
147 break;
148 }
149 }
150 return bstack;
151}
152int addBindableStack(ttglobal tg, bindablestack* bstack){
153 //returns index of added bindablestack
154 //layer and layoutlayer should call this once in their lifetime to add their stack
155 int layerId = bstack->layerId;
156 while(vectorSize(tg->Bindable.bstacks)<layerId+1)
157 vector_pushBack(bindablestack*,tg->Bindable.bstacks,NULL);
158 vector_set(bindablestack*,tg->Bindable.bstacks,layerId,bstack);
159 return layerId;
160}
161bindablestack* getActiveBindableStacks(ttglobal tg )
162{
163 return getBindableStacksByLayer(tg,tg->Bindable.activeLayer);
164}
165int getBindableStacksCount(ttglobal tg){
166 return vectorSize(tg->Bindable.bstacks);
167}
168void printStatsBindingStacks()
169{
170 int i,nstacks;
171 bindablestack* bstack;
172 ttglobal tg = gglobal();
173 nstacks = getBindableStacksCount(tg);
174 for(i=0;i<nstacks;i++){
175 bstack = getBindableStacksByLayer(tg,i);
176 if(0){
177 ConsoleMessage("Layer %d",i);
178 if(i == tg->Bindable.activeLayer)
179 ConsoleMessage(" activeLayer");
180 ConsoleMessage(":\n");
181 }else{
182 char* al = " ";
183 if(i == tg->Bindable.activeLayer)
184 al = " activeLayer";
185 ConsoleMessage("Layer %d%s:\n",i,al);
186 }
187 ConsoleMessage("%25s %d\n","Background stack count", vectorSize(bstack->background));
188 ConsoleMessage("%25s %d\n","Fog stack count", vectorSize(bstack->fog));
189 ConsoleMessage("%25s %d\n","Navigation stack count", vectorSize(bstack->navigation));
190 ConsoleMessage("%25s %d\n","Viewpoint stack count", vectorSize(bstack->viewpoint));
191 }
192}
193
194/* common entry routine for setting avatar size */
195void set_naviWidthHeightStep(double wid, double hei, double step) {
196 ppBindable p;
197 ttglobal tg = gglobal();
198 p = (ppBindable)tg->Bindable.prv;
199
200 p->naviinfo.width = wid;
201 p->naviinfo.height = hei;
202 p->naviinfo.step = step;
203
204 //printf ("set_naviWdithHeightStep - width %lf height %lf step %lf speed %lf\n",wid,hei,step,Viewer()->speed);
205
206}
207
208/* called when binding NavigationInfo nodes */
209void set_naviinfo(struct X3D_NavigationInfo *node) {
210 struct Uni_String **svptr;
211 int i;
212 char *typeptr;
213 X3D_Viewer *viewer = ViewerByLayerId(node->_layerId);
214
215 viewer->speed = (double) node->speed;
216 if (node->avatarSize.n < 2) {
217 //old cosmo one-number way? kuka scene has { avatarSize 180 }
218 //printf ("set_naviinfo, avatarSize smaller than expected\n");
219 if(node->avatarSize.n == 1){
220 //take it as height, and scale width and step by it
221 // web3d v3.3 default size: 0.25 1.6 0.75
222 double avScale = (double)(node->avatarSize.p[0])/1.6;
223 set_naviWidthHeightStep (.25*avScale,1.6*avScale,.75*avScale);
224 }
225 } else {
226 set_naviWidthHeightStep ((double)(node->avatarSize.p[0]),
227 (double)(node->avatarSize.p[1]),
228 (double)((node->avatarSize.p[2]))); //dug9 Jan 6, 2010 - this is too crazy for the new gravity. * node->speed) * 2));
229 }
230
231 /* keep track of valid Navigation types. */
232 svptr = node->type.p;
233
234 /* assume "NONE" is set */
235 for (i=0; i<18; i++) viewer->oktypes[i] = FALSE;
236
237
238 /* now, find the ones that are ok */
239 for (i = 0; i < node->type.n; i++) {
240 /* get the string pointer */
241 typeptr = svptr[i]->strptr;
242
243 if (strcmp(typeptr,"WALK") == 0) {
244 viewer->oktypes[VIEWER_WALK] = TRUE;
245 if (i==0) fwl_set_viewer_type0(viewer, VIEWER_WALK);
246 }
247 if (strcmp(typeptr,"FLY") == 0) {
248 viewer->oktypes[VIEWER_FLY] = TRUE;
249 if (i==0) fwl_set_viewer_type0(viewer, VIEWER_FLY);
250 }
251 if (strcmp(typeptr,"EXAMINE") == 0) {
252 viewer->oktypes[VIEWER_EXAMINE] = TRUE;
253 if (i==0) fwl_set_viewer_type0(viewer, VIEWER_EXAMINE);
254 }
255 if (strcmp(typeptr,"NONE") == 0) {
256 viewer->oktypes[VIEWER_NONE] = TRUE;
257 if (i==0) fwl_set_viewer_type0(viewer, VIEWER_NONE);
258 }
259 if (strcmp(typeptr,"EXFLY") == 0) {
260 viewer->oktypes[VIEWER_EXFLY] = TRUE;
261 if (i==0) fwl_set_viewer_type0(viewer, VIEWER_EXFLY);
262 }
263 if (strcmp(typeptr,"EXPLORE") == 0) {
264 viewer->oktypes[VIEWER_EXPLORE] = TRUE;
265 if (i==0) fwl_set_viewer_type0(viewer, VIEWER_EXPLORE);
266 }
267 if (strcmp(typeptr,"LOOKAT") == 0) {
268 viewer->oktypes[VIEWER_LOOKAT] = TRUE;
269 //if (i==0) fwl_set_viewer_type(VIEWER_LOOKAT);
270 }
271 if (strcmp(typeptr,"SPHERICAL") == 0) {
272 viewer->oktypes[VIEWER_SPHERICAL] = TRUE;
273 if (i==0) fwl_set_viewer_type0(viewer, VIEWER_SPHERICAL);
274 }
275 if (strcmp(typeptr, "TURNTABLE") == 0) {
276 viewer->oktypes[VIEWER_TURNTABLE] = TRUE;
277 if (i == 0) fwl_set_viewer_type0(viewer, VIEWER_TURNTABLE);
278 }
279 if (strcmp(typeptr, "DIST") == 0) {
280 viewer->oktypes[VIEWER_DIST] = TRUE;
281 if (i == 0) fwl_set_viewer_type0(viewer, VIEWER_DIST);
282 }
283
284 if (strcmp(typeptr, "ANY") == 0) {
285 viewer->oktypes[VIEWER_EXAMINE] = TRUE;
286 viewer->oktypes[VIEWER_WALK] = TRUE;
287 viewer->oktypes[VIEWER_EXFLY] = TRUE;
288 viewer->oktypes[VIEWER_FLY] = TRUE;
289 viewer->oktypes[VIEWER_EXPLORE] = TRUE;
290 viewer->oktypes[VIEWER_LOOKAT] = TRUE;
291 viewer->oktypes[VIEWER_SPHERICAL] = TRUE;
292 viewer->oktypes[VIEWER_TURNTABLE] = TRUE;
293 viewer->oktypes[VIEWER_DIST] = TRUE;
294 if (i==0) fwl_set_viewer_type0(viewer, VIEWER_WALK); /* just choose one */
295 }
296 }
297 viewer->headlight = node->headlight;
298 /* tell the menu buttons of the state of this headlight */
299 //setMenuButton_headlight(node->headlight);
300
301 /* transition effects */
302 viewer->transitionTime = node->transitionTime;
303 /* bounds checking */
304 if (viewer->transitionTime < 0.0) viewer->transitionTime = 0.0;
305
306 viewer->transitionType = VIEWER_TRANSITION_LINEAR; /* assume LINEAR */
307 if (node->transitionType.n > 0) {
308 if (strcmp("LINEAR", node->transitionType.p[0]->strptr) == 0) viewer->transitionType = VIEWER_TRANSITION_LINEAR;
309 else if (strcmp("TELEPORT", node->transitionType.p[0]->strptr) == 0) viewer->transitionType = VIEWER_TRANSITION_TELEPORT;
310 else if (strcmp("ANIMATE", node->transitionType.p[0]->strptr) == 0) viewer->transitionType = VIEWER_TRANSITION_ANIMATE;
311 else {
312 ConsoleMessage ("Unknown NavigationInfo transitionType :%s:",node->transitionType.p[0]->strptr);
313 }
314 }
315
316}
317
318
319int layerFromBindable(struct X3D_Node *node){
320 int layerId = 0;
321 switch(node->_nodeType){
322 case NODE_Viewpoint:
323 layerId = X3D_VIEWPOINT(node)->_layerId; break;
324 case NODE_OrthoViewpoint:
325 layerId = X3D_ORTHOVIEWPOINT(node)->_layerId; break;
326 case NODE_GeoViewpoint:
327 layerId = X3D_GEOVIEWPOINT(node)->_layerId; break;
328 case NODE_Background:
329 layerId = X3D_BACKGROUND(node)->_layerId; break;
330 case NODE_TextureBackground:
331 layerId = X3D_TEXTUREBACKGROUND(node)->_layerId; break;
332 case NODE_Fog:
333 layerId = X3D_FOG(node)->_layerId; break;
334 case NODE_NavigationInfo:
335 layerId = X3D_NAVIGATIONINFO(node)->_layerId; break;
336 default:
337 layerId = 0; break;
338 }
339 return layerId;
340}
341
342/* send a set_bind event from an event to this Bindable node */
343void send_bind_to(struct X3D_Node *node, int value) {
344 int layerId;
345 ttglobal tg = gglobal();
346 /* printf ("\n%lf: send_bind_to, nodetype %s node %u value %d\n",TickTime(),stringNodeType(node->_nodeType),node,value); */
347
348 layerId = layerFromBindable(node);
349 switch (node->_nodeType) {
350 case NODE_Background: {
351 struct X3D_Background *bg = (struct X3D_Background *) node;
352 bg->set_bind = value;
353 bind_node (node, getBindableStacksByLayer(tg,bg->_layerId)->background); //tg->Bindable.background_stack
354 break;
355 }
356
357 case NODE_TextureBackground: {
358 struct X3D_TextureBackground *tbg = (struct X3D_TextureBackground *) node;
359 tbg->set_bind = value;
360 bind_node (node, getBindableStacksByLayer(tg,tbg->_layerId)->background);
361 break;
362 }
363
364 case NODE_OrthoViewpoint: {
365 struct X3D_OrthoViewpoint *ovp = (struct X3D_OrthoViewpoint *) node;
366 ovp->set_bind = value;
367 setMenuStatusVP(ovp->description->strptr);
368 bind_node (node, getBindableStacksByLayer(tg,ovp->_layerId)->viewpoint);
369 if (value==1) {
370 bind_OrthoViewpoint (ovp);
371 }
372 break;
373 }
374
375 case NODE_Viewpoint: {
376 struct X3D_Viewpoint* vp = (struct X3D_Viewpoint *) node;
377 vp->set_bind = value;
378 setMenuStatusVP (vp->description->strptr);
379 bind_node (node, getBindableStacksByLayer(tg,vp->_layerId)->viewpoint);
380 if (value==1) {
381 bind_Viewpoint (vp);
382 }
383 break;
384 }
385
386 case NODE_GeoViewpoint: {
387 struct X3D_GeoViewpoint *gvp = (struct X3D_GeoViewpoint *) node;
388 gvp->set_bind = value;
389 setMenuStatusVP (gvp->description->strptr);
390 bind_node (node, getBindableStacksByLayer(tg,gvp->_layerId)->viewpoint);
391 if (value==1) {
392 bind_GeoViewpoint (gvp);
393 }
394 break;
395 }
396
397
398 case NODE_Fog: {
399 struct X3D_Fog *fg = (struct X3D_Fog *) node;
400 fg->set_bind = value;
401 bind_node (node, getBindableStacksByLayer(tg,fg->_layerId)->fog);
402 if(value==1){
403 bind_Fog(fg);
404 }
405 break;
406 }
407
408 case NODE_NavigationInfo: {
409 struct X3D_NavigationInfo *nv = (struct X3D_NavigationInfo *) node;
410 nv->set_bind = value;
411 bind_node (node, getBindableStacksByLayer(tg,nv->_layerId)->navigation);
412 if (value==1) set_naviinfo(nv);
413 break;
414 }
415
416 default:
417 ConsoleMessage("send_bind_to, cant send a set_bind to %s %p!!\n",stringNodeType(node->_nodeType),node);
418 }
419}
420
421
422
423
424/* Do binding for node and stack - works for all bindable nodes */
425
426/* return the setBind offset of this node */
427static size_t setBindofst(void *node) {
428 struct X3D_Background *tn;
429 tn = (struct X3D_Background *) node;
430 switch (tn->_nodeType) {
431 case NODE_Background: return offsetof(struct X3D_Background, set_bind);
432 case NODE_TextureBackground: return offsetof(struct X3D_TextureBackground, set_bind);
433 case NODE_Viewpoint: return offsetof(struct X3D_Viewpoint, set_bind);
434 case NODE_OrthoViewpoint: return offsetof(struct X3D_OrthoViewpoint, set_bind);
435 case NODE_GeoViewpoint: return offsetof(struct X3D_GeoViewpoint, set_bind);
436 case NODE_Fog: return offsetof(struct X3D_Fog, set_bind);
437 case NODE_NavigationInfo: return offsetof(struct X3D_NavigationInfo, set_bind);
438 default: {printf ("setBindoffst - huh? node type %d\n",tn->_nodeType); }
439 }
440 return 0;
441}
442
443/* return the isBound offset of this node */
444static size_t bindTimeoffst (struct X3D_Node *node) {
445 X3D_NODE_CHECK(node);
446
447 switch (node->_nodeType) {
448 case NODE_Background: return offsetof(struct X3D_Background, bindTime);
449 case NODE_TextureBackground: return offsetof(struct X3D_TextureBackground, bindTime);
450 case NODE_Viewpoint: return offsetof(struct X3D_Viewpoint, bindTime);
451 case NODE_OrthoViewpoint: return offsetof(struct X3D_OrthoViewpoint, bindTime);
452 case NODE_GeoViewpoint: return offsetof(struct X3D_GeoViewpoint, bindTime);
453 case NODE_Fog: return offsetof(struct X3D_Fog, bindTime);
454 case NODE_NavigationInfo: return offsetof(struct X3D_NavigationInfo, bindTime);
455 default: {printf ("bindTimeoffst - huh? node type %s\n",stringNodeType(node->_nodeType)); }
456 }
457 return 0;
458}
459
460/* return the isBound offset of this node */
461static size_t isboundofst(void *node) {
462 struct X3D_Background *tn;
463
464 /* initialization */
465 tn = (struct X3D_Background *) node;
466
467 X3D_NODE_CHECK(node);
468
469 switch (tn->_nodeType) {
470 case NODE_Background: return offsetof(struct X3D_Background, isBound);
471 case NODE_TextureBackground: return offsetof(struct X3D_TextureBackground, isBound);
472 case NODE_Viewpoint: return offsetof(struct X3D_Viewpoint, isBound);
473 case NODE_OrthoViewpoint: return offsetof(struct X3D_OrthoViewpoint, isBound);
474 case NODE_GeoViewpoint: return offsetof(struct X3D_GeoViewpoint, isBound);
475 case NODE_Fog: return offsetof(struct X3D_Fog, isBound);
476 case NODE_NavigationInfo: return offsetof(struct X3D_NavigationInfo, isBound);
477 default: {printf ("isBoundoffst - huh? node type %s\n",stringNodeType(tn->_nodeType)); }
478 }
479 return 0;
480}
481int removeNodeFromVector(int iaction, struct Vector *v, struct X3D_Node *node);
482void bind_node (struct X3D_Node *node, struct Vector *thisStack) {
483 int *isBoundPtr;
484 int *setBindPtr;
485 size_t offst;
486
487 isBoundPtr = offsetPointer_deref(int*, node, isboundofst(node));
488 setBindPtr = offsetPointer_deref(int*, node, setBindofst(node));
489
490 #ifdef BINDVERBOSE
491 printf ("bind_node, node %p (%s), set_bind %d isBound %d\n",node,stringNodeType(node->_nodeType),*setBindPtr,*isBoundPtr);
492 #endif
493
494 /* is this guy already bound? */
495 if (*isBoundPtr && (*setBindPtr != 0) ){
496 #ifdef BINDVERBOSE
497 printf("%p already bound\n",node);
498 #endif
499 *setBindPtr = 100;
500 return; /* It has to be at the top of the stack so return */
501 }
502
503
504 /* we either have a setBind of 1, which is a push, or 0, which
505 is a pop. the value of 100 (arbitrary) indicates that this
506 is not a new push or pop */
507
508 /* is this a push? */
509 if (*setBindPtr == 1) {
510 /* PUSH THIS TO THE TOP OF THE STACK */
511
512 /* isBound mimics setBind */
513 *isBoundPtr = 1;
514
515 /* unset the set_bind flag - setBind can be 0 or 1; lets make it garbage */
516 *setBindPtr = 100;
517
518 MARK_EVENT (node, (unsigned int) isboundofst(node));
519
520 /* set up the "bindTime" field */
521 offst = bindTimeoffst(node);
522 if (offst != 0) {
523 double *dp;
524 dp = offsetPointer_deref(double*, node, offst);
525 *dp = TickTime();
526 MARK_EVENT (node, offst);
527 }
528
529 /* unbind the one below, unless it is same node */
530 if (vectorSize(thisStack)>0) {
531 struct X3D_Node* oldTOS;
532
533 oldTOS = vector_back(struct X3D_Node *,thisStack);
534 /* printf ("already have a node here...have to unbind it %p %p\n",node,oldTOS); */
535
536 if (oldTOS == node) return; /* do not unbind */
537 isBoundPtr = offsetPointer_deref(int*, oldTOS, isboundofst(oldTOS));
538 setBindPtr = offsetPointer_deref(int*, oldTOS, setBindofst(oldTOS));
539 *isBoundPtr = 0;
540 *setBindPtr = 100;
541 MARK_EVENT (oldTOS, (unsigned int) isboundofst(oldTOS));
542 }
543
544 /* push it now */
545 vector_pushBack(struct X3D_Node*,thisStack,node);
546
547
548 } else if (*setBindPtr == 0) {
549 /* POP FROM TOP OF STACK - if we ARE the top of stack */
550 /* isBound mimics setBind */
551 *isBoundPtr = 0;
552
553 /* unset the set_bind flag - setBind can be 0 or 1; lets make it garbage */
554 *setBindPtr = 100;
555
556 MARK_EVENT (node, (unsigned int) isboundofst(node));
557
558 /* are we top of stack? */
559 if (vectorSize(thisStack)>0) {
560 struct X3D_Node* oldTOS;
561
562 oldTOS = vector_back(struct X3D_Node *,thisStack);
563 /* printf ("already have a node here...have to unbind it %p %p\n",node,oldTOS); */
564
565 if (oldTOS != node) {
566 if(!removeNodeFromVector(0, thisStack, node)){
567 if (node->_nodeType == NODE_Viewpoint){
568 if(0){
569 //bad scene design etiquette, but no harm done
570 printf ("can not pop from stack, not top (%p != %p)\n",node,oldTOS);
571 printf ("%p Viewpoint, description :%s:\n",node,X3D_VIEWPOINT(node)->description->strptr);
572 printf ("%p Viewpoint, description :%s:\n",oldTOS,X3D_VIEWPOINT(oldTOS)->description->strptr);
573 printf ("oldTOS, isBound %d, setBindPtr %d\n",*(offsetPointer_deref(int*, oldTOS, isboundofst(oldTOS))),
574 *(offsetPointer_deref(int*, oldTOS, setBindofst(oldTOS))));
575 printf("and not found in stack\n");
576 }
577 }
578 }
579 return;
580 } else {
581 /* we are top of stack... */
582 /* get myself off of the stack */
583 vector_popBack(struct X3D_Node *,thisStack);
584 removeNodeFromVector(0, thisStack, node); //sometimes there are duplicates further down the stack. for unloading inlines, we need to get rid of all occurrances
585 if (vectorSize(thisStack)>0) {
586 /* get the older one back */
587 oldTOS = vector_back(struct X3D_Node *,thisStack);
588
589 /* set it to be bound */
590 isBoundPtr = offsetPointer_deref(int*, oldTOS, isboundofst(oldTOS));
591 setBindPtr = offsetPointer_deref(int*, oldTOS, setBindofst(oldTOS));
592 *isBoundPtr = 1;
593 *setBindPtr = 100;
594 MARK_EVENT (oldTOS, (unsigned int) isboundofst(oldTOS));
595 }
596 }
597 } else {
598 /* printf ("stack is zero size, can not pop off\n"); */
599 }
600
601
602 } else {
603 printf ("setBindPtr %d\n",*setBindPtr);
604 }
605#undef BINDVERBOSE
606}
607
608//fog: see also notes in Component_EnvironEffects.c
609void bind_Fog(struct X3D_Fog *node){
610 //new Aug 2016, goal GLES2 compatible (no builtin opengl fog)
611 //nothing to do in here - we'll check the binding stack for fog before rendering
612 //ttglobal tg = gglobal();
613
614 /* check the set_bind eventin to see if it is TRUE or FALSE */
615 //if (node->set_bind < 100) {
616 // bind_node (X3D_NODE(node), getActiveBindableStacks(tg)->fog);
617
618 /* if we do not have any more nodes on top of stack, disable fog */
619 //if(vectorSize(getActiveBindableStacks(tg)->fog) <= 0)
620 // we'll check before general scengraph rendering glDisable(GL_FOG);
621 //}
622 //glEnable(GL_FOG);
623
624 //if(!node->isBound) return;
625 //if(node->isBound)
626 // printf("bound global fog\n");
627}
628
629void render_Fog_OLD (struct X3D_Fog *node) {
630 #ifndef GL_ES_VERSION_2_0 // this should be handled in material shader
631 GLDOUBLE mod[16];
632 GLDOUBLE proj[16];
633 GLDOUBLE x,y,z;
634 GLDOUBLE x1,y1,z1;
635 GLDOUBLE sx, sy, sz;
636 GLfloat fog_colour [4];
637 char *fogptr;
638 int foglen;
639 GLDOUBLE unit[16] = {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
640 ttglobal tg = gglobal();
641
642 UNUSED(foglen); //mitigate compiler warnings - should eventually use this variable though!
643
644 /* printf ("render_Fog, node %d isBound %d color %f %f %f set_bind %d\n",
645 node, node->isBound, node->color.c[0],node->color.c[1],node->color.c[2],node->set_bind); */
646
647 /* check the set_bind eventin to see if it is TRUE or FALSE */
648 if (node->set_bind < 100) {
649
650 bind_node (X3D_NODE(node), getActiveBindableStacks(tg)->fog);
651
652 /* if we do not have any more nodes on top of stack, disable fog */
653 glDisable(GL_FOG);
654 }
655
656 if(!node->isBound) return;
657 if (node->visibilityRange <= 0.00001) return;
658
659 fog_colour[0] = node->color.c[0];
660 fog_colour[1] = node->color.c[1];
661 fog_colour[2] = node->color.c[2];
662 fog_colour[3] = (float) 1.0;
663
664 fogptr = node->fogType->strptr;
665 foglen = node->fogType->len;
666 FW_GL_PUSH_MATRIX();
667 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, mod);
668 FW_GL_GETDOUBLEV(GL_PROJECTION_MATRIX, proj);
669 /* Get origin */
670 FW_GLU_UNPROJECT(0.0f,0.0f,0.0f,mod,proj,viewport,&x,&y,&z);
671 FW_GL_TRANSLATE_D(x,y,z);
672
673 FW_GLU_UNPROJECT(0.0f,0.0f,0.0f,mod,unit,viewport,&x,&y,&z);
674 /* Get scale */
675 FW_GLU_PROJECT(x+1,y,z,mod,unit,viewport,&x1,&y1,&z1);
676 sx = 1/sqrt( x1*x1 + y1*y1 + z1*z1*4 );
677 FW_GLU_PROJECT(x,y+1,z,mod,unit,viewport,&x1,&y1,&z1);
678 sy = 1/sqrt( x1*x1 + y1*y1 + z1*z1*4 );
679 FW_GLU_PROJECT(x,y,z+1,mod,unit,viewport,&x1,&y1,&z1);
680 sz = 1/sqrt( x1*x1 + y1*y1 + z1*z1*4 );
681 /* Undo the translation and scale effects */
682 FW_GL_SCALE_D(sx,sy,sz);
683
684
685 /* now do the foggy stuff */
686 FW_GL_FOGFV(GL_FOG_COLOR,fog_colour);
687
688 /* make the fog look like the examples in the VRML Source Book */
689 if (strcmp("LINEAR",fogptr)) {
690 /* Exponential */
691 FW_GL_FOGF(GL_FOG_DENSITY, (float) (4.0)/ (node->visibilityRange));
692 FW_GL_FOGF(GL_FOG_END, (float) (node->visibilityRange));
693 FW_GL_FOGI(GL_FOG_MODE, GL_EXP);
694 } else {
695 /* Linear */
696 FW_GL_FOGF(GL_FOG_START, (float) 1.0);
697 FW_GL_FOGF(GL_FOG_END, (float) (node->visibilityRange));
698 FW_GL_FOGI(GL_FOG_MODE, GL_LINEAR);
699 }
700 glEnable(GL_FOG);
701
702 FW_GL_POP_MATRIX();
703 #endif /* GL_ES_VERSION_2_0 this should be handled in material shader */
704}
705
706
707/******************************************************************************
708 *
709 * Background, TextureBackground stuff
710 *
711 ******************************************************************************/
712
713/* save a Background vertex into the __points and __colours arrays */
714static void saveBGVert (float *colptr, float *pt,
715 int *vertexno, float *col, double dist,
716 double x, double y, double z) {
717 /* save the colour */
718 memcpy (&colptr[*vertexno*3], col, sizeof(float)*3);
719
720 /* and, save the vertex info */
721 pt[*vertexno*3+0] = (float)(x*dist);
722 pt[*vertexno*3+1] = (float)(y*dist);
723 pt[*vertexno*3+2] = (float)(z*dist);
724
725 (*vertexno)++;
726}
727
728/* the background centre follows our position, so, move it! */
729static void moveBackgroundCentre () {
730 GLDOUBLE mod[16];
731 GLDOUBLE proj[16];
732 GLDOUBLE unit[16] = {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
733 GLDOUBLE x,y,z;
734 GLDOUBLE x1,y1,z1;
735 GLDOUBLE sx, sy, sz;
736 ttglobal tg = gglobal();
737
738 FW_GL_PUSH_MATRIX();
739 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, mod);
740 if(0){
741 FW_GL_GETDOUBLEV(GL_PROJECTION_MATRIX, proj);
742 /* Get origin */
743 FW_GLU_UNPROJECT(0.0f,0.0f,0.0f,mod,proj,viewport,&x,&y,&z);
744 FW_GL_TRANSLATE_D(x,y,z);
745
746 if(0){
747 if(0) LIGHTING_OFF
748
749 FW_GLU_UNPROJECT(0.0f,0.0f,0.0f,mod,unit,viewport,&x,&y,&z);
750 /* Get scale */
751 FW_GLU_PROJECT(x+1,y,z,mod,unit,viewport,&x1,&y1,&z1);
752 sx = 1/sqrt( x1*x1 + y1*y1 + z1*z1*4 );
753 FW_GLU_PROJECT(x,y+1,z,mod,unit,viewport,&x1,&y1,&z1);
754 sy = 1/sqrt( x1*x1 + y1*y1 + z1*z1*4 );
755 FW_GLU_PROJECT(x,y,z+1,mod,unit,viewport,&x1,&y1,&z1);
756 sz = 1/sqrt( x1*x1 + y1*y1 + z1*z1*4 );
757
758 /* Undo the translation and scale effects */
759 FW_GL_SCALE_D(sx,sy,sz);
760 //printf("moveBackground old T %f %f %f old S %f %f %f\n",x,y,z,sx,sy,sz);
761 }
762 }
763 if(1){
764 //feature-AFFINE_GLU_UNPROJECT
765 //translation, scale same as glu_unproject (no 4*z needed for this way)
766 double modi[16];
767 struct point_XYZ p, q;
768 p.x = p.y = p.z = 0.0;
769 matinverseAFFINE(modi,mod);
770 transform(&p,&p,modi);
771 FW_GL_TRANSLATE_D(p.x,p.y,p.z);
772 //printf("moveBackground new T %f %f %f \n",p.x,p.y,p.z);
773 //LIGHTING_OFF
774 if(1){ //jan 2018
775 /* Get scale */
776 q = p;
777 q.x += 1.0;
778 transform(&q,&q,mod);
779 sx = 1.0/sqrt( q.x*q.x + q.y*q.y + q.z*q.z );
780 q = p;
781 q.y += 1.0;
782 transform(&q,&q,mod);
783 sy = 1.0/sqrt( q.x*q.x + q.y*q.y + q.z*q.z );
784 q = p;
785 q.z += 1.0;
786 transform(&q,&q,mod);
787 sz = 1.0/sqrt( q.x*q.x + q.y*q.y + q.z*q.z );
788 }
789 /* Undo the translation and scale effects */
790 // dug9 jan 2018: if(0)
791 FW_GL_SCALE_D(sx,sy,sz);
792 //printf("moveBackground new T %f %f %f new S %f %f %f\n",x,y,z,sx,sy,sz);
793 //printf("\n");
794 }
795}
796
797static void recalculateBackgroundVectors(struct X3D_Background *node) {
798 struct SFColor *c1,*c2;
799 int hdiv; /* number of horizontal strips allowed */
800 int h,v;
801 double va1, va2, ha1, ha2; /* JS - vert and horiz angles */
802 int estq;
803 int actq;
804
805 /* filled in if this is a TextureBackground node */
806 struct X3D_TextureBackground *tbnode;
807
808 /* generic structures between nodes used for taking individual pointers from node defns */
809 struct SFColor *skyCol; int skyColCt;
810 struct SFColor *gndCol; int gndColCt;
811 float *skyAng; int skyAngCt;
812 float *gndAng; int gndAngCt;
813 float *newPoints; float *newColors;
814 double outsideRadius, insideRadius;
815
816 /* initialization */
817 tbnode = NULL;
818 hdiv = 20;
819
820 /* We draw spheres, one for the sky, one for the ground - outsideRadius and insideRadius */
821 //outsideRadius = DEFAULT_FARPLANE* 0.750;
822 //insideRadius = DEFAULT_FARPLANE * 0.50;
823
824 /* lets try these values - we will scale when we draw this */
825 outsideRadius = 1.001;// 1.0;
826 insideRadius = 1.0005; // 0.5;
827
828 /* handle Background and TextureBackgrounds here */
829 if (node->_nodeType == NODE_Background) {
830 skyCol = node->skyColor.p;
831 gndCol = node ->groundColor.p;
832 skyColCt = node->skyColor.n;
833 gndColCt = node->groundColor.n;
834 skyAng = node->skyAngle.p;
835 gndAng = node ->groundAngle.p;
836 skyAngCt = node->skyAngle.n;
837 gndAngCt = node->groundAngle.n;
838 } else {
839 tbnode = (struct X3D_TextureBackground *) node;
840 skyCol = tbnode->skyColor.p;
841 gndCol = tbnode ->groundColor.p;
842 skyColCt = tbnode->skyColor.n;
843 gndColCt = tbnode->groundColor.n;
844 skyAng = tbnode->skyAngle.p;
845 gndAng = tbnode ->groundAngle.p;
846 skyAngCt = tbnode->skyAngle.n;
847 gndAngCt = tbnode->groundAngle.n;
848 }
849
850 /* do we have NO background triangles? (ie, maybe all textures??) */
851 if ((skyColCt == 0) & (gndColCt == 0)) {
852 if (node->_nodeType == NODE_Background) {
853 MARK_NODE_COMPILED
854 /* do we have an old background to destroy? */
855 FREE_IF_NZ (node->__points.p);
856 FREE_IF_NZ (node->__colours.p);
857 node->__quadcount = 0;
858 } else {
859 tbnode->_ichange = tbnode->_change; /* mimic MARK_NODE_COMPILED */
860
861 /* do we have an old background to destroy? */
862 FREE_IF_NZ (tbnode->__points.p);
863 FREE_IF_NZ (tbnode->__colours.p);
864 tbnode->__quadcount = 0;
865 }
866 return;
867 }
868
869
870 /* calculate how many quads are required */
871 estq=0; actq=0;
872 if(skyColCt == 1) {
873 estq += 40;
874 } else {
875 estq += (skyColCt-1) * 20 + 20;
876 /* attempt to find exact estimate, fails if no skyAngle, so
877 simply changed above line to add 20 automatically.
878 if ((skyColCt >2) &&
879 (skyAngCt > skyColCt-2)) {
880 if (skyAng[skyColCt-2] < (PI-0.01))
881 estq += 20;
882 }
883 */
884 }
885
886 if(gndColCt == 1) estq += 40;
887 else if (gndColCt>0) estq += (gndColCt-1) * 20;
888
889 /* now, MALLOC space for new arrays - 3 points per vertex, 6 per quad. */
890 newPoints = MALLOC (GLfloat *, sizeof (GLfloat) * estq * 3 * 6);
891 newColors = MALLOC (GLfloat *, sizeof (GLfloat) * estq * 3 * 6);
892
893
894 if(skyColCt == 1) {
895 c1 = &skyCol[0];
896 va1 = 0;
897 va2 = PI/2;
898
899 for(v=0; v < 2; v++) {
900 for(h=0; h<hdiv; h++) {
901 ha1 = h * PI*2 / hdiv;
902 ha2 = (h+1) * PI*2 / hdiv;
903 /* 0 */ saveBGVert (newColors, newPoints, &actq,&c1->c[0],outsideRadius, sin(va2)*cos(ha1), cos(va2), sin(va2)*sin(ha1));
904 /* 1 */ saveBGVert (newColors, newPoints, &actq,&c1->c[0],outsideRadius, sin(va2)*cos(ha2), cos(va2), sin(va2)*sin(ha2));
905 /* 2 */ saveBGVert (newColors, newPoints, &actq,&c1->c[0],outsideRadius, sin(va1)*cos(ha2), cos(va1), sin(va1)*sin(ha2));
906 /* 0 */ saveBGVert (newColors, newPoints, &actq,&c1->c[0],outsideRadius, sin(va2)*cos(ha1), cos(va2), sin(va2)*sin(ha1));
907 /* 2 */ saveBGVert (newColors, newPoints, &actq,&c1->c[0],outsideRadius, sin(va1)*cos(ha2), cos(va1), sin(va1)*sin(ha2));
908 /* 3 */ saveBGVert (newColors, newPoints, &actq,&c1->c[0],outsideRadius, sin(va1)*cos(ha1), cos(va1), sin(va1) * sin(ha1));
909 }
910 va1 = va2;
911 va2 = PI;
912 }
913 } else {
914 va1 = 0;
915 /* this gets around a compiler warning - we really DO want last values of this from following
916 for loop */
917 c1 = &skyCol[0];
918 if (skyAngCt>0) {
919 va2= skyAng[0];
920 } else {
921 va2 = PI/2;
922 }
923 c2=c1;
924
925
926 for(v=0; v<(skyColCt-1); v++) {
927 c1 = &skyCol[v];
928 c2 = &skyCol[v+1];
929 if (skyAngCt>0) { va2 = skyAng[v];}
930 else { va2 = PI/2; }
931
932 for(h=0; h<hdiv; h++) {
933 ha1 = h * PI*2 / hdiv;
934 ha2 = (h+1) * PI*2 / hdiv;
935 /* 0 */ saveBGVert(newColors,newPoints, &actq,&c2->c[0],outsideRadius, sin(va2)*cos(ha1), cos(va2), sin(va2) * sin(ha1));
936 /* 1 */ saveBGVert(newColors,newPoints, &actq,&c2->c[0],outsideRadius, sin(va2)*cos(ha2), cos(va2), sin(va2) * sin(ha2));
937 /* 2 */ saveBGVert(newColors,newPoints, &actq,&c1->c[0],outsideRadius, sin(va1)*cos(ha2), cos(va1), sin(va1) * sin(ha2));
938 /* 0 */ saveBGVert(newColors,newPoints, &actq,&c2->c[0],outsideRadius, sin(va2)*cos(ha1), cos(va2), sin(va2) * sin(ha1));
939 /* 2 */ saveBGVert(newColors,newPoints, &actq,&c1->c[0],outsideRadius, sin(va1)*cos(ha2), cos(va1), sin(va1) * sin(ha2));
940 /* 3 */ saveBGVert(newColors,newPoints, &actq,&c1->c[0],outsideRadius, sin(va1) * cos(ha1), cos(va1), sin(va1) * sin(ha1));
941 }
942 va1 = va2;
943 }
944
945 /* now, the spec states: "If the last skyAngle is less than pi, then the
946 colour band between the last skyAngle and the nadir is clamped to the last skyColor." */
947 if (va2 < (PI-0.01)) {
948 for(h=0; h<hdiv; h++) {
949 ha1 = h * PI*2 / hdiv;
950 ha2 = (h+1) * PI*2 / hdiv;
951 /* 0 */ saveBGVert(newColors,newPoints,&actq,&c2->c[0],outsideRadius, sin(PI) * cos(ha1), cos(PI), sin(PI) * sin(ha1));
952 /* 1 */ saveBGVert(newColors,newPoints,&actq,&c2->c[0],outsideRadius, sin(PI) * cos(ha2), cos(PI), sin(PI) * sin(ha2));
953 /* 2 */ saveBGVert(newColors,newPoints,&actq,&c2->c[0],outsideRadius, sin(va2) * cos(ha2), cos(va2), sin(va2) * sin(ha2));
954 /* 0 */ saveBGVert(newColors,newPoints,&actq,&c2->c[0],outsideRadius, sin(PI) * cos(ha1), cos(PI), sin(PI) * sin(ha1));
955 /* 2 */ saveBGVert(newColors,newPoints,&actq,&c2->c[0],outsideRadius, sin(va2) * cos(ha2), cos(va2), sin(va2) * sin(ha2));
956 /* 3 */ saveBGVert(newColors,newPoints,&actq,&c2->c[0],outsideRadius, sin(va2) * cos(ha1), cos(va2), sin(va2) * sin(ha1));
957 }
958 }
959 }
960
961 /* Do the ground, if there is anything to do. */
962
963 if (gndColCt>0) {
964 if(gndColCt == 1) {
965 c1 = &gndCol[0];
966 for(h=0; h<hdiv; h++) {
967 ha1 = h * PI*2 / hdiv;
968 ha2 = (h+1) * PI*2 / hdiv;
969
970 /* 0 */ saveBGVert(newColors,newPoints,&actq,&c1->c[0],insideRadius, sin(PI) * cos(ha1), cos(PI), sin(PI) * sin(ha1));
971 /* 1 */ saveBGVert(newColors,newPoints,&actq,&c1->c[0],insideRadius, sin(PI) * cos(ha2), cos(PI), sin(PI) * sin(ha2));
972 /* 2 */ saveBGVert(newColors,newPoints,&actq,&c1->c[0],insideRadius, sin(PI/2) * cos(ha2), cos(PI/2), sin(PI/2) * sin(ha2));
973 /* 0 */ saveBGVert(newColors,newPoints,&actq,&c1->c[0],insideRadius, sin(PI) * cos(ha1), cos(PI), sin(PI) * sin(ha1));
974 /* 2 */ saveBGVert(newColors,newPoints,&actq,&c1->c[0],insideRadius, sin(PI/2) * cos(ha2), cos(PI/2), sin(PI/2) * sin(ha2));
975 /* 3 */ saveBGVert(newColors,newPoints,&actq,&c1->c[0],insideRadius, sin(PI/2) * cos(ha1), cos(PI/2), sin(PI/2) * sin(ha1));
976 }
977 } else {
978 va1 = PI;
979 for(v=0; v<gndColCt-1; v++) {
980 c1 = &gndCol[v];
981 c2 = &gndCol[v+1];
982 if (v>=gndAngCt) va2 = PI; /* bounds check */
983 else va2 = PI - gndAng[v];
984
985 for(h=0; h<hdiv; h++) {
986 ha1 = h * PI*2 / hdiv;
987 ha2 = (h+1) * PI*2 / hdiv;
988
989 /* 0 */ saveBGVert(newColors,newPoints,&actq,&c1->c[0],insideRadius, sin(va1)*cos(ha1), cos(va1), sin(va1)*sin(ha1));
990 /* 1 */ saveBGVert(newColors,newPoints,&actq,&c1->c[0],insideRadius, sin(va1)*cos(ha2), cos(va1), sin(va1)*sin(ha2));
991 /* 2 */ saveBGVert(newColors,newPoints,&actq,&c2->c[0],insideRadius, sin(va2)*cos(ha2), cos(va2), sin(va2)*sin(ha2));
992 /* 0 */ saveBGVert(newColors,newPoints,&actq,&c1->c[0],insideRadius, sin(va1)*cos(ha1), cos(va1), sin(va1)*sin(ha1));
993 /* 2 */ saveBGVert(newColors,newPoints,&actq,&c2->c[0],insideRadius, sin(va2)*cos(ha2), cos(va2), sin(va2)*sin(ha2));
994 /* 3 */ saveBGVert(newColors,newPoints,&actq,&c2->c[0],insideRadius, sin(va2) * cos(ha1), cos(va2), sin(va2)*sin(ha1));
995 }
996 va1 = va2;
997 }
998 }
999 }
1000
1001 /* We have guessed at the quad count; lets make sure
1002 * we record what we have. */
1003 if (actq > (estq*6)) {
1004 printf ("Background quadcount error, %d > %d\n",
1005 actq,estq);
1006 actq = 0;
1007 }
1008
1009 /* save changes */
1010 /* if we are doing shaders, we write the vertex and color info to a VBO, else we keep pointers in the node */
1011 if (node->_nodeType == NODE_Background) {
1012
1013 MARK_NODE_COMPILED
1014
1015 /* do we have an old background to destroy? */
1016 FREE_IF_NZ (node->__points.p);
1017 FREE_IF_NZ (node->__colours.p);
1018 node->__quadcount = actq;
1019 } else {
1020 tbnode->_ichange = tbnode->_change; /* mimic MARK_NODE_COMPILED */
1021 /* do we have an old background to destroy? */
1022 FREE_IF_NZ (tbnode->__points.p);
1023 FREE_IF_NZ (tbnode->__colours.p);
1024 tbnode->__quadcount = actq;
1025
1026 }
1027
1028
1029 {
1030 struct MyVertex *combinedBuffer = MALLOC(struct MyVertex *, sizeof (struct MyVertex) * actq * 2);
1031 int i;
1032 float *npp = newPoints;
1033 float *ncp = newColors;
1034
1035
1036 if (node->_nodeType == NODE_Background) {
1037 if (node->__VBO == 0) glGenBuffers(1,(unsigned int*) &node->__VBO);
1038 } else {
1039 if (tbnode->__VBO == 0) glGenBuffers(1,(unsigned int*) &tbnode->__VBO);
1040 }
1041
1042 /* stream both the vertex and colours together (could have done this above, but
1043 maybe can redo this if we go 100% material shaders */
1044
1045 /* NOTE - we use SFColorRGBA - and set the Alpha to 1 so that we can use the
1046 shader with other nodes with Color fields */
1047
1048 for (i=0; i<actq; i++) {
1049 combinedBuffer[i].vert.c[0] = *npp; npp++;
1050 combinedBuffer[i].vert.c[1] = *npp; npp++;
1051 combinedBuffer[i].vert.c[2] = *npp; npp++;
1052 combinedBuffer[i].col.c[0] = *ncp; ncp++;
1053 combinedBuffer[i].col.c[1] = *ncp; ncp++;
1054 combinedBuffer[i].col.c[2] = *ncp; ncp++;
1055 combinedBuffer[i].col.c[3] = 1.0f;
1056 }
1057 FREE_IF_NZ(newPoints);
1058 FREE_IF_NZ(newColors);
1059
1060 /* send this data along ... */
1061 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER,node->__VBO);
1062 glBufferData(GL_ARRAY_BUFFER, sizeof (struct MyVertex)*actq, combinedBuffer, GL_STATIC_DRAW);
1063
1064 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER,0);
1065
1066 /* and, we can free it */
1067 FREE_IF_NZ(combinedBuffer);
1068 //node->__combined = X3D_NODE(combinedBuffer);
1069 }
1070}
1071void reallyDraw();
1072void render_Background(struct X3D_Background *node){
1073 if (renderstate()->render_blend) return;
1074 if(!node->isBound) return;
1075 {
1076 //we need the model matrix - between root node and background - to capture any scene authored background tilts
1077 double viewi[16], mat[16];
1078 bindablestack *bstack;
1079 ttglobal tg = gglobal();
1080
1081 bstack = getActiveBindableStacks(tg);
1082 matinverseAFFINE(viewi,bstack->viewmatrix);
1083 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX,mat);
1084 //matmultiplyAFFINE(bstack->backgroundmatrix,viewi,mat);
1085 matmultiplyAFFINE(bstack->backgroundmatrix,mat,viewi);
1086 }
1087
1088}
1089void render_TextureBackground(struct X3D_TextureBackground *node){
1090 if (renderstate()->render_blend) return;
1091 if(!node->isBound) return;
1092 {
1093 //we need the model matrix - between root node and background - to capture any scene authored background tilts
1094 double viewi[16], mat[16];
1095 bindablestack *bstack;
1096 ttglobal tg = gglobal();
1097
1098 bstack = getActiveBindableStacks(tg);
1099 matinverseAFFINE(viewi,bstack->viewmatrix);
1100 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX,mat);
1101 //matmultiplyAFFINE(bstack->backgroundmatrix,viewi,mat);
1102 matmultiplyAFFINE(bstack->backgroundmatrix,mat,viewi);
1103 }
1104}
1105void render_Background_OLD (struct X3D_Background *node) {
1106 ttglobal tg = gglobal();
1107
1108 X3D_Viewer *viewer = Viewer();
1109 /* if we are rendering blended nodes, don't bother with this one */
1110 if (renderstate()->render_blend) return;
1111
1112 /* printf ("RBG, num %d node %d ib %d sb %d gepvp\n",node->__BGNumber, node,node->isBound,node->set_bind); */
1113 /* check the set_bind eventin to see if it is TRUE or FALSE */
1114 if (node->set_bind < 100) {
1115 bind_node (X3D_NODE(node), getActiveBindableStacks(tg)->background);
1116 }
1117
1118 /* don't even bother going further if this node is not bound on the top */
1119 if(!node->isBound) return;
1120
1121 if (vectorSize(getActiveBindableStacks(tg)->fog) >0) glDisable(GL_FOG);
1122
1123 /* Cannot start_list() because of moving center, so we do our own list later */
1124 moveBackgroundCentre();
1125
1126 if (NODE_NEEDS_COMPILING) {
1127 recalculateBackgroundVectors(node);
1128 }
1129
1130 /* we have a sphere (maybe one and a half, as the sky and ground are different) so scale it up so that
1131 all geometry fits within the spheres
1132 dug9 Sept 2014: background could in theory be a tiny box or sphere that wraps around the avatar, if
1133 you can draw it first on each frame _and_ turn off 'depth' when you draw it.
1134 dug9 Jan 2018: turned off scaling of background geom, and toggled depth test)
1135 - due to problems with float coordinate rounding when doing a geoSpatial scene
1136 - (with GC geocentric) coords at rootnode when using geoViewpoint
1137 - still problem with geo-horizon leveling of background (for near-ground)
1138 */
1139 //if(0) FW_GL_SCALE_D (viewer->backgroundPlane, viewer->backgroundPlane, viewer->backgroundPlane);
1140 glDisable(GL_DEPTH_TEST);
1141 enableGlobalShader(getMyShader(COLOUR_MATERIAL_SHADER));
1142 LIGHTING_OFF
1143
1144 FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER, 0);
1145 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, node->__VBO);
1146 #define BUFFER_OFFSET(i) ((char *)NULL + (i))
1147 FW_GL_VERTEX_POINTER(3, GL_FLOAT, (GLsizei) sizeof(struct MyVertex), (GLfloat *)BUFFER_OFFSET(0)); //The starting point of the VBO, for the vertices
1148 FW_GL_COLOR_POINTER(4, GL_FLOAT, (GLsizei) sizeof(struct MyVertex), (GLfloat *)BUFFER_OFFSET(sizeof(struct SFVec3f))); //The starting point of Colours, 12 bytes away
1149
1150 if(setupShaderB()){
1151 sendArraysToGPU (GL_TRIANGLES, 0, node->__quadcount);
1152 reallyDraw();
1153 }
1154 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, 0);
1155 FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER, 0);
1156 finishedWithGlobalShader();
1157
1158 /* now, for the textures, if they exist */
1159 if (((node->backUrl).n>0) ||
1160 ((node->frontUrl).n>0) ||
1161 ((node->leftUrl).n>0) ||
1162 ((node->rightUrl).n>0) ||
1163 ((node->topUrl).n>0) ||
1164 ((node->bottomUrl).n>0)) {
1165
1166 glEnable(GL_TEXTURE_2D);
1167
1168 FW_GL_VERTEX_POINTER (3,GL_FLOAT,0,BackgroundVert);
1169 FW_GL_NORMAL_POINTER (GL_FLOAT,0,Backnorms);
1170 FW_GL_TEXCOORD_POINTER (2,GL_FLOAT,0,boxtex,0);
1171
1172 enableGlobalShader(getMyShader(ONE_TEX_APPEARANCE_SHADER));
1173
1174
1175 loadBackgroundTextures(node);
1176
1177 finishedWithGlobalShader();
1178 }
1179 glEnable(GL_DEPTH_TEST);
1180
1181 FW_GL_POP_MATRIX();
1182
1183 /* is fog enabled? if so, disable it right now */
1184 if (vectorSize(getActiveBindableStacks(tg)->fog) >0) glEnable(GL_FOG);
1185}
1186//void prep_Background (struct X3D_Background *node) {
1187// ttglobal tg = gglobal();
1188//
1189// /* if we are rendering blended nodes, don't bother with this one */
1190// if (!renderstate()->render_background) return;
1191//
1192// /* printf ("RBG, num %d node %d ib %d sb %d gepvp\n",node->__BGNumber, node,node->isBound,node->set_bind); */
1193// /* check the set_bind eventin to see if it is TRUE or FALSE */
1194// if (node->set_bind < 100) {
1195// bind_node (X3D_NODE(node), getActiveBindableStacks(tg)->background);
1196// }
1197//}
1198void fw_gluPerspective_2(GLDOUBLE xcenter, GLDOUBLE fovy, GLDOUBLE aspect, GLDOUBLE zNear, GLDOUBLE zFar);
1199void fw_depth_slice_push(double nearplane, double farplane){
1200 //lets say you have a big scene -maybe a planet and a few moons to scale,
1201 //and avatar on the surface of a moon, planting a flag and looking up at the main planet
1202 //And lets say your 24bit depth buffer seems a bit strained.
1203 //one idea is to iterate from far to near, over depth slices.
1204 //start with the farthest slices, slices can 'touch' but not overlap
1205 //then you could have your usual .1 to 21000 for human-size things close by,
1206 // and 21000 to infinity for distant mountains, planets etc.
1207 // and backgrounds could be rendered in .1 to 10 range
1208 // - enough to cover sphere radius 1 or box size 2 -
1209 // - with depth testing off, before anything else
1210 // haven't tried it in render() but I think you would do this:
1211 // render_background
1212 // for(i=0;i<dept_slices;i++){
1213 // fw_depth_slice_push(nearp[i],farp[i]);
1214 // glClear(GL_DEPTH)
1215 // render_hier() - theres a few of these
1216 // fw_depth_slice_pop();
1217 // }
1218 // would that work?
1219 double save_nearPlane, save_farPlane;
1220 X3D_Viewer *viewer = Viewer();
1221
1222 FW_GL_MATRIX_MODE(GL_PROJECTION);
1223 FW_GL_PUSH_MATRIX();
1224
1225 save_nearPlane = viewer->nearPlane;
1226 save_farPlane = viewer->farPlane;
1227 viewer->nearPlane = nearplane;
1228 viewer->farPlane = farplane;
1229 setup_projection(); //will put back in modelview mode
1230 viewer->nearPlane = save_nearPlane;
1231 viewer->farPlane = save_farPlane;
1232}
1233void fw_depth_slice_pop(){
1234 FW_GL_MATRIX_MODE(GL_PROJECTION);
1235 FW_GL_POP_MATRIX();
1236 FW_GL_MATRIX_MODE(GL_MODELVIEW);
1237}
1238
1239void render_prepped_Background(struct X3D_Background *node){
1240 double bgscale;
1241 int didPerspective;
1242 ttglobal tg = gglobal();
1243 X3D_Viewer *viewer = Viewer();
1244
1245 if (vectorSize(getActiveBindableStacks(tg)->fog) >0) glDisable(GL_FOG);
1246
1247 /* Cannot start_list() because of moving center, so we do our own list later */
1248
1249 if(0){
1250 //this ignors tilts and yaws (but with respect to what? bound viewpoint?)
1251 moveBackgroundCentre();
1252 }else if(1){
1253 //March 2018 - this re-allows scene-file authored tilts to the background like other browsers
1254 // <Transform> <Background> </Transform> - tilts captured in render_Background
1255 // which we broke a few months ago
1256 double pp[3], mvmat[16], mvinv[16];
1257 bindablestack *bstack;
1258 ttglobal tg = gglobal();
1259 bstack = getActiveBindableStacks(tg);
1260 FW_GL_MATRIX_MODE(GL_MODELVIEW);
1261 FW_GL_PUSH_MATRIX();
1262 FW_GL_TRANSFORM_D(bstack->backgroundmatrix); //see (new) render_Background
1263 //we now need to cancel/undo the translation part
1264 // by moving the background back to where the vp is at 0,0,0
1265 // see also:
1266 // double * matrixAFFINE2RotationMatrix(double* rotmat, double *fullmat);
1267 // which I made from this code, but didn't have time to try here.
1268 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, mvmat);
1269 matinverseAFFINE(mvinv,mvmat);
1270 vecsetd(pp,0.0,0.0,0.0);
1271 transformAFFINEd(pp,pp,mvinv);
1272 FW_GL_TRANSLATE_D(pp[0],pp[1],pp[2]);
1273 if(1){
1274 //cancel/undo scale part, so that our background mesh stays at radius 1.0
1275 double sx,sy,sz, q[3],p[3],d[3];
1276 /* Get scale */
1277 vecsetd(p,0.0,0.0,0.0);
1278 transformAFFINEd(p,p,mvmat);
1279 vecsetd(q,1.0,0.0,0.0);
1280 transformAFFINEd(q,q,mvmat);
1281 sx = 1.0/veclengthd(vecdifd(d,q,p));
1282 vecsetd(q,0.0,1.0,0.0);
1283 transformAFFINEd(q,q,mvmat);
1284 sy = 1.0/veclengthd(vecdifd(d,q,p));
1285 vecsetd(q,0.0,0.0,1.0);
1286 transformAFFINEd(q,q,mvmat);
1287 sz = 1.0/veclengthd(vecdifd(d,q,p));
1288 /* Undo the scale effects */
1289 FW_GL_SCALE_D(sx,sy,sz);
1290 }
1291 }else if(0){
1292 //instead of transforming back to viewpoint, can we just replace transform top-of-stack with identity?
1293 //benefit: good for diagnosing background problems: near/far plane vs offset
1294 //problem: then the horizon (or orientation with texture background)- doesn't change with a tilt (or yaw)
1295 FW_GL_MATRIX_MODE(GL_MODELVIEW);
1296 FW_GL_PUSH_MATRIX();
1297 FW_GL_LOAD_IDENTITY();
1298 if(1){
1299 //this adds vertical tilt but not horizontal yaw
1300 double matA2BVVA[16],matBVVA2A[16];
1301 avatar2BoundViewpointVerticalAvatar(matA2BVVA,matBVVA2A);
1302 fw_glSetDoublev(GL_MODELVIEW_MATRIX,matBVVA2A);
1303 }
1304 }
1305
1306 if (NODE_NEEDS_COMPILING) {
1307 recalculateBackgroundVectors(node);
1308 }
1309
1310 /* we have a sphere (maybe one and a half, as the sky and ground are different) so scale it up so that
1311 all geometry fits within the spheres
1312 dug9 Sept 2014: background could in theory be a tiny box or sphere that wraps around the avatar, if
1313 you can draw it first on each frame _and_ turn off 'depth' when you draw it.
1314 dug9 Jan 2018: turned off scaling of background geom, and toggled depth test)
1315 - due to problems with float coordinate rounding when doing a geoSpatial scene
1316 - (with GC geocentric) coords at rootnode when using geoViewpoint
1317 - still problem with geo-horizon leveling of background (for near-ground)
1318 */
1319 didPerspective = FALSE;
1320
1321 if(0){
1322 //we need to scale because somewhere else we set up a perspective transformation that
1323 //may have a big number for a nearPlane (ie with geo scenes stretching depth range)
1324 //and the perspective transforms our z's into gl's 0 to 1 range for depth
1325 //if(1) FW_GL_SCALE_D (viewer->backgroundPlane, viewer->backgroundPlane, viewer->backgroundPlane);
1326 bgscale = 1.0;
1327 //if( viewer->nearPlane >= bgscale*.5)
1328 bgscale = viewer->nearPlane + (viewer->farPlane - viewer->nearPlane)*.3;
1329 //printf("near %lf far %lf bgscale %lf\n",viewer->nearPlane,viewer->farPlane,bgscale);
1330 FW_GL_SCALE_D (bgscale, bgscale, bgscale);
1331 }else{
1332 //alternately we can replace the perspective transform, or scale the depth range
1333 GLclampd znear, zfar;
1334 fw_depth_slice_push(.1,100); //SEEMS TO WORK remember to pop
1335 didPerspective = TRUE;
1336 }
1337 glDisable(GL_DEPTH_TEST);
1338 glDepthMask(GL_FALSE);
1339 enableGlobalShader(getMyShader(COLOUR_MATERIAL_SHADER));
1340 LIGHTING_OFF
1341
1342 FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER, 0);
1343 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, node->__VBO);
1344 #define BUFFER_OFFSET(i) ((char *)NULL + (i))
1345 FW_GL_VERTEX_POINTER(3, GL_FLOAT, (GLsizei) sizeof(struct MyVertex), (GLfloat *)BUFFER_OFFSET(0)); //The starting point of the VBO, for the vertices
1346 FW_GL_COLOR_POINTER(4, GL_FLOAT, (GLsizei) sizeof(struct MyVertex), (GLfloat *)BUFFER_OFFSET(sizeof(struct SFVec3f))); //The starting point of Colours, 12 bytes away
1347
1348 if(setupShaderB()){
1349 sendArraysToGPU (GL_TRIANGLES, 0, node->__quadcount);
1350 reallyDraw();
1351 }
1352 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, 0);
1353 FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER, 0);
1354 finishedWithGlobalShader();
1355
1356 /* now, for the textures, if they exist */
1357 if (((node->backUrl).n>0) ||
1358 ((node->frontUrl).n>0) ||
1359 ((node->leftUrl).n>0) ||
1360 ((node->rightUrl).n>0) ||
1361 ((node->topUrl).n>0) ||
1362 ((node->bottomUrl).n>0)) {
1363 glEnable(GL_TEXTURE_2D);
1364
1365 FW_GL_VERTEX_POINTER (3,GL_FLOAT,0,BackgroundVert);
1366 FW_GL_NORMAL_POINTER (GL_FLOAT,0,Backnorms);
1367 FW_GL_TEXCOORD_POINTER (2,GL_FLOAT,0,boxtex,0);
1368
1369 enableGlobalShader(getMyShader(ONE_TEX_APPEARANCE_SHADER));
1370
1371
1372 loadBackgroundTextures(node);
1373 finishedWithGlobalShader();
1374 }
1375 glDepthMask(GL_TRUE);
1376 glEnable(GL_DEPTH_TEST);
1377 if(didPerspective){
1378 fw_depth_slice_pop();
1379 }
1380
1381 FW_GL_POP_MATRIX();
1382
1383 /* is fog enabled? if so, disable it right now */
1384 if (vectorSize(getActiveBindableStacks(tg)->fog) >0) glEnable(GL_FOG);
1385}
1386
1387
1388void render_TextureBackground_OLD (struct X3D_TextureBackground *node) {
1389 ttglobal tg = gglobal();
1390
1391 X3D_Viewer *viewer = Viewer();
1392 /* if we are rendering blended nodes, don't bother with this one */
1393 if (renderstate()->render_blend) return;
1394
1395
1396 /* printf ("RTBG, node %d ib %d sb %d gepvp\n",node,node->isBound,node->set_bind); */
1397 /* check the set_bind eventin to see if it is TRUE or FALSE */
1398 if (node->set_bind < 100) {
1399 bind_node (X3D_NODE(node), getActiveBindableStacks(tg)->background);
1400 }
1401
1402 /* don't even bother going further if this node is not bound on the top */
1403 if(!node->isBound) return;
1404
1405 /* is fog enabled? if so, disable it right now */
1406 if (vectorSize(getActiveBindableStacks(tg)->fog) >0) glDisable(GL_FOG);
1407
1408 /* Cannot start_list() because of moving center, so we do our own list later */
1409 moveBackgroundCentre();
1410
1411 if NODE_NEEDS_COMPILING
1412 /* recalculateBackgroundVectors will determine exact node type */
1413 recalculateBackgroundVectors((struct X3D_Background *)node);
1414
1415 /* we have a sphere (maybe one and a half, as the sky and ground are different) so scale it up so that
1416 all geometry fits within the spheres */
1417 //FW_GL_SCALE_D (viewer->backgroundPlane, viewer->backgroundPlane, viewer->backgroundPlane);
1418 glDisable(GL_DEPTH_TEST);
1419
1420 enableGlobalShader(getMyShader(COLOUR_MATERIAL_SHADER));
1421
1422 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, node->__VBO);
1423 //FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER, 0);
1424
1425 #define BUFFER_OFFSET(i) ((char *)NULL + (i))
1426 FW_GL_VERTEX_POINTER(3, GL_FLOAT, sizeof(struct MyVertex), (GLfloat *)BUFFER_OFFSET(0)); //The starting point of the VBO, for the vertices
1427 FW_GL_COLOR_POINTER(4, GL_FLOAT, sizeof(struct MyVertex), (GLfloat *)BUFFER_OFFSET(sizeof(struct SFVec3f))); //The starting point of Colours, 12 bytes away
1428
1429 sendArraysToGPU (GL_TRIANGLES, 0, node->__quadcount);
1430 reallyDraw();
1431 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, 0);
1432 FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER, 0);
1433 finishedWithGlobalShader();
1434
1435 /* now, for the textures, if they exist */
1436 if ((node->backTexture !=0) ||
1437 (node->frontTexture !=0) ||
1438 (node->leftTexture !=0) ||
1439 (node->rightTexture !=0) ||
1440 (node->topTexture !=0) ||
1441 (node->bottomTexture !=0)) {
1442
1443
1444 enableGlobalShader(getMyShader(ONE_TEX_APPEARANCE_SHADER));
1445
1446
1447
1448 loadTextureBackgroundTextures(node);
1449
1450 finishedWithGlobalShader();
1451
1452 }
1453 glEnable(GL_DEPTH_TEST);
1454
1455 /* pushes are done in moveBackgroundCentre */
1456 FW_GL_POP_MATRIX();
1457
1458 if (vectorSize(getActiveBindableStacks(tg)->fog) >0) glEnable (GL_FOG);
1459}
1460
1461//void prep_TextureBackground (struct X3D_TextureBackground *node) {
1462// ttglobal tg = gglobal();
1463//
1464// X3D_Viewer *viewer = Viewer();
1465// /* if we are rendering blended nodes, don't bother with this one */
1466// if (renderstate()->render_blend) return;
1467//
1468//
1469// /* printf ("RTBG, node %d ib %d sb %d gepvp\n",node,node->isBound,node->set_bind); */
1470// /* check the set_bind eventin to see if it is TRUE or FALSE */
1471// if (node->set_bind < 100) {
1472// bind_node (X3D_NODE(node), getActiveBindableStacks(tg)->background);
1473// }
1474//}
1475void render_prepped_TextureBackground(struct X3D_TextureBackground *node) {
1476 double bgscale;
1477 int didPerspective;
1478 X3D_Viewer *viewer = Viewer();
1479 ttglobal tg = gglobal();
1480
1481 /* is fog enabled? if so, disable it right now */
1482 if (vectorSize(getActiveBindableStacks(tg)->fog) >0) glDisable(GL_FOG);
1483
1484 /* Cannot start_list() because of moving center, so we do our own list later */
1485 if(0){
1486 moveBackgroundCentre();
1487 }else if(1){
1488 //March 2018 - this re-allows scene-file authored tilts to the background like other browsers
1489 // <Transform> <Background> </Transform> - tilts captured in render_Background
1490 // which we broke a few months ago
1491 double pp[3], mvmat[16], mvinv[16];
1492 bindablestack *bstack;
1493 ttglobal tg = gglobal();
1494 bstack = getActiveBindableStacks(tg);
1495 FW_GL_MATRIX_MODE(GL_MODELVIEW);
1496 FW_GL_PUSH_MATRIX();
1497 FW_GL_TRANSFORM_D(bstack->backgroundmatrix); //see (new) render_Background
1498 //we now need to cancel/undo the translation part
1499 // by moving the background back to where the vp is at 0,0,0
1500 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, mvmat);
1501 matinverseAFFINE(mvinv,mvmat);
1502 vecsetd(pp,0.0,0.0,0.0);
1503 transformAFFINEd(pp,pp,mvinv);
1504 FW_GL_TRANSLATE_D(pp[0],pp[1],pp[2]);
1505 if(1){
1506 //cancel/undo scale part, so that our background mesh stays at diameter 1.0
1507 double sx,sy,sz, q[3],p[3],d[3];
1508 /* Get scale */
1509 vecsetd(p,0.0,0.0,0.0);
1510 transformAFFINEd(p,p,mvmat);
1511 vecsetd(q,1.0,0.0,0.0);
1512 transformAFFINEd(q,q,mvmat);
1513 sx = 1.0/veclengthd(vecdifd(d,q,p));
1514 vecsetd(q,0.0,1.0,0.0);
1515 transformAFFINEd(q,q,mvmat);
1516 sy = 1.0/veclengthd(vecdifd(d,q,p));
1517 vecsetd(q,0.0,0.0,1.0);
1518 transformAFFINEd(q,q,mvmat);
1519 sz = 1.0/veclengthd(vecdifd(d,q,p));
1520 /* Undo the scale effects */
1521 FW_GL_SCALE_D(sx,sy,sz);
1522 }
1523 }
1524
1525
1526 if NODE_NEEDS_COMPILING
1527 /* recalculateBackgroundVectors will determine exact node type */
1528 recalculateBackgroundVectors((struct X3D_Background *)node);
1529
1530 /* we have a sphere (maybe one and a half, as the sky and ground are different) so scale it up so that
1531 all geometry fits within the spheres */
1532 //FW_GL_SCALE_D (viewer->backgroundPlane, viewer->backgroundPlane, viewer->backgroundPlane);
1533 didPerspective = FALSE;
1534
1535 if(0){
1536 bgscale = 1.0;
1537 if( viewer->nearPlane > bgscale) bgscale = viewer->nearPlane;
1538 FW_GL_SCALE_D (bgscale, bgscale, bgscale);
1539 }else{
1540 //alternately we can replace the perspective transform, or scale the depth range
1541 GLclampd znear, zfar;
1542 fw_depth_slice_push(.1,100); //SEEMS TO WORK remember to pop
1543 didPerspective = TRUE;
1544 }
1545
1546 glDisable(GL_DEPTH_TEST);
1547
1548 enableGlobalShader(getMyShader(COLOUR_MATERIAL_SHADER));
1549
1550 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, node->__VBO);
1551 //FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER, 0);
1552
1553 #define BUFFER_OFFSET(i) ((char *)NULL + (i))
1554 FW_GL_VERTEX_POINTER(3, GL_FLOAT, sizeof(struct MyVertex), (GLfloat *)BUFFER_OFFSET(0)); //The starting point of the VBO, for the vertices
1555 FW_GL_COLOR_POINTER(4, GL_FLOAT, sizeof(struct MyVertex), (GLfloat *)BUFFER_OFFSET(sizeof(struct SFVec3f))); //The starting point of Colours, 12 bytes away
1556
1557 sendArraysToGPU (GL_TRIANGLES, 0, node->__quadcount);
1558 reallyDraw();
1559 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, 0);
1560 FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER, 0);
1561 finishedWithGlobalShader();
1562
1563 /* now, for the textures, if they exist */
1564 if ((node->backTexture !=0) ||
1565 (node->frontTexture !=0) ||
1566 (node->leftTexture !=0) ||
1567 (node->rightTexture !=0) ||
1568 (node->topTexture !=0) ||
1569 (node->bottomTexture !=0)) {
1570
1571
1572 enableGlobalShader(getMyShader(ONE_TEX_APPEARANCE_SHADER));
1573
1574 loadTextureBackgroundTextures(node);
1575
1576 finishedWithGlobalShader();
1577
1578 }
1579 glEnable(GL_DEPTH_TEST);
1580 if(didPerspective){
1581 fw_depth_slice_pop();
1582 }
1583
1584 /* pushes are done in moveBackgroundCentre */
1585 FW_GL_POP_MATRIX();
1586
1587 if (vectorSize(getActiveBindableStacks(tg)->fog) >0) glEnable (GL_FOG);
1588}
1589
1590void render_bound_background(){
1591 //Jan 2018 changed to render bound Background first, before other nodes,
1592 // - so can turn off gl depth and don't need to scale it up - can be unit sphere, unit cube
1593
1594 ttglobal tg = gglobal();
1595 if (vectorSize(getActiveBindableStacks(tg)->background) >0){
1596 struct X3D_Node * node = vector_back(struct X3D_Node *,getActiveBindableStacks(tg)->background);
1597 switch(node->_nodeType){
1598 case NODE_Background:
1599 render_prepped_Background((struct X3D_Background*)node);
1600 break;
1601 case NODE_TextureBackground:
1602 render_prepped_TextureBackground((struct X3D_TextureBackground*)node);
1603 break;
1604 default: break;
1605 }
1606 }
1607}