FreeWRL/FreeX3D  3.0.0
Bindable.c
1 /*
2 
3 
4 Bindable 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 
55 /* for Background spheres */
56 struct MyVertex
57  {
58  struct SFVec3f vert; //Vertex
59  struct SFColorRGBA col; //Colour
60  };
61 
62 
63 
64 static void saveBGVert (float *colptr, float *pt, int *vertexno, float *col, double dist, double x, double y, double z) ;
65 
66 void init_bindablestack(bindablestack *bstack, int layerId, int nodetype){
67  bstack->background = newVector(struct X3D_Node*, 2);
68  bstack->viewpoint = newVector(struct X3D_Node*, 2);
69  bstack->fog = newVector(struct X3D_Node*, 2);
70  bstack->navigation = newVector(struct X3D_Node*, 2);
71  bstack->layerId = layerId;
72  loadIdentityMatrix(bstack->screenorientationmatrix);
73  loadIdentityMatrix(bstack->viewtransformmatrix);
74  loadIdentityMatrix(bstack->posorimatrix);
75  loadIdentityMatrix(bstack->stereooffsetmatrix[0]);
76  loadIdentityMatrix(bstack->stereooffsetmatrix[1]);
77  bstack->isStereo = 0;
78  bstack->iside = 0;
79  bstack->viewer = NULL; //X3D_Viewer - navigation is per-layer
80  bstack->nodetype = nodetype;
81  loadIdentityMatrix(bstack->pickraymatrix[0]);
82  loadIdentityMatrix(bstack->pickraymatrix[1]);
83 }
84 void free_bindablestack(bindablestack *bstack){
85  deleteVector(struct X3D_Node*, bstack->background);
86  deleteVector(struct X3D_Node*, bstack->viewpoint);
87  deleteVector(struct X3D_Node*, bstack->fog);
88  deleteVector(struct X3D_Node*, bstack->navigation);
89  FREE_IF_NZ(bstack->viewer);
90 }
91 typedef struct pBindable{
92  struct sNaviInfo naviinfo;
93  bindablestack bstack;
94 }* ppBindable;
95 void *Bindable_constructor(){
96  void *v = MALLOCV(sizeof(struct pBindable));
97  memset(v,0,sizeof(struct pBindable));
98  return v;
99 }
100 void Bindable_init(struct tBindable *t){
101  //public
102  //these are the binding stacks as descriped in Core Component in the specs which store just the bound bindables
103  //t->background_stack = newVector(struct X3D_Node*, 2);
104  //t->viewpoint_stack = newVector(struct X3D_Node*, 2);
105  //t->fog_stack = newVector(struct X3D_Node*, 2);
106  //t->navigation_stack = newVector(struct X3D_Node*, 2);
107 
108  t->prv = Bindable_constructor();
109  t->activeLayer = 0;
110  t->bstacks = newVector(bindablestack*,4);
111  {
112  ppBindable p = (ppBindable)t->prv;
113  init_bindablestack(&p->bstack,0, NODE_Viewpoint); //default binding stacks layer=0
114  vector_pushBack(bindablestack*, t->bstacks, &p->bstack);
115  p->naviinfo.width = 0.25;
116  p->naviinfo.height = 1.6;
117  p->naviinfo.step = 0.75;
118  t->naviinfo = &p->naviinfo;
119  }
120 
121 }
122 void Bindable_clear(struct tBindable *t){
123  int i;
124  //public
125  //deleteVector(struct X3D_Node*, t->background_stack);
126  //deleteVector(struct X3D_Node*, t->viewpoint_stack);
127  //deleteVector(struct X3D_Node*, t->fog_stack);
128  //deleteVector(struct X3D_Node*, t->navigation_stack);
129  for(i=0;i<vectorSize(t->bstacks);i++){
130  bindablestack* bstack = vector_get(bindablestack*,t->bstacks,i);
131  free_bindablestack(bstack);
132  if(i>0) FREE_IF_NZ(bstack); //the first bstack is &something_not_malloced
133  }
134  deleteVector(bindablestack*,t->bstacks);
135 }
136 bindablestack* getBindableStacksByLayer(ttglobal tg, int layerId )
137 {
138  int i;
139  bindablestack* bstack, *bstacktmp;
140  bstack = NULL; // vector_get(bindablestack*,tg->Bindable.bstacks,0); //default
141  for(i=0;i<vectorSize(tg->Bindable.bstacks);i++){
142  bstacktmp = vector_get(bindablestack*,tg->Bindable.bstacks,i);
143  if(bstacktmp->layerId == layerId){
144  bstack = bstacktmp;
145  break;
146  }
147  }
148  return bstack;
149 }
150 int addBindableStack(ttglobal tg, bindablestack* bstack){
151  //returns index of added bindablestack
152  //layer and layoutlayer should call this once in their lifetime to add their stack
153  int layerId = bstack->layerId;
154  while(vectorSize(tg->Bindable.bstacks)<layerId+1)
155  vector_pushBack(bindablestack*,tg->Bindable.bstacks,NULL);
156  vector_set(bindablestack*,tg->Bindable.bstacks,layerId,bstack);
157  return layerId;
158 }
159 bindablestack* getActiveBindableStacks(ttglobal tg )
160 {
161  return getBindableStacksByLayer(tg,tg->Bindable.activeLayer);
162 }
163 int getBindableStacksCount(ttglobal tg){
164  return vectorSize(tg->Bindable.bstacks);
165 }
166 void printStatsBindingStacks()
167 {
168  int i,nstacks;
169  bindablestack* bstack;
170  ttglobal tg = gglobal();
171  nstacks = getBindableStacksCount(tg);
172  for(i=0;i<nstacks;i++){
173  bstack = getBindableStacksByLayer(tg,i);
174  if(0){
175  ConsoleMessage("Layer %d",i);
176  if(i == tg->Bindable.activeLayer)
177  ConsoleMessage(" activeLayer");
178  ConsoleMessage(":\n");
179  }else{
180  char* al = " ";
181  if(i == tg->Bindable.activeLayer)
182  al = " activeLayer";
183  ConsoleMessage("Layer %d%s:\n",i,al);
184  }
185  ConsoleMessage("%25s %d\n","Background stack count", vectorSize(bstack->background));
186  ConsoleMessage("%25s %d\n","Fog stack count", vectorSize(bstack->fog));
187  ConsoleMessage("%25s %d\n","Navigation stack count", vectorSize(bstack->navigation));
188  ConsoleMessage("%25s %d\n","Viewpoint stack count", vectorSize(bstack->viewpoint));
189  }
190 }
191 
192 /* common entry routine for setting avatar size */
193 void set_naviWidthHeightStep(double wid, double hei, double step) {
194  ppBindable p;
195  ttglobal tg = gglobal();
196  p = (ppBindable)tg->Bindable.prv;
197 
198  p->naviinfo.width = wid;
199  p->naviinfo.height = hei;
200  p->naviinfo.step = step;
201 
202  /* printf ("set_naviWdithHeightStep - width %lf height %lf step %lf speed %lf\n",wid,hei,step,Viewer.speed); */
203 
204 }
205 
206 /* called when binding NavigationInfo nodes */
207 void set_naviinfo(struct X3D_NavigationInfo *node) {
208  struct Uni_String **svptr;
209  int i;
210  char *typeptr;
211  X3D_Viewer *viewer = ViewerByLayerId(node->_layerId);
212 
213  viewer->speed = (double) node->speed;
214  if (node->avatarSize.n<2) {
215  printf ("set_naviinfo, avatarSize smaller than expected\n");
216  } else {
217  set_naviWidthHeightStep ((double)(node->avatarSize.p[0]),
218  (double)(node->avatarSize.p[1]),
219  (double)((node->avatarSize.p[2]))); //dug9 Jan 6, 2010 - this is too crazy for the new gravity. * node->speed) * 2));
220  }
221 
222  /* keep track of valid Navigation types. */
223  svptr = node->type.p;
224 
225  /* assume "NONE" is set */
226  for (i=0; i<18; i++) viewer->oktypes[i] = FALSE;
227 
228 
229  /* now, find the ones that are ok */
230  for (i = 0; i < node->type.n; i++) {
231  /* get the string pointer */
232  typeptr = svptr[i]->strptr;
233 
234  if (strcmp(typeptr,"WALK") == 0) {
235  viewer->oktypes[VIEWER_WALK] = TRUE;
236  if (i==0) fwl_set_viewer_type0(viewer, VIEWER_WALK);
237  }
238  if (strcmp(typeptr,"FLY") == 0) {
239  viewer->oktypes[VIEWER_FLY] = TRUE;
240  if (i==0) fwl_set_viewer_type0(viewer, VIEWER_FLY);
241  }
242  if (strcmp(typeptr,"EXAMINE") == 0) {
243  viewer->oktypes[VIEWER_EXAMINE] = TRUE;
244  if (i==0) fwl_set_viewer_type0(viewer, VIEWER_EXAMINE);
245  }
246  if (strcmp(typeptr,"NONE") == 0) {
247  viewer->oktypes[VIEWER_NONE] = TRUE;
248  if (i==0) fwl_set_viewer_type0(viewer, VIEWER_NONE);
249  }
250  if (strcmp(typeptr,"EXFLY") == 0) {
251  viewer->oktypes[VIEWER_EXFLY] = TRUE;
252  if (i==0) fwl_set_viewer_type0(viewer, VIEWER_EXFLY);
253  }
254  if (strcmp(typeptr,"EXPLORE") == 0) {
255  viewer->oktypes[VIEWER_EXPLORE] = TRUE;
256  if (i==0) fwl_set_viewer_type0(viewer, VIEWER_EXPLORE);
257  }
258  if (strcmp(typeptr,"LOOKAT") == 0) {
259  viewer->oktypes[VIEWER_LOOKAT] = TRUE;
260  //if (i==0) fwl_set_viewer_type(VIEWER_LOOKAT);
261  }
262  if (strcmp(typeptr,"SPHERICAL") == 0) {
263  viewer->oktypes[VIEWER_SPHERICAL] = TRUE;
264  if (i==0) fwl_set_viewer_type0(viewer, VIEWER_SPHERICAL);
265  }
266  if (strcmp(typeptr, "TURNTABLE") == 0) {
267  viewer->oktypes[VIEWER_TURNTABLE] = TRUE;
268  if (i == 0) fwl_set_viewer_type0(viewer, VIEWER_TURNTABLE);
269  }
270  if (strcmp(typeptr, "DIST") == 0) {
271  viewer->oktypes[VIEWER_DIST] = TRUE;
272  if (i == 0) fwl_set_viewer_type0(viewer, VIEWER_DIST);
273  }
274 
275  if (strcmp(typeptr, "ANY") == 0) {
276  viewer->oktypes[VIEWER_EXAMINE] = TRUE;
277  viewer->oktypes[VIEWER_WALK] = TRUE;
278  viewer->oktypes[VIEWER_EXFLY] = TRUE;
279  viewer->oktypes[VIEWER_FLY] = TRUE;
280  viewer->oktypes[VIEWER_EXPLORE] = TRUE;
281  viewer->oktypes[VIEWER_LOOKAT] = TRUE;
282  viewer->oktypes[VIEWER_SPHERICAL] = TRUE;
283  viewer->oktypes[VIEWER_TURNTABLE] = TRUE;
284  viewer->oktypes[VIEWER_DIST] = TRUE;
285  if (i==0) fwl_set_viewer_type0(viewer, VIEWER_WALK); /* just choose one */
286  }
287  }
288  viewer->headlight = node->headlight;
289  /* tell the menu buttons of the state of this headlight */
290  //setMenuButton_headlight(node->headlight);
291 
292  /* transition effects */
293  viewer->transitionTime = node->transitionTime;
294  /* bounds checking */
295  if (viewer->transitionTime < 0.0) viewer->transitionTime = 0.0;
296 
297  viewer->transitionType = VIEWER_TRANSITION_LINEAR; /* assume LINEAR */
298  if (node->transitionType.n > 0) {
299  if (strcmp("LINEAR", node->transitionType.p[0]->strptr) == 0) viewer->transitionType = VIEWER_TRANSITION_LINEAR;
300  else if (strcmp("TELEPORT", node->transitionType.p[0]->strptr) == 0) viewer->transitionType = VIEWER_TRANSITION_TELEPORT;
301  else if (strcmp("ANIMATE", node->transitionType.p[0]->strptr) == 0) viewer->transitionType = VIEWER_TRANSITION_ANIMATE;
302  else {
303  ConsoleMessage ("Unknown NavigationInfo transitionType :%s:",node->transitionType.p[0]->strptr);
304  }
305  }
306 
307 }
308 
309 
310 int layerFromBindable(struct X3D_Node *node){
311  int layerId = 0;
312  switch(node->_nodeType){
313  case NODE_Viewpoint:
314  layerId = X3D_VIEWPOINT(node)->_layerId; break;
315  case NODE_OrthoViewpoint:
316  layerId = X3D_ORTHOVIEWPOINT(node)->_layerId; break;
317  case NODE_GeoViewpoint:
318  layerId = X3D_GEOVIEWPOINT(node)->_layerId; break;
319  case NODE_Background:
320  layerId = X3D_BACKGROUND(node)->_layerId; break;
321  case NODE_TextureBackground:
322  layerId = X3D_TEXTUREBACKGROUND(node)->_layerId; break;
323  case NODE_Fog:
324  layerId = X3D_FOG(node)->_layerId; break;
325  case NODE_NavigationInfo:
326  layerId = X3D_NAVIGATIONINFO(node)->_layerId; break;
327  default:
328  layerId = 0; break;
329  }
330  return layerId;
331 }
332 
333 /* send a set_bind event from an event to this Bindable node */
334 void send_bind_to(struct X3D_Node *node, int value) {
335  int layerId;
336  ttglobal tg = gglobal();
337  /* printf ("\n%lf: send_bind_to, nodetype %s node %u value %d\n",TickTime(),stringNodeType(node->_nodeType),node,value); */
338 
339  layerId = layerFromBindable(node);
340  switch (node->_nodeType) {
341  case NODE_Background: {
342  struct X3D_Background *bg = (struct X3D_Background *) node;
343  bg->set_bind = value;
344  bind_node (node, getBindableStacksByLayer(tg,bg->_layerId)->background); //tg->Bindable.background_stack
345  break;
346  }
347 
348  case NODE_TextureBackground: {
349  struct X3D_TextureBackground *tbg = (struct X3D_TextureBackground *) node;
350  tbg->set_bind = value;
351  bind_node (node, getBindableStacksByLayer(tg,tbg->_layerId)->background);
352  break;
353  }
354 
355  case NODE_OrthoViewpoint: {
356  struct X3D_OrthoViewpoint *ovp = (struct X3D_OrthoViewpoint *) node;
357  ovp->set_bind = value;
358  setMenuStatusVP(ovp->description->strptr);
359  bind_node (node, getBindableStacksByLayer(tg,ovp->_layerId)->viewpoint);
360  if (value==1) {
361  bind_OrthoViewpoint (ovp);
362  }
363  break;
364  }
365 
366  case NODE_Viewpoint: {
367  struct X3D_Viewpoint* vp = (struct X3D_Viewpoint *) node;
368  vp->set_bind = value;
369  setMenuStatusVP (vp->description->strptr);
370  bind_node (node, getBindableStacksByLayer(tg,vp->_layerId)->viewpoint);
371  if (value==1) {
372  bind_Viewpoint (vp);
373  }
374  break;
375  }
376 
377  case NODE_GeoViewpoint: {
378  struct X3D_GeoViewpoint *gvp = (struct X3D_GeoViewpoint *) node;
379  gvp->set_bind = value;
380  setMenuStatusVP (gvp->description->strptr);
381  bind_node (node, getBindableStacksByLayer(tg,gvp->_layerId)->viewpoint);
382  if (value==1) {
383  bind_GeoViewpoint (gvp);
384  }
385  break;
386  }
387 
388 
389  case NODE_Fog: {
390  struct X3D_Fog *fg = (struct X3D_Fog *) node;
391  fg->set_bind = value;
392  bind_node (node, getBindableStacksByLayer(tg,fg->_layerId)->fog);
393  if(value==1){
394  bind_Fog(fg);
395  }
396  break;
397  }
398 
399  case NODE_NavigationInfo: {
400  struct X3D_NavigationInfo *nv = (struct X3D_NavigationInfo *) node;
401  nv->set_bind = value;
402  bind_node (node, getBindableStacksByLayer(tg,nv->_layerId)->navigation);
403  if (value==1) set_naviinfo(nv);
404  break;
405  }
406 
407  default:
408  ConsoleMessage("send_bind_to, cant send a set_bind to %s %p!!\n",stringNodeType(node->_nodeType),node);
409  }
410 }
411 
412 
413 
414 
415 /* Do binding for node and stack - works for all bindable nodes */
416 
417 /* return the setBind offset of this node */
418 static size_t setBindofst(void *node) {
419  struct X3D_Background *tn;
420  tn = (struct X3D_Background *) node;
421  switch (tn->_nodeType) {
422  case NODE_Background: return offsetof(struct X3D_Background, set_bind);
423  case NODE_TextureBackground: return offsetof(struct X3D_TextureBackground, set_bind);
424  case NODE_Viewpoint: return offsetof(struct X3D_Viewpoint, set_bind);
425  case NODE_OrthoViewpoint: return offsetof(struct X3D_OrthoViewpoint, set_bind);
426  case NODE_GeoViewpoint: return offsetof(struct X3D_GeoViewpoint, set_bind);
427  case NODE_Fog: return offsetof(struct X3D_Fog, set_bind);
428  case NODE_NavigationInfo: return offsetof(struct X3D_NavigationInfo, set_bind);
429  default: {printf ("setBindoffst - huh? node type %d\n",tn->_nodeType); }
430  }
431  return 0;
432 }
433 
434 /* return the isBound offset of this node */
435 static size_t bindTimeoffst (struct X3D_Node *node) {
436  X3D_NODE_CHECK(node);
437 
438  switch (node->_nodeType) {
439  case NODE_Background: return offsetof(struct X3D_Background, bindTime);
440  case NODE_TextureBackground: return offsetof(struct X3D_TextureBackground, bindTime);
441  case NODE_Viewpoint: return offsetof(struct X3D_Viewpoint, bindTime);
442  case NODE_OrthoViewpoint: return offsetof(struct X3D_OrthoViewpoint, bindTime);
443  case NODE_GeoViewpoint: return offsetof(struct X3D_GeoViewpoint, bindTime);
444  case NODE_Fog: return offsetof(struct X3D_Fog, bindTime);
445  case NODE_NavigationInfo: return offsetof(struct X3D_NavigationInfo, bindTime);
446  default: {printf ("bindTimeoffst - huh? node type %s\n",stringNodeType(node->_nodeType)); }
447  }
448  return 0;
449 }
450 
451 /* return the isBound offset of this node */
452 static size_t isboundofst(void *node) {
453  struct X3D_Background *tn;
454 
455  /* initialization */
456  tn = (struct X3D_Background *) node;
457 
458  X3D_NODE_CHECK(node);
459 
460  switch (tn->_nodeType) {
461  case NODE_Background: return offsetof(struct X3D_Background, isBound);
462  case NODE_TextureBackground: return offsetof(struct X3D_TextureBackground, isBound);
463  case NODE_Viewpoint: return offsetof(struct X3D_Viewpoint, isBound);
464  case NODE_OrthoViewpoint: return offsetof(struct X3D_OrthoViewpoint, isBound);
465  case NODE_GeoViewpoint: return offsetof(struct X3D_GeoViewpoint, isBound);
466  case NODE_Fog: return offsetof(struct X3D_Fog, isBound);
467  case NODE_NavigationInfo: return offsetof(struct X3D_NavigationInfo, isBound);
468  default: {printf ("isBoundoffst - huh? node type %s\n",stringNodeType(tn->_nodeType)); }
469  }
470  return 0;
471 }
472 int removeNodeFromVector(int iaction, struct Vector *v, struct X3D_Node *node);
473 void bind_node (struct X3D_Node *node, struct Vector *thisStack) {
474  int *isBoundPtr;
475  int *setBindPtr;
476  size_t offst;
477 
478  isBoundPtr = offsetPointer_deref(int*, node, isboundofst(node));
479  setBindPtr = offsetPointer_deref(int*, node, setBindofst(node));
480 
481  #ifdef BINDVERBOSE
482  printf ("bind_node, node %p (%s), set_bind %d isBound %d\n",node,stringNodeType(node->_nodeType),*setBindPtr,*isBoundPtr);
483  #endif
484 
485  /* is this guy already bound? */
486  if (*isBoundPtr && (*setBindPtr != 0) ){
487  #ifdef BINDVERBOSE
488  printf("%p already bound\n",node);
489  #endif
490  *setBindPtr = 100;
491  return; /* It has to be at the top of the stack so return */
492  }
493 
494 
495  /* we either have a setBind of 1, which is a push, or 0, which
496  is a pop. the value of 100 (arbitrary) indicates that this
497  is not a new push or pop */
498 
499  /* is this a push? */
500  if (*setBindPtr == 1) {
501  /* PUSH THIS TO THE TOP OF THE STACK */
502 
503  /* isBound mimics setBind */
504  *isBoundPtr = 1;
505 
506  /* unset the set_bind flag - setBind can be 0 or 1; lets make it garbage */
507  *setBindPtr = 100;
508 
509  MARK_EVENT (node, (unsigned int) isboundofst(node));
510 
511  /* set up the "bindTime" field */
512  offst = bindTimeoffst(node);
513  if (offst != 0) {
514  double *dp;
515  dp = offsetPointer_deref(double*, node, offst);
516  *dp = TickTime();
517  MARK_EVENT (node, offst);
518  }
519 
520  /* unbind the one below, unless it is same node */
521  if (vectorSize(thisStack)>0) {
522  struct X3D_Node* oldTOS;
523 
524  oldTOS = vector_back(struct X3D_Node *,thisStack);
525  /* printf ("already have a node here...have to unbind it %p %p\n",node,oldTOS); */
526 
527  if (oldTOS == node) return; /* do not unbind */
528  isBoundPtr = offsetPointer_deref(int*, oldTOS, isboundofst(oldTOS));
529  setBindPtr = offsetPointer_deref(int*, oldTOS, setBindofst(oldTOS));
530  *isBoundPtr = 0;
531  *setBindPtr = 100;
532  MARK_EVENT (oldTOS, (unsigned int) isboundofst(oldTOS));
533  }
534 
535  /* push it now */
536  vector_pushBack(struct X3D_Node*,thisStack,node);
537 
538 
539  } else if (*setBindPtr == 0) {
540  /* POP FROM TOP OF STACK - if we ARE the top of stack */
541  /* isBound mimics setBind */
542  *isBoundPtr = 0;
543 
544  /* unset the set_bind flag - setBind can be 0 or 1; lets make it garbage */
545  *setBindPtr = 100;
546 
547  MARK_EVENT (node, (unsigned int) isboundofst(node));
548 
549  /* are we top of stack? */
550  if (vectorSize(thisStack)>0) {
551  struct X3D_Node* oldTOS;
552 
553  oldTOS = vector_back(struct X3D_Node *,thisStack);
554  /* printf ("already have a node here...have to unbind it %p %p\n",node,oldTOS); */
555 
556  if (oldTOS != node) {
557  if(!removeNodeFromVector(0, thisStack, node)){
558  if (node->_nodeType == NODE_Viewpoint){
559  printf ("can not pop from stack, not top (%p != %p)\n",node,oldTOS);
560  printf ("%p Viewpoint, description :%s:\n",node,X3D_VIEWPOINT(node)->description->strptr);
561  printf ("%p Viewpoint, description :%s:\n",oldTOS,X3D_VIEWPOINT(oldTOS)->description->strptr);
562  printf ("oldTOS, isBound %d, setBindPtr %d\n",*(offsetPointer_deref(int*, oldTOS, isboundofst(oldTOS))),
563  *(offsetPointer_deref(int*, oldTOS, setBindofst(oldTOS))));
564  printf("and not found in stack\n");
565  }
566  }
567  return;
568  } else {
569  /* we are top of stack... */
570  /* get myself off of the stack */
571  vector_popBack(struct X3D_Node *,thisStack);
572  removeNodeFromVector(0, thisStack, node); //sometimes there are duplicates further down the stack. for unloading inlines, we need to get rid of all occurrances
573  if (vectorSize(thisStack)>0) {
574  /* get the older one back */
575  oldTOS = vector_back(struct X3D_Node *,thisStack);
576 
577  /* set it to be bound */
578  isBoundPtr = offsetPointer_deref(int*, oldTOS, isboundofst(oldTOS));
579  setBindPtr = offsetPointer_deref(int*, oldTOS, setBindofst(oldTOS));
580  *isBoundPtr = 1;
581  *setBindPtr = 100;
582  MARK_EVENT (oldTOS, (unsigned int) isboundofst(oldTOS));
583  }
584  }
585  } else {
586  /* printf ("stack is zero size, can not pop off\n"); */
587  }
588 
589 
590  } else {
591  printf ("setBindPtr %d\n",*setBindPtr);
592  }
593 #undef BINDVERBOSE
594 }
595 
596 //fog: see also notes in Component_EnvironEffects.c
597 void bind_Fog(struct X3D_Fog *node){
598  //new Aug 2016, goal GLES2 compatible (no builtin opengl fog)
599  //nothing to do in here - we'll check the binding stack for fog before rendering
600  //ttglobal tg = gglobal();
601 
602  /* check the set_bind eventin to see if it is TRUE or FALSE */
603  //if (node->set_bind < 100) {
604  // bind_node (X3D_NODE(node), getActiveBindableStacks(tg)->fog);
605 
606  /* if we do not have any more nodes on top of stack, disable fog */
607  //if(vectorSize(getActiveBindableStacks(tg)->fog) <= 0)
608  // we'll check before general scengraph rendering glDisable(GL_FOG);
609  //}
610  //glEnable(GL_FOG);
611 
612  //if(!node->isBound) return;
613  //if(node->isBound)
614  // printf("bound global fog\n");
615 }
616 
617 void render_Fog_OLD (struct X3D_Fog *node) {
618  #ifndef GL_ES_VERSION_2_0 // this should be handled in material shader
619  GLDOUBLE mod[16];
620  GLDOUBLE proj[16];
621  GLDOUBLE x,y,z;
622  GLDOUBLE x1,y1,z1;
623  GLDOUBLE sx, sy, sz;
624  GLfloat fog_colour [4];
625  char *fogptr;
626  int foglen;
627  GLDOUBLE unit[16] = {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
628  ttglobal tg = gglobal();
629 
630  UNUSED(foglen); //mitigate compiler warnings - should eventually use this variable though!
631 
632  /* printf ("render_Fog, node %d isBound %d color %f %f %f set_bind %d\n",
633  node, node->isBound, node->color.c[0],node->color.c[1],node->color.c[2],node->set_bind); */
634 
635  /* check the set_bind eventin to see if it is TRUE or FALSE */
636  if (node->set_bind < 100) {
637 
638  bind_node (X3D_NODE(node), getActiveBindableStacks(tg)->fog);
639 
640  /* if we do not have any more nodes on top of stack, disable fog */
641  glDisable(GL_FOG);
642  }
643 
644  if(!node->isBound) return;
645  if (node->visibilityRange <= 0.00001) return;
646 
647  fog_colour[0] = node->color.c[0];
648  fog_colour[1] = node->color.c[1];
649  fog_colour[2] = node->color.c[2];
650  fog_colour[3] = (float) 1.0;
651 
652  fogptr = node->fogType->strptr;
653  foglen = node->fogType->len;
654  FW_GL_PUSH_MATRIX();
655  FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, mod);
656  FW_GL_GETDOUBLEV(GL_PROJECTION_MATRIX, proj);
657  /* Get origin */
658  FW_GLU_UNPROJECT(0.0f,0.0f,0.0f,mod,proj,viewport,&x,&y,&z);
659  FW_GL_TRANSLATE_D(x,y,z);
660 
661  FW_GLU_UNPROJECT(0.0f,0.0f,0.0f,mod,unit,viewport,&x,&y,&z);
662  /* Get scale */
663  FW_GLU_PROJECT(x+1,y,z,mod,unit,viewport,&x1,&y1,&z1);
664  sx = 1/sqrt( x1*x1 + y1*y1 + z1*z1*4 );
665  FW_GLU_PROJECT(x,y+1,z,mod,unit,viewport,&x1,&y1,&z1);
666  sy = 1/sqrt( x1*x1 + y1*y1 + z1*z1*4 );
667  FW_GLU_PROJECT(x,y,z+1,mod,unit,viewport,&x1,&y1,&z1);
668  sz = 1/sqrt( x1*x1 + y1*y1 + z1*z1*4 );
669  /* Undo the translation and scale effects */
670  FW_GL_SCALE_D(sx,sy,sz);
671 
672 
673  /* now do the foggy stuff */
674  FW_GL_FOGFV(GL_FOG_COLOR,fog_colour);
675 
676  /* make the fog look like the examples in the VRML Source Book */
677  if (strcmp("LINEAR",fogptr)) {
678  /* Exponential */
679  FW_GL_FOGF(GL_FOG_DENSITY, (float) (4.0)/ (node->visibilityRange));
680  FW_GL_FOGF(GL_FOG_END, (float) (node->visibilityRange));
681  FW_GL_FOGI(GL_FOG_MODE, GL_EXP);
682  } else {
683  /* Linear */
684  FW_GL_FOGF(GL_FOG_START, (float) 1.0);
685  FW_GL_FOGF(GL_FOG_END, (float) (node->visibilityRange));
686  FW_GL_FOGI(GL_FOG_MODE, GL_LINEAR);
687  }
688  glEnable(GL_FOG);
689 
690  FW_GL_POP_MATRIX();
691  #endif /* GL_ES_VERSION_2_0 this should be handled in material shader */
692 }
693 
694 
695 /******************************************************************************
696  *
697  * Background, TextureBackground stuff
698  *
699  ******************************************************************************/
700 
701 /* save a Background vertex into the __points and __colours arrays */
702 static void saveBGVert (float *colptr, float *pt,
703  int *vertexno, float *col, double dist,
704  double x, double y, double z) {
705  /* save the colour */
706  memcpy (&colptr[*vertexno*3], col, sizeof(float)*3);
707 
708  /* and, save the vertex info */
709  pt[*vertexno*3+0] = (float)(x*dist);
710  pt[*vertexno*3+1] = (float)(y*dist);
711  pt[*vertexno*3+2] = (float)(z*dist);
712 
713  (*vertexno)++;
714 }
715 
716 /* the background centre follows our position, so, move it! */
717 static void moveBackgroundCentre () {
718  GLDOUBLE mod[16];
719  GLDOUBLE proj[16];
720  GLDOUBLE unit[16] = {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
721  GLDOUBLE x,y,z;
722  GLDOUBLE x1,y1,z1;
723  GLDOUBLE sx, sy, sz;
724  ttglobal tg = gglobal();
725 
726  FW_GL_PUSH_MATRIX();
727  FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, mod);
728  if(0){
729  FW_GL_GETDOUBLEV(GL_PROJECTION_MATRIX, proj);
730  /* Get origin */
731  FW_GLU_UNPROJECT(0.0f,0.0f,0.0f,mod,proj,viewport,&x,&y,&z);
732  FW_GL_TRANSLATE_D(x,y,z);
733 
734  LIGHTING_OFF
735 
736  FW_GLU_UNPROJECT(0.0f,0.0f,0.0f,mod,unit,viewport,&x,&y,&z);
737  /* Get scale */
738  FW_GLU_PROJECT(x+1,y,z,mod,unit,viewport,&x1,&y1,&z1);
739  sx = 1/sqrt( x1*x1 + y1*y1 + z1*z1*4 );
740  FW_GLU_PROJECT(x,y+1,z,mod,unit,viewport,&x1,&y1,&z1);
741  sy = 1/sqrt( x1*x1 + y1*y1 + z1*z1*4 );
742  FW_GLU_PROJECT(x,y,z+1,mod,unit,viewport,&x1,&y1,&z1);
743  sz = 1/sqrt( x1*x1 + y1*y1 + z1*z1*4 );
744 
745  /* Undo the translation and scale effects */
746  FW_GL_SCALE_D(sx,sy,sz);
747  //printf("moveBackground old T %f %f %f old S %f %f %f\n",x,y,z,sx,sy,sz);
748  }
749  if(1){
750  //feature-AFFINE_GLU_UNPROJECT
751  //translation, scale same as glu_unproject (no 4*z needed for this way)
752  double modi[16];
753  struct point_XYZ p, q;
754  p.x = p.y = p.z = 0.0;
755  matinverseAFFINE(modi,mod);
756  transform(&p,&p,modi);
757  FW_GL_TRANSLATE_D(p.x,p.y,p.z);
758 
759  LIGHTING_OFF
760 
761  /* Get scale */
762  q = p;
763  q.x += 1.0;
764  transform(&q,&q,mod);
765  sx = 1.0/sqrt( q.x*q.x + q.y*q.y + q.z*q.z );
766  q = p;
767  q.y += 1.0;
768  transform(&q,&q,mod);
769  sy = 1.0/sqrt( q.x*q.x + q.y*q.y + q.z*q.z );
770  q = p;
771  q.z += 1.0;
772  transform(&q,&q,mod);
773  sz = 1.0/sqrt( q.x*q.x + q.y*q.y + q.z*q.z );
774  /* Undo the translation and scale effects */
775  FW_GL_SCALE_D(sx,sy,sz);
776  //printf("moveBackground new T %f %f %f new S %f %f %f\n",x,y,z,sx,sy,sz);
777  //printf("\n");
778  }
779 }
780 
781 static void recalculateBackgroundVectors(struct X3D_Background *node) {
782  struct SFColor *c1,*c2;
783  int hdiv; /* number of horizontal strips allowed */
784  int h,v;
785  double va1, va2, ha1, ha2; /* JS - vert and horiz angles */
786  int estq;
787  int actq;
788 
789  /* filled in if this is a TextureBackground node */
790  struct X3D_TextureBackground *tbnode;
791 
792  /* generic structures between nodes used for taking individual pointers from node defns */
793  struct SFColor *skyCol; int skyColCt;
794  struct SFColor *gndCol; int gndColCt;
795  float *skyAng; int skyAngCt;
796  float *gndAng; int gndAngCt;
797  float *newPoints; float *newColors;
798  double outsideRadius, insideRadius;
799 
800  /* initialization */
801  tbnode = NULL;
802  hdiv = 20;
803 
804  /* We draw spheres, one for the sky, one for the ground - outsideRadius and insideRadius */
805  outsideRadius = DEFAULT_FARPLANE* 0.750;
806  insideRadius = DEFAULT_FARPLANE * 0.50;
807 
808  /* lets try these values - we will scale when we draw this */
809  outsideRadius = 1.0;
810  insideRadius = 0.5;
811 
812  /* handle Background and TextureBackgrounds here */
813  if (node->_nodeType == NODE_Background) {
814  skyCol = node->skyColor.p;
815  gndCol = node ->groundColor.p;
816  skyColCt = node->skyColor.n;
817  gndColCt = node->groundColor.n;
818  skyAng = node->skyAngle.p;
819  gndAng = node ->groundAngle.p;
820  skyAngCt = node->skyAngle.n;
821  gndAngCt = node->groundAngle.n;
822  } else {
823  tbnode = (struct X3D_TextureBackground *) node;
824  skyCol = tbnode->skyColor.p;
825  gndCol = tbnode ->groundColor.p;
826  skyColCt = tbnode->skyColor.n;
827  gndColCt = tbnode->groundColor.n;
828  skyAng = tbnode->skyAngle.p;
829  gndAng = tbnode ->groundAngle.p;
830  skyAngCt = tbnode->skyAngle.n;
831  gndAngCt = tbnode->groundAngle.n;
832  }
833 
834  /* do we have NO background triangles? (ie, maybe all textures??) */
835  if ((skyColCt == 0) & (gndColCt == 0)) {
836  if (node->_nodeType == NODE_Background) {
837  MARK_NODE_COMPILED
838  /* do we have an old background to destroy? */
839  FREE_IF_NZ (node->__points.p);
840  FREE_IF_NZ (node->__colours.p);
841  node->__quadcount = 0;
842  } else {
843  tbnode->_ichange = tbnode->_change; /* mimic MARK_NODE_COMPILED */
844 
845  /* do we have an old background to destroy? */
846  FREE_IF_NZ (tbnode->__points.p);
847  FREE_IF_NZ (tbnode->__colours.p);
848  tbnode->__quadcount = 0;
849  }
850  return;
851  }
852 
853 
854  /* calculate how many quads are required */
855  estq=0; actq=0;
856  if(skyColCt == 1) {
857  estq += 40;
858  } else {
859  estq += (skyColCt-1) * 20 + 20;
860  /* attempt to find exact estimate, fails if no skyAngle, so
861  simply changed above line to add 20 automatically.
862  if ((skyColCt >2) &&
863  (skyAngCt > skyColCt-2)) {
864  if (skyAng[skyColCt-2] < (PI-0.01))
865  estq += 20;
866  }
867  */
868  }
869 
870  if(gndColCt == 1) estq += 40;
871  else if (gndColCt>0) estq += (gndColCt-1) * 20;
872 
873  /* now, MALLOC space for new arrays - 3 points per vertex, 6 per quad. */
874  newPoints = MALLOC (GLfloat *, sizeof (GLfloat) * estq * 3 * 6);
875  newColors = MALLOC (GLfloat *, sizeof (GLfloat) * estq * 3 * 6);
876 
877 
878  if(skyColCt == 1) {
879  c1 = &skyCol[0];
880  va1 = 0;
881  va2 = PI/2;
882 
883  for(v=0; v<2; v++) {
884  for(h=0; h<hdiv; h++) {
885  ha1 = h * PI*2 / hdiv;
886  ha2 = (h+1) * PI*2 / hdiv;
887  /* 0 */ saveBGVert (newColors, newPoints, &actq,&c1->c[0],outsideRadius, sin(va2)*cos(ha1), cos(va2), sin(va2)*sin(ha1));
888  /* 1 */ saveBGVert (newColors, newPoints, &actq,&c1->c[0],outsideRadius, sin(va2)*cos(ha2), cos(va2), sin(va2)*sin(ha2));
889  /* 2 */ saveBGVert (newColors, newPoints, &actq,&c1->c[0],outsideRadius, sin(va1)*cos(ha2), cos(va1), sin(va1)*sin(ha2));
890  /* 0 */ saveBGVert (newColors, newPoints, &actq,&c1->c[0],outsideRadius, sin(va2)*cos(ha1), cos(va2), sin(va2)*sin(ha1));
891  /* 2 */ saveBGVert (newColors, newPoints, &actq,&c1->c[0],outsideRadius, sin(va1)*cos(ha2), cos(va1), sin(va1)*sin(ha2));
892  /* 3 */ saveBGVert (newColors, newPoints, &actq,&c1->c[0],outsideRadius, sin(va1)*cos(ha1), cos(va1), sin(va1) * sin(ha1));
893  }
894  va1 = va2;
895  va2 = PI;
896  }
897  } else {
898  va1 = 0;
899  /* this gets around a compiler warning - we really DO want last values of this from following
900  for loop */
901  c1 = &skyCol[0];
902  if (skyAngCt>0) {
903  va2= skyAng[0];
904  } else {
905  va2 = PI/2;
906  }
907  c2=c1;
908 
909 
910  for(v=0; v<(skyColCt-1); v++) {
911  c1 = &skyCol[v];
912  c2 = &skyCol[v+1];
913  if (skyAngCt>0) { va2 = skyAng[v];}
914  else { va2 = PI/2; }
915 
916  for(h=0; h<hdiv; h++) {
917  ha1 = h * PI*2 / hdiv;
918  ha2 = (h+1) * PI*2 / hdiv;
919  /* 0 */ saveBGVert(newColors,newPoints, &actq,&c2->c[0],outsideRadius, sin(va2)*cos(ha1), cos(va2), sin(va2) * sin(ha1));
920  /* 1 */ saveBGVert(newColors,newPoints, &actq,&c2->c[0],outsideRadius, sin(va2)*cos(ha2), cos(va2), sin(va2) * sin(ha2));
921  /* 2 */ saveBGVert(newColors,newPoints, &actq,&c1->c[0],outsideRadius, sin(va1)*cos(ha2), cos(va1), sin(va1) * sin(ha2));
922  /* 0 */ saveBGVert(newColors,newPoints, &actq,&c2->c[0],outsideRadius, sin(va2)*cos(ha1), cos(va2), sin(va2) * sin(ha1));
923  /* 2 */ saveBGVert(newColors,newPoints, &actq,&c1->c[0],outsideRadius, sin(va1)*cos(ha2), cos(va1), sin(va1) * sin(ha2));
924  /* 3 */ saveBGVert(newColors,newPoints, &actq,&c1->c[0],outsideRadius, sin(va1) * cos(ha1), cos(va1), sin(va1) * sin(ha1));
925  }
926  va1 = va2;
927  }
928 
929  /* now, the spec states: "If the last skyAngle is less than pi, then the
930  colour band between the last skyAngle and the nadir is clamped to the last skyColor." */
931  if (va2 < (PI-0.01)) {
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(PI) * cos(ha1), cos(PI), sin(PI) * sin(ha1));
936  /* 1 */ saveBGVert(newColors,newPoints,&actq,&c2->c[0],outsideRadius, sin(PI) * cos(ha2), cos(PI), sin(PI) * sin(ha2));
937  /* 2 */ saveBGVert(newColors,newPoints,&actq,&c2->c[0],outsideRadius, sin(va2) * cos(ha2), cos(va2), sin(va2) * sin(ha2));
938  /* 0 */ saveBGVert(newColors,newPoints,&actq,&c2->c[0],outsideRadius, sin(PI) * cos(ha1), cos(PI), sin(PI) * sin(ha1));
939  /* 2 */ saveBGVert(newColors,newPoints,&actq,&c2->c[0],outsideRadius, sin(va2) * cos(ha2), cos(va2), sin(va2) * sin(ha2));
940  /* 3 */ saveBGVert(newColors,newPoints,&actq,&c2->c[0],outsideRadius, sin(va2) * cos(ha1), cos(va2), sin(va2) * sin(ha1));
941  }
942  }
943  }
944 
945  /* Do the ground, if there is anything to do. */
946 
947  if (gndColCt>0) {
948  if(gndColCt == 1) {
949  c1 = &gndCol[0];
950  for(h=0; h<hdiv; h++) {
951  ha1 = h * PI*2 / hdiv;
952  ha2 = (h+1) * PI*2 / hdiv;
953 
954  /* 0 */ saveBGVert(newColors,newPoints,&actq,&c1->c[0],insideRadius, sin(PI) * cos(ha1), cos(PI), sin(PI) * sin(ha1));
955  /* 1 */ saveBGVert(newColors,newPoints,&actq,&c1->c[0],insideRadius, sin(PI) * cos(ha2), cos(PI), sin(PI) * sin(ha2));
956  /* 2 */ saveBGVert(newColors,newPoints,&actq,&c1->c[0],insideRadius, sin(PI/2) * cos(ha2), cos(PI/2), sin(PI/2) * sin(ha2));
957  /* 0 */ saveBGVert(newColors,newPoints,&actq,&c1->c[0],insideRadius, sin(PI) * cos(ha1), cos(PI), sin(PI) * sin(ha1));
958  /* 2 */ saveBGVert(newColors,newPoints,&actq,&c1->c[0],insideRadius, sin(PI/2) * cos(ha2), cos(PI/2), sin(PI/2) * sin(ha2));
959  /* 3 */ saveBGVert(newColors,newPoints,&actq,&c1->c[0],insideRadius, sin(PI/2) * cos(ha1), cos(PI/2), sin(PI/2) * sin(ha1));
960  }
961  } else {
962  va1 = PI;
963  for(v=0; v<gndColCt-1; v++) {
964  c1 = &gndCol[v];
965  c2 = &gndCol[v+1];
966  if (v>=gndAngCt) va2 = PI; /* bounds check */
967  else va2 = PI - gndAng[v];
968 
969  for(h=0; h<hdiv; h++) {
970  ha1 = h * PI*2 / hdiv;
971  ha2 = (h+1) * PI*2 / hdiv;
972 
973  /* 0 */ saveBGVert(newColors,newPoints,&actq,&c1->c[0],insideRadius, sin(va1)*cos(ha1), cos(va1), sin(va1)*sin(ha1));
974  /* 1 */ saveBGVert(newColors,newPoints,&actq,&c1->c[0],insideRadius, sin(va1)*cos(ha2), cos(va1), sin(va1)*sin(ha2));
975  /* 2 */ saveBGVert(newColors,newPoints,&actq,&c2->c[0],insideRadius, sin(va2)*cos(ha2), cos(va2), sin(va2)*sin(ha2));
976  /* 0 */ saveBGVert(newColors,newPoints,&actq,&c1->c[0],insideRadius, sin(va1)*cos(ha1), cos(va1), sin(va1)*sin(ha1));
977  /* 2 */ saveBGVert(newColors,newPoints,&actq,&c2->c[0],insideRadius, sin(va2)*cos(ha2), cos(va2), sin(va2)*sin(ha2));
978  /* 3 */ saveBGVert(newColors,newPoints,&actq,&c2->c[0],insideRadius, sin(va2) * cos(ha1), cos(va2), sin(va2)*sin(ha1));
979  }
980  va1 = va2;
981  }
982  }
983  }
984 
985  /* We have guessed at the quad count; lets make sure
986  * we record what we have. */
987  if (actq > (estq*6)) {
988  printf ("Background quadcount error, %d > %d\n",
989  actq,estq);
990  actq = 0;
991  }
992 
993  /* save changes */
994  /* if we are doing shaders, we write the vertex and color info to a VBO, else we keep pointers in the node */
995  if (node->_nodeType == NODE_Background) {
996 
997  MARK_NODE_COMPILED
998 
999  /* do we have an old background to destroy? */
1000  FREE_IF_NZ (node->__points.p);
1001  FREE_IF_NZ (node->__colours.p);
1002  node->__quadcount = actq;
1003  } else {
1004  tbnode->_ichange = tbnode->_change; /* mimic MARK_NODE_COMPILED */
1005  /* do we have an old background to destroy? */
1006  FREE_IF_NZ (tbnode->__points.p);
1007  FREE_IF_NZ (tbnode->__colours.p);
1008  tbnode->__quadcount = actq;
1009 
1010  }
1011 
1012 
1013  {
1014  struct MyVertex *combinedBuffer = MALLOC(struct MyVertex *, sizeof (struct MyVertex) * actq * 2);
1015  int i;
1016  float *npp = newPoints;
1017  float *ncp = newColors;
1018 
1019 
1020  if (node->_nodeType == NODE_Background) {
1021  if (node->__VBO == 0) glGenBuffers(1,(unsigned int*) &node->__VBO);
1022  } else {
1023  if (tbnode->__VBO == 0) glGenBuffers(1,(unsigned int*) &tbnode->__VBO);
1024  }
1025 
1026  /* stream both the vertex and colours together (could have done this above, but
1027  maybe can redo this if we go 100% material shaders */
1028 
1029  /* NOTE - we use SFColorRGBA - and set the Alpha to 1 so that we can use the
1030  shader with other nodes with Color fields */
1031 
1032  for (i=0; i<actq; i++) {
1033  combinedBuffer[i].vert.c[0] = *npp; npp++;
1034  combinedBuffer[i].vert.c[1] = *npp; npp++;
1035  combinedBuffer[i].vert.c[2] = *npp; npp++;
1036  combinedBuffer[i].col.c[0] = *ncp; ncp++;
1037  combinedBuffer[i].col.c[1] = *ncp; ncp++;
1038  combinedBuffer[i].col.c[2] = *ncp; ncp++;
1039  combinedBuffer[i].col.c[3] = 1.0f;
1040  }
1041  FREE_IF_NZ(newPoints);
1042  FREE_IF_NZ(newColors);
1043 
1044  /* send this data along ... */
1045  FW_GL_BINDBUFFER(GL_ARRAY_BUFFER,node->__VBO);
1046  glBufferData(GL_ARRAY_BUFFER, sizeof (struct MyVertex)*actq, combinedBuffer, GL_STATIC_DRAW);
1047  FW_GL_BINDBUFFER(GL_ARRAY_BUFFER,0);
1048 
1049  /* and, we can free it */
1050  FREE_IF_NZ(combinedBuffer);
1051  }
1052 }
1053 void reallyDraw();
1054 void render_Background (struct X3D_Background *node) {
1055  ttglobal tg = gglobal();
1056 
1057  X3D_Viewer *viewer = Viewer();
1058  /* if we are rendering blended nodes, don't bother with this one */
1059  if (renderstate()->render_blend) return;
1060 
1061  /* printf ("RBG, num %d node %d ib %d sb %d gepvp\n",node->__BGNumber, node,node->isBound,node->set_bind); */
1062  /* check the set_bind eventin to see if it is TRUE or FALSE */
1063  if (node->set_bind < 100) {
1064  bind_node (X3D_NODE(node), getActiveBindableStacks(tg)->background);
1065  }
1066 
1067  /* don't even bother going further if this node is not bound on the top */
1068  if(!node->isBound) return;
1069 
1070  if (vectorSize(getActiveBindableStacks(tg)->fog) >0) glDisable(GL_FOG);
1071 
1072  /* Cannot start_list() because of moving center, so we do our own list later */
1073  moveBackgroundCentre();
1074 
1075  if (NODE_NEEDS_COMPILING) {
1076  recalculateBackgroundVectors(node);
1077  }
1078 
1079  /* we have a sphere (maybe one and a half, as the sky and ground are different) so scale it up so that
1080  all geometry fits within the spheres
1081  dug9 Sept 2014: background could in theory be a tiny box or sphere that wraps around the avatar, if
1082  you can draw it first on each frame _and_ turn off 'depth' when you draw it.
1083  */
1084  FW_GL_SCALE_D (viewer->backgroundPlane, viewer->backgroundPlane, viewer->backgroundPlane);
1085 
1086  enableGlobalShader(getMyShader(COLOUR_MATERIAL_SHADER));
1087 
1088  FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, node->__VBO);
1089  FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER, 0);
1090 
1091  #define BUFFER_OFFSET(i) ((char *)NULL + (i))
1092  FW_GL_VERTEX_POINTER(3, GL_FLOAT, (GLsizei) sizeof(struct MyVertex), (GLfloat *)BUFFER_OFFSET(0)); //The starting point of the VBO, for the vertices
1093  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
1094 
1095  setupShaderB();
1096  sendArraysToGPU (GL_TRIANGLES, 0, node->__quadcount);
1097  reallyDraw();
1098  FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, 0);
1099  FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER, 0);
1100  finishedWithGlobalShader();
1101 
1102  /* now, for the textures, if they exist */
1103  if (((node->backUrl).n>0) ||
1104  ((node->frontUrl).n>0) ||
1105  ((node->leftUrl).n>0) ||
1106  ((node->rightUrl).n>0) ||
1107  ((node->topUrl).n>0) ||
1108  ((node->bottomUrl).n>0)) {
1109 
1110  glEnable(GL_TEXTURE_2D);
1111 
1112  FW_GL_VERTEX_POINTER (3,GL_FLOAT,0,BackgroundVert);
1113  FW_GL_NORMAL_POINTER (GL_FLOAT,0,Backnorms);
1114  FW_GL_TEXCOORD_POINTER (2,GL_FLOAT,0,boxtex,0);
1115 
1116  enableGlobalShader(getMyShader(ONE_TEX_APPEARANCE_SHADER));
1117 
1118 
1119  loadBackgroundTextures(node);
1120 
1121  finishedWithGlobalShader();
1122  }
1123  FW_GL_POP_MATRIX();
1124 
1125  /* is fog enabled? if so, disable it right now */
1126  if (vectorSize(getActiveBindableStacks(tg)->fog) >0) glEnable(GL_FOG);
1127 }
1128 
1129 
1130 void render_TextureBackground (struct X3D_TextureBackground *node) {
1131  ttglobal tg = gglobal();
1132 
1133  X3D_Viewer *viewer = Viewer();
1134  /* if we are rendering blended nodes, don't bother with this one */
1135  if (renderstate()->render_blend) return;
1136 
1137 
1138  /* printf ("RTBG, node %d ib %d sb %d gepvp\n",node,node->isBound,node->set_bind); */
1139  /* check the set_bind eventin to see if it is TRUE or FALSE */
1140  if (node->set_bind < 100) {
1141  bind_node (X3D_NODE(node), getActiveBindableStacks(tg)->background);
1142  }
1143 
1144  /* don't even bother going further if this node is not bound on the top */
1145  if(!node->isBound) return;
1146 
1147  /* is fog enabled? if so, disable it right now */
1148  if (vectorSize(getActiveBindableStacks(tg)->fog) >0) glDisable(GL_FOG);
1149 
1150  /* Cannot start_list() because of moving center, so we do our own list later */
1151  moveBackgroundCentre();
1152 
1153  if NODE_NEEDS_COMPILING
1154  /* recalculateBackgroundVectors will determine exact node type */
1155  recalculateBackgroundVectors((struct X3D_Background *)node);
1156 
1157  /* we have a sphere (maybe one and a half, as the sky and ground are different) so scale it up so that
1158  all geometry fits within the spheres */
1159  FW_GL_SCALE_D (viewer->backgroundPlane, viewer->backgroundPlane, viewer->backgroundPlane);
1160 
1161 
1162  enableGlobalShader(getMyShader(COLOUR_MATERIAL_SHADER));
1163 
1164  FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, node->__VBO);
1165  FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER, 0);
1166 
1167  #define BUFFER_OFFSET(i) ((char *)NULL + (i))
1168  FW_GL_VERTEX_POINTER(3, GL_FLOAT, sizeof(struct MyVertex), (GLfloat *)BUFFER_OFFSET(0)); //The starting point of the VBO, for the vertices
1169  FW_GL_COLOR_POINTER(4, GL_FLOAT, sizeof(struct MyVertex), (GLfloat *)BUFFER_OFFSET(sizeof(struct SFVec3f))); //The starting point of Colours, 12 bytes away
1170 
1171  sendArraysToGPU (GL_TRIANGLES, 0, node->__quadcount);
1172  reallyDraw();
1173  FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, 0);
1174  FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER, 0);
1175  finishedWithGlobalShader();
1176 
1177  /* now, for the textures, if they exist */
1178  if ((node->backTexture !=0) ||
1179  (node->frontTexture !=0) ||
1180  (node->leftTexture !=0) ||
1181  (node->rightTexture !=0) ||
1182  (node->topTexture !=0) ||
1183  (node->bottomTexture !=0)) {
1184 
1185 
1186  enableGlobalShader(getMyShader(ONE_TEX_APPEARANCE_SHADER));
1187 
1188 
1189 
1190  loadTextureBackgroundTextures(node);
1191 
1192  finishedWithGlobalShader();
1193  }
1194 
1195  /* pushes are done in moveBackgroundCentre */
1196  FW_GL_POP_MATRIX();
1197 
1198  if (vectorSize(getActiveBindableStacks(tg)->fog) >0) glEnable (GL_FOG);
1199 }
Definition: Viewer.h:196
Definition: Vector.h:36