FreeWRL/FreeX3D  3.0.0
Component_Shape.c
1 /*
2 
3 
4 X3D Shape Component
5 
6 */
7 
8 
9 /****************************************************************************
10  This file is part of the FreeWRL/FreeX3D Distribution.
11 
12  Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
13 
14  FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
15  it under the terms of the GNU Lesser Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  FreeWRL/FreeX3D is distributed in the hope that it will be useful,
20  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  GNU General Public License for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
26 ****************************************************************************/
27 
28 
29 
30 #include <config.h>
31 #include <system.h>
32 #include <display.h>
33 #include <internal.h>
34 
35 #include <libFreeWRL.h>
36 
37 #include "../vrml_parser/Structs.h"
38 #include "../main/headers.h"
39 #include "../opengl/Frustum.h"
40 #include "../opengl/Material.h"
41 #include "../opengl/OpenGL_Utils.h"
42 #include "../opengl/Textures.h"
43 #include "Component_ProgrammableShaders.h"
44 #include "Component_Shape.h"
45 #include "RenderFuncs.h"
46 
47 #define NOTHING 0
48 
49 typedef struct pComponent_Shape{
50 
51  struct matpropstruct appearanceProperties;
52 
53  /* pointer for a TextureTransform type of node */
54  struct X3D_Node * this_textureTransform; /* do we have some kind of textureTransform? */
55 
56  /* for doing shader material properties */
57  struct X3D_TwoSidedMaterial *material_twoSided;
58  struct X3D_Material *material_oneSided;
59 
60  /* Any user defined shaders here? */
61  struct X3D_Node * userShaderNode;
62 
64 
65 static void *Component_Shape_constructor(){
66  void *v = MALLOCV(sizeof(struct pComponent_Shape));
67  memset(v,0,sizeof(struct pComponent_Shape));
68  return v;
69 }
70 void Component_Shape_init(struct tComponent_Shape *t){
71  //public
72  //private
73  t->prv = Component_Shape_constructor();
74 }
75 
76 //getters
77 struct matpropstruct *getAppearanceProperties(){
78  ppComponent_Shape p = (ppComponent_Shape)gglobal()->Component_Shape.prv;
79 
80  return &p->appearanceProperties;
81 }
82 
83 // see if the Appearance node has a valid Shader node as a child.
84 static int hasUserDefinedShader(struct X3D_Node *node) {
85 #define NO_SHADER 99999
86  unsigned int rv = NO_SHADER;
87 
88  if (node==NULL) return 0;
89 
90  //ConsoleMessage ("hasUserDeginedShader, node ptr %p",node);
91  //ConsoleMessage ("hasUserDefinedShader, nodeType %s",stringNodeType(node->_nodeType));
92  if (node->_nodeType == NODE_Appearance) {
93  struct X3D_Appearance *ap;
94  POSSIBLE_PROTO_EXPANSION(struct X3D_Appearance *, node, ap);
95  //ConsoleMessage ("appearance node shaders is %d %p",ap->shaders.n, ap->shaders.p);
96 
97  if (ap && ap->shaders.n != 0) {
98  struct X3D_ComposedShader *cps;
99 
100  /* ok - what kind of node is here, and are there more than two? */
101  if (ap->shaders.n > 1) {
102  ConsoleMessage ("warning, Appearance->shaders has more than 1 node, using only first one");
103  }
104 
105  POSSIBLE_PROTO_EXPANSION(struct X3D_ComposedShader *, ap->shaders.p[0], cps);
106 
107  //ConsoleMessage ("node type of shaders is :%s:",stringNodeType(cps->_nodeType));
108  if(cps){
109  if (cps->_nodeType == NODE_ComposedShader) {
110  // might be set in compile_Shader already
111  //ConsoleMessage ("cps->_initialized %d",cps->_initialized);
112  //ConsoleMessage ("cps->_retrievedURLData %d",cps->_retrievedURLData);
113 
114  if (cps->_retrievedURLData) {
115  if (cps->_shaderUserNumber == -1) cps->_shaderUserNumber = getNextFreeUserDefinedShaderSlot();
116  rv = cps->_shaderUserNumber;
117  }
118  } else if (cps->_nodeType == NODE_PackagedShader) {
119  // might be set in compile_Shader already
120  if (X3D_PACKAGEDSHADER(cps)->_retrievedURLData) {
121  if (X3D_PACKAGEDSHADER(cps)->_shaderUserNumber == -1)
122  X3D_PACKAGEDSHADER(cps)->_shaderUserNumber = getNextFreeUserDefinedShaderSlot();
123  rv = X3D_PACKAGEDSHADER(cps)->_shaderUserNumber;
124  }
125  } else if (cps->_nodeType == NODE_ProgramShader) {
126  // might be set in compile_Shader already
127  if (X3D_PROGRAMSHADER(cps)->_retrievedURLData) {
128  if (X3D_PROGRAMSHADER(cps)->_shaderUserNumber == -1)
129  X3D_PROGRAMSHADER(cps)->_shaderUserNumber = getNextFreeUserDefinedShaderSlot();
130 
131  rv = X3D_PROGRAMSHADER(cps)->_shaderUserNumber;
132  }
133  } else {
134  ConsoleMessage ("shader field of Appearance is a %s, ignoring",stringNodeType(cps->_nodeType));
135  }
136  }
137 
138  }
139  }
140 
141  //ConsoleMessage ("and ste is %d",ste);
142 
143  // ok - did we find an integer between 0 and some MAX_SUPPORTED_USER_SHADERS value?
144  if (rv == NO_SHADER) rv = 0;
145  //else rv = USER_DEFINED_SHADER_START * (rv+1);
146 
147  //ConsoleMessage ("rv is going to be %x",rv);
148 
149  //ConsoleMessage ("hasUserDefinedShader, returning %p",*shaderTableEntry);
150  return rv;
151 }
152 int hasGeneratedCubeMapTexture(struct X3D_Appearance *appearance){
153  int ret = FALSE;
154  struct X3D_Appearance *tmpN;
155  POSSIBLE_PROTO_EXPANSION(struct X3D_Appearance *, X3D_NODE(appearance),tmpN)
156  if(tmpN && tmpN->texture)
157  if(tmpN->texture->_nodeType == NODE_GeneratedCubeMapTexture) ret = TRUE;
158  return ret;
159 }
160 // Save the shader node from the render_*Shader so that we can send in parameters when required
161 void setUserShaderNode(struct X3D_Node *me) {
162  ppComponent_Shape p = (ppComponent_Shape)gglobal()->Component_Shape.prv;
163  p->userShaderNode = me;
164 }
165 
166 struct X3D_Node *getThis_textureTransform(){
167  ppComponent_Shape p = (ppComponent_Shape)gglobal()->Component_Shape.prv;
168  return p->this_textureTransform;
169 }
170 
171 void child_Appearance (struct X3D_Appearance *node) {
172  struct X3D_Node *tmpN;
173  ttglobal tg = gglobal();
174 
175  /* printf ("in Appearance, this %d, nodeType %d\n",node, node->_nodeType);
176  printf (" vp %d geom %d light %d sens %d blend %d prox %d col %d\n",
177  render_vp,render_geom,render_light,render_sensitive,render_blend,render_proximity,render_collision); */
178 
179  /* Render the material node... */
180  RENDER_MATERIAL_SUBNODES(node->material);
181 
182  if (node->fillProperties) {
183  POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, node->fillProperties,tmpN);
184  render_node(tmpN);
185  }
186 
187  /* set line widths - if we have line a lineProperties node */
188  if (node->lineProperties) {
189  POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, node->lineProperties,tmpN);
190  render_node(tmpN);
191  }
192 
193  if(node->texture) {
194  /* we have to do a glPush, then restore, later */
195  /* glPushAttrib(GL_ENABLE_BIT); */
196 
197  ppComponent_Shape p = (ppComponent_Shape)gglobal()->Component_Shape.prv;
198 
199 
200  /* is there a TextureTransform? if no texture, fugutaboutit */
201  POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, node->textureTransform,p->this_textureTransform);
202 
203  /* now, render the texture */
204  POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, node->texture,tmpN);
205  tg->RenderFuncs.texturenode = (void*)tmpN;
206 
207  render_node(tmpN);
208  }
209 
210  /* shaders here/supported?? */
211  if (node->shaders.n !=0) {
212  int count;
213  int foundGoodShader = FALSE;
214 
215  for (count=0; count<node->shaders.n; count++) {
216  POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, node->shaders.p[count], tmpN);
217 
218  /* have we found a valid shader yet? */
219  if(tmpN){
220  if (foundGoodShader) {
221  /* printf ("skipping shader %d of %d\n",count, node->shaders.n); */
222  /* yes, just tell other shaders that they are not selected */
223  SET_SHADER_SELECTED_FALSE(tmpN);
224  } else {
225  /* render this node; if it is valid, then we call this one the selected one */
226  SET_FOUND_GOOD_SHADER(tmpN);
227  DEBUG_SHADER("running shader (%s) %d of %d\n",
228  stringNodeType(X3D_NODE(tmpN)->_nodeType),count, node->shaders.n);
229  render_node(tmpN);
230  }
231  }
232  }
233  }
234 
235  /* castle Effects here/supported?? */
236  if (node->effects.n !=0) {
237  //int count;
238  //int foundGoodShader = FALSE;
239  prep_sibAffectors(X3D_NODE(node),&node->effects);
240 
241  //for (count=0; count<node->effects.n; count++) {
242  // POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, node->effects.p[count], tmpN);
243  //
244  // /* have we found a valid shader yet? */
245  // if(tmpN){
246  // //if (foundGoodShader) {
247  // // /* printf ("skipping shader %d of %d\n",count, node->shaders.n); */
248  // // /* yes, just tell other shaders that they are not selected */
249  // // SET_SHADER_SELECTED_FALSE(tmpN);
250  // //} else {
251  // // /* render this node; if it is valid, then we call this one the selected one */
252  // // SET_FOUND_GOOD_SHADER(tmpN);
253  // DEBUG_SHADER("running shader (%s) %d of %d\n",
254  // stringNodeType(X3D_NODE(tmpN)->_nodeType),count, node->effects.n);
255  // //render_node(tmpN);
256  // prep_sibAffectors(node,&node->effects);
257  // //}
258  // }
259  //}
260  }
261 
262 }
263 
264 
265 void render_Material (struct X3D_Material *node) {
266  COMPILE_IF_REQUIRED
267  {
268  ppComponent_Shape p = (ppComponent_Shape)gglobal()->Component_Shape.prv;
269 
270  /* record this node for OpenGL-ES and OpenGL-3.1 operation */
271  p->material_oneSided = node;
272  }
273 }
274 struct X3D_Material *get_material_oneSided(){
275  ppComponent_Shape p = (ppComponent_Shape)gglobal()->Component_Shape.prv;
276  return p->material_oneSided;
277 }
278 struct X3D_TwoSidedMaterial *get_material_twoSided(){
279  ppComponent_Shape p = (ppComponent_Shape)gglobal()->Component_Shape.prv;
280  return p->material_twoSided;
281 }
282 
283 /* bounds check the material node fields */
284 void compile_Material (struct X3D_Material *node) {
285  int i;
286  float trans;
287 
288  /* verify that the numbers are within range */
289  if (node->ambientIntensity < 0.0f) node->ambientIntensity=0.0f;
290  if (node->ambientIntensity > 1.0f) node->ambientIntensity=1.0f;
291  if (node->shininess < 0.0f) node->shininess=0.0f;
292  if (node->shininess > 1.0f) node->shininess=1.0f;
293  if (node->transparency < 0.0f) node->transparency=MIN_NODE_TRANSPARENCY;
294  if (node->transparency >= 1.0f) node->transparency=MAX_NODE_TRANSPARENCY;
295 
296  for (i=0; i<3; i++) {
297  if (node->diffuseColor.c[i] < 0.0f) node->diffuseColor.c[i]=0.0f;
298  if (node->diffuseColor.c[i] > 1.0f) node->diffuseColor.c[i]=1.0f;
299  if (node->emissiveColor.c[i] < 0.0f) node->emissiveColor.c[i]=0.0f;
300  if (node->emissiveColor.c[i] > 1.0f) node->emissiveColor.c[i]=1.0f;
301  if (node->specularColor.c[i] < 0.0f) node->specularColor.c[i]=0.0f;
302  if (node->specularColor.c[i] > 1.0f) node->specularColor.c[i]=1.0f;
303  }
304 
305  /* set the transparency here for the material */
306  /* Remember, VRML/X3D transparency 0.0 = solid; OpenGL 1.0 = solid, so we reverse it... */
307  trans = 1.0f - node->transparency;
308 
309  /* we now keep verified params in a structure that maps to Shaders well...
310  struct gl_MaterialParameters {
311  vec4 emission;
312  vec4 ambient;
313  vec4 diffuse;
314  vec4 specular;
315  float shininess;
316  };
317  which is stored in the _verifiedColor[17] array here.
318  emission [0]..[3];
319  ambient [4]..[7];
320  diffuse [8]..[11];
321  specular [12]..[15];
322  shininess [16]
323 */
324  /* first, put in the transparency */
325  node->_verifiedColor.p[3] = trans;
326  node->_verifiedColor.p[7] = trans;
327  node->_verifiedColor.p[11] = trans;
328  node->_verifiedColor.p[15] = trans;
329 
330  /* DiffuseColor */
331  memcpy((void *)(&node->_verifiedColor.p[8]), node->diffuseColor.c, sizeof (float) * 3);
332 
333  /* Ambient - diffuseColor * ambientIntensity */
334  for(i=0; i<3; i++) { node->_verifiedColor.p[i+4] = node->_verifiedColor.p[i+8] * node->ambientIntensity; }
335 
336  /* Specular */
337  memcpy((void *)(&node->_verifiedColor.p[12]), node->specularColor.c, sizeof (float) * 3);
338 
339  /* Emissive */
340  memcpy((void *)(&node->_verifiedColor.p[0]), node->emissiveColor.c, sizeof (float) * 3);
341 
342  /* Shininess */
343  node->_verifiedColor.p[16] = node->shininess * 128.0f;
344 
345 #define MAX_SHIN 128.0f
346 #define MIN_SHIN 0.01f
347  if ((node->_verifiedColor.p[16] > MAX_SHIN) || (node->_verifiedColor.p[16] < MIN_SHIN)) {
348  if (node->_verifiedColor.p[16]>MAX_SHIN){node->_verifiedColor.p[16] = MAX_SHIN;}else{node->_verifiedColor.p[16]=MIN_SHIN;}
349  }
350 #undef MAX_SHIN
351 #undef MIN_SHIN
352 
353  MARK_NODE_COMPILED
354 }
355 
356 #define CHECK_COLOUR_FIELD(aaa) \
357  case NODE_##aaa: { \
358  struct X3D_##aaa *me = (struct X3D_##aaa *)realNode; \
359  if (me->color == NULL) return NOTHING; /* do not add any properties here */\
360  else return COLOUR_MATERIAL_SHADER; \
361  break; \
362  }
363 #define CHECK_FOGCOORD_FIELD(aaa) \
364  case NODE_##aaa: { \
365  struct X3D_##aaa *me = (struct X3D_##aaa *)realNode; \
366  if (me->fogCoord == NULL) return NOTHING; /* do not add any properties here */\
367  else return HAVE_FOG_COORDS; \
368  break; \
369  }
370 
371 
372 /* if this is a LineSet, PointSet, etc... */
373 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/lighting.html#Lightingoff
374 // 'shapes that represent points or lines are unlit
375 static bool getIfLinePoints(struct X3D_Node *realNode) {
376  if (realNode == NULL) return false;
377  switch (realNode->_nodeType) {
378  case NODE_IndexedLineSet:
379  case NODE_LineSet:
380  case NODE_PointSet:
381  case NODE_Polyline2D:
382  case NODE_Polypoint2D:
383  case NODE_Circle2D:
384  case NODE_Arc2D:
385  return true;
386  }
387  return false; // do not add any capabilites here.
388 }
389 
390 /* is the texCoord field a TextureCoordinateGenerator or not? */
391 struct X3D_Node *getGeomTexCoordField(struct X3D_Node *realGeomNode){
392  struct X3D_Node *tc = NULL;
393  int *fieldOffsetsPtr = NULL;
394 
395  //ConsoleMessage ("getShapeTextureCoordGen, node type %s\n",stringNodeType(realNode->_nodeType));
396  if (realGeomNode == NULL) return tc;
397 
398  fieldOffsetsPtr = (int *)NODE_OFFSETS[realGeomNode->_nodeType];
399  /*go thru all field*/
400  while (*fieldOffsetsPtr != -1) {
401  if (*fieldOffsetsPtr == FIELDNAMES_texCoord) {
402  // get the pointer stored here...
403  memcpy(&tc,offsetPointer_deref(void*, realGeomNode,*(fieldOffsetsPtr+1)),sizeof(struct X3D_Node *));
404  break;
405  }
406  fieldOffsetsPtr += 5;
407  }
408  return tc;
409 
410 }
411 static int getShapeTextureCoordGen(struct X3D_Node *realNode) {
412  struct X3D_Node *tc = NULL;
413  tc = getGeomTexCoordField(realNode);
414  if (tc != NULL) {
415  if (tc->_nodeType == NODE_TextureCoordinateGenerator) return HAVE_TEXTURECOORDINATEGENERATOR;
416  }
417  return 0;
418 }
419 
420 
421 /* Some shapes have Color nodes - if so, then we have other shaders */
422 static int getShapeColourShader (struct X3D_Node *myGeom) {
423  struct X3D_Node *realNode;
424 
425  POSSIBLE_PROTO_EXPANSION(struct X3D_Node *,myGeom,realNode);
426 
427  if (realNode == NULL) return NOTHING;
428 
429  /* go through each node type that can have a Color node, and if it is not NULL
430  we know we have a Color node */
431 
432  switch (realNode->_nodeType) {
433  CHECK_COLOUR_FIELD(IndexedFaceSet);
434  CHECK_COLOUR_FIELD(IndexedLineSet);
435  CHECK_COLOUR_FIELD(IndexedTriangleFanSet);
436  CHECK_COLOUR_FIELD(IndexedTriangleSet);
437  CHECK_COLOUR_FIELD(IndexedTriangleStripSet);
438  CHECK_COLOUR_FIELD(LineSet);
439  CHECK_COLOUR_FIELD(PointSet);
440  CHECK_COLOUR_FIELD(TriangleFanSet);
441  CHECK_COLOUR_FIELD(TriangleStripSet);
442  CHECK_COLOUR_FIELD(TriangleSet);
443  CHECK_COLOUR_FIELD(ElevationGrid);
444  CHECK_COLOUR_FIELD(GeoElevationGrid);
445  CHECK_COLOUR_FIELD(QuadSet);
446  CHECK_COLOUR_FIELD(IndexedQuadSet);
447  }
448 
449  /* if we are down here, we KNOW we do not have a color field */
450  return NOTHING; /* do not add any capabilites here */
451 }
452 /* Some shapes have Color nodes - if so, then we have other shaders */
453 static int getShapeFogShader (struct X3D_Node *myGeom) {
454  struct X3D_Node *realNode;
455 
456  POSSIBLE_PROTO_EXPANSION(struct X3D_Node *,myGeom,realNode);
457 
458  if (realNode == NULL) return NOTHING;
459 
460  /* go through each node type that can have a Color node, and if it is not NULL
461  we know we have a Color node */
462 
463  switch (realNode->_nodeType) {
464  CHECK_FOGCOORD_FIELD(IndexedFaceSet);
465  CHECK_FOGCOORD_FIELD(IndexedLineSet);
466  CHECK_FOGCOORD_FIELD(IndexedTriangleFanSet);
467  CHECK_FOGCOORD_FIELD(IndexedTriangleSet);
468  CHECK_FOGCOORD_FIELD(IndexedTriangleStripSet);
469  CHECK_FOGCOORD_FIELD(LineSet);
470  CHECK_FOGCOORD_FIELD(PointSet);
471  CHECK_FOGCOORD_FIELD(TriangleFanSet);
472  CHECK_FOGCOORD_FIELD(TriangleStripSet);
473  CHECK_FOGCOORD_FIELD(TriangleSet);
474  CHECK_FOGCOORD_FIELD(ElevationGrid);
475  //CHECK_FOGCOORD_FIELD(GeoElevationGrid);
476  CHECK_FOGCOORD_FIELD(QuadSet);
477  CHECK_FOGCOORD_FIELD(IndexedQuadSet);
478  }
479 
480  /* if we are down here, we KNOW we do not have a color field */
481  return NOTHING; /* do not add any capabilites here */
482 }
483 
484 static int getAppearanceShader (struct X3D_Node *myApp) {
485  struct X3D_Appearance *realAppearanceNode;
486  struct X3D_Node *realMaterialNode;
487 
488 
489  int retval = NOTHING;
490 
491  /* if there is no appearance node... */
492  if (myApp == NULL) return retval;
493 
494  POSSIBLE_PROTO_EXPANSION(struct X3D_Appearance *, myApp,realAppearanceNode);
495  if (!realAppearanceNode || realAppearanceNode->_nodeType != NODE_Appearance) return retval;
496 
497  if (realAppearanceNode->material != NULL) {
498  POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, realAppearanceNode->material,realMaterialNode);
499  if(realMaterialNode) {
500  if (realMaterialNode->_nodeType == NODE_Material) {
501  retval |= MATERIAL_APPEARANCE_SHADER;
502  }
503  if (realMaterialNode->_nodeType == NODE_TwoSidedMaterial) {
504  retval |= TWO_MATERIAL_APPEARANCE_SHADER;
505  }
506  }
507  }
508 
509 
510  if (realAppearanceNode->fillProperties != NULL) {
511  struct X3D_Node *fp;
512  POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, realAppearanceNode->fillProperties,fp);
513  if(fp){
514  if (fp->_nodeType != NODE_FillProperties) {
515  ConsoleMessage("getAppearanceShader, fillProperties has a node type of %s",stringNodeType(fp->_nodeType));
516  } else {
517  // is this a FillProperties node, but is it enabled?
518  if (X3D_FILLPROPERTIES(fp)->_enabled)
519  retval |= FILL_PROPERTIES_SHADER;
520  }
521  }
522  }
523 
524 
525  if (realAppearanceNode->texture != NULL) {
526  //printf ("getAppearanceShader - rap node is %s\n",stringNodeType(realAppearanceNode->texture->_nodeType));
527  struct X3D_Node *tex;
528 
529  POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, realAppearanceNode->texture,tex);
530  if(tex){
531  if ((tex->_nodeType == NODE_ImageTexture) ||
532  (tex->_nodeType == NODE_MovieTexture) ||
533  (tex->_nodeType == NODE_PixelTexture) ){
534  retval |= ONE_TEX_APPEARANCE_SHADER;
535  } else if( (tex->_nodeType == NODE_PixelTexture3D) ||
536  (tex->_nodeType == NODE_ComposedTexture3D) ||
537  (tex->_nodeType == NODE_ImageTexture3D) ) {
538  retval |= ONE_TEX_APPEARANCE_SHADER;
539  retval |= TEX3D_SHADER; //VOLUME by default
540  if(tex->_nodeType == NODE_ComposedTexture3D)
541  retval |= TEX3D_LAYER_SHADER; //else VOLUME
542  } else if (tex->_nodeType == NODE_MultiTexture) {
543  retval |= MULTI_TEX_APPEARANCE_SHADER;
544  } else if ((tex->_nodeType == NODE_ComposedCubeMapTexture) ||
545  (tex->_nodeType == NODE_ImageCubeMapTexture) ||
546  (tex->_nodeType == NODE_GeneratedCubeMapTexture)) {
547  retval |= HAVE_CUBEMAP_TEXTURE;
548  } else {
549  ConsoleMessage ("getAppearanceShader, texture field %s not supported yet\n",
550  stringNodeType(tex->_nodeType));
551  }
552  }
553  }
554 
555  #ifdef SHAPE_VERBOSE
556  printf ("getAppearanceShader, returning %x\n",retval);
557  #endif //SHAPE_VERBOSE
558 
559  return retval;
560 }
561 
562 
563 /* find info on the appearance of this Shape and create a shader */
564 /*
565  The possible sequence of a properly constructed appearance field is:
566 
567  Shape.appearance -> Appearance
568 
569  Appearance.fillProperties -> FillProperties
570  Appearance.lineProperties -> LineProperties
571  Appearance.material -> Material
572  -> TwoSidedMaterial
573  Appearance.shaders -> ComposedShader
574  Appearance.shaders -> PackagedShader
575  Appearance.shaders -> ProgramShader
576 
577  Appearance.texture -> Texture
578  Appearance.texture -> MultiTexture
579  Appearance.textureTransform ->
580 
581 */
582 
583 /* now works with our pushing matricies (norm, proj, modelview) but not for complete shader appearance replacement */
584 void render_FillProperties (struct X3D_FillProperties *node) {
585  GLfloat hatchX;
586  GLfloat hatchY;
587  GLint algor;
588  GLint hatched;
589  GLint filled;
590 
591  struct matpropstruct *me= getAppearanceProperties();
592 
593  hatchX = 0.80f; hatchY = 0.80f;
594  algor = node->hatchStyle; filled = node->filled; hatched = node->hatched;
595  switch (node->hatchStyle) {
596  case 0: break; /* bricking - not standard X3D */
597  case 1: hatchX = 1.0f; break; /* horizontal lines */
598  case 2: hatchY = 1.0f; break; /* vertical lines */
599  case 3: hatchY=1.0f; break; /* positive sloped lines */
600  case 4: hatchY=1.0f; break; /* negative sloped lines */
601  case 5: break; /* square pattern */
602  case 6: hatchY = 1.0f; break; /* diamond pattern */
603 
604  default :{
605  node->hatched = FALSE; /* woops - something wrong here disable */
606  }
607  }
608 
609  me->filledBool = filled;
610  me->hatchedBool = hatched;
611  me->hatchPercent[0] = hatchX;
612  me->hatchPercent[1] = hatchY;
613  me->hatchScale[0] = node->_hatchScale.c[0];
614  me->hatchScale[1] = node->_hatchScale.c[1];
615  me->algorithm = algor;
616  me->hatchColour[0]=node->hatchColor.c[0]; me->hatchColour[1]=node->hatchColor.c[1]; me->hatchColour[2] = node->hatchColor.c[2];
617  me->hatchColour[3] = 1.0;
618 }
619 
620 
621 void render_LineProperties (struct X3D_LineProperties *node) {
622  #ifdef NEED_TO_ADD_TO_SHADER
623  much of this was working in older versions of FreeWRL,
624  before we went to 100% shader based code. Check FreeWRL
625  from (say) 2011 to see what the shader code looked like
626 
627  GLushort pat;
628  #endif
629 
630  if (node->applied) {
631  //ppComponent_Shape p = (ppComponent_Shape)gglobal()->Component_Shape.prv;
632 
633  if (node->linewidthScaleFactor > 1.0) {
634  struct matpropstruct *me;
635  glLineWidth(node->linewidthScaleFactor);
636  me= getAppearanceProperties();
637  me->pointSize = node->linewidthScaleFactor;
638  }
639 
640 
641  #ifdef NEED_TO_ADD_TO_SHADER
642  if (node->linetype > 1) {
643  pat = 0xffff; /* can not support fancy line types - this is the default */
644  switch (node->linetype) {
645  case 2: pat = 0xff00; break; /* dashed */
646  case 3: pat = 0x4040; break; /* dotted */
647  case 4: pat = 0x04ff; break; /* dash dot */
648  case 5: pat = 0x44fe; break; /* dash dot dot */
649  case 6: pat = 0x0100; break; /* optional */
650  case 7: pat = 0x0100; break; /* optional */
651  case 10: pat = 0xaaaa; break; /* optional */
652  case 11: pat = 0x0170; break; /* optional */
653  case 12: pat = 0x0000; break; /* optional */
654  case 13: pat = 0x0000; break; /* optional */
655  default: {}
656  }
657  }
658  #endif
659  }
660 }
661 
662 textureTableIndexStruct_s *getTableTableFromTextureNode(struct X3D_Node *textureNode);
663 
664 int getImageChannelCountFromTTI(struct X3D_Node *appearanceNode ){
665  //int channels, imgalpha, isLit, isUnlitGeometry, hasColorNode, whichShapeColorShader;
666  int channels, imgalpha, haveTexture;
667  struct X3D_Appearance *appearance;
668  channels = 0;
669  imgalpha = 0;
670  haveTexture = 0;
671  POSSIBLE_PROTO_EXPANSION(struct X3D_Appearance*,appearanceNode,appearance);
672 
673  if(appearance){
674  //do I need possible proto expansione of texture, or will compile_appearance have done that?
675  if(appearance->texture){
676  //mutli-texture? should loop over multitexture->texture nodes?
677  // --to get to get max channels or hasAlpha, or need channels for each one?
678  // H0: if nay of the multitextures has an alpha, then its alpha replaces material alpha
679  // H1: multitexture alpha is only for composing textures, assumed to take material alpha
680  if(appearance->texture->_nodeType == NODE_MultiTexture ||
681  appearance->texture->_nodeType == NODE_ComposedTexture3D ){
682  int k;
683  struct Multi_Node * mtex = NULL;
684  switch(appearance->texture->_nodeType){
685  case NODE_MultiTexture: mtex = &((struct X3D_MultiTexture*)appearance->texture)->texture; break;
686  case NODE_ComposedTexture3D: mtex = &((struct X3D_ComposedTexture3D*)appearance->texture)->texture; break;
687  }
688  channels = 0;
689  imgalpha = 0;
690  if(mtex)
691  for(k=0;k<mtex->n;k++){
692  textureTableIndexStruct_s *tti = getTableTableFromTextureNode(mtex->p[k]);
693  haveTexture = 1;
694  if(tti){
695  //new Aug 6, 2016, check LoadTextures.c for your platform channel counting
696  //NoImage=0, Luminance=1, LuminanceAlpha=2, RGB=3, RGBA=4
697  //PROBLEM: if tti isn't loaded -with #channels, alpha set-, we don't want to compile child
698  channels = max(channels,tti->channels);
699  imgalpha = max(tti->hasAlpha,imgalpha);
700  //if(tti->status < TEX_NEEDSBINDING)
701  // printf("."); //should Unmark node compiled
702  }
703  }
704  }else if(appearance->texture->_nodeType == NODE_ComposedCubeMapTexture){
705  int k;
706  struct X3D_Node* p[6];
707  struct X3D_ComposedCubeMapTexture * ccmt;
708  ccmt = (struct X3D_ComposedCubeMapTexture *)appearance->texture;
709  p[0] = ccmt->top;
710  p[1] = ccmt->left;
711  p[2] = ccmt->front;
712  p[3] = ccmt->right;
713  p[4] = ccmt->back;
714  p[5] = ccmt->bottom;
715  for(k=0;k<6;k++){
716  if(p[k]){
717  textureTableIndexStruct_s *tti = getTableTableFromTextureNode(p[k]);
718  haveTexture = 1;
719  if(tti){
720  //new Aug 6, 2016, check LoadTextures.c for your platform channel counting
721  //NoImage=0, Luminance=1, LuminanceAlpha=2, RGB=3, RGBA=4
722  //PROBLEM: if tti isn't loaded -with #channels, alpha set-, we don't want to compile child
723  channels = max(channels,tti->channels);
724  imgalpha = max(tti->hasAlpha,imgalpha);
725  }
726  }
727  }
728  }else{
729  //single texture:
730  textureTableIndexStruct_s *tti = getTableTableFromTextureNode(appearance->texture);
731  haveTexture = 1;
732  if(tti){
733  //new Aug 6, 2016, check LoadTextures.c for your platform channel counting
734  //NoImage=0, Luminance=1, LuminanceAlpha=2, RGB=3, RGBA=4
735  //PROBLEM: if tti isn't loaded -with #channels, alpha set-, we don't want to compile child
736  channels = tti->channels;
737  imgalpha = tti->hasAlpha;
738  //if(tti->status < TEX_NEEDSBINDING)
739  // printf("."); //should Unmark node compiled
740  }
741  }
742  }
743  }
744  channels = haveTexture ? channels : 0; //-1;
745  return channels;
746 }
747 
748 
749 //unsigned int getShaderFlags();
750 shaderflagsstruct getShaderFlags();
751 struct X3D_Node *getFogParams();
752 void update_effect_uniforms();
753 bool setupShaderB();
754 void textureTransform_start();
755 void reallyDraw();
756 
757 void child_Shape (struct X3D_Shape *node) {
758  struct X3D_Node *tmpNG;
759  //int channels;
761  ttglobal tg = gglobal();
762  struct fw_MaterialParameters defaultMaterials = {
763  {0.0f, 0.0f, 0.0f, 1.0f}, /* Emission */
764  {0.0f, 0.0f, 0.0f, 1.0f}, /* Ambient */
765  {0.8f, 0.8f, 0.8f, 1.0f}, /* Diffuse */
766  {0.0f, 0.0f, 0.0f, 1.0f}, /* Specular */
767  10.0f}; /* Shininess */
768 
769  COMPILE_IF_REQUIRED
770 
771  /* JAS - if not collision, and render_geom is not set, no need to go further */
772  /* printf ("child_Shape vp %d geom %d light %d sens %d blend %d prox %d col %d\n",
773  render_vp,render_geom,render_light,render_sensitive,render_blend,render_proximity,render_collision); */
774 
775  if(!(node->geometry)) { return; }
776 
777  RECORD_DISTANCE
778 
779  if((renderstate()->render_collision) || (renderstate()->render_sensitive)) {
780  /* only need to forward the call to the child */
781  POSSIBLE_PROTO_EXPANSION(struct X3D_Node *,node->geometry,tmpNG);
782  render_node(tmpNG);
783  return;
784  }
785  p = (ppComponent_Shape)tg->Component_Shape.prv;
786 
787  /* initialization. This will get overwritten if there is a texture in an Appearance
788  node in this shape (see child_Appearance) */
789  tg->RenderFuncs.last_texture_type = NOTEXTURE;
790  tg->RenderFuncs.shapenode = node;
791 
792  /* copy the material stuff in preparation for copying all to the shader */
793  memcpy (&p->appearanceProperties.fw_FrontMaterial, &defaultMaterials, sizeof (struct fw_MaterialParameters));
794  memcpy (&p->appearanceProperties.fw_BackMaterial, &defaultMaterials, sizeof (struct fw_MaterialParameters));
795 
796  if((renderstate()->render_cube) && hasGeneratedCubeMapTexture((struct X3D_Appearance*)node->appearance))
797  return; //don't draw if this node uses a generatedcubemaptexture and its a cubemaptexture generation pass; is there more optimal place to do this?
798 
799  /* now, are we rendering blended nodes or normal nodes?*/
800  if (renderstate()->render_blend == (node->_renderFlags & VF_Blend)) {
801  int isUserShader; //colorSource, isLit, alphaSource,
803  //unsigned int shader_requirements;
804  shaderflagsstruct shader_requirements;
805  memset(&shader_requirements,0,sizeof(shaderflagsstruct));
806 
807  //prep_Appearance
808  RENDER_MATERIAL_SUBNODES(node->appearance); //child_Appearance
809 
810 
811 
812  if (p->material_oneSided != NULL) {
813  memcpy (&p->appearanceProperties.fw_FrontMaterial, p->material_oneSided->_verifiedColor.p, sizeof (struct fw_MaterialParameters));
814  memcpy (&p->appearanceProperties.fw_BackMaterial, p->material_oneSided->_verifiedColor.p, sizeof (struct fw_MaterialParameters));
815  /* copy the emissive colour over for lines and points */
816  memcpy(p->appearanceProperties.emissionColour,p->material_oneSided->_verifiedColor.p, 3*sizeof(float));
817 
818  } else if (p->material_twoSided != NULL) {
819  memcpy (&p->appearanceProperties.fw_FrontMaterial, p->material_twoSided->_verifiedFrontColor.p, sizeof (struct fw_MaterialParameters));
820  memcpy (&p->appearanceProperties.fw_BackMaterial, p->material_twoSided->_verifiedBackColor.p, sizeof (struct fw_MaterialParameters));
821  /* copy the emissive colour over for lines and points */
822  memcpy(p->appearanceProperties.emissionColour,p->material_twoSided->_verifiedFrontColor.p, 3*sizeof(float));
823  } else {
824  /* no materials selected.... */
825  }
826 
827  /* enable the shader for this shape */
828  //ConsoleMessage("turning shader on %x",node->_shaderTableEntry);
829 
830  POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, node->geometry,tmpNG);
831 
832  shader_requirements.base = node->_shaderflags_base; //_shaderTableEntry;
833  shader_requirements.effects = node->_shaderflags_effects;
834  shader_requirements.usershaders = node->_shaderflags_usershaders;
835  isUserShader = shader_requirements.usershaders ? TRUE : FALSE; // >= USER_DEFINED_SHADER_START ? TRUE : FALSE;
836  //if(!p->userShaderNode || !(shader_requirements >= USER_DEFINED_SHADER_START)){
837  if(!isUserShader){
838  //for Luminance and Luminance-Alpha images, we have to tinker a bit in the Vertex shader
839  // New concept of operations Aug 26, 2016
840  // in the specs there are some things that can replace other things (but not the reverse)
841  // Texture can repace CPV, diffuse and 111
842  // CPV can replace diffuse and 111
843  // diffuse can replace 111
844  // Texture > CPV > Diffuse > (1,1,1)
845  // so there's a kind of order / sequence to it.
846  // There can be a flag at each step saying if you want to replace the prior value (otherwise modulate)
847  // Diffuse replacing or modulating (111) is the same thing, no flag needed
848  // Therefore we need at most 2 flags for color:
849  // TEXTURE_REPLACE_PRIOR and CPV_REPLACE_PRIOR.
850  // and other flag for alpha: ALPHA_REPLACE_PRIOR (same as ! WANT_TEXALPHA)
851  // if all those are false, then its full modulation.
852  // our WANT_LUMINANCE is really == ! TEXTURE_REPLACE_PRIOR
853  // we are missing a CPV_REPLACE_PRIOR, or more precisely this is a default burned into the shader
854 
855  int channels;
856  //modulation:
857  //- for Castle-style full-modulation of texture x CPV x mat.diffuse
858  // and texalpha x (1-mat.trans), set 2
859  //- for specs table 17-2 RGB Tex replaces CPV with modulation
860  // of table 17-2 entries with mat.diffuse and (1-mat.trans) set 1
861  //- for specs table 17-3 as written and ignoring modulation sentences
862  // so CPV replaces diffuse, texture replaces CPV and diffuse- set 0
863  // testing: KelpForest SharkLefty.x3d has CPV, ImageTexture RGB, and mat.diffuse
864  // 29C.wrl has mat.transparency=1 and LumAlpha image, modulate=0 shows sphere, 1,2 inivisble
865  // test all combinations of: modulation {0,1,2} x shadingStyle {gouraud,phong}: 0 looks bright texture only, 1 texture and diffuse, 2 T X C X D
866  int modulation = 1; //freewrl default 1 (dug9 Aug 27, 2016 interpretation of Lighting specs)
867  channels = getImageChannelCountFromTTI(node->appearance);
868 
869  if(modulation == 0)
870  shader_requirements.base |= MAT_FIRST; //strict use of table 17-3, CPV can replace mat.diffuse, so texture > cpv > diffuse > 111
871 
872  if(shader_requirements.base & COLOUR_MATERIAL_SHADER){
873  //printf("has a color node\n");
874  //lets turn it off, and see if we get texture
875  //shader_requirements &= ~(COLOUR_MATERIAL_SHADER);
876  if(modulation == 0)
877  shader_requirements.base |= CPV_REPLACE_PRIOR;
878  }
879 
880  if(channels && (channels == 3 || channels == 4) && modulation < 2)
881  shader_requirements.base |= TEXTURE_REPLACE_PRIOR;
882  //if the image has a real alpha, we may want to turn off alpha modulation,
883  // see comment about modulate in Compositing_Shaders.c
884  if(channels && (channels == 2 || channels == 4) && modulation == 0)
885  shader_requirements.base |= TEXALPHA_REPLACE_PRIOR;
886 
887  //getShaderFlags() are from non-leaf-node shader influencers:
888  // fog, local_lights, clipplane, Effect/EffectPart (for CastlePlugs) ...
889  // - as such they may be different for the same shape node DEF/USEd in different branches of the scenegraph
890  // - so they are ORd here before selecting a shader permutation
891  shader_requirements.base |= getShaderFlags().base;
892  shader_requirements.effects |= getShaderFlags().effects;
893  //if(shader_requirements & FOG_APPEARANCE_SHADER)
894  // printf("fog in child_shape\n");
895  }
896  //printf("child_shape shader_requirements base %d effects %d user %d\n",shader_requirements.base,shader_requirements.effects,shader_requirements.usershaders);
897  scap = getMyShaders(shader_requirements);
898  enableGlobalShader(scap);
899  //enableGlobalShader (getMyShader(shader_requirements)); //node->_shaderTableEntry));
900 
901  //see if we have to set up a TextureCoordinateGenerator type here
902  if (tmpNG && tmpNG->_intern) {
903  if (tmpNG->_intern->tcoordtype == NODE_TextureCoordinateGenerator) {
904  getAppearanceProperties()->texCoordGeneratorType = tmpNG->_intern->texgentype;
905  //ConsoleMessage("shape, matprop val %d, geom val %d",getAppearanceProperties()->texCoordGeneratorType, node->geometry->_intern->texgentype);
906  }
907  }
908  //userDefined = (whichOne >= USER_DEFINED_SHADER_START) ? TRUE : FALSE;
909  //if (p->userShaderNode != NULL && shader_requirements >= USER_DEFINED_SHADER_START) {
910  if(isUserShader && p->userShaderNode){
911  //we come in here right after a COMPILE pass in APPEARANCE which renders the shader, which sets p->userShaderNode
912  //if nothing changed with appearance -no compile pass- we don't come in here again
913  //ConsoleMessage ("have a shader of type %s",stringNodeType(p->userShaderNode->_nodeType));
914  switch (p->userShaderNode->_nodeType) {
915  case NODE_ComposedShader:
916  if (X3D_COMPOSEDSHADER(p->userShaderNode)->isValid) {
917  if (!X3D_COMPOSEDSHADER(p->userShaderNode)->_initialized) {
918  sendInitialFieldsToShader(p->userShaderNode);
919  }
920  }
921  break;
922  case NODE_ProgramShader:
923  if (X3D_PROGRAMSHADER(p->userShaderNode)->isValid) {
924  if (!X3D_PROGRAMSHADER(p->userShaderNode)->_initialized) {
925  sendInitialFieldsToShader(p->userShaderNode);
926  }
927  }
928 
929  break;
930  case NODE_PackagedShader:
931  if (X3D_PACKAGEDSHADER(p->userShaderNode)->isValid) {
932  if (!X3D_PACKAGEDSHADER(p->userShaderNode)->_initialized) {
933  sendInitialFieldsToShader(p->userShaderNode);
934  }
935  }
936 
937  break;
938  }
939  }
940  //update effect field uniforms
941  if(shader_requirements.effects){
942  update_effect_uniforms();
943  }
944 
945 
946  #ifdef SHAPEOCCLUSION
947  beginOcclusionQuery((struct X3D_VisibilitySensor*)node,renderstate()->render_geom); //BEGINOCCLUSIONQUERY;
948  #endif
949  //call stack to get from child_shape to sendMaterialsToShader and sendLightInfo as of Aug 13, 2016
950  //child_shape
951  //- render_node
952  //-- render_indexedfaceset (or other specific shape)
953  //--- render_polyrep
954  //---- sendArraysToGPU (or sendElementsToGPU)
955  //----- setupShader
956  //------ sendMaterialsToShader
957  // Uniforms being sent for materials and hatching
958  //--------- sendLightInfo
959  // Uniforms sent for lights
960  //----- glDrawArrays/glDrawElements
961  textureTransform_start();
962  setupShaderB();
963  render_node(tmpNG);
964  reallyDraw();
965  FW_GL_BINDBUFFER(GL_ARRAY_BUFFER, 0);
966  FW_GL_BINDBUFFER(GL_ELEMENT_ARRAY_BUFFER, 0);
967  textureTransform_end();
968 
969  #ifdef SHAPEOCCLUSION
970  endOcclusionQuery((struct X3D_VisibilitySensor*)node,renderstate()->render_geom); //ENDOCCLUSIONQUERY;
971  #endif
972 
973  //fin_Appearance
974  if(node->appearance){
975  struct X3D_Appearance *tmpA;
976  POSSIBLE_PROTO_EXPANSION(struct X3D_Appearance *,node->appearance,tmpA);
977  if(tmpA->effects.n)
978  fin_sibAffectors(X3D_NODE(tmpA),&tmpA->effects);
979  }
980 
981  }
982 
983  /* any shader turned on? if so, turn it off */
984 
985  //ConsoleMessage("turning shader off");
986  finishedWithGlobalShader();
987  p->material_twoSided = NULL;
988  p->material_oneSided = NULL;
989  p->userShaderNode = NULL;
990  tg->RenderFuncs.shapenode = NULL;
991 
992  /* load the identity matrix for textures. This is necessary, as some nodes have TextureTransforms
993  and some don't. So, if we have a TextureTransform, loadIdentity */
994 
995  if (p->this_textureTransform) {
996  p->this_textureTransform = NULL;
997  FW_GL_MATRIX_MODE(GL_TEXTURE);
998  FW_GL_LOAD_IDENTITY();
999  FW_GL_MATRIX_MODE(GL_MODELVIEW);
1000  }
1001 
1002  /* LineSet, PointSets, set the width back to the original. */
1003  {
1004  float gl_linewidth = tg->Mainloop.gl_linewidth;
1005  glLineWidth(gl_linewidth);
1006  p->appearanceProperties.pointSize = gl_linewidth;
1007  }
1008 
1009  /* did the lack of an Appearance or Material node turn lighting off? */
1010  LIGHTING_ON;
1011 
1012  /* turn off face culling */
1013  DISABLE_CULL_FACE;
1014 }
1015 
1016 void compile_Shape (struct X3D_Shape *node) {
1017  int whichAppearanceShader = 0;
1018  int whichShapeColorShader = 0;
1019  int whichShapeFogShader = 0;
1020  bool isUnlitGeometry = false;
1021  int hasTextureCoordinateGenerator = 0;
1022  int whichUnlitGeometry = 0;
1023  struct X3D_Node *tmpN = NULL;
1024  struct X3D_Node *tmpG = NULL;
1025  // struct X3D_Appearance *appearance = NULL;
1026  int userDefinedShader = 0;
1027 // int colorSource, alphaSource, channels, isLit;
1028 
1029 
1030  // ConsoleMessage ("**** Compile Shape ****");
1031 
1032 
1033  POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, node->geometry,tmpG);
1034  whichShapeColorShader = getShapeColourShader(tmpG);
1035  whichShapeFogShader = getShapeFogShader(tmpG);
1036 
1037  isUnlitGeometry = getIfLinePoints(tmpG);
1038  hasTextureCoordinateGenerator = getShapeTextureCoordGen(tmpG);
1039 
1040  POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, node->appearance,tmpN);
1041 
1042 
1043  /* first - does appearance have a shader node? */
1044  userDefinedShader = hasUserDefinedShader(tmpN);
1045 
1046  //Aug 26 2016 change: don't fiddle around with flags here, rather report the state of the node
1047  // - then do any fiddling in child_shape, when we have the channel count and modulation flag
1048  if(isUnlitGeometry)
1049  whichUnlitGeometry = HAVE_LINEPOINTS_COLOR;
1050  whichAppearanceShader = getAppearanceShader(tmpN);
1051 
1052  /* in case we had no appearance, etc, we do the bland NO_APPEARANCE_SHADER */
1053  //node->_shaderTableEntry=
1054  node->_shaderflags_base = (whichShapeColorShader | whichShapeFogShader | whichAppearanceShader |
1055  hasTextureCoordinateGenerator | whichUnlitGeometry ); //| userDefinedShader);
1056  node->_shaderflags_usershaders = userDefinedShader;
1057  node->_shaderflags_effects = 0;
1058 
1059 
1060  //if (node->_shaderTableEntry == NOTHING)
1061  // node->_shaderTableEntry = NO_APPEARANCE_SHADER;
1062 
1063  if (node->_shaderflags_base == NOTHING)
1064  node->_shaderflags_base = NO_APPEARANCE_SHADER;
1065 
1066 
1067  //printf ("compile_Shape, node->_shaderTableEntry is %x\n",node->_shaderTableEntry);
1068 
1069  MARK_NODE_COMPILED
1070 }
1071 
1072 
1073 void compile_TwoSidedMaterial (struct X3D_TwoSidedMaterial *node) {
1074  int i;
1075  float trans;
1076 
1077  /* verify that the numbers are within range */
1078  if (node->ambientIntensity < 0.0) node->ambientIntensity=0.0f;
1079  if (node->ambientIntensity > 1.0) node->ambientIntensity=1.0f;
1080  if (node->shininess < 0.0) node->shininess=0.0f;
1081  if (node->shininess > 1.0) node->shininess=1.0f;
1082  if (node->transparency < 0.0) node->transparency=MIN_NODE_TRANSPARENCY;
1083  if (node->transparency >= 1.0) node->transparency=MAX_NODE_TRANSPARENCY;
1084 
1085  if (node->backAmbientIntensity < 0.0) node->backAmbientIntensity=0.0f;
1086  if (node->backAmbientIntensity > 1.0) node->backAmbientIntensity=1.0f;
1087  if (node->backShininess < 0.0) node->backShininess=0.0f;
1088  if (node->backShininess > 1.0) node->backShininess=1.0f;
1089  if (node->backTransparency < 0.0) node->backTransparency=0.0f;
1090  if (node->backTransparency > 1.0) node->backTransparency=1.0f;
1091 
1092  for (i=0; i<3; i++) {
1093  if (node->diffuseColor.c[i] < 0.0) node->diffuseColor.c[i]=0.0f;
1094  if (node->diffuseColor.c[i] > 1.0) node->diffuseColor.c[i]=1.0f;
1095  if (node->emissiveColor.c[i] < 0.0) node->emissiveColor.c[i]=0.0f;
1096  if (node->emissiveColor.c[i] > 1.0) node->emissiveColor.c[i]=1.0f;
1097  if (node->specularColor.c[i] < 0.0) node->specularColor.c[i]=0.0f;
1098  if (node->specularColor.c[i] > 1.0) node->specularColor.c[i]=1.0f;
1099 
1100  if (node->backDiffuseColor.c[i] < 0.0) node->backDiffuseColor.c[i]=0.0f;
1101  if (node->backDiffuseColor.c[i] > 1.0) node->backDiffuseColor.c[i]=1.0f;
1102  if (node->backEmissiveColor.c[i] < 0.0) node->backEmissiveColor.c[i]=0.0f;
1103  if (node->backEmissiveColor.c[i] > 1.0) node->backEmissiveColor.c[i]=1.0f;
1104  if (node->backSpecularColor.c[i] < 0.0) node->backSpecularColor.c[i]=0.0f;
1105  if (node->backSpecularColor.c[i] > 1.0) node->backSpecularColor.c[i]=1.0f;
1106  }
1107 
1108  /* first, put in the transparency */
1109  trans = 1.0f - node->transparency;
1110  node->_verifiedFrontColor.p[3] = trans;
1111  node->_verifiedFrontColor.p[7] = trans;
1112  node->_verifiedFrontColor.p[11] = trans;
1113  node->_verifiedFrontColor.p[15] = trans;
1114  trans = 1.0f - node->backTransparency;
1115  node->_verifiedBackColor.p[3] = trans;
1116  node->_verifiedBackColor.p[7] = trans;
1117  node->_verifiedBackColor.p[11] = trans;
1118  node->_verifiedBackColor.p[15] = trans;
1119 
1120 
1121  /* DiffuseColor */
1122  memcpy((void *)(&node->_verifiedFrontColor.p[8]), node->diffuseColor.c, sizeof (float) * 3);
1123 
1124  /* Ambient - diffuseFrontColor * ambientIntensity */
1125  for(i=0; i<4; i++) { node->_verifiedFrontColor.p[i+4] = node->_verifiedFrontColor.p[i+8] * node->ambientIntensity; }
1126 
1127  /* Specular */
1128  memcpy((void *)(&node->_verifiedFrontColor.p[12]), node->specularColor.c, sizeof (float) * 3);
1129 
1130  /* Emissive */
1131  memcpy((void *)(&node->_verifiedFrontColor.p[0]), node->emissiveColor.c, sizeof (float) * 3);
1132 
1133  /* Shininess */
1134  node->_verifiedFrontColor.p[16] = node->shininess * 128.0f;
1135 
1136 #define MAX_SHIN 128.0f
1137 #define MIN_SHIN 0.01f
1138  if ((node->_verifiedFrontColor.p[16] > MAX_SHIN) || (node->_verifiedFrontColor.p[16] < MIN_SHIN)) {
1139  if (node->_verifiedFrontColor.p[16]>MAX_SHIN){node->_verifiedFrontColor.p[16] = MAX_SHIN;}else{node->_verifiedFrontColor.p[16]=MIN_SHIN;}
1140  }
1141 #undef MAX_SHIN
1142 #undef MIN_SHIN
1143 
1144  if (node->separateBackColor) {
1145 
1146  /* DiffuseColor */
1147  memcpy((void *)(&node->_verifiedBackColor.p[8]), node->backDiffuseColor.c, sizeof (float) * 3);
1148 
1149  /* Ambient - diffuseBackColor * ambientIntensity */
1150  for(i=0; i<3; i++) { node->_verifiedBackColor.p[i+4] = node->_verifiedBackColor.p[i+8] * node->ambientIntensity; }
1151 
1152  /* Specular */
1153  memcpy((void *)(&node->_verifiedBackColor.p[12]), node->backSpecularColor.c, sizeof (float) * 3);
1154 
1155  /* Emissive */
1156  memcpy((void *)(&node->_verifiedBackColor.p[0]), node->backEmissiveColor.c, sizeof (float) * 3);
1157 
1158  /* Shininess */
1159  node->_verifiedBackColor.p[16] = node->shininess * 128.0f;
1160 
1161 #define MAX_SHIN 128.0f
1162 #define MIN_SHIN 0.01f
1163  if ((node->_verifiedBackColor.p[16] > MAX_SHIN) || (node->_verifiedBackColor.p[16] < MIN_SHIN)) {
1164  if (node->_verifiedBackColor.p[16]>MAX_SHIN){node->_verifiedBackColor.p[16] = MAX_SHIN;}else{node->_verifiedBackColor.p[16]=MIN_SHIN;}
1165  }
1166 #undef MAX_SHIN
1167 #undef MIN_SHIN
1168 
1169  } else {
1170  /* just copy the front materials to the back */
1171  memcpy(node->_verifiedBackColor.p, node->_verifiedFrontColor.p, sizeof (float) * 17);
1172  }
1173 
1174 
1175  MARK_NODE_COMPILED
1176 }
1177 
1178 void render_TwoSidedMaterial (struct X3D_TwoSidedMaterial *node) {
1179 
1180  COMPILE_IF_REQUIRED
1181  {
1182  ppComponent_Shape p = (ppComponent_Shape)gglobal()->Component_Shape.prv;
1183 
1184  /* record this node for OpenGL-ES and OpenGL-3.1 operation */
1185  p->material_twoSided = node;
1186  }
1187 }
1188