FreeWRL/FreeX3D  3.0.0
OpenGL_Utils.c
1 
2 /*
3 
4  FreeWRL support library.
5  OpenGL initialization and functions. Rendering functions.
6 */
7 
8 
9 /****************************************************************************
10  This file is part of the FreeWRL/FreeX3D Distribution.
11 
12  Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
13 
14  FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
15  it under the terms of the GNU Lesser Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  FreeWRL/FreeX3D is distributed in the hope that it will be useful,
20  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  GNU General Public License for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
26 ****************************************************************************/
27 
28 #include <config.h>
29 #include <system.h>
30 #include <system_threads.h>
31 
32 #include <display.h>
33 #include <internal.h>
34 
35 #include <libFreeWRL.h>
36 #include <list.h>
37 #include <io_files.h>
38 
39 
40 #include "../vrml_parser/Structs.h"
41 #include "../main/headers.h"
42 #include "../main/ProdCon.h"
43 #include "../vrml_parser/CParseGeneral.h"
44 #include "../scenegraph/Vector.h"
45 #include "../vrml_parser/CFieldDecls.h"
46 #include "../vrml_parser/CParseParser.h"
47 #include "../vrml_parser/CParseLexer.h"
48 #include "../vrml_parser/CParse.h"
49 #include "../vrml_parser/CRoutes.h"
50 #include "../scenegraph/quaternion.h"
51 #include "../scenegraph/Viewer.h"
52 #include "../scenegraph/sounds.h"
53 #include "../scenegraph/LinearAlgebra.h"
54 #include "../scenegraph/Component_KeyDevice.h" /* resolving implicit declarations */
55 #include "../input/EAIHeaders.h" /* resolving implicit declarations */
56 #include "../input/InputFunctions.h"
57 #include "Frustum.h"
58 #include "../opengl/Material.h"
59 #include "../scenegraph/Component_Core.h"
60 #include "../scenegraph/Component_Networking.h"
61 #include "LoadTextures.h"
62 #include "OpenGL_Utils.h"
63 #include "Textures.h"
64 #include "../scenegraph/RenderFuncs.h"
65 #include "../scenegraph/Component_Shape.h"
66 #include <float.h>
67 
68 #include "../x3d_parser/Bindable.h"
69 
70 #include "../ui/common.h"
71 
72 void kill_rendering(void);
73 
74 //static void killNode_hide_obsolete (int index);
75 
76 static void mesa_Frustum(GLDOUBLE left, GLDOUBLE right, GLDOUBLE bottom, GLDOUBLE top, GLDOUBLE nearZ, GLDOUBLE farZ, GLDOUBLE *m);
77 
78 #undef DEBUG_FW_LOADMAT
79 #ifdef DEBUG_FW_LOADMAT
80 static void fw_glLoadMatrixd(GLDOUBLE *val,char *, int);
81 #define FW_GL_LOADMATRIX(aaa) fw_glLoadMatrixd(aaa,__FILE__,__LINE__);
82 #else
83 static void fw_glLoadMatrixd(GLDOUBLE *val);
84 #define FW_GL_LOADMATRIX(aaa) fw_glLoadMatrixd(aaa);
85 #endif
86 
87 
89  //unsigned int whichOne;
90  shaderflagsstruct whichOne;
91  s_shader_capabilities_t *myCapabilities;
92 
93 };
94 
95 int unload_broto(struct X3D_Proto* node);
96 
97 static void mesa_Ortho(GLDOUBLE left, GLDOUBLE right, GLDOUBLE bottom, GLDOUBLE top, GLDOUBLE nearZ, GLDOUBLE farZ, GLDOUBLE *m);
98 static void getShaderCommonInterfaces (s_shader_capabilities_t *me);
99 static void makeAndCompileShader(struct shaderTableEntry *);
100 
102 //int displayDepth = 24;
103 //
105 //int cc_changed = FALSE;
106 
107 //static pthread_mutex_t memtablelock = PTHREAD_MUTEX_INITIALIZER;
108 #define LOCK_MEMORYTABLE pthread_mutex_lock(&p->memtablelock);
109 #define UNLOCK_MEMORYTABLE pthread_mutex_unlock(&p->memtablelock);
110 /*
111 #define LOCK_MEMORYTABLE {printf ("LOCK_MEMORYTABLE at %s:%d\n",__FILE__,__LINE__); pthread_mutex_lock(&memtablelock);}
112 #define UNLOCK_MEMORYTABLE {printf ("UNLOCK_MEMORYTABLE at %s:%d\n",__FILE__,__LINE__); pthread_mutex_unlock(&memtablelock);}
113 */
114 
115 /* OpenGL perform matrix state here */
116 #define MAX_LARGE_MATRIX_STACK 256 /* depth of stacks */
117 #define MAX_SMALL_MATRIX_STACK 9 /* depth of stacks */
118 #define MATRIX_SIZE 16 /* 4 x 4 matrix */
119 typedef GLDOUBLE MATRIX4[MATRIX_SIZE];
120 
121 #ifdef OLDCODE
122 OLDCODE
123 OLDCODE#ifdef DISABLER
124 OLDCODEvoid fwl_glGenQueries(GLsizei n, GLuint* ids)
125 OLDCODE{
126 OLDCODE#if defined(IPHONE)
127 OLDCODE s_renderer_capabilities_t *rdr_caps;
128 OLDCODE ttglobal tg = gglobal();
129 OLDCODE rdr_caps = tg->display.rdr_caps;
130 OLDCODE if (rdr_caps->have_GL_VERSION_3_0)
131 OLDCODE {
132 OLDCODE glGenQueries(n, ids);
133 OLDCODE }
134 OLDCODE else
135 OLDCODE {
136 OLDCODE glGenQueriesEXT(n, ids);
137 OLDCODE }
138 OLDCODE#else
139 OLDCODE glGenQueries(n, ids);
140 OLDCODE#endif
141 OLDCODE}
142 OLDCODEvoid fwl_glDeleteQueries(GLsizei n, const GLuint* ids)
143 OLDCODE{
144 OLDCODE#if defined(IPHONE)
145 OLDCODE s_renderer_capabilities_t *rdr_caps;
146 OLDCODE ttglobal tg = gglobal();
147 OLDCODE rdr_caps = tg->display.rdr_caps;
148 OLDCODE if (rdr_caps->have_GL_VERSION_3_0)
149 OLDCODE {
150 OLDCODE glDeleteQueries(n, ids);
151 OLDCODE }
152 OLDCODE else
153 OLDCODE {
154 OLDCODE glDeleteQueriesEXT(n, ids);
155 OLDCODE }
156 OLDCODE#else
157 OLDCODE glDeleteQueries(n, ids);
158 OLDCODE#endif
159 OLDCODE}
160 OLDCODEvoid fwl_glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params)
161 OLDCODE{
162 OLDCODE#if defined(IPHONE)
163 OLDCODE s_renderer_capabilities_t *rdr_caps;
164 OLDCODE ttglobal tg = gglobal();
165 OLDCODE rdr_caps = tg->display.rdr_caps;
166 OLDCODE if (rdr_caps->have_GL_VERSION_3_0)
167 OLDCODE {
168 OLDCODE glGetQueryObjectuiv(id, pname, params);
169 OLDCODE }
170 OLDCODE else
171 OLDCODE {
172 OLDCODE glGetQueryObjectuivEXT(id, pname, params);
173 OLDCODE }
174 OLDCODE#else
175 OLDCODE glGetQueryObjectuiv(id, pname, params);
176 OLDCODE#endif
177 OLDCODE}
178 OLDCODE#endif
179 #endif //OLDCODE
180 
181 
182 typedef struct pOpenGL_Utils{
183  // list of all X3D nodes in this system.
184  // scene graph is tree-structured. this is a linear list.
185  struct Vector *linearNodeTable;
186  // how many holes might we have in this table, due to killing nodes, etc?
187  int potentialHoleCount;
188 
189  float cc_red, cc_green, cc_blue, cc_alpha;
190  pthread_mutex_t memtablelock;// = PTHREAD_MUTEX_INITIALIZER;
191  MATRIX4 FW_ModelView[MAX_LARGE_MATRIX_STACK];
192  MATRIX4 FW_ProjectionView[MAX_SMALL_MATRIX_STACK];
193  MATRIX4 FW_TextureView[MAX_SMALL_MATRIX_STACK];
194 
195  int modelviewTOS;// = 0;
196  int projectionviewTOS;// = 0;
197  int textureviewTOS;// = 0;
198  //int pickrayviewTOS;// = 0;
199 
200  int whichMode;// = GL_MODELVIEW;
201  GLDOUBLE *currentMatrix;// = FW_ModelView[0];
202 #ifdef GLEW_MX
203  GLEWContext glewC;
204 #endif
205 
206  struct Vector *myShaderTable; /* list of all active shaders requested by input */
207  int userDefinedShaderCount; /* if the user actually has a Shader node */
208  char *userDefinedFragmentShader[MAX_USER_DEFINED_SHADERS];
209  char *userDefinedVertexShader[MAX_USER_DEFINED_SHADERS];
210 
211  int shadingStyle; //0=flat, 1=gouraud, 2=phong 3=wireframe
212  int maxStackUsed;
213 }* ppOpenGL_Utils;
214 
215 void *OpenGL_Utils_constructor(){
216  void *v = MALLOCV(sizeof(struct pOpenGL_Utils));
217  memset(v,0,sizeof(struct pOpenGL_Utils));
218  return v;
219 }
220 void OpenGL_Utils_init(struct tOpenGL_Utils *t)
221 {
222  //public
223  /* is this 24 bit depth? 16? 8?? Assume 24, unless set on opening */
224  t->displayDepth = 24;
225 
226  //static float cc_red = 0.0f, cc_green = 0.0f, cc_blue = 0.0f, cc_alpha = 1.0f;
227  t->cc_changed = FALSE;
228 
229  //private
230  t->prv = OpenGL_Utils_constructor();
231  {
232  ppOpenGL_Utils p = (ppOpenGL_Utils)t->prv;
233  p->linearNodeTable = NULL;
234  p->potentialHoleCount = 0;
235  p->cc_red = 0.0f;
236  p->cc_green = 0.0f;
237  p->cc_blue = 0.0f;
238  p->cc_alpha = 1.0f;
239  //p->memtablelock = PTHREAD_MUTEX_INITIALIZER;
240  pthread_mutex_init(&(p->memtablelock), NULL);
241  // LoadIdentity will initialize these
242 
243  p->modelviewTOS = 0;
244  p->projectionviewTOS = 0;
245  p->textureviewTOS = 0;
246  //p->pickrayviewTOS = 0;
247 
248  p->whichMode = GL_MODELVIEW;
249  p->currentMatrix = p->FW_ModelView[0];
250 
251  // load identity matricies in here
252  loadIdentityMatrix(p->FW_ModelView[0]);
253  loadIdentityMatrix(p->FW_ProjectionView[0]);
254  loadIdentityMatrix(p->FW_TextureView[0]);
255 
256 
257  // create room for some shaders. The order in this table is
258  // the order in which they are first referenced.
259  p->myShaderTable = newVector(struct shaderTableEntry *, 8);
260 
261  // userDefinedShaders - assume 0, unless the user is a geek.
262  p->userDefinedShaderCount = 0;
263 
264  p->shadingStyle = 1; //0=flat, 1=gouraud (default), 2=phong, 3=wireframe
265  //ConsoleMessage ("setting usePhongShaders to true"); p->usePhongShaders=true;
266  p->maxStackUsed = 0;
267  }
268 }
269 void OpenGL_Utils_clear(struct tOpenGL_Utils *t)
270 {
271  //public
272  //private
273  {
274  ppOpenGL_Utils p = (ppOpenGL_Utils)t->prv;
275  deleteVector(struct X3D_Node*,p->linearNodeTable);
276  if(p->myShaderTable){
277  int i;
278  for(i=0;i<vectorSize(p->myShaderTable);i++){
279  struct shaderTableEntry *entry = vector_get(struct shaderTableEntry *,p->myShaderTable,i);
280  FREE_IF_NZ(entry->myCapabilities);
281  FREE_IF_NZ(entry);
282  }
283  deleteVector(struct shaderTableEntry *, p->myShaderTable);
284  }
285  }
286 }
287 #ifdef GLEW_MX
288 GLEWContext * glewGetContext()
289 {
290  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
291  return &(p->glewC);
292 }
293 #endif
294 
295 GLDOUBLE *getPickrayMatrix(int index)
296 {
297  //feature-AFFINE_GLU_UNPROJECT
298  bindablestack *bstack;
299  ttglobal tg = gglobal();
300  bstack = getActiveBindableStacks(tg);
301  return bstack->pickraymatrix[index];
302 }
303 void setPickrayMatrix(int index, GLDOUBLE *mat)
304 {
305  //feature-AFFINE_GLU_UNPROJECT
306  bindablestack *bstack;
307  ttglobal tg = gglobal();
308  bstack = getActiveBindableStacks(tg);
309  memcpy(bstack->pickraymatrix[index],mat,16*sizeof(GLDOUBLE));
310 }
311 
312 // we have a new world, get rid of any old user defined shaders here
313 void kill_userDefinedShaders() {
314  int i;
315  ppOpenGL_Utils p;
316  ttglobal tg = gglobal();
317  p = (ppOpenGL_Utils)tg->OpenGL_Utils.prv;
318 
319  //ConsoleMessage ("start kill_userDefinedShaders");
320  p->userDefinedShaderCount = 0;
321 
322 
323  // free the strings for the shader source, if they exist
324  for (i=0; i<MAX_USER_DEFINED_SHADERS; i++) {
325 
326  //ConsoleMessage ("udf shader %d source is %p %p",i,p->userDefinedVertexShader[i], p->userDefinedFragmentShader[i]);
327  FREE_IF_NZ (p->userDefinedFragmentShader[i]);
328  FREE_IF_NZ (p->userDefinedVertexShader[i]);
329  }
330 
331  for (i=0; i <vectorSize(p->myShaderTable); i++) {
332  struct shaderTableEntry *me = vector_get(struct shaderTableEntry *,p->myShaderTable, i);
333  FREE_IF_NZ(me->myCapabilities);
334 
335  //me->whichOne = 0;
336  FREE_IF_NZ(me);
337  }
338 
339  // set the vector to 0 size. we will keep the Vector around, for the next set
340  // of shaders for the next world.
341  p->myShaderTable->n = 0;
342 }
343 
344 
345 // we allow a certain number of user-defined shaders to (somehow) fit in here.
346 int getNextFreeUserDefinedShaderSlot() {
347  int rv;
348  ppOpenGL_Utils p;
349  ttglobal tg = gglobal();
350  p = (ppOpenGL_Utils)tg->OpenGL_Utils.prv;
351 
352  p->userDefinedShaderCount++;
353  if (p->userDefinedShaderCount == MAX_USER_DEFINED_SHADERS) return -1;
354 
355  rv = p->userDefinedShaderCount;
356 
357  return rv;
358 }
359 
360 // from a user defined shader, we capture the shader text here.
361 void sendShaderTextToEngine(int ste, int parts, char ** vertSource, char ** fragSource) {
362  char *fs = NULL;
363  char *vs = NULL;
364  int i;
365 
366  ppOpenGL_Utils p;
367  ttglobal tg = gglobal();
368  p = (ppOpenGL_Utils)tg->OpenGL_Utils.prv;
369 
370  // find the non-null for each shader text.
371  for (i=0; i<parts; i++) {
372  //ConsoleMessage ("for ptr ind %d, :%s: :%s:",i,vertSource[i],fragSource[i]);
373  if (vertSource[i] != NULL) vs=vertSource[i];
374  if (fragSource[i] != NULL) fs=fragSource[i];
375  }
376  //ConsoleMessage ("sendShaderTextToEngine, saving in %d",ste);
377 
378  p->userDefinedFragmentShader[ste] = fs;
379  p->userDefinedVertexShader[ste] = vs;
380  //printf ("so for shaderTableEntry %d, we have %d %d\n",ste,strlen(fs),strlen(vs));
381 }
382 
383 #if defined (_ANDROID)
384 
385 /***************************************************************************************/
386 /* */
387 /* UI FrontEnd Scenegraph manipulation nodes. Right now, the FreeX3D UI uses these, */
388 /* but they are NOT Android specific. Feel free to look and use. JAS. */
389 /* */
390 /***************************************************************************************/
391 
392 
393 /* pass in a X3D_Shape pointer, and from that, we go and return a bunch of fields of
394  the Shape. If a field is NULL, NULL is returned. If a field is a PROTO, the PROTO
395  expansion is returned */
396 
397 void fwl_decomposeShape(struct X3D_Shape * node,
398  struct X3D_FillProperties **fpptr,
399  struct X3D_LineProperties **lpptr,
400  struct X3D_Material **matptr,
401  struct X3D_ImageTexture **texptr,
402  struct X3D_TextureTransform **texttptr,
403  struct X3D_Node **geomptr) {
404 
405  struct X3D_Appearance *app = X3D_APPEARANCE(node->appearance);
406  struct X3D_Node * geom = node->geometry;
407 
408  // initialize every return value to NULL, possibly filed in later
409  *fpptr = NULL; *lpptr = NULL; *matptr = NULL; *texptr = NULL;
410  *texttptr = NULL; *geomptr = NULL;
411 
412  POSSIBLE_PROTO_EXPANSION(struct X3D_Appearance *,X3D_NODE(app),app);
413  POSSIBLE_PROTO_EXPANSION(struct X3D_Node*,geom,geom);
414 
415  if (app != NULL) {
416  struct X3D_FillProperties *fp = X3D_FILLPROPERTIES(app->fillProperties);
417  struct X3D_LineProperties *lp = X3D_LINEPROPERTIES(app->lineProperties);
418  struct X3D_Material *mat = X3D_MATERIAL(app->material);
419  struct X3D_ImageTexture *tex = X3D_IMAGETEXTURE(app->texture);
420  struct X3D_TextureTransform *tt = X3D_TEXTURE_TRANSFORM(app->textureTransform);
421 
422  POSSIBLE_PROTO_EXPANSION(struct X3D_FillProperties *,X3D_NODE(fp),*fpptr);
423  POSSIBLE_PROTO_EXPANSION(struct X3D_LineProperties *,X3D_NODE(lp),*lpptr);
424  POSSIBLE_PROTO_EXPANSION(struct X3D_Material *,X3D_NODE(mat),*matptr);
425  POSSIBLE_PROTO_EXPANSION(struct X3D_ImageTexture *,X3D_NODE(tex),*texptr);
426  POSSIBLE_PROTO_EXPANSION(struct X3D_TextureTransform *,X3D_NODE(tt),*texttptr);
427  }
428 
429  if (geom != NULL) {
430  POSSIBLE_PROTO_EXPANSION(struct X3D_Node *,geom,*geomptr);
431  }
432 }
433 
434 /* returns a Shape node list - Shape nodes must have valid, light (lightable?) geometry.
435  Expects a pointer to a Vector, will create Vector if required.
436  Returns an int with the number of valid nodes found;
437  Returns the filled in Vector pointer, with NODE_Shape pointers. */
438 
439 int fwl_android_get_valid_shapeNodes(struct Vector **shapeNodes) {
440 
441  struct Vector *me;
442  int tc;
443  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
444 
445  //ConsoleMessage ("fwl_android_get_valid_shapeNodes, passed in vector %p",*shapeNodes);
446 
447  // create the new vector, if required
448  if (*shapeNodes == NULL) {
449  *shapeNodes = newVector (struct X3D_Shape *, 16);
450  }
451 
452  // are we running yet?
453  if (p==NULL) return 0;
454  if (p->linearNodeTable==NULL) return 0;
455 
456  // ease of use of this vector -
457  me = *shapeNodes;
458  vectorSize(me) = 0;
459 
460  LOCK_MEMORYTABLE
461  for (tc=0; tc<vectorSize(p->linearNodeTable); tc++){
462  struct X3D_Node *node = vector_get(struct X3D_Node *,p->linearNodeTable, tc);
463 
464  // do we have a valid node?
465  if (node != NULL) {
466 
467  POSSIBLE_PROTO_EXPANSION (struct X3D_Node *,node,node);
468 
469  // do we have a shape, that is actually used?
470  if ((node->_nodeType == NODE_Shape) && (node->referenceCount>0)) {
471  struct X3D_Node *geom = X3D_SHAPE(node)->geometry;
472 
473  // does it actually have a lit geometry underneath it?
474  if (geom != NULL) {
475  POSSIBLE_PROTO_EXPANSION (struct X3D_Node *, geom, geom);
476 
477  if ((geom->_nodeType != NODE_IndexedLineSet) &&
478  (geom->_nodeType != NODE_LineSet) &&
479  (geom->_nodeType != NODE_PointSet)) {
480 
481  // yep! return this one!
482  vector_pushBack(struct X3D_Node *,me, node);
483  }
484  }
485  }
486  }
487  }
488  UNLOCK_MEMORYTABLE
489 
490 /*
491 uncomment to print out the shape nodes found
492 
493  for (tc=0; tc<vectorSize(me); tc++) {
494  struct X3D_FillProperties *fp;
495  struct X3D_LineProperties *lp;
496  struct X3D_Material *mat;
497  struct X3D_ImageTexture *tex;
498  struct X3D_TextureTransform *tt;
499  struct X3D_Node *geom;
500 
501  struct X3D_Node *node = vector_get(struct X3D_Node *,me, tc);
502  ConsoleMessage ("node %d is a %s",tc,stringNodeType(node->_nodeType));
503  fwl_decomposeShape(X3D_SHAPE(node),&fp,&lp,&mat,&tex,&tt,&geom);
504 
505  ConsoleMessage ("EOL, geometry is %s\n",stringNodeType(geom->_nodeType));
506  if (fp == NULL) ConsoleMessage ("fillProperties NULL"); else ConsoleMessage ("fillProperties %s",stringNodeType(fp->_nodeType));
507  if (lp == NULL) ConsoleMessage ("lineProperties NULL"); else ConsoleMessage ("lineProperties %s",stringNodeType(lp->_nodeType));
508  if (mat == NULL) ConsoleMessage ("material NULL"); else ConsoleMessage ("material %s",stringNodeType(mat->_nodeType));
509  if (tex == NULL) ConsoleMessage ("texture NULL"); else ConsoleMessage ("texture %s",stringNodeType(tex->_nodeType));
510  if (tt == NULL) ConsoleMessage ("texureTransform NULL"); else ConsoleMessage ("texureTransform %s",stringNodeType(tt->_nodeType));
511 
512  }
513 */
514 
515  return vectorSize(me);
516 }
517 
518 /* Zeroes the Shape Node table, for instance, when loading in a new world,
519  you want to zero this, otherwise all of the existing node pointers will
520  be invalid */
521 
522 void fwl_android_zero_shapeNodeTable(struct Vector **shapeNodes) {
523  if (*shapeNodes == NULL) {
524  *shapeNodes = newVector (struct X3D_Shape *, 16);
525  }
526  //ConsoleMessage ("fwl_android_zero_shapeNodeTable, was %d, should be 0 after this",vectorSize(*shapeNodes));
527  vectorSize(*shapeNodes) = 0;
528  //ConsoleMessage ("fwl_android_zero_shapeNodeTable, is %d, should be 0 after this",vectorSize(*shapeNodes));
529 }
530 
531 
532 
533 /* returns TRUE if the shape node actually has a fillProperties node,
534  and the FillProperties field "_enabled" is TRUE,
535  returns FALSE if the node does not exist or does not have a FillProperty,
536  or the FillProperties field "_enabled" is FALSE */
537 int fwl_get_FillPropStatus(struct Vector **shapeNodes, int whichEntry) {
538  struct X3D_FillProperties *fp;
539  struct X3D_LineProperties *lp;
540  struct X3D_Material *mat;
541  struct X3D_ImageTexture *tex;
542  struct X3D_TextureTransform *tt;
543  struct X3D_Node *geom;
544 
545  //ConsoleMessage ("fwl_get_FillPropStatus, pointer is %p");
546  //ConsoleMessage ("fwl_get_FillPropStatus, vecto size %d",vectorSize(*shapeNodes));
547 
548  // If we do not have any node entries, maybe this is a new scene, and we have to get
549  // the valid nodes?
550  if (vectorSize(*shapeNodes) == 0 ) {
551  if (fwl_android_get_valid_shapeNodes(shapeNodes) == 0) return FALSE;
552  }
553 
554  // if we are here, we really do have at least one Shape node.
555 
556  struct X3D_Node *node = vector_get(struct X3D_Node *,*shapeNodes, whichEntry);
557  //ConsoleMessage ("node %d is a %s",whichEntry,stringNodeType(node->_nodeType));
558  fwl_decomposeShape(X3D_SHAPE(node),&fp,&lp,&mat,&tex,&tt,&geom);
559  //ConsoleMessage ("and the fp field is %p",fp);
560 
561  if (fp != NULL) {
562  return (fp->_enabled);
563  }
564  return (FALSE);
565 }
566 
567 void fwl_set_FillPropStatus (struct Vector **shapeNodes, int whichEntry, int yesNo, float fillScale) {
568  struct X3D_FillProperties *fp;
569  struct X3D_LineProperties *lp;
570  struct X3D_Material *mat;
571  struct X3D_ImageTexture *tex;
572  struct X3D_TextureTransform *tt;
573  struct X3D_Node *geom;
574  struct X3D_Appearance *ap;
575 
576  // If we do not have any node entries, maybe this is a new scene, and we have to get
577  // the valid nodes?
578  if (vectorSize(*shapeNodes) == 0 ) {
579  if (fwl_android_get_valid_shapeNodes(shapeNodes) == 0) return;
580  }
581 
582  // if we are here, we really do have at least one Shape node.
583 
584  struct X3D_Node *node = vector_get(struct X3D_Node *,*shapeNodes, whichEntry);
585 
586  //ConsoleMessage ("node %d is a %s",whichEntry,stringNodeType(node->_nodeType));
587  fwl_decomposeShape(X3D_SHAPE(node),&fp,&lp,&mat,&tex,&tt,&geom);
588 
589  if (yesNo) {
590  struct X3D_FillProperties *fp;
591 
592  // does the shape have an Appearance node yet?
593  if (X3D_SHAPE(node)->appearance == NULL) {
594  struct X3D_Material *mat;
595  ap = createNewX3DNode(NODE_Appearance);
596  AddRemoveSFNodeFieldChild(node,
597  offsetPointer_deref(struct X3D_Node **,node,offsetof (struct X3D_Shape, appearance)),
598  X3D_NODE(ap),0,__FILE__,__LINE__);
599 
600  mat = createNewX3DNode(NODE_Material);
601  AddRemoveSFNodeFieldChild(X3D_NODE(ap),
602  offsetPointer_deref(struct X3D_Node **,ap,offsetof (struct X3D_Appearance, material)),
603  X3D_NODE(mat),0,__FILE__,__LINE__);
604 
605  }
606 
607  ap = X3D_APPEARANCE(X3D_SHAPE(node)->appearance);
608 
609  // create the node, then "set" it in place. If a node previously existed in the
610  // fillProperties field, then it gets removed by AddRemoveChild
611 
612  if (ap->fillProperties == NULL) {
613  //ConsoleMessage ("fwl_set_FillPropStatus, creating a FillProperties");
614  fp = X3D_FILLPROPERTIES(createNewX3DNode(NODE_FillProperties));
615  AddRemoveSFNodeFieldChild(X3D_NODE(ap),
616  offsetPointer_deref(struct X3D_Node **,X3D_NODE(ap),offsetof (struct X3D_Appearance, fillProperties)),
617  X3D_NODE(fp),0,__FILE__,__LINE__);
618  } else {
619  //ConsoleMessage ("fwl_set_FilPropStatus, just enabling FillProperties _enabled field");
620  fp = X3D_FILLPROPERTIES(ap->fillProperties);
621  // ok, we have a node here, if it is a FillProperties, set the enabled flag
622  if (fp->_nodeType == NODE_FillProperties) fp->_enabled = TRUE;
623  }
624 
625  // ensure that the FillProperties scale is ok.
626  fp->_hatchScale.c[0] = fillScale;
627  fp->_hatchScale.c[1] = fillScale;
628  } else {
629  //ConsoleMessage ("fwl_set_FillPropStatus, removing a FillProperties");
630  /* do not bother removing it - keep it around in case we re-enable and want original settings
631  AddRemoveSFNodeFieldChild(X3D_NODE(X3D_SHAPE(node)->appearance),
632  offsetPointer_deref(struct X3D_Node **,X3D_NODE(X3D_SHAPE(node)->appearance),offsetof (struct X3D_Appearance, fillProperties)),
633  X3D_NODE(fp),2,__FILE__,__LINE__);
634  */
635  ap = X3D_APPEARANCE(X3D_SHAPE(node)->appearance);
636  if (ap != NULL) {
637  if (ap->fillProperties != NULL) {
638  struct X3D_FillProperties *fp = X3D_FILLPROPERTIES(ap->fillProperties);
639  // ok, we have a node here, if it is a FillProperties, set the enabled flag
640  if (fp->_nodeType == NODE_FillProperties) fp->_enabled = FALSE;
641  }
642  }
643  }
644  // tell the Shape node that we need to check the shaders it uses...
645  node->_change ++;
646 }
647 
648 /* return whether FillProperties hatched is true/false */
649 int fwl_get_FillPropHatched(struct Vector **shapeNodes, int whichEntry) {
650  struct X3D_FillProperties *fp;
651  struct X3D_LineProperties *lp;
652  struct X3D_Material *mat;
653  struct X3D_ImageTexture *tex;
654  struct X3D_TextureTransform *tt;
655  struct X3D_Node *geom;
656 
657  // Assume that we have a Shape node
658  if (vectorSize(*shapeNodes) == 0 ) {
659  return FALSE;
660  }
661 
662  // if we are here, we really do have at least one Shape node.
663  struct X3D_Node *node = vector_get(struct X3D_Node *,*shapeNodes, whichEntry);
664  fwl_decomposeShape(X3D_SHAPE(node),&fp,&lp,&mat,&tex,&tt,&geom);
665 
666  return (fp->hatched);
667 }
668 
669 /* set current FillProperties to hatched */
670 void fwl_set_FillPropHatched (struct Vector **shapeNodes, int whichEntry, int yesNo) {
671  struct X3D_FillProperties *fp;
672  struct X3D_LineProperties *lp;
673  struct X3D_Material *mat;
674  struct X3D_ImageTexture *tex;
675  struct X3D_TextureTransform *tt;
676  struct X3D_Node *geom;
677  struct X3D_Appearance *ap;
678 
679  // Assume that we have a Shape node
680  if (vectorSize(*shapeNodes) == 0 ) {
681  return;
682  }
683 
684  // if we are here, we really do have at least one Shape node.
685  struct X3D_Node *node = vector_get(struct X3D_Node *,*shapeNodes, whichEntry);
686  fwl_decomposeShape(X3D_SHAPE(node),&fp,&lp,&mat,&tex,&tt,&geom);
687 
688  if (fp!=NULL) fp->hatched = yesNo;
689 }
690 
691 /* return whether FillProperties filled is true/false */
692 int fwl_get_FillPropFilled(struct Vector **shapeNodes, int whichEntry) {
693  struct X3D_FillProperties *fp;
694  struct X3D_LineProperties *lp;
695  struct X3D_Material *mat;
696  struct X3D_ImageTexture *tex;
697  struct X3D_TextureTransform *tt;
698  struct X3D_Node *geom;
699 
700  // Assume that we have a Shape node
701  if (vectorSize(*shapeNodes) == 0 ) {
702  return FALSE;
703  }
704 
705  // if we are here, we really do have at least one Shape node.
706  struct X3D_Node *node = vector_get(struct X3D_Node *,*shapeNodes, whichEntry);
707  fwl_decomposeShape(X3D_SHAPE(node),&fp,&lp,&mat,&tex,&tt,&geom);
708 
709  return (fp->filled);
710 }
711 
712 /* set current FillProperties to filled */
713 void fwl_set_FillPropFilled (struct Vector **shapeNodes, int whichEntry, int yesNo) {
714  struct X3D_FillProperties *fp;
715  struct X3D_LineProperties *lp;
716  struct X3D_Material *mat;
717  struct X3D_ImageTexture *tex;
718  struct X3D_TextureTransform *tt;
719  struct X3D_Node *geom;
720  struct X3D_Appearance *ap;
721 
722  // Assume that we have a Shape node
723  if (vectorSize(*shapeNodes) == 0 ) {
724  return;
725  }
726 
727  // if we are here, we really do have at least one Shape node.
728  struct X3D_Node *node = vector_get(struct X3D_Node *,*shapeNodes, whichEntry);
729  fwl_decomposeShape(X3D_SHAPE(node),&fp,&lp,&mat,&tex,&tt,&geom);
730 
731  if (fp!=NULL) fp->filled = yesNo;
732 }
733 
734 
735 /* return FillProperties style */
736 int fwl_get_FillPropStyle(struct Vector **shapeNodes, int whichEntry) {
737  struct X3D_FillProperties *fp;
738  struct X3D_LineProperties *lp;
739  struct X3D_Material *mat;
740  struct X3D_ImageTexture *tex;
741  struct X3D_TextureTransform *tt;
742  struct X3D_Node *geom;
743 
744  // Assume that we have a Shape node
745  if (vectorSize(*shapeNodes) == 0 ) {
746  return 0;
747  }
748 
749  // if we are here, we really do have at least one Shape node.
750  struct X3D_Node *node = vector_get(struct X3D_Node *,*shapeNodes, whichEntry);
751  fwl_decomposeShape(X3D_SHAPE(node),&fp,&lp,&mat,&tex,&tt,&geom);
752 
753  if (fp==NULL) return 0;
754  return (fp->hatchStyle);
755 }
756 
757 /* set current FillProperties hatchStyle */
758 void fwl_set_FillPropStyle (struct Vector **shapeNodes, int whichEntry, int which) {
759  struct X3D_FillProperties *fp;
760  struct X3D_LineProperties *lp;
761  struct X3D_Material *mat;
762  struct X3D_ImageTexture *tex;
763  struct X3D_TextureTransform *tt;
764  struct X3D_Node *geom;
765  struct X3D_Appearance *ap;
766 
767  // Assume that we have a Shape node
768  if (vectorSize(*shapeNodes) == 0 ) {
769  return;
770  }
771 
772  // if we are here, we really do have at least one Shape node.
773  struct X3D_Node *node = vector_get(struct X3D_Node *,*shapeNodes, whichEntry);
774  fwl_decomposeShape(X3D_SHAPE(node),&fp,&lp,&mat,&tex,&tt,&geom);
775 
776  if (fp!=NULL) fp->hatchStyle = which;
777 }
778 
779 
780 /* return FillProperties colour */
781 int fwl_get_FillPropColour(struct Vector **shapeNodes, int whichEntry) {
782  struct X3D_FillProperties *fp;
783  struct X3D_LineProperties *lp;
784  struct X3D_Material *mat;
785  struct X3D_ImageTexture *tex;
786  struct X3D_TextureTransform *tt;
787  struct X3D_Node *geom;
788  int integer_colour;
789 
790  // Assume that we have a Shape node
791  if (vectorSize(*shapeNodes) == 0 ) {
792  return 0;
793  }
794 
795  // if we are here, we really do have at least one Shape node.
796  struct X3D_Node *node = vector_get(struct X3D_Node *,*shapeNodes, whichEntry);
797  fwl_decomposeShape(X3D_SHAPE(node),&fp,&lp,&mat,&tex,&tt,&geom);
798 
799  #define CLAMP(value, min, max) (((value) >(max)) ? (max) : (((value) <(min)) ? (min) : (value)))
800  if (fp==NULL) return 0;
801 
802  integer_colour = 0xFF000000 + (
803  ((uint8_t)(255.0f *CLAMP(fp->hatchColor.c[0], 0.0, 1.0)) <<16) |
804  ((uint8_t)(255.0f *CLAMP(fp->hatchColor.c[1], 0.0, 1.0)) <<8) |
805  ((uint8_t)(255.0f *CLAMP(fp->hatchColor.c[2], 0.0, 1.0))));
806 
807  //ConsoleMessage ("fwl_get_fp, is %x",integer_colour);
808  return (integer_colour);
809 }
810 
811 /* set current FillProperties hatchColour */
812 void fwl_set_FillPropColour (struct Vector **shapeNodes, int whichEntry, int argbColour) {
813  struct X3D_FillProperties *fp;
814  struct X3D_LineProperties *lp;
815  struct X3D_Material *mat;
816  struct X3D_ImageTexture *tex;
817  struct X3D_TextureTransform *tt;
818  struct X3D_Node *geom;
819  struct X3D_Appearance *ap;
820 
821  // Assume that we have a Shape node
822  if (vectorSize(*shapeNodes) == 0 ) {
823  return;
824  }
825 
826  // if we are here, we really do have at least one Shape node.
827  struct X3D_Node *node = vector_get(struct X3D_Node *,*shapeNodes, whichEntry);
828  fwl_decomposeShape(X3D_SHAPE(node),&fp,&lp,&mat,&tex,&tt,&geom);
829 
830  if (fp!=NULL) {
831  fp->hatchColor.c[0] =CLAMP(((float)((argbColour &0xff0000) >>16)) /255.0, 0.0, 1.0);
832  fp->hatchColor.c[1] =CLAMP(((float)((argbColour &0x00ff00) >>8)) /255.0, 0.0, 1.0);
833  fp->hatchColor.c[2] =CLAMP(((float)((argbColour &0x0000ff))) /255.0, 0.0, 1.0);
834  //ConsoleMessage ("converted colour to %f %f %f ", fp->hatchColor.c[0], fp->hatchColor.c[1], fp->hatchColor.c[2]);
835  }
836 }
837 
838 
839 // MAterial - we need to ensure that this is node has a Material; we make it a TwoSidedMaterial
840 // even if it was a normal Material node.
841 // returns whether two-sided is true or not.
842 //JNIEXPORT jboolean JNICALL Java_org_freex3d_FreeX3DLib_setMaterialExisting(JNIEnv *env, jobject obj) {
843 // return fwl_set_MaterialExisting(&shapeNodes,0);
844 //}
845 
846 int fwl_set_MaterialExisting(struct Vector **shapeNodes, int whichEntry) {
847  struct X3D_FillProperties *fp;
848  struct X3D_LineProperties *lp;
849  struct X3D_Material *mat;
850  struct X3D_ImageTexture *tex;
851  struct X3D_TextureTransform *tt;
852  struct X3D_Node *geom;
853  struct X3D_Appearance *ap;
854  struct X3D_TwoSidedMaterial *tsm;
855 
856  int twoSided = FALSE;
857 
858  // If we do not have any node entries, maybe this is a new scene, and we have to get
859  // the valid nodes?
860  if (vectorSize(*shapeNodes) == 0 ) {
861  if (fwl_android_get_valid_shapeNodes(shapeNodes) == 0) return FALSE;
862  }
863 
864  // if we are here, we really do have at least one Shape node.
865 
866  struct X3D_Node *node = vector_get(struct X3D_Node *,*shapeNodes, whichEntry);
867 
868  //ConsoleMessage ("node %d is a %s",whichEntry,stringNodeType(node->_nodeType));
869  fwl_decomposeShape(X3D_SHAPE(node),&fp,&lp,&mat,&tex,&tt,&geom);
870 
871 
872  // does the shape have an Appearance node yet?
873  if (X3D_SHAPE(node)->appearance == NULL) {
874  struct X3D_Material *mat;
875  ap = createNewX3DNode(NODE_Appearance);
876  AddRemoveSFNodeFieldChild(node,
877  offsetPointer_deref(struct X3D_Node **,node,offsetof (struct X3D_Shape, appearance)),
878  X3D_NODE(ap),0,__FILE__,__LINE__);
879 
880  mat = createNewX3DNode(NODE_TwoSidedMaterial);
881  AddRemoveSFNodeFieldChild(X3D_NODE(ap),
882  offsetPointer_deref(struct X3D_Node **,ap,offsetof (struct X3D_Appearance, material)),
883  X3D_NODE(mat),0,__FILE__,__LINE__);
884  }
885 
886  ap = X3D_APPEARANCE(X3D_SHAPE(node)->appearance);
887  //ConsoleMessage ("so, at this point in time, we have an appearance, type %s",stringNodeType(ap->_nodeType));
888 
889  // create the node, then "set" it in place. If a node previously existed in the
890  // fillProperties field, then it gets removed by AddRemoveChild
891 
892  if (ap->material == NULL) {
893  //ConsoleMessage ("fwl_set_MaterialPropStatus, creating a MaterialProperties");
894  tsm = X3D_TWOSIDEDMATERIAL(createNewX3DNode(NODE_TwoSidedMaterial));
895  AddRemoveSFNodeFieldChild(X3D_NODE(ap),
896  offsetPointer_deref(struct X3D_Node **,X3D_NODE(ap),offsetof (struct X3D_Appearance, material)),
897  X3D_NODE(tsm),0,__FILE__,__LINE__);
898  }
899 
900  tsm = X3D_TWOSIDEDMATERIAL(ap->material);
901  // ok, we have a node here, if it is a FillProperties, set the enabled flag
902 
903  // do we have to change a Material to TwoSidedMaterial??
904  if (tsm->_nodeType != NODE_TwoSidedMaterial) {
905  struct X3D_Material *mat = X3D_MATERIAL(tsm);
906  struct X3D_TwoSidedMaterial *ntsm = createNewX3DNode(NODE_TwoSidedMaterial);
907  if (mat->_nodeType == NODE_Material) {
908  //copy over the fields
909  ntsm->ambientIntensity = mat->ambientIntensity;
910  ntsm->backAmbientIntensity = mat->ambientIntensity;
911  ntsm->shininess = mat->shininess;
912  ntsm->backShininess = mat->shininess;
913  ntsm->transparency = mat->transparency;
914  ntsm->backTransparency = mat->transparency;
915  memcpy((void *)&ntsm->diffuseColor, (void *)&mat->diffuseColor,sizeof(struct SFColor));
916  memcpy((void *)&ntsm->backDiffuseColor, (void *)&mat->diffuseColor,sizeof(struct SFColor));
917  memcpy((void *)&ntsm->emissiveColor, (void *)&mat->emissiveColor,sizeof(struct SFColor));
918  memcpy((void *)&ntsm->backEmissiveColor, (void *)&mat->emissiveColor,sizeof(struct SFColor));
919  memcpy((void *)&ntsm->specularColor, (void *)&mat->specularColor,sizeof(struct SFColor));
920  memcpy((void *)&ntsm->backSpecularColor, (void *)&mat->specularColor,sizeof(struct SFColor));
921  ntsm->separateBackColor=FALSE;
922  } else {
923  ConsoleMessage ("somehow the Material is not a node of Material type for this node");
924  }
925 
926  // now, make the child our TwoSidedMaterial node
927  AddRemoveSFNodeFieldChild(X3D_NODE(ap),
928  offsetPointer_deref(struct X3D_Node **,ap,offsetof (struct X3D_Appearance, material)),
929  X3D_NODE(ntsm),0,__FILE__,__LINE__);
930  } else {
931  // We DO have a TwoSidedMaterial...
932  twoSided = X3D_TWOSIDEDMATERIAL(tsm)->separateBackColor;
933  }
934 
935  // tell the Shape node that we need to check the shaders it uses...
936  node->_change ++;
937 
938  return twoSided;
939 }
940 
941 /* fwl_get_MaterialColourValue(xx) - example usage:
942  <item>Front Diffuse</item>
943  <item>Front Emissive</item>
944  <item>Front Specular</item>
945  <item>Back Diffuse</item>
946  <item>Back Emissive</item>
947  <item>Back Specular</item>
948 
949  int frontDiffuse = FreeX3DLib.getMaterialColourValue(0);
950  int frontEmissive = FreeX3DLib.getMaterialColourValue(1);
951  int frontSpecular = FreeX3DLib.getMaterialColourValue(2);
952  int backDiffuse = FreeX3DLib.getMaterialColourValue(3);
953  int backEmissive = FreeX3DLib.getMaterialColourValue(4);
954  int backSpecular = FreeX3DLib.getMaterialColourValue(5);
955 
956 */
957 
958 int fwl_get_MaterialColourValue(struct Vector **shapeNodes, int whichEntry, int whichValue) {
959  struct X3D_FillProperties *fp;
960  struct X3D_LineProperties *lp;
961  struct X3D_Material *mat;
962  struct X3D_ImageTexture *tex;
963  struct X3D_TextureTransform *tt;
964  struct X3D_Node *geom;
965  struct X3D_Appearance *ap;
966  struct X3D_TwoSidedMaterial *tsm;
967 
968  // If we do not have any node entries, maybe this is a new scene, and we have to get
969  // the valid nodes?
970  if (vectorSize(*shapeNodes) == 0 ) {
971  if (fwl_android_get_valid_shapeNodes(shapeNodes) == 0) return 0;
972  }
973 
974  // if we are here, we really do have at least one Shape node.
975 
976  struct X3D_Node *node = vector_get(struct X3D_Node *,*shapeNodes, whichEntry);
977 
978  //ConsoleMessage ("node %d is a %s",whichEntry,stringNodeType(node->_nodeType));
979  fwl_decomposeShape(X3D_SHAPE(node),&fp,&lp,&mat,&tex,&tt,&geom);
980 
981  if (mat == NULL) return 0;
982 
983  if (mat->_nodeType == NODE_TwoSidedMaterial) {
984  struct SFColor *col = NULL;
985  struct X3D_TwoSidedMaterial *tmat = X3D_TWOSIDEDMATERIAL(mat);
986  switch (whichValue) {
987  case 0: col = &tmat->diffuseColor; break;
988  case 1: col = &tmat->emissiveColor; break;
989  case 2: col = &tmat->specularColor; break;
990  case 3: col = &tmat->backDiffuseColor; break;
991  case 4: col = &tmat->backEmissiveColor; break;
992  case 5: col = &tmat->backSpecularColor; break;
993  default: {}
994  }
995  if (col != NULL) {
996  int integer_colour;
997  integer_colour = 0xFF000000 + (
998  ((uint8_t)(255.0f *CLAMP(col->c[0], 0.0, 1.0)) <<16) |
999  ((uint8_t)(255.0f *CLAMP(col->c[1], 0.0, 1.0)) <<8) |
1000  ((uint8_t)(255.0f *CLAMP(col->c[2], 0.0, 1.0))));
1001  //ConsoleMessage ("getMaterialValue, returning colour %d\n",integer_colour);
1002  return integer_colour;
1003  }
1004  } else {
1005  ConsoleMessage ("getMaterialValue, expected a TwoSidedMaterial, not a %s\n",stringNodeType(mat->_nodeType));
1006  }
1007  return 0;
1008 }
1009 
1010 
1011 void fwl_set_TwoSidedMaterialStatus( struct Vector **shapeNodes, int whichEntry, int oneTwo) {
1012  struct X3D_FillProperties *fp;
1013  struct X3D_LineProperties *lp;
1014  struct X3D_Material *mat;
1015  struct X3D_ImageTexture *tex;
1016  struct X3D_TextureTransform *tt;
1017  struct X3D_Node *geom;
1018  struct X3D_Appearance *ap;
1019 
1020  // Assume that we have a Shape node
1021  if (vectorSize(*shapeNodes) == 0 ) {
1022  return;
1023  }
1024 
1025  // if we are here, we really do have at least one Shape node.
1026  struct X3D_Node *node = vector_get(struct X3D_Node *,*shapeNodes, whichEntry);
1027  fwl_decomposeShape(X3D_SHAPE(node),&fp,&lp,&mat,&tex,&tt,&geom);
1028 
1029  if (mat == NULL) return;
1030  if (mat->_nodeType == NODE_TwoSidedMaterial) {
1031  // ok - we are in the correct place.
1032  X3D_TWOSIDEDMATERIAL(mat)->separateBackColor = oneTwo;
1033  mat->_change++; // signal that this node has changed
1034  }
1035 }
1036 
1037 /* set current colour */
1038 void fwl_set_MaterialColourValue (struct Vector **shapeNodes, int whichEntry, int whichValue, int argbColour) {
1039  struct X3D_FillProperties *fp;
1040  struct X3D_LineProperties *lp;
1041  struct X3D_Material *mat;
1042  struct X3D_ImageTexture *tex;
1043  struct X3D_TextureTransform *tt;
1044  struct X3D_Node *geom;
1045  struct X3D_Appearance *ap;
1046 
1047  // Assume that we have a Shape node
1048  if (vectorSize(*shapeNodes) == 0 ) {
1049  return;
1050  }
1051 
1052  // if we are here, we really do have at least one Shape node.
1053  struct X3D_Node *node = vector_get(struct X3D_Node *,*shapeNodes, whichEntry);
1054  fwl_decomposeShape(X3D_SHAPE(node),&fp,&lp,&mat,&tex,&tt,&geom);
1055 
1056  if (mat == NULL) return;
1057  if (mat->_nodeType == NODE_TwoSidedMaterial) {
1058  struct SFColor *col = NULL;
1059  struct X3D_TwoSidedMaterial *tmat = X3D_TWOSIDEDMATERIAL(mat);
1060  switch (whichValue) {
1061  case 0: col = &tmat->diffuseColor; break;
1062  case 1: col = &tmat->emissiveColor; break;
1063  case 2: col = &tmat->specularColor; break;
1064  case 3: col = &tmat->backDiffuseColor; break;
1065  case 4: col = &tmat->backEmissiveColor; break;
1066  case 5: col = &tmat->backSpecularColor; break;
1067  default: {}
1068  }
1069  if (col != NULL) {
1070  col->c[0] =CLAMP(((float)((argbColour &0xff0000) >>16)) /255.0, 0.0, 1.0);
1071  col->c[1] =CLAMP(((float)((argbColour &0x00ff00) >>8)) /255.0, 0.0, 1.0);
1072  col->c[2] =CLAMP(((float)((argbColour &0x0000ff))) /255.0, 0.0, 1.0);
1073  tmat->_change ++; // signal that this has been updated
1074  }
1075  }
1076 }
1077 
1078 
1079 
1080 /* for a SeekBar, get a field, for a side, and return it as a % 0-100
1081  whichSide - 0->2 front side,
1082  - 3-n, back side,
1083  whichField - 1 - shininess, 2 transparency, 3- Ambient Intensity
1084 */
1085 int fwl_get_MaterialFloatValue(struct Vector **shapeNodes, int whichEntry, int whichSide, int whichField) {
1086  struct X3D_FillProperties *fp;
1087  struct X3D_LineProperties *lp;
1088  struct X3D_Material *mat;
1089  struct X3D_ImageTexture *tex;
1090  struct X3D_TextureTransform *tt;
1091  struct X3D_Node *geom;
1092  struct X3D_Appearance *ap;
1093  struct X3D_TwoSidedMaterial *tsm;
1094 
1095 //ConsoleMessage ("gwl_get_materialFloatValue, entry %d, side %d, value %d",whichEntry, whichSide, whichField);
1096 
1097  // If we do not have any node entries, maybe this is a new scene, and we have to get
1098  // the valid nodes?
1099  if (vectorSize(*shapeNodes) == 0 ) {
1100  if (fwl_android_get_valid_shapeNodes(shapeNodes) == 0) return 0;
1101  }
1102 
1103  // if we are here, we really do have at least one Shape node.
1104 
1105  struct X3D_Node *node = vector_get(struct X3D_Node *,*shapeNodes, whichEntry);
1106 
1107  //ConsoleMessage ("node %d is a %s",whichEntry,stringNodeType(node->_nodeType));
1108  fwl_decomposeShape(X3D_SHAPE(node),&fp,&lp,&mat,&tex,&tt,&geom);
1109 
1110  if (mat == NULL) return 0;
1111 
1112  if (mat->_nodeType == NODE_TwoSidedMaterial) {
1113  float fcol = 0.0;
1114  struct X3D_TwoSidedMaterial *tmat = X3D_TWOSIDEDMATERIAL(mat);
1115  if (whichSide <3) {
1116  switch (whichField) {
1117  case 1: fcol = tmat->shininess; break;
1118  case 2: fcol = tmat->transparency; break;
1119  case 3: fcol = tmat->ambientIntensity; break;
1120  default: {
1121  ConsoleMessage ("hmmm - expect 1-3, got %d",whichField);
1122  return 0;
1123  }
1124  }
1125  } else {
1126  switch (whichField) {
1127  case 1: fcol = tmat->backShininess; break;
1128  case 2: fcol = tmat->backTransparency; break;
1129  case 3: fcol = tmat->backAmbientIntensity; break;
1130  default: {
1131  ConsoleMessage ("hmmm - expect 1-3, got %d",whichField);
1132  return 0;
1133  }
1134  }
1135  }
1136 
1137  return (int)(fcol*100.0); // fcol;
1138  } else {
1139  ConsoleMessage ("getMaterialValue, expected a TwoSidedMaterial, not a %s\n",stringNodeType(mat->_nodeType));
1140  }
1141 
1142  return 0;
1143 }
1144 
1145 void fwl_set_MaterialFloatValue(struct Vector **shapeNodes, int whichEntry, int whichSide, int whichField, int nv) {
1146  struct X3D_FillProperties *fp;
1147  struct X3D_LineProperties *lp;
1148  struct X3D_Material *mat;
1149  struct X3D_ImageTexture *tex;
1150  struct X3D_TextureTransform *tt;
1151  struct X3D_Node *geom;
1152  struct X3D_Appearance *ap;
1153  struct X3D_TwoSidedMaterial *tsm;
1154 
1155  //ConsoleMessage ("gwl_set_materialFloatValue, entry %d, side %d, value %d new value %d",whichEntry, whichSide, whichField, nv);
1156 
1157  // If we do not have any node entries, maybe this is a new scene, and we have to get
1158  // the valid nodes?
1159  if (vectorSize(*shapeNodes) == 0 ) {
1160  if (fwl_android_get_valid_shapeNodes(shapeNodes) == 0) return;
1161  }
1162 
1163  // if we are here, we really do have at least one Shape node.
1164 
1165  struct X3D_Node *node = vector_get(struct X3D_Node *,*shapeNodes, whichEntry);
1166 
1167  //ConsoleMessage ("node %d is a %s",whichEntry,stringNodeType(node->_nodeType));
1168  fwl_decomposeShape(X3D_SHAPE(node),&fp,&lp,&mat,&tex,&tt,&geom);
1169 
1170  if (mat == NULL) return;
1171 
1172  if (mat->_nodeType == NODE_TwoSidedMaterial) {
1173  struct X3D_TwoSidedMaterial *tmat = X3D_TWOSIDEDMATERIAL(mat);
1174  float nnv = CLAMP(((float)nv)/100.0,0.0,1.0);
1175  // ConsoleMessage("nv as int %d, as float %f",nv,nnv);
1176  if (whichSide <3) {
1177  switch (whichField) {
1178  case 1: tmat->shininess=nnv; break;
1179  case 2: tmat->transparency=nnv; break;
1180  case 3: tmat->ambientIntensity=nnv; break;
1181  default: {
1182  ConsoleMessage ("hmmm - expect 1-3, got %d",whichField);
1183  }
1184  }
1185  } else {
1186  switch (whichField) {
1187  case 1: tmat->backShininess=nnv; break;
1188  case 2: tmat->backTransparency=nnv; break;
1189  case 3: tmat->backAmbientIntensity=nnv; break;
1190  default: {
1191  ConsoleMessage ("hmmm - expect 1-3, got %d",whichField);
1192  }
1193  }
1194  }
1195  tmat->_change++; // signal that this node has changed
1196  } else {
1197  ConsoleMessage ("getMaterialValue, expected a TwoSidedMaterial, not a %s\n",stringNodeType(mat->_nodeType));
1198  }
1199 }
1200 
1201 #ifdef OLDCODE
1202 OLDCODE#undef JASTESTING
1203 OLDCODE#ifdef JASTESTING
1204 OLDCODE
1205 OLDCODE
1206 OLDCODE/* this is for looking at and manipulating the node memory table. Expect it to disappear sometime */
1207 OLDCODEvoid printNodeMemoryTable(void) {
1208 OLDCODE
1209 OLDCODE int tc;
1210 OLDCODE ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
1211 OLDCODE
1212 OLDCODE int foundHoleCount = 0;
1213 OLDCODE
1214 OLDCODE LOCK_MEMORYTABLE
1215 OLDCODE for (tc=0; tc<vectorSize(p->linearNodeTable); tc++){
1216 OLDCODE struct X3D_Node *node = vector_get(struct X3D_Node *,p->linearNodeTable,tc);
1217 OLDCODE
1218 OLDCODE if (node != NULL) {
1219 OLDCODE if (node->_nodeType == NODE_Shape) {
1220 OLDCODE //ConsoleMessage ("have shape/n");
1221 OLDCODE struct X3D_Shape *sh = X3D_SHAPE(node);
1222 OLDCODE if (sh->appearance != NULL) {
1223 OLDCODE struct X3D_Appearance *ap = X3D_APPEARANCE(sh->appearance);
1224 OLDCODE //ConsoleMessage ("have appearance\n");
1225 OLDCODE if (ap->material != NULL) {
1226 OLDCODE int i;
1227 OLDCODE struct X3D_Material *mt = X3D_MATERIAL(ap->material);
1228 OLDCODE //ConsoleMessage("have material\n");
1229 OLDCODE
1230 OLDCODE/*
1231 OLDCODE for (i=0; i<3; i++) {
1232 OLDCODE mt->diffuseColor.c[i] += 0.2;
1233 OLDCODE if (mt->diffuseColor.c[i] > 0.95) mt->diffuseColor.c[i] = 0.2;
1234 OLDCODE }
1235 OLDCODE*/
1236 OLDCODE
1237 OLDCODE mt->transparency += 0.05;
1238 OLDCODE if (mt->transparency > 1.0) mt->transparency=0.0;
1239 OLDCODE mt->_change ++;
1240 OLDCODE }
1241 OLDCODE
1242 OLDCODE }
1243 OLDCODE
1244 OLDCODE/*
1245 OLDCODE ConsoleMessage ("mem table %d is %s ref %d\n",tc,stringNodeType(node->_nodeType),node->referenceCount);
1246 OLDCODE ConsoleMessage (" shape appearance %p, geometry %p bbox %f %f %f bbcen %f %f %f\n",
1247 OLDCODE sh->appearance, sh->geometry,sh->bboxSize.c[0],sh->bboxSize.c[1],sh->bboxSize.c[2],
1248 OLDCODE sh->bboxCenter.c[0],sh->bboxCenter.c[1],sh->bboxCenter.c[2]);
1249 OLDCODE*/
1250 OLDCODE
1251 OLDCODE
1252 OLDCODE }
1253 OLDCODE } else {
1254 OLDCODE foundHoleCount ++;
1255 OLDCODE }
1256 OLDCODE }
1257 OLDCODE
1258 OLDCODE //ConsoleMessage ("potentialHoleCount %d, foundHoleCount %d",p->potentialHoleCount, foundHoleCount);
1259 OLDCODE
1260 OLDCODE UNLOCK_MEMORYTABLE
1261 OLDCODE
1262 OLDCODE}
1263 OLDCODE#endif //JASTESTING
1264 #endif //OLDCODE
1265 
1266 #endif //ANDROID
1267 
1268 #define TURN_OFF_SHOULDSORTCHILDREN node->_renderFlags = node->_renderFlags & (0xFFFF^ VF_shouldSortChildren);
1269 
1270 
1271 #ifdef OLDCODE
1272 OLDCODE/******************************************************************/
1273 OLDCODE/* textureTransforms of all kinds */
1274 OLDCODE
1275 OLDCODE/* change the clear colour, selected from the GUI, but do the command in the
1276 OLDCODE OpenGL thread */
1277 OLDCODE
1278 OLDCODEvoid fwl_set_glClearColor (float red , float green , float blue , float alpha) {
1279 OLDCODE ppOpenGL_Utils p;
1280 OLDCODE ttglobal tg = gglobal();
1281 OLDCODE p = (ppOpenGL_Utils)tg->OpenGL_Utils.prv;
1282 OLDCODE p->cc_red = red; p->cc_green = green ; p->cc_blue = blue ; p->cc_alpha = alpha ;
1283 OLDCODE tg->OpenGL_Utils.cc_changed = TRUE;
1284 OLDCODE}
1285 OLDCODE
1286 OLDCODEvoid setglClearColor (float *val) {
1287 OLDCODE ppOpenGL_Utils p;
1288 OLDCODE ttglobal tg = gglobal();
1289 OLDCODE p = (ppOpenGL_Utils)tg->OpenGL_Utils.prv;
1290 OLDCODE p->cc_red = *val; val++;
1291 OLDCODE p->cc_green = *val; val++;
1292 OLDCODE p->cc_blue = *val;
1293 OLDCODE
1294 OLDCODE// OLD_IPHONE_AQUA #ifdef AQUA
1295 OLDCODE// OLD_IPHONE_AQUA val++;
1296 OLDCODE// OLD_IPHONE_AQUA p->cc_alpha = *val;
1297 OLDCODE// OLD_IPHONE_AQUA #endif
1298 OLDCODE
1299 OLDCODE tg->OpenGL_Utils.cc_changed = TRUE;
1300 OLDCODE}
1301 OLDCODE
1302 #endif //OLDCODE
1303 
1304 void fwl_setShadingStyle(int val) {
1305  //0=flat 1=gouraud 2=phong 3=wireframe
1306  ppOpenGL_Utils p;
1307  ttglobal tg = gglobal();
1308  p = (ppOpenGL_Utils)tg->OpenGL_Utils.prv;
1309  p->shadingStyle = val;
1310 }
1311 int fwl_getShadingStyle() {
1312  ppOpenGL_Utils p;
1313  ttglobal tg = gglobal();
1314  p = (ppOpenGL_Utils)tg->OpenGL_Utils.prv;
1315  return p->shadingStyle;
1316 }
1317 
1318 #ifdef OLDCODE
1319 OLDCODE
1320 OLDCODE// use phong shading - better light reflectivity if set to true
1321 OLDCODEvoid fwl_set_phongShading (int val) {
1322 OLDCODE ppOpenGL_Utils p;
1323 OLDCODE ttglobal tg = gglobal();
1324 OLDCODE p = (ppOpenGL_Utils)tg->OpenGL_Utils.prv;
1325 OLDCODE if(val) fwl_setShadingStyle(2);
1326 OLDCODE else fwl_setShadingStyle(1);
1327 OLDCODE}
1328 OLDCODE
1329 OLDCODEint fwl_get_phongShading () {
1330 OLDCODE ppOpenGL_Utils p;
1331 OLDCODE ttglobal tg = gglobal();
1332 OLDCODE p = (ppOpenGL_Utils)tg->OpenGL_Utils.prv;
1333 OLDCODE return fwl_getShadingStyle() == 2 ? TRUE : FALSE;
1334 OLDCODE}
1335 #endif //OLDCODE
1336 
1337 
1338 
1339 /**************************************************************************************
1340 
1341  Determine near far clip planes.
1342 
1343 We have 2 choices; normal geometry, or we have a Geospatial sphere.
1344 
1345 If we have normal geometry (normal Viewpoint, or GeoViewpoint with GC coordinates)
1346 then, we take our AABB (axis alligned bounding box), rotate the 8 Vertices, and
1347 find the min/max Z distance, and just use this.
1348 
1349 This works very well for examine objects, or when we are within a virtual world.
1350 ----
1351 
1352 If we are Geospatializing around the earth, so we have GeoSpatial and have UTM or GD
1353 coordinates, lets do some optimizations here.
1354 
1355 First optimization, we know our height above the origin, and we most certainly are not
1356 going to see things past the origin, so we assume far plane is height above the origin.
1357 
1358 Second, we know our AABB contains the Geospatial sphere, and it ALSO contains the highest
1359 mountain peak, so we just go and find the value representing the highest peak. Our
1360 near plane is thus farPlane - highestPeak.
1361 
1362 **************************************************************************************/
1363 
1364 #undef MAXREADSIZE
1365 
1366 
1367 static void shaderErrorLog(GLuint myShader, char *which) {
1368  #if defined (GL_VERSION_2_0) || defined (GL_ES_VERSION_2_0)
1369  #define MAX_INFO_LOG_SIZE 512
1370  GLchar infoLog[MAX_INFO_LOG_SIZE];
1371  char outline[MAX_INFO_LOG_SIZE*2];
1372  glGetShaderInfoLog(myShader, MAX_INFO_LOG_SIZE, NULL, infoLog);
1373  sprintf(outline,"problem with %s shader: %s",which, infoLog);
1374  ConsoleMessage (outline);
1375  #else
1376  ConsoleMessage ("Problem compiling shader");
1377  #endif
1378 }
1379 
1380 
1381 /****************************************************************************************/
1382 
1383 
1384 
1385 /* find a shader that matches the capabilities requested. If no match, recreate it */
1386 s_shader_capabilities_t *getMyShaders(shaderflagsstruct rq_cap0) { //unsigned int rq_cap0) {
1387 
1388  /* GL_ES_VERSION_2_0 has GL_SHADER_COMPILER */
1389  #ifdef GL_SHADER_COMPILER
1390  GLboolean b;
1391  static bool haveDoneThis = false;
1392  #endif
1393  //unsigned int rq_cap;
1394  shaderflagsstruct rq_cap;
1395  int i;
1396 
1397 
1398 
1399  ppOpenGL_Utils p = gglobal()->OpenGL_Utils.prv;
1400  struct Vector *myShaderTable = p->myShaderTable;
1401  struct shaderTableEntry *new = NULL;
1402 
1403  rq_cap = rq_cap0;
1404  //rq_cap = NO_APPEARANCE_SHADER; //for thunking to simplest when debugging
1405 
1406  for (i=0; i<vectorSize(myShaderTable); i++) {
1407  struct shaderTableEntry *me = vector_get(struct shaderTableEntry *,myShaderTable, i);
1408  if(rq_cap0.volume){
1409  if(me->whichOne.volume == rq_cap0.volume && me->whichOne.effects == rq_cap0.effects){
1410  return me->myCapabilities;
1411  }
1412  }else{
1413  if (me->whichOne.base == rq_cap0.base && me->whichOne.effects == rq_cap0.effects && me->whichOne.usershaders == rq_cap0.usershaders) {
1414  //printf("getMyShaders chosen shader caps base %d effects %d user %d\n",me->whichOne.base,me->whichOne.effects,me->whichOne.usershaders);
1415  return me->myCapabilities;
1416  }
1417  }
1418  }
1419 
1420 
1421  // if here, we did not find the shader already compiled for us.
1422 
1423  //ConsoleMessage ("getMyShader, looking for %x",rq_cap);
1424 
1425  //ConsoleMessage ("getMyShader, not found, have to create");
1426  //for (i=0; i<vectorSize(myShaderTable); i++) {
1427  //struct shaderTableEntry *me = vector_get(struct shaderTableEntry *,myShaderTable, i);
1428  //ConsoleMessage ("getMyShader, i %d, rq_cap %x, me->whichOne %x myCap %p\n",i,rq_cap,me->whichOne,me->myCapabilities);
1429  //}
1430 
1431 
1432 
1433 
1434 
1435  /* GL_ES_VERSION_2_0 has GL_SHADER_COMPILER */
1436 #ifdef GL_SHADER_COMPILER
1437  glGetBooleanv(GL_SHADER_COMPILER,&b);
1438  if (!haveDoneThis) {
1439  haveDoneThis = true;
1440  if (!b) {
1441  //I found desktop openGL version 2.1.2 comes in here, but does still render OK
1442  //ConsoleMessage("NO SHADER COMPILER - have to sometime figure out binary shader distros");
1443  ConsoleMessage("no shader compiler\n");
1444  return NULL;
1445  }
1446  }
1447 #endif
1448 
1449  // ConsoleMessage ("getMyShader, here now");
1450 
1451 #ifdef VERBOSE
1452 #if defined (GL_SHADER_COMPILER) && defined (GL_HIGH_FLOAT)
1453  /* GL_ES_VERSION_2_0 variables for shaders */
1454  { /* debugging */
1455  GLint range[2]; GLint precision;
1456  GLboolean b;
1457 
1458  ConsoleMessage("starting getMyShader");
1459 
1460  glGetBooleanv(GL_SHADER_COMPILER,&b);
1461  if (b) ConsoleMessage("have shader compiler"); else ConsoleMessage("NO SHADER COMPILER");
1462 
1463 
1464  glGetShaderPrecisionFormat(GL_VERTEX_SHADER,GL_LOW_FLOAT, range, &precision);
1465  ConsoleMessage ("GL_VERTEX_SHADER, GL_LOW_FLOAT range [%d,%d],precision %d",range[0],range[1],precision);
1466  glGetShaderPrecisionFormat(GL_VERTEX_SHADER,GL_MEDIUM_FLOAT, range, &precision);
1467  ConsoleMessage ("GL_VERTEX_SHADER, GL_MEDIUM_FLOAT range [%d,%d],precision %d",range[0],range[1],precision);
1468  glGetShaderPrecisionFormat(GL_VERTEX_SHADER,GL_HIGH_FLOAT, range, &precision);
1469  ConsoleMessage ("GL_VERTEX_SHADER, GL_HIGH_FLOAT range [%d,%d],precision %d",range[0],range[1],precision);
1470 
1471  glGetShaderPrecisionFormat(GL_VERTEX_SHADER,GL_LOW_INT, range, &precision);
1472  ConsoleMessage ("GL_VERTEX_SHADER, GL_LOW_INT range [%d,%d],precision %d",range[0],range[1],precision);
1473  glGetShaderPrecisionFormat(GL_VERTEX_SHADER,GL_MEDIUM_INT, range, &precision);
1474  ConsoleMessage ("GL_VERTEX_SHADER, GL_MEDIUM_INT range [%d,%d],precision %d",range[0],range[1],precision);
1475  glGetShaderPrecisionFormat(GL_VERTEX_SHADER,GL_HIGH_INT, range, &precision);
1476  ConsoleMessage ("GL_VERTEX_SHADER, GL_HIGH_INT range [%d,%d],precision %d",range[0],range[1],precision);
1477 
1478  glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER,GL_LOW_FLOAT, range, &precision);
1479  ConsoleMessage ("GL_FRAGMENT_SHADER, GL_LOW_FLOAT range [%d,%d],precision %d",range[0],range[1],precision);
1480  glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER,GL_MEDIUM_FLOAT, range, &precision);
1481  ConsoleMessage ("GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT range [%d,%d],precision %d",range[0],range[1],precision);
1482  glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER,GL_HIGH_FLOAT, range, &precision);
1483  ConsoleMessage ("GL_FRAGMENT_SHADER, GL_HIGH_FLOAT range [%d,%d],precision %d",range[0],range[1],precision);
1484 
1485  glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER,GL_LOW_INT, range, &precision);
1486  ConsoleMessage ("GL_FRAGMENT_SHADER, GL_LOW_INT range [%d,%d],precision %d",range[0],range[1],precision);
1487  glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER,GL_MEDIUM_INT, range, &precision);
1488  ConsoleMessage ("GL_FRAGMENT_SHADER, GL_MEDIUM_INT range [%d,%d],precision %d",range[0],range[1],precision);
1489  glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER,GL_HIGH_INT, range, &precision);
1490  ConsoleMessage ("GL_FRAGMENT_SHADER, GL_HIGH_INT range [%d,%d],precision %d",range[0],range[1],precision);
1491  }
1492 #endif // #ifdef GL_ES_VERSION_2_0 specific debugging
1493 #endif //VERBOSE
1494 
1495  new = MALLOC(struct shaderTableEntry *, sizeof (struct shaderTableEntry));
1496 
1497  new ->whichOne = rq_cap;
1498  new->myCapabilities = MALLOC(s_shader_capabilities_t*, sizeof (s_shader_capabilities_t));
1499 
1500  //ConsoleMessage ("going to compile new shader for %x",rq_cap);
1501  makeAndCompileShader(new);
1502 
1503  vector_pushBack(struct shaderTableEntry*, myShaderTable, new);
1504 
1505  //ConsoleMessage ("going to return new %p",new);
1506  //ConsoleMessage ("... myCapabilities is %p",new->myCapabilities);
1507  return new->myCapabilities;
1508 }
1509 
1510 s_shader_capabilities_t *getMyShader(unsigned int rq_cap0) {
1511  shaderflagsstruct rq_cap0s;
1512  memset(&rq_cap0s,0,sizeof(shaderflagsstruct));
1513  rq_cap0s.base = rq_cap0;
1514  return getMyShaders(rq_cap0s);
1515 }
1516 #define DESIRE(whichOne,zzz) ((whichOne & zzz)==zzz)
1517 
1518 /* VERTEX inputs */
1519 
1520 static const GLchar *vertPosDec = "\
1521  attribute vec4 fw_Vertex; \n \
1522  uniform mat4 fw_ModelViewMatrix; \n \
1523  uniform mat4 fw_ProjectionMatrix; \n ";
1524 
1525 static const GLchar *vertNormDec = " \
1526  uniform mat3 fw_NormalMatrix;\n \
1527  attribute vec3 fw_Normal; \n";
1528 
1529 static const GLchar *vertSimColDec = "\
1530  attribute vec4 fw_Color;\n ";
1531 
1532 static const GLchar *vertTexMatrixDec = "\
1533  uniform mat4 fw_TextureMatrix0;\n";
1534 
1535 static const GLchar *vertTexCoordGenDec ="\
1536  uniform int fw_textureCoordGenType;\n";
1537 
1538 static const GLchar *vertTexCoordDec = "\
1539  attribute vec2 fw_MultiTexCoord0;\n";
1540 
1541 static const GLchar *vertOneMatDec = "\
1542  uniform fw_MaterialParameters\n\
1543  fw_FrontMaterial; \n";
1544 static const GLchar *vertBackMatDec = "\
1545  uniform fw_MaterialParameters fw_BackMaterial; \n";
1546 
1547 
1548 
1549 /* VERTEX outputs */
1550 
1551 static const GLchar *vecNormPos = " \
1552  vec3 vertexNorm; \
1553  vec4 vertexPos; \n";
1554 
1555 static const GLchar *varyingNormPos = " \
1556  varying vec3 vertexNorm; \
1557  varying vec4 vertexPos; \n";
1558 
1559 static const GLchar *varyingTexCoord = "\
1560  varying vec3 fw_TexCoord[4];\n";
1561 
1562 static const GLchar *varyingFrontColour = "\
1563  varying vec4 v_front_colour; \n";
1564 
1565 static const GLchar *varyingHatchPosition = "\
1566  varying vec2 hatchPosition; \n";
1567 
1568 /* VERTEX Calculations */
1569 
1570 static const GLchar *vertMainStart = "void main(void) { \n";
1571 
1572 static const GLchar *vertEnd = "}";
1573 
1574 static const GLchar *vertPos = "gl_Position = fw_ProjectionMatrix * fw_ModelViewMatrix * fw_Vertex;\n ";
1575 
1576 static const GLchar *vertNormPosCalc = "\
1577  vertexNorm = normalize(fw_NormalMatrix * fw_Normal);\n \
1578  vertexPos = fw_ModelViewMatrix * fw_Vertex;\n ";
1579 
1580 static const GLchar *vertSimColUse = "v_front_colour = fw_Color; \n";
1581 
1582 static const GLchar *vertEmissionOnlyColourAss = "v_front_colour = fw_FrontMaterial.emission;\n";
1583 static const GLchar *vertSingTexCalc = "fw_TexCoord[0] = vec3(vec4(fw_TextureMatrix0 *vec4(fw_MultiTexCoord0,0,0))).stp;\n";
1584 
1585 static const GLchar *vertSingTexCubeCalc = "\
1586  vec3 u=normalize(vec3(fw_ProjectionMatrix * fw_Vertex)); /* myEyeVertex */ \
1587  /* vec3 n=normalize(vec3(fw_NormalMatrix*fw_Normal)); \
1588  fw_TexCoord[0] = reflect(u,n); myEyeNormal */ \n \
1589  /* v_texC = reflect(normalize(vec3(vertexPos)),vertexNorm);\n */ \
1590  fw_TexCoord[0] = reflect(u,vertexNorm);\n";
1591 
1592 
1593 /* TextureCoordinateGenerator mapping */
1594 const static GLchar *fragTCGTDefs = TEXTURECOORDINATEGENERATORDefs;
1595 
1596 /*
1597 Good hints for code here: http://www.opengl.org/wiki/Mathematics_of_glTexGen
1598 */
1599 static const GLchar *sphEnvMapCalc = " \n \
1600 /* sphereEnvironMapping Calculation */ \
1601 /* vec3 u=normalize(vec3(fw_ModelViewMatrix * fw_Vertex)); (myEyeVertex) \
1602 vec3 n=normalize(vec3(fw_NormalMatrix*fw_Normal)); \
1603 vec3 r = reflect(u,n); (myEyeNormal) */ \n\
1604 vec3 u=normalize(vec3(vertexPos)); /* u is normalized position, used below more than once */ \n \
1605 vec3 r= reflect(u,vertexNorm); \n\
1606 if (fw_textureCoordGenType==TCGT_SPHERE) { /* TCGT_SPHERE GL_SPHERE_MAP OpenGL Equiv */ \n\
1607  float m=2.0 * sqrt(r.x*r.x + r.y*r.y + (r.z*1.0)*(r.z*1.0)); \n\
1608  fw_TexCoord[0] = vec3(r.x/m+0.5,r.y/m+0.5,0.0); \n \
1609 }else if (fw_textureCoordGenType==TCGT_CAMERASPACENORMAL) /* GL_REFLECTION_MAP used for sampling cubemaps */ {\n \
1610  float dotResult = 2.0 * dot(u,r); \n\
1611  fw_TexCoord[0] = vec3(u-r)*dotResult;\n\
1612 } else { /* default usage - like default CubeMaps */ \n\
1613  vec3 u=normalize(vec3(fw_ProjectionMatrix * fw_Vertex)); /* myEyeVertex */ \
1614  fw_TexCoord[0] = reflect(u,vertexNorm);\n \
1615 }\n\
1616 ";
1617 
1618 static const GLchar *vertHatchPosCalc = "hatchPosition = fw_Vertex.xy;\n";
1619 
1620 static const GLchar *fillPropDefines = "\
1621 uniform vec4 HatchColour; \n\
1622 uniform bool hatched; uniform bool filled;\n\
1623 uniform vec2 HatchScale; uniform vec2 HatchPct; uniform int algorithm; ";
1624 
1625 //=============STRUCT METHOD FOR LIGHTS==================
1626 // use for opengl, and angleproject desktop/d3d9
1627 static const GLchar *lightDefines = "\
1628 struct fw_MaterialParameters {\n\
1629  vec4 emission;\n\
1630  vec4 ambient;\n\
1631  vec4 diffuse;\n\
1632  vec4 specular;\n\
1633  float shininess;\n\
1634 };\n\
1635 uniform int lightcount;\n\
1636 //uniform float lightRadius[MAX_LIGHTS];\n\
1637 uniform int lightType[MAX_LIGHTS];//ANGLE like this\n\
1638 struct fw_LightSourceParameters { \n\
1639  vec4 ambient; \n\
1640  vec4 diffuse; \n\
1641  vec4 specular; \n\
1642  vec4 position; \n\
1643  vec4 halfVector; \n\
1644  vec4 spotDirection; \n\
1645  float spotBeamWidth; \n\
1646  float spotCutoff; \n\
1647  vec3 Attenuations; \n\
1648  //float constantAttenuation; \n\
1649  //float linearAttenuation; \n\
1650  //float quadraticAttenuation; \n\
1651  float lightRadius; \n\
1652  //int lightType; ANGLE doesnt like int in struct array \n\
1653 }; \n\
1654 \n\
1655 uniform fw_LightSourceParameters fw_LightSource[MAX_LIGHTS] /* gl_MaxLights */ ;\n\
1656 ";
1657 
1658 
1659 
1660 /* replace:
1661  linearAttenuation uniform float light_linAtten[MAX_LIGHTS]; \n\
1662  constantAttenuation uniform float light_constAtten[MAX_LIGHTS]; \n\
1663  quadraticAttenuation uniform float light_quadAtten[MAX_LIGHTS]; \n\
1664  spotCutoff uniform float lightSpotCutoffAngle[MAX_LIGHTS]; \n\
1665  spotExponent uniform float lightSpotBeamWidth[MAX_LIGHTS]; \n\
1666  ambient uniform vec4 lightAmbient[MAX_LIGHTS];\n\
1667  diffuse uniform vec4 lightDiffuse[MAX_LIGHTS];\n\
1668  position uniform vec4 lightPosition[MAX_LIGHTS];\n\
1669  spotDirection uniform vec4 lightSpotDirection[MAX_LIGHTS];\n\
1670  specular uniform vec4 lightSpecular[MAX_LIGHTS];\n\
1671 */
1672 
1673 
1674 static const GLchar *ADSLLightModel = "\n\
1675 /* use ADSLightModel here the ADS colour is returned from the function. */\n\
1676 vec4 ADSLightModel(in vec3 myNormal, in vec4 myPosition, in bool useMatDiffuse) {\n\
1677  int i;\n\
1678  vec4 diffuse = vec4(0., 0., 0., 0.);\n\
1679  vec4 ambient = vec4(0., 0., 0., 0.);\n\
1680  vec4 specular = vec4(0., 0., 0., 1.);\n\
1681  vec3 normal = normalize (myNormal);\n\
1682 \n\
1683  vec3 viewv = -normalize(myPosition.xyz); \n \
1684  bool backFacing = (dot(normal,viewv) < 0.0); \n \
1685  vec4 emissive;\n\
1686  vec4 matdiffuse = vec4(1.0,1.0,1.0,1.0);\n\
1687  float myAlph = 0.0;\n\
1688 \n\
1689  fw_MaterialParameters myMat = fw_FrontMaterial;\n\
1690 \n\
1691 /* back Facing materials - flip the normal and grab back materials */ \n \
1692 if (backFacing) { \n \
1693  normal = -normal; \n \
1694  myMat = fw_BackMaterial; \n \
1695 } \n \
1696 \n\
1697  emissive = myMat.emission;\n\
1698  myAlph = myMat.diffuse.a;\n\
1699  if(useMatDiffuse)\n\
1700  matdiffuse = myMat.diffuse;\n\
1701 \n\
1702  /* apply the lights to this material */\n\
1703  for (i=0; i<MAX_LIGHTS; i++) {\n\
1704  if(i<lightcount) { /*weird but ANGLE needs constant loop*/ \n\
1705  vec4 myLightDiffuse = fw_LightSource[i].diffuse;\n\
1706  vec4 myLightAmbient = fw_LightSource[i].ambient;\n\
1707  vec4 myLightSpecular = fw_LightSource[i].specular;\n\
1708  vec4 myLightPosition = fw_LightSource[i].position; \n\
1709  int myLightType = lightType[i]; //fw_LightSource[i].lightType;\n\
1710  vec3 myLightDir = fw_LightSource[i].spotDirection.xyz; \n\
1711  vec3 eyeVector = normalize(myPosition.xyz);\n\
1712  vec3 VP; /* vector of light direction and distance */\n\
1713  VP = myLightPosition.xyz - myPosition.xyz;\n\
1714  vec3 L = myLightDir; /*directional light*/ \n\
1715  if(myLightType < 2) /*point and spot*/ \n\
1716  L = normalize(VP); \n\
1717  float nDotL = max(dot(normal, L), 0.0);\n\
1718  vec3 halfVector = normalize(L - eyeVector);\n\
1719  /* normal dot light half vector */\n\
1720  float nDotHV = max(dot(normal,halfVector),0.0);\n\
1721  \n\
1722  if (myLightType==1) {\n\
1723  /* SpotLight */\n\
1724  float spotDot; \n\
1725  float spotAttenuation = 0.0; \n\
1726  float powerFactor = 0.0; /* for light dropoff */ \n\
1727  float attenuation; /* computed attenuation factor */\n\
1728  float d; /* distance to vertex */ \n\
1729  d = length(VP);\n\
1730  if (nDotL > 0.0) {\n\
1731  powerFactor = pow(nDotL,myMat.shininess); \n\
1732  /* tone down the power factor if myMat.shininess borders 0 */\n\
1733  if (myMat.shininess < 1.0) {\n\
1734  powerFactor *= myMat.shininess; \n\
1735  } \n\
1736  } \n\
1737  attenuation = 1.0/(fw_LightSource[i].Attenuations.x + (fw_LightSource[i].Attenuations.y * d) + (fw_LightSource[i].Attenuations.z *d *d));\n\
1738  spotDot = dot (-L,myLightDir);\n\
1739  /* check against spotCosCutoff */\n\
1740  if (spotDot > fw_LightSource[i].spotCutoff) {\n\
1741  spotAttenuation = pow(spotDot,fw_LightSource[i].spotCutoff);\n\
1742  }\n\
1743  attenuation *= spotAttenuation;\n\
1744  /* diffuse light computation */\n\
1745  diffuse += nDotL* matdiffuse*myLightDiffuse * attenuation;\n\
1746  /* ambient light computation */\n\
1747  ambient += myMat.ambient*myLightAmbient;\n\
1748  /* specular light computation */\n\
1749  specular += myLightSpecular * powerFactor * attenuation;\n\
1750  \n\
1751  } else if (myLightType == 2) { \n\
1752  /* DirectionalLight */ \n\
1753  float powerFactor = 0.0; /* for light dropoff */\n\
1754  if (nDotL > 0.0) {\n\
1755  powerFactor = pow(nDotHV, myMat.shininess);\n\
1756  /* tone down the power factor if myMat.shininess borders 0 */\n\
1757  if (myMat.shininess < 1.0) {\n\
1758  powerFactor *= myMat.shininess;\n\
1759  }\n\
1760  }\n\
1761  /* Specular light computation */\n\
1762  specular += myMat.specular *myLightSpecular*powerFactor;\n\
1763  /* diffuse light computation */\n\
1764  diffuse += nDotL*matdiffuse*myLightDiffuse;\n\
1765  /* ambient light computation */\n\
1766  ambient += myMat.ambient*myLightAmbient; \n\
1767  } else {\n\
1768  /* PointLight */\n\
1769  float powerFactor=0.0; /* for light dropoff */\n\
1770  float attenuation = 0.0; /* computed attenuation factor */\n\
1771  float d = length(VP); /* distance to vertex */ \n\
1772  /* are we within range? */\n\
1773  if (d <= fw_LightSource[i].lightRadius) {\n\
1774  if (nDotL > 0.0) {\n\
1775  powerFactor = pow(nDotL, myMat.shininess);\n\
1776  //attenuation = (myMat.shininess-128.0);\n\
1777  }\n\
1778  /* this is actually the SFVec3f attenuation field */\n\
1779  attenuation = 1.0/(fw_LightSource[i].Attenuations.x + (fw_LightSource[i].Attenuations.y * d) + (fw_LightSource[i].Attenuations.z *d *d));\n\
1780  /* diffuse light computation */\n\
1781  diffuse += nDotL* matdiffuse*myLightDiffuse * attenuation;\n\
1782  /* ambient light computation */\n\
1783  ambient += myMat.ambient*myLightAmbient;\n\
1784  /* specular light computation */\n\
1785  attenuation *= (myMat.shininess/128.0);\n\
1786  specular += myLightSpecular * powerFactor * attenuation;\n\
1787  }\n\
1788  }\n\
1789  }\n\
1790  }\n\
1791  return clamp(vec4(vec3(ambient+diffuse+specular+emissive),myAlph), 0.0, 1.0);\n\
1792 }\n\
1793 ";
1794 #ifdef USING_SHADER_LIGHT_ARRAY_METHOD
1795 //============= USING_SHADER_LIGHT_ARRAY_METHOD FOR LIGHTS==================
1796 //used for angleproject winRT d3d11 (which can't/doesn't convert GLSL struct[] array to HLSL properly - just affects lights)
1797 //will break custom shader node vertex/pixel shaders that try to use gl_LightSource[] ie teapot-Toon.wrl
1798 
1799 static const GLchar *lightDefinesArrayMethod = "\
1800 struct fw_MaterialParameters {\n\
1801  vec4 emission;\n\
1802  vec4 ambient;\n\
1803  vec4 diffuse;\n\
1804  vec4 specular;\n\
1805  float shininess;\n\
1806 };\n\
1807 uniform int lightcount;\n\
1808 uniform int lightType[MAX_LIGHTS];\n\
1809 uniform vec4 lightambient[MAX_LIGHTS]; \n\
1810 uniform vec4 lightdiffuse[MAX_LIGHTS]; \n\
1811 uniform vec4 lightspecular[MAX_LIGHTS]; \n\
1812 uniform vec4 lightposition[MAX_LIGHTS]; \n\
1813 uniform vec4 lighthalfVector[MAX_LIGHTS]; \n\
1814 uniform vec4 lightspotDirection[MAX_LIGHTS]; \n\
1815 uniform float lightspotBeamWidth[MAX_LIGHTS]; \n\
1816 uniform float lightspotCutoff[MAX_LIGHTS]; \n\
1817 uniform float lightRadius[MAX_LIGHTS]; \n\
1818 uniform vec3 lightAttenuations[MAX_LIGHTS]; \n\
1819 ";
1820 
1821 static const GLchar *ADSLLightModelArrayMethod = "\n\
1822 /* use ADSLightModel here the ADS colour is returned from the function. */\n\
1823 vec4 ADSLightModel(in vec3 myNormal, in vec4 myPosition, in bool useMatDiffuse) {\n\
1824  int i;\n\
1825  vec4 diffuse = vec4(0., 0., 0., 0.);\n\
1826  vec4 ambient = vec4(0., 0., 0., 0.);\n\
1827  vec4 specular = vec4(0., 0., 0., 1.);\n\
1828  vec3 normal = normalize (myNormal);\n\
1829 \n\
1830  vec3 viewv = -normalize(myPosition.xyz); \n \
1831  bool backFacing = (dot(normal,viewv) < 0.0); \n \
1832  vec4 emissive;\n\
1833  vec4 matdiffuse = vec4(1.0,1.0,1.0,1.0);\n\
1834  float myAlph = 0.0;\n\
1835 \n\
1836  fw_MaterialParameters myMat = fw_FrontMaterial;\n\
1837 \n\
1838 /* back Facing materials - flip the normal and grab back materials */ \n \
1839 if (backFacing) { \n \
1840  normal = -normal; \n \
1841  myMat = fw_BackMaterial; \n \
1842 } \n \
1843 \n\
1844  emissive = myMat.emission;\n\
1845  myAlph = myMat.diffuse.a;\n\
1846  if(useMatDiffuse)\n\
1847  matdiffuse = myMat.diffuse;\n\
1848 \n\
1849  /* apply the lights to this material */\n\
1850  for (i=0; i<MAX_LIGHTS; i++) {\n\
1851  if(i<lightcount){ /* weird but ANGLE for d3d9 needs constant loop (d3d11/winrt OK with variable loop)*/ \n\
1852  vec4 myLightDiffuse = lightdiffuse[i];\n\
1853  vec4 myLightAmbient = lightambient[i];\n\
1854  vec4 myLightSpecular = lightspecular[i];\n\
1855  vec4 myLightPosition = lightposition[i]; \n\
1856  vec4 myspotDirection = lightspotDirection[i]; \n\
1857  int myLightType = lightType[i]; \n\
1858  vec3 myLightDir = myspotDirection.xyz; \n\
1859  vec3 eyeVector = normalize(myPosition.xyz);\n\
1860  vec3 VP; /* vector of light direction and distance */\n\
1861  VP = myLightPosition.xyz - myPosition.xyz;\n\
1862  vec3 L = myLightDir; /*directional light*/ \n\
1863  if(myLightType < 2) /*point and spot*/ \n\
1864  L = normalize(VP); \n\
1865  float nDotL = max(dot(normal, L), 0.0);\n\
1866  vec3 halfVector = normalize(L - eyeVector);\n\
1867  /* normal dot light half vector */\n\
1868  float nDotHV = max(dot(normal,halfVector),0.0);\n\
1869  \n\
1870  if (myLightType==1) {\n\
1871  /* SpotLight */\n\
1872  float spotDot; \n\
1873  float spotAttenuation = 0.0; \n\
1874  float powerFactor = 0.0; /* for light dropoff */ \n\
1875  float attenuation; /* computed attenuation factor */\n\
1876  float d; /* distance to vertex */ \n\
1877  d = length(VP);\n\
1878  if (nDotL > 0.0) {\n\
1879  powerFactor = pow(nDotL,myMat.shininess); \n\
1880  /* tone down the power factor if myMat.shininess borders 0 */\n\
1881  if (myMat.shininess < 1.0) {\n\
1882  powerFactor *= myMat.shininess; \n\
1883  } \n\
1884  } \n\
1885  attenuation = 1.0/(lightAttenuations[i].x + (lightAttenuations[i].y * d) + (lightAttenuations[i].z *d *d));\n\
1886  spotDot = dot (-L,myLightDir);\n\
1887  /* check against spotCosCutoff */\n\
1888  if (spotDot > lightspotCutoff[i]) {\n\
1889  spotAttenuation = pow(spotDot,lightspotBeamWidth[i]);\n\
1890  }\n\
1891  attenuation *= spotAttenuation;\n\
1892  /* diffuse light computation */\n\
1893  diffuse += nDotL* matdiffuse*myLightDiffuse * attenuation;\n\
1894  /* ambient light computation */\n\
1895  ambient += myMat.ambient*myLightAmbient;\n\
1896  /* specular light computation */\n\
1897  specular += myLightSpecular * powerFactor * attenuation;\n\
1898  \n\
1899  } else if (myLightType == 2) { \n\
1900  /* DirectionalLight */ \n\
1901  float powerFactor = 0.0; /* for light dropoff */\n\
1902  if (nDotL > 0.0) {\n\
1903  powerFactor = pow(nDotHV, myMat.shininess);\n\
1904  /* tone down the power factor if myMat.shininess borders 0 */\n\
1905  if (myMat.shininess < 1.0) {\n\
1906  powerFactor *= myMat.shininess;\n\
1907  }\n\
1908  }\n\
1909  /* Specular light computation */\n\
1910  specular += myMat.specular *myLightSpecular*powerFactor;\n\
1911  /* diffuse light computation */\n\
1912  diffuse += nDotL*matdiffuse*myLightDiffuse;\n\
1913  /* ambient light computation */\n\
1914  ambient += myMat.ambient*myLightAmbient; \n\
1915  } else {\n\
1916  /* PointLight */\n\
1917  float powerFactor=0.0; /* for light dropoff */\n\
1918  float attenuation = 0.0; /* computed attenuation factor */\n\
1919  float d = length(VP); /* distance to vertex */ \n\
1920  /* are we within range? */\n\
1921  if (d <= lightRadius[i]) {\n\
1922  if (nDotL > 0.0) {\n\
1923  powerFactor = pow(nDotL, myMat.shininess);\n\
1924  }\n\
1925  /* this is actually the SFVec3f attenuation field */\n\
1926  attenuation = 1.0/(lightAttenuations[i].x + (lightAttenuations[i].y * d) + (lightAttenuations[i].z *d *d));\n\
1927  /* diffuse light computation */\n\
1928  diffuse += nDotL* matdiffuse*myLightDiffuse * attenuation;\n\
1929  /* ambient light computation */\n\
1930  ambient += myMat.ambient*myLightAmbient;\n\
1931  /* specular light computation */\n\
1932  attenuation *= (myMat.shininess/128.0);\n\
1933  specular += myLightSpecular * powerFactor * attenuation;\n\
1934  }\n\
1935  }\n\
1936  }\n\
1937  }\n\
1938  return clamp(vec4(vec3(ambient+diffuse+specular+emissive),myAlph), 0.0, 1.0);\n\
1939 }\n\
1940 ";
1941 
1942 #endif
1943 
1944 /* FRAGMENT bits */
1945 //#if defined (GL_HIGH_FLOAT) && defined(GL_MEDIUM_FLOAT)
1946 
1947 
1948 /* GL_ES and Desktop GL are different... */
1949 #if defined (GL_ES_VERSION_2_0)
1950  static const GLchar *fragHighPrecision = "precision highp float;\n ";
1951  static const GLchar *fragMediumPrecision = "precision mediump float;\n ";
1952  static const GLchar *maxLights = STR_MAX_LIGHTS; //"\n#define MAX_LIGHTS 2\n ";
1953 #else
1954  static const GLchar *maxLights = STR_MAX_LIGHTS; //"\n#define MAX_LIGHTS 8\n ";
1955 #endif
1956 
1957 
1958 /* NOTE that we write to the vec4 "finalFrag", and at the end we assign
1959  the gl_FragColor, because we might have textures, fill properties, etc
1960  dug9 Jan 5, 2014 change of strategy to accommodate ONE_MAT + ONE_TEX = 0x2 + 0x8 = 0x10
1961  - in frag main change to 'cascade of v4*v4' so it's easier to combine MAT with TEX
1962  - frag main:
1963  void main() {
1964  vec4 finalFrag = vec4(1.0,1.0,1.0,1.0);
1965  finalFrag = v_front_color * finalFrag; //material
1966  finalFrag = texture2D(fw_Texture_unit0, v_texC.st) * finalFrag; //texture
1967  gl_FragColor = finalFrag;
1968  }
1969 
1970 
1971 */
1972 
1973 //dug9 Jan 5, 2014 static const GLchar *fragMainStart = "void main() { vec4 finalFrag = vec4(0.,0.,0.,0.);\n";
1974 static const GLchar *fragMainStart = "void main() { vec4 finalFrag = vec4(1.,1.,1.,1.);\n";
1975 static const GLchar *anaglyphGrayFragEnd = "float gray = dot(finalFrag.rgb, vec3(0.299, 0.587, 0.114)); \n \
1976  gl_FragColor = vec4(gray, gray, gray, finalFrag.a);}";
1977 
1978 /* discard operations needed for really doing a good job in transparent situations (FillProperties, filled = false,
1979  for instance - drawing operations preclude sorting individual triangles for best rendering, so when the user
1980  requests best shaders, we add in this discard. */
1981 
1982 static const GLchar *discardInFragEnd = "if (finalFrag.a==0.0) {discard; } else {gl_FragColor = finalFrag;}}";
1983 static const GLchar *fragEnd = "gl_FragColor = finalFrag;}";
1984 
1985 
1986 static const GLchar *fragTex0Dec = "uniform sampler2D fw_Texture_unit0; \n";
1987 static const GLchar *fragTex0CubeDec = "uniform samplerCube fw_Texture_unit0; \n";
1988 
1989 
1990 //dug9 Jan 5,2014 change to 'cascade of v4*v4' in frag main
1991 static const GLchar *fragSimColAss = "finalFrag = v_front_colour * finalFrag;\n ";
1992 static const GLchar *fragNoAppAss = "finalFrag = vec4(1.0, 1.0, 1.0, 1.0);\n";
1993 static const GLchar *fragFrontColAss= " finalFrag = v_front_colour * finalFrag;";
1994 const static GLchar *fragADSLAss = "finalFrag = ADSLightModel(vertexNorm,vertexPos,true) * finalFrag;";
1995 const static GLchar *vertADSLCalc = "v_front_colour = ADSLightModel(vertexNorm,vertexPos,true);";
1996 const static GLchar *vertADSLCalc0 = "v_front_colour = ADSLightModel(vertexNorm,vertexPos,false);";
1997 
1998 const static GLchar *fragSingTexAss = "finalFrag = texture2D(fw_Texture_unit0, fw_TexCoord[0].st) * finalFrag;\n";
1999 const static GLchar *fragSingTexCubeAss = "finalFrag = textureCube(fw_Texture_unit0, fw_TexCoord[0]) * finalFrag;\n";
2000 
2001 
2002 /* MultiTexture stuff */
2003 /* still to do:
2004  #define MTMODE_BLENDCURRENTALPHA 2
2005  #define MTMODE_DOTPRODUCT3 4
2006  #define MTMODE_SELECTARG2 5
2007  #define MTMODE_SELECTARG1 6
2008  #define MTMODE_BLENDDIFFUSEALPHA 7
2009  #define MTMODE_MODULATEINVCOLOR_ADDALPHA 10
2010  #define MTMODE_MODULATEINVALPHA_ADDCOLOR 15
2011  #define MTMODE_MODULATEALPHA_ADDCOLOR 16
2012  */
2013 const static GLchar *fragMultiTexDef = MULTITEXTUREDefs;
2014 
2015 static const GLchar *fragMultiTexUniforms = " \
2016 /* defined for single textures... uniform sampler2D fw_Texture_unit0; */\
2017 uniform sampler2D fw_Texture_unit1; \
2018 uniform sampler2D fw_Texture_unit2; \
2019 /* REMOVE these as shader compile takes long \
2020 uniform sampler2D fw_Texture_unit3; \
2021 uniform sampler2D fw_Texture_unit4; \
2022 uniform sampler2D fw_Texture_unit5; \
2023 uniform sampler2D fw_Texture_unit6; \
2024 uniform sampler2D fw_Texture_unit7; \
2025 */ \
2026 uniform int fw_Texture_mode0; \
2027 uniform int fw_Texture_mode1; \
2028 uniform int fw_Texture_mode2; \
2029 /* REMOVE these as shader compile takes long \
2030 uniform int fw_Texture_mode3; \
2031 uniform int fw_Texture_mode4; \
2032 uniform int fw_Texture_mode5; \
2033 uniform int fw_Texture_mode6; \
2034 uniform int fw_Texture_mode7; \
2035 */ \n\
2036 \
2037 uniform int textureCount;\n";
2038 
2039 static const GLchar *fragFillPropFunc = "\
2040 vec4 fillPropCalc(in vec4 prevColour, vec2 MCposition, int algorithm) {\
2041 vec4 colour; \
2042 vec2 position, useBrick; \
2043 \
2044 position = MCposition / HatchScale; \
2045 \
2046 if (algorithm == 0) {/* bricking */ \
2047  if (fract(position.y * 0.5) > 0.5) \
2048  position.x += 0.5; \
2049  }\
2050 \
2051 /* algorithm 1, 2 = no futzing required here */ \
2052 if (algorithm == 3) {/* positive diagonals */ \
2053  vec2 curpos = position; \
2054  position.x -= curpos.y; \
2055 } \
2056 \
2057 if (algorithm == 4) {/* negative diagonals */ \
2058  vec2 curpos = position; \
2059  position.x += curpos.y; \
2060 } \
2061 \
2062 if (algorithm == 6) {/* diagonal crosshatch */ \
2063  vec2 curpos = position; \
2064  if (fract(position.y) > 0.5) { \
2065  if (fract(position.x) < 0.5) position.x += curpos.y; \
2066  else position.x -= curpos.y; \
2067  } else { \
2068  if (fract(position.x) > 0.5) position.x += curpos.y; \
2069  else position.x -= curpos.y; \
2070  } \
2071 } \
2072 \
2073 position = fract(position); \
2074 \
2075 useBrick = step(position, HatchPct); \
2076 \
2077  if (filled) {colour = prevColour;} else { colour=vec4(0.,0.,0.,0); }\
2078 if (hatched) { \
2079  colour = mix(HatchColour, colour, useBrick.x * useBrick.y); \
2080 } \
2081 return colour; } ";
2082 
2083 static const GLchar *fragFillPropCalc = "\
2084 finalFrag= fillPropCalc(finalFrag, hatchPosition, algorithm);\n";
2085 
2086 static const GLchar *fragMulTexFunc ="\
2087 vec4 finalColCalc(in vec4 prevColour, in int mode, in sampler2D tex, in vec2 texcoord) { \
2088 vec4 texel = texture2D(tex,texcoord); \
2089 vec4 rv = vec4(1.,0.,1.,1.); \
2090 \
2091 if (mode==MTMODE_OFF) { rv = vec4(prevColour);} \
2092 else if (mode==MTMODE_REPLACE) {rv = vec4(texture2D(tex, texcoord));}\
2093 else if (mode==MTMODE_MODULATE) { \
2094 \
2095 vec3 ct,cf; \
2096 float at,af; \
2097 \
2098 cf = prevColour.rgb; \
2099 af = prevColour.a; \
2100 \
2101 ct = texel.rgb; \
2102 at = texel.a; \
2103 \
2104 \
2105 rv = vec4(ct*cf, at*af); \
2106 \
2107 } \
2108 else if (mode==MTMODE_MODULATE2X) { \
2109 vec3 ct,cf; \
2110 float at,af; \
2111 \
2112 cf = prevColour.rgb; \
2113 af = prevColour.a; \
2114 \
2115 ct = texel.rgb; \
2116 at = texel.a; \
2117 rv = vec4(vec4(ct*cf, at*af)*vec4(2.,2.,2.,2.)); \
2118 }\
2119 else if (mode==MTMODE_MODULATE4X) { \
2120 vec3 ct,cf; \
2121 float at,af; \
2122 \
2123 cf = prevColour.rgb; \
2124 af = prevColour.a; \
2125 \
2126 ct = texel.rgb; \
2127 at = texel.a; \
2128 rv = vec4(vec4(ct*cf, at*af)*vec4(4.,4.,4.,4.)); \
2129 }\
2130 else if (mode== MTMODE_ADDSIGNED) {\
2131 rv = vec4 (prevColour + texel - vec4 (0.5, 0.5, 0.5, -.5)); \
2132 } \
2133 else if (mode== MTMODE_ADDSIGNED2X) {\
2134 rv = vec4 ((prevColour + texel - vec4 (0.5, 0.5, 0.5, -.5))*vec4(2.,2.,2.,2.)); \
2135 } \
2136 else if (mode== MTMODE_ADD) {\
2137 rv= vec4 (prevColour + texel); \
2138 } \
2139 else if (mode== MTMODE_SUBTRACT) {\
2140 rv = vec4 (prevColour - texel); \
2141 } \
2142 else if (mode==MTMODE_ADDSMOOTH) { \
2143 rv = vec4 (prevColour + (prevColour - vec4 (1.,1.,1.,1.)) * texel); \
2144 } \
2145 return rv; \
2146 \
2147 } \n";
2148 
2149 const static GLchar *fragMulTexCalc = "\
2150 if(textureCount>=1) {finalFrag=finalColCalc(finalFrag,fw_Texture_mode0,fw_Texture_unit0,fw_TexCoord[0].st);} \n\
2151 if(textureCount>=2) {finalFrag=finalColCalc(finalFrag,fw_Texture_mode1,fw_Texture_unit1,fw_TexCoord[0].st);} \n\
2152 if(textureCount>=3) {finalFrag=finalColCalc(finalFrag,fw_Texture_mode2,fw_Texture_unit2,fw_TexCoord[0].st);} \n\
2153 /* REMOVE these as shader compile takes long \
2154 if(textureCount>=4) {finalFrag=finalColCalc(finalFrag,fw_Texture_mode3,fw_Texture_unit3,fw_TexCoord[0].st);} \n\
2155 if(textureCount>=5) {finalFrag=finalColCalc(finalFrag,fw_Texture_mode4,fw_Texture_unit4,fw_TexCoord[0].st);} \n\
2156 if(textureCount>=6) {finalFrag=finalColCalc(finalFrag,fw_Texture_mode5,fw_Texture_unit5,fw_TexCoord[0].st);} \n\
2157 if(textureCount>=7) {finalFrag=finalColCalc(finalFrag,fw_Texture_mode6,fw_Texture_unit6,fw_TexCoord[0].st);} \n\
2158 if(textureCount>=8) {finalFrag=finalColCalc(finalFrag,fw_Texture_mode7,fw_Texture_unit7,fw_TexCoord[0].st);} \n\
2159 */ \n";
2160 
2161 
2162 
2163 
2164 const static GLchar *pointSizeDeclare="uniform float pointSize;\n";
2165 const static GLchar *pointSizeAss="gl_PointSize = pointSize; \n";
2166 
2167 
2168 static int getSpecificShaderSourceOriginal (const GLchar *vertexSource[vertexEndMarker],
2169  const GLchar *fragmentSource[fragmentEndMarker], shaderflagsstruct whichOne) { //unsigned int whichOne) {
2170 
2171  bool doThis;
2172  bool didADSLmaterial;
2173 #ifdef USING_SHADER_LIGHT_ARRAY_METHOD
2174  //for angleproject winRT d3d11 - can't do struct[] array for lights
2175  const GLchar *lightDefines0 = lightDefinesArrayMethod;
2176  const GLchar *ADSLLightModel0 = ADSLLightModelArrayMethod;
2177 #else
2178  const GLchar *lightDefines0 = lightDefines;
2179  const GLchar *ADSLLightModel0 = ADSLLightModel;
2180 #endif
2181 
2182  /* GL_ES - do we have medium precision, or just low precision?? */
2183  /* Phong shading - use the highest we have */
2184  /* GL_ES_VERSION_2_0 has these definitions */
2185 
2186 #if defined (GL_ES_VERSION_2_0)
2187  bool haveHighPrecisionFragmentShaders = false;
2188 
2189 #ifdef VARY_VERTEX_PRECISION
2190  bool haveHighPrecisionVertexShaders = false;
2191 #endif
2192 
2193  GLint range[2]; GLint precision;
2194 
2195  // see where we are doing the lighting. Use highest precision there, if we can.
2196  if (DESIRE(whichOne.base,SHADINGSTYLE_PHONG)) {
2197  glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER,GL_HIGH_FLOAT, range, &precision);
2198  if (precision!=0) {
2199  haveHighPrecisionFragmentShaders=true;
2200  } else {
2201  haveHighPrecisionFragmentShaders=false;
2202  glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER,GL_MEDIUM_FLOAT, range, &precision);
2203  if (precision == 0) {
2204  ConsoleMessage("low precision Fragment shaders only available - view may not work so well");
2205  }
2206  }
2207 #ifdef VARY_VERTEX_PRECISION
2208  // if we do lighting on the Vertex shader side, do we have to worry about precision?
2209  } else {
2210  glGetShaderPrecisionFormat(GL_VERTEX_SHADER,GL_HIGH_FLOAT, range, &precision);
2211  if (precision!=0) {
2212  haveHighPrecisionVertexShaders=true;
2213  } else {
2214  haveHighPrecisionVertexShaders=false;
2215  glGetShaderPrecisionFormat(GL_VERTEX_SHADER,GL_MEDIUM_FLOAT, range, &precision);
2216  if (precision == 0) {
2217  ConsoleMessage("low precision Vertex shaders only available - view may not work so well");
2218  }
2219  }
2220 #endif //VARY_VERTEX_PRECISION
2221 
2222  }
2223 #else
2224  // ConsoleMessage ("seem to not have GL_MEDIUM_FLOAT or GL_HIGH_FLOAT");
2225 #endif // GL_ES_VERSION_2_0 for GL_HIGH_FLOAT or GL_MEDIUM_FLOAT
2226 
2227  #if defined (VERBOSE) && defined (GL_ES_VERSION_2_0)
2228  { /* debugging - only */
2229  GLboolean b;
2230 
2231  glGetBooleanv(GL_SHADER_COMPILER,&b);
2232  if (b) ConsoleMessage("have shader compiler"); else ConsoleMessage("NO SHADER COMPILER");
2233 
2234 
2235  glGetShaderPrecisionFormat(GL_VERTEX_SHADER,GL_LOW_FLOAT, range, &precision);
2236  ConsoleMessage ("GL_VERTEX_SHADER, GL_LOW_FLOAT range [%d,%d],precision %d",range[0],range[1],precision);
2237  glGetShaderPrecisionFormat(GL_VERTEX_SHADER,GL_MEDIUM_FLOAT, range, &precision);
2238  ConsoleMessage ("GL_VERTEX_SHADER, GL_MEDIUM_FLOAT range [%d,%d],precision %d",range[0],range[1],precision);
2239  glGetShaderPrecisionFormat(GL_VERTEX_SHADER,GL_HIGH_FLOAT, range, &precision);
2240  ConsoleMessage ("GL_VERTEX_SHADER, GL_HIGH_FLOAT range [%d,%d],precision %d",range[0],range[1],precision);
2241 
2242  glGetShaderPrecisionFormat(GL_VERTEX_SHADER,GL_LOW_INT, range, &precision);
2243  ConsoleMessage ("GL_VERTEX_SHADER, GL_LOW_INT range [%d,%d],precision %d",range[0],range[1],precision);
2244  glGetShaderPrecisionFormat(GL_VERTEX_SHADER,GL_MEDIUM_INT, range, &precision);
2245  ConsoleMessage ("GL_VERTEX_SHADER, GL_MEDIUM_INT range [%d,%d],precision %d",range[0],range[1],precision);
2246  glGetShaderPrecisionFormat(GL_VERTEX_SHADER,GL_HIGH_INT, range, &precision);
2247  ConsoleMessage ("GL_VERTEX_SHADER, GL_HIGH_INT range [%d,%d],precision %d",range[0],range[1],precision);
2248 
2249  glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER,GL_LOW_FLOAT, range, &precision);
2250  ConsoleMessage ("GL_FRAGMENT_SHADER, GL_LOW_FLOAT range [%d,%d],precision %d",range[0],range[1],precision);
2251  glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER,GL_MEDIUM_FLOAT, range, &precision);
2252  ConsoleMessage ("GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT range [%d,%d],precision %d",range[0],range[1],precision);
2253  glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER,GL_HIGH_FLOAT, range, &precision);
2254  ConsoleMessage ("GL_FRAGMENT_SHADER, GL_HIGH_FLOAT range [%d,%d],precision %d",range[0],range[1],precision);
2255 
2256  glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER,GL_LOW_INT, range, &precision);
2257  ConsoleMessage ("GL_FRAGMENT_SHADER, GL_LOW_INT range [%d,%d],precision %d",range[0],range[1],precision);
2258  glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER,GL_MEDIUM_INT, range, &precision);
2259  ConsoleMessage ("GL_FRAGMENT_SHADER, GL_MEDIUM_INT range [%d,%d],precision %d",range[0],range[1],precision);
2260  glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER,GL_HIGH_INT, range, &precision);
2261  ConsoleMessage ("GL_FRAGMENT_SHADER, GL_HIGH_INT range [%d,%d],precision %d",range[0],range[1],precision);
2262  }
2263  #endif //VERBOSE for GL_ES_VERSION_2_0
2264 
2265  #ifdef VERBOSE
2266  if DESIRE(whichOne.base,NO_APPEARANCE_SHADER) ConsoleMessage ("want NO_APPEARANCE_SHADER");
2267  if DESIRE(whichOne.base,MATERIAL_APPEARANCE_SHADER) ConsoleMessage ("want MATERIAL_APPEARANCE_SHADER");
2268  if DESIRE(whichOne.base,TWO_MATERIAL_APPEARANCE_SHADER) ConsoleMessage ("want TWO_MATERIAL_APPEARANCE_SHADER");
2269  if DESIRE(whichOne.base,ONE_TEX_APPEARANCE_SHADER)ConsoleMessage("want ONE_TEX_APPEARANCE_SHADER");
2270  if DESIRE(whichOne.base,MULTI_TEX_APPEARANCE_SHADER)ConsoleMessage("want MULTI_TEX_APPEARANCE_SHADER");
2271  if DESIRE(whichOne.base,COLOUR_MATERIAL_SHADER)ConsoleMessage("want COLOUR_MATERIAL_SHADER");
2272  if DESIRE(whichOne.base,FILL_PROPERTIES_SHADER)ConsoleMessage("want FILL_PROPERTIES_SHADER");
2273  if DESIRE(whichOne.base,HAVE_LINEPOINTS_COLOR)ConsoleMessage ("want LINE_POINTS_COLOR");
2274  if DESIRE(whichOne.base,HAVE_LINEPOINTS_APPEARANCE)ConsoleMessage ("want LINE_POINTS_APPEARANCE");
2275  if DESIRE(whichOne.base,HAVE_TEXTURECOORDINATEGENERATOR) ConsoleMessage ("want HAVE_TEXTURECOORDINATEGENERATOR");
2276  if DESIRE(whichOne.base,HAVE_CUBEMAP_TEXTURE) ConsoleMessage ("want HAVE_CUBEMAP_TEXTURE");
2277  #endif //VERBOSE
2278 #undef VERBOSE
2279 
2280 
2281  /* Cross shader Fragment bits - GL_ES_VERSION_2_0 has this */
2282 #if defined(GL_ES_VERSION_2_0)
2283  fragmentSource[fragmentGLSLVersion] = "#version 100\n";
2284  vertexSource[vertexGLSLVersion] = "#version 100\n";
2285  if (haveHighPrecisionFragmentShaders) {
2286  fragmentSource[fragmentPrecisionDeclare] = fragHighPrecision;
2287  //ConsoleMessage("have high precision fragment shaders");
2288  } else {
2289  fragmentSource[fragmentPrecisionDeclare] = fragMediumPrecision;
2290  //ConsoleMessage("have medium precision fragment shaders");
2291  }
2292 
2293 #ifdef VARY_VERTEX_PRECISION
2294  // if we do lighting on the Vertex shader side, do we have to worry about precision?
2295  if (haveHighPrecisionVertexShaders) {
2296  vertexSource[vertexPrecisionDeclare] = fragHighPrecision;
2297  ConsoleMessage("have high precision vertex shaders");
2298  } else {
2299  vertexSource[vertexPrecisionDeclare] = fragMediumPrecision;
2300  ConsoleMessage("have medium precision vertex shaders");
2301  }
2302 #endif //VARY_VERTEX_PRECISION
2303 
2304 #else
2305  //changed from 120 to 110 Apr2014: main shaders still seem to work the same, openGL 2.0 now compiles them, and 2.1 (by specs) compiles 110
2306  fragmentSource[fragmentGLSLVersion] = "#version 110\n";//"#version 120\n";
2307  vertexSource[vertexGLSLVersion] = "#version 110\n"; //"#version 120\n";
2308 #endif
2309 
2310  fragmentSource[fragMaxLightsDeclare] = maxLights;
2311  vertexSource[vertMaxLightsDeclare] = maxLights;
2312  vertexSource[vertexPositionDeclare] = vertPosDec;
2313 
2314 
2315 
2316  /* User defined shaders - only give the defines, let the user do the rest */
2317 
2318  if (!whichOne.usershaders) { // & USER_DEFINED_SHADER_MASK) == 0) {
2319  /* initialize */
2320 
2321  /* Generic things first */
2322 
2323  /* Cross shader Vertex bits */
2324 
2325  vertexSource[vertexMainStart] = vertMainStart;
2326  vertexSource[vertexPositionCalculation] = vertPos;
2327  vertexSource[vertexMainEnd] = vertEnd;
2328 
2329 
2330  fragmentSource[fragmentMainStart] = fragMainStart;
2331  if(Viewer()->anaglyph || Viewer()->anaglyphB)
2332  fragmentSource[fragmentMainEnd] = anaglyphGrayFragEnd;
2333  else {
2334  if (DESIRE(whichOne.base,SHADINGSTYLE_PHONG)) fragmentSource[fragmentMainEnd] = discardInFragEnd;
2335  else fragmentSource[fragmentMainEnd] = fragEnd;
2336  //fragmentSource[fragmentMainEnd] = discardInFragEnd;
2337  }
2338 
2339  //ConsoleMessage ("whichOne %x mask %x",whichOne,~whichOne);
2340 
2341 
2342  /* specific strings for specific shader capabilities */
2343 
2344  if DESIRE(whichOne.base,COLOUR_MATERIAL_SHADER) {
2345  vertexSource[vertexSimpleColourDeclare] = vertSimColDec;
2346  vertexSource[vertFrontColourDeclare] = varyingFrontColour;
2347  vertexSource[vertexSimpleColourCalculation] = vertSimColUse;
2348  vertexSource[vertexPointSizeDeclare] = pointSizeDeclare;
2349  vertexSource[vertexPointSizeAssign] = pointSizeAss;
2350  fragmentSource[fragmentSimpleColourDeclare] = varyingFrontColour;
2351  fragmentSource[fragmentSimpleColourAssign] = fragSimColAss;
2352  }
2353 
2354  if DESIRE(whichOne.base,NO_APPEARANCE_SHADER) {
2355  fragmentSource[fragmentSimpleColourAssign] = fragNoAppAss;
2356  vertexSource[vertexPointSizeDeclare] = pointSizeDeclare;
2357  vertexSource[vertexPointSizeAssign] = pointSizeAss;
2358 
2359  }
2360 
2361 
2362  /* One or TWO material no texture shaders - one material, choose between
2363  Phong shading (slower) or Gouraud shading (faster). */
2364 
2365  if (DESIRE(whichOne.base,SHADINGSTYLE_PHONG)) {
2366  doThis = (DESIRE(whichOne.base,MATERIAL_APPEARANCE_SHADER)) ||
2367  (DESIRE(whichOne.base,TWO_MATERIAL_APPEARANCE_SHADER));
2368  } else {
2369  doThis = DESIRE(whichOne.base,TWO_MATERIAL_APPEARANCE_SHADER);
2370  }
2371 
2372  if (doThis) {
2373  vertexSource[vertexNormPosOutput] = varyingNormPos;
2374  vertexSource[vertexNormalDeclare] = vertNormDec;
2375  vertexSource[vertexNormPosCalculation] = vertNormPosCalc;
2376 
2377  fragmentSource[fragmentLightDefines] = lightDefines0;
2378  fragmentSource[fragmentOneColourDeclare] = vertOneMatDec;
2379  fragmentSource[fragmentBackColourDeclare] = vertBackMatDec;
2380  fragmentSource[fragmentNormPosDeclare] = varyingNormPos;
2381  fragmentSource[fragmentADSLLightModel] = ADSLLightModel0;
2382  fragmentSource[fragmentADSLAssign] = fragADSLAss;
2383 
2384  }
2385 
2386 
2387  /* TWO_MATERIAL_APPEARANCE_SHADER - this does not crop up
2388  that often, so just use the PHONG shader. */
2389  didADSLmaterial = false;
2390  if((DESIRE(whichOne.base,MATERIAL_APPEARANCE_SHADER)) && (!DESIRE(whichOne.base,SHADINGSTYLE_PHONG))) {
2391  vertexSource[vertexNormalDeclare] = vertNormDec;
2392  vertexSource[vertexLightDefines] = lightDefines0;
2393  vertexSource[vertexOneMaterialDeclare] = vertOneMatDec;
2394  vertexSource[vertFrontColourDeclare] = varyingFrontColour;
2395  vertexSource[vertexNormPosCalculation] = vertNormPosCalc;
2396  vertexSource[vertexNormPosOutput] = vecNormPos;
2397  vertexSource[vertexLightingEquation] = ADSLLightModel0;
2398  vertexSource[vertexBackMaterialDeclare] = vertBackMatDec;
2399  vertexSource[vertexADSLCalculation] = vertADSLCalc;
2400  didADSLmaterial = true;
2401  fragmentSource[fragmentOneColourDeclare] = varyingFrontColour;
2402  fragmentSource[fragmentOneColourAssign] = fragFrontColAss;
2403  }
2404 
2405 
2406  if DESIRE(whichOne.base,HAVE_LINEPOINTS_APPEARANCE) {
2407  vertexSource[vertexLightDefines] = lightDefines0;
2408  vertexSource[vertFrontColourDeclare] = varyingFrontColour;
2409  vertexSource[vertexOneMaterialDeclare] = vertOneMatDec;
2410 
2411  #if defined (GL_ES_VERSION_2_0)
2412  vertexSource[vertexPointSizeDeclare] = pointSizeDeclare;
2413  vertexSource[vertexPointSizeAssign] = pointSizeAss;
2414  #endif
2415 
2416  vertexSource[vertexOneMaterialCalculation] = vertEmissionOnlyColourAss;
2417  fragmentSource[fragmentSimpleColourDeclare] = varyingFrontColour;
2418  fragmentSource[fragmentSimpleColourAssign] = fragSimColAss;
2419  }
2420 
2421 
2422  /* texturing - MULTI_TEX builds on ONE_TEX */
2423  if (DESIRE(whichOne.base,ONE_TEX_APPEARANCE_SHADER) ||
2424  DESIRE(whichOne.base,HAVE_TEXTURECOORDINATEGENERATOR) ||
2425  DESIRE(whichOne.base,HAVE_CUBEMAP_TEXTURE) ||
2426  DESIRE(whichOne.base,MULTI_TEX_APPEARANCE_SHADER)) {
2427  vertexSource[vertexTexCoordInputDeclare] = vertTexCoordDec;
2428  vertexSource[vertexTexCoordOutputDeclare] = varyingTexCoord;
2429  vertexSource[vertexTextureMatrixDeclare] = vertTexMatrixDec;
2430  vertexSource[vertexSingleTextureCalculation] = vertSingTexCalc;
2431  if(didADSLmaterial)
2432  vertexSource[vertexADSLCalculation] = vertADSLCalc0; //over-ride material diffuseColor with texture
2433 
2434  fragmentSource[fragmentTexCoordDeclare] = varyingTexCoord;
2435  fragmentSource[fragmentTex0Declare] = fragTex0Dec;
2436  fragmentSource[fragmentTextureAssign] = fragSingTexAss;
2437  }
2438 
2439  /* Cubemaps - do not multi-texture these yet */
2440  if (DESIRE(whichOne.base,HAVE_CUBEMAP_TEXTURE)) {
2441  vertexSource[vertexSingleTextureCalculation] = vertSingTexCubeCalc;
2442 
2443  fragmentSource[fragmentTex0Declare] = fragTex0CubeDec;
2444  fragmentSource[fragmentTextureAssign] = fragSingTexCubeAss;
2445  }
2446 
2447  /* MULTI_TEX builds on ONE_TEX */
2448  if DESIRE(whichOne.base,MULTI_TEX_APPEARANCE_SHADER) {
2449  /* we have to do the material params, in case we need to
2450  modulate/play with this. */
2451 
2452  vertexSource[vertexOneMaterialDeclare] = vertOneMatDec;
2453  vertexSource[vertexLightDefines] = lightDefines0;
2454  vertexSource[vertexNormPosCalculation] = vertNormPosCalc;
2455  vertexSource[vertexNormPosOutput] = vecNormPos;
2456  vertexSource[vertexLightingEquation] = ADSLLightModel0;
2457  vertexSource[vertexBackMaterialDeclare] = vertBackMatDec;
2458 
2459  fragmentSource[fragmentMultiTexDefines]= fragMultiTexUniforms;
2460  fragmentSource[fragmentMultiTexDeclare] = fragMultiTexDef;
2461  fragmentSource[fragmentTex0Declare] = fragTex0Dec;
2462  fragmentSource[fragmentMultiTexModel] = fragMulTexFunc;
2463  fragmentSource[fragmentTextureAssign] = fragMulTexCalc;
2464  }
2465 
2466  /* TextureCoordinateGenerator - do calcs in Vertex, fragment like one texture */
2467  if DESIRE(whichOne.base,HAVE_TEXTURECOORDINATEGENERATOR) {
2468  /* the vertex single texture calculation is different from normal single texture */
2469  /* pass in the type of generator, and do the calculations */
2470  vertexSource[vertexTextureMatrixDeclare] = vertTexCoordGenDec;
2471  vertexSource[vertexSingleTextureCalculation] = sphEnvMapCalc;
2472 
2473  vertexSource[vertexTCGTDefines] = fragTCGTDefs;
2474 
2475  }
2476 
2477  if DESIRE(whichOne.base,FILL_PROPERTIES_SHADER) {
2478  /* just add on top of the other shaders the fill properties "stuff" */
2479 
2480  vertexSource[vertexHatchPositionDeclare] = varyingHatchPosition;
2481  vertexSource[vertexHatchPositionCalculation] = vertHatchPosCalc;
2482 
2483  fragmentSource[fragmentFillPropDefines] = fillPropDefines;
2484  fragmentSource[fragmentHatchPositionDeclare] = varyingHatchPosition;
2485  fragmentSource[fragmentFillPropModel] = fragFillPropFunc;
2486  fragmentSource[fragmentFillPropAssign] = fragFillPropCalc;
2487  }
2488 
2489  } else { // user defined shaders
2490 
2491  if (whichOne.usershaders) { // >= USER_DEFINED_SHADER_START) {
2492  int me = 0;
2493  ppOpenGL_Utils p;
2494  ttglobal tg = gglobal();
2495  p = (ppOpenGL_Utils)tg->OpenGL_Utils.prv;
2496 
2497  //me = (whichOne / USER_DEFINED_SHADER_START) -1;
2498  me = whichOne.usershaders;
2499  //ConsoleMessage ("HAVE USER DEFINED SHADER %x",whichOne);
2500 
2501  // add the following:
2502  // this has both Vertex manipulations, and lighting, etc.
2503  // #define HEADLIGHT_LIGHT (MAX_LIGHTS-1)\n
2504  vertexSource[vertexMainStart] = " \n \
2505  #define HEADLIGHT_LIGHT 0\n \
2506  #define ftransform() (fw_ProjectionMatrix*fw_ModelViewMatrix*fw_Vertex)\n \
2507  #define gl_ModelViewProjectionMatrix (fw_ProjectionMatrix*fw_ModelViewMatrix)\n \
2508  #define gl_NormalMatrix fw_NormalMatrix\n \
2509  #define gl_ProjectionMatrix fw_ProjectionMatrix \n\
2510  #define gl_ModelViewMatrix fw_ModelViewMatrix \n\
2511  #define fw_TextureMatrix fw_TextureMatrix0 \n\
2512  #define gl_TextureMatrix fw_TextureMatrix0 \n\
2513  #define gl_Vertex fw_Vertex \n \
2514  #define gl_Normal fw_Normal\n \
2515  #define gl_Texture_unit0 fw_Texture_unit0\n \
2516  #define gl_MultiTexCoord0 fw_MultiTexCoord0\n \
2517  #define gl_Texture_unit1 fw_Texture_unit1\n \
2518  #define gl_MultiTexCoord1 fw_MultiTexCoord1\n \
2519  #define gl_Texture_unit2 fw_Texture_unit2\n \
2520  #define gl_MultiTexCoord2 fw_MultiTexCoord2\n \
2521  #define gl_LightSource fw_LightSource\n ";
2522 
2523  // copy over the same defines, but for the fragment shader.
2524  // Some GLSL compilers will complain about the "fttransform()"
2525  // definition if defined in a Fragment shader, so we judiciously
2526  // copy over things that are fragment-only.
2527 
2528  // #define HEADLIGHT_LIGHT (MAX_LIGHTS-1)\n
2529  fragmentSource[fragmentMainStart] = " \
2530  #define HEADLIGHT_LIGHT 0\n \
2531  #define gl_NormalMatrix fw_NormalMatrix\n \
2532  #define gl_Normal fw_Normal\n \
2533  #define gl_LightSource fw_LightSource\n ";
2534 
2535 
2536 
2537 
2538  vertexSource[vertexLightDefines] = lightDefines0;
2539  vertexSource[vertexSimpleColourDeclare] = vertSimColDec;
2540  vertexSource[vertFrontColourDeclare] = varyingFrontColour;
2541 
2542 
2543 
2544  vertexSource[vertexNormalDeclare] = vertNormDec;
2545  fragmentSource[fragmentLightDefines] = lightDefines0;
2546  //ConsoleMessage ("sources here for %d are %p and %p", me, p->userDefinedVertexShader[me], p->userDefinedFragmentShader[me]);
2547 
2548  if ((p->userDefinedVertexShader[me] == NULL) || (p->userDefinedFragmentShader[me]==NULL)) {
2549  ConsoleMessage ("no Shader Source found for user defined shaders...");
2550  return false;
2551 
2552  }
2553  fragmentSource[fragmentUserDefinedInput] = p->userDefinedFragmentShader[me];
2554  vertexSource[vertexUserDefinedInput] = p->userDefinedVertexShader[me];
2555 
2556  }
2557  }
2558 
2559 //#define VERBOSE 1
2560  #ifdef VERBOSE
2561  /* print out the vertex source here */
2562  {
2563  vertexShaderResources_t x1;
2564  fragmentShaderResources_t x2;
2565  int i;
2566 
2567  ConsoleMessage ("Vertex source:\n");
2568  for (x1=vertexGLSLVersion; x1<vertexEndMarker; x1++) {
2569  if (strlen(vertexSource[x1])>0)
2570  ConsoleMessage("%s",vertexSource[x1]);
2571  }
2572  ConsoleMessage("Fragment Source:\n");
2573  i=0;
2574  for (x2=fragmentGLSLVersion; x2<fragmentEndMarker; x2++) {
2575  if (strlen(fragmentSource[x2])>0)
2576  ConsoleMessage("%s",fragmentSource[x2]);
2577  }
2578  }
2579  #endif //VERBOSE
2580 //#undef VERBOSE
2581  return TRUE;
2582 }
2583 #undef VERBOSE
2584 
2585 //see Composite_Shading.c for CastlePlugs details.
2586 int getSpecificShaderSourceCastlePlugs (const GLchar **vertexSource, const GLchar **fragmentSource, shaderflagsstruct whichOne);
2587 int getSpecificShaderSourceVolume (const GLchar **vertexSource, const GLchar **fragmentSource, shaderflagsstruct whichOne);
2588 static int getSpecificShaderSource (const GLchar *vertexSource[vertexEndMarker], const GLchar *fragmentSource[fragmentEndMarker],
2589  shaderflagsstruct whichOne) {
2590  int iret, userDefined, usingCastlePlugs = 1;
2591  userDefined = whichOne.usershaders ? TRUE : FALSE;
2592 
2593  if(usingCastlePlugs && !userDefined) { // && !DESIRE(whichOne,SHADINGSTYLE_PHONG)) {
2594  //new Aug 2016 castle plugs
2595  if(whichOne.volume)
2596  iret = getSpecificShaderSourceVolume(vertexSource, fragmentSource, whichOne);
2597  else
2598  iret = getSpecificShaderSourceCastlePlugs(vertexSource, fragmentSource, whichOne);
2599  }else{
2600  iret = getSpecificShaderSourceOriginal(vertexSource, fragmentSource, whichOne);
2601  }
2602  return iret;
2603 }
2604 
2605 
2606 static void makeAndCompileShader(struct shaderTableEntry *me) {
2607 
2608  GLint success;
2609  GLuint myVertexShader = 0;
2610  GLuint myFragmentShader= 0;
2611 
2612  GLuint myProg = 0;
2613  s_shader_capabilities_t *myShader = me->myCapabilities;
2614  const GLchar *vertexSource[vertexEndMarker];
2615  const GLchar *fragmentSource[fragmentEndMarker];
2616  vertexShaderResources_t x1;
2617  fragmentShaderResources_t x2;
2618 
2619 
2620 #ifdef VERBOSE
2621  ConsoleMessage ("makeAndCompileShader called");
2622 #endif //VERBOSE
2623 #undef VERBOSE
2624 
2625  /* initialize shader sources to blank strings, later we'll fill it in */
2626  for (x1=vertexGLSLVersion; x1<vertexEndMarker; x1++)
2627  vertexSource[x1] = "";
2628  for (x2=fragmentGLSLVersion; x2<fragmentEndMarker; x2++)
2629  fragmentSource[x2] = "";
2630 
2631 
2632  /* pointerize this */
2633  myProg = glCreateProgram(); /* CREATE_PROGRAM */
2634  (*myShader).myShaderProgram = myProg;
2635 
2636  /* assume the worst... */
2637  (*myShader).compiledOK = FALSE;
2638 
2639  /* we put the sources in 2 formats, allows for differing GL/GLES prefixes */
2640  if (!getSpecificShaderSource(vertexSource, fragmentSource, me->whichOne)) {
2641  return;
2642  }
2643 
2644 
2645  myVertexShader = CREATE_SHADER (VERTEX_SHADER);
2646  SHADER_SOURCE(myVertexShader, vertexEndMarker, ((const GLchar **)vertexSource), NULL);
2647  COMPILE_SHADER(myVertexShader);
2648  GET_SHADER_INFO(myVertexShader, COMPILE_STATUS, &success);
2649  if (!success) {
2650  shaderErrorLog(myVertexShader,"VERTEX");
2651  } else {
2652 
2653  ATTACH_SHADER(myProg, myVertexShader);
2654  }
2655 
2656  /* get Fragment shader */
2657  myFragmentShader = CREATE_SHADER (FRAGMENT_SHADER);
2658  SHADER_SOURCE(myFragmentShader, fragmentEndMarker, (const GLchar **) fragmentSource, NULL);
2659  COMPILE_SHADER(myFragmentShader);
2660  GET_SHADER_INFO(myFragmentShader, COMPILE_STATUS, &success);
2661  if (!success) {
2662  shaderErrorLog(myFragmentShader,"FRAGMENT");
2663  } else {
2664  ATTACH_SHADER(myProg, myFragmentShader);
2665  }
2666 
2667  LINK_SHADER(myProg);
2668 
2669  glGetProgramiv(myProg,GL_LINK_STATUS, &success);
2670  (*myShader).compiledOK = (success == GL_TRUE);
2671 
2672  getShaderCommonInterfaces(myShader);
2673 }
2674 static void getShaderCommonInterfaces (s_shader_capabilities_t *me) {
2675  GLuint myProg = me->myShaderProgram;
2676  int i;
2677 
2678 
2679  #ifdef SHADERVERBOSE
2680  {
2681  GLsizei count;
2682  GLuint shaders[10];
2683  GLint xxx[10];
2684  int i;
2685  GLchar sl[3000];
2686 
2687 
2688  printf ("getShaderCommonInterfaces, I am program %d\n",myProg);
2689 
2690  if (glIsProgram(myProg))
2691  printf ("getShaderCommonInterfaces, %d is a program\n",myProg);
2692  else
2693  printf ("hmmm - it is not a program!\n");
2694  glGetAttachedShaders(myProg,10,&count,shaders);
2695  printf ("got %d attached shaders, they are: \n",count);
2696  for (i=0; i<count; i++) {
2697  GLsizei len;
2698 
2699  printf ("%d\n",shaders[i]);
2700  glGetShaderSource(shaders[i],3000,&len,sl);
2701  printf ("len %d\n",len);
2702  printf ("sl: %s\n",sl);
2703  }
2704  glGetProgramiv(myProg,GL_INFO_LOG_LENGTH, xxx); printf ("GL_INFO_LOG_LENGTH_STATUS %d\n",xxx[0]);
2705  glGetProgramiv(myProg,GL_LINK_STATUS, xxx); printf ("GL_LINK_STATUS %d\n",xxx[0]);
2706  glGetProgramiv(myProg,GL_VALIDATE_STATUS, xxx); printf ("GL_VALIDATE_STATUS %d\n",xxx[0]);
2707  glGetProgramiv(myProg,GL_ACTIVE_ATTRIBUTES, xxx); printf ("GL_ACTIVE_ATTRIBUTES %d\n",xxx[0]);
2708  glGetProgramiv(myProg,GL_ACTIVE_UNIFORMS, xxx); printf ("GL_ACTIVE_UNIFORMS %d\n",xxx[0]);
2709 
2710  glGetProgramiv(myProg,GL_INFO_LOG_LENGTH, xxx);
2711  if (xxx[0] != 0) {
2712  #define MAX_INFO_LOG_SIZE 512
2713  GLchar infoLog[MAX_INFO_LOG_SIZE];
2714  glGetProgramInfoLog(myProg, MAX_INFO_LOG_SIZE, NULL, infoLog);
2715  printf ("log: %s\n",infoLog);
2716  }
2717  }
2718  #endif /* DEBUG */
2719 
2720 
2721  me->myMaterialEmission = GET_UNIFORM(myProg,"fw_FrontMaterial.emission");
2722  me->myMaterialDiffuse = GET_UNIFORM(myProg,"fw_FrontMaterial.diffuse");
2723  me->myMaterialShininess = GET_UNIFORM(myProg,"fw_FrontMaterial.shininess");
2724  me->myMaterialAmbient = GET_UNIFORM(myProg,"fw_FrontMaterial.ambient");
2725  me->myMaterialSpecular = GET_UNIFORM(myProg,"fw_FrontMaterial.specular");
2726 
2727  me->myMaterialBackEmission = GET_UNIFORM(myProg,"fw_BackMaterial.emission");
2728  me->myMaterialBackDiffuse = GET_UNIFORM(myProg,"fw_BackMaterial.diffuse");
2729  me->myMaterialBackShininess = GET_UNIFORM(myProg,"fw_BackMaterial.shininess");
2730  me->myMaterialBackAmbient = GET_UNIFORM(myProg,"fw_BackMaterial.ambient");
2731  me->myMaterialBackSpecular = GET_UNIFORM(myProg,"fw_BackMaterial.specular");
2732 
2733  //me->lightState = GET_UNIFORM(myProg,"lightState");
2734  //me->lightType = GET_UNIFORM(myProg,"lightType");
2735  //me->lightRadius = GET_UNIFORM(myProg,"lightRadius");
2736  me->lightcount = GET_UNIFORM(myProg,"lightcount");
2737 
2738  /* get lights in a more normal OpenGL GLSL format */
2739 
2740  /*
2741  struct gl_LightSourceParameters
2742  {
2743  vec4 ambient; // Aclarri
2744  vec4 diffuse; // Dcli
2745  vec4 specular; // Scli
2746  vec4 position; // Ppli
2747  vec4 halfVector; // Derived: Hi
2748  vec4 spotDirection; // Sdli
2749  float spotExponent; // Srli
2750  float spotCutoff; // Crli
2751  float spotCosCutoff; // Derived: cos(Crli)
2752  vec3 Attenuations (const,lin,quad)
2753  //float constantAttenuation; // K0
2754  //float linearAttenuation; // K1
2755  //float quadraticAttenuation;// K2
2756  float lightRadius;
2757  int lightType;
2758  };
2759 
2760 
2761  uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];
2762  */
2763  {
2764  //using lighsource arrays - see shader
2765  char uniformName[100];
2766  me->haveLightInShader = false;
2767 #ifdef USING_SHADER_LIGHT_ARRAY_METHOD
2768  //char* sndx;
2769  for (i = 0; i<MAX_LIGHTS; i++) {
2770  char* sndx;
2771  /* go through and modify the array for each variable */
2772  strcpy(uniformName, "lightambient[0]");
2773  sndx = strstr(uniformName, "[");
2774  sndx[1] = '0' + i;
2775  me->lightAmbient[i] = GET_UNIFORM(myProg, uniformName);
2776 
2777  //ConsoleMessage ("light Uniform test for %d is %s, %d",i,uniformName,me->lightAmbient[i]);
2778 
2779  strcpy(uniformName, "lightdiffuse[0]");
2780  sndx = strstr(uniformName, "[");
2781  sndx[1] = '0' + i;
2782  me->lightDiffuse[i] = GET_UNIFORM(myProg, uniformName);
2783  //ConsoleMessage ("light Uniform test for %d is %s, %d",i,uniformName,me->lightDiffuse[i]);
2784 
2785 
2786  strcpy(uniformName, "lightspecular[0]");
2787  sndx = strstr(uniformName, "[");
2788  sndx[1] = '0' + i;
2789  me->lightSpecular[i] = GET_UNIFORM(myProg, uniformName);
2790  //ConsoleMessage ("light Uniform test for %d is %s, %d",i,uniformName,me->lightSpecular[i]);
2791 
2792 
2793  strcpy(uniformName, "lightposition[0]");
2794  sndx = strstr(uniformName, "[");
2795  sndx[1] = '0' + i;
2796  me->lightPosition[i] = GET_UNIFORM(myProg, uniformName);
2797  //ConsoleMessage ("light Uniform test for %d is %s, %d",i,uniformName,me->lightPosition[i]);
2798 
2799 
2800  // flag used to determine if we have to send light position info to this shader
2801  if (me->lightPosition[i] != -1) me->haveLightInShader = true;
2802 
2803  strcpy(uniformName, "lightspotDirection[0]");
2804  sndx = strstr(uniformName, "[");
2805  sndx[1] = '0' + i;
2806  me->lightSpotDir[i] = GET_UNIFORM(myProg, uniformName);
2807  //ConsoleMessage ("light Uniform test for %d is %s, %d",i,uniformName,me->lightSpotDir[i]);
2808 
2809 
2810  strcpy(uniformName, "lightspotExponent[0]");
2811  sndx = strstr(uniformName, "[");
2812  sndx[1] = '0' + i;
2813  me->lightSpotBeamWidth[i] = GET_UNIFORM(myProg, uniformName);
2814  //ConsoleMessage ("light Uniform test for %d is %s, %d",i,uniformName,me->lightSpotBeamWidth[i]);
2815 
2816 
2817  strcpy(uniformName, "lightspotCutoff[0]");
2818  sndx = strstr(uniformName, "[");
2819  sndx[1] = '0' + i;
2820  me->lightSpotCutoffAngle[i] = GET_UNIFORM(myProg, uniformName);
2821  //ConsoleMessage ("light Uniform test for %d is %s, %d",i,uniformName,me->lightSpotCutoffAngle[i]);
2822 
2823 
2824  strcpy(uniformName, "lightAttenuations[0]");
2825  sndx = strstr(uniformName, "[");
2826  sndx[1] = '0' + i;
2827  me->lightAtten[i] = GET_UNIFORM(myProg, uniformName);
2828 
2829  strcpy(uniformName, "lightRadius[0]");
2830  sndx = strstr(uniformName, "[");
2831  sndx[1] = '0' + i;
2832  me->lightRadius[i] = GET_UNIFORM(myProg, uniformName);
2833  //ConsoleMessage ("light Uniform test for %d is %s, %d",i,uniformName,me->lightQuadAtten[i]);
2834 
2835  }
2836 
2837 #else //USING_SHADER_LIGHT_ARRAY_METHOD
2838  strcpy(uniformName,"fw_LightSource[0].");
2839  for (i=0; i<MAX_LIGHTS; i++) {
2840  /* go through and modify the array for each variable */
2841  uniformName[15] = '0' + i;
2842 
2843  strcpy(&uniformName[18],"ambient");
2844 
2845  //ConsoleMessage ("have uniform name request :%s:",uniformName);
2846  me->lightAmbient[i] = GET_UNIFORM(myProg,uniformName);
2847 
2848  //ConsoleMessage ("light Uniform test for %d is %s, %d",i,uniformName,me->lightAmbient[i]);
2849 
2850  strcpy(&uniformName[18],"diffuse");
2851  me->lightDiffuse[i] = GET_UNIFORM(myProg,uniformName);
2852  //ConsoleMessage ("light Uniform test for %d is %s, %d",i,uniformName,me->lightDiffuse[i]);
2853 
2854 
2855  strcpy(&uniformName[18],"specular");
2856  me->lightSpecular[i] = GET_UNIFORM(myProg,uniformName);
2857  //ConsoleMessage ("light Uniform test for %d is %s, %d",i,uniformName,me->lightSpecular[i]);
2858 
2859 
2860  strcpy(&uniformName[18],"position");
2861  me->lightPosition[i] = GET_UNIFORM(myProg,uniformName);
2862  //ConsoleMessage ("light Uniform test for %d is %s, %d",i,uniformName,me->lightPosition[i]);
2863 
2864 
2865  // flag used to determine if we have to send light position info to this shader
2866  if (me->lightPosition[i] != -1) me->haveLightInShader = true;
2867 
2868  strcpy(&uniformName[18],"spotDirection");
2869  me->lightSpotDir[i] = GET_UNIFORM(myProg,uniformName);
2870  //ConsoleMessage ("light Uniform test for %d is %s, %d",i,uniformName,me->lightSpotDir[i]);
2871 
2872 
2873  //strcpy(&uniformName[18],"spotExponent");
2874  strcpy(&uniformName[18],"spotBeamWidth");
2875  me->lightSpotBeamWidth[i] = GET_UNIFORM(myProg,uniformName);
2876  //ConsoleMessage ("light Uniform test for %d is %s, %d",i,uniformName,me->lightSpotBeamWidth[i]);
2877 
2878 
2879  strcpy(&uniformName[18],"spotCutoff");
2880  me->lightSpotCutoffAngle[i] = GET_UNIFORM(myProg,uniformName);
2881  //ConsoleMessage ("light Uniform test for %d is %s, %d",i,uniformName,me->lightSpotCutoffAngle[i]);
2882 
2883 
2884  strcpy(&uniformName[18],"Attenuations");
2885  me->lightAtten[i] = GET_UNIFORM(myProg,uniformName);
2886 
2887  //strcpy(&uniformName[18],"constantAttenuation");
2888  //me->lightConstAtten[i] = GET_UNIFORM(myProg,uniformName);
2890  //
2891 
2892  //strcpy(&uniformName[18],"linearAttenuation");
2893  //me->lightLinAtten[i] = GET_UNIFORM(myProg,uniformName);
2895  //
2896 
2897  //strcpy(&uniformName[18],"quadraticAttenuation");
2898  //me->lightQuadAtten[i] = GET_UNIFORM(myProg,uniformName);
2900 
2901  strcpy(&uniformName[18],"lightRadius");
2902  me->lightRadius[i] = GET_UNIFORM(myProg,uniformName);
2903  //ConsoleMessage ("light Uniform test for %d is %s, %d",i,uniformName,me->lightQuadAtten[i]);
2904 
2905  //strcpy(&uniformName[18],"lightType");
2906  //me->lightType[i] = GET_UNIFORM(myProg,uniformName);
2907  //ConsoleMessage ("light Uniform test for %d is %s, %d",i,uniformName,me->lightQuadAtten[i]);
2908 
2909  }
2910 #endif // USING_SHADER_LIGHT_ARRAY_METHOD
2911  strcpy(uniformName,"lightType[0]");
2912  for (i = 0; i < MAX_LIGHTS; i++) {
2913  /* go through and modify the array for each variable */
2914  uniformName[10] = '0' + i;
2915  me->lightType[i] = GET_UNIFORM(myProg, uniformName);
2916  }
2917  }
2918 
2919  //if (me->haveLightInShader) ConsoleMessage ("this shader HAS lightfields");
2920 
2921  me->ModelViewMatrix = GET_UNIFORM(myProg,"fw_ModelViewMatrix");
2922  me->ProjectionMatrix = GET_UNIFORM(myProg,"fw_ProjectionMatrix");
2923  me->NormalMatrix = GET_UNIFORM(myProg,"fw_NormalMatrix");
2924  me->ModelViewInverseMatrix = GET_UNIFORM(myProg,"fw_ModelViewInverseMatrix");
2925  //for (i=0; i<MAX_MULTITEXTURE; i++) {
2926  me->TextureMatrix[0] = GET_UNIFORM(myProg,"fw_TextureMatrix0");
2927  me->TextureMatrix[1] = GET_UNIFORM(myProg,"fw_TextureMatrix1");
2928  me->TextureMatrix[2] = GET_UNIFORM(myProg,"fw_TextureMatrix2");
2929  me->TextureMatrix[3] = GET_UNIFORM(myProg,"fw_TextureMatrix3");
2930 
2931  me->Vertices = GET_ATTRIB(myProg,"fw_Vertex");
2932 
2933  me->Normals = GET_ATTRIB(myProg,"fw_Normal");
2934  me->Colours = GET_ATTRIB(myProg,"fw_Color");
2935  me->FogCoords = GET_ATTRIB(myProg,"fw_FogCoords");
2936 
2937 
2938  //for (i=0; i<MAX_MULTITEXTURE; i++) {
2939  me->TexCoords[0] = GET_ATTRIB(myProg,"fw_MultiTexCoord0");
2940  me->TexCoords[1] = GET_ATTRIB(myProg,"fw_MultiTexCoord1");
2941  me->TexCoords[2] = GET_ATTRIB(myProg,"fw_MultiTexCoord2");
2942  me->TexCoords[3] = GET_ATTRIB(myProg,"fw_MultiTexCoord3");
2943 
2944 
2945  for (i=0; i<MAX_MULTITEXTURE; i++) {
2946  char line[200];
2947  sprintf (line,"fw_Texture_unit%d",i);
2948  me->TextureUnit[i]= GET_UNIFORM(myProg,line);
2949  sprintf (line,"fw_Texture_mode%d",i);
2950  me->TextureMode[i] = GET_UNIFORM(myProg,line);
2951  sprintf (line,"fw_Texture_source%d",i);
2952  me->TextureSource[i] = GET_UNIFORM(myProg,line);
2953  sprintf (line,"fw_Texture_function%d",i);
2954  me->TextureFunction[i] = GET_UNIFORM(myProg,line);
2955  //printf (" i %d tu %d mode %d\n",i,me->TextureUnit[i],me->TextureMode[i]);
2956 
2957  }
2958 
2959  me->textureCount = GET_UNIFORM(myProg,"textureCount");
2960  me->multitextureColor = GET_UNIFORM(myProg,"mt_Color");
2961  //printf ("GETUNIFORM for textureCount is %d\n",me->textureCount);
2962 
2963  //texture3D
2964  me->tex3dTiles = GET_UNIFORM(myProg,"tex3dTiles");
2965  me->tex3dUseVertex = GET_UNIFORM(myProg,"tex3dUseVertex");
2966  me->magFilter = GET_UNIFORM(myProg,"magFilter");
2967  me->repeatSTR = GET_UNIFORM(myProg,"repeatSTR");
2968 
2969 
2970  /* for FillProperties */
2971  me->myPointSize = GET_UNIFORM(myProg, "pointSize");
2972  me->hatchColour = GET_UNIFORM(myProg,"HatchColour");
2973  me->hatchPercent = GET_UNIFORM(myProg,"HatchPct");
2974  me->hatchScale = GET_UNIFORM(myProg,"HatchScale");
2975  me->filledBool = GET_UNIFORM(myProg,"filled");
2976  me->hatchedBool = GET_UNIFORM(myProg,"hatched");
2977  me->algorithm = GET_UNIFORM(myProg,"algorithm");
2978 
2979  me->fogColor = GET_UNIFORM(myProg,"fw_fogparams.fogColor");
2980  me->fogvisibilityRange = GET_UNIFORM(myProg,"fw_fogparams.visibilityRange");
2981  me->fogScale = GET_UNIFORM(myProg,"fw_fogparams.fogScale");
2982  me->fogType = GET_UNIFORM(myProg,"fw_fogparams.fogType");
2983 
2984  /* clipplane */
2985  me->clipplanes = GET_UNIFORM(myProg,"fw_clipplanes");
2986  me->nclipplanes = GET_UNIFORM(myProg,"fw_nclipplanes");
2987 
2988  /* TextureCoordinateGenerator */
2989  me->texCoordGenType = GET_UNIFORM(myProg,"fw_textureCoordGenType");
2990 
2991 
2992  #ifdef VERBOSE
2993  printf ("shader uniforms: vertex %d normal %d modelview %d projection %d\n",
2994  me->Vertices, me->Normals, me->ModelViewMatrix, me->ProjectionMatrix);
2995  printf ("hatchColour %d, hatchPercent %d",me->hatchColour, me->hatchPercent);
2996  #endif
2997 
2998 
2999 }
3000 
3001 void calculateViewingSpeed();
3002 static void handle_GeoLODRange(struct X3D_GeoLOD *node) {
3003  int oldInRange;
3004  GLDOUBLE cx,cy,cz;
3005  /* find the length of the line between the moved center and our current viewer position */
3006  getCurrentPosInModel(FALSE);
3007  calculateViewingSpeed();
3008  cx = Viewer()->currentPosInModel.x - node->__movedCoords.c[0];
3009  cy = Viewer()->currentPosInModel.y - node->__movedCoords.c[1];
3010  cz = Viewer()->currentPosInModel.z - node->__movedCoords.c[2];
3011 
3012  //printf ("geoLOD, distance between me and center is %lf\n", sqrt (cx*cx + cy*cy + cz*cz));
3013 
3014  /* try to see if we are closer than the range */
3015  oldInRange = node->__inRange;
3016 
3017  /* handle squares, as it is faster than doing square roots */
3018  if((cx*cx+cy*cy+cz*cz) > (node->range * node->range)) {
3019  node->__inRange = FALSE;
3020  } else {
3021  node->__inRange = TRUE;
3022  }
3023 
3024 
3025  if (oldInRange != node->__inRange) {
3026 
3027  #ifdef VERBOSE
3028  if (node->__inRange) printf ("TRUE: "); else printf ("FALSE: ");
3029  printf ("range changed; level %d, comparing %lf:%lf:%lf and range %lf node %u\n",
3030  node->__level, cx,cy,cz, node->range, node);
3031  #endif
3032 
3033  /* initialize the "children" field, if required */
3034  if (node->children.p == NULL) node->children.p=MALLOC(struct X3D_Node **,sizeof(struct X3D_Node *) * 4);
3035 
3036  if (node->__inRange == TRUE) {
3037  #ifdef VERBOSE
3038  printf ("GeoLOD %u level %d, inRange set to FALSE, range %lf\n",node, node->__level, node->range);
3039  #endif
3040  node->level_changed = 1;
3041  node->children.p[0] = node->__child1Node;
3042  node->children.p[1] = node->__child2Node;
3043  node->children.p[2] = node->__child3Node;
3044  node->children.p[3] = node->__child4Node;
3045  node->children.n = 4;
3046  } else {
3047  #ifdef VERBOSE
3048  printf ("GeoLOD %u level %d, inRange set to TRUE range %lf\n",node, node->__level, node->range);
3049  #endif
3050  node->level_changed = 0;
3051  node->children.n = 0;
3052  if( node->__rootUrl )
3053  {
3054  node->children.p[0] = node->__rootUrl;
3055  node->children.n = 1;
3056  }
3057  else if( node->rootNode.p && node->rootNode.p[0] )
3058  {
3059  node->children.p[0] = node->rootNode.p[0];
3060  node->children.n = 1;
3061  }
3062  }
3063  MARK_EVENT(X3D_NODE(node), offsetof (struct X3D_GeoLOD, level_changed));
3064  MARK_EVENT(X3D_NODE(node), offsetof (struct X3D_GeoLOD, children));
3065  oldInRange = X3D_GEOLOD(node)->__inRange;
3066 
3067  /* lets work out extent here */
3068  INITIALIZE_EXTENT;
3069  /* printf ("geolod range changed, initialized extent, czyzsq %4.2f rangesw %4.2f from %4.2f %4.2f %4.2f\n",
3070 cx*cx+cy*cy+cz*cz,node->range*node->range,cx,cy,cz); */
3071  update_node(X3D_NODE(node));
3072  }
3073 }
3074 
3075 #ifdef DEBUGGING_CODE
3076 /* draw a simple bounding box around an object */
3077 void drawBBOX(struct X3D_Node *node) {
3078 
3079 /* debugging */ FW_GL_COLOR3F((float)1.0,(float)0.6,(float)0.6);
3080 /* debugging */
3081 /* debugging */ /* left group */
3082 /* debugging */ glBegin(GL_LINES);
3083 /* debugging */ glVertex3d(node->EXTENT_MIN_X, node->EXTENT_MIN_Y, node->EXTENT_MIN_Z);
3084 /* debugging */ glVertex3d(node->EXTENT_MIN_X, node->EXTENT_MIN_Y, node->EXTENT_MAX_Z);
3085 /* debugging */ glEnd();
3086 /* debugging */
3087 /* debugging */ glBegin (GL_LINES);
3088 /* debugging */ glVertex3d(node->EXTENT_MIN_X, node->EXTENT_MIN_Y, node->EXTENT_MIN_Z);
3089 /* debugging */ glVertex3d(node->EXTENT_MIN_X, node->EXTENT_MAX_Y, node->EXTENT_MIN_Z);
3090 /* debugging */ glEnd();
3091 /* debugging */
3092 /* debugging */ glBegin (GL_LINES);
3093 /* debugging */ glVertex3d(node->EXTENT_MIN_X, node->EXTENT_MAX_Y, node->EXTENT_MIN_Z);
3094 /* debugging */ glVertex3d(node->EXTENT_MIN_X, node->EXTENT_MAX_Y, node->EXTENT_MAX_Z);
3095 /* debugging */ glEnd();
3096 /* debugging */
3097 /* debugging */ glBegin (GL_LINES);
3098 /* debugging */ glVertex3d(node->EXTENT_MIN_X, node->EXTENT_MIN_Y, node->EXTENT_MAX_Z);
3099 /* debugging */ glVertex3d(node->EXTENT_MIN_X, node->EXTENT_MAX_Y, node->EXTENT_MAX_Z);
3100 /* debugging */ glEnd();
3101 /* debugging */
3102 /* debugging */ /* right group */
3103 /* debugging */ glBegin (GL_LINES);
3104 /* debugging */ glVertex3d(node->EXTENT_MAX_X, node->EXTENT_MIN_Y, node->EXTENT_MIN_Z);
3105 /* debugging */ glVertex3d(node->EXTENT_MAX_X, node->EXTENT_MIN_Y, node->EXTENT_MAX_Z);
3106 /* debugging */ glEnd();
3107 /* debugging */
3108 /* debugging */ glBegin (GL_LINES);
3109 /* debugging */ glVertex3d(node->EXTENT_MAX_X, node->EXTENT_MIN_Y, node->EXTENT_MIN_Z);
3110 /* debugging */ glVertex3d(node->EXTENT_MAX_X, node->EXTENT_MAX_Y, node->EXTENT_MIN_Z);
3111 /* debugging */ glEnd();
3112 /* debugging */
3113 /* debugging */ glBegin (GL_LINES);
3114 /* debugging */ glVertex3d(node->EXTENT_MAX_X, node->EXTENT_MAX_Y, node->EXTENT_MIN_Z);
3115 /* debugging */ glVertex3d(node->EXTENT_MAX_X, node->EXTENT_MAX_Y, node->EXTENT_MAX_Z);
3116 /* debugging */ glEnd();
3117 /* debugging */
3118 /* debugging */ glBegin (GL_LINES);
3119 /* debugging */ glVertex3d(node->EXTENT_MAX_X, node->EXTENT_MIN_Y, node->EXTENT_MAX_Z);
3120 /* debugging */ glVertex3d(node->EXTENT_MAX_X, node->EXTENT_MAX_Y, node->EXTENT_MAX_Z);
3121 /* debugging */ glEnd();
3122 /* debugging */
3123 /* debugging */ /* joiners */
3124 /* debugging */ glBegin (GL_LINES);
3125 /* debugging */ glVertex3d(node->EXTENT_MIN_X, node->EXTENT_MIN_Y, node->EXTENT_MIN_Z);
3126 /* debugging */ glVertex3d(node->EXTENT_MAX_X, node->EXTENT_MIN_Y, node->EXTENT_MIN_Z);
3127 /* debugging */ glEnd();
3128 /* debugging */
3129 /* debugging */ glBegin (GL_LINES);
3130 /* debugging */ glVertex3d(node->EXTENT_MIN_X, node->EXTENT_MIN_Y, node->EXTENT_MAX_Z);
3131 /* debugging */ glVertex3d(node->EXTENT_MAX_X, node->EXTENT_MIN_Y, node->EXTENT_MAX_Z);
3132 /* debugging */ glEnd();
3133 /* debugging */
3134 /* debugging */ glBegin (GL_LINES);
3135 /* debugging */ glVertex3d(node->EXTENT_MIN_X, node->EXTENT_MAX_Y, node->EXTENT_MIN_Z);
3136 /* debugging */ glVertex3d(node->EXTENT_MAX_X, node->EXTENT_MAX_Y, node->EXTENT_MIN_Z);
3137 /* debugging */ glEnd();
3138 /* debugging */
3139 /* debugging */ glBegin (GL_LINES);
3140 /* debugging */ glVertex3d(node->EXTENT_MIN_X, node->EXTENT_MAX_Y, node->EXTENT_MAX_Z);
3141 /* debugging */ glVertex3d(node->EXTENT_MAX_X, node->EXTENT_MAX_Y, node->EXTENT_MAX_Z);
3142 /* debugging */ glEnd();
3143 
3144 }
3145 #endif //DEBUGGING_CODE
3146 
3147 static void calculateNearFarplanes(struct X3D_Node *vpnode, int layerid ) {
3148  struct point_XYZ bboxPoints[8];
3149  GLDOUBLE cfp = -DBL_MAX;
3150  GLDOUBLE cnp = DBL_MAX;
3151  GLDOUBLE MM[16];
3152  bool doingGeoSpatial = false;
3153  double bboxMovedCentreZ = 0.0;
3154  double bboxSphereRadius = 0.0;
3155 
3156 #ifdef VERBOSE
3157  int smooger = 0;
3158 #endif
3159 
3160  int ci;
3161  struct X3D_Node* rn = rootNode();
3162  ttglobal tg = gglobal();
3163  X3D_Viewer *viewer = ViewerByLayerId(layerid);
3164 
3165 
3166 
3167  #ifdef VERBOSE
3168  if (smooger == 0) {
3169  printf ("have a bound viewpoint... lets calculate our near/far planes from it \n");
3170  printf ("we are currently at %4.2f %4.2f %4.2f\n",Viewer()->currentPosInModel.x, Viewer()->currentPosInModel.y, Viewer()->currentPosInModel.z);
3171  }
3172  #endif
3173 
3174 
3175  /* verify parameters here */
3176  if ((vpnode->_nodeType != NODE_Viewpoint) &&
3177  (vpnode->_nodeType != NODE_OrthoViewpoint) &&
3178  (vpnode->_nodeType != NODE_GeoViewpoint)) {
3179  printf ("can not do this node type yet %s, for cpf\n",stringNodeType(vpnode->_nodeType));
3180  viewer->nearPlane = DEFAULT_NEARPLANE;
3181  viewer->farPlane = DEFAULT_FARPLANE;
3182  viewer->backgroundPlane = DEFAULT_BACKGROUNDPLANE;
3183  return;
3184  }
3185 
3186  if (vpnode->_nodeType == NODE_GeoViewpoint) {
3187  doingGeoSpatial = true;
3188  }
3189 
3190  if (rn == NULL) {
3191  return; /* nothing to display yet */
3192  }
3193 
3194  /* if doing GeoSpatial, use radius to view model, rather than a rotated bounding box */
3195  if (doingGeoSpatial) {
3196  if ((rn->EXTENT_MAX_X - rn->EXTENT_MIN_X) > bboxSphereRadius) {
3197  bboxSphereRadius = rn->EXTENT_MAX_X - rn->EXTENT_MIN_X;
3198  }
3199  if ((rn->EXTENT_MAX_Y - rn->EXTENT_MIN_Y) > bboxSphereRadius) {
3200  bboxSphereRadius = rn->EXTENT_MAX_Y - rn->EXTENT_MIN_Y;
3201  }
3202  if ((rn->EXTENT_MAX_Z - rn->EXTENT_MIN_Z) > bboxSphereRadius) {
3203  bboxSphereRadius = rn->EXTENT_MAX_Z - rn->EXTENT_MIN_Z;
3204  }
3205  bboxSphereRadius /=2.0; // diameter to radius
3206 
3207 #ifdef VERBOSE
3208  if (smooger == 0) {
3209  ConsoleMessage ("bboxSphereRadius %lf",bboxSphereRadius);
3210  }
3211 #endif
3212 
3213  }
3214 
3215  FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, MM);
3216 
3217  #ifdef VERBOSE
3218  printf ("rootNode extents x: %4.2f %4.2f y:%4.2f %4.2f z: %4.2f %4.2f\n",rootNode()->EXTENT_MAX_X, rootNode()->EXTENT_MIN_X,rootNode()->EXTENT_MAX_Y, rootNode()->EXTENT_MIN_Y,rootNode()->EXTENT_MAX_Z, rootNode()->EXTENT_MIN_Z);
3219  #endif
3220 
3221  /* make up 8 vertices for our bounding box, and place them within our view */
3222  moveAndRotateThisPoint(&bboxPoints[0], rn->EXTENT_MIN_X, rn->EXTENT_MIN_Y, rn->EXTENT_MIN_Z,MM);
3223  moveAndRotateThisPoint(&bboxPoints[1], rn->EXTENT_MIN_X, rn->EXTENT_MIN_Y, rn->EXTENT_MAX_Z,MM);
3224  moveAndRotateThisPoint(&bboxPoints[2], rn->EXTENT_MIN_X, rn->EXTENT_MAX_Y, rn->EXTENT_MIN_Z,MM);
3225  moveAndRotateThisPoint(&bboxPoints[3], rn->EXTENT_MIN_X, rn->EXTENT_MAX_Y, rn->EXTENT_MAX_Z,MM);
3226  moveAndRotateThisPoint(&bboxPoints[4], rn->EXTENT_MAX_X, rn->EXTENT_MIN_Y, rn->EXTENT_MIN_Z,MM);
3227  moveAndRotateThisPoint(&bboxPoints[5], rn->EXTENT_MAX_X, rn->EXTENT_MIN_Y, rn->EXTENT_MAX_Z,MM);
3228  moveAndRotateThisPoint(&bboxPoints[6], rn->EXTENT_MAX_X, rn->EXTENT_MAX_Y, rn->EXTENT_MIN_Z,MM);
3229  moveAndRotateThisPoint(&bboxPoints[7], rn->EXTENT_MAX_X, rn->EXTENT_MAX_Y, rn->EXTENT_MAX_Z,MM);
3230 
3231 
3232 
3233  for (ci=0; ci<8; ci++) {
3234  bboxMovedCentreZ += bboxPoints[ci].z;
3235 
3236  #ifdef XXVERBOSE
3237  if (smooger == 0)
3238  printf ("moved bbox node %d is %4.2f %4.2f %4.2f\n",ci,bboxPoints[ci].x, bboxPoints[ci].y, bboxPoints[ci].z);
3239  #endif
3240 
3241  if (!doingGeoSpatial) {
3242  if (-(bboxPoints[ci].z) > cfp) cfp = -(bboxPoints[ci].z);
3243  if (-(bboxPoints[ci].z) < cnp) cnp = -(bboxPoints[ci].z);
3244  }
3245  }
3246 
3247  bboxMovedCentreZ /= 8.0; // average of 8 z values from bbox
3248 
3249  if (doingGeoSpatial) {
3250  cnp = -bboxMovedCentreZ - bboxSphereRadius;
3251  cfp = -bboxMovedCentreZ; // + bboxSphereRadius;
3252  }
3253 
3254 #ifdef VERBOSE
3255  if (smooger==0) {
3256  ConsoleMessage ("centre of bbox is %lf Z away",bboxMovedCentreZ);
3257  ConsoleMessage ("bboxMovedCentreZ minus bboxRadius %lf",-bboxMovedCentreZ - bboxSphereRadius);
3258  }
3259 #endif
3260 
3261  /* lets bound check here, both must be positive, and farPlane more than DEFAULT_NEARPLANE */
3262  /* because we may be navigating towards the shapes, we give the nearPlane a bit of room, otherwise
3263  we might miss part of the geometry that comes closest to us */
3264  cnp = cnp/2.0;
3265  if (cnp<DEFAULT_NEARPLANE) cnp = DEFAULT_NEARPLANE;
3266 
3267  if (cfp<1.0) cfp = 1.0;
3268  /* if we are moving, or if we have something with zero depth, floating point calculation errors could
3269  give us a geometry that is at (or, over) the far plane. Eg, tests/49.wrl, where we have Text nodes,
3270  can give us this issue; so lets give us a bit of leeway here, too */
3271  cfp *= 1.25;
3272 
3273 
3274  #ifdef VERBOSE
3275  if (smooger == 0) {
3276 
3277  printf ("cnp %lf cfp before leaving room for Background %lf\n",cnp,cfp);
3278  //cnp = 0.1; cfp = 75345215.0 * 2.0;
3279  }
3280 #endif
3281 
3282  /* do we have a GeoViewpoint, and is the near plane about zero? */
3283  /* we CAN have the issue if we have the world in an AABB, and we have one of the */
3284  /* corners of the AABB behind us; the near plane will be <1, but the surface */
3285  /* will still be really far away */
3286  /* In this case, we try and use the elevation to give us a hand */
3287  if ((cnp<1.0) && (vpnode->_nodeType == NODE_GeoViewpoint)) {
3288 #ifdef VERBOSE
3289  cnp = Viewer()->currentPosInModel.z/16.0;
3290  if (smooger == 0) {
3291  ConsoleMessage ("vp height %lf moved height %lf posinModel %f",X3D_GEOVIEWPOINT(vpnode)->position.c[2],
3292  X3D_GEOVIEWPOINT(vpnode)->__movedPosition.c[2],Viewer()->currentPosInModel.z);
3293  smooger ++; if (smooger == 100) smooger = 0;
3294  }
3295 #endif
3296 #undef VERBOSE
3297 
3298  }
3299 
3300  /* lets use these values; leave room for a Background or TextureBackground node here */
3301  viewer->nearPlane = min(cnp,DEFAULT_NEARPLANE);
3302  /* backgroundPlane goes between the farthest geometry, and the farPlane */
3303  if (vectorSize(getActiveBindableStacks(tg)->background)!= 0) {
3304  viewer->farPlane = max(cfp * 10.0,DEFAULT_FARPLANE);
3305  viewer->backgroundPlane = max(cfp*5.0,DEFAULT_BACKGROUNDPLANE);
3306  } else {
3307  viewer->farPlane = max(cfp,DEFAULT_FARPLANE);
3308  viewer->backgroundPlane = max(cfp,DEFAULT_BACKGROUNDPLANE); /* just set it to something */
3309  }
3310 }
3311 
3312 void doglClearColor() {
3313  ppOpenGL_Utils p;
3314  ttglobal tg = gglobal();
3315  p = (ppOpenGL_Utils)tg->OpenGL_Utils.prv;
3316  FW_GL_CLEAR_COLOR(p->cc_red, p->cc_green, p->cc_blue, p->cc_alpha);
3317  tg->OpenGL_Utils.cc_changed = FALSE;
3318 }
3319 
3320 
3321 
3322 
3323 
3324 
3325 void clear_shader_table()
3326 {
3327  /* clearing the shader table forces the shaders to be re-lego-assembled and compiled
3328  - useful for switching anaglyph on/off (a different fragEnd pixel shader is used)
3329  - used in fwl_initialize_GL()
3330  */
3331  ppOpenGL_Utils p;
3332  ttglobal tg = gglobal();
3333  p = (ppOpenGL_Utils)tg->OpenGL_Utils.prv;
3334 
3335  if (p->myShaderTable != NULL) {
3336  int i;
3337 
3338  for (i=0; i<vectorSize(p->myShaderTable); i++) {
3339  struct shaderTableEntry *me = vector_get(struct shaderTableEntry *,p->myShaderTable, i);
3340  FREE_IF_NZ(me);
3341  }
3342  deleteVector (struct shaderTableEntry *,p->myShaderTable);
3343  p->myShaderTable = newVector(struct shaderTableEntry *, 8);
3344 
3345  }
3346 }
3350 bool fwl_initialize_GL()
3351 {
3352  char blankTexture[] = {0x40, 0x40, 0x40, 0xFF};
3353  float gl_linewidth;
3354  ppOpenGL_Utils p;
3355  ttglobal tg = gglobal();
3356  p = (ppOpenGL_Utils)tg->OpenGL_Utils.prv;
3357 
3358  PRINT_GL_ERROR_IF_ANY("fwl_initialize_GL start 1");
3359  initialize_rdr_caps();
3360 
3361  PRINT_GL_ERROR_IF_ANY("fwl_initialize_GL start 3");
3362 
3363  /* lets make sure everything is sync'd up */
3364 
3365 #if KEEP_FV_INLIB
3366 #if defined(TARGET_X11) || defined(TARGET_MOTIF)
3367  XFlush(Xdpy);
3368 #endif
3369 #endif /* KEEP_FV_INLIB */
3370 
3371 
3372  PRINT_GL_ERROR_IF_ANY("fwl_initialize_GL start 4");
3373 
3374  FW_GL_MATRIX_MODE(GL_PROJECTION);
3375  FW_GL_LOAD_IDENTITY();
3376  FW_GL_MATRIX_MODE(GL_MODELVIEW);
3377 
3378  PRINT_GL_ERROR_IF_ANY("fwl_initialize_GL start 6");
3379 
3380  FW_GL_CLEAR_COLOR(p->cc_red, p->cc_green, p->cc_blue, p->cc_alpha);
3381 
3382  PRINT_GL_ERROR_IF_ANY("fwl_initialize_GL start 7");
3383 
3384  PRINT_GL_ERROR_IF_ANY("fwl_initialize_GL start 8");
3385 
3386 
3387  FW_GL_DEPTHFUNC(GL_LEQUAL);
3388  glEnable(GL_DEPTH_TEST);
3389 
3390  PRINT_GL_ERROR_IF_ANY("fwl_initialize_GL start 9");
3391 
3392  gl_linewidth = gglobal()->Mainloop.gl_linewidth;
3393 
3394  // dp pointSize in shaders on more modern OpenGL renderings
3395  // keep Windows and Linux doing old way, as we have failures
3396  // circa 2013 in this.
3397 
3398  #if defined (GL_ES_VERSION_2_0)
3399  #if defined (GL_PROGRAM_POINT_SIZE)
3400  glEnable(GL_PROGRAM_POINT_SIZE);
3401  #endif
3402  #if defined (GL_PROGRAM_POINT_SIZE_EXT)
3403  glEnable(GL_PROGRAM_POINT_SIZE_EXT);
3404  #endif
3405  #else
3406  glPointSize (gl_linewidth);
3407  #endif
3408 
3409  glLineWidth(gl_linewidth);
3410 
3411  PRINT_GL_ERROR_IF_ANY("fwl_initialize_GL start a");
3412 
3413 
3414 
3415  /*
3416  * JAS - ALPHA testing for textures - right now we just use 0/1 alpha
3417  * JAS channel for textures - true alpha blending can come when we sort
3418  * JAS nodes.
3419  */
3420 
3421  glEnable(GL_BLEND);
3422  FW_GL_BLENDFUNC(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
3423  FW_GL_CLEAR(GL_COLOR_BUFFER_BIT);
3424 
3425  PRINT_GL_ERROR_IF_ANY("fwl_initialize_GL start b");
3426 
3427  /* for textured appearance add specular highlights as a separate secondary color
3428  redbook p.270, p.455 and http://www.gamedev.net/reference/programming/features/oglch9excerpt/
3429 
3430  if we don't have texture we can disable this (less computation)...
3431  but putting this here is already a saving ;)...
3432  */
3433 
3434  PRINT_GL_ERROR_IF_ANY("fwl_initialize_GL start c0");
3435 
3436  /* keep track of light states; initial turn all lights off except for headlight */
3437  initializeLightTables();
3438 
3439  PRINT_GL_ERROR_IF_ANY("fwl_initialize_GL start c1");
3440 
3441 
3442  /* ensure state of GL_CULL_FACE */
3443  CULL_FACE_INITIALIZE;
3444 
3445  FW_GL_PIXELSTOREI(GL_UNPACK_ALIGNMENT,1);
3446  FW_GL_PIXELSTOREI(GL_PACK_ALIGNMENT,1);
3447 
3448  PRINT_GL_ERROR_IF_ANY("fwl_initialize_GL start c");
3449 
3450 
3451  /* create an empty texture, defaultBlankTexture, to be used when a texture is loading, or if it fails */
3452  FW_GL_GENTEXTURES (1,&tg->Textures.defaultBlankTexture);
3453  glBindTexture (GL_TEXTURE_2D, tg->Textures.defaultBlankTexture);
3454  FW_GL_TEXPARAMETERI( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3455  FW_GL_TEXPARAMETERI( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3456  FW_GL_TEXIMAGE2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, blankTexture);
3457 
3458  PRINT_GL_ERROR_IF_ANY("fwl_initialize_GL start d");
3459 
3460  /* remove entries in the shader table, if they exist. Android, on "bring to front" will
3461  call this routine, and shaders will be re-created as they are needed to display geometry.
3462  */
3463  clear_shader_table();
3464  /* moved to clear_shader_table() for anaglyph toggling, dug9 Aug 5, 2012
3465  if (p->myShaderTable != NULL) {
3466  int i;
3467 
3468  for (i=0; i<vectorSize(p->myShaderTable); i++) {
3469  struct shaderTableEntry *me = vector_get(struct shaderTableEntry *,p->myShaderTable, i);
3470  FREE_IF_NZ(me);
3471  }
3472  deleteVector (struct shaderTableEntry *,p->myShaderTable);
3473  p->myShaderTable = newVector(struct shaderTableEntry *, 8);
3474 
3475  }
3476  */
3477  return TRUE;
3478 }
3479 ivec4 get_current_viewport();
3480 void BackEndClearBuffer(int which) {
3481  ivec4 vport = get_current_viewport();
3482  FW_GL_SCISSOR(vport.X,vport.Y,vport.W,vport.H);
3483  glEnable(GL_SCISSOR_TEST);
3484  if(which == 2) {
3485  FW_GL_CLEAR(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3486  } else {
3487  if(which==1) {
3488  FW_GL_CLEAR(GL_DEPTH_BUFFER_BIT);
3489  }
3490  }
3491  glDisable(GL_SCISSOR_TEST);
3492 }
3493 
3494 /* turn off all non-headlight lights; will turn them on if required. */
3495 void BackEndLightsOff() {
3496  int i;
3497  for (i=0; i<HEADLIGHT_LIGHT; i++) {
3498  setLightState(i, FALSE);
3499  }
3500 }
3501 
3502 
3503 void fw_glMatrixMode(GLint mode) {
3504  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
3505 
3506  p->whichMode = mode;
3507  #ifdef VERBOSE
3508  printf ("fw_glMatrixMode, projTOS %d, modTOS %d texvTOS %d\n",p->projectionviewTOS,p->modelviewTOS, p->textureviewTOS);
3509 
3510  switch (p->whichMode) {
3511  case GL_PROJECTION: printf ("glMatrixMode(GL_PROJECTION)\n"); break;
3512  case GL_MODELVIEW: printf ("glMatrixMode(GL_MODELVIEW)\n"); break;
3513  case GL_TEXTURE: printf ("glMatrixMode(GL_TEXTURE)\n"); break;
3514  }
3515  #endif
3516 
3517  switch (p->whichMode) {
3518  case GL_PROJECTION: p->currentMatrix = (GLDOUBLE *) &p->FW_ProjectionView[p->projectionviewTOS]; break;
3519  case GL_MODELVIEW: p->currentMatrix = (GLDOUBLE *) &p->FW_ModelView[p->modelviewTOS]; break;
3520  case GL_TEXTURE: p->currentMatrix = (GLDOUBLE *) &p->FW_TextureView[p->textureviewTOS]; break;
3521  default: printf ("invalid mode sent in it is %d, expected one of %d %d %d\n",p->whichMode, GL_PROJECTION,GL_MODELVIEW,GL_TEXTURE);
3522  }
3523 
3524 }
3525 
3526 void fw_glLoadIdentity(void) {
3527  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
3528  //ConsoleMessage ("fw_glLoadIdentity, whichMode %d, tex %d",p->whichMode,GL_TEXTURE);
3529  loadIdentityMatrix(p->currentMatrix);
3530  FW_GL_LOADMATRIX(p->currentMatrix);
3531 }
3532 
3533 MATRIX4* PushMat( int a, int *b, int c, MATRIX4 *d){
3534  (*b)++;
3535  if (*b >= c) {
3536  printf("stack overflow, depth %d whichmode %d\n", *b, a);
3537  *b = c - 1;
3538  }
3539  memcpy((void *)d[*b], (void *)d[*b - 1], sizeof(GLDOUBLE)* 16);
3540  return &d[*b];
3541 }
3542 
3543 
3544 void printMaxStackUsed(){
3545  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
3546  ConsoleMessage("%25s %d\n","max modelview stack used", p->maxStackUsed);
3547 }
3548 void fw_glPushMatrix(void) {
3549  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
3550 
3551  switch (p->whichMode) {
3552  case GL_PROJECTION: p->currentMatrix = *PushMat(GL_PROJECTION, &p->projectionviewTOS, MAX_SMALL_MATRIX_STACK, p->FW_ProjectionView); break;
3553  case GL_MODELVIEW: p->currentMatrix = *PushMat(GL_MODELVIEW, &p->modelviewTOS, MAX_LARGE_MATRIX_STACK, p->FW_ModelView); break;
3554  case GL_TEXTURE: p->currentMatrix = *PushMat(GL_TEXTURE, &p->textureviewTOS, MAX_SMALL_MATRIX_STACK, p->FW_TextureView); break;
3555  default:printf("wrong mode in popMatrix\n");
3556  }
3557  p->maxStackUsed = max(p->maxStackUsed, p->modelviewTOS);
3558  FW_GL_LOADMATRIX(p->currentMatrix);
3559 }
3560 //void fw_glPushMatrix(void) {
3561 // ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
3562 //
3563 // switch (p->whichMode) {
3564 // PUSHMAT (GL_PROJECTION,p->projectionviewTOS,MAX_SMALL_MATRIX_STACK,p->FW_ProjectionView)
3565 // PUSHMAT (GL_MODELVIEW,p->modelviewTOS,MAX_LARGE_MATRIX_STACK,p->FW_ModelView)
3566 // PUSHMAT (GL_TEXTURE,p->textureviewTOS,MAX_SMALL_MATRIX_STACK,p->FW_TextureView)
3567 // default :printf ("wrong mode in popMatrix\n");
3568 // }
3569 //
3570 // FW_GL_LOADMATRIX(p->currentMatrix);
3571 //}
3572 //#undef PUSHMAT
3573 
3574 //#define POPMAT(a,b,c) case a: b--; if (b<0) {b=0;printf ("popMatrix, stack underflow, whichMode %d\n",p->whichMode);} p->currentMatrix = c[b]; break;
3575 MATRIX4 *PopMat(int a, int *b, MATRIX4 *c){
3576  (*b)--;
3577  if (*b < 0) {
3578  *b = 0;
3579  printf("popMatrix, stack underflow, whichMode %d\n", a);
3580  }
3581  return &c[*b];
3582 }
3583 void fw_glPopMatrix(void) {
3584  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
3585 
3586  switch (p->whichMode) {
3587  case GL_PROJECTION: p->currentMatrix = *PopMat(GL_PROJECTION, &p->projectionviewTOS, p->FW_ProjectionView); break;
3588  case GL_MODELVIEW: p->currentMatrix = *PopMat(GL_MODELVIEW, &p->modelviewTOS, p->FW_ModelView); break;
3589  case GL_TEXTURE: p->currentMatrix = *PopMat(GL_TEXTURE, &p->textureviewTOS, p->FW_TextureView); break;
3590 
3591  default: printf ("wrong mode in popMatrix\n");
3592  }
3593 
3594  FW_GL_LOADMATRIX(p->currentMatrix);
3595 }
3596 //void fw_glPopMatrix(void) {
3597 // ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
3598 //
3599 // switch (p->whichMode) {
3600 // POPMAT(GL_PROJECTION, p->projectionviewTOS, p->FW_ProjectionView)
3601 // POPMAT(GL_MODELVIEW, p->modelviewTOS, p->FW_ModelView)
3602 // POPMAT(GL_TEXTURE, p->textureviewTOS, p->FW_TextureView)
3603 // default:printf("wrong mode in popMatrix\n");
3604 // }
3605 //
3606 // FW_GL_LOADMATRIX(p->currentMatrix);
3607 //}
3608 //#undef POPMAT
3609 
3610 
3611 void fw_glTranslated(GLDOUBLE x, GLDOUBLE y, GLDOUBLE z) {
3612  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
3613 
3614  //printf ("fw_glTranslated %lf %lf %lf\n",x,y,z);
3615  //printf ("translated, currentMatrix %p\n",p->currentMatrix);
3616 
3617  p->currentMatrix[12] = p->currentMatrix[0] * x + p->currentMatrix[4] * y + p->currentMatrix[8] * z + p->currentMatrix[12];
3618  p->currentMatrix[13] = p->currentMatrix[1] * x + p->currentMatrix[5] * y + p->currentMatrix[9] * z + p->currentMatrix[13];
3619  p->currentMatrix[14] = p->currentMatrix[2] * x + p->currentMatrix[6] * y + p->currentMatrix[10] * z + p->currentMatrix[14];
3620  p->currentMatrix[15] = p->currentMatrix[3] * x + p->currentMatrix[7] * y + p->currentMatrix[11] * z + p->currentMatrix[15];
3621 
3622  FW_GL_LOADMATRIX(p->currentMatrix);
3623 }
3624 
3625 void fw_glTranslatef(float x, float y, float z) {
3626  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
3627 
3628  //printf ("fw_glTranslatef %f %f %f\n",x,y,z);
3629  p->currentMatrix[12] = p->currentMatrix[0] * x + p->currentMatrix[4] * y + p->currentMatrix[8] * z + p->currentMatrix[12];
3630  p->currentMatrix[13] = p->currentMatrix[1] * x + p->currentMatrix[5] * y + p->currentMatrix[9] * z + p->currentMatrix[13];
3631  p->currentMatrix[14] = p->currentMatrix[2] * x + p->currentMatrix[6] * y + p->currentMatrix[10] * z + p->currentMatrix[14];
3632  p->currentMatrix[15] = p->currentMatrix[3] * x + p->currentMatrix[7] * y + p->currentMatrix[11] * z + p->currentMatrix[15];
3633 
3634  FW_GL_LOADMATRIX(p->currentMatrix);
3635 }
3636 
3637 /* perform rotation, assuming that the angle is in radians. */
3638 void fw_glRotateRad (GLDOUBLE angle, GLDOUBLE x, GLDOUBLE y, GLDOUBLE z) {
3639  MATRIX4 myMat;
3640  GLDOUBLE mag;
3641  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
3642 
3643  //printf ("fw_glRotateRad %lf %lf %lf %lf modTOS %d projTOS %d\n",angle,x,y,z,p->modelviewTOS,p->projectionviewTOS);
3644  //printmatrix2(p->currentMatrix,"in rad");
3645  loadIdentityMatrix (myMat);
3646 
3647  /* FIXME - any way we can ensure that the angles are normalized? */
3648  mag = x*x + y*y + z*z;
3649 
3650  /* bounds check - the axis is invalid. */
3651  if (APPROX(mag,0.00)) {
3652  return;
3653  }
3654 
3655  /* bounds check - angle is zero, no rotation happening here */
3656  if (APPROX(angle,0.0)) {
3657  return;
3658  }
3659 
3660  if (!APPROX(mag,1.0)) {
3661  struct point_XYZ in; struct point_XYZ out;
3662  in.x = x; in.y = y, in.z = z;
3663  vecnormal(&out,&in);
3664  x = out.x; y = out.y; z = out.z;
3665  }
3666  //printf ("rad, normalized axis %lf %lf %lf\n",x,y,z);
3667 
3668 
3669  matrotate(myMat,angle,x,y,z);
3670 
3671  //printmatrix2 (myMat, "rotation matrix");
3672  matmultiplyAFFINE(p->currentMatrix,myMat,p->currentMatrix);
3673 
3674  //printmatrix2 (p->currentMatrix,"currentMatrix after rotate");
3675 
3676  FW_GL_LOADMATRIX(p->currentMatrix);
3677 }
3678 
3679 /* perform the rotation, assuming that the angle is in degrees */
3680 void fw_glRotated (GLDOUBLE angle, GLDOUBLE x, GLDOUBLE y, GLDOUBLE z) {
3681  MATRIX4 myMat;
3682  GLDOUBLE mag;
3683  GLDOUBLE radAng;
3684  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
3685 
3686  /* convert angle from degrees to radians */
3687  /* FIXME - must try and make up a rotate-radians call to get rid of these incessant conversions */
3688  radAng = angle * 3.1415926536/ 180.0;
3689 
3690  loadIdentityMatrix (myMat);
3691 
3692  /* FIXME - any way we can ensure that the angles are normalized? */
3693  mag = x*x + y*y + z*z;
3694 
3695  /* bounds check - the axis is invalid. */
3696  if (APPROX(mag,0.00)) {
3697  return;
3698  }
3699 
3700  /* bounds check - angle is zero, no rotation happening here */
3701  if (APPROX(angle,0.0)) {
3702  return;
3703  }
3704 
3705  if (!APPROX(mag,1.0)) {
3706  struct point_XYZ in; struct point_XYZ out;
3707  in.x = x; in.y = y, in.z = z;
3708  vecnormal(&out,&in);
3709  x = out.x; y = out.y; z = out.z;
3710  }
3711 
3712 
3713  /* are the axis close to zero? */
3714  if (mag < 0.001) {
3715  return;
3716  }
3717  matrotate(myMat,radAng,x,y,z);
3718  matmultiplyAFFINE(p->currentMatrix,p->currentMatrix,myMat);
3719 
3720  FW_GL_LOADMATRIX(p->currentMatrix);
3721 }
3722 
3723 void fw_glRotatef (float a, float x, float y, float z) {
3724  fw_glRotated((GLDOUBLE)a, (GLDOUBLE)x, (GLDOUBLE)y, (GLDOUBLE)z);
3725 }
3726 
3727 void fw_glScaled (GLDOUBLE x, GLDOUBLE y, GLDOUBLE z) {
3728  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
3729 
3730 // printf ("glScaled(%5.4lf %5.4lf %5.4lf)\n",x,y,z);
3731 
3732  p->currentMatrix[0] *= x; p->currentMatrix[4] *= y; p->currentMatrix[8] *= z;
3733  p->currentMatrix[1] *= x; p->currentMatrix[5] *= y; p->currentMatrix[9] *= z;
3734  p->currentMatrix[2] *= x; p->currentMatrix[6] *= y; p->currentMatrix[10] *= z;
3735  p->currentMatrix[3] *= x; p->currentMatrix[7] *= y; p->currentMatrix[11] *= z;
3736 
3737  FW_GL_LOADMATRIX(p->currentMatrix);
3738 }
3739 
3740 void fw_glScalef (float x, float y, float z) {
3741  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
3742 
3743 // printf ("glScalef(%5.4f %5.4f %5.4f)\n",x,y,z);
3744 
3745  p->currentMatrix[0] *= x; p->currentMatrix[4] *= y; p->currentMatrix[8] *= z;
3746  p->currentMatrix[1] *= x; p->currentMatrix[5] *= y; p->currentMatrix[9] *= z;
3747  p->currentMatrix[2] *= x; p->currentMatrix[6] *= y; p->currentMatrix[10] *= z;
3748  p->currentMatrix[3] *= x; p->currentMatrix[7] *= y; p->currentMatrix[11] *= z;
3749 
3750  FW_GL_LOADMATRIX(p->currentMatrix);
3751 }
3752 
3753 
3754 void fw_glGetDoublev (int ty, GLDOUBLE *mat) {
3755  GLDOUBLE *dp;
3756  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
3757 
3758 /*
3759  switch (ty) {
3760  case GL_PROJECTION_MATRIX: printf ("getDoublev(GL_PROJECTION_MATRIX)\n"); break;
3761  case GL_MODELVIEW_MATRIX: printf ("getDoublev(GL_MODELVIEW_MATRIX)\n"); break;
3762  case GL_TEXTURE_MATRIX: printf ("getDoublev(GL_TEXTURE_MATRIX)\n"); break;
3763  }
3764 */
3765 
3766  switch (ty) {
3767  case GL_PROJECTION_MATRIX: dp = p->FW_ProjectionView[p->projectionviewTOS]; break;
3768  case GL_MODELVIEW_MATRIX: dp = p->FW_ModelView[p->modelviewTOS]; break;
3769  case GL_TEXTURE_MATRIX: dp = p->FW_TextureView[p->textureviewTOS]; break;
3770  default: {
3771  loadIdentityMatrix(mat);
3772  printf ("invalid mode sent in it is %d, expected one of %d %d %d\n",ty,GL_PROJECTION_MATRIX,GL_MODELVIEW_MATRIX,GL_TEXTURE_MATRIX);
3773  return;}
3774  }
3775  memcpy((void *)mat, (void *) dp, sizeof (GLDOUBLE) * MATRIX_SIZE);
3776 }
3777 
3778 void fw_glSetDoublev (int ty, GLDOUBLE *mat) {
3779  GLDOUBLE *dp;
3780  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
3781 
3782 /*
3783  switch (ty) {
3784  case GL_PROJECTION_MATRIX: printf ("getDoublev(GL_PROJECTION_MATRIX)\n"); break;
3785  case GL_MODELVIEW_MATRIX: printf ("getDoublev(GL_MODELVIEW_MATRIX)\n"); break;
3786  case GL_TEXTURE_MATRIX: printf ("getDoublev(GL_TEXTURE_MATRIX)\n"); break;
3787  }
3788 */
3789 
3790  switch (ty) {
3791  case GL_PROJECTION_MATRIX: dp = p->FW_ProjectionView[p->projectionviewTOS]; break;
3792  case GL_MODELVIEW_MATRIX: dp = p->FW_ModelView[p->modelviewTOS]; break;
3793  case GL_TEXTURE_MATRIX: dp = p->FW_TextureView[p->textureviewTOS]; break;
3794  default: {
3795  printf ("invalid mode sent in it is %d, expected one of %d %d %d\n",ty,GL_PROJECTION_MATRIX,GL_MODELVIEW_MATRIX,GL_TEXTURE_MATRIX);
3796  return;}
3797  }
3798  memcpy((void *) dp, (void *)mat, sizeof (GLDOUBLE) * MATRIX_SIZE);
3799 }
3800 
3801 
3802 /* for Sarah's front end - should be removed sometime... */
3803 void kill_rendering() {
3804 /* printf ("kill_rendering called...\n"); */
3805 }
3806 
3807 
3808 /* if we have a ReplaceWorld style command, we have to remove the old world. */
3809 /* NOTE: There are 2 kinds of of replaceworld commands - sometimes we have a URL
3810  (eg, from an Anchor) and sometimes we have a list of nodes (from a Javascript
3811  replaceWorld, for instance). The URL ones can really replaceWorld, the node
3812  ones, really, it's just replace the rootNode children, as WE DO NOT KNOW
3813  what the user has programmed, and what nodes are (re) used in the Scene Graph */
3814 
3815 void killNodes();
3816 
3817 void kill_oldWorld(int kill_EAI, int kill_JavaScript, char *file, int line) {
3818  int i;
3819  struct X3D_Node* rootnode;
3820  struct VRMLParser *globalParser = (struct VRMLParser *)gglobal()->CParse.globalParser;
3821  char mystring[20];
3822 
3823  //printf ("kill_oldWorld called...\n");
3824 
3825 
3826 #ifdef VERBOSE
3827  printf ("kill 1 myThread %u displayThread %u\n",pthread_self(), gglobal()->threads.DispThrd);
3828 #ifdef _MSC_VER
3829  if (pthread_self().p != gglobal()->threads.DispThrd.p ) {
3830 #else
3831  if (pthread_self() != gglobal()->threads.DispThrd) {
3832 #endif
3833  ConsoleMessage ("kill_oldWorld must run in the displayThread called at %s:%d\n",file,line);
3834  return;
3835  }
3836 #endif
3837 
3838  /* get rid of sensor events */
3839  resetSensorEvents();
3840 
3841 
3842  /* make the root_res equal NULL - this throws away all old resource info */
3843  /*
3844  if (gglobal()->resources.root_res != NULL) {
3845  printf ("root_res %p has the following...\n",gglobal()->resources.root_res);
3846  resource_dump(gglobal()->resources.root_res);
3847  }else {printf ("root_res is null, no need to dump\n");}
3848  */
3849  resource_tree_destroy(); //dug9 sep2,2013 added this call. just comment out if giving trouble before a release
3850 
3851 
3852  gglobal()->resources.root_res = NULL;
3853 
3854 
3855 
3856 
3857 
3858  /* mark all rootNode children for Dispose */
3859  rootnode = rootNode();
3860  if (rootnode != NULL) {
3861  if(rootnode->_nodeType == NODE_Proto){
3862  unload_broto(X3D_PROTO(rootnode));
3863  }else{
3864  struct Multi_Node *children, *sortedChildren;
3865 
3866  children = &X3D_PROTO(rootNode())->__children;
3867  sortedChildren = &X3D_PROTO(rootNode())->_sortedChildren;
3868  //children = childrenField(rootNode());
3869  if (children->n != 0) {
3870  for (i=0; i<children->n; i++) {
3871  markForDispose(children->p[i], TRUE);
3872  }
3873  }
3874  //if (sortedChildren->n != 0) {
3875  // for (i=0; i<sortedChildren->n; i++) {
3876  // markForDispose(sortedChildren->p[i], TRUE);
3877  // }
3878  //}
3879 
3880 
3881  /* stop rendering */
3882  sortedChildren->n = 0;
3883  children->n = 0;
3884  }
3885  }
3886 
3887  /* close the Console Message system, if required. */
3888  closeConsoleMessage();
3889 
3890  /* occlusion testing - zero total count, but keep MALLOC'd memory around */
3891  zeroOcclusion();
3892 
3893  /* clock events - stop them from ticking */
3894  kill_clockEvents();
3895 
3896 
3897  /* kill DEFS, handles */
3898  EAI_killBindables();
3899  kill_bindables();
3900  killKeySensorNodeList();
3901 
3902  /* stop routing */
3903  kill_routing();
3904 
3905  /* tell the statusbar that it needs to reinitialize */
3906  //kill_status();
3907  setMenuStatus(NULL);
3908 
3909  /* any user defined Shader nodes - ComposedShader, PackagedShader, ProgramShader?? */
3910  kill_userDefinedShaders();
3911 
3912  /* free textures */
3913 /*
3914  kill_openGLTextures();
3915 */
3916 
3917  /* free scripts */
3918 
3919  kill_javascript();
3920 
3921 
3922 #if !defined(EXCLUDE_EAI)
3923  /* free EAI */
3924  if (kill_EAI) {
3925  /* shutdown_EAI(); */
3926  fwlio_RxTx_control(CHANNEL_EAI, RxTx_STOP) ;
3927  }
3928 #endif
3929 
3930 // OLD_IPHONE_AQUA #ifndef AQUA
3931  sprintf (mystring, "QUIT");
3932  Sound_toserver(mystring);
3933 // OLD_IPHONE_AQUA #endif
3934 
3935 
3936  /* reset any VRML Parser data */
3937  if (globalParser != NULL) {
3938  parser_destroyData(globalParser);
3939  //globalParser = NULL;
3940  //moved to CParse_clear gglobal()->CParse.globalParser = NULL;
3941  }
3942 
3943  kill_X3DDefs();
3944 
3945  /* tell statusbar that we have none */
3946  //viewer_default();
3947  setMenuStatus("NONE");
3948 }
3949 void unload_globalParser() {
3950  // unload any string tables, and signal to any replacworld scene that it needs a new parser+lexer struct
3951  struct VRMLParser *globalParser = (struct VRMLParser *)gglobal()->CParse.globalParser;
3952  if(globalParser){
3953  parser_destroyData(globalParser); //destroys lexer data too
3954  FREE_IF_NZ(globalParser->lexer);
3955  }
3956  FREE_IF_NZ(globalParser);
3957  gglobal()->CParse.globalParser = NULL; //set to null to trigger a fresh createParser on replaceworld
3958 }
3959 void unload_libraryscenes();
3960 void reset_Browser(){
3961  // erase old world but keep gglobal in good shape, ie everything in _init() functions still good
3962  // -gglobal is erased elsewhere in finalizeRenderSceneUpdateScene()
3963  // also don't erase browser metadata key,value pairs, which could be avatar state to be
3964  // carried over between room-scenes in multi-scene game
3965  struct X3D_Node *rootnode = rootNode();
3966  if (rootnode != NULL) {
3967  if( rootnode->_nodeType == NODE_Proto){
3968  unload_broto(X3D_PROTO(rootnode)); //we still want a rootnode: empty and waiting for parsing (destroy in finalizeRenderSceneUpdateScene only on exit)
3969  unload_globalParser();
3970  resource_tree_destroy();
3971  unload_libraryscenes(); //debate: should proto libraryscenes hang around in case the same protos are used in a different, anchored-to scene?
3972  kill_javascript();
3973  }else{
3974  kill_oldWorld(TRUE,TRUE,__FILE__,__LINE__);
3975  }
3976  }
3977 }
3978 
3979 
3980 #if defined (_ANDROID)
3981 
3982 /* Android wants the OpenGL system to re-create assets like textures on onSurfaceCreated call */
3983 void fwl_Android_reloadAssets(void) {
3984  int tc;
3985  struct X3D_Node *node;
3986  ppOpenGL_Utils p;
3987 
3988  p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
3989 
3990  /* reset the RenderFuncs cache */
3991  resetGlobalShader();
3992 
3993  //ConsoleMessage("fwl_Android_reloadAssets called");
3994 
3995  //ConsoleMessage ("fwl_Android_reloadAssets - reloading shader code");
3996  fwl_initialize_GL();
3997 
3998  //ConsoleMessage("fwl_Android_reloadAssets - reload the current active shaders");
3999 
4000  if (p->linearNodeTable != NULL) {
4001  LOCK_MEMORYTABLE
4002  for (tc=0; tc<vectorSize(p->linearNodeTable); tc++){
4003  node = vector_get(struct X3D_Node *,p->linearNodeTable,tc);
4004 
4005  //ConsoleMessage ("rla, node %p\n",node);
4006 
4007  if (node!=NULL) {
4008 
4009  /* tell each node to update itself */
4010  node->_change ++;
4011  switch (node->_nodeType) {
4012  case NODE_Sphere: {
4013  struct X3D_Sphere *me = (struct X3D_Sphere *)node;
4014  //ConsoleMessage ("Sphere - zeroing VBO");
4015  me->_sideVBO = 0;
4016  me->__SphereIndxVBO = 0;
4017  FREE_IF_NZ(me->__points.p);
4018  me->__points.p = NULL;
4019  me->__points.n = 0;
4020  node->_change ++;
4021  break;
4022 
4023  }
4024  case NODE_Cone: {
4025  struct X3D_Cone *me = (struct X3D_Cone *)node;
4026  me->__coneVBO = 0;
4027  node->_change ++;
4028  break;
4029  }
4030  case NODE_Cylinder: {
4031  struct X3D_Cylinder *me = (struct X3D_Cylinder *)node;
4032  me->__cylinderVBO = 0;
4033  node->_change ++;
4034  break;
4035  }
4036  case NODE_Background: {
4037  struct X3D_Background *me = (struct X3D_Background *)node;
4038  //ConsoleMessage ("Background - zeroing VBO");
4039  me->__VBO = 0;
4040  node->_change ++;
4041  break;
4042  }
4043  default: {
4044  struct X3D_PolyRep *pr = node->_intern;
4045  int i;
4046 
4047  //ConsoleMessage ("node Type %s, intern %p",stringNodeType(node->_nodeType),pr);
4048 
4049  // get rid of the PolyRep VBOs.
4050  if (pr!=NULL) {
4051  for (i=0; i<VBO_COUNT; i++) pr->VBO_buffers[i] = 0;
4052  pr->irep_change ++;
4053  node->_change ++;
4054  }
4055  }
4056 
4057  }
4058  }
4059 
4060  }
4061  UNLOCK_MEMORYTABLE
4062  }
4063 }
4064 #endif
4065 
4066 /* for verifying that a memory pointer exists */
4067 int checkNode(struct X3D_Node *node, char *fn, int line) {
4068  int tc;
4069  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
4070 
4071  if (node == NULL) {
4072  printf ("checkNode, node is NULL at %s %d\n",fn,line);
4073  return FALSE;
4074  }
4075 
4076  if (node == X3D_NODE(rootNode())) return FALSE;
4077 
4078  LOCK_MEMORYTABLE;
4079 
4080  for (tc=0; tc<vectorSize(p->linearNodeTable); tc++){
4081  if (vector_get(struct X3D_Node *,p->linearNodeTable,tc) == node) {
4082  if (node->referenceCount > 0) {
4083  UNLOCK_MEMORYTABLE;
4084  return TRUE;
4085  }
4086  }
4087  }
4088 
4089 
4090 
4091  //printf ("checkNode: did not find %p in memory table at i%s %d\n",node,fn,line);
4092 
4093  UNLOCK_MEMORYTABLE;
4094 
4095  return FALSE;
4096 }
4097 
4098 
4099 /*creating node table*/
4100 static void createMemoryTable(){
4101  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
4102 
4103  p->linearNodeTable = newVector(struct X3D_Node*, 128);
4104 
4105 
4106 }
4107 
4108 /*keep track of node created*/
4109 void registerX3DNode(struct X3D_Node * tmp){
4110  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
4111  int tc;
4112  bool filledHole = FALSE;
4113 
4114  LOCK_MEMORYTABLE
4115 
4116  if (p->linearNodeTable == NULL) {
4117  createMemoryTable();
4118  }
4119 
4120  // fill in a hole, or just tack it on the end?
4121  if (p->potentialHoleCount > 0) {
4122  for (tc=0; tc<vectorSize(p->linearNodeTable); tc++){
4123  if (!filledHole) {
4124  if (vector_get(struct X3D_Node *,p->linearNodeTable,tc) == NULL) {
4125  vector_set(struct X3D_Node *, p->linearNodeTable, tc, tmp);
4126  p->potentialHoleCount--;
4127  filledHole = TRUE;
4128 //ConsoleMessage ("registerX3DNode, found a hole at %d, now phc %d for type %s",tc,p->potentialHoleCount,stringNodeType(tmp->_nodeType));
4129  }
4130  }
4131  }
4132  }
4133 
4134 
4135  /*
4136  if (filledHole) ConsoleMessage ("registerX3DNode, filled hole, now phc %d for type %s",p->potentialHoleCount,stringNodeType(tmp->_nodeType));
4137  if (!filledHole) ConsoleMessage ("registerX3DNode, no hole, phc %d for type %s",p->potentialHoleCount,stringNodeType(tmp->_nodeType));
4138  */
4139 
4140  if (!filledHole) vector_pushBack(struct X3D_Node *, p->linearNodeTable, tmp);
4141 
4142  UNLOCK_MEMORYTABLE
4143 }
4144 int removeNodeFromVector(int iaction, struct Vector *v, struct X3D_Node *node);
4145 void unRegisterX3DNode(struct X3D_Node * tmp){
4146  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
4147  LOCK_MEMORYTABLE
4148  if (p->linearNodeTable ) {
4149  removeNodeFromVector(1, p->linearNodeTable, tmp);
4150  //int tc;
4151  //for (tc=0; tc<vectorSize(p->linearNodeTable); tc++){
4152  // struct X3D_Node *ns;
4153  // ns = vector_get(struct X3D_Node *,p->linearNodeTable,tc);
4154  // if(ns == tmp) {
4155  // vector_set(struct X3D_Node *, p->linearNodeTable, tc, NULL);
4156  // break;
4157  // }
4158  //}
4159  }
4160  UNLOCK_MEMORYTABLE
4161 }
4162 
4163 
4164 /*We don't register the first node created for reload reason*/
4165 void doNotRegisterThisNodeForDestroy(struct X3D_Node * nodePtr){
4166  int i;
4167 
4168  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
4169 
4170  LOCK_MEMORYTABLE
4171  /* find this node, and if found, just delete it from the memory table */
4172 
4173  for (i=0; i<vectorSize(p->linearNodeTable); i++) {
4174  if (vector_get(struct X3D_Node *,p->linearNodeTable,i) == nodePtr) {
4175  vector_set(struct X3D_Node *,p->linearNodeTable,i,NULL);
4176  p->potentialHoleCount++;
4177  }
4178  }
4179 
4180  UNLOCK_MEMORYTABLE
4181 }
4182 
4183 
4184 
4185 /* sort children - use bubble sort with early exit flag */
4186 /* we use this for z buffer rendering; drawing scene in correct z-buffer order */
4187 /* we ONLY sort if:
4188  1) the node has changed - this is the "needsCompiling" field;
4189  2) the number of children has changed - again, the "needsCompiling" flag should be set,
4190  but we enforce it;
4191  3) the first pass shows that nodes are out of order
4192 */
4193 
4194 static void sortChildren (int line, struct Multi_Node *ch, struct Multi_Node *sortedCh, int sortForDistance) {
4195  int i,j;
4196  int nc;
4197  int noswitch;
4198  struct X3D_Node *a, *b, *c;
4199 
4200 
4201  /* Thread Race Warning: the (non-broto) parser can still be
4202  adding children in its thread, while we are rendering in this thread.
4203  We don't have mutex locks, so we are relying on 'atomic operations'
4204  if it bombs in here check also REINITIALIZE_SORTED_NODES_FIELD macro which does the same thing
4205  */
4206  nc = ch->n; //ATOMIC OP - saves the instantaneous size of ch, which may keep growing
4207 
4208  #ifdef VERBOSE
4209  printf ("sortChildren line %d nc %d ",line,nc);
4210  if (sortForDistance) printf ("sortForDistance ");
4211  printf ("\n");
4212  #endif //VERBOSE
4213 
4214 
4215  /* has this changed size? */
4216  if (nc != sortedCh->n) {
4217  FREE_IF_NZ(sortedCh->p); //Mar 11, 2014:
4218  sortedCh->p = MALLOC(void *, sizeof (struct X3DNode *) * nc);
4219  memcpy(sortedCh->p, ch->p, sizeof(struct X3DNode *) * nc); //ATOMIC-OP - ch->p gets realloced frequently, we need a snapshot which may be bigger than nc above
4220  sortedCh->n = nc;
4221  }
4222 
4223  #ifdef VERBOSE
4224  printf ("sortChildren start, %d, chptr %u\n",nc,ch);
4225  #endif
4226 
4227  /* do we care about rendering order? */
4228 
4229  if (!sortForDistance) return;
4230  if (nc < 2) return;
4231  /* simple, inefficient bubble sort */
4232  /* this is a fast sort when nodes are already sorted;
4233  may wish to go and "QuickSort" or so on, when nodes
4234  move around a lot. (Bubblesort is bad when nodes
4235  have to be totally reversed) */
4236 
4237  for(i=0; i<nc; i++) {
4238  noswitch = TRUE;
4239  for (j=(nc-1); j>i; j--) {
4240  /* printf ("comparing %d %d\n",i,j); */
4241  a = X3D_NODE(sortedCh->p[j-1]);
4242  b = X3D_NODE(sortedCh->p[j]);
4243 
4244  /* check to see if a child is NULL - if so, skip it */
4245  if (a && b) {
4246  if (a->_dist > b->_dist) {
4247  // printf ("sortChildren at %lf, have to switch %d %d dists %lf %lf\n",TickTime(),i,j,a->_dist, b->_dist);
4248  c = a;
4249  sortedCh->p[j-1] = b;
4250  sortedCh->p[j] = c;
4251  noswitch = FALSE;
4252 
4253  }
4254  }
4255  }
4256  /* did we have a clean run? */
4257  if (noswitch) {
4258  break;
4259  }
4260  }
4261 
4262  #ifdef VERBOSE
4263  printf ("sortChildren returning.\n");
4264  for(i=0; i<nc; i++) {
4265  b = sortedCh->p[i];
4266  if (b)
4267  printf ("child %d %u %f %s",i,b,b->_dist,stringNodeType(b->_nodeType));
4268  else
4269  printf ("no child %d", i);
4270  b = ch->p[i];
4271  printf (" unsorted %u\n",b);
4272  }
4273  #endif
4274 }
4275 
4276 /* zero the Visibility flag in all nodes */
4277 void zeroVisibilityFlag(void) {
4278  struct X3D_Node* node;
4279  int i;
4280  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
4281 
4282  /* do not bother doing this if the inputThread is active. */
4283  if (fwl_isinputThreadParsing()) return;
4284  LOCK_MEMORYTABLE
4285 
4286  /* do we have GL_ARB_occlusion_query, or are we still parsing Textures? */
4287  if ((gglobal()->Frustum.OccFailed) || fwl_isTextureParsing()) {
4288  /* if we have textures still loading, display all the nodes, so that the textures actually
4289  get put into OpenGL-land. If we are not texture parsing... */
4290  /* no, we do not have GL_ARB_occlusion_query, just tell every node that it has visible children
4291  and hope that, sometime, the user gets a good computer graphics card */
4292  for (i=0; i<vectorSize(p->linearNodeTable); i++){
4293  node = vector_get(struct X3D_Node *,p->linearNodeTable,i);
4294  if (node != NULL) {
4295  node->_renderFlags = node->_renderFlags | VF_hasVisibleChildren;
4296  }
4297  }
4298  }
4299  else if (p->linearNodeTable)
4300  {
4301  /* we do... lets zero the hasVisibleChildren flag */
4302  for (i=0; i<vectorSize(p->linearNodeTable); i++){
4303  node = vector_get(struct X3D_Node *,p->linearNodeTable,i);
4304 
4305  if (node != NULL) {
4306 
4307  #ifdef OCCLUSIONVERBOSE
4308  if (((node->_renderFlags) & VF_hasVisibleChildren) != 0) {
4309  printf ("%lf, zeroVisibility - %d is a %s, flags %x\n",TickTime(), i,stringNodeType(node->_nodeType), (node->_renderFlags) & VF_hasVisibleChildren);
4310  }
4311  #endif
4312 
4313  node->_renderFlags = node->_renderFlags & (0xFFFF^VF_hasVisibleChildren);
4314  }
4315 
4316  }
4317  }
4318 
4319  UNLOCK_MEMORYTABLE
4320 }
4321 
4322 /* go through the linear list of nodes, and do "special things" for special nodes, like
4323  Sensitive nodes, Viewpoint nodes, ... */
4324 
4325 #define CMD(TTT,YYY) \
4326  /* printf ("nt %s change %d ichange %d\n",stringNodeType(X3D_NODE(YYY)->_nodeType),X3D_NODE(YYY)->_change, X3D_NODE(YYY)->_ichange); */ \
4327  if (NODE_NEEDS_COMPILING) compile_Metadata##TTT((struct X3D_Metadata##TTT *) YYY)
4328 
4329 #define BEGIN_NODE(thistype) case NODE_##thistype:
4330 #define END_NODE break;
4331 
4332 #define SIBLING_SENSITIVE(thistype) \
4333  /* make Sensitive */ \
4334  if (((struct X3D_##thistype *)node)->enabled) { \
4335  nParents = vectorSize((struct X3D_##thistype *)pnode->_parentVector); \
4336  parentVector = (((struct X3D_##thistype *)pnode)->_parentVector); \
4337  }
4338 
4339 #define ANCHOR_SENSITIVE(thistype) \
4340  /* make THIS Sensitive - most nodes make the parents sensitive, Anchors have children...*/ \
4341  anchorPtr = (struct X3D_Anchor *)node;
4342 
4343 //#ifdef VIEWPOINT
4344 //#undef VIEWPOINT /* defined for the EAI,SAI, does not concern us uere */
4345 //#endif
4346 #define BINDABLE(thistype) \
4347  setBindPtr = (int *)(((char*)(node))+offsetof (struct X3D_##thistype, set_bind)); \
4348  if ((*setBindPtr) == 100) {setBindPtr = NULL; } //else {printf ("OpenGL, BINDING %d\n",*setBindPtr);}/* already done */
4349 
4350 #define CHILDREN_NODE(thistype) \
4351  addChildren = NULL; removeChildren = NULL; \
4352  offsetOfChildrenPtr = offsetof (struct X3D_##thistype, children); \
4353  if (((struct X3D_##thistype *)node)->addChildren.n > 0) { \
4354  addChildren = &((struct X3D_##thistype *)node)->addChildren; \
4355  childrenPtr = &((struct X3D_##thistype *)node)->children; \
4356  } \
4357  if (((struct X3D_##thistype *)node)->removeChildren.n > 0) { \
4358  removeChildren = &((struct X3D_##thistype *)node)->removeChildren; \
4359  childrenPtr = &((struct X3D_##thistype *)node)->children; \
4360  }
4361 
4362 #define CHILDREN_SWITCH_NODE(thistype) \
4363  addChildren = NULL; removeChildren = NULL; \
4364  offsetOfChildrenPtr = offsetof (struct X3D_##thistype, choice); \
4365  if (((struct X3D_##thistype *)node)->addChildren.n > 0) { \
4366  addChildren = &((struct X3D_##thistype *)node)->addChildren; \
4367  childrenPtr = &((struct X3D_##thistype *)node)->choice; \
4368  } \
4369  if (((struct X3D_##thistype *)node)->removeChildren.n > 0) { \
4370  removeChildren = &((struct X3D_##thistype *)node)->removeChildren; \
4371  childrenPtr = &((struct X3D_##thistype *)node)->choice; \
4372  }
4373 
4374 #define CHILDREN_LOD_NODE \
4375  addChildren = NULL; removeChildren = NULL; \
4376  offsetOfChildrenPtr = offsetof (struct X3D_LOD, children); \
4377  if (X3D_LODNODE(node)->addChildren.n > 0) { \
4378  addChildren = &X3D_LODNODE(node)->addChildren; \
4379  if (X3D_LODNODE(node)->__isX3D == 0) childrenPtr = &X3D_LODNODE(node)->level; \
4380  else childrenPtr = &X3D_LODNODE(node)->children; \
4381  } \
4382  if (X3D_LODNODE(node)->removeChildren.n > 0) { \
4383  removeChildren = &X3D_LODNODE(node)->removeChildren; \
4384  if (X3D_LODNODE(node)->__isX3D == 0) childrenPtr = &X3D_LODNODE(node)->level; \
4385  else childrenPtr = &X3D_LODNODE(node)->children; \
4386  }
4387 
4388 #define CHILDREN_ANY_NODE(thistype,thischildren) \
4389  addChildren = NULL; removeChildren = NULL; \
4390  offsetOfChildrenPtr = offsetof (struct X3D_##thistype, thischildren); \
4391  if (((struct X3D_##thistype *)node)->addChildren.n > 0) { \
4392  addChildren = &((struct X3D_##thistype *)node)->addChildren; \
4393  childrenPtr = &((struct X3D_##thistype *)node)->thischildren; \
4394  } \
4395  if (((struct X3D_##thistype *)node)->removeChildren.n > 0) { \
4396  removeChildren = &((struct X3D_##thistype *)node)->removeChildren; \
4397  childrenPtr = &((struct X3D_##thistype *)node)->thischildren; \
4398  }
4399 
4400 
4401 #define EVIN_AND_FIELD_SAME(thisfield, thistype) \
4402  if ((((struct X3D_##thistype *)node)->set_##thisfield.n) > 0) { \
4403  ((struct X3D_##thistype *)node)->thisfield.n = 0; \
4404  FREE_IF_NZ (((struct X3D_##thistype *)node)->thisfield.p); \
4405  ((struct X3D_##thistype *)node)->thisfield.p = ((struct X3D_##thistype *)node)->set_##thisfield.p; \
4406  ((struct X3D_##thistype *)node)->thisfield.n = ((struct X3D_##thistype *)node)->set_##thisfield.n; \
4407  ((struct X3D_##thistype *)node)->set_##thisfield.n = 0; \
4408  ((struct X3D_##thistype *)node)->set_##thisfield.p = NULL; \
4409  node->_change++; \
4410  }
4411  //above - polyrep needs to compile after set_coordIndex is copied to coordIndex
4412 
4413 #ifdef OLDCODE
4414 OLDCODE/* just tell the parent (a grouping node) that there is a locally scoped light as a child */
4415 OLDCODE/* do NOT send this up the scenegraph! */
4416 OLDCODE#define LOCAL_LIGHT_PARENT_FLAG \
4417 OLDCODE{ int i; \
4418 OLDCODE for (i = 0; i < vectorSize(pnode->_parentVector); i++) { \
4419 OLDCODE struct X3D_Node *n = vector_get(struct X3D_Node*, pnode->_parentVector, i); \
4420 OLDCODE if( n != 0 ) n->_renderFlags = n->_renderFlags | VF_localLight; \
4421 OLDCODE } \
4422 OLDCODE}
4423 #endif //OLDCODE
4424 
4425 #define ADD_TO_PARENT_SIBAFFECTORS \
4426 { int i; \
4427  for (i = 0; i < vectorSize(pnode->_parentVector); i++) { \
4428  struct X3D_Node *n = vector_get(struct X3D_Node*, pnode->_parentVector, i); \
4429  if( n != 0 ) AddToSibAffectors(n,pnode); \
4430  } \
4431 }
4432 
4433 #define CHECK_MATERIAL_TRANSPARENCY \
4434 if (((struct X3D_Material *)node)->transparency > 0.0001) { \
4435 /* printf ("node %p MATERIAL HAS TRANSPARENCY of %f \n", node, ((struct X3D_Material *)node)->transparency); */ \
4436 update_renderFlag(X3D_NODE(pnode),VF_Blend | VF_shouldSortChildren);\
4437 gglobal()->RenderFuncs.have_transparency = TRUE; \
4438 }
4439 
4440 #define CHECK_FILL_PROPERTY_FILLED \
4441  if ((((struct X3D_FillProperties *)node)->_enabled == TRUE) && (((struct X3D_FillProperties *)node)->filled == FALSE)) { \
4442  /* printf ("node %p FillProperty filled FALSE\n",node); */ \
4443  update_renderFlag(X3D_NODE(pnode),VF_Blend | VF_shouldSortChildren);\
4444  gglobal()->RenderFuncs.have_transparency = TRUE; \
4445 }
4446 
4447 #define CHECK_TWOSIDED_MATERIAL_TRANSPARENCY \
4448  if ((((struct X3D_TwoSidedMaterial *)node)->transparency > 0.0001) || (((struct X3D_TwoSidedMaterial *)node)->backTransparency > 0.0001)){ \
4449  /* printf ("node %p TwoSidedMATERIAL HAS TRANSPARENCY of %f %f \n", node, ((struct X3D_TwoSidedMaterial *)node)->transparency,((struct X3D_TwoSidedMaterial *)node)->backTransparency);*/ \
4450  update_renderFlag(X3D_NODE(pnode),VF_Blend | VF_shouldSortChildren);\
4451  gglobal()->RenderFuncs.have_transparency = TRUE; \
4452  }
4453 
4454 #define CHECK_IMAGETEXTURE_TRANSPARENCY \
4455  if (isTextureAlpha(((struct X3D_ImageTexture *)node)->__textureTableIndex)) { \
4456  /* printf ("node %d IMAGETEXTURE HAS TRANSPARENCY\n", node); */ \
4457  update_renderFlag(X3D_NODE(pnode),VF_Blend | VF_shouldSortChildren);\
4458  gglobal()->RenderFuncs.have_transparency = TRUE; \
4459  }
4460 
4461 #define CHECK_PIXELTEXTURE_TRANSPARENCY \
4462  if (isTextureAlpha(((struct X3D_PixelTexture *)node)->__textureTableIndex)) { \
4463  /* printf ("node %d PIXELTEXTURE HAS TRANSPARENCY\n", node); */ \
4464  update_renderFlag(X3D_NODE(pnode),VF_Blend | VF_shouldSortChildren);\
4465  gglobal()->RenderFuncs.have_transparency = TRUE; \
4466  }
4467 
4468 #define CHECK_MOVIETEXTURE_TRANSPARENCY \
4469  if (isTextureAlpha(((struct X3D_MovieTexture *)node)->__textureTableIndex)) { \
4470  /* printf ("node %d MOVIETEXTURE HAS TRANSPARENCY\n", node); */ \
4471  update_renderFlag(X3D_NODE(pnode),VF_Blend | VF_shouldSortChildren);\
4472  gglobal()->RenderFuncs.have_transparency = TRUE; \
4473  }
4474 
4475 //dug9 dec 13 >>
4476 //also used in renderfuncs.c setSensitive()
4477 //definition: type node: its the node that represents the type of the node
4478 //which for builtin nodes is the same as the node
4479 // it's only different for protoInstances, where the type node is the first node in the ProtoBody
4480 // or if the first node in the protoBody is a Proto, then its first node ad infinitum
4481 // goal: get the type node, given the node
4482 // then the Proto IS-A typeNode or can be used as one in some places
4483 struct X3D_Node* getTypeNode(struct X3D_Node *node)
4484 {
4485  struct X3D_Node* dnode;
4486  dnode = node; //for builtin types, the type node is just the node
4487  if(node){
4488  if(node->_nodeType == NODE_Proto)
4489  {
4490  struct X3D_Proto *pn = (struct X3D_Proto*)node;
4491  if(1) //some flag to say it's not the scene, but a protoInstance where only the first node is rendered - see isProto
4492  {
4493  //the first node in a protobody determines its type
4494  if(pn->__children.n > 0)
4495  dnode = getTypeNode(pn->__children.p[0]);
4496  else
4497  dnode = NULL;
4498  }
4499  }
4500 
4501  }
4502  return dnode;
4503 }
4504 void printStatsNodes(){
4505  ppOpenGL_Utils p;
4506  ttglobal tg = gglobal();
4507  p = (ppOpenGL_Utils)tg->OpenGL_Utils.prv;
4508 
4509  ConsoleMessage("%25s %d\n","Nodes count", p->linearNodeTable->n);
4510 }
4511 
4512 int unRegisterX3DAnyNode(struct X3D_Node *node);
4513 
4514 void killNodes()
4515 {
4516  int i;
4517  struct X3D_Node* node;
4518  ppOpenGL_Utils p;
4519  ttglobal tg = gglobal();
4520  p = (ppOpenGL_Utils)tg->OpenGL_Utils.prv;
4521 
4522  for (i = 0; i < vectorSize(p->linearNodeTable); i++){
4523  node = vector_get(struct X3D_Node *, p->linearNodeTable, i);
4524  if (node != NULL) {
4525  if (node->referenceCount <= 0) {
4526  //ConsoleMessage ("%d ref %d\n",i,node->referenceCount);
4527  //killNode(i);
4528  unRegisterX3DAnyNode(node);
4529  FREE_IF_NZ(node);
4530  vector_set(struct X3D_Node *,p->linearNodeTable,i,NULL);
4531  }
4532  //else{
4533  // printf("%d ", i);
4534  //}
4535  }
4536  }
4537 }
4538 //will have sibprep_ and sibfin_ functions:
4539 int isSiblingAffector(struct X3D_Node *node){
4540  int ret = 0;
4541  switch(node->_nodeType){
4542  case NODE_DirectionalLight: //lights are always added, then global is checked on the local pass and skipped if not local
4543  case NODE_SpotLight:
4544  case NODE_PointLight:
4545  case NODE_LocalFog:
4546  case NODE_ClipPlane:
4547  case NODE_Effect:
4548  ret = 1; break;
4549  default:
4550  ret = 0; break;
4551  }
4552  return ret;
4553 }
4554 //has _siblingAffector field:
4555 //(in perl VRMLNodes.pm, __sibAffectors was added after all removeChildren)
4556 // Proto (scene), Inline, Group, Transform, Anchor, Billboard, Collision,
4557 // GeoLocation, GeoTransform, HAnimHumanoid, HAnimSite, EspduTransform, CADAssembly, CADLayer, CADPart,
4558 // Viewport, Layer, LayoutLayer, LayoutGroup, ScreenGroup, PickableGroup
4559 // siblingAffector action, but no add/remove children: staticGroup
4560 //might have _siblingAffector field, but not used: LOD, Switch, HAnimJoint, HAnimSegment, CADLayer
4561 
4562 
4563 int hasSiblingAffectorField(struct X3D_Node *node, int whereFrom){
4564  //assume everything with AddChildren, RemoveChildren fields qualifies
4565  // and this filter has already been applied ie we are inside AddRemoveChildren
4566  int ret = 0;
4567  // except:
4568 if (node==NULL) {
4569  printf ("hasSiblingAffectorField, node %p from line %d\n",node,whereFrom);
4570  return 0;
4571 }
4572  switch(node->_nodeType){
4573  case NODE_Proto:
4574  case NODE_Inline:
4575  case NODE_Group:
4576  case NODE_Transform:
4577  case NODE_Anchor:
4578  case NODE_Billboard:
4579  case NODE_Collision:
4580  case NODE_GeoLocation:
4581  case NODE_GeoTransform:
4582  case NODE_HAnimSite:
4583  case NODE_HAnimHumanoid:
4584  //case NODE_HAnimSegment:
4585  //case NODE_HAnimJoint:
4586  case NODE_EspduTransform:
4587  case NODE_CADAssembly:
4588  //case NODE_CADLayer:
4589  case NODE_CADPart:
4590  case NODE_Viewport:
4591  case NODE_Layer:
4592  case NODE_LayoutLayer:
4593  case NODE_LayoutGroup:
4594  case NODE_ScreenGroup:
4595  case NODE_PickableGroup:
4596  case NODE_StaticGroup:
4597  ret = 1; break;
4598  default:
4599  ret = 0; break;
4600  }
4601  return ret;
4602 }
4603 void *sibAffectorPtr(struct X3D_Node *node){
4604  //gets the sibAffectors field from the X3DGrouping node (plus staticGroup)
4605  // or returns null if not found
4606  void *fieldPtr;
4607  int *fieldOffsetsPtr;
4608  fieldOffsetsPtr = (int*) NODE_OFFSETS[node->_nodeType];
4609  fieldPtr = NULL;
4610  while(fieldOffsetsPtr[0] > -1){
4611  //printf("foff[0]=%d ft_sas=%d\n",fieldOffsetsPtr[0],FIELDNAMES___sibAffectors);
4612  if(fieldOffsetsPtr[0] == FIELDNAMES___sibAffectors){
4613  fieldPtr = offsetPointer_deref(char *, node,fieldOffsetsPtr[1]);
4614  break;
4615  }
4616  fieldOffsetsPtr += 5; // &fieldOffsetsPtr[5]; //5 ints per table entry
4617  }
4618  return fieldPtr;
4619 }
4620 void AddToSibAffectors(struct X3D_Node *parent, struct X3D_Node *affector){
4621  //called from 2nd, big loop in startofloopnodeupdates to accumulate
4622  // a list of nodes that affect their siblings, to store in parent
4623  // as alternate to VK_ flagging parent, and doing 3 full loops over children[] in X3DGrouping child_ functions
4624  // - a kind of short list so child_ functions do:
4625  // a short loop (prep_sibAffectors), full loop (normalChildren), short loop (fin_sibAffectors)
4626 
4627 //JAS
4628 if (parent==NULL) {
4629 printf ("in AddToSibAffectors, we have node parent NULL, node is a %s\n",stringNodeType(affector->_nodeType));
4630 }
4631 
4632 
4633  if(hasSiblingAffectorField(parent,__LINE__) && isSiblingAffector(affector)){
4634  struct Multi_Node *safs = sibAffectorPtr(parent);
4635  if(safs){
4636  safs->p = REALLOC(safs->p,(safs->n+1)*sizeof(struct X3D_Node*));
4637  safs->p[safs->n] = affector;
4638  safs->n += 1;
4639  }
4640  }
4641 }
4642 void zeroSibAffectors(struct X3D_Node *node){
4643  //called from first loop in startofloopnodeupdates
4644  //we clear on each frame, then re-populate
4645  struct Multi_Node* saf = sibAffectorPtr(node);
4646  saf->n = 0; //not freeing p, will realloc in AddToSibAffectors
4647  // Q. fragging/memory fragmentation? Multi_Node.nalloc needed?
4648  // alternate to reallocs and MF.nalloc:
4649  // 1. here go through p[] and set each one to NULL, but leave n.
4650  // 2. then in Add, look for first null, realloc only if too short.
4651  // 3. then in prep_sibAffectors and fin_sibAffectors check if entry is null and skip.
4652 }
4653 
4654 //dug9 dec 13 <<
4655 int needs_updating_Inline(struct X3D_Node *node);
4656 void update_Inline(struct X3D_Inline *node);
4657 // Dec 14, 2012 new proto IS-A version (see below for older version)
4658 void startOfLoopNodeUpdates(void) {
4659  struct X3D_Node* node;
4660  struct X3D_Node* pnode;
4661  struct X3D_Anchor* anchorPtr;
4662  struct Vector *parentVector;
4663  int nParents;
4664  int i,j,k,foundbound;
4665  int* setBindPtr;
4666 
4667  struct Multi_Node *addChildren;
4668  struct Multi_Node *removeChildren;
4669  struct Multi_Node *childrenPtr;
4670  size_t offsetOfChildrenPtr;
4671 
4672  /* process one inline per loop; do it outside of the lock/unlock memory table */
4673  //struct Vector *loadInlines;
4674  ppOpenGL_Utils p;
4675  ttglobal tg = gglobal();
4676  p = (ppOpenGL_Utils)tg->OpenGL_Utils.prv;
4677 
4678  if (rootNode() == NULL) return; /* nothing to do, and we have not really started yet */
4679 
4680  /* initialization */
4681  addChildren = NULL;
4682  removeChildren = NULL;
4683  childrenPtr = NULL;
4684  parentVector = NULL;
4685  //loadInlines = NULL;
4686  offsetOfChildrenPtr = 0;
4687 
4688  /* assume that we do not have any sensitive nodes at all... */
4689  tg->Mainloop.HaveSensitive = FALSE;
4690  tg->RenderFuncs.have_transparency = FALSE;
4691 
4692 
4693  /* do not bother doing this if the inputparsing thread is active */
4694  if (fwl_isinputThreadParsing()) return;
4695  profile_start("loopnodeupdt");
4696  LOCK_MEMORYTABLE
4697 
4698  //printf ("\n******************************************\nstartOfLoopNodeUpdates\n");
4699 
4700  /* go through the node table, and zero any bits of interest */
4701 
4702  for (i=0; i<vectorSize(p->linearNodeTable); i++){
4703  node = vector_get(struct X3D_Node *,p->linearNodeTable,i);
4704  if (node != NULL) {
4705  if (node->referenceCount <= 0) {
4706  //unload_brotos -a new way to clean out an old scene of 2014- doesn't rely on reference counting
4707  // when cleaning up a scene - it calls unregisterX3Dnode()
4708  //ConsoleMessage ("%d ref %d\n",i,node->referenceCount);
4709  //killNode(i);
4710 
4711  //JAS printf ("node %p has zero reference count...it is a %s\n",
4712  //JAS node,stringNodeType(node->_nodeType));
4713  FREE_IF_NZ(node);
4714  vector_set(struct X3D_Node *,p->linearNodeTable,i,NULL);
4715  } else {
4716  /* turn OFF these flags */
4717  node->_renderFlags = node->_renderFlags & (0xFFFF^VF_Sensitive);
4718  node->_renderFlags = node->_renderFlags & (0xFFFF^VF_Viewpoint);
4719  node->_renderFlags = node->_renderFlags & (0xFFFF^VF_localLight);
4720  node->_renderFlags = node->_renderFlags & (0xFFFF^VF_globalLight);
4721  node->_renderFlags = node->_renderFlags & (0xFFFF^VF_Blend);
4722 //JAS - move this within the ELSE statement as node is free'd by this time.
4723  if(hasSiblingAffectorField(node,__LINE__)){
4724  zeroSibAffectors(node);
4725  }
4726  }
4727  }
4728  }
4729  /* turn OFF these flags */
4730  {
4731  struct X3D_Node* rn = rootNode();
4732  rn->_renderFlags = rn->_renderFlags & (0xFFFF^VF_Sensitive);
4733  rn->_renderFlags = rn->_renderFlags & (0xFFFF^VF_Viewpoint);
4734  rn->_renderFlags = rn->_renderFlags & (0xFFFF^VF_localLight);
4735  rn->_renderFlags = rn->_renderFlags & (0xFFFF^VF_globalLight);
4736  rn->_renderFlags = rn->_renderFlags & (0xFFFF^VF_Blend);
4737  }
4738 
4739  /* sort the rootNode, if it is Not NULL */
4740  /* remember, the rootNode is not in the linearNodeTable, so we have to do this outside
4741  of that loop */
4742  if (rootNode() != NULL) {
4743  struct Multi_Node *children, *_sortedChildren;
4744  node = (struct X3D_Node*)rootNode();
4745  children = NULL;
4746  _sortedChildren = NULL;
4747  if(node->_nodeType == NODE_Proto){
4748  children = &X3D_PROTO(node)->__children;
4749  _sortedChildren = &X3D_PROTO(node)->_sortedChildren;
4750  }
4751  if(node->_nodeType == NODE_Group) {
4752  children = &X3D_GROUP(node)->children;
4753  _sortedChildren = &X3D_GROUP(node)->_sortedChildren;
4754  }
4755  sortChildren (__LINE__,children, _sortedChildren,rootNode()->_renderFlags & VF_shouldSortChildren);
4756  rootNode()->_renderFlags=rootNode()->_renderFlags & (0xFFFF^VF_shouldSortChildren);
4757  if(node->_nodeType == NODE_Proto){
4758  //CHILDREN_NODE(Proto)
4759  /* DRracer/t85.wrl has 'children' user fields on protos. This works with other browsers.
4760  But not freewrl. Unless I hide the children field as _children. Then it works.
4761  */
4762  addChildren = NULL; removeChildren = NULL;
4763  offsetOfChildrenPtr = offsetof (struct X3D_Proto, __children);
4764  if (((struct X3D_Proto *)node)->addChildren.n > 0) {
4765  addChildren = &((struct X3D_Proto *)node)->addChildren;
4766  childrenPtr = &((struct X3D_Proto *)node)->__children;
4767  }
4768  if (((struct X3D_Proto *)node)->removeChildren.n > 0) {
4769  removeChildren = &((struct X3D_Proto *)node)->removeChildren;
4770  childrenPtr = &((struct X3D_Proto *)node)->__children;
4771  }
4772 
4773  }else{
4774  CHILDREN_NODE(Group)
4775  }
4776  /* this node possibly has to do add/remove children? */
4777  if (childrenPtr != NULL) {
4778  if (addChildren != NULL) {
4779  AddRemoveChildren(node,childrenPtr,(struct X3D_Node * *) addChildren->p,addChildren->n,1,__FILE__,__LINE__);
4780  addChildren->n=0;
4781  }
4782  if (removeChildren != NULL) {
4783  AddRemoveChildren(node,childrenPtr,(struct X3D_Node * *) removeChildren->p,removeChildren->n,2,__FILE__,__LINE__);
4784  removeChildren->n=0;
4785  }
4786  /* printf ("OpenGL, marking children changed\n"); */
4787  MARK_EVENT(node,offsetOfChildrenPtr);
4788  childrenPtr = NULL;
4789  }
4790  }
4791 
4792  /* go through the list of nodes, and "work" on any that need work */
4793  nParents = 0;
4794  setBindPtr = NULL;
4795  anchorPtr = NULL;
4796 
4797 
4798  for (i=0; i<vectorSize(p->linearNodeTable); i++){
4799  node = vector_get(struct X3D_Node *,p->linearNodeTable,i);
4800  if (node != NULL)
4801  if (node->referenceCount > 0) {
4802  pnode = node;
4803  node = getTypeNode(node); //+ dug9 dec 13
4804  if(node == NULL && pnode != NULL) //+ dug9 sept 2014
4805  if(pnode->_nodeType == NODE_Proto){
4806  UNLOCK_MEMORYTABLE
4807  /*dug9 sept 2014: I put load_EPI (externProtoInstance) here because I designed it like Inline
4808  where we check and give a time slice to loading when we visit the node instance during render().
4809  But that doesn't work for EPIs which have no concrete NODE type, nor VF_ flag
4810  so render_hier/render() never visits them until they are loaded and we can
4811  see the concrete type of their first node, and perculate VF_ flags up to the EPI
4812  There were other options such as event queue, or following a cascade of protoInstance arrays
4813  down the context heirarchy, or tinkering with the VF_ flag visitation rules in render()
4814  or inventing a VF_Proto flag, or expanding the role of the resource thread to do more work
4815  and keep a list of subscribers with the EPD (externProtoDeclare).
4816  And any of those might work too. This was just convenient/easy/quick
4817  for me, so feel free to move it.
4818  */
4819  load_externProtoInstance(X3D_PROTO(pnode));
4820  LOCK_MEMORYTABLE
4821  node = getTypeNode(pnode);
4822  }
4823  if (node != NULL)
4824  //switch (node->_nodeType) { //- dug9 dec 13
4825  switch (node->_nodeType) { //+ dug9 dec 13
4826  BEGIN_NODE(Shape)
4827  /* send along a "look at me" flag if we are visible, or we should look again */
4828  if ((X3D_SHAPE(node)->__occludeCheckCount <=0) ||
4829  (X3D_SHAPE(node)->__visible)) {
4830  update_renderFlag (X3D_NODE(pnode),VF_hasVisibleChildren);
4831  /* printf ("shape occludecounter, pushing visiblechildren flags\n"); */
4832 
4833  }
4834  X3D_SHAPE(node)->__occludeCheckCount--;
4835  /* printf ("shape occludecounter %d\n",X3D_SHAPE(node)->__occludeCheckCount); */
4836  END_NODE
4837 
4838  /* Lights. DirectionalLights are "scope relative", PointLights and
4839  SpotLights are transformed */
4840 
4841  BEGIN_NODE(DirectionalLight)
4842  if (X3D_DIRECTIONALLIGHT(node)->on) {
4843  if (X3D_DIRECTIONALLIGHT(node)->global)
4844  update_renderFlag(pnode,VF_globalLight);
4845  else{
4846  //LOCAL_LIGHT_PARENT_FLAG
4847  ADD_TO_PARENT_SIBAFFECTORS
4848  }
4849  }
4850  END_NODE
4851  BEGIN_NODE(SpotLight)
4852  if (X3D_SPOTLIGHT(node)->on) {
4853  if (X3D_SPOTLIGHT(node)->global)
4854  update_renderFlag(pnode,VF_globalLight);
4855  else{
4856  //LOCAL_LIGHT_PARENT_FLAG
4857  ADD_TO_PARENT_SIBAFFECTORS
4858  }
4859  }
4860  END_NODE
4861  BEGIN_NODE(PointLight)
4862  if (X3D_POINTLIGHT(node)->on) {
4863  if (X3D_POINTLIGHT(node)->global)
4864  update_renderFlag(pnode,VF_globalLight);
4865  else{
4866  //LOCAL_LIGHT_PARENT_FLAG
4867  ADD_TO_PARENT_SIBAFFECTORS
4868  }
4869  }
4870  END_NODE
4871  BEGIN_NODE(LocalFog)
4872  ADD_TO_PARENT_SIBAFFECTORS
4873  END_NODE
4874  BEGIN_NODE(ClipPlane)
4875  ADD_TO_PARENT_SIBAFFECTORS
4876  END_NODE
4877  BEGIN_NODE(Effect)
4878  ADD_TO_PARENT_SIBAFFECTORS
4879  END_NODE
4880 
4881 
4882  /* some nodes, like Extrusions, have "set_" fields same as normal internal fields,
4883  eg, "set_spine" and "spine". Here we just copy the fields over, and remove the
4884  "set_" fields. This works for MF* fields ONLY */
4885  BEGIN_NODE(IndexedLineSet)
4886  EVIN_AND_FIELD_SAME(colorIndex,IndexedLineSet)
4887  EVIN_AND_FIELD_SAME(coordIndex,IndexedLineSet)
4888  END_NODE
4889 
4890  BEGIN_NODE(IndexedTriangleFanSet)
4891  EVIN_AND_FIELD_SAME(index,IndexedTriangleFanSet)
4892  END_NODE
4893  BEGIN_NODE(IndexedTriangleSet)
4894  EVIN_AND_FIELD_SAME(index,IndexedTriangleSet)
4895  END_NODE
4896  BEGIN_NODE(IndexedTriangleStripSet)
4897  EVIN_AND_FIELD_SAME(index,IndexedTriangleStripSet)
4898  END_NODE
4899  BEGIN_NODE(GeoElevationGrid)
4900  EVIN_AND_FIELD_SAME(height,GeoElevationGrid)
4901  END_NODE
4902  BEGIN_NODE(ElevationGrid)
4903  EVIN_AND_FIELD_SAME(height,ElevationGrid)
4904  END_NODE
4905  BEGIN_NODE(Extrusion)
4906  EVIN_AND_FIELD_SAME(crossSection,Extrusion)
4907  EVIN_AND_FIELD_SAME(orientation,Extrusion)
4908  EVIN_AND_FIELD_SAME(scale,Extrusion)
4909  EVIN_AND_FIELD_SAME(spine,Extrusion)
4910  END_NODE
4911  BEGIN_NODE(IndexedFaceSet)
4912  EVIN_AND_FIELD_SAME(colorIndex,IndexedFaceSet)
4913  EVIN_AND_FIELD_SAME(coordIndex,IndexedFaceSet)
4914  EVIN_AND_FIELD_SAME(normalIndex,IndexedFaceSet)
4915  EVIN_AND_FIELD_SAME(texCoordIndex,IndexedFaceSet)
4916  END_NODE
4917 /* GeoViewpoint works differently than other nodes - see compile_GeoViewpoint for manipulation of these fields
4918  BEGIN_NODE(GeoViewpoint)
4919  EVIN_AND_FIELD_SAME(orientation,GeoViewpoint)
4920  EVIN_AND_FIELD_SAME(position,GeoViewpoint)
4921  END_NODE
4922 */
4923 
4924  /* get ready to mark these nodes as Mouse Sensitive */
4925  BEGIN_NODE(LineSensor) SIBLING_SENSITIVE(LineSensor) END_NODE
4926  BEGIN_NODE(PlaneSensor) SIBLING_SENSITIVE(PlaneSensor) END_NODE
4927  BEGIN_NODE(SphereSensor) SIBLING_SENSITIVE(SphereSensor) END_NODE
4928  BEGIN_NODE(CylinderSensor) SIBLING_SENSITIVE(CylinderSensor) END_NODE
4929  BEGIN_NODE(TouchSensor) SIBLING_SENSITIVE(TouchSensor) END_NODE
4930  BEGIN_NODE(GeoTouchSensor) SIBLING_SENSITIVE(GeoTouchSensor) END_NODE
4931 
4932  /* Anchor is Mouse Sensitive, AND has Children nodes */
4933  BEGIN_NODE(Anchor)
4934  propagateExtent(X3D_NODE(node));
4935  ANCHOR_SENSITIVE(Anchor)
4936  CHILDREN_NODE(Anchor)
4937  END_NODE
4938 
4939  BEGIN_NODE(CADFace)
4940  // the attached Shape node will do the occlusion testing, if enabled.
4941  update_renderFlag (X3D_NODE(pnode),VF_hasVisibleChildren);
4942  END_NODE
4943 
4944  BEGIN_NODE(CADLayer)
4945  propagateExtent(X3D_NODE(node));
4946  CHILDREN_NODE(Switch)
4947  END_NODE
4948 
4949 
4950  BEGIN_NODE(CADPart)
4951  sortChildren (__LINE__,&X3D_CADPART(node)->children,&X3D_CADPART(node)->_sortedChildren,pnode->_renderFlags & VF_shouldSortChildren);
4952  TURN_OFF_SHOULDSORTCHILDREN
4953  propagateExtent(X3D_NODE(node));
4954  CHILDREN_NODE(CADPart)
4955  END_NODE
4956 
4957 
4958  BEGIN_NODE(CADAssembly)
4959  sortChildren (__LINE__,&X3D_CADASSEMBLY(node)->children,&X3D_CADASSEMBLY(node)->_sortedChildren,pnode->_renderFlags & VF_shouldSortChildren);
4960  TURN_OFF_SHOULDSORTCHILDREN
4961  propagateExtent(X3D_NODE(node));
4962  CHILDREN_NODE(CADAssembly)
4963  END_NODE
4964 
4965  /* maybe this is the current Viewpoint? */
4966  BEGIN_NODE(Viewpoint) BINDABLE(Viewpoint) END_NODE
4967  BEGIN_NODE(OrthoViewpoint) BINDABLE(OrthoViewpoint) END_NODE
4968  BEGIN_NODE(GeoViewpoint) BINDABLE(GeoViewpoint) END_NODE
4969 
4970  BEGIN_NODE(NavigationInfo)
4971  //render_NavigationInfo ((struct X3D_NavigationInfo *)node);
4972  BINDABLE(NavigationInfo)
4973  END_NODE
4974 
4975  BEGIN_NODE(StaticGroup)
4976  /* we should probably not do this, but... */
4977  sortChildren (__LINE__,&X3D_STATICGROUP(node)->children,&X3D_STATICGROUP(node)->_sortedChildren,pnode->_renderFlags & VF_shouldSortChildren);
4978  TURN_OFF_SHOULDSORTCHILDREN
4979  propagateExtent(X3D_NODE(node));
4980  END_NODE
4981 
4982 
4983  /* does this one possibly have add/removeChildren? */
4984  BEGIN_NODE(Group)
4985  sortChildren (__LINE__,&X3D_GROUP(node)->children,&X3D_GROUP(node)->_sortedChildren,pnode->_renderFlags & VF_shouldSortChildren);
4986  TURN_OFF_SHOULDSORTCHILDREN
4987  propagateExtent(X3D_NODE(node));
4988  CHILDREN_NODE(Group)
4989  END_NODE
4990 
4991  BEGIN_NODE(PickableGroup)
4992  //sortChildren (__LINE__,&X3D_PICKABLEGROUP(node)->children,&X3D_PICKABLEGROUP(node)->_sortedChildren,pnode->_renderFlags & VF_shouldSortChildren);
4993  //TURN_OFF_SHOULDSORTCHILDREN
4994  propagateExtent(X3D_NODE(node));
4995  CHILDREN_NODE(PickableGroup)
4996  END_NODE
4997 
4998  BEGIN_NODE(Inline)
4999  sortChildren (__LINE__,&X3D_INLINE(node)->__children,&X3D_INLINE(node)->_sortedChildren,node->_renderFlags & VF_shouldSortChildren);
5000  TURN_OFF_SHOULDSORTCHILDREN
5001  propagateExtent(X3D_NODE(node));
5002  CHILDREN_ANY_NODE(Inline,__children)
5003  END_NODE
5004 
5005  BEGIN_NODE(Transform)
5006  sortChildren (__LINE__,&X3D_TRANSFORM(node)->children,&X3D_TRANSFORM(node)->_sortedChildren,pnode->_renderFlags & VF_shouldSortChildren);
5007  TURN_OFF_SHOULDSORTCHILDREN
5008  propagateExtent(X3D_NODE(node));
5009  CHILDREN_NODE(Transform)
5010  END_NODE
5011 
5012 
5013 
5014 /* BEGIN_NODE(NurbsGroup)
5015  CHILDREN_NODE(NurbsGroup)
5016  END_NODE
5017 */
5018  BEGIN_NODE(Contour2D)
5019  CHILDREN_NODE(Contour2D)
5020  END_NODE
5021 
5022  BEGIN_NODE(HAnimSite)
5023  CHILDREN_NODE(HAnimSite)
5024  END_NODE
5025 
5026  BEGIN_NODE(HAnimSegment)
5027  CHILDREN_NODE(HAnimSegment)
5028  END_NODE
5029 
5030  BEGIN_NODE(HAnimJoint)
5031  CHILDREN_NODE(HAnimJoint)
5032  END_NODE
5033 
5034  BEGIN_NODE(Billboard)
5035  propagateExtent(X3D_NODE(node));
5036  CHILDREN_NODE(Billboard)
5037  update_renderFlag(pnode,VF_Proximity);
5038  END_NODE
5039 
5040  BEGIN_NODE(Collision)
5041  propagateExtent(X3D_NODE(node));
5042  CHILDREN_NODE(Collision)
5043  END_NODE
5044 
5045  BEGIN_NODE(Switch)
5046  propagateExtent(X3D_NODE(node));
5047  CHILDREN_SWITCH_NODE(Switch)
5048  END_NODE
5049 
5050  BEGIN_NODE(LOD)
5051  propagateExtent(X3D_NODE(node));
5052  CHILDREN_LOD_NODE
5053  update_renderFlag(pnode,VF_Proximity);
5054  END_NODE
5055 
5056  /* Material - transparency of materials */
5057  BEGIN_NODE(Material) CHECK_MATERIAL_TRANSPARENCY END_NODE
5058  BEGIN_NODE(TwoSidedMaterial) CHECK_TWOSIDED_MATERIAL_TRANSPARENCY END_NODE
5059  BEGIN_NODE(FillProperties) CHECK_FILL_PROPERTY_FILLED END_NODE
5060 
5061  /* Textures - check transparency */
5062  BEGIN_NODE(ImageTexture) CHECK_IMAGETEXTURE_TRANSPARENCY END_NODE
5063  BEGIN_NODE(PixelTexture) CHECK_PIXELTEXTURE_TRANSPARENCY END_NODE
5064  BEGIN_NODE(MovieTexture) CHECK_MOVIETEXTURE_TRANSPARENCY END_NODE
5065 
5066  BEGIN_NODE(VolumeData)
5067  tg->RenderFuncs.have_transparency = TRUE;
5068  update_renderFlag(X3D_NODE(pnode),VF_Blend | VF_shouldSortChildren);\
5069  END_NODE
5070  BEGIN_NODE(SegmentedVolumeData)
5071  tg->RenderFuncs.have_transparency = TRUE;
5072  update_renderFlag(X3D_NODE(pnode),VF_Blend | VF_shouldSortChildren);\
5073  END_NODE
5074  BEGIN_NODE(IsoSurfaceVolumeData)
5075  tg->RenderFuncs.have_transparency = TRUE;
5076  update_renderFlag(X3D_NODE(pnode),VF_Blend | VF_shouldSortChildren);\
5077  END_NODE
5078 
5079 
5080  /* Backgrounds, Fog */
5081  BEGIN_NODE(Background)
5082  BINDABLE(Background)
5083  //if (X3D_BACKGROUND(node)->isBound) update_renderFlag (X3D_NODE(pnode),VF_hasVisibleChildren);
5084  END_NODE
5085 
5086  BEGIN_NODE(TextureBackground)
5087  BINDABLE(TextureBackground)
5088  //if (X3D_TEXTUREBACKGROUND(node)->isBound) update_renderFlag (X3D_NODE(pnode),VF_hasVisibleChildren);
5089  END_NODE
5090 
5091  BEGIN_NODE(Fog)
5092  BINDABLE(Fog)
5093  //if (X3D_FOG(node)->isBound) update_renderFlag (X3D_NODE(pnode),VF_hasVisibleChildren);
5094  END_NODE
5095 
5096 
5097  /* VisibilitySensor needs its own flag sent up the chain */
5098  BEGIN_NODE (VisibilitySensor)
5099  #ifdef OCCLUSION_STUFF
5100  /* send along a "look at me" flag if we are visible, or we should look again */
5101  if ((X3D_VISIBILITYSENSOR(node)->__occludeCheckCount <=0) ||
5102  (X3D_VISIBILITYSENSOR(node)->__visible)) {
5103  update_renderFlag (X3D_NODE(pnode),VF_hasVisibleChildren);
5104  /* printf ("vis occludecounter, pushing visiblechildren flags\n"); */
5105 
5106  }
5107  X3D_VISIBILITYSENSOR(node)->__occludeCheckCount--;
5108  /* VisibilitySensors have a transparent bounding box we have to render */
5109 
5110  update_renderFlag(pnode,VF_Blend & VF_shouldSortChildren);
5111  #else //simple AABB
5112  //pnode->_renderFlags = VF_Other;
5113  //X3D_VISIBILITYSENSOR(node)->__Samples = 0; //cleared at end of do_visibilitysensor
5114  update_renderFlag(pnode,VF_Other);
5115  #endif
5116  END_NODE
5117 
5118  /* ProximitySensor needs its own flag sent up the chain */
5119  BEGIN_NODE (ProximitySensor)
5120  if (X3D_PROXIMITYSENSOR(node)->enabled) update_renderFlag(pnode,VF_Proximity);
5121  END_NODE
5122 
5123  /* GeoProximitySensor needs its own flag sent up the chain */
5124  BEGIN_NODE (GeoProximitySensor)
5125  if (X3D_GEOPROXIMITYSENSOR(node)->enabled) update_renderFlag(pnode,VF_Proximity);
5126  END_NODE
5127 
5128  /* GeoLOD needs its own flag sent up the chain, and it has to push extent up, too */
5129  BEGIN_NODE (GeoLOD)
5130  if (!(NODE_NEEDS_COMPILING)) {
5131  handle_GeoLODRange(X3D_GEOLOD(node));
5132  }
5133  /* update_renderFlag(pnode,VF_Proximity); */
5134  propagateExtent(X3D_NODE(node));
5135  END_NODE
5136 
5137  BEGIN_NODE (GeoTransform)
5138  sortChildren (__LINE__,&X3D_GEOTRANSFORM(node)->children,&X3D_GEOTRANSFORM(node)->_sortedChildren,pnode->_renderFlags & VF_shouldSortChildren);
5139  TURN_OFF_SHOULDSORTCHILDREN
5140  propagateExtent(X3D_NODE(node));
5141  CHILDREN_NODE(GeoTransform)
5142  END_NODE
5143 
5144  BEGIN_NODE (GeoLocation)
5145  sortChildren (__LINE__,&X3D_GEOLOCATION(node)->children,&X3D_GEOLOCATION(node)->_sortedChildren,pnode->_renderFlags & VF_shouldSortChildren);
5146  TURN_OFF_SHOULDSORTCHILDREN
5147  propagateExtent(X3D_NODE(node));
5148  CHILDREN_NODE(GeoLocation)
5149  END_NODE
5150 
5151  BEGIN_NODE(MetadataSFBool) CMD(SFBool,node); END_NODE
5152  BEGIN_NODE(MetadataSFFloat) CMD(SFFloat,node); END_NODE
5153  BEGIN_NODE(MetadataMFFloat) CMD(MFFloat,node); END_NODE
5154  BEGIN_NODE(MetadataSFRotation) CMD(SFRotation,node); END_NODE
5155  BEGIN_NODE(MetadataMFRotation) CMD(MFRotation,node); END_NODE
5156  BEGIN_NODE(MetadataSFVec3f) CMD(SFVec3f,node); END_NODE
5157  BEGIN_NODE(MetadataMFVec3f) CMD(MFVec3f,node); END_NODE
5158  BEGIN_NODE(MetadataMFBool) CMD(MFBool,node); END_NODE
5159  BEGIN_NODE(MetadataSFInt32) CMD(SFInt32,node); END_NODE
5160  BEGIN_NODE(MetadataMFInt32) CMD(MFInt32,node); END_NODE
5161  BEGIN_NODE(MetadataSFNode) CMD(SFNode,node); END_NODE
5162  BEGIN_NODE(MetadataMFNode) CMD(MFNode,node); END_NODE
5163  BEGIN_NODE(MetadataSFColor) CMD(SFColor,node); END_NODE
5164  BEGIN_NODE(MetadataMFColor) CMD(MFColor,node); END_NODE
5165  BEGIN_NODE(MetadataSFColorRGBA) CMD(SFColorRGBA,node); END_NODE
5166  BEGIN_NODE(MetadataMFColorRGBA) CMD(MFColorRGBA,node); END_NODE
5167  BEGIN_NODE(MetadataSFTime) CMD(SFTime,node); END_NODE
5168  BEGIN_NODE(MetadataMFTime) CMD(MFTime,node); END_NODE
5169  BEGIN_NODE(MetadataSFString) CMD(SFString,node); END_NODE
5170  BEGIN_NODE(MetadataMFString) CMD(MFString,node); END_NODE
5171  BEGIN_NODE(MetadataSFVec2f) CMD(SFVec2f,node); END_NODE
5172  BEGIN_NODE(MetadataMFVec2f) CMD(MFVec2f,node); END_NODE
5173  BEGIN_NODE(MetadataSFImage) CMD(SFImage,node); END_NODE
5174  BEGIN_NODE(MetadataSFVec3d) CMD(SFVec3d,node); END_NODE
5175  BEGIN_NODE(MetadataMFVec3d) CMD(MFVec3d,node); END_NODE
5176  BEGIN_NODE(MetadataSFDouble) CMD(SFDouble,node); END_NODE
5177  BEGIN_NODE(MetadataMFDouble) CMD(MFDouble,node); END_NODE
5178  BEGIN_NODE(MetadataSFMatrix3f) CMD(SFMatrix3f,node); END_NODE
5179  BEGIN_NODE(MetadataMFMatrix3f) CMD(MFMatrix3f,node); END_NODE
5180  BEGIN_NODE(MetadataSFMatrix3d) CMD(SFMatrix3d,node); END_NODE
5181  BEGIN_NODE(MetadataMFMatrix3d) CMD(MFMatrix3d,node); END_NODE
5182  BEGIN_NODE(MetadataSFMatrix4f) CMD(SFMatrix4f,node); END_NODE
5183  BEGIN_NODE(MetadataMFMatrix4f) CMD(MFMatrix4f,node); END_NODE
5184  BEGIN_NODE(MetadataSFMatrix4d) CMD(SFMatrix4d,node); END_NODE
5185  BEGIN_NODE(MetadataMFMatrix4d) CMD(MFMatrix4d,node); END_NODE
5186  BEGIN_NODE(MetadataSFVec2d) CMD(SFVec2d,node); END_NODE
5187  BEGIN_NODE(MetadataMFVec2d) CMD(MFVec2d,node); END_NODE
5188  BEGIN_NODE(MetadataSFVec4f) CMD(SFVec4f,node); END_NODE
5189  BEGIN_NODE(MetadataMFVec4f) CMD(MFVec4f,node); END_NODE
5190  BEGIN_NODE(MetadataSFVec4d) CMD(SFVec4d,node); END_NODE
5191  BEGIN_NODE(MetadataMFVec4d) CMD(MFVec4d,node); END_NODE
5192  }
5193 
5194  }
5195 
5196 
5197  /* now, act on this node for Sensitive nodes. here we tell the PARENTS that they are sensitive */
5198  if (nParents != 0) {
5199  for (j=0; j<nParents; j++) {
5200  struct X3D_Node *n = vector_get(struct X3D_Node *, parentVector, j);
5201  n->_renderFlags = n->_renderFlags | VF_Sensitive;
5202  }
5203  /* tell mainloop that we have to do a sensitive pass now */
5204  tg->Mainloop.HaveSensitive = TRUE;
5205  nParents = 0;
5206  }
5207 
5208  /* Anchor nodes are slightly different than sibling-sensitive nodes */
5209  if (anchorPtr != NULL) {
5210  anchorPtr->_renderFlags = anchorPtr->_renderFlags | VF_Sensitive;
5211 
5212  /* tell mainloop that we have to do a sensitive pass now */
5213  tg->Mainloop.HaveSensitive = TRUE;
5214  anchorPtr = NULL;
5215  }
5216 
5217  /* do BINDING of Viewpoint Nodes */
5218  if (setBindPtr != NULL) {
5219  /* check the set_bind eventin to see if it is TRUE or FALSE */
5220  if (*setBindPtr < 100) {
5221  /* up_vector is reset after a bind */
5222  //if (*setBindPtr==1) reset_upvector();
5223  send_bind_to(node,*setBindPtr);
5224  //if(0){
5225  //bind_node (node, getActiveBindableStacks(tg)->viewpoint);
5226 
5230  //if (node->_nodeType==NODE_Viewpoint) {
5231  // struct X3D_Viewpoint* vp = (struct X3D_Viewpoint *) node;
5232  // bind_Viewpoint(vp);
5233  // setMenuStatusVP (vp->description->strptr);
5234  //} else if (node->_nodeType==NODE_OrthoViewpoint) {
5235  // struct X3D_OrthoViewpoint *ovp = (struct X3D_OrthoViewpoint *) node;
5236  // bind_OrthoViewpoint(ovp);
5237  // setMenuStatusVP (ovp->description->strptr);
5238  //} else {
5239  // struct X3D_GeoViewpoint *gvp = (struct X3D_GeoViewpoint *) node;
5240  // bind_GeoViewpoint(gvp);
5241  // setMenuStatusVP (gvp->description->strptr);
5242  //}
5243  //}
5244  }
5245  setBindPtr = NULL;
5246  }
5247 
5248  /* this node possibly has to do add/remove children? */
5249  if (childrenPtr != NULL) {
5250  //JAS printf ("ok, childrenPtr is NOT NULL in startOfLoopNodeUpdates\n");
5251  if (addChildren != NULL) {
5252  //int i;
5253  //for (i=0; i<addChildren->n; i++) {
5254  //struct X3D_Node *ch = X3D_NODE(addChildren->p[i]);
5255  //printf ("SOLNU: adding child indx %d, is %p\n",i,ch);
5256  //}
5257 
5258  AddRemoveChildren(node,childrenPtr,(struct X3D_Node * *) addChildren->p,addChildren->n,1,__FILE__,__LINE__);
5259 
5260  // now go through and tell the addChildren field that the
5261  // event has been processed.
5262  for (i=0; i<addChildren->n; i++) {
5263  struct X3D_Node *ch = X3D_NODE(addChildren->p[i]);
5264  remove_parent(ch,node);
5265  }
5266 
5267  addChildren->n=0;
5268  }
5269 
5270  if (removeChildren != NULL) {
5271  AddRemoveChildren(node,childrenPtr,(struct X3D_Node * *) removeChildren->p,removeChildren->n,2,__FILE__,__LINE__);
5272  // now go through and tell the addChildren field that the
5273  // event has been processed.
5274  for (i=0; i<removeChildren->n; i++) {
5275  struct X3D_Node *ch = X3D_NODE(removeChildren->p[i]);
5276  remove_parent(ch,node);
5277  }
5278  removeChildren->n=0;
5279  }
5280 
5281 
5282  /* printf ("OpenGL, marking children changed\n"); */
5283  MARK_EVENT(node,offsetOfChildrenPtr);
5284  childrenPtr = NULL;
5285  }
5286  }
5287 
5288 
5289 
5290  UNLOCK_MEMORYTABLE
5291 
5292  /* now, we can go and tell the grouping nodes which ones are the lucky ones that contain the current Viewpoint node */
5293  foundbound = FALSE;
5294  for(k=0;k<vectorSize(tg->Bindable.bstacks);k++){
5295  bindablestack *bstack = vector_get(bindablestack*,tg->Bindable.bstacks,k);
5296  //if (vectorSize(getActiveBindableStacks(tg)->viewpoint) > 0) {
5297  if( vectorSize(bstack->viewpoint) > 0){
5298  //ConsoleMessage ("going to updateRF on viewpoint, stack is %d in size\n", vectorSize(tg->Bindable.viewpoint_stack));
5299 
5300  //struct X3D_Node *boundvp = vector_back(struct X3D_Node*,getActiveBindableStacks(tg)->viewpoint);
5301  struct X3D_Node *boundvp = vector_back(struct X3D_Node*,bstack->viewpoint);
5302  update_renderFlag(boundvp, VF_Viewpoint);
5303  calculateNearFarplanes(boundvp, bstack->layerId);
5304  //update_renderFlag(vector_back(struct X3D_Node*,
5305  // tg->Bindable.viewpoint_stack), VF_Viewpoint);
5306  //calculateNearFarplanes(vector_back(struct X3D_Node*, tg->Bindable.viewpoint_stack));
5307  }
5308  }
5309  if(!foundbound){
5310  /* keep these at the defaults, if no viewpoint is present. */
5311  X3D_Viewer *viewer = Viewer();
5312  viewer->nearPlane = DEFAULT_NEARPLANE;
5313  viewer->farPlane = DEFAULT_FARPLANE;
5314  viewer->backgroundPlane = DEFAULT_BACKGROUNDPLANE;
5315  }
5316  profile_end("loopnodeupdt");
5317 
5318 }
5319 
5320 
5321 
5322 //#define VERBOSE 1
5323 void markForDispose(struct X3D_Node *node, int recursive){
5324 
5325  int *fieldOffsetsPtr;
5326  char * fieldPtr;
5327 
5328  if (node==NULL) return;
5329  if (node==X3D_NODE(rootNode()) && node->_nodeType != NODE_Proto) {
5330  ConsoleMessage ("not disposing rootNode");
5331  return;
5332  }
5333 
5334 
5335  #ifdef VERBOSE
5336  ConsoleMessage ("\nmarkingForDispose %p (%s) currently at %d",node,
5337  stringNodeType(node->_nodeType),node->referenceCount);
5338  #endif
5339 
5340 
5341  if (node->referenceCount > 0)
5342  node->referenceCount--;
5343  else
5344  return; //already marked
5345 
5346  if (recursive) {
5347 
5348  /* cast a "const int" to an "int" */
5349  fieldOffsetsPtr = (int*) NODE_OFFSETS[node->_nodeType];
5350  /*go thru all field*/
5351  while (*fieldOffsetsPtr != -1) {
5352  fieldPtr = offsetPointer_deref(char *, node,*(fieldOffsetsPtr+1));
5353  #ifdef VERBOSE
5354  ConsoleMessage ("looking at field %s type %s",FIELDNAMES[*fieldOffsetsPtr],FIELDTYPES[*(fieldOffsetsPtr+2)]);
5355  #endif
5356 
5357  /* some fields we skip, as the pointers are duplicated, and we CAN NOT free both */
5358  if (*fieldOffsetsPtr == FIELDNAMES_setValue)
5359  break; /* can be a duplicate SF/MFNode pointer */
5360 
5361  if (*fieldOffsetsPtr == FIELDNAMES_valueChanged)
5362  break; /* can be a duplicate SF/MFNode pointer */
5363 
5364  if (*fieldOffsetsPtr == FIELDNAMES__selected)
5365  break; /* can be a duplicate SFNode pointer - field only in NODE_LOD and NODE_GeoLOD */
5366 
5367  if (*fieldOffsetsPtr == FIELDNAMES___oldChildren)
5368  break; /* can be a duplicate SFNode pointer - field only in NODE_LOD and NODE_GeoLOD */
5369 
5370  if (*fieldOffsetsPtr == FIELDNAMES___oldKeyPtr)
5371  break; /* used for seeing if interpolator values change */
5372 
5373  if (*fieldOffsetsPtr == FIELDNAMES___oldKeyValuePtr)
5374  break; /* used for seeing if interpolator values change */
5375 
5376  /* GeoLOD nodes, the children field exports either the rootNode, or the list of child nodes */
5377  if (node->_nodeType == NODE_GeoLOD) {
5378  if (*fieldOffsetsPtr == FIELDNAMES_children) break;
5379  }
5380 
5381  if (*fieldOffsetsPtr == FIELDNAMES__shaderUserDefinedFields)
5382  break; /* have to get rid of the fields of a shader here....*/
5383 
5384  /* nope, not a special field, lets just get rid of it as best we can */
5385  switch(*(fieldOffsetsPtr+2)){
5386  case FIELDTYPE_MFNode: {
5387  int i;
5388  struct Multi_Node* MNode;
5389  struct X3D_Node *tp;
5390 
5391  MNode=(struct Multi_Node *)fieldPtr;
5392  /* printf (" ... field MFNode, %s type %s\n",FIELDNAMES[*fieldOffsetsPtr],FIELDTYPES[*(fieldOffsetsPtr+2)]); */
5393 
5394  for (i=0; i<MNode->n; i++) {
5395  tp = MNode->p[i];
5396 
5397  if (tp!=NULL) {
5398  #ifdef VERBOSE
5399  ConsoleMessage ("calling markForDispose on node %p as it is an element of an MFNode",tp);
5400  #endif
5401  markForDispose(tp,TRUE);
5402  }
5403  }
5404  // MNode->n=0; unlink_node needs this in order to properly unlink children.
5405  break;
5406  }
5407  case FIELDTYPE_SFNode: {
5408  struct X3D_Node *SNode;
5409 
5410  memcpy(&SNode,fieldPtr,sizeof(struct X3D_Node *));
5411 
5412  #ifdef VERBOSE
5413  ConsoleMessage ("SFNode, field is %p...",SNode);
5414  if (SNode != NULL) {
5415  ConsoleMessage ("SFNode, .... and it is of type %s",stringNodeType(SNode->_nodeType));
5416  ConsoleMessage (" ... field SFNode, %s type %s\n",FIELDNAMES[*fieldOffsetsPtr],FIELDTYPES[*(fieldOffsetsPtr+2)]);
5417  }
5418  #endif
5419 
5420  if(SNode && SNode->referenceCount > 0) {
5421  #ifdef VERBOSE
5422  ConsoleMessage ("calling markForDispose on node %p as it is contents of SFNode field",SNode);
5423  #endif
5424  markForDispose(SNode, TRUE);
5425  }
5426  break;
5427 
5428 
5429  }
5430  default:; /* do nothing - field not malloc'd */
5431  }
5432  fieldOffsetsPtr+=5;
5433  }
5434 
5435 
5436  }
5437 }
5438 #undef VERBOSE
5439 
5440 #ifdef OLDCODE
5441 OLDCODE #define DELETE_IF_IN_PRODCON(aaa) \
5442 OLDCODE if (tg->ProdCon.aaa) { \
5443 OLDCODE bool foundIt = FALSE; \
5444 OLDCODE /* ConsoleMessage ("ProdCon stack is %d in size\n",vectorSize(tg->ProdCon.aaa)); */ \
5445 OLDCODE for (i=0; i<vectorSize(tg->ProdCon.aaa); i++) { \
5446 OLDCODE if (vector_get(struct X3D_Node*,tg->ProdCon.aaa, i) == structptr) { \
5447 OLDCODE foundIt = TRUE; \
5448 OLDCODE /* ConsoleMessage ("found it in the stack!\n"); */ \
5449 OLDCODE } \
5450 OLDCODE } \
5451 OLDCODE if (foundIt) { \
5452 OLDCODE struct Vector *newStack = newVector(struct X3D_Node*, 2); \
5453 OLDCODE for (i=0; i<vectorSize(tg->ProdCon.aaa); i++) { \
5454 OLDCODE if (vector_get(struct X3D_Node*,tg->ProdCon.aaa, i) != structptr) { \
5455 OLDCODE vector_pushBack(struct X3D_Node*, newStack, \
5456 OLDCODE vector_get(struct X3D_Node*,tg->ProdCon.aaa,i)); \
5457 OLDCODE } \
5458 OLDCODE } \
5459 OLDCODE deleteVector(struct X3D_Node*, tg->ProdCon.aaa); \
5460 OLDCODE tg->ProdCon.aaa = newStack; \
5461 OLDCODE } \
5462 OLDCODE }
5463 OLDCODE
5464 OLDCODE #define DELETE_IF_IN_STACK(aaa) \
5465 OLDCODE if (tg->Bindable.aaa) { \
5466 OLDCODE bool foundIt = FALSE; \
5467 OLDCODE /* ConsoleMessage ("Bindable stack is %d in size\n",vectorSize(tg->Bindable.aaa)); */ \
5468 OLDCODE for (i=0; i<vectorSize(tg->Bindable.aaa); i++) { \
5469 OLDCODE if (vector_get(struct X3D_Node*,tg->Bindable.aaa, i) == structptr) { \
5470 OLDCODE foundIt = TRUE; \
5471 OLDCODE /* ConsoleMessage ("found it in the stack!\n"); */ \
5472 OLDCODE } \
5473 OLDCODE } \
5474 OLDCODE if (foundIt) { \
5475 OLDCODE struct Vector *newStack = newVector(struct X3D_Node*, 2); \
5476 OLDCODE for (i=0; i<vectorSize(tg->Bindable.aaa); i++) { \
5477 OLDCODE if (vector_get(struct X3D_Node*,tg->Bindable.aaa, i) != structptr) { \
5478 OLDCODE vector_pushBack(struct X3D_Node*, newStack, \
5479 OLDCODE vector_get(struct X3D_Node*,tg->Bindable.aaa,i)); \
5480 OLDCODE } \
5481 OLDCODE } \
5482 OLDCODE deleteVector(struct X3D_Node*, tg->Bindable.aaa); \
5483 OLDCODE tg->Bindable.aaa = newStack; \
5484 OLDCODE } \
5485 OLDCODE }
5486 #endif //OLDCODE
5487 
5488 //#define WRLMODE(val) (((val) % 4)+4) //jan 2013 codegen PROTOKEYWORDS[] was ordered with x3d synonyms first, wrl last
5489 //#define X3DMODE(val) ((val) % 4)
5490 
5491 // OLDCODE #ifndef DISABLER
5492 BOOL walk_fields(struct X3D_Node* node, BOOL (*callbackFunc)(), void* callbackData)
5493 // OLDCODE #else
5494 // OLDCODE BOOL walk_fields(struct X3D_Node* node, BOOL (*callbackFunc)(void *callbackData,struct X3D_Node* node,int jfield,union anyVrml *fieldPtr,
5495 // OLDCODE const char *fieldName, indexT mode, indexT type,int isource,BOOL publicfield), void* callbackData)
5496 // OLDCODE #endif
5497 {
5498  //field isource: 0=builtin 1=script user field 2=shader_program user field 3=Proto/Broto user field 4=group __protoDef
5499  int type,mode,source;
5500  BOOL publicfield;
5501  int *fieldOffsetsPtr;
5502  int jfield;
5503  union anyVrml *fieldPtr;
5504  const char* fname;
5505  int foundField = 0;
5506 
5507  source = -1;
5508  mode = 0;
5509  type = 0;
5510  fieldPtr = NULL;
5511  jfield = -1;
5512  // field/event exists on the node?
5513  fieldOffsetsPtr = (int *)NODE_OFFSETS[node->_nodeType];
5514  /*go thru all builtin fields (borrowed from OpenGL_Utils killNode() L.3705*/
5515  while (*fieldOffsetsPtr != -1) {
5516  fname = FIELDNAMES[fieldOffsetsPtr[0]];
5517  //skip private fields which scene authors shouldn't be routing or ISing to
5518  publicfield = fname && (fname[0] != '_') ? TRUE : FALSE;
5519  mode = PKW_from_KW(fieldOffsetsPtr[3]);
5520  type = fieldOffsetsPtr[2];
5521  //retrieve nodeinstance values
5522  fieldPtr = (union anyVrml*)offsetPointer_deref(char *, node,*(fieldOffsetsPtr+1));
5523  source = 0;
5524  jfield++;
5525  foundField = callbackFunc(callbackData,node,jfield,fieldPtr,fname,mode,type,source,publicfield);
5526  if( foundField )break;
5527  fieldOffsetsPtr+=5;
5528  }
5529  if(!foundField)
5530  {
5531  //user-field capable node?
5532  int user;
5533  user = nodeTypeSupportsUserFields(node);
5534  jfield = -1;
5535  publicfield = 1; //assume all user fields are public
5536  if(user)
5537  {
5538  //lexer_stringUser_fieldName(me->lexer, name, mode);
5539  //struct VRMLParser* parser;
5540  //struct VRMLLexer* lexer;
5541  //ttglobal tg = gglobal();
5542  //lexer = NULL;
5543  //parser = tg->CParse.globalParser;
5544  //if (parser)
5545  // lexer = parser->lexer;
5546 
5547  //user fields on user-field-capable nodes
5548  switch(node->_nodeType)
5549  {
5550  case NODE_Script:
5551  case NODE_ComposedShader:
5552  case NODE_ShaderProgram :
5553  case NODE_Effect :
5554  case NODE_PackagedShader:
5555  {
5556  int j; //, nameIndex;
5557  struct ScriptFieldDecl* sfield;
5558  struct Shader_Script* shader = NULL;
5559 
5560  switch(node->_nodeType)
5561  {
5562  case NODE_Script: shader =(struct Shader_Script *)(X3D_SCRIPT(node)->__scriptObj); break;
5563  case NODE_ComposedShader: shader =(struct Shader_Script *)(X3D_COMPOSEDSHADER(node)->_shaderUserDefinedFields); break;
5564  case NODE_ShaderProgram: shader =(struct Shader_Script *)(X3D_SHADERPROGRAM(node)->_shaderUserDefinedFields); break;
5565  case NODE_PackagedShader: shader =(struct Shader_Script *)(X3D_PACKAGEDSHADER(node)->_shaderUserDefinedFields); break;
5566  case NODE_Effect: shader =(struct Shader_Script *)(X3D_EFFECT(node)->_shaderUserDefinedFields); break;
5567  }
5568  if (shader)
5569  for(j=0; j!=vectorSize(shader->fields); ++j)
5570  {
5571  sfield= vector_get(struct ScriptFieldDecl*, shader->fields, j);
5572  mode = sfield->fieldDecl->PKWmode;
5573  fname = ScriptFieldDecl_getName(sfield);
5574  type = sfield->fieldDecl->fieldType;
5575  fieldPtr = &sfield->value;
5576  source = node->_nodeType == NODE_Script ? 1 : 2;
5577  jfield = j;
5578  foundField = callbackFunc(callbackData,node,jfield,fieldPtr,fname,mode,type,source,publicfield);
5579  if( foundField)
5580  break;
5581  }
5582  }
5583  break;
5584  case NODE_Proto:
5585  {
5586  int j; //, nameIndex;
5587  struct ProtoFieldDecl* pfield;
5588  struct X3D_Proto* pnode = (struct X3D_Proto*)node;
5589  if(pnode) {
5590  struct ProtoDefinition* pstruct = (struct ProtoDefinition*) pnode->__protoDef;
5591  if(pstruct)
5592  if(pstruct->iface)
5593  for(j=0; j!=vectorSize(pstruct->iface); ++j)
5594  {
5595  pfield= vector_get(struct ProtoFieldDecl*, pstruct->iface, j);
5596  mode = pfield->mode;
5597  fname = pfield->cname;
5598  type = pfield->type;
5599  fieldPtr = &pfield->defaultVal;
5600  source = 3;
5601  jfield = j;
5602  foundField = callbackFunc(callbackData,node,jfield,fieldPtr,fname,mode,type,source,publicfield);
5603  if( foundField)
5604  break;
5605  }
5606  }
5607  }
5608  case NODE_Group:
5609  //not sure how to do it with the metanode interface and mangled names
5610  break;
5611  default:
5612  break;
5613  }
5614  }
5615  }
5616  return foundField;
5617 }
5618 
5619 
5620 /*
5621  memory management policy, Feb 22, 2013, dug9 after adding unlink_node() call to killNode()
5622  Background: we aren't using any smart pointers / garbage collection library in freewrl. Just old fashioned
5623  malloc and free, with one exception:
5624 
5625  We register malloced nodes in linearNodeTable, and when their reference
5626  count goes to zero we call killNode (which calls unlink_node()) and deallocate their memory.
5627 
5628  There's one place -startofloopnodeupdates- and one function -killNode- where they get deleted. But there's
5629  two basic scenarios:
5630  a) a node is markForDispose() during the freewrl session. tests/46.wrl
5631  b) you anchor or File > Open another scene. The old scene -in kill_OldWorld() markForDispose() calls
5632  referenceCount-- and then when the new scene comes into startofloopnodeupdates() all the old
5633  nodes trigger a call for killNode().
5634  So to test, I used 46.wrl and File>Open from the statusbar, and that would trigger some killNode activity
5635  (for FileOpen you can open an empty scene with just the vrml header, to simplify debugging)
5636 
5637  As I started to do this, freewrl bombed here and there with different data sets. One thing that will
5638  help is to be consistent about what we manage. For that have a policy: what malloced things we are
5639  managing now, so as programmers we are clear on what gets linked, and deleted. We'll call the carefully
5640  linked and unlinked and deallocated nodes 'managed nodes' and the fields we manage 'managed fields'.
5641 
5642  Examples,
5643  a) a node hold pointers to other nodes in its SFNode and MFNode fields such as 'children' and
5644  'material'. We'll call all those children.
5645  b) a node holds pointers to other nodes that have it as a child, in its parentVector.
5646  A DEF/USE pair of parent nodes mean the child's parentVector will have 2 entries, one for each
5647  of the DEF and USE.
5648 
5649  Here's the rule (I used) for managing nodes:
5650  - Definitions:
5651  public field: a field with no _ prefix on the name, or else its a user field in a Script/shader or Proto
5652  value holding field: initializeOnly/field or inputOutput/exposedField
5653  event field: inputOnly/eventIn or outputOnly/eventOut
5654  node field: SFNode or MFNode type
5655  managed field: value holding public node field, plus prescribed fields, minus exempted fields
5656  prescribed fields: fields we decided to also manage: (none)
5657  exempted fields: fields we decided not to manage: (none)
5658 
5659  - if a node is in a managed field of another node -a parent- then it
5660  registers/adds that parent in its own parentVector.
5661  - when the node is taken out/removed from a managed field, it removes the parent
5662  from its parentVector (if it's in just one managed field. If in 2, and removed from one, then parent stays)
5663  - when a node deletes itself, it:
5664  a) goes through all its managed fields and it tells those nodes -called children- to delete it
5665  from their parentVector. Then it clears/zeros that field in itself to zero so its not
5666  pointing at those children. And
5667  b) it goes through its parentVector and tells each parent to remove it from any managed fields.
5668  - if a node is in an event field or private field then it does not register that node in its parent field
5669  - if a node gets routed to an event field of a target node, no parent is registered.
5670  - if a node gets routed from an event field of a source node, the source node is not
5671  registerd in its parentVector (example: script node generates a node in an eventOut field,
5672  and whether or not it's routed anywhere, the script is not put into the nodes' parent list)
5673  HTH
5674 */
5675 BOOL isManagedField(int mode, int type, BOOL isPublic)
5676 {
5677  BOOL isManaged = (type == FIELDTYPE_SFNode || type == FIELDTYPE_MFNode);
5678  isManaged = isManaged && (mode == PKW_initializeOnly || mode == PKW_inputOutput);
5679  isManaged = isManaged && isPublic;
5680  return isManaged;
5681 }
5682 
5683 
5684 /* print the parent vector and and SFNode and MFNode subfield entry pointers
5685  for debugging unlink_node (and any linking code)
5686  -needs generalization for FILE*
5687  -maybe a dumpscreen option to get all rootnodes
5688 */
5689 void indentf(int indent){
5690  int m;
5691  for(m=0;m<indent;m++) printf(" ");
5692 }
5693 
5694 void print_node_links0(struct X3D_Node* sfn, int *level);
5695 BOOL cbPrintLinks(void *callbackData,struct X3D_Node* node,int jfield,
5696  union anyVrml *fieldPtr,char *fieldName, int mode,int type,int source,BOOL publicfield)
5697 {
5698  int *level = (int*)callbackData;
5699  (*level)++;
5700  //if((*level) > 80)
5701  // return FALSE;
5702  //if(publicfield && (type == FIELDTYPE_SFNode || type == FIELDTYPE_MFNode))
5703  if(isManagedField(type,mode,publicfield))
5704  {
5705  int n,k,haveSomething;
5706  struct X3D_Node **plist, *sfn;
5707  haveSomething = (type==FIELDTYPE_SFNode && fieldPtr->sfnode) || (type==FIELDTYPE_MFNode && fieldPtr->mfnode.n);
5708  if(haveSomething){
5709  indentf(*level);
5710  printf("%s ",fieldName);
5711  if(type==FIELDTYPE_SFNode){
5712  plist = &fieldPtr->sfnode;
5713  n = 1;
5714  }else{
5715  plist = fieldPtr->mfnode.p;
5716  n = fieldPtr->mfnode.n;
5717  if(n > 1){
5718  printf("[\n");
5719  (*level)++;
5720  //indentf((*level));
5721  }
5722  }
5723  for(k=0;k<n;k++)
5724  {
5725  sfn = plist[k];
5726  if(n>1) indentf((*level));
5727  print_node_links0(sfn,level);
5728  }
5729  if(type==FIELDTYPE_MFNode && n > 1){
5730  (*level)--;
5731  indentf((*level));
5732  printf("]\n");
5733  }
5734  }
5735  }
5736  (*level)--;
5737  return FALSE; //false to keep walking fields, true to break out
5738 }
5739 
5740 void print_node_links0(struct X3D_Node* sfn, int *level)
5741 {
5742  if(sfn)
5743  {
5744  /* unlink children in any SFNode or MFNode field of node */
5745  printf("node %p ",sfn);
5746  if(sfn->_parentVector && vectorSize(sfn->_parentVector)){
5747  int j;
5748  printf(" parents={");
5749  for(j=0;j<vectorSize(sfn->_parentVector);j++){
5750  struct X3D_Node *parent = vector_get(struct X3D_Node *,sfn->_parentVector, j);
5751  printf("%p, ",parent);
5752  }
5753  printf("}");
5754  }
5755  printf("\n");
5756  walk_fields(sfn,cbPrintLinks,level);
5757  }
5758 }
5759 void print_node_links(struct X3D_Node* sfn)
5760 {
5761  int level = 0;
5762  print_node_links0(sfn,&level);
5763  if(level != 0)
5764  printf("ouch level =%d\n",level);
5765 }
5766 
5767 
5768 BOOL cbUnlinkChild(void *callbackData,struct X3D_Node* node,int jfield,
5769  union anyVrml *fieldPtr,char *fieldName, int mode,int type,int source,BOOL publicfield)
5770 {
5771  if(isManagedField(mode,type,publicfield)){
5772  if(type == FIELDTYPE_SFNode){
5773  struct X3D_Node **sfn = &fieldPtr->sfnode;
5774  AddRemoveSFNodeFieldChild(node,sfn,*sfn,2,__FILE__,__LINE__);
5775  if(fieldPtr->sfnode)
5776  printf("didn't delete sfnode child\n");
5777  }else if(type == FIELDTYPE_MFNode){
5778  struct Multi_Node* mfn = &fieldPtr->mfnode;
5779  AddRemoveChildren(node,mfn,mfn->p,mfn->n,2,__FILE__,__LINE__);
5780  }
5781  }
5782  return FALSE; //false to keep walking fields, true to break out
5783 }
5784 BOOL cbUnlinkParent(void *callbackData,struct X3D_Node* parent,int jfield,
5785  union anyVrml *fieldPtr,char *fieldName, int mode,int type,int source,BOOL publicfield)
5786 {
5787  struct X3D_Node* node = X3D_NODE(callbackData);
5788  if(isManagedField(mode,type,publicfield)){
5789  if(type == FIELDTYPE_SFNode){
5790  struct X3D_Node **sfn = &fieldPtr->sfnode;
5791  AddRemoveSFNodeFieldChild(parent,sfn,node,2,__FILE__,__LINE__);
5792  }else if(type == FIELDTYPE_MFNode){
5793  struct Multi_Node* mfn = &fieldPtr->mfnode;
5794  AddRemoveChildren(parent,mfn,&node,1,2,__FILE__,__LINE__); //Q. is 2 remove?
5795  }
5796  }
5797  return FALSE; //false to keep walking fields, true to break out
5798 }
5799 void unlink_node(struct X3D_Node* node)
5800 {
5801  if(node)
5802  {
5803  /* unlink children in any SFNode or MFNode field of node */
5804  walk_fields(node,cbUnlinkChild,NULL);
5805  /* unlink/remove node from any SFNode or MFNode field of parents */
5806  if(node->_parentVector && vectorSize(node->_parentVector)){
5807  int j;
5808  struct Vector* pp = newVector(struct X3D_Node*,vectorSize(node->_parentVector));
5809  for(j=0;j<vectorSize(node->_parentVector);j++){
5810  struct X3D_Node *parent = vector_get(struct X3D_Node *,node->_parentVector, j);
5811  vector_pushBack(struct X3D_Node*,pp,parent);
5812  }
5813  for(j=0;j<vectorSize(pp);j++){
5814  struct X3D_Node *parent = vector_get(struct X3D_Node *,pp, j);
5815  walk_fields(parent,cbUnlinkParent,node);
5816  }
5817  node->_parentVector->n = 0;
5818  deleteVector(struct X3D_Node*, pp);
5819  }
5820  }
5821 }
5822 
5823 void deleteMallocedFieldValue(int type,union anyVrml *fieldPtr);
5824 BOOL cbFreeMallocedBuiltinField(void *callbackData,struct X3D_Node* node,int jfield,
5825  union anyVrml *fieldPtr,char *fieldName, int mode,int type,int source,BOOL publicfield)
5826 {
5827  //for builtins, the field is malloced as part of the node size, so we don't free the field itself
5828  // .. just if its a complex field type holding a malloced pointer
5829  // .. like MF.p or SFString.ptr
5830  // and only if the node owns the pointer, which we determine by if the field is initializeOnly or inputOutput
5831  if(source == 0){
5832  //if(mode == PKW_initializeOnly || mode == PKW_inputOutput){
5833  if(1){
5834  //#define FIELDTYPE_FreeWRLPTR 22
5835  //#define FIELDTYPE_SFImage 23
5836  //if(strcmp(fieldName,"__oldurl") && strcmp(fieldName,"__oldSFString") && strcmp(fieldName,"__oldMFString") && strcmp(fieldName,"_parentVector")) {
5837  if(strcmp(fieldName,"__oldurl") && strcmp(fieldName,"_parentVector")) {
5838  //if(1){
5839  //skip double underscore prefixed fields, which we will treat as not-to-be-deleted, because duplicates like GeoViewpoint __oldMFString which is a duplicate of navType
5840  deleteMallocedFieldValue(type,fieldPtr);
5841  if(type == FIELDTYPE_FreeWRLPTR){
5842  if(!strncmp(fieldName,"__x",3) || !strncmp(fieldName,"__v",3)) { //May 2015 special field name prefixes __x and __v signals OK to FREE_IF_NZ
5843  FREE_IF_NZ(fieldPtr->sfnode); //free it as a pointer
5844  }
5845  }
5846  }
5847  }
5848  }
5849  return FALSE; //false to keep walking fields, true to break out
5850 }
5851 BOOL cbFreePublicMallocedBuiltinField(void *callbackData,struct X3D_Node* node,int jfield,
5852  union anyVrml *fieldPtr,char *fieldName, int mode,int type,int source,BOOL publicfield)
5853 {
5854  //for builtins, the field is malloced as part of the node size, so we don't free the field itself
5855  // .. just if its a complex field type holding a malloced pointer
5856  // .. like MF.p or SFString.ptr
5857  // and only if the node owns the pointer, which we determine by if the field is initializeOnly or inputOutput
5858  if(source == 0){
5859  //if(mode == PKW_initializeOnly || mode == PKW_inputOutput){
5860  if(1){
5861  //#define FIELDTYPE_FreeWRLPTR 22
5862  //#define FIELDTYPE_SFImage 23
5863  if(strncmp(fieldName,"_",1)) { //only public fields, skip _ and __ private fields
5864  //if(1){
5865  //skip double underscore prefixed fields, which we will treat as not-to-be-deleted, because duplicates like GeoViewpoint __oldMFString which is a duplicate of navType
5866  deleteMallocedFieldValue(type,fieldPtr);
5867  }
5868  }
5869  }
5870  return FALSE; //false to keep walking fields, true to break out
5871 }
5872 BOOL cbFreeMallocedUserField(void *callbackData,struct X3D_Node* node,int jfield,
5873  union anyVrml *fieldPtr,char *fieldName, int mode,int type,int source,BOOL publicfield)
5874 {
5875  //for userFields (ie on Script, Proto), the field is malloced as part of a bigger struct
5876  // .. so we free any pointers contained in the field like MF.p or SFString.ptr
5877  // and only if the node owns the pointer, which we determine by if the field is initializeOnly or inputOutput
5878  // .. but we don't free the anyVrml* pointer itself
5879  // .. we rely on something freeing the user fields elsewhere to free the vector of userfields and
5880  // .. a few of their malloced contents
5881 
5882  if(source > 0){
5883  //user field in source = {script=1, shaders etc 2, protos = 3}
5884  //if(mode == PKW_initializeOnly || mode == PKW_inputOutput){
5885  if(1){
5886  if(strncmp(fieldName,"__",2)) {
5887  //if(1){
5888  //skip double underscore prefixed fields, which we will treat as not-to-be-deleted, because duplicates like GeoViewpoint __oldMFString which is a duplicate of navType
5889  deleteMallocedFieldValue(type,fieldPtr);
5890  }
5891  }
5892  }
5893  return FALSE; //false to keep walking fields, true to break out
5894 }
5895 struct Shader_Script *getShader(struct X3D_Node *node){
5896  struct Shader_Script *shader = NULL;
5897  switch(node->_nodeType)
5898  {
5899  case NODE_Script: shader =(struct Shader_Script *)(X3D_SCRIPT(node)->__scriptObj); break;
5900  case NODE_ComposedShader: shader =(struct Shader_Script *)(X3D_COMPOSEDSHADER(node)->_shaderUserDefinedFields); break;
5901  case NODE_Effect: shader =(struct Shader_Script *)(X3D_EFFECT(node)->_shaderUserDefinedFields); break;
5902  case NODE_ShaderProgram: shader =(struct Shader_Script *)(X3D_SHADERPROGRAM(node)->_shaderUserDefinedFields); break;
5903  case NODE_PackagedShader: shader =(struct Shader_Script *)(X3D_PACKAGEDSHADER(node)->_shaderUserDefinedFields); break;
5904  }
5905  return shader;
5906 }
5907 void setShader(struct X3D_Node *node, struct Shader_Script *shader){
5908  switch(node->_nodeType)
5909  {
5910  case NODE_Script: X3D_SCRIPT(node)->__scriptObj = (void *)shader; break;
5911  case NODE_ComposedShader: X3D_COMPOSEDSHADER(node)->_shaderUserDefinedFields = (void *)shader;; break;
5912  case NODE_Effect: X3D_EFFECT(node)->_shaderUserDefinedFields = (void *)shader;; break;
5913  case NODE_ShaderProgram: X3D_SHADERPROGRAM(node)->_shaderUserDefinedFields = (void *)shader;; break;
5914  case NODE_PackagedShader: X3D_PACKAGEDSHADER(node)->_shaderUserDefinedFields = (void *)shader;; break;
5915  }
5916 
5917 }
5918 void deleteShaderDefinition(struct Shader_Script *shader){
5919  if(shader){
5920  if(shader->fields){
5921  int i;
5922  for(i=0;i<vectorSize(shader->fields);i++){
5923  struct ScriptFieldDecl *field = vector_get(struct ScriptFieldDecl*,shader->fields,i);
5924  deleteScriptFieldDecl(field);
5925 
5926  }
5927  deleteVector(struct ScriptFieldDecl*,shader->fields);
5928  FREE_IF_NZ(shader->fields);
5929  }
5930  FREE_IF_NZ(shader);
5931  }
5932 }
5933 //static struct Vector freed;
5934 //static struct fieldFree ffs[100];
5935 void freeMallocedNodeFields0(struct X3D_Node* node){
5936  //PIMPL Idiom in C is like objects in C++ - each object should know how to delete itself
5937  //we don't have good pimpl habits yet in freewrl
5938  //Here we try and generically free what a node may have allocated
5939  //(a pimpl alternative might be node-type specific freeing)
5940  //assume node->_intern = polyrep, node->_parents vector, and other common private fields are already done
5941  //then this walks over node-specific fields, attempting to free any potentially malloced fields
5942  //except SFNode (and SFNode contents of MFNode) which are garbage collected from
5943  //a per-broto/executioncontext node table
5944  if(node){
5945  int isScriptType, isBrotoType, hasUserFields;
5946  isScriptType = node->_nodeType == NODE_Script || node->_nodeType == NODE_ComposedShader || node->_nodeType == NODE_ShaderProgram || node->_nodeType == NODE_PackagedShader;
5947  isBrotoType = node->_nodeType == NODE_Proto; //inlines have no fields, freed elsewhere || node->_nodeType == NODE_Inline;
5948  hasUserFields = isScriptType || isBrotoType;
5949  //freed.data = ffs;
5950  //freed.allocn = 100;
5951  //freed.n = 0;
5952  if(hasUserFields){
5953  walk_fields(node,cbFreeMallocedUserField,NULL); //&freed);
5954  if(isScriptType){
5955  struct Shader_Script *shader = getShader(node);
5956  if (shader){
5957  deleteShaderDefinition(shader);
5958  setShader(node,NULL);
5959  }
5960  }else if(isBrotoType){
5961  struct X3D_Proto* pnode = (struct X3D_Proto*)node;
5962  deleteProtoDefinition(pnode->__protoDef);
5963  FREE_IF_NZ(pnode->__protoDef);
5964  FREE_IF_NZ(pnode->__typename);
5965  //struct ProtoDefinition* pstruct = (struct ProtoDefinition*) pnode->__protoDef;
5966  //if(pstruct){
5967  // //for vectorget.n field->malloced stuff
5968  // deleteVector(struct ProtoDefinition*,pstruct);
5969  // pnode->__protoDef = NULL;
5970  //}
5971  }
5972  }
5973  /* free malloced public fields */
5974  walk_fields(node,cbFreeMallocedBuiltinField,NULL); //&freed);
5975  }
5976 }
5977 //void freePublicBuiltinNodeFields(struct X3D_Node* node){
5978 // if(node)
5979 // walk_fields(node,cbFreePublicMallocedBuiltinField,NULL); //&freed);
5980 //}
5981 void freeMallocedNodeFields(struct X3D_Node* node){
5982  if(node){
5983  deleteVector(void*,node->_parentVector);
5984  if(node->_gc) free_registered_node_gc(node);
5985  freeMallocedNodeFields0(node);
5986  }
5987 }
5988 
5989 #ifdef OLDCODE
5990 
5991 OLDCODE/*delete node created
5992 OLDCODEstatic void killNode_hide_obsolete (int index) {
5993 OLDCODE int j=0;
5994 OLDCODE int *fieldOffsetsPtr;
5995 OLDCODE char * fieldPtr;
5996 OLDCODE struct X3D_Node* structptr;
5997 OLDCODE struct Multi_Float* MFloat;
5998 OLDCODE struct Multi_Rotation* MRotation;
5999 OLDCODE struct Multi_Vec3f* MVec3f;
6000 OLDCODE struct Multi_Bool* Mbool;
6001 OLDCODE struct Multi_Int32* MInt32;
6002 OLDCODE struct Multi_Node* MNode;
6003 OLDCODE struct Multi_Color* MColor;
6004 OLDCODE struct Multi_ColorRGBA* MColorRGBA;
6005 OLDCODE struct Multi_Time* MTime;
6006 OLDCODE struct Multi_String* MString;
6007 OLDCODE struct Multi_Vec2f* MVec2f;
6008 OLDCODE intptr_t * VPtr;
6009 OLDCODE struct Uni_String *MyS;
6010 OLDCODE int i;
6011 OLDCODE
6012 OLDCODE ppOpenGL_Utils p;
6013 OLDCODE ttglobal tg = gglobal();
6014 OLDCODE p = (ppOpenGL_Utils)tg->OpenGL_Utils.prv;
6015 OLDCODE
6016 OLDCODE structptr = vector_get(struct X3D_Node *,p->linearNodeTable,index);
6017 OLDCODE //ConsoleMessage("killNode - looking for node %p of type %s in one of the stacks\n", structptr,stringNodeType(structptr->_nodeType));
6018 OLDCODE
6019 OLDCODE if( structptr->referenceCount > -1 ){
6020 OLDCODE // unlinking the node from special arrays, parents and children
6021 OLDCODE // we just need to do this once, and early in the kill process
6022 OLDCODE // - I wish we had a sentinal value for 'unlinked'
6023 OLDCODE DELETE_IF_IN_STACK(viewpoint_stack);
6024 OLDCODE DELETE_IF_IN_STACK(background_stack);
6025 OLDCODE DELETE_IF_IN_STACK(fog_stack);
6026 OLDCODE DELETE_IF_IN_STACK(navigation_stack);
6027 OLDCODE DELETE_IF_IN_PRODCON(viewpointNodes);
6028 OLDCODE delete_first(structptr);
6029 OLDCODE //print_node_links(structptr);
6030 OLDCODE unlink_node(structptr); //unlink before settledown deleting..
6031 OLDCODE //printf("after: \n");
6032 OLDCODE //print_node_links(structptr);
6033 OLDCODE }
6034 OLDCODE
6035 OLDCODE // give this time for things to "settle" in terms of rendering, etc
6036 OLDCODE //JAS: "OpenGL - old code called flush() or finish(), but when the front-end does the actual rendering,
6037 OLDCODE //what happens is that the GL calls get queued up for the GPU, then run when possible. So, there
6038 OLDCODE //is a "hidden" multi-threading going on there. IIRC, I gave it 10 rendering loops for an unused
6039 OLDCODE //node before deleting any of the items in it; really 1 or 2 loops should be fine. (1, but don't
6040 OLDCODE //know about double buffering; 10 is a safe overkill) Without that, having OpenGL issues was a
6041 OLDCODE //random certainty when removing nodes, and data from these nodes."
6042 OLDCODE
6043 OLDCODE structptr->referenceCount --;
6044 OLDCODE if (structptr->referenceCount > -10) {
6045 OLDCODE //ConsoleMessage ("ref count for %p is just %d, waiting\n",structptr,structptr->referenceCount);
6046 OLDCODE return;
6047 OLDCODE }
6048 OLDCODE //ConsoleMessage ("kn %d %s\n",index,stringNodeType(structptr->_nodeType));
6049 OLDCODE
6050 OLDCODE #ifdef VERBOSE
6051 OLDCODE printf("killNode: Node pointer = %p entry %d of %d ",structptr,i,vectorSize(p->linearNodeTable));
6052 OLDCODE if (structptr) {
6053 OLDCODE if (structptr->_parentVector)
6054 OLDCODE printf (" number of parents %d ", vectorSize(structptr->_parentVector));
6055 OLDCODE printf("Node Type = %s",stringNodeType(structptr->_nodeType));
6056 OLDCODE } printf ("\n");
6057 OLDCODE #endif
6058 OLDCODE // node must be already unlinked with unlink_node() when we get here
6059 OLDCODE // delete parent vector.
6060 OLDCODE deleteVector(char*, structptr->_parentVector);
6061 OLDCODE // clear child vector - done below
6062 OLDCODE
6063 OLDCODE fieldOffsetsPtr = (int *)NODE_OFFSETS[structptr->_nodeType];
6064 OLDCODE //go thru all field
6065 OLDCODE while (*fieldOffsetsPtr != -1) {
6066 OLDCODE fieldPtr = offsetPointer_deref(char *, structptr,*(fieldOffsetsPtr+1));
6067 OLDCODE #ifdef VERBOSE
6068 OLDCODE printf ("looking at field %s type %s\n",FIELDNAMES[*fieldOffsetsPtr],FIELDTYPES[*(fieldOffsetsPtr+2)]);
6069 OLDCODE #endif
6070 OLDCODE
6071 OLDCODE // some fields we skip, as the pointers are duplicated, and we CAN NOT free both
6072 OLDCODE if (*fieldOffsetsPtr == FIELDNAMES_setValue)
6073 OLDCODE break; // can be a duplicate SF/MFNode pointer
6074 OLDCODE
6075 OLDCODE if (*fieldOffsetsPtr == FIELDNAMES_valueChanged)
6076 OLDCODE break; // can be a duplicate SF/MFNode pointer
6077 OLDCODE
6078 OLDCODE if (*fieldOffsetsPtr == FIELDNAMES__parentResource)
6079 OLDCODE break; // can be a duplicate SF/MFNode pointer
6080 OLDCODE
6081 OLDCODE
6082 OLDCODE if (*fieldOffsetsPtr == FIELDNAMES___oldmetadata)
6083 OLDCODE break; // can be a duplicate SFNode pointer
6084 OLDCODE
6085 OLDCODE if (*fieldOffsetsPtr == FIELDNAMES__selected)
6086 OLDCODE break; // can be a duplicate SFNode pointer - field only in NODE_LOD and NODE_GeoLOD
6087 OLDCODE
6088 OLDCODE if (*fieldOffsetsPtr == FIELDNAMES___oldChildren)
6089 OLDCODE break; // can be a duplicate SFNode pointer - field only in NODE_LOD and NODE_GeoLOD
6090 OLDCODE
6091 OLDCODE if (*fieldOffsetsPtr == FIELDNAMES___oldMFString)
6092 OLDCODE break;
6093 OLDCODE
6094 OLDCODE if (*fieldOffsetsPtr == FIELDNAMES___scriptObj)
6095 OLDCODE break;
6096 OLDCODE
6097 OLDCODE if (*fieldOffsetsPtr == FIELDNAMES___oldSFString)
6098 OLDCODE break;
6099 OLDCODE
6100 OLDCODE if (*fieldOffsetsPtr == FIELDNAMES___oldKeyPtr)
6101 OLDCODE break; // used for seeing if interpolator values change
6102 OLDCODE
6103 OLDCODE if (*fieldOffsetsPtr == FIELDNAMES___oldKeyValuePtr)
6104 OLDCODE break; // used for seeing if interpolator values change
6105 OLDCODE
6106 OLDCODE
6107 OLDCODE // GeoLOD nodes, the children field exports either the rootNode, or the list of child nodes
6108 OLDCODE if (structptr->_nodeType == NODE_GeoLOD) {
6109 OLDCODE if (*fieldOffsetsPtr == FIELDNAMES_children) break;
6110 OLDCODE }
6111 OLDCODE
6112 OLDCODE // nope, not a special field, lets just get rid of it as best we can
6113 OLDCODE // dug9 sept 2014: GC garbage collection: I wonder if it would be easier/simpler when we malloc something,
6114 OLDCODE // to put it into a flat scene-GC list (and inline-GC list?) - as we do for a few things already, like nodes -
6115 OLDCODE // and don't GC here for fields on occassionally removed nodes, just when we change scenes
6116 OLDCODE // wipe out the whole GC table(s)?
6117 OLDCODE //
6118 OLDCODE switch(*(fieldOffsetsPtr+2)){
6119 OLDCODE case FIELDTYPE_MFFloat:
6120 OLDCODE MFloat=(struct Multi_Float *)fieldPtr;
6121 OLDCODE MFloat->n=0;
6122 OLDCODE FREE_IF_NZ(MFloat->p);
6123 OLDCODE break;
6124 OLDCODE case FIELDTYPE_MFRotation:
6125 OLDCODE MRotation=(struct Multi_Rotation *)fieldPtr;
6126 OLDCODE MRotation->n=0;
6127 OLDCODE FREE_IF_NZ(MRotation->p);
6128 OLDCODE break;
6129 OLDCODE case FIELDTYPE_MFVec3f:
6130 OLDCODE MVec3f=(struct Multi_Vec3f *)fieldPtr;
6131 OLDCODE MVec3f->n=0;
6132 OLDCODE FREE_IF_NZ(MVec3f->p);
6133 OLDCODE break;
6134 OLDCODE case FIELDTYPE_MFBool:
6135 OLDCODE Mbool=(struct Multi_Bool *)fieldPtr;
6136 OLDCODE Mbool->n=0;
6137 OLDCODE FREE_IF_NZ(Mbool->p);
6138 OLDCODE break;
6139 OLDCODE case FIELDTYPE_MFInt32:
6140 OLDCODE MInt32=(struct Multi_Int32 *)fieldPtr;
6141 OLDCODE MInt32->n=0;
6142 OLDCODE FREE_IF_NZ(MInt32->p);
6143 OLDCODE break;
6144 OLDCODE case FIELDTYPE_MFNode:
6145 OLDCODE MNode=(struct Multi_Node *)fieldPtr;
6146 OLDCODE #ifdef VERBOSE
6147 OLDCODE //verify node structure. Each child should point back to me.
6148 OLDCODE {
6149 OLDCODE int i;
6150 OLDCODE struct X3D_Node *tp;
6151 OLDCODE for (i=0; i<MNode->n; i++) {
6152 OLDCODE tp = MNode->p[i];
6153 OLDCODE printf (" MNode field has child %p\n",tp);
6154 OLDCODE if (tp!=NULL)
6155 OLDCODE printf (" ct %s\n",stringNodeType(tp->_nodeType));
6156 OLDCODE }
6157 OLDCODE }
6158 OLDCODE #endif
6159 OLDCODE MNode->n=0;
6160 OLDCODE FREE_IF_NZ(MNode->p);
6161 OLDCODE break;
6162 OLDCODE
6163 OLDCODE case FIELDTYPE_MFColor:
6164 OLDCODE MColor=(struct Multi_Color *)fieldPtr;
6165 OLDCODE MColor->n=0;
6166 OLDCODE FREE_IF_NZ(MColor->p);
6167 OLDCODE break;
6168 OLDCODE case FIELDTYPE_MFColorRGBA:
6169 OLDCODE MColorRGBA=(struct Multi_ColorRGBA *)fieldPtr;
6170 OLDCODE MColorRGBA->n=0;
6171 OLDCODE FREE_IF_NZ(MColorRGBA->p);
6172 OLDCODE break;
6173 OLDCODE case FIELDTYPE_MFTime:
6174 OLDCODE MTime=(struct Multi_Time *)fieldPtr;
6175 OLDCODE MTime->n=0;
6176 OLDCODE FREE_IF_NZ(MTime->p);
6177 OLDCODE break;
6178 OLDCODE case FIELDTYPE_MFString:
6179 OLDCODE MString=(struct Multi_String *)fieldPtr;
6180 OLDCODE {
6181 OLDCODE struct Uni_String* ustr;
6182 OLDCODE for (j=0; j<MString->n; j++) {
6183 OLDCODE ustr=MString->p[j];
6184 OLDCODE if (ustr != NULL) {
6185 OLDCODE ustr->len=0;
6186 OLDCODE ustr->touched=0;
6187 OLDCODE FREE_IF_NZ(ustr->strptr);
6188 OLDCODE }
6189 OLDCODE }
6190 OLDCODE MString->n=0;
6191 OLDCODE FREE_IF_NZ(MString->p);
6192 OLDCODE }
6193 OLDCODE break;
6194 OLDCODE case FIELDTYPE_MFVec2f:
6195 OLDCODE MVec2f=(struct Multi_Vec2f *)fieldPtr;
6196 OLDCODE MVec2f->n=0;
6197 OLDCODE FREE_IF_NZ(MVec2f->p);
6198 OLDCODE break;
6199 OLDCODE case FIELDTYPE_FreeWRLPTR:
6200 OLDCODE VPtr = (intptr_t *) fieldPtr;
6201 OLDCODE VPtr = (intptr_t *) (*VPtr);
6202 OLDCODE FREE_IF_NZ(VPtr);
6203 OLDCODE break;
6204 OLDCODE case FIELDTYPE_SFString:
6205 OLDCODE VPtr = (intptr_t *) fieldPtr;
6206 OLDCODE MyS = (struct Uni_String *) *VPtr;
6207 OLDCODE MyS->len = 0;
6208 OLDCODE FREE_IF_NZ(MyS->strptr);
6209 OLDCODE FREE_IF_NZ(MyS);
6210 OLDCODE break;
6211 OLDCODE
6212 OLDCODE default:; // do nothing - field not malloc'd
6213 OLDCODE }
6214 OLDCODE fieldOffsetsPtr+=5;
6215 OLDCODE }
6216 OLDCODE
6217 OLDCODE FREE_IF_NZ(structptr);
6218 OLDCODE vector_set(struct X3D_Node *, p->linearNodeTable,index,NULL);
6219 OLDCODE p->potentialHoleCount++;
6220 OLDCODE //ConsoleMessage ("kill, index %d, phc %d",index,p->potentialHoleCount);
6221 OLDCODE}
6222 OLDCODE*/
6223 #endif //OLDCODE
6224 
6225 #ifdef DEBUG_FW_LOADMAT
6226  static void fw_glLoadMatrixd(GLDOUBLE *val,char *where, int line) {
6227  {int i;
6228  for (i=0; i<16; i++) {
6229  if (val[i] > 2000.0) printf ("FW_GL_LOADMATRIX, val %d %lf at %s:%d\n",i,val[i],where,line);
6230  if (val[i] < -2000.0) printf ("FW_GL_LOADMATRIX, val %d %lf at %s:%d\n",i,val[i],where,line);
6231  }
6232  }
6233 #else
6234  static void fw_glLoadMatrixd(GLDOUBLE *val) {
6235 #endif
6236 
6237  /* printf ("loading matrix...\n"); */
6238  #ifndef GL_ES_VERSION_2_0
6239  glLoadMatrixd(val);
6240  #endif
6241 }
6242 BOOL matrix3x3_inverse_float(float *inn, float *outt);
6243 
6244 void sendExplicitMatriciesToShader (GLint ModelViewMatrix, GLint ProjectionMatrix, GLint NormalMatrix, GLint *TextureMatrix, GLint ModelViewInverseMatrix)
6245 
6246 {
6247 
6248  float spval[16];
6249  int i,j;
6250  float *sp;
6251  GLDOUBLE *dp;
6252  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
6253 
6254 
6255  /* ModelView first */
6256  dp = p->FW_ModelView[p->modelviewTOS];
6257  sp = spval;
6258 
6259  /* convert GLDOUBLE to float */
6260  for (i=0; i<16; i++) {
6261  *sp = (float) *dp;
6262  sp ++; dp ++;
6263  }
6264  profile_start("sendmtx");
6265  GLUNIFORMMATRIX4FV(ModelViewMatrix,1,GL_FALSE,spval);
6266  profile_end("sendmtx");
6267  /* ProjectionMatrix */
6268  sp = spval;
6269  dp = p->FW_ProjectionView[p->projectionviewTOS];
6270 
6271  matdouble2float4(sp,dp);
6273  //for (i=0; i<16; i++) {
6274  // *sp = (float) *dp;
6275  // sp ++; dp ++;
6276  //}
6277  profile_start("sendmtx");
6278  GLUNIFORMMATRIX4FV(ProjectionMatrix,1,GL_FALSE,spval);
6279  profile_end("sendmtx");
6280  /* TextureMatrix */
6281  if(TextureMatrix)
6282  for(j=0;j<MAX_MULTITEXTURE;j++) {
6283  int itexturestackposition = j+1;
6284  if (TextureMatrix[j] != -1 && itexturestackposition <= p->textureviewTOS) {
6285  sp = spval;
6286  dp = p->FW_TextureView[itexturestackposition]; //[p->textureviewTOS];
6287 
6288  //ConsoleMessage ("sendExplicitMatriciesToShader, sizeof GLDOUBLE %d sizeof float %d\n",sizeof(GLDOUBLE), sizeof(float));
6289  //printmatrix2(dp,"dp");
6290  /* convert GLDOUBLE to float */
6291  for (i=0; i<16; i++) {
6292  *sp = (float) *dp;
6293  sp ++; dp ++;
6294  }
6295  profile_start("sendmtx");
6296  GLUNIFORMMATRIX4FV(TextureMatrix[j],1,GL_FALSE,spval);
6297  profile_end("sendmtx");
6298  }
6299  }
6300 
6301  if( ModelViewInverseMatrix != -1){
6302  //send in the inverse of the modelview matrix
6303  //- handy for cube-map texturing
6304  float spvali[16];
6305  int ii; //,jj;
6306  float *spi;
6307  double *dpi, *dpp;
6308  GLDOUBLE inverseMV[16];
6309  //GLDOUBLE transInverseMV[16];
6310  GLDOUBLE MV[16];
6311 
6312  dpp = p->FW_ModelView[p->modelviewTOS];
6313  memcpy(MV,dpp,sizeof(GLDOUBLE)*16);
6314  matinverse (inverseMV,MV);
6315  dpi = inverseMV;
6316  spi = spvali;
6317  for (ii=0; ii<16; ii++) {
6318  *spi = (float) *dpi;
6319  spi ++; dpi ++;
6320  }
6321  GLUNIFORMMATRIX4FV(ModelViewInverseMatrix,1,GL_FALSE,spvali);
6322  }
6323  /* send in the NormalMatrix */
6324  /* Uniform mat3 gl_NormalMatrix; transpose of the inverse of the upper
6325  leftmost 3x3 of gl_ModelViewMatrix */
6326  if (NormalMatrix != -1) {
6327  float normMat[9];
6328  dp = p->FW_ModelView[p->modelviewTOS];
6329 
6330  if(1){
6331  //trying to find another .01 FPS
6332  //switch from 4x4 double to 3x3 float inverse
6333  float ftemp[9];
6334  /* convert GLDOUBLE to float */
6335  for (i=0; i<3; i++)
6336  for(j=0;j<3;j++)
6337  spval[i*3 +j] = (float) dp[i*4 + j];
6338 
6339  matrix3x3_inverse_float(spval, ftemp);
6340  //transpose
6341  for (i = 0; i < 3; i++)
6342  for (j = 0; j < 3; j++)
6343  normMat[i*3 +j] = ftemp[j*3 + i];
6344 
6345  }
6346  if(0){
6347  GLDOUBLE inverseMV[16];
6348  GLDOUBLE transInverseMV[16];
6349  GLDOUBLE MV[16];
6350  memcpy(MV,dp,sizeof(GLDOUBLE)*16);
6351 
6352  matinverse (inverseMV,MV);
6353  mattranspose(transInverseMV,inverseMV);
6354  /* get the 3x3 normal matrix from this guy */
6355  normMat[0] = (float) transInverseMV[0];
6356  normMat[1] = (float) transInverseMV[1];
6357  normMat[2] = (float) transInverseMV[2];
6358 
6359  normMat[3] = (float) transInverseMV[4];
6360  normMat[4] = (float) transInverseMV[5];
6361  normMat[5] = (float) transInverseMV[6];
6362 
6363  normMat[6] = (float) transInverseMV[8];
6364  normMat[7] = (float) transInverseMV[9];
6365  normMat[8] = (float) transInverseMV[10];
6366  }
6367 /*
6368 printf ("NormalMatrix: \n \t%4.3f %4.3f %4.3f\n \t%4.3f %4.3f %4.3f\n \t%4.3f %4.3f %4.3f\n",
6369 normMat[0],normMat[1],normMat[2],
6370 normMat[3],normMat[4],normMat[5],
6371 normMat[6],normMat[7],normMat[8]);
6372 */
6373  profile_start("sendmtx");
6374  GLUNIFORMMATRIX3FV(NormalMatrix,1,GL_FALSE,normMat);
6375  profile_end("sendmtx");
6376  }
6377 
6378 }
6379 
6380 
6381 /* make this more generic, so that the non-OpenGL-ES 2.0 FillProperties, etc, still work */
6382 
6383 void sendMatriciesToShader(s_shader_capabilities_t *me) {
6384  sendExplicitMatriciesToShader (me->ModelViewMatrix, me->ProjectionMatrix, me->NormalMatrix,me->TextureMatrix,me->ModelViewInverseMatrix);
6385 
6386 }
6387 #define SEND_VEC2(myMat,myVal) \
6388 if (me->myMat != -1) { GLUNIFORM2FV(me->myMat,1,myVal);}
6389 
6390 #define SEND_VEC4(myMat,myVal) \
6391 if (me->myMat != -1) { GLUNIFORM4FV(me->myMat,1,myVal);}
6392 
6393 #define SEND_FLOAT(myMat,myVal) \
6394 if (me->myMat != -1) { GLUNIFORM1F(me->myMat,myVal);}
6395 
6396 #define SEND_INT(myMat,myVal) \
6397 if (me->myMat != -1) { GLUNIFORM1I(me->myMat,myVal);}
6398 
6399 
6400 struct X3D_Node *getFogParams();
6401 void sendFogToShader(s_shader_capabilities_t *me) {
6402  float color4[4];
6403  struct X3D_Fog *fog = (struct X3D_Fog*) getFogParams(); //gets it from the fog stack, LocalFog and Fog are upcast to Fog: perl first fields in same order
6404  if(!fog) return;
6405 
6406  profile_start("sendvec");
6407  memcpy(color4,fog->color.c,sizeof(float)*3);
6408  color4[3] = 1.0;
6409  SEND_VEC4(fogColor,color4);
6410  SEND_FLOAT(fogvisibilityRange,fog->visibilityRange*fog->__fogScale);
6411  SEND_FLOAT(fogScale,1.0f); //fog->__fogScale);
6412  SEND_INT(fogType,fog->__fogType);
6413  //SEND_INT(fogHaveCoords,fogparams->haveCoords);
6414  profile_end("sendvec");
6415 
6416 }
6417 float *getTransformedClipPlanes();
6418 int getClipPlaneCount();
6419 void sendClipplanesToShader(s_shader_capabilities_t *me){
6420  int nsend; //i,
6421 
6422  float *clipplanes = getTransformedClipPlanes();
6423  nsend = getClipPlaneCount();
6424  GLUNIFORM4FV(me->clipplanes,nsend,clipplanes);
6425  GLUNIFORM1I(me->nclipplanes,nsend);
6426 }
6427 
6428 void sendMaterialsToShader(s_shader_capabilities_t *me) {
6429  struct matpropstruct *myap = getAppearanceProperties();
6430  struct fw_MaterialParameters *fw_FrontMaterial;
6431  struct fw_MaterialParameters *fw_BackMaterial;
6432 
6433  if (!myap) return;
6434  fw_FrontMaterial = &myap->fw_FrontMaterial;
6435  fw_BackMaterial = &myap->fw_BackMaterial;
6436 
6437 
6438  /* go through all of the Uniforms for this shader */
6439 
6440  /* ConsoleMessage ("sending in front diffuse %f %f %f %f ambient %f %f %f %f spec %f %f %f %f emission %f %f %f %f, shin %f",
6441  fw_FrontMaterial.diffuse[0],fw_FrontMaterial.diffuse[1],fw_FrontMaterial.diffuse[2],fw_FrontMaterial.diffuse[3],
6442  fw_FrontMaterial.ambient[0],fw_FrontMaterial.ambient[1],fw_FrontMaterial.ambient[2],fw_FrontMaterial.ambient[3],
6443  fw_FrontMaterial.specular[0],fw_FrontMaterial.specular[1],fw_FrontMaterial.specular[2],fw_FrontMaterial.specular[3],
6444  fw_FrontMaterial.emission[0],fw_FrontMaterial.emission[1],fw_FrontMaterial.emission[2],fw_FrontMaterial.emission[3],
6445  fw_FrontMaterial.shininess);
6446 
6447  ConsoleMessage ("sending in back diffuse %f %f %f %f ambient %f %f %f %f spec %f %f %f %f emission %f %f %f %f, shin %f",
6448  fw_BackMaterial.diffuse[0],fw_BackMaterial.diffuse[1],fw_BackMaterial.diffuse[2],fw_BackMaterial.diffuse[3],
6449  fw_BackMaterial.ambient[0],fw_BackMaterial.ambient[1],fw_BackMaterial.ambient[2],fw_BackMaterial.ambient[3],
6450  fw_BackMaterial.specular[0],fw_BackMaterial.specular[1],fw_BackMaterial.specular[2],fw_BackMaterial.specular[3],
6451  fw_BackMaterial.emission[0],fw_BackMaterial.emission[1],fw_BackMaterial.emission[2],fw_BackMaterial.emission[3],
6452  fw_BackMaterial.shininess);
6453 */
6454 
6455 PRINT_GL_ERROR_IF_ANY("BEGIN sendMaterialsToShader");
6456 
6457 /* eventually do this with code blocks in glsl */
6458  profile_start("sendvec");
6459  SEND_VEC4(myMaterialAmbient,fw_FrontMaterial->ambient);
6460  SEND_VEC4(myMaterialDiffuse,fw_FrontMaterial->diffuse);
6461  SEND_VEC4(myMaterialSpecular,fw_FrontMaterial->specular);
6462  SEND_VEC4(myMaterialEmission,fw_FrontMaterial->emission);
6463  SEND_FLOAT(myMaterialShininess,fw_FrontMaterial->shininess);
6464 
6465  SEND_VEC4(myMaterialBackAmbient,fw_BackMaterial->ambient);
6466  SEND_VEC4(myMaterialBackDiffuse,fw_BackMaterial->diffuse);
6467  SEND_VEC4(myMaterialBackSpecular,fw_BackMaterial->specular);
6468  SEND_VEC4(myMaterialBackEmission,fw_BackMaterial->emission);
6469  SEND_FLOAT(myMaterialBackShininess,fw_BackMaterial->shininess);
6470  profile_end("sendvec");
6471 
6472  if (me->haveLightInShader) sendLightInfo(me);
6473 
6474  /* FillProperties, LineProperty lineType */
6475  #if defined (GL_ES_VERSION_2_0)
6476  SEND_FLOAT(myPointSize,myap->pointSize);
6477  #else
6478  glPointSize(myap->pointSize > 0 ? myap->pointSize : 1);
6479  #endif
6480 
6481  profile_start("sendmat");
6482  //ConsoleMessage ("rlp %d %d %d %d",me->hatchPercent,me->filledBool,me->hatchedBool,me->algorithm,me->hatchColour);
6483  SEND_INT(filledBool,myap->filledBool);
6484  SEND_INT(hatchedBool,myap->hatchedBool);
6485  SEND_INT(algorithm,myap->algorithm);
6486  SEND_VEC4(hatchColour,myap->hatchColour);
6487  SEND_VEC2(hatchScale,myap->hatchScale);
6488  SEND_VEC2(hatchPercent,myap->hatchPercent);
6489 
6490  //TextureCoordinateGenerator
6491  SEND_INT(texCoordGenType,myap->texCoordGeneratorType);
6492  profile_end("sendmat");
6493  PRINT_GL_ERROR_IF_ANY("END sendMaterialsToShader");
6494 }
6495 
6496 void __gluMultMatrixVecd(const GLDOUBLE matrix[16], const GLDOUBLE in[4],
6497  GLDOUBLE out[4])
6498 {
6499  int i;
6500 
6501  for (i=0; i<4; i++) {
6502  out[i] =
6503  in[0] * matrix[0*4+i] +
6504  in[1] * matrix[1*4+i] +
6505  in[2] * matrix[2*4+i] +
6506  in[3] * matrix[3*4+i];
6507  }
6508 }
6509 
6510 
6511 void fw_gluProject
6512 (GLDOUBLE objx, GLDOUBLE objy, GLDOUBLE objz,
6513  const GLDOUBLE modelMatrix[16],
6514  const GLDOUBLE projMatrix[16],
6515  const GLint viewport[4],
6516  GLDOUBLE *winx, GLDOUBLE *winy, GLDOUBLE *winz)
6517 {
6518  GLDOUBLE in[4];
6519  GLDOUBLE out[4];
6520 
6521  in[0]=objx;
6522  in[1]=objy;
6523  in[2]=objz;
6524  in[3]=1.0;
6525  __gluMultMatrixVecd(modelMatrix, in, out);
6526  __gluMultMatrixVecd(projMatrix, out, in);
6527  if (in[3] == 0.0) return;
6528  in[0] /= in[3];
6529  in[1] /= in[3];
6530  in[2] /= in[3];
6531  /* Map x, y and z to range 0-1 */
6532  in[0] = in[0] * 0.5 + 0.5;
6533  in[1] = in[1] * 0.5 + 0.5;
6534  in[2] = in[2] * 0.5 + 0.5;
6535 
6536  /* Map x,y to viewport */
6537  in[0] = in[0] * viewport[2] + viewport[0];
6538  in[1] = in[1] * viewport[3] + viewport[1];
6539 
6540  *winx=in[0];
6541  *winy=in[1];
6542  *winz=in[2];
6543 }
6544 
6545 void __gluMultMatricesd(const GLDOUBLE a[16], const GLDOUBLE b[16],
6546  GLDOUBLE r[16])
6547 {
6548  int i, j;
6549 
6550  for (i = 0; i < 4; i++) {
6551  for (j = 0; j < 4; j++) {
6552  r[i*4+j] =
6553  a[i*4+0]*b[0*4+j] +
6554  a[i*4+1]*b[1*4+j] +
6555  a[i*4+2]*b[2*4+j] +
6556  a[i*4+3]*b[3*4+j];
6557  }
6558  }
6559 }
6560 
6561 
6562 /*
6563 ** Invert 4x4 matrix.
6564 ** Contributed by David Moore (See Mesa bug #6748)
6565 */
6566 int __gluInvertMatrixd(const GLDOUBLE m[16], GLDOUBLE invOut[16])
6567 {
6568  GLDOUBLE inv[16], det;
6569  int i;
6570 
6571  inv[0] = m[5]*m[10]*m[15] - m[5]*m[11]*m[14] - m[9]*m[6]*m[15]
6572  + m[9]*m[7]*m[14] + m[13]*m[6]*m[11] - m[13]*m[7]*m[10];
6573  inv[4] = -m[4]*m[10]*m[15] + m[4]*m[11]*m[14] + m[8]*m[6]*m[15]
6574  - m[8]*m[7]*m[14] - m[12]*m[6]*m[11] + m[12]*m[7]*m[10];
6575  inv[8] = m[4]*m[9]*m[15] - m[4]*m[11]*m[13] - m[8]*m[5]*m[15]
6576  + m[8]*m[7]*m[13] + m[12]*m[5]*m[11] - m[12]*m[7]*m[9];
6577  inv[12] = -m[4]*m[9]*m[14] + m[4]*m[10]*m[13] + m[8]*m[5]*m[14]
6578  - m[8]*m[6]*m[13] - m[12]*m[5]*m[10] + m[12]*m[6]*m[9];
6579  inv[1] = -m[1]*m[10]*m[15] + m[1]*m[11]*m[14] + m[9]*m[2]*m[15]
6580  - m[9]*m[3]*m[14] - m[13]*m[2]*m[11] + m[13]*m[3]*m[10];
6581  inv[5] = m[0]*m[10]*m[15] - m[0]*m[11]*m[14] - m[8]*m[2]*m[15]
6582  + m[8]*m[3]*m[14] + m[12]*m[2]*m[11] - m[12]*m[3]*m[10];
6583  inv[9] = -m[0]*m[9]*m[15] + m[0]*m[11]*m[13] + m[8]*m[1]*m[15]
6584  - m[8]*m[3]*m[13] - m[12]*m[1]*m[11] + m[12]*m[3]*m[9];
6585  inv[13] = m[0]*m[9]*m[14] - m[0]*m[10]*m[13] - m[8]*m[1]*m[14]
6586  + m[8]*m[2]*m[13] + m[12]*m[1]*m[10] - m[12]*m[2]*m[9];
6587  inv[2] = m[1]*m[6]*m[15] - m[1]*m[7]*m[14] - m[5]*m[2]*m[15]
6588  + m[5]*m[3]*m[14] + m[13]*m[2]*m[7] - m[13]*m[3]*m[6];
6589  inv[6] = -m[0]*m[6]*m[15] + m[0]*m[7]*m[14] + m[4]*m[2]*m[15]
6590  - m[4]*m[3]*m[14] - m[12]*m[2]*m[7] + m[12]*m[3]*m[6];
6591  inv[10] = m[0]*m[5]*m[15] - m[0]*m[7]*m[13] - m[4]*m[1]*m[15]
6592  + m[4]*m[3]*m[13] + m[12]*m[1]*m[7] - m[12]*m[3]*m[5];
6593  inv[14] = -m[0]*m[5]*m[14] + m[0]*m[6]*m[13] + m[4]*m[1]*m[14]
6594  - m[4]*m[2]*m[13] - m[12]*m[1]*m[6] + m[12]*m[2]*m[5];
6595  inv[3] = -m[1]*m[6]*m[11] + m[1]*m[7]*m[10] + m[5]*m[2]*m[11]
6596  - m[5]*m[3]*m[10] - m[9]*m[2]*m[7] + m[9]*m[3]*m[6];
6597  inv[7] = m[0]*m[6]*m[11] - m[0]*m[7]*m[10] - m[4]*m[2]*m[11]
6598  + m[4]*m[3]*m[10] + m[8]*m[2]*m[7] - m[8]*m[3]*m[6];
6599  inv[11] = -m[0]*m[5]*m[11] + m[0]*m[7]*m[9] + m[4]*m[1]*m[11]
6600  - m[4]*m[3]*m[9] - m[8]*m[1]*m[7] + m[8]*m[3]*m[5];
6601  inv[15] = m[0]*m[5]*m[10] - m[0]*m[6]*m[9] - m[4]*m[1]*m[10]
6602  + m[4]*m[2]*m[9] + m[8]*m[1]*m[6] - m[8]*m[2]*m[5];
6603 
6604  det = m[0]*inv[0] + m[1]*inv[4] + m[2]*inv[8] + m[3]*inv[12];
6605  if (det == 0)
6606  return GL_FALSE;
6607 
6608  det = 1.0 / det;
6609 
6610  for (i = 0; i < 16; i++)
6611  invOut[i] = inv[i] * det;
6612 
6613  return GL_TRUE;
6614 }
6615 
6616 
6617 
6618 void fw_gluUnProject(GLDOUBLE winx, GLDOUBLE winy, GLDOUBLE winz,
6619  const GLDOUBLE modelMatrix[16],
6620  const GLDOUBLE projMatrix[16],
6621  const GLint viewport[4],
6622  GLDOUBLE *objx, GLDOUBLE *objy, GLDOUBLE *objz)
6623 {
6624  /* https://www.opengl.org/sdk/docs/man2/xhtml/gluUnProject.xml
6625  FLOPs 196 double: full matmult 64, full mat inverse 102, full transform 16, miscalaneous 8
6626  */
6627  GLDOUBLE finalMatrix[16];
6628  GLDOUBLE in[4];
6629  GLDOUBLE out[4];
6630 
6631  __gluMultMatricesd(modelMatrix, projMatrix, finalMatrix);
6632  if (!__gluInvertMatrixd(finalMatrix, finalMatrix)) return;
6633 
6634  in[0]=winx;
6635  in[1]=winy;
6636  in[2]=winz;
6637  in[3]=1.0;
6638 
6639  /* Map x and y from window coordinates */
6640  in[0] = (in[0] - viewport[0]) / viewport[2];
6641  in[1] = (in[1] - viewport[1]) / viewport[3];
6642 
6643  /* Map to range -1 to 1 */
6644  in[0] = in[0] * 2 - 1;
6645  in[1] = in[1] * 2 - 1;
6646  in[2] = in[2] * 2 - 1;
6647 
6648  __gluMultMatrixVecd(finalMatrix, in, out);
6649  if (out[3] == 0.0) return;
6650  out[0] /= out[3];
6651  out[1] /= out[3];
6652  out[2] /= out[3];
6653  *objx = out[0];
6654  *objy = out[1];
6655  *objz = out[2];
6656 }
6657 
6658 
6659 void fw_Ortho (GLDOUBLE left, GLDOUBLE right, GLDOUBLE bottom, GLDOUBLE top, GLDOUBLE nearZ, GLDOUBLE farZ) {
6660  GLDOUBLE *dp;
6661  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
6662 
6663  /* do the glOrtho on the top of the stack, and send that along */
6664  dp = p->FW_ProjectionView[p->projectionviewTOS];
6665 
6666  /* do some bounds checking here */
6667  if (right <= left) right = left+1.0; /* resolve divide by zero possibility */
6668  if (top <= bottom) top= bottom+1.0; /* resolve divide by zero possibility */
6669  if (farZ <= nearZ) farZ= nearZ + 2.0; /* resolve divide by zero possibility */
6670 
6671  /* {int i; for (i=0; i<16;i++) { printf ("ModView before %d: %4.3f \n",i,dp[i]); } } */
6672  mesa_Ortho(left,right,bottom,top,nearZ,farZ,dp);
6673 
6674  /* {int i; for (i=0; i<16;i++) { printf ("ModView after %d: %4.3f \n",i,dp[i]); } } */
6675 
6676  FW_GL_LOADMATRIX(dp);
6677 }
6678 
6679 
6680 /* gluPerspective replacement */
6681 void fw_gluPerspective(GLDOUBLE fovy, GLDOUBLE aspect, GLDOUBLE zNear, GLDOUBLE zFar) {
6682  GLDOUBLE xmin, xmax, ymin, ymax;
6683 
6684  GLDOUBLE *dp;
6685  GLDOUBLE ndp[16];
6686  GLDOUBLE ndp2[16];
6687  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
6688 
6689 
6690 
6691  ymax = zNear * tan(fovy * M_PI / 360.0);
6692  ymin = -ymax;
6693  xmin = ymin * aspect;
6694  xmax = ymax * aspect;
6695 
6696  /* do the glFrsutum on the top of the stack, and send that along */
6697  FW_GL_MATRIX_MODE(GL_PROJECTION);
6698  //FW_GL_LOAD_IDENTITY();
6699  dp = p->FW_ProjectionView[p->projectionviewTOS];
6700 
6701  mesa_Frustum(xmin, xmax, ymin, ymax, zNear, zFar, ndp);
6702  mattranspose(ndp2,ndp);
6703 
6704  //printmatrix2(ndp,"ndp");
6705  //printmatrix2(ndp2,"ndp2 = transpose(ndp)");
6706  //JAS printmatrix2(dp,"dp");
6707 
6708  matmultiplyFULL(ndp,ndp2,dp);
6709 
6710  //printmatrix2(ndp,"ndp = ndp2*dp");
6711 
6712  /* method = 1; */
6713  #define TRY_PERSPECTIVE_METHOD_1
6714  #ifdef TRY_PERSPECTIVE_METHOD_1
6715  FW_GL_LOADMATRIX(ndp);
6716  /* put the matrix back on our matrix stack */
6717  memcpy (p->FW_ProjectionView[p->projectionviewTOS],ndp,16*sizeof (GLDOUBLE));
6718  #endif
6719 
6720 
6721  #ifdef TRY_PERSPECTIVE_METHOD_2
6722 /* testing... */
6723 {
6724  GLDOUBLE m[16];
6725  GLDOUBLE sine, cotangent, deltaZ;
6726  GLDOUBLE radians = fovy / 2.0 * M_PI / 180.0;
6727 
6728  deltaZ = zFar - zNear;
6729  sine = sin(radians);
6730  if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) {
6731  return;
6732  }
6733  cotangent = cos(radians) / sine;
6734 
6735  loadIdentityMatrix(m); //(&m);
6736  //__gluMakeIdentityd(&m[0][0]);
6737  m[0*4+0] = cotangent / aspect;
6738  m[1*4+1] = cotangent;
6739  m[2*4+2] = -(zFar + zNear) / deltaZ;
6740  m[2*4+3] = -1;
6741  m[3*4+2] = -2 * zNear * zFar / deltaZ;
6742  m[3*4+3] = 0;
6743  matmultiplyFULL(m,m,dp);
6744  if(method==2)
6745  FW_GL_LOADMATRIX(m);
6746 
6747  //glMultMatrixd(&m[0][0]);
6748 }
6749  #endif
6750 
6751 
6752  #ifdef TRY_PERSPECTIVE_METHOD_3
6753  {
6754  GLDOUBLE yyy[16];
6755 //printf ("fw_gluPerspective, have...\n");
6756 
6757  if(method==3)
6758  gluPerspective(fovy,aspect,zNear,zFar);
6759  FW_GL_GETDOUBLEV(GL_PROJECTION_MATRIX,yyy);
6760  //JAS printmatrix2(dp,"dp orig");
6761  //JAS printmatrix2(ndp,"ndp myPup");
6762  //JAS printmatrix2(yyy,"yyy gluP");
6763  //JAS printmatrix2(m,"m mesa");
6764  //for (i=0; i<16;i++) {printf ("%d orig: %5.2lf myPup: %5.2lf gluP: %5.2lf mesa %5.2lf\n",i,dp[i],
6765  // ndp[i],yyy[i],m[i]);
6766  //}
6767  }
6768  #endif
6769 
6770 }
6771 
6772 void fw_gluPerspective_2(GLDOUBLE xcenter, GLDOUBLE fovy, GLDOUBLE aspect, GLDOUBLE zNear, GLDOUBLE zFar) {
6773  //xcenter is 0.0 if you want the perspective in the center of the viewport.
6774  // -1.0 if you want it on the left edge
6775  // +1.0 if you want it on the right edge
6776  GLDOUBLE xmin, xmax, ymin, ymax;
6777 
6778  GLDOUBLE *dp;
6779  GLDOUBLE ndp[16];
6780  GLDOUBLE ndp2[16];
6781  ppOpenGL_Utils p = (ppOpenGL_Utils)gglobal()->OpenGL_Utils.prv;
6782 
6783 
6784 
6785  ymax = zNear * tan(fovy * M_PI / 360.0);
6786  ymin = -ymax;
6787  xmin = ymin * aspect;
6788  xmax = ymax * aspect;
6789  xmin += xcenter * xmin;
6790  xmax += xcenter * xmin;
6791  /* do the glFrsutum on the top of the stack, and send that along */
6792  FW_GL_MATRIX_MODE(GL_PROJECTION);
6793  //FW_GL_LOAD_IDENTITY();
6794  dp = p->FW_ProjectionView[p->projectionviewTOS];
6795 
6796  mesa_Frustum(xmin, xmax, ymin, ymax, zNear, zFar, ndp);
6797  mattranspose(ndp2,ndp);
6798 
6799  //printmatrix2(ndp,"ndp");
6800  //printmatrix2(ndp2,"ndp2 = transpose(ndp)");
6801  //JAS printmatrix2(dp,"dp");
6802 
6803  matmultiplyFULL(ndp,ndp2,dp);
6804 
6805  //printmatrix2(ndp,"ndp = ndp2*dp");
6806 
6807  /* method = 1; */
6808  FW_GL_LOADMATRIX(ndp);
6809  /* put the matrix back on our matrix stack */
6810  memcpy (p->FW_ProjectionView[p->projectionviewTOS],ndp,16*sizeof (GLDOUBLE));
6811 }
6812 
6813 
6814 /* gluPickMatrix replacement */
6815 void fw_gluPickMatrix(GLDOUBLE xx, GLDOUBLE yy, GLDOUBLE width, GLDOUBLE height, GLint *vp) {
6816  #ifdef VERBOSE
6817  printf ("PickMat %lf %lf %lf %lf %d %d %d %d\n",xx,yy,width,height,vp[0], vp[1],vp[2],vp[3]);
6818  #endif
6819 
6820  if ((width < 0.0) || (height < 0.0)) return;
6821  /* Translate and scale the picked region to the entire window */
6822  FW_GL_TRANSLATE_D((vp[2] - 2.0 * (xx - vp[0])) / width, (vp[3] - 2.0 * (yy - vp[1])) / height, 0.0);
6823  FW_GL_SCALE_D(vp[2] / width, vp[3] / height, 1.0);
6824 
6825 }
6826 
6827 
6828 /* glFrustum replacement - taken from the MESA source;
6829 
6830  * matrix.c
6831  *
6832  * Some useful matrix functions.
6833  *
6834  * Brian Paul
6835  * 10 Feb 2004
6836  */
6837 
6842 static void
6843 mesa_Frustum(GLDOUBLE left, GLDOUBLE right, GLDOUBLE bottom, GLDOUBLE top, GLDOUBLE nearZ, GLDOUBLE farZ, GLDOUBLE *m)
6844 {
6845  /* http://www.songho.ca/opengl/gl_projectionmatrix.html shows derivation*/
6846  GLDOUBLE x = (2.0*nearZ) / (right-left);
6847  GLDOUBLE y = (2.0*nearZ) / (top-bottom);
6848  GLDOUBLE a = (right+left) / (right-left);
6849  GLDOUBLE b = (top+bottom) / (top-bottom);
6850  GLDOUBLE c = -(farZ+nearZ) / ( farZ-nearZ);
6851  GLDOUBLE d = -(2.0F*farZ*nearZ) / (farZ-nearZ);
6852 
6853  /* printf ("mesa_Frustum (%lf, %lf, %lf, %lf, %lf, %lf)\n",left,right,bottom,top,nearZ, farZ); */
6854  m[0] = x;
6855  m[1] = 0.0;
6856  m[2] = a;
6857  m[3] = 0.0;
6858 
6859  m[4] = 0.0;
6860  m[5] = y;
6861  m[6] = b;
6862  m[7] = 0.0;
6863 
6864  m[8] = 0.0;
6865  m[9] = 0.0;
6866  m[10] = c;
6867  m[11] = d;
6868 
6869  m[12] = 0.0;
6870  m[13] = 0.0;
6871  m[14] = -1.0;
6872  m[15] = 0.0;
6873 /*
6874 
6875 #define M(row,col) m[col*4+row]
6876  M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F;
6877  M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F;
6878  M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d;
6879  M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F;
6880 #undef M
6881 */
6882 }
6883 
6887 static void
6888 mesa_Ortho(GLDOUBLE left, GLDOUBLE right, GLDOUBLE bottom, GLDOUBLE top, GLDOUBLE nearZ, GLDOUBLE farZ, GLDOUBLE *m)
6889 {
6890 #define M(row,col) m[col*4+row]
6891  M(0,0) = 2.0F / (right-left);
6892  M(0,1) = 0.0F;
6893  M(0,2) = 0.0F;
6894  M(0,3) = -(right+left) / (right-left);
6895 
6896  M(1,0) = 0.0F;
6897  M(1,1) = 2.0F / (top-bottom);
6898  M(1,2) = 0.0F;
6899  M(1,3) = -(top+bottom) / (top-bottom);
6900 
6901  M(2,0) = 0.0F;
6902  M(2,1) = 0.0F;
6903  M(2,2) = -2.0F / (farZ-nearZ);
6904  M(2,3) = -(farZ+nearZ) / (farZ-nearZ);
6905 
6906  M(3,0) = 0.0F;
6907  M(3,1) = 0.0F;
6908  M(3,2) = 0.0F;
6909  M(3,3) = 1.0F;
6910 #undef M
6911 }
Definition: Viewer.h:196
Definition: Vector.h:36
Definition: display.c:65