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