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