FreeWRL/FreeX3D  3.0.0
RenderTextures.c
1 /*
2 
3 
4 Texturing during Runtime
5 texture enabling - works for single texture, for multitexture.
6 
7 */
8 
9 
10 /****************************************************************************
11  This file is part of the FreeWRL/FreeX3D Distribution.
12 
13  Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
14 
15  FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
16  it under the terms of the GNU Lesser Public License as published by
17  the Free Software Foundation, either version 3 of the License, or
18  (at your option) any later version.
19 
20  FreeWRL/FreeX3D is distributed in the hope that it will be useful,
21  but WITHOUT ANY WARRANTY; without even the implied warranty of
22  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23  GNU General Public License for more details.
24 
25  You should have received a copy of the GNU General Public License
26  along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
27 ****************************************************************************/
28 
29 
30 
31 #include <config.h>
32 #include <system.h>
33 #include <display.h>
34 #include <internal.h>
35 
36 #include <libFreeWRL.h>
37 
38 #include "../vrml_parser/Structs.h"
39 #include "../main/headers.h"
40 #include "../opengl/OpenGL_Utils.h"
41 #include "../scenegraph/Component_Shape.h"
42 #include "../scenegraph/RenderFuncs.h"
43 #include "../scenegraph/LinearAlgebra.h"
44 
45 #include "Textures.h"
46 #include "Material.h"
47 
48 
50 int multitex_mode[2];
51 int multitex_source[2];
52 int multitex_function;
53 };
54 
55 typedef struct pRenderTextures{
56  struct multiTexParams textureParameterStack[MAX_MULTITEXTURE];
58 
59 void *RenderTextures_constructor(){
60  void *v = MALLOCV(sizeof(struct pRenderTextures));
61  memset(v,0,sizeof(struct pRenderTextures));
62  return v;
63 }
64 void RenderTextures_init(struct tRenderTextures *t){
65  t->prv = RenderTextures_constructor();
66  {
68  /* variables for keeping track of status */
69  t->textureParameterStack = (void *)p->textureParameterStack;
70  }
71 }
72 
73 
74 /* function params */
75 //static void passedInGenTex(struct textureVertexInfo *genTex);
76 
77 /* which texture unit are we going to use? is this texture not OFF?? Should we set the
78  background coloUr??? Larry the Cucumber, help! */
79 
80 static int setActiveTexture (int c, GLfloat thisTransparency, GLint *texUnit, GLint *texMode)
81 {
83  ttglobal tg = gglobal();
84  p = (ppRenderTextures)tg->RenderTextures.prv;
85 
86  /* which texture unit are we working on? */
87 
88  /* tie each fw_TextureX uniform into the correct texture unit */
89 
90  /* here we assign the texture unit to a specific number. NOTE: in the current code, this will ALWAYS
91  * be [0] = 0, [1] = 1; etc. */
92  texUnit[c] = c;
93 
94 #ifdef TEXVERBOSE
95  if (getAppearanceProperties()->currentShaderProperties != NULL) {
96  printf ("setActiveTexture %d, boundTextureStack is %d, sending to uniform %d\n",c,
97  tg->RenderFuncs.boundTextureStack[c],
98  getAppearanceProperties()->currentShaderProperties->TextureUnit[c]);
99  } else {
100  printf ("setActiveTexture %d, boundTextureStack is %d, sending to uniform [NULL--No Shader]\n",c,
101  tg->RenderFuncs.boundTextureStack[c]);
102  }
103 #endif
104 
105  /* is this a MultiTexture, or just a "normal" single texture? When we
106  * bind_image, we store a pointer for the texture parameters. It is
107  * NULL, possibly different for MultiTextures */
108 
109  if (p->textureParameterStack[c].multitex_mode[0] == INT_ID_UNDEFINED) {
110 
111  #ifdef TEXVERBOSE
112  printf ("setActiveTexture - simple texture NOT a MultiTexture \n");
113  #endif
114 
115  /* should we set the coloUr to 1,1,1,1 so that the material does not show
116  * through a RGB texture?? */
117  /* only do for the first texture if MultiTexturing */
118  if (c == 0) {
119  #ifdef TEXVERBOSE
120  printf ("setActiveTexture - firsttexture \n");
121  #endif
122  texMode[c]= GL_MODULATE;
123  } else {
124  texMode[c]=GL_ADD;
125  }
126 
127  } else {
128  /* printf ("muititex source for %d is %d\n",c,tg->RenderTextures.textureParameterStack[c].multitex_source); */
129  if (p->textureParameterStack[c].multitex_source[0] != MTMODE_OFF) {
130  } else {
131  //glDisable(GL_TEXTURE_2D); /* DISABLE_TEXTURES */
132  //return FALSE;
133  // we do OFF right in the shader
134  }
135  }
136 
137 
138  PRINT_GL_ERROR_IF_ANY("");
139 
140  return TRUE;
141 }
142 
143 
144 /* lets disable texture transforms here */
145 void textureTransform_end(void) {
146  int j;
147  ttglobal tg = gglobal();
148 
149 #ifdef TEXVERBOSE
150  printf ("start of textureDraw_end\n");
151 #endif
152 
153  /* DISABLE_TEXTURES */
154  /* setting this ENSURES that items, like the HUD, that are not within the normal
155  rendering path do not try and use textures... */
156  FW_GL_MATRIX_MODE(GL_TEXTURE);
157  for(j=0;j<tg->RenderFuncs.textureStackTop;j++)
158  FW_GL_POP_MATRIX(); //pushed in passedInGenTex
159 
160  tg->RenderFuncs.textureStackTop = 0;
161  tg->RenderFuncs.texturenode = NULL;
162  FW_GL_MATRIX_MODE(GL_MODELVIEW);
163 }
164 
165 /* did we have a TextureTransform in the Appearance node? */
166 void do_textureTransform (struct X3D_Node *textureNode, int ttnum) {
167 
168  /* is this a simple TextureTransform? */
169  if (textureNode->_nodeType == NODE_TextureTransform) {
170  //ConsoleMessage ("do_textureTransform, node is indeed a NODE_TextureTransform");
171  struct X3D_TextureTransform *ttt = (struct X3D_TextureTransform *) textureNode;
172  /* Render transformations according to spec.*/
173  //http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/texturing.html#TextureTransform
174  //specs say 'translate, rotate, then scale'
175  FW_GL_TRANSLATE_F(-((ttt->center).c[0]),-((ttt->center).c[1]), 0); /* 5*/
176  FW_GL_SCALE_F(((ttt->scale).c[0]),((ttt->scale).c[1]),1); /* 4*/
177  FW_GL_ROTATE_RADIANS(ttt->rotation,0,0,1); /* 3*/
178  FW_GL_TRANSLATE_F(((ttt->center).c[0]),((ttt->center).c[1]), 0); /* 2*/
179  FW_GL_TRANSLATE_F(((ttt->translation).c[0]), ((ttt->translation).c[1]), 0); /* 1*/
180  /* is this a MultiTextureTransform? */
181  } else if (textureNode->_nodeType == NODE_MultiTextureTransform) {
182  struct X3D_MultiTextureTransform *mtt = (struct X3D_MultiTextureTransform *) textureNode;
183  if (ttnum < mtt->textureTransform.n) {
184  struct X3D_TextureTransform *ttt = (struct X3D_TextureTransform *) mtt->textureTransform.p[ttnum];
185  /* is this a simple TextureTransform? */
186  if (ttt->_nodeType == NODE_TextureTransform) {
187  /* Render transformations according to spec.*/
188  FW_GL_TRANSLATE_F(-((ttt->center).c[0]),-((ttt->center).c[1]), 0); /* 5*/
189  FW_GL_SCALE_F(((ttt->scale).c[0]),((ttt->scale).c[1]),1); /* 4*/
190  FW_GL_ROTATE_RADIANS(ttt->rotation,0,0,1); /* 3*/
191  FW_GL_TRANSLATE_F(((ttt->center).c[0]),((ttt->center).c[1]), 0); /* 2*/
192  FW_GL_TRANSLATE_F(((ttt->translation).c[0]), ((ttt->translation).c[1]), 0); /* 1*/
193  } else {
194  static int once = 0;
195  if(!once){
196  printf ("MultiTextureTransform expected a textureTransform for texture %d, got %d \n",
197  ttnum, ttt->_nodeType);
198  once = 1;
199  }
200  }
201  } else {
202  static int once = 0;
203  if(!once){
204  printf ("not enough transforms in MultiTextureTransform -will fill with Identity matrix\n");
205  once = 1;
206  }
207  }
208  } else if (textureNode->_nodeType == NODE_TextureTransform3D) {
209  //ConsoleMessage ("do_textureTransform, node is indeed a NODE_TextureTransform");
210  struct X3D_TextureTransform3D *ttt = (struct X3D_TextureTransform3D *) textureNode;
211  /* Render transformations according to spec.*/
212  FW_GL_TRANSLATE_F(-((ttt->center).c[0]),-((ttt->center).c[1]), -((ttt->center).c[2])); /* 5*/
213  FW_GL_SCALE_F(((ttt->scale).c[0]),((ttt->scale).c[1]),((ttt->scale).c[2])); /* 4*/
214  FW_GL_ROTATE_RADIANS(ttt->rotation.c[3], ttt->rotation.c[0],ttt->rotation.c[1],ttt->rotation.c[2]);
215  FW_GL_TRANSLATE_F(((ttt->center).c[0]),((ttt->center).c[1]), ((ttt->center).c[2])); /* 2*/
216  FW_GL_TRANSLATE_F(((ttt->translation).c[0]), ((ttt->translation).c[1]), ((ttt->translation).c[2])); /* 1*/
217  } else if (textureNode->_nodeType == NODE_TextureTransformMatrix3D) {
218  //ConsoleMessage ("do_textureTransform, node is indeed a NODE_TextureTransform");
219  int i;
220  double mat[16];
221  struct X3D_TextureTransformMatrix3D *ttt = (struct X3D_TextureTransformMatrix3D *) textureNode;
222  for(i=0;i<16;i++)
223  mat[i] = (double)ttt->matrix.c[i];
224  FW_GL_SETDOUBLEV(GL_TEXTURE_MATRIX,mat);
225  } else {
226  static int once = 0;
227  if(!once){
228  printf ("expected a textureTransform node, got %d\n",textureNode->_nodeType);
229  once = 1;
230  }
231  }
232 
233  //FW_GL_MATRIX_MODE(GL_MODELVIEW);
234 }
235 
236 /***********************************************************************************/
237 int isMultiTexture(struct X3D_Node *node){
238  int ret = FALSE;
239  if(node && node->_nodeType == NODE_MultiTexture)
240  ret = TRUE;
241  return ret;
242 }
243 textureTableIndexStruct_s *getTableTableFromTextureNode(struct X3D_Node *textureNode);
244 int isTex3D(struct X3D_Node *node);
245 
246 #ifdef OLDCODE
247 OLDCODE static void passedInGenTex_OLD(struct textureVertexInfo *genTex) {
248 OLDCODE int c;
249 OLDCODE int i, isStrict, isMulti, isIdentity;
250 OLDCODE GLint texUnit[MAX_MULTITEXTURE];
251 OLDCODE GLint texMode[MAX_MULTITEXTURE];
252 OLDCODE s_shader_capabilities_t *me;
253 OLDCODE struct textureVertexInfo *genTexPtr;
254 OLDCODE struct X3D_Node *tnode;
255 OLDCODE
256 OLDCODE ppRenderTextures p;
257 OLDCODE ttglobal tg = gglobal();
258 OLDCODE p = (ppRenderTextures)tg->RenderTextures.prv;
259 OLDCODE tnode = tg->RenderFuncs.texturenode;
260 OLDCODE
261 OLDCODE me = getAppearanceProperties()->currentShaderProperties;
262 OLDCODE
263 OLDCODE #ifdef TEXVERBOSE
264 OLDCODE printf ("passedInGenTex, using passed in genTex, textureStackTop %d\n",tg->RenderFuncs.textureStackTop);
265 OLDCODE printf ("passedInGenTex, cubeFace %d\n",getAppearanceProperties()->cubeFace);
266 OLDCODE #endif
267 OLDCODE
268 OLDCODE FW_GL_MATRIX_MODE(GL_TEXTURE);
269 OLDCODE
270 OLDCODE //printf ("passedInGenTex, B\n");
271 OLDCODE isStrict = 1; //web3d specs say if its a multitexture,
272 OLDCODE //and you give it a single textureTransform instead of multitexturetransform
273 OLDCODE //it should ignore the singleTextureTransform and use identities.
274 OLDCODE //strict: This is a change of functionality for freewrl Aug 31, 2016
275 OLDCODE genTexPtr = genTex;
276 OLDCODE isIdentity = TRUE;
277 OLDCODE for (c=0; c<tg->RenderFuncs.textureStackTop; c++) {
278 OLDCODE FW_GL_PUSH_MATRIX(); //POPPED in textureDraw_end
279 OLDCODE FW_GL_LOAD_IDENTITY();
280 OLDCODE //printf ("passedInGenTex, c=%d\n",c);
281 OLDCODE /* are we ok with this texture yet? */
282 OLDCODE if (tg->RenderFuncs.boundTextureStack[c]!=0) {
283 OLDCODE isMulti = isMultiTexture(tg->RenderFuncs.texturenode);
284 OLDCODE //printf ("passedInGenTex, C, boundTextureStack %d\n",tg->RenderFuncs.boundTextureStack[c]);
285 OLDCODE if (setActiveTexture(c,getAppearanceProperties()->transparency,texUnit,texMode)) {
286 OLDCODE //printf ("passedInGenTex, going to bind to texture %d\n",tg->RenderFuncs.boundTextureStack[c]);
287 OLDCODE GLuint texture;
288 OLDCODE struct X3D_Node *tt = getThis_textureTransform();
289 OLDCODE if (tt!=NULL) {
290 OLDCODE int match = FALSE;
291 OLDCODE match = isMulti && (tt->_nodeType == NODE_MultiTextureTransform);
292 OLDCODE match = match || (!isMulti && (tt->_nodeType != NODE_MultiTextureTransform));
293 OLDCODE if(isStrict){
294 OLDCODE if(match){
295 OLDCODE do_textureTransform(tt,c);
296 OLDCODE isIdentity = FALSE;
297 OLDCODE }
298 OLDCODE }else{
299 OLDCODE do_textureTransform(tt,c);
300 OLDCODE isIdentity = FALSE;
301 OLDCODE }
302 OLDCODE }
303 OLDCODE //TEXTURE 3D
304 OLDCODE if(isTex3D(tnode)){
305 OLDCODE textureTableIndexStruct_s *tti = getTableTableFromTextureNode(tnode);
306 OLDCODE if(tnode->_nodeType != NODE_ComposedTexture3D){
307 OLDCODE //pixelTexture3D, imageTexture3D (but not composedTexture3D which uses textureCount above)
308 OLDCODE if(me){
309 OLDCODE if(tti){
310 OLDCODE glUniform1iv(me->tex3dTiles,3,tti->tiles);
311 OLDCODE }
312 OLDCODE }
313 OLDCODE }
314 OLDCODE //all texture3d
315 OLDCODE if(tg->RenderFuncs.shapenode && isIdentity && genTexPtr->TC_size < 3){
316 OLDCODE //_if_ no TextureTransform3D was explicitly specified for Texture3D,
317 OLDCODE //_and_ no textureCoordinate3D or textureCoordinate4D was explicilty specified with the goem node
318 OLDCODE //_then_ bounding box of shape, in local coordinates, is used to scale/translate
319 OLDCODE //geometry vertices into 0-1 range on each axis for re-use as default texture3D coordinates
320 OLDCODE float bbox[6], *bmin, *bmax;
321 OLDCODE struct X3D_Node *gn;
322 OLDCODE struct X3D_Shape *sn = (struct X3D_Shape *)tg->RenderFuncs.shapenode;
323 OLDCODE POSSIBLE_PROTO_EXPANSION(struct X3D_Node *,sn->geometry,gn);
324 OLDCODE if(gn){
325 OLDCODE //first vec3 is minimum xyz
326 OLDCODE bmin = bbox;
327 OLDCODE bmax = &bbox[3];
328 OLDCODE for(i=0;i<3;i++){
329 OLDCODE bmin[i] = gn->_extent[i*2 + 1];
330 OLDCODE bmax[i] = gn->_extent[i*2];
331 OLDCODE }
332 OLDCODE //second vec3 is 1/size - so can be applied directly in vertex shader
333 OLDCODE vecdif3f(bmax,bmax,bmin);
334 OLDCODE for(i=0;i<3;i++){
335 OLDCODE if(bmax[i] != 0.0f)
336 OLDCODE bmax[i] = 1.0f/bmax[i];
337 OLDCODE else
338 OLDCODE bmax[i] = 1.0f;
339 OLDCODE }
340 OLDCODE //if(fabs(bmin[0]) > 10.0f)
341 OLDCODE // printf("bbox shift [%f %f %f] scale [%f %f %f]\n",bmin[0],bmin[1],bmin[2],bmax[0],bmax[1],bmax[2]);
342 OLDCODE
343 OLDCODE //special default texture transform for 3D textures posing as 2D textures
344 OLDCODE
345 OLDCODE //the order of applying transform elements seems reversed for texture transforms
346 OLDCODE //H: related to order of operands in mat * vec in shader:
347 OLDCODE // fw_TexCoord[0] = vec3(fw_TextureMatrix0 *vec4(texcoord,1.0));
348 OLDCODE // but sign on elements is what you expect
349 OLDCODE //flip z from RHS to LHS in fragment shader plug_tex3d apply
350 OLDCODE //printf("default tt\n");
351 OLDCODE FW_GL_SCALE_F(bmax[0],bmax[1],bmax[2]);
352 OLDCODE FW_GL_TRANSLATE_F(-bmin[0],-bmin[1],-bmin[2]);
353 OLDCODE }
354 OLDCODE }
355 OLDCODE if(me){
356 OLDCODE if(tg->RenderFuncs.shapenode && genTexPtr->TC_size < 3){
357 OLDCODE //3D but no 3D coords supplied - gen from vertex in vertex shader
358 OLDCODE glUniform1i(me->tex3dUseVertex,1); //vertex shader flag to over-ride texCoords with vertex
359 OLDCODE }else{
360 OLDCODE glUniform1i(me->tex3dUseVertex,0);
361 OLDCODE }
362 OLDCODE if(tti){
363 OLDCODE if(me->repeatSTR > -1)
364 OLDCODE glUniform1iv(me->repeatSTR,3,tti->repeatSTR);
365 OLDCODE if(me->magFilter > -1)
366 OLDCODE glUniform1i(me->magFilter,tti->magFilter);
367 OLDCODE }
368 OLDCODE }
369 OLDCODE }
370 OLDCODE
371 OLDCODE texture = tg->RenderFuncs.boundTextureStack[c];
372 OLDCODE
373 OLDCODE // SET_TEXTURE_UNIT_AND_BIND
374 OLDCODE glActiveTexture(GL_TEXTURE0+c);
375 OLDCODE //printf("active texture %d texture %d c %d\n",GL_TEXTURE0+c,texture,c);
376 OLDCODE if (getAppearanceProperties()->cubeFace==0) {
377 OLDCODE glBindTexture(GL_TEXTURE_2D,texture);
378 OLDCODE } else {
379 OLDCODE glBindTexture(GL_TEXTURE_CUBE_MAP,texture);
380 OLDCODE }
381 OLDCODE if(genTexPtr->VBO)
382 OLDCODE FW_GL_BINDBUFFER(GL_ARRAY_BUFFER,genTexPtr->VBO);
383 OLDCODE
384 OLDCODE if (genTexPtr->pre_canned_textureCoords != NULL) {
385 OLDCODE /* simple shapes, like Boxes and Cones and Spheres will have pre-canned arrays */
386 OLDCODE FW_GL_TEXCOORD_POINTER (2,GL_FLOAT,0,genTexPtr->pre_canned_textureCoords,c);
387 OLDCODE }else{
388 OLDCODE FW_GL_TEXCOORD_POINTER (genTexPtr->TC_size,
389 OLDCODE genTexPtr->TC_type,
390 OLDCODE genTexPtr->TC_stride,
391 OLDCODE genTexPtr->TC_pointer,c);
392 OLDCODE }
393 OLDCODE }
394 OLDCODE }
395 OLDCODE genTexPtr = genTexPtr->next ? genTexPtr->next : genTexPtr; //duplicate the prior coords if not enough for all MultiTextures
396 OLDCODE }
397 OLDCODE /* set up the selected shader for this texture(s) config */
398 OLDCODE if (me != NULL) {
399 OLDCODE tnode = tg->RenderFuncs.texturenode;
400 OLDCODE //printf ("passedInGenTex, we have tts %d tc %d\n",tg->RenderFuncs.textureStackTop, me->textureCount);
401 OLDCODE
402 OLDCODE if (me->textureCount != -1) {
403 OLDCODE glUniform1i(me->textureCount, tg->RenderFuncs.textureStackTop);
404 OLDCODE }
405 OLDCODE if(tg->RenderFuncs.textureStackTop){
406 OLDCODE if(isMultiTexture(tg->RenderFuncs.texturenode)){
407 OLDCODE struct X3D_MultiTexture * mtnode = (struct X3D_MultiTexture *)tg->RenderFuncs.texturenode;
408 OLDCODE glUniform4f(me->multitextureColor,mtnode->color.c[0],mtnode->color.c[1],mtnode->color.c[2],mtnode->alpha);
409 OLDCODE }
410 OLDCODE }
411 OLDCODE for (i=0; i<tg->RenderFuncs.textureStackTop; i++) {
412 OLDCODE //static int once = 0;
413 OLDCODE //if(once < 10) {
414 OLDCODE //printf (" sending in i%d tu %d mode %d src %d fnc %d\n",i,i,
415 OLDCODE // p->textureParameterStack[i].multitex_mode,
416 OLDCODE // p->textureParameterStack[i].multitex_source,
417 OLDCODE // p->textureParameterStack[i].multitex_function);
418 OLDCODE // once++;
419 OLDCODE //}
420 OLDCODE glUniform1i(me->TextureUnit[i],i);
421 OLDCODE //the 2i wasn't working for me even with ivec2 in shader
422 OLDCODE glUniform2i(me->TextureMode[i],p->textureParameterStack[i].multitex_mode[0], p->textureParameterStack[i].multitex_mode[1]);
423 OLDCODE glUniform2i(me->TextureSource[i],p->textureParameterStack[i].multitex_source[0], p->textureParameterStack[i].multitex_source[1]);
424 OLDCODE //glUniform1i(me->TextureMode[i],p->textureParameterStack[i].multitex_mode[0]);
425 OLDCODE //glUniform1i(me->TextureSource[i],p->textureParameterStack[i].multitex_source[0]);
426 OLDCODE glUniform1i(me->TextureFunction[i],p->textureParameterStack[i].multitex_function);
427 OLDCODE }
428 OLDCODE #ifdef TEXVERBOSE
429 OLDCODE } else {
430 OLDCODE printf (" NOT sending in %d i+tu+mode because currentShaderProperties is NULL\n",tg->RenderFuncs.textureStackTop);
431 OLDCODE #endif
432 OLDCODE }
433 OLDCODE
434 OLDCODE FW_GL_MATRIX_MODE(GL_MODELVIEW);
435 OLDCODE
436 OLDCODE PRINT_GL_ERROR_IF_ANY("");
437 OLDCODE }
438 #endif //OLDCODE
439 
440 void textureCoord_send(struct textureVertexInfo *genTex) {
441  // Oct 2016 refactoring before particleSystem
442  // moved texturetransform stuff out of here and into (below) textureTransform_start()
443  int c;
444  //int isIdentity; //isMulti, isStrict,i,
445  //GLint texUnit[MAX_MULTITEXTURE];
446  //GLint texMode[MAX_MULTITEXTURE];
447  // OLDCODE s_shader_capabilities_t *me;
448  struct textureVertexInfo *genTexPtr;
449  // OLDCODE struct X3D_Node *tnode;
450 
451  // OLDCODE ppRenderTextures p;
452  ttglobal tg = gglobal();
453  // OLDCODE p = (ppRenderTextures)tg->RenderTextures.prv;
454  // OLDCODE tnode = tg->RenderFuncs.texturenode;
455 
456  // OLDCODE me = getAppearanceProperties()->currentShaderProperties;
457 
458  genTexPtr = genTex;
459  for (c=0; c<tg->RenderFuncs.textureStackTop; c++) {
460  if(genTexPtr->VBO)
461  FW_GL_BINDBUFFER(GL_ARRAY_BUFFER,genTexPtr->VBO);
462 
463  if (genTexPtr->pre_canned_textureCoords != NULL) {
464  /* simple shapes, like Boxes and Cones and Spheres will have pre-canned arrays */
465  FW_GL_TEXCOORD_POINTER (2,GL_FLOAT,0,genTexPtr->pre_canned_textureCoords,c);
466  }else{
467  FW_GL_TEXCOORD_POINTER (genTexPtr->TC_size,
468  genTexPtr->TC_type,
469  genTexPtr->TC_stride,
470  genTexPtr->TC_pointer,c);
471  }
472  genTexPtr = genTexPtr->next ? genTexPtr->next : genTexPtr; //duplicate the prior coords if not enough for all MultiTextures
473  }
474 }
475 
476 
477 void textureTransform_start() {
478  int c;
479  int i, isStrict, isMulti, isIdentity;
480  GLint texUnit[MAX_MULTITEXTURE];
481  GLint texMode[MAX_MULTITEXTURE];
483  struct X3D_Node *tnode;
484 
486  ttglobal tg = gglobal();
487  p = (ppRenderTextures)tg->RenderTextures.prv;
488  tnode = tg->RenderFuncs.texturenode;
489 
490  me = getAppearanceProperties()->currentShaderProperties;
491 
492  #ifdef TEXVERBOSE
493  printf ("passedInGenTex, using passed in genTex, textureStackTop %d\n",tg->RenderFuncs.textureStackTop);
494  printf ("passedInGenTex, cubeFace %d\n",getAppearanceProperties()->cubeFace);
495  #endif
496 
497  FW_GL_MATRIX_MODE(GL_TEXTURE);
498 
499  //printf ("passedInGenTex, B\n");
500  isStrict = 1; //web3d specs say if its a multitexture,
501  //and you give it a single textureTransform instead of multitexturetransform
502  //it should ignore the singleTextureTransform and use identities.
503  //strict: This is a change of functionality for freewrl Aug 31, 2016
504  isIdentity = TRUE;
505  for (c=0; c<tg->RenderFuncs.textureStackTop; c++) {
506  FW_GL_PUSH_MATRIX(); //POPPED in textureDraw_end
507  FW_GL_LOAD_IDENTITY();
508  //printf ("passedInGenTex, c=%d\n",c);
509  /* are we ok with this texture yet? */
510  if (tg->RenderFuncs.boundTextureStack[c]!=0) {
511  isMulti = isMultiTexture(tg->RenderFuncs.texturenode);
512  //printf ("passedInGenTex, C, boundTextureStack %d\n",tg->RenderFuncs.boundTextureStack[c]);
513  if (setActiveTexture(c,getAppearanceProperties()->transparency,texUnit,texMode)) {
514  //printf ("passedInGenTex, going to bind to texture %d\n",tg->RenderFuncs.boundTextureStack[c]);
515  GLuint texture;
516  struct X3D_Node *tt = getThis_textureTransform();
517  if (tt!=NULL) {
518  int match = FALSE;
519  match = isMulti && (tt->_nodeType == NODE_MultiTextureTransform);
520  match = match || (!isMulti && (tt->_nodeType != NODE_MultiTextureTransform));
521  if(isStrict){
522  if(match){
523  do_textureTransform(tt,c);
524  isIdentity = FALSE;
525  }
526  }else{
527  do_textureTransform(tt,c);
528  isIdentity = FALSE;
529  }
530  }
531  //TEXTURE 3D
532  if(isTex3D(tnode)){
533  textureTableIndexStruct_s *tti = getTableTableFromTextureNode(tnode);
534  if(tnode->_nodeType != NODE_ComposedTexture3D){
535  //pixelTexture3D, imageTexture3D (but not composedTexture3D which uses textureCount above)
536  if(me){
537  if(tti){
538  glUniform1iv(me->tex3dTiles,3,tti->tiles);
539  }
540  }
541  }
542  //all texture3d
543  if(tg->RenderFuncs.shapenode && isIdentity ) { //&& genTexPtr->TC_size < 3){
544  //_if_ no TextureTransform3D was explicitly specified for Texture3D,
545  //_and_ no textureCoordinate3D or textureCoordinate4D was explicilty specified with the goem node
546  //_then_ bounding box of shape, in local coordinates, is used to scale/translate
547  //geometry vertices into 0-1 range on each axis for re-use as default texture3D coordinates
548  float bbox[6], *bmin, *bmax;
549  struct X3D_Node *gn;
550  struct X3D_Shape *sn = (struct X3D_Shape *)tg->RenderFuncs.shapenode;
551  POSSIBLE_PROTO_EXPANSION(struct X3D_Node *,sn->geometry,gn);
552  if(gn){
553  //first vec3 is minimum xyz
554  bmin = bbox;
555  bmax = &bbox[3];
556  for(i=0;i<3;i++){
557  bmin[i] = gn->_extent[i*2 + 1];
558  bmax[i] = gn->_extent[i*2];
559  }
560  //second vec3 is 1/size - so can be applied directly in vertex shader
561  vecdif3f(bmax,bmax,bmin);
562  for(i=0;i<3;i++){
563  if(bmax[i] != 0.0f)
564  bmax[i] = 1.0f/bmax[i];
565  else
566  bmax[i] = 1.0f;
567  }
568  //if(fabs(bmin[0]) > 10.0f)
569  // printf("bbox shift [%f %f %f] scale [%f %f %f]\n",bmin[0],bmin[1],bmin[2],bmax[0],bmax[1],bmax[2]);
570 
571  //special default texture transform for 3D textures posing as 2D textures
572 
573  //the order of applying transform elements seems reversed for texture transforms
574  //H: related to order of operands in mat * vec in shader:
575  // fw_TexCoord[0] = vec3(fw_TextureMatrix0 *vec4(texcoord,1.0));
576  // but sign on elements is what you expect
577  //flip z from RHS to LHS in fragment shader plug_tex3d apply
578  //printf("default tt\n");
579  FW_GL_SCALE_F(bmax[0],bmax[1],bmax[2]);
580  FW_GL_TRANSLATE_F(-bmin[0],-bmin[1],-bmin[2]);
581  }
582  }
583  if(me){
584  if(tg->RenderFuncs.shapenode ) { //&& genTexPtr->TC_size < 3){
585  //3D but no 3D coords supplied - gen from vertex in vertex shader
586  glUniform1i(me->tex3dUseVertex,1); //vertex shader flag to over-ride texCoords with vertex
587  }else{
588  glUniform1i(me->tex3dUseVertex,0);
589  }
590  if(tti){
591  if(me->repeatSTR > -1)
592  glUniform1iv(me->repeatSTR,3,tti->repeatSTR);
593  if(me->magFilter > -1)
594  glUniform1i(me->magFilter,tti->magFilter);
595  }
596  }
597  }
598 
599  texture = tg->RenderFuncs.boundTextureStack[c];
600 
601  // SET_TEXTURE_UNIT_AND_BIND
602  glActiveTexture(GL_TEXTURE0+c);
603  //printf("active texture %d texture %d c %d\n",GL_TEXTURE0+c,texture,c);
604  if (getAppearanceProperties()->cubeFace==0) {
605  glBindTexture(GL_TEXTURE_2D,texture);
606  } else {
607  glBindTexture(GL_TEXTURE_CUBE_MAP,texture);
608  }
609  }
610  }
611  }
612  /* set up the selected shader for this texture(s) config */
613  if (me != NULL) {
614  tnode = tg->RenderFuncs.texturenode;
615  //printf ("passedInGenTex, we have tts %d tc %d\n",tg->RenderFuncs.textureStackTop, me->textureCount);
616 
617  if (me->textureCount != -1) {
618  glUniform1i(me->textureCount, tg->RenderFuncs.textureStackTop);
619  }
620  if(tg->RenderFuncs.textureStackTop){
621  if(isMultiTexture(tg->RenderFuncs.texturenode)){
622  struct X3D_MultiTexture * mtnode = (struct X3D_MultiTexture *)tg->RenderFuncs.texturenode;
623  glUniform4f(me->multitextureColor,mtnode->color.c[0],mtnode->color.c[1],mtnode->color.c[2],mtnode->alpha);
624  }
625  }
626  for (i=0; i<tg->RenderFuncs.textureStackTop; i++) {
627  //static int once = 0;
628  //if(once < 10) {
629  //printf (" sending in i%d tu %d mode %d src %d fnc %d\n",i,i,
630  // p->textureParameterStack[i].multitex_mode,
631  // p->textureParameterStack[i].multitex_source,
632  // p->textureParameterStack[i].multitex_function);
633  // once++;
634  //}
635  glUniform1i(me->TextureUnit[i],i);
636  //the 2i wasn't working for me even with ivec2 in shader
637  glUniform2i(me->TextureMode[i],p->textureParameterStack[i].multitex_mode[0], p->textureParameterStack[i].multitex_mode[1]);
638  glUniform2i(me->TextureSource[i],p->textureParameterStack[i].multitex_source[0], p->textureParameterStack[i].multitex_source[1]);
639  //glUniform1i(me->TextureMode[i],p->textureParameterStack[i].multitex_mode[0]);
640  //glUniform1i(me->TextureSource[i],p->textureParameterStack[i].multitex_source[0]);
641  glUniform1i(me->TextureFunction[i],p->textureParameterStack[i].multitex_function);
642  }
643  #ifdef TEXVERBOSE
644  } else {
645  printf (" NOT sending in %d i+tu+mode because currentShaderProperties is NULL\n",tg->RenderFuncs.textureStackTop);
646  #endif
647  }
648 
649  FW_GL_MATRIX_MODE(GL_MODELVIEW);
650 
651  PRINT_GL_ERROR_IF_ANY("");
652 }