FreeWRL / FreeX3D 4.3.0
Textures.c
1/*
2
3 FreeWRL support library.
4 Texture handling code.
5
6*/
7
8/****************************************************************************
9 This file is part of the FreeWRL/FreeX3D Distribution.
10
11 Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
12
13 FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
14 it under the terms of the GNU Lesser Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 FreeWRL/FreeX3D is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
25****************************************************************************/
26
27
28
29#include <config.h>
30#include <system.h>
31#include <system_threads.h>
32#include <display.h>
33#include <internal.h>
34
35#include <libFreeWRL.h>
36#include <list.h>
37
38#include <threads.h>
39
40#include "../vrml_parser/Structs.h"
41#include "../main/headers.h"
42
43#include "../scenegraph/readpng.h"
44#include "../input/InputFunctions.h"
45#include "../opengl/Material.h"
46#include "../opengl/OpenGL_Utils.h"
47#include "Textures.h"
48#include "../world_script/fieldSet.h"
49#include "../scenegraph/Component_Shape.h"
50#include "../scenegraph/Component_CubeMapTexturing.h"
51#include "../scenegraph/RenderFuncs.h"
52#include "LoadTextures.h"
53
54// OLD_IPHONE_AQUA #ifdef AQUA
55// OLD_IPHONE_AQUA #ifndef IPHONE
56// OLD_IPHONE_AQUA # include <Carbon/Carbon.h>
57// OLD_IPHONE_AQUA # include <QuickTime/QuickTime.h>
58// OLD_IPHONE_AQUA #endif
59// OLD_IPHONE_AQUA #else
60// OLD_IPHONE_AQUA # if HAVE_JPEGLIB_H
61// OLD_IPHONE_AQUA #undef HAVE_STDLIB_H
62// OLD_IPHONE_AQUA #undef FAR
63// OLD_IPHONE_AQUA # include <jpeglib.h>
64// OLD_IPHONE_AQUA # include <setjmp.h>
65// OLD_IPHONE_AQUA # endif
66// OLD_IPHONE_AQUA #endif
67
68
69
70struct multiTexParams {
71int multitex_mode[2];
72int multitex_source[2];
73int multitex_function;
74};
75
76
77#ifndef GL_EXT_texture_cube_map
78//OLDCODE # define GL_NORMAL_MAP_EXT 0x8511
79//OLDCODE # define GL_REFLECTION_MAP_EXT 0x8512
80# define GL_TEXTURE_CUBE_MAP_EXT 0x8513
81//OLDCODE # define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514
82# define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515
83//OLDCODE # define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516
84//OLDCODE # define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517
85//OLDCODE # define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518
86//OLDCODE # define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519
87//OLDCODE # define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A
88//OLDCODE # define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B
89//OLDCODE # define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C
90#endif
91
92
93static void new_bind_image(struct X3D_Node *node, struct multiTexParams *vparam);
94textureTableIndexStruct_s *getTableIndex(int i);
95
96typedef struct pTextures{
97 struct Vector *activeTextureTable;
98 textureTableIndexStruct_s* loadThisTexture;
99
100 /* current index into loadparams that texture thread is working on */
101 int currentlyWorkingOn;// = -1;
102 int textureInProcess;// = -1;
103}* ppTextures;
104
105
106
107
108void *Textures_constructor(){
109 void *v = MALLOCV(sizeof(struct pTextures));
110 memset(v,0,sizeof(struct pTextures));
111 return v;
112}
113void Textures_init(struct tTextures *t){
114 //public
115
116 //private
117 t->prv = Textures_constructor();
118 {
119 ppTextures p = (ppTextures)t->prv;
120 p->activeTextureTable = NULL;
121
122 /* current index into loadparams that texture thread is working on */
123 p->currentlyWorkingOn = -1;
124
125 p->textureInProcess = -1;
126 }
127}
128void Textures_clear(struct tTextures *t){
129 //public
130 glDeleteBuffers (1,&t->defaultBlankTexture);
131 //private
132 {
133 //int i;
134 ppTextures p = (ppTextures)t->prv;
135 //for(i=0;i<vectorSize(p->activeTextureTable);i++){
136 // textureTableIndexStruct_s *tti = vector_get(textureTableIndexStruct_s *,p->activeTextureTable,i);
137 // if(tti && tti->texdata)
138 // FREE_IF_NZ(tti->texdata);
139 //}
140 deleteVector(textureTableIndexStruct_s *, p->activeTextureTable);
141 }
142}
143
144
145// OLD_IPHONE_AQUA #if defined(AQUA) /* for AQUA OS X sharing of OpenGL Contexts */
146
147// OLD_IPHONE_AQUA #elif defined(_MSC_VER)
148#if defined(_MSC_VER) || defined(AQUA)
149
150
151#else
152#if !defined(_ANDROID) && !defined(ANDROIDNDK) && !defined(GLES2)
153GLXContext textureContext = NULL;
154#endif
155
156#endif
157
158/* function Prototypes */
159int findTextureFile(textureTableIndexStruct_s *entry);
160//void _textureThread(void);
161
162void move_texture_to_opengl(textureTableIndexStruct_s*);
163struct Uni_String *newASCIIString(const char *str);
164
165int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight);
166void readpng_cleanup(int free_image_data);
167
168
169static void myTexImage2D (int generateMipMaps, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLubyte *pixels);
170
171/* gluScaleImage replacement */
172
173/* we manipulate things here as 4 byte colours (RGBA, or BGRA) so we try and ensure
174that we have 32 bit numbers, thus this definition. ES-2.0 is 32 bits, but in case
175someone compiles on a 64 bit system, with Material shader definitions in OpenGL-3.x,
176then hopefully this will work for them, too */
177
178#ifndef uint32
179# define uint32 uint32_t
180#endif
181
182
183
184static void myScaleImage(int srcX,int srcY,int destX,int destY,unsigned char *src, unsigned char *dest) {
185 float YscaleFactor;
186 float XscaleFactor;
187 int wye, yex;
188 uint32 *src32 = (uint32 *)src;
189 uint32 *dest32 = (uint32 *)dest;
190
191 if ((srcY<=0) || (destY<=0) || (srcX<=0) || (destX<=0)) return;
192 if (src == NULL) return;
193 if (dest == NULL) return;
194
195 if ((srcY==destY) && (srcX==destX)) {
196 /* printf ("simple copy\n"); */
197 memcpy (dest,src,srcY*srcX*4); /* assuming FreeWRL-standard RGBA or BGRA textures */
198 }
199
200 /* do x direction first */
201 YscaleFactor = ((float)srcY) / ((float)destY);
202 XscaleFactor = ((float)srcX) / ((float)destX);
203
204 for (wye=0; wye<destY; wye++) {
205 for (yex=0; yex<destX; yex++) {
206 float fx, fy;
207 int row, column;
208 size_t oldIndex, newIndex;
209
210 fx = YscaleFactor * ((float) wye);
211 fy = XscaleFactor * ((float) yex);
212 row = (int)(fx);
213 column = (int)(fy);
214 oldIndex = (size_t)row * (size_t)srcX + (size_t)column; /* so many rows, each row has srcX columns */
215 newIndex = (size_t)wye * (size_t)destX + (size_t)yex; //wye*destX+yex
216 dest32[newIndex] = src32[oldIndex];
217 }
218 }
219}
220
221static void myScaleImage3D(int srcX,int srcY,int srcZ, int destX,int destY,int destZ, unsigned char *src, unsigned char *dest) {
222 float YscaleFactor;
223 float XscaleFactor;
224 float ZscaleFactor;
225 float fx,fy,fz;
226 int iy, ix, iz;
227 uint32 *src32 = (uint32 *)src;
228 uint32 *dest32 = (uint32 *)dest;
229
230 if ((srcY<=0) || (destY<=0) || (srcX<=0) || (destX<=0) || (srcZ<=0) || (destZ<=0)) return;
231 if (src == NULL) return;
232 if (dest == NULL) return;
233
234 if ((srcY==destY) && (srcX==destX) && (srcZ==destZ)) {
235 /* printf ("simple copy\n"); */
236 memcpy (dest,src,srcY*srcX*srcZ*4); /* assuming FreeWRL-standard RGBA or BGRA textures */
237 }
238
239 /* do x direction first */
240 YscaleFactor = ((float)srcY) / ((float)destY);
241 XscaleFactor = ((float)srcX) / ((float)destX);
242 ZscaleFactor = ((float)srcZ) / ((float)destZ);
243
244 for (iz=0; iz<destZ; iz++) {
245 int page;
246 fz = ZscaleFactor * ((float) iz);
247 page = (int)fz;
248 for (iy=0; iy<destY; iy++) {
249 int row;
250 fy = YscaleFactor * ((float) iy);
251 row = (int)(fy);
252 for (ix=0; ix<destX; ix++) {
253 int column;
254 int oldIndex;
255
256 fx = XscaleFactor * ((float) ix);
257 column = (int)(fx);
258 oldIndex = (page * srcY + row) * srcX + column; /* so many rows, each row has srcX columns */
259 dest32[(iz*destY + iy)*destX+ix] = src32[oldIndex];
260 }
261 }
262 }
263}
264int iclamp(int ival, int istart, int iend) {
265 int iret = ival;
266 iret = ival > iend? iend : ival;
267 iret = iret < istart ? istart : iret;
268 return iret;
269}
270void compute_3D_alpha_gradient_store_rgb(char *dest,int x,int y, int z){
271 //assumes we have a scalar image with info only in alpha, but (unused) RGB channels
272 //we compute 3D alpha/scalar gradient using one of sobel, roberts ...
273 //gradient has magnitude and direction (vs normal, which is of unit length)
274 //here we do an axis-aligned roberts ie gradient_x = x1 - x0
275 int iz,iy,ix, jz,jy,jx,jzz,jyy,jxx, k;
276 char *rgba0, *rgba1;
277 int gradient[3], maxgradient[3], mingradient[3];
278 unsigned char *urgba;
279 uint32 *pixels = (uint32 *)dest;
280
281 for(k=0;k<3;k++) {
282 maxgradient[k] = -1;
283 mingradient[k] = 1;
284 }
285
286
287 for(iz=0;iz<z;iz++){
288 for(iy=0;iy<y;iy++){
289 for(ix=0;ix<x;ix++){
290 //initialize gradient
291 for(k=0;k<3;k++) gradient[k] = 0;
292 rgba0 = (char *) &pixels[(iz*y +iy)*x + ix];
293 urgba = (unsigned char *)rgba0;
294 if(1){
295 //sum onto gradient
296 jxx = jyy = jzz = 0;
297 //what if we are on the edge? for roberts, just duplicate next-to-edge by backing up one
298 if(iz == z-1) jzz = -1;
299 if(iy == y-1) jyy = -1;
300 if(ix == x-1) jxx = -1;
301 jx = jxx; jy = jyy; jz = jzz;
302 jx = jxx + 1;
303 rgba1 = (char *) &pixels[((iz+jz)*y +(iy+jy))*x + (ix+jx)];
304 gradient[0] = (int)rgba1[3] - (int)rgba0[3];
305 jx = jxx;
306 jy = jyy+1;
307 rgba1 = (char *) &pixels[((iz+jz)*y +(iy+jy))*x + (ix+jx)];
308 gradient[1] = (int)rgba1[3] - (int)rgba0[3];
309 jy = jyy;
310 jz = jzz+1;
311 rgba1 = (char *) &pixels[((iz+jz)*y +(iy+jy))*x + (ix+jx)];
312 gradient[2] = (int)rgba1[3] - (int)rgba0[3];
313 }else {
314 //extract edge-clamped 3x3x3
315 // X Y Z with [1] in center
316 int cube[3][3][3], i,j,ii,jj,kk;
317 for(i=-1;i<2;i++){
318 ii = iclamp(ix+i,0,x-1);
319 for(j=-1;j<2;j++){
320 jj= iclamp(iy+j,0,y-1);
321 for(k=-1;k<2;k++){
322 kk = iclamp(iz+k,0,z-1);
323 cube[i+1][j+1][k+1] = ((unsigned char *)&pixels[(kk*y +jj)*x + ii])[3];
324 }
325 }
326 }
327 if(1){
328 //roberts cross
329 //gradient[0] = (cube[2][2][2] - cube[1][1][1]) + (cube[2][0][0] - cube[1][1][1];
330 }
331 if(1){
332 //sobel gradient
333 gradient[0] = 0;
334 gradient[0] += cube[0][0][1] + 2*cube[0][1][1] + cube[0][2][1];
335 gradient[0] -= cube[2][0][1] + 2*cube[2][1][1] + cube[2][2][1];
336 gradient[0] += cube[0][1][0] + 2*cube[0][1][1] + cube[0][1][2];
337 gradient[0] -= cube[2][1][0] + 2*cube[2][1][1] + cube[2][1][2];
338
339 gradient[1] = 0;
340 gradient[1] += cube[1][0][0] + 2*cube[1][0][1] + cube[1][0][2];
341 gradient[1] -= cube[1][2][0] + 2*cube[1][2][1] + cube[1][2][2];
342 gradient[1] += cube[0][0][1] + 2*cube[1][0][1] + cube[2][0][1];
343 gradient[1] -= cube[9][2][1] + 2*cube[1][2][1] + cube[2][2][1];
344
345 gradient[2] = 0;
346 gradient[2] += cube[0][1][0] + 2*cube[1][1][0] + cube[2][1][0];
347 gradient[2] -= cube[0][1][2] + 2*cube[1][1][2] + cube[2][1][2];
348 gradient[2] += cube[1][0][0] + 2*cube[1][1][0] + cube[1][2][0];
349 gradient[2] -= cube[1][9][2] + 2*cube[1][1][2] + cube[1][2][2];
350 for(k=0;k<3;k++)
351 gradient[k] /= 2;
352
353 }
354 }
355
356 //scale gradient to -127 to +127 in each dimension
357 //roberts: a1 - a0 could be in range (255 - 0) to (0 -255) or -255 to 255,
358 // we need -127 to 127 signed char on each dim
359 for(k=0;k<3;k++) gradient[k] /= 2;
360 for(k=0;k<3;k++) {
361 maxgradient[k] = max(maxgradient[k],gradient[k]);
362 mingradient[k] = min(mingradient[k],gradient[k]);
363 }
364
365 //but when texture2D / sampler2D convert from image pixel to float,
366 //the expect the pixels to be unsigned char.
367 //so we add 127 here, and subtract .5 in the shader, once they are float
368 for(k=0;k<3;k++) gradient[k] += 127;
369
370 //set gradient in RGB channels
371 for(k=0;k<3;k++) urgba[k] = (unsigned char)gradient[k];
372 //if(rgba0[0] || rgba0[1] || rgba0[2]){
373 // if(rgba0[0] != rgba0[1] || rgba0[1] != rgba0[2])
374 // printf("[%d %d %d]",(int)rgba0[0],(int)rgba0[1],(int)rgba0[2]);
375 //}
376 }
377 }
378 }
379 if(0){
380 printf("mingradient %d %d %d\n",mingradient[0],mingradient[1],mingradient[2]);
381 printf("maxgradient %d %d %d\n",maxgradient[0],maxgradient[1],maxgradient[2]);
382 }
383 if(0){
384 //save gradient image for testing
386 tti2 = &tt;
387 tti2->x = x;
388 tti2->y = y;
389 tti2->z = z;
390 tti2->texdata = (unsigned char *)dest;
391 tti2->channels = 3;
392 saveImage_web3dit(tti2,"gradientRGB.web3dit");
393 tti2->channels = 4;
394 saveImage_web3dit(tti2,"gradientRGBA.web3dit");
395
396 }
397
398}
399static void GenMipMap2D( GLubyte *src, GLubyte **dst, int srcWidth, int srcHeight, int *dstWidth, int *dstHeight )
400{
401 int x,
402 y;
403 int texelSize = 4;
404 size_t total_size;
405 GLubyte *dest, *pix;
406
407
408 *dstWidth = srcWidth / 2;
409 if ( *dstWidth <= 0 )
410 *dstWidth = 1;
411
412 *dstHeight = srcHeight / 2;
413 if ( *dstHeight <= 0 )
414 *dstHeight = 1;
415
416 total_size = sizeof(GLubyte) * (size_t)texelSize * (size_t)(*dstWidth) * (size_t)(*dstHeight);
417 *dst = MALLOC(void *, total_size );
418 dest = *dst;
419 if ( *dst == NULL )
420 return;
421
422 for ( y = 0; y < *dstHeight; y++ )
423 {
424 for( x = 0; x < *dstWidth; x++ )
425 {
426 size_t srcIndex[4], x2, y2, swidth, texsize, kd;
427 float r = 0.0f,
428 g = 0.0f,
429 b = 0.0f,
430 a = 0.0f;
431
432 int sample;
433
434 // Compute the offsets for 2x2 grid of pixels in previous
435 // image to perform box filter
436 //srcIndex[0] =
437 // (((y * 2) * srcWidth) + (x * 2)) * texelSize;
438 //srcIndex[1] =
439 // (((y * 2) * srcWidth) + (x * 2 + 1)) * texelSize;
440 //srcIndex[2] =
441 // ((((y * 2) + 1) * srcWidth) + (x * 2)) * texelSize;
442 //srcIndex[3] =
443 // ((((y * 2) + 1) * srcWidth) + (x * 2 + 1)) * texelSize;
444
445 swidth = srcWidth;
446 texsize = texelSize;
447 y2 = y * 2L;
448 x2 = x * 2L;
449 srcIndex[0] = (y2*swidth + x2) * texsize;
450 srcIndex[1] = (y2*swidth + x2 + (size_t)1L) * texsize;
451 srcIndex[2] = ((y2 + 1L)*swidth + x2) * texsize;
452 srcIndex[3] = ((y2 + 1L)*swidth + x2 + (size_t)1L) * texsize;
453
454 // Sum all pixels
455 for ( sample = 0; sample < 4; sample++ )
456 {
457 r += src[srcIndex[sample] + (size_t)0L];
458 g += src[srcIndex[sample] + (size_t)1L];
459 b += src[srcIndex[sample] + (size_t)2L];
460 a += src[srcIndex[sample] + (size_t)3L];
461 }
462
463 // Average results
464 r /= 4.0f;
465 g /= 4.0f;
466 b /= 4.0f;
467 a /= 4.0f;
468
469 // Store resulting pixels
470 kd = ((size_t)y * (size_t)(*dstWidth) + (size_t)x ) * (size_t)texelSize;
471 pix = dest + kd;
472 pix[0] = (GLubyte)( r );
473 pix[1] = (GLubyte)( g );
474 pix[2] = (GLubyte)( b );
475 pix[3] = (GLubyte)( a );
476
477 //(*dst)[ ( y * (*dstWidth) + x ) * texelSize ] = (GLubyte)( r );
478 //(*dst)[ ( y * (*dstWidth) + x ) * texelSize + 1] = (GLubyte)( g );
479 //(*dst)[ ( y * (*dstWidth) + x ) * texelSize + 2] = (GLubyte)( b );
480 //(*dst)[ ( y * (*dstWidth) + x ) * texelSize + 3] = (GLubyte)( a );
481 }
482 }
483}
484/* create the MIPMAPS ourselves, as the OpenGL ES 2.0 can not do it */
485static void myTexImage2D (int generateMipMaps, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLubyte *pixels) {
486 GLubyte *prevImage = NULL;
487 GLubyte *newImage = NULL;
488 size_t total_size;
489
490 /* first, base image */
491
492 FW_GL_TEXIMAGE2D(target,level,internalformat,width,height,border,format,type,pixels);
493 {
494 GLenum err;
495 err = glGetError();
496 switch(err){
497 case GL_NO_ERROR: break;
498 default:
499 ConsoleMessage("glError %d in glTexImage2D\n",(int)err);
500 }
501 }
502 if (!generateMipMaps) return;
503 if ((width <=1) && (height <=1)) return;
504
505
506 /* go and create a bunch of mipmaps */
507 total_size = (size_t)4L * width * height;
508 prevImage = MALLOC(GLubyte *, total_size);
509 memcpy (prevImage, pixels, total_size);
510
511 /* from the OpenGL-ES 2.0 book, page 189 */
512 level = 1;
513
514 while ((width > 1) && (height > 1)) {
515 GLint newWidth, newHeight;
516
517 GenMipMap2D(prevImage,&newImage, width, height, &newWidth, &newHeight);
518
519 FW_GL_TEXIMAGE2D(target,level,internalformat,newWidth,newHeight,0,format,GL_UNSIGNED_BYTE,newImage);
520
521 FREE_IF_NZ(prevImage);
522 prevImage = newImage;
523 level++;
524 width = newWidth;
525 height = newHeight;
526 }
527
528 FREE_IF_NZ(newImage);
529}
530
531
535const char *texst(int num)
536{
537 if (num == TEX_NOTLOADED) return "TEX_NOTLOADED";
538 if (num == TEX_LOADING) return "TEX_LOADING";
539 if (num == TEX_NEEDSBINDING)return "TEX_NEEDSBINDING";
540 if (num == TEX_LOADED)return "TEX_LOADED";
541 if (num == TEX_UNSQUASHED)return "UNSQUASHED";
542 return "unknown";
543}
544
545
546/* does a texture have alpha? - pass in a __tableIndex from a MovieTexture, ImageTexture or PixelTexture. */
547int isTextureAlpha(int texno) {
549
550 /* no, have not even started looking at this */
551 /* if (texno == 0) return FALSE; */
552
553 ti = getTableIndex(texno);
554 if (ti==NULL) return FALSE;
555
556 if (ti->status==TEX_LOADED) {
557 return ti->hasAlpha;
558 }
559 return FALSE;
560}
561
562
563/* is the texture thread initialized yet? */
564int fwl_isTextureinitialized() {
565 return gglobal()->threads.TextureThreadRunning; // gglobal()->LoadTextures.TextureThreadInitialized;
566}
567
568/* is this texture loaded? used in LoadSensor */
569int fwl_isTextureLoaded(int texno) {
571
572 /* no, have not even started looking at this */
573 /* if (texno == 0) return FALSE; */
574
575 ti = getTableIndex(texno);
576 return (ti->status==TEX_LOADED);
577}
578
579/* statusbar uses this to tell user that we are still loading */
580int fwl_isTextureParsing() {
581 ppTextures p = (ppTextures)gglobal()->Textures.prv;
582
583 /* return currentlyWorkingOn>=0; */
584#ifdef TEXVERBOSE
585 if (p->textureInProcess > 0) {
586 printf("call to fwl_isTextureParsing %d, returning %d\n",
587 p->textureInProcess,p->textureInProcess > 0);
588 }
589#endif
590 return p->textureInProcess >0;
591}
592
593/* this node has changed - if there was a texture, destroy it */
594void releaseTexture(struct X3D_Node *node) {
595
596 int tableIndex;
598
599 if (node->_nodeType == NODE_ImageTexture) {
600 tableIndex = ((struct X3D_ImageTexture *)node)->__textureTableIndex;
601 } else if (node->_nodeType == NODE_PixelTexture) {
602 tableIndex = ((struct X3D_PixelTexture *)node)->__textureTableIndex;
603 } else if (node->_nodeType == NODE_MovieTexture) {
604 tableIndex = ((struct X3D_MovieTexture *)node)->__textureTableIndex;
605 } else if (node->_nodeType == NODE_PixelTexture3D) {
606 tableIndex = ((struct X3D_PixelTexture3D *)node)->__textureTableIndex;
607 } else if (node->_nodeType == NODE_ImageTexture3D) {
608 tableIndex = ((struct X3D_ImageTexture3D *)node)->__textureTableIndex;
609 } else if (node->_nodeType == NODE_ComposedTexture3D) {
610 tableIndex = ((struct X3D_ComposedTexture3D *)node)->__textureTableIndex;
611
612 } else return;
613
614#ifdef TEXVERBOSE
615 printf ("releaseTexture, calling getTableIndex\n");
616 ti = getTableIndex(tableIndex);
617 printf ("releaseTexture, ti %p, ti->status %d\n",ti,ti->status);
618 ti->status = TEX_NOTLOADED;
619
620 if (ti->OpenGLTexture != TEXTURE_INVALID) {
621 printf ("deleting %d textures, starting at %u\n",ti->frames, ti->OpenGLTexture);
622 ti->OpenGLTexture = TEXTURE_INVALID;
623/* FREE_IF_NZ(ti->OpenGLTexture); */
624 }
625#endif
626
627 ti = getTableIndex(tableIndex);
628 if(ti){
629 ti->status = TEX_NOTLOADED;
630 if (ti->OpenGLTexture != TEXTURE_INVALID) {
631 FW_GL_DELETETEXTURES(1, &ti->OpenGLTexture);
632 ti->OpenGLTexture = TEXTURE_INVALID;
633 /* FREE_IF_NZ(ti->OpenGLTexture); */
634 }
635 }
636}
637
638
639
640textureTableIndexStruct_s *getTableIndex(int indx) {
641 ppTextures p = (ppTextures)gglobal()->Textures.prv;
642
643#ifdef VERBOSE
644{char line[200];
645sprintf (line,"getTableIndex, looking for %d",indx);
646ConsoleMessage (line);}
647#endif
648 if (indx < 0) {
649 ConsoleMessage ("getTableIndex, texture <0 requested");
650 return NULL;
651 }
652
653 if (p->activeTextureTable ==NULL ) {
654 ConsoleMessage ("NULL sizing errror in getTableIndex");
655 return NULL;
656 }
657
658
659 if (indx >= vectorSize(p->activeTextureTable)) {
660 ConsoleMessage ("sizing errror in getTableIndex");
661 return NULL;
662 }
663
664
665#ifdef VERBOSE
666{char line[200];
667printf ("getTableIndex - valid request\n");
668sprintf (line,"getTableIndex, for %d, size %d",indx, vectorSize(p->activeTextureTable));
669ConsoleMessage (line);}
670#endif
671
672 return vector_get(textureTableIndexStruct_s *, p->activeTextureTable, indx);
673}
674int getTextureTableIndexFromFromTextureNode(struct X3D_Node *node){
675 int thisTexture = -1;
676 int thisTextureType = node->_nodeType;
677 if (thisTextureType==NODE_ImageTexture){
678 struct X3D_ImageTexture* it = (struct X3D_ImageTexture*) node;
679 thisTexture = it->__textureTableIndex;
680 } else if (thisTextureType==NODE_PixelTexture){
681 struct X3D_PixelTexture* pt = (struct X3D_PixelTexture*) node;
682 thisTexture = pt->__textureTableIndex;
683 } else if (thisTextureType==NODE_MovieTexture){
684 struct X3D_MovieTexture* mt = (struct X3D_MovieTexture*) node;
685 thisTexture = mt->__textureTableIndex;
686 } else if (thisTextureType==NODE_ImageCubeMapTexture){
687 struct X3D_ImageCubeMapTexture* ict = (struct X3D_ImageCubeMapTexture*) node;
688 thisTexture = ict->__textureTableIndex;
689 } else if (thisTextureType==NODE_GeneratedCubeMapTexture){
690 struct X3D_GeneratedCubeMapTexture* ict = (struct X3D_GeneratedCubeMapTexture*) node;
691 thisTexture = ict->__textureTableIndex;
692 } else if (thisTextureType==NODE_PixelTexture3D){
693 struct X3D_PixelTexture3D* pt = (struct X3D_PixelTexture3D*) node;
694 thisTexture = pt->__textureTableIndex;
695 } else if (thisTextureType==NODE_ImageTexture3D){
696 struct X3D_ImageTexture3D* pt = (struct X3D_ImageTexture3D*) node;
697 thisTexture = pt->__textureTableIndex;
698 } else if (thisTextureType==NODE_ComposedTexture3D){
699 struct X3D_ComposedTexture3D* pt = (struct X3D_ComposedTexture3D*) node;
700 thisTexture = pt->__textureTableIndex;
701 } else if (thisTextureType==NODE_MultiTexture){
702 struct X3D_MultiTexture* pt = (struct X3D_MultiTexture*) node;
703 thisTexture = getTextureTableIndexFromFromTextureNode(X3D_NODE(pt->texture.p[0]));
704 } else {
705 ConsoleMessage ("Invalid type for texture, %s\n",stringNodeType(thisTextureType));
706 }
707 return thisTexture;
708}
709textureTableIndexStruct_s *getTableTableFromTextureNode(struct X3D_Node *textureNode){
710 textureTableIndexStruct_s *ret = NULL;
711 int index = getTextureTableIndexFromFromTextureNode(textureNode);
712 if(index > -1)
713 ret = getTableIndex(index);
714 return ret;
715}
716int getGlTextureNumberFromTextureNode(struct X3D_Node *textureNode){
717 textureTableIndexStruct_s *tts = getTableTableFromTextureNode(textureNode);
718 if(tts == NULL) return 0;
719 return tts->OpenGLTexture;
720}
721
722int getTextureSizeFromTextureNode(struct X3D_Node *textureNode, int *ixyz){
723 int iret;
724 textureTableIndexStruct_s *tts = getTableTableFromTextureNode(textureNode);
725 ixyz[0] = ixyz[1] = ixyz[2] = 0;
726 iret = 0;
727 if(tts){
728 ixyz[0] = tts->x;
729 ixyz[1] = tts->y;
730 ixyz[2] = tts->z;
731 iret = 1;
732 }
733 return iret;
734}
735
736
737/* is this node a texture node? if so, lets keep track of its textures. */
738/* worry about threads - do not make anything reallocable */
739void registerTexture0(int iaction, struct X3D_Node *tmp) {
740 //iaction =1 add, =0 remove
741 struct X3D_ImageTexture *it;
742
743
744 it = (struct X3D_ImageTexture *) tmp;
745 /* printf ("registerTexture, found a %s\n",stringNodeType(it->_nodeType)); */
746
747 if ((it->_nodeType == NODE_ImageTexture) ||
748 (it->_nodeType == NODE_PixelTexture) ||
749 (it->_nodeType == NODE_ImageCubeMapTexture) ||
750 (it->_nodeType == NODE_GeneratedCubeMapTexture) ||
751 (it->_nodeType == NODE_PixelTexture3D) ||
752 (it->_nodeType == NODE_ImageTexture3D) ||
753 (it->_nodeType == NODE_ComposedTexture3D) ||
754 (it->_nodeType == NODE_MovieTexture)
755 ) {
756 ppTextures p = (ppTextures)gglobal()->Textures.prv;
757 if(iaction){
758 //ADD
759 // for the index, stored in the X3D node.
760 int textureNumber;
761 // new texture table entry. Zero all data
763 memset(newTexture,0,sizeof(textureTableIndexStruct_s));
764 newTexture->z = 1; //just texturing3D is > 1
765
766
767 if (p->activeTextureTable == NULL) {
768 p->activeTextureTable =newVector(textureTableIndexStruct_s *, 16);
769 vector_pushBack(textureTableIndexStruct_s *, p->activeTextureTable, newTexture);
770 }
771
772 // keep track of which texture this one is.
773 textureNumber = vectorSize(p->activeTextureTable);
774
775 //{char line[200]; sprintf (line,"registerTexture textureNumber %d",textureNumber); ConsoleMessage(line);}
776
777 DEBUG_TEX("CREATING TEXTURE NODE: type %d\n", it->_nodeType);
778 /* I need to know the texture "url" here... */
779
780 switch (it->_nodeType) {
781 /* save this index in the scene graph node */
782 case NODE_ImageTexture:
783 it->__textureTableIndex = textureNumber;
784 break;
785 case NODE_PixelTexture: {
786 struct X3D_PixelTexture *pt;
787 pt = (struct X3D_PixelTexture *) tmp;
788 pt->__textureTableIndex = textureNumber;
789 break; }
790 case NODE_PixelTexture3D: {
791 struct X3D_PixelTexture3D *pt;
792 pt = (struct X3D_PixelTexture3D *) tmp;
793 pt->__textureTableIndex = textureNumber;
794 break; }
795 case NODE_ImageTexture3D: {
796 struct X3D_ImageTexture3D *pt;
797 pt = (struct X3D_ImageTexture3D *) tmp;
798 pt->__textureTableIndex = textureNumber;
799 break; }
800 case NODE_ComposedTexture3D: {
801 struct X3D_ComposedTexture3D *pt;
802 pt = (struct X3D_ComposedTexture3D *) tmp;
803 pt->__textureTableIndex = textureNumber;
804 break; }
805 case NODE_MovieTexture: {
806 struct X3D_MovieTexture *mt;
807 mt = (struct X3D_MovieTexture *) tmp;
808 mt->__textureTableIndex = textureNumber;
809 break; }
810
811 case NODE_ImageCubeMapTexture: {
812 struct X3D_ImageCubeMapTexture *v1t;
813 v1t = (struct X3D_ImageCubeMapTexture *) tmp;
814 v1t->__textureTableIndex = textureNumber;
815 break;
816 }
817
818 case NODE_GeneratedCubeMapTexture: {
819 struct X3D_GeneratedCubeMapTexture *v1t;
820 v1t = (struct X3D_GeneratedCubeMapTexture *) tmp;
821 v1t->__textureTableIndex = textureNumber;
822 break;
823 }
824
825 }
826
827 /* set the scenegraphNode here */
828 newTexture->nodeType = it->_nodeType;
829 newTexture->scenegraphNode = X3D_NODE(tmp);
830 newTexture->textureNumber = textureNumber;
831 // save this to our texture table
832 vector_pushBack(textureTableIndexStruct_s *, p->activeTextureTable, newTexture);
833 }else{
834 //REMOVE
835 //we're using int indexes so we can't compact the vector to remove the element
836 //we need to flag it some how, and many functions use tti *getTableIndex(int num)
837 //and check if the returned value is null before trying to use it.
838 //we'll try using NULL as the signal its deleted.
839 textureTableIndexStruct_s * tti = NULL;
840 int *textureNumber = NULL;
841
842 releaseTexture(tmp); //Mar 23, 2015 added, to zap from gl texture name list (and its texture storage)
843 //otherwise for geoLOD and inline, the OS MEM usage keeps going up after unload/load cycle
844
845 switch (it->_nodeType) {
846 /* save this index in the scene graph node */
847 case NODE_ImageTexture:
848 textureNumber = &it->__textureTableIndex;
849 break;
850 case NODE_PixelTexture: {
851 struct X3D_PixelTexture *pt;
852 pt = (struct X3D_PixelTexture *) tmp;
853 textureNumber = &pt->__textureTableIndex;
854 break; }
855 case NODE_PixelTexture3D: {
856 struct X3D_PixelTexture3D *pt;
857 pt = (struct X3D_PixelTexture3D *) tmp;
858 textureNumber = &pt->__textureTableIndex;
859 break; }
860 case NODE_ImageTexture3D: {
861 struct X3D_ImageTexture3D *pt;
862 pt = (struct X3D_ImageTexture3D *) tmp;
863 textureNumber = &pt->__textureTableIndex;
864 break; }
865 case NODE_ComposedTexture3D: {
866 struct X3D_ComposedTexture3D *pt;
867 pt = (struct X3D_ComposedTexture3D *) tmp;
868 textureNumber = &pt->__textureTableIndex;
869 break; }
870 case NODE_MovieTexture: {
871 struct X3D_MovieTexture *mt;
872 mt = (struct X3D_MovieTexture *) tmp;
873 textureNumber = &mt->__textureTableIndex;
874 break; }
875
876 case NODE_ImageCubeMapTexture: {
877 struct X3D_ImageCubeMapTexture *v1t;
878 v1t = (struct X3D_ImageCubeMapTexture *) tmp;
879 textureNumber = &v1t->__textureTableIndex;
880 break; }
881
882 case NODE_GeneratedCubeMapTexture: {
883 struct X3D_GeneratedCubeMapTexture *v1t;
884 v1t = (struct X3D_GeneratedCubeMapTexture *) tmp;
885 textureNumber = &v1t->__textureTableIndex;
886 break; }
887 }
888 if(textureNumber){
889 tti = getTableIndex(*textureNumber);
890 if(tti){
891 // (*textureNumber) = -1; //is there a better flag?
892 vector_set(textureTableIndexStruct_s *,p->activeTextureTable,*textureNumber,NULL);
893 //unregister/unbind/deallocate anything else that was registered/bound/allocated above
894
895 //Problem: when unloading an inline (including geoLOD inlines) with images that haven't yet loaded,
896 // load_inline > unload_broto > unregister_broto_instance > unRegisterX3DAnyNode > unRegisterTexture > registerTexture0 (here)
897 // if we zap the tti, then when the resource thread finishes downloading the image and goes to paste
898 // into wheretoplacedata* which is a tti* that's been zapped, we crash.
899 //Solution:
900 // quick fix: don't zap tti here, leave a memory leak TRIED, WORKED AS BANDAID
901 // proper fix: redesign resource fetch so it has a way to check if tti still exists, IMPLEMENTED Dec5,2014
902 // for example, have it use the table index number instead of a pointer directly to *tti,
903 // and here leave a NULL in the table at that index so resource thread can check if its been zapped
904 FREE_IF_NZ(tti->texdata);
905 //->filename is not strduped, just a pointer to actual_file which is freed in resource
906 FREE_IF_NZ(tti);
907 }
908 }
909 }
910 } else {
911 //ConsoleMessage ("registerTexture, ignoring this node");
912 }
913}
914void registerTexture(struct X3D_Node *tmp) {
915 registerTexture0(1,tmp);
916}
917void unRegisterTexture(struct X3D_Node *tmp) {
918 registerTexture0(0,tmp);
919}
920
921void free_polyrep(struct X3D_PolyRep *rep);
922
923void unRegisterPolyRep(struct X3D_Node *tmp)
924{
925 if (tmp->_intern)
926 {
927 free_polyrep(tmp->_intern);
928 }
929}
930
931
932void add_node_to_broto_context(struct X3D_Proto *currentContext,struct X3D_Node *node);
933/* do TextureBackground textures, if possible */
934void reallyDraw();
935void push_render_geom(int igeom);
936void pop_render_geom();
937void loadBackgroundTextures (struct X3D_Background *node) {
938 struct X3D_ImageTexture *thistex;
939 struct X3D_TextureProperties *thistp;
940 struct Multi_String thisurl;
941 int count;
942
943 /* initialization */
944 struct textureVertexInfo mtf = {boxtex,2,GL_FLOAT,0,NULL,NULL};
945 thisurl.n = 0; thisurl.p = NULL;
946 thistex = NULL;
947
948 for (count=0; count<6; count++) {
949 /* go through these, back, front, top, bottom, right left */
950 switch (count) {
951 case 0: {thistex = X3D_IMAGETEXTURE(node->__frontTexture); thisurl = node->frontUrl; break;}
952 case 1: {thistex = X3D_IMAGETEXTURE(node->__backTexture); thisurl = node->backUrl; break;}
953 case 2: {thistex = X3D_IMAGETEXTURE(node->__topTexture); thisurl = node->topUrl; break;}
954 case 3: {thistex = X3D_IMAGETEXTURE(node->__bottomTexture); thisurl = node->bottomUrl; break;}
955 case 4: {thistex = X3D_IMAGETEXTURE(node->__rightTexture); thisurl = node->rightUrl; break;}
956 case 5: {thistex = X3D_IMAGETEXTURE(node->__leftTexture); thisurl = node->leftUrl; break;}
957 }
958 if (thisurl.n != 0 ) {
959 /* we might have to create a "shadow" node for the image texture */
960 if (thistex == NULL) {
961 int i;
962 thistex = createNewX3DNode(NODE_ImageTexture);
963 thistp = createNewX3DNode (NODE_TextureProperties);
964 if(node->_executionContext){
965 add_node_to_broto_context(X3D_PROTO(node->_executionContext),X3D_NODE(thistex));
966 add_node_to_broto_context(X3D_PROTO(node->_executionContext),X3D_NODE(thistp));
967 }
968
969 /* set up TextureProperties, and link it in */
970
971 /* we use the generic TextureProperties - especially the GenerateMipMaps flag... */
972 thistp->generateMipMaps = GL_FALSE; /* default settings, put here to ensure that */
973 /* future changes to the spec do no harm */
974
975 thistex->textureProperties = X3D_NODE(thistp);
976 ADD_PARENT(X3D_NODE(thistp), X3D_NODE(thistex));
977
978#ifdef TEXVERBOSE
979 printf ("bg, creating shadow texture node url.n = %d\n",thisurl.n);
980#endif
981
982 /* copy over the urls */
983 thistex->url.p = MALLOC(struct Uni_String **, sizeof (struct Uni_String) * thisurl.n);
984 for (i=0; i<thisurl.n; i++) {
985 thistex->url.p[i] = newASCIIString (thisurl.p[i]->strptr);
986 }
987 thistex->url.n = thisurl.n;
988
989 switch (count) {
990 case 0: {node->__frontTexture = X3D_NODE(thistex); break;}
991 case 1: {node->__backTexture = X3D_NODE(thistex); break;}
992 case 2: {node->__topTexture = X3D_NODE(thistex); break;}
993 case 3: {node->__bottomTexture = X3D_NODE(thistex); break;}
994 case 4: {node->__rightTexture = X3D_NODE(thistex); break;}
995 case 5: {node->__leftTexture = X3D_NODE(thistex); break;}
996 }
997 }
998
999 /* we have an image specified for this face */
1000 gglobal()->RenderFuncs.textureStackTop = 0;
1001 /* render the proper texture */
1002 push_render_geom(1);
1003 render_node(X3D_NODE(thistex));
1004 pop_render_geom();
1005 //OLDCODE FW_GL_COLOR3D(1.0,1.0,1.0);
1006 textureTransform_start();
1007 setupShaderB();
1008
1009 textureCoord_send(&mtf);
1010 FW_GL_VERTEX_POINTER(3,GL_FLOAT,0,BackgroundVert);
1011 FW_GL_NORMAL_POINTER(GL_FLOAT,0,Backnorms);
1012
1013 sendArraysToGPU (GL_TRIANGLES, count*6, 6);
1014 reallyDraw();
1015 textureTransform_end();
1016
1017 }
1018 }
1019}
1020/* do TextureBackground textures, if possible */
1021void loadTextureBackgroundTextures (struct X3D_TextureBackground *node) {
1022 struct X3D_Node *thistex = NULL;
1023 struct X3D_TextureProperties *thistp = NULL;
1024 int count;
1025 struct textureVertexInfo mtf = {boxtex,2,GL_FLOAT,0,NULL,NULL};
1026
1027 for (count=0; count<6; count++) {
1028 /* go through these, back, front, top, bottom, right left */
1029 switch (count) {
1030 case 0: {POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, node->frontTexture,thistex); break;}
1031 case 1: {POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, node->backTexture,thistex); break;}
1032 case 2: {POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, node->topTexture,thistex); break;}
1033 case 3: {POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, node->bottomTexture,thistex); break;}
1034 case 4: {POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, node->rightTexture,thistex); break;}
1035 case 5: {POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, node->leftTexture,thistex); break;}
1036 }
1037 if (thistex != 0) {
1038 /* we have an image specified for this face */
1039 /* the X3D spec says that a X3DTextureNode has to be one of... */
1040 if ((thistex->_nodeType == NODE_ImageTexture) ||
1041 (thistex->_nodeType == NODE_PixelTexture) ||
1042 (thistex->_nodeType == NODE_MovieTexture) ||
1043 (thistex->_nodeType == NODE_MultiTexture)) {
1044
1045 /* if we have no texture properties, add one here to disable mipmapping */
1046 switch (thistex->_nodeType) {
1047 case NODE_ImageTexture: {
1048 if (X3D_IMAGETEXTURE(thistex)->textureProperties == NULL) {
1049 thistp = createNewX3DNode (NODE_TextureProperties);
1050 if(node->_executionContext){
1051 add_node_to_broto_context(X3D_PROTO(node->_executionContext),X3D_NODE(thistp));
1052 }
1053 X3D_IMAGETEXTURE(thistex)->textureProperties = X3D_NODE(thistp);
1054 ADD_PARENT(X3D_NODE(thistp),thistex);
1055 }
1056 break;
1057 }
1058 case NODE_PixelTexture: {
1059 if (X3D_PIXELTEXTURE(thistex)->textureProperties == NULL) {
1060 thistp = createNewX3DNode (NODE_TextureProperties);
1061 if(node->_executionContext){
1062 add_node_to_broto_context(X3D_PROTO(node->_executionContext),X3D_NODE(thistp));
1063 }
1064
1065 X3D_PIXELTEXTURE(thistex)->textureProperties = X3D_NODE(thistp);
1066 ADD_PARENT(X3D_NODE(thistp),thistex);
1067 }
1068 break;
1069 }
1070
1071 case NODE_MovieTexture:
1072 case NODE_MultiTexture:
1073 break;
1074 };
1075
1076 gglobal()->RenderFuncs.textureStackTop = 0;
1077 /* render the proper texture */
1078 render_node((void *)thistex);
1079 //OLDCODE FW_GL_COLOR3D(1.0,1.0,1.0);
1080
1081 textureCoord_send(&mtf);
1082 FW_GL_VERTEX_POINTER(3,GL_FLOAT,0,BackgroundVert);
1083 FW_GL_NORMAL_POINTER(GL_FLOAT,0,Backnorms);
1084
1085 sendArraysToGPU (GL_TRIANGLES, count*6, 6);
1086 reallyDraw();
1087 }
1088 }
1089 }
1090}
1091
1092
1093/* load in a texture, if possible */
1094void loadTextureNode (struct X3D_Node *node, void *vparam)
1095{
1096 //printf ("loadTextureNode, node %p, params %p",node,param);
1097 if (NODE_NEEDS_COMPILING) {
1098
1099 DEBUG_TEX ("FORCE NODE RELOAD: %p %s\n", node, stringNodeType(node->_nodeType));
1100
1101 /* force a node reload - make it a new texture. Don't change
1102 the parameters for the original number, because if this
1103 texture is shared, then ALL references will change! so,
1104 we just accept that the current texture parameters have to
1105 be left behind. */
1106 MARK_NODE_COMPILED;
1107
1108 /* this will cause bind_image to create a new "slot" for this texture */
1109 /* cast to GLuint because __texture defined in VRMLNodes.pm as SFInt */
1110
1111 switch (node->_nodeType) {
1112
1113 case NODE_MovieTexture: {
1114 //releaseTexture(node);
1115 }
1116 break;
1117
1118 case NODE_PixelTexture:
1119 releaseTexture(node);
1120 break;
1121
1122 case NODE_ImageTexture:
1123 releaseTexture(node);
1124 break;
1125
1126 case NODE_ImageCubeMapTexture:
1127 releaseTexture(node);
1128 break;
1129
1130 case NODE_GeneratedCubeMapTexture:
1131 //releaseTexture(node);
1132 break;
1133
1134 case NODE_PixelTexture3D:
1135 releaseTexture(node);
1136 break;
1137 case NODE_ImageTexture3D:
1138 releaseTexture(node);
1139 break;
1140 case NODE_ComposedTexture3D:
1141 releaseTexture(node);
1142 break;
1143
1144 default: {
1145 printf ("loadTextureNode, unknown node type %s\n",stringNodeType(node->_nodeType));
1146 return;
1147 }
1148
1149 }
1150 }
1151
1152 new_bind_image (X3D_NODE(node), (struct multiTexParams *)vparam);
1153 return;
1154}
1155
1156static void compileMultiTexture (struct X3D_MultiTexture *node) {
1157 struct multiTexParams *paramPtr;
1158 int count;
1159 int max;
1160 s_renderer_capabilities_t *rdr_caps;
1161 ttglobal tg = gglobal();
1162 rdr_caps = tg->display.rdr_caps;
1163
1164 /* have to regen the shape*/
1165 MARK_NODE_COMPILED;
1166
1167 /* alloc fields, if required - only do this once, even if node changes */
1168 if (node->__xparams == 0) {
1169 /* printf ("loadMulti, MALLOCing for params\n"); */
1170 node->__xparams = MALLOC (void *, sizeof (struct multiTexParams) * rdr_caps->texture_units);
1171
1172 //printf ("just mallocd %ld in size for __params\n",sizeof (struct multiTexParams) * gglobal()->display.rdr_caps.texture_units);
1173
1174 //printf ("paramPtr is %p\n",(int *)node->__params);
1175
1176 paramPtr = (struct multiTexParams*) node->__xparams;
1177
1178 /* set defaults for these fields */
1179 for (count = 0; count < rdr_caps->texture_units; count++) {
1180 paramPtr->multitex_mode[0]= MTMODE_MODULATE; //rgba (or rgb if a > 0)
1181 paramPtr->multitex_mode[1]= 0; //0=unused -1=default else alpha channel part
1182 paramPtr->multitex_source[0]=INT_ID_UNDEFINED; //rgba (or rgb if a > 0)
1183 paramPtr->multitex_source[1]=0; //0=unused -1=default else alpha channel part
1184 paramPtr->multitex_function=INT_ID_UNDEFINED;
1185 paramPtr++;
1186 }
1187 }
1188
1189 /* how many textures can we use? no sense scanning those we cant use */
1190 //max = node->mode.n;
1191 max = node->texture.n;
1192 if (max > rdr_caps->texture_units) max = rdr_caps->texture_units;
1193
1194 // warn users that function and source parameters not looked at right now
1195 //if ((node->source.n>0) || (node->function.n>0)) {
1196 // ConsoleMessage ("currently, MultiTexture source and function parameters defaults used");
1197 //}
1198 /* go through the params, and change string name into an int */
1199 paramPtr = (struct multiTexParams*) node->__xparams;
1200 for (count = 0; count < max; count++) {
1201 char *smode, *ssource, *sfunc;
1202 smode = ssource = sfunc = NULL;
1203 if(node->mode.n>count){
1204 int mode, modea;
1205 smode = node->mode.p[count]->strptr;
1206 modea = 0; //unused
1207 mode = findFieldInMULTITEXTUREMODE(smode); //we offset by 1 in the #defines
1208 if(mode > -1) mode += 1; //one-based defines
1209 if(mode == -1){
1210 //might be Castle style "RGB / ALPHA" dual modes
1211 if(strchr(smode,'/') || strchr(smode,',')){
1212 //yes, castle protocol
1213 char *srgb, *salpha, *b1,*b2, *splittable;
1214 int modergb, modealpha;
1215 splittable = strdup(smode);
1216 b1 = strchr(splittable,' ');
1217 b2 = strrchr(splittable,' ');
1218 salpha = b2+1;
1219 splittable[b1 - splittable] = '\0';
1220 srgb = splittable;
1221 modergb = findFieldInMULTITEXTUREMODE(srgb);
1222 if(modergb == -1)
1223 modergb = MTMODE_MODULATE;
1224 else
1225 modergb +=1; //one-based defines
1226 modealpha = findFieldInMULTITEXTUREMODE(salpha);
1227 if(modealpha == -1)
1228 modealpha = MTMODE_MODULATE; //default
1229 else
1230 modealpha += 1; //one-based defines
1231 free(splittable);
1232 mode = modergb;
1233 modea = modealpha;
1234 }
1235 }
1236 if(mode > -1){
1237 paramPtr->multitex_mode[0] = mode;
1238 paramPtr->multitex_mode[1] = modea;
1239 }
1240 //else default
1241 }
1242 if(node->source.n > count) {
1243 int source, sourcea;
1244 ssource = node->source.p[count]->strptr;
1245 source = findFieldInMULTITEXTURESOURCE(ssource); //we offset by 1 in the #defines
1246 if(source > -1) source += 1; //one-based defines
1247 sourcea = 0; //0=unused
1248 if(source == -1){
1249 //might be Castle style "RGB / ALPHA" dual modes
1250 if(strchr(ssource,'/') || strchr(ssource,',')){
1251 //yes, castle protocol
1252 char *srgb, *salpha, *b1,*b2, *splittable;
1253 int sourcergb, sourcealpha;
1254 splittable = strdup(ssource);
1255 b1 = strchr(splittable,' ');
1256 b2 = strrchr(splittable,' ');
1257 salpha = b2+1;
1258 splittable[b1 - splittable] = '\0';
1259 srgb = splittable;
1260 sourcergb = findFieldInMULTITEXTURESOURCE(srgb);
1261 if(sourcergb == -1)
1262 sourcergb = INT_ID_UNDEFINED; //default
1263 else
1264 sourcergb +=1; //one-based defines
1265 sourcealpha = findFieldInMULTITEXTURESOURCE(salpha);
1266 free(splittable);
1267 source = sourcergb;
1268 sourcea = sourcealpha;
1269 }
1270 }
1271 if(source > -1){
1272 paramPtr->multitex_source[0] = source;
1273 paramPtr->multitex_source[1] = sourcea;
1274 }
1275 //else default
1276 }
1277
1278 if (node->function.n>count) {
1279 int ifunc;
1280 sfunc = node->function.p[count]->strptr;
1281 {
1282 ifunc = findFieldInMULTITEXTUREFUNCTION(sfunc);
1283 }
1284 if(ifunc > -1)
1285 paramPtr->multitex_function = ifunc;
1286 //else default
1287 }
1288
1289#ifdef TEXVERBOSE
1290printf ("compile_MultiTexture, %d of %d, mode %d %d source %d %d function %d m %s s %s f %s\n",
1291count,max,paramPtr->multitex_mode[0],paramPtr->multitex_mode[1],paramPtr->multitex_source[0],paramPtr->multitex_source[1],paramPtr->multitex_function,smode,ssource,sfunc);
1292#endif //TEXVERBOSE
1293
1294 paramPtr++;
1295 }
1296 //printf("end of compileMultiTexture\n");
1297}
1298
1299void loadMultiTexture (struct X3D_MultiTexture *node) {
1300 int count;
1301 int max;
1302 struct multiTexParams *paramPtr;
1303 struct X3D_ImageTexture *nt;
1304 s_renderer_capabilities_t *rdr_caps;
1305 ttglobal tg = gglobal();
1306 rdr_caps = tg->display.rdr_caps;
1307
1308#ifdef TEXVERBOSE
1309 printf ("loadMultiTexture, this %s has %d textures %x %x\n",stringNodeType(node->_nodeType),
1310 node->texture.n,
1311 (int) node->texture.p[0], (int) node->texture.p[1]);
1312 printf (" change %d ichange %d\n",node->_change, node->_ichange);
1313#endif
1314
1315 /* new node, or node paramaters changed */
1316 if (NODE_NEEDS_COMPILING) {
1317 compileMultiTexture(node);
1318 }
1319
1320 /* ok, normally the scene graph contains function pointers. What we have
1321 here is a set of pointers to datastructures of (hopefully!)
1322 types like X3D_ImageTexture, X3D_PixelTexture, and X3D_MovieTexture.
1323
1324 */
1325
1326 /* how many textures can we use? */
1327 max = node->texture.n;
1328 //printf ("texture.n %d, texture_units %d, MAX_MULTITEXTURE %d\n", node->texture.n, gglobal()->display.rdr_caps.texture_units, MAX_MULTITEXTURE);
1329
1330 if (max > rdr_caps->texture_units) max = rdr_caps->texture_units;
1331 if (max > MAX_MULTITEXTURE) max = MAX_MULTITEXTURE;
1332
1333
1334 /* go through and get all of the textures */
1335 paramPtr = (struct multiTexParams *) node->__xparams;
1336
1337#ifdef TEXVERBOSE
1338 printf ("loadMultiTExture, param stack:\n");
1339 for (count=0; count<max; count++) {
1340 printf (" tex %d source %d mode %d\n",count,paramPtr[count].multitex_source,paramPtr[count].multitex_mode);
1341 }
1342#endif
1343
1344 for (count=0; count < max; count++) {
1345#ifdef TEXVERBOSE
1346 printf ("loadMultiTexture, working on texture %d\n",count);
1347#endif
1348
1349 /* get the texture */
1350 nt = X3D_IMAGETEXTURE(node->texture.p[count]);
1351
1352 switch (nt->_nodeType) {
1353 case NODE_PixelTexture:
1354 case NODE_ImageTexture :
1355 /* printf ("MultiTexture %d is a ImageTexture param %d\n",count,*paramPtr); */
1356 loadTextureNode (X3D_NODE(nt),paramPtr);
1357 break;
1358 case NODE_MultiTexture:
1359 printf ("MultiTexture texture %d is a MULTITEXTURE!!\n",count);
1360 break;
1361 default:
1362 printf ("MultiTexture - unknown sub texture type %d\n",
1363 nt->_nodeType);
1364 }
1365
1366 /* now, lets increment textureStackTop. The current texture will be
1367 stored in boundTextureStack[textureStackTop]; textureStackTop will be 1
1368 for "normal" textures; at least 1 for MultiTextures. */
1369
1370 tg->RenderFuncs.textureStackTop++;
1371
1372
1373
1374 paramPtr++;
1375
1376#ifdef TEXVERBOSE
1377 printf ("loadMultiTexture, textureStackTop %d\n",gglobal()->RenderFuncs.textureStackTop);
1378 printf ("loadMultiTexture, finished with texture %d\n",count);
1379#endif
1380 }
1381 //tg->RenderFuncs.multitexturenode = (void*)node;
1382}
1383
1384int getTextureDescriptors(struct X3D_Node *textureNode, int *textures, int *modes, int *sources, int *funcs, int *width, int *height){
1385 int ntexture = 0;
1386 if( textureNode == NULL) return 0;
1387 if(textureNode->_nodeType == NODE_MultiTexture){
1388 struct multiTexParams *xparam;
1389 struct X3D_MultiTexture* pt = (struct X3D_MultiTexture*) textureNode;
1390 xparam = (struct multiTexParams *)pt->__xparams;
1391 ntexture = pt->texture.n;
1392 for(int i=0;i<ntexture;i++){
1393 int iret, ixyz[3];
1394
1395 textures[i] = getGlTextureNumberFromTextureNode(pt->texture.p[i]);
1396 iret = getTextureSizeFromTextureNode(pt->texture.p[i],ixyz);
1397
1398 modes[i] = xparam[i].multitex_mode[0] + + 100*xparam[i].multitex_mode[1];
1399 sources[i] = xparam[i].multitex_source[0] + 100*xparam[i].multitex_source[1];
1400 funcs[i] = xparam[i].multitex_function;
1401 }
1402 }else{
1403 //single texture, use web3d default texture descriptor
1404 int iret, ixyz[3];
1405 ntexture = 1;
1406 textures[0] = getGlTextureNumberFromTextureNode(textureNode);
1407 //web3d.org defaults? not sure, I think its replace
1408 modes[0] = MTMODE_REPLACE;
1409 sources[0] = INT_ID_UNDEFINED;
1410 funcs[0] = INT_ID_UNDEFINED;
1411 iret = getTextureSizeFromTextureNode(textureNode,ixyz);
1412 width[0] = ixyz[0];
1413 height[0] = ixyz[1];
1414 }
1415 return ntexture;
1416}
1417
1418
1419#define BOUNDARY_TO_GL(direct) \
1420 switch (findFieldInTEXTUREBOUNDARYKEYWORDS(tpNode->boundaryMode##direct->strptr)) { \
1421 case TB_CLAMP: direct##rc=GL_CLAMP; break; \
1422 case TB_CLAMP_TO_EDGE: direct##rc=GL_CLAMP_TO_EDGE; break; \
1423 case TB_CLAMP_TO_BOUNDARY: direct##rc=GL_CLAMP_TO_BORDER; break; \
1424 case TB_MIRRORED_REPEAT: direct##rc=GL_MIRRORED_REPEAT; break; \
1425 case TB_REPEAT: direct##rc=GL_REPEAT; break; \
1426 default: direct##rc = GL_REPEAT; \
1427 }
1428
1429/* do we do 1 texture, or is this a series of textures, requiring final binding
1430 by this thread? */
1431#define DEF_FINDFIELD(arr) \
1432 static int findFieldIn##arr(const char* field) \
1433 { \
1434 return findFieldInARR(field, arr, arr##_COUNT); \
1435 }
1436
1437DEF_FINDFIELD(TEXTUREMINIFICATIONKEYWORDS)
1438DEF_FINDFIELD(TEXTUREMAGNIFICATIONKEYWORDS)
1439DEF_FINDFIELD(TEXTUREBOUNDARYKEYWORDS)
1440DEF_FINDFIELD(TEXTURECOMPRESSIONKEYWORDS)
1441
1442void unpackImageCubeMap6 (textureTableIndexStruct_s* me);
1443void move_texture_to_opengl(textureTableIndexStruct_s* me) {
1444 int rx,ry,rz,sx,sy,sz;
1445 int x,y,z;
1446 GLint iformat;
1447 GLenum format;
1448
1449 /* default texture properties; can be changed by a TextureProperties node */
1450 float anisotropicDegree=1.0f;
1451 int borderWidth;
1452
1453 GLint Trc,Src,Rrc;
1454 GLint minFilter, magFilter;
1455 GLint compression;
1456 int generateMipMaps;
1457
1458 unsigned char *mytexdata;
1459
1460 // JAS - if multi-threading using a creation program,
1461 // we can have issues sending textures here, so
1462 // single thread this.
1463 #ifdef PATH_PLANNER
1464 pthread_mutex_t gl_mutex1 = PTHREAD_MUTEX_INITIALIZER;
1465 #endif //PATH_PLANNER
1466
1467 /* for getting repeatS and repeatT info. */
1468 struct X3D_PixelTexture *pt = NULL;
1469 struct X3D_MovieTexture *mt = NULL;
1470 struct X3D_ImageTexture *it = NULL;
1471 struct X3D_PixelTexture3D *pt3d = NULL;
1472
1473 struct X3D_TextureProperties *tpNode = NULL;
1474 int haveValidTexturePropertiesNode;
1475 GLfloat texPri;
1476 struct SFColorRGBA borderColour;
1477 s_renderer_capabilities_t *rdr_caps;
1478
1479 #ifdef PATH_PLANNER
1480 pthread_mutex_lock( &gl_mutex1 );
1481 #endif //PATH_PLANNER
1482
1483 ttglobal tg = gglobal();
1484 rdr_caps = tg->display.rdr_caps;
1485
1486
1487 /* initialization */
1488 Src = FALSE; Trc = FALSE; Rrc = FALSE;
1489 tpNode = NULL;
1490 haveValidTexturePropertiesNode = FALSE;
1491 texPri=0.0f;
1492 borderColour.c[0]=0.0f;borderColour.c[1]=0.0f;borderColour.c[2]=0.0f;borderColour.c[3]=0.0f;
1493 compression = GL_FALSE;
1494 borderWidth = 0;
1495 mytexdata = NULL;
1496
1497 /* did this node get killed on the way here? */
1498 if (!checkNode(me->scenegraphNode, __FILE__,__LINE__)) {
1499 ConsoleMessage ("main node disappeared, ignoring texture\n");
1500 me->status = TEXTURE_INVALID;
1501
1502 #ifdef PATH_PLANNER
1503 pthread_mutex_unlock( &gl_mutex1 );
1504 #endif //PATH_PLANNER
1505
1506 return;
1507 }
1508 /* printf ("move_texture_to_opengl, node of type %s\n",stringNodeType(me->scenegraphNode->_nodeType)); */
1509
1510 /* is this texture invalid and NOT caught before here? */
1511 /* this is the same as the defaultBlankTexture; the following code should NOT be executed */
1512 if (me->texdata == NULL) {
1513 char buff[] = {0x70, 0x70, 0x70, 0xff} ; /* same format as ImageTextures - GL_BGRA or GL_RGBA here */
1514 me->x = 1;
1515 me->y = 1;
1516 me->z = 1;
1517 me->hasAlpha = FALSE;
1518 me->texdata = MALLOC(unsigned char *, 4);
1519 memcpy (me->texdata, buff, 4);
1520 }
1521
1522 /* do we need to convert this to an OpenGL texture stream?*/
1523
1524//printf ("JAS - moveTex, texture %d, TEXTURE_INVALID %d at %s:%d\n",me->OpenGLTexture,TEXTURE_INVALID,__FILE__,__LINE__);
1525
1526 /* we need to get parameters. */
1527 if (me->OpenGLTexture == TEXTURE_INVALID) {
1528/* me->OpenGLTexture = MALLOC (GLuint *, sizeof (GLuint) * me->frames); */
1529 if ((getAppearanceProperties()->cubeFace==0) || (getAppearanceProperties()->cubeFace == GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT)) {
1530 FW_GL_GENTEXTURES (1, &me->OpenGLTexture);
1531 }
1532
1533#ifdef TEXVERBOSE
1534 printf ("just glGend texture for block %p is %u, type %s\n",
1535 me, me->OpenGLTexture,stringNodeType(me->nodeType));
1536#endif
1537
1538 }
1539
1540 /* get the repeatS and repeatT info from the scenegraph node */
1541 if (me->nodeType == NODE_ImageTexture) {
1542 it = (struct X3D_ImageTexture *) me->scenegraphNode;
1543 Src = it->repeatS; Trc = it->repeatT;
1544 tpNode = X3D_TEXTUREPROPERTIES(it->textureProperties);
1545 } else if (me->nodeType == NODE_PixelTexture) {
1546 pt = (struct X3D_PixelTexture *) me->scenegraphNode;
1547 Src = pt->repeatS; Trc = pt->repeatT;
1548 tpNode = X3D_TEXTUREPROPERTIES(pt->textureProperties);
1549 } else if (me->nodeType == NODE_MovieTexture) {
1550 mt = (struct X3D_MovieTexture *) me->scenegraphNode;
1551 Src = mt->repeatS; Trc = mt->repeatT;
1552 tpNode =X3D_TEXTUREPROPERTIES(mt->textureProperties);
1553 } else if (me->nodeType == NODE_PixelTexture3D) {
1554 pt3d = (struct X3D_PixelTexture3D *) me->scenegraphNode;
1555 Src = pt3d->repeatS; Trc = pt3d->repeatT; Rrc = pt3d->repeatR;
1556 tpNode = X3D_TEXTUREPROPERTIES(pt3d->textureProperties);
1557 } else if (me->nodeType == NODE_ImageTexture3D) {
1558 struct X3D_ImageTexture3D * it3d;
1559 it3d = (struct X3D_ImageTexture3D *) me->scenegraphNode;
1560 Src = it3d->repeatS; Trc = it3d->repeatT; Rrc = it3d->repeatR;
1561 tpNode = X3D_TEXTUREPROPERTIES(it3d->textureProperties);
1562 } else if (me->nodeType == NODE_ComposedTexture3D) {
1563 struct X3D_ComposedTexture3D * ct3d;
1564 ct3d = (struct X3D_ComposedTexture3D *) me->scenegraphNode;
1565 Src = ct3d->repeatS; Trc = ct3d->repeatT; Rrc = ct3d->repeatR;
1566 tpNode = X3D_TEXTUREPROPERTIES(ct3d->textureProperties);
1567 } else if (me->nodeType == NODE_ImageCubeMapTexture) {
1568 struct X3D_ImageCubeMapTexture *mi = (struct X3D_ImageCubeMapTexture *) me->scenegraphNode;
1569 tpNode = X3D_TEXTUREPROPERTIES(mi->textureProperties);
1570 } else if (me->nodeType == NODE_GeneratedCubeMapTexture) {
1571 struct X3D_GeneratedCubeMapTexture *mi = (struct X3D_GeneratedCubeMapTexture *) me->scenegraphNode;
1572 tpNode = X3D_TEXTUREPROPERTIES(mi->textureProperties);
1573 }
1574 //texure3D faked via texture2D (in non-extended GLES2)
1575 //.. needs repeats for manual wrap vs clamp, will send in
1576 //.. passedInGenTex
1577 me->repeatSTR[0] = Src;
1578 me->repeatSTR[1] = Trc;
1579 me->repeatSTR[2] = Rrc;
1580
1581
1582 /* do we have a TextureProperties node? */
1583 if (tpNode) {
1584 if (tpNode->_nodeType != NODE_TextureProperties) {
1585 ConsoleMessage ("have a %s as a textureProperties node",stringNodeType(tpNode->_nodeType));
1586 } else {
1587 haveValidTexturePropertiesNode = TRUE;
1588 generateMipMaps = tpNode->generateMipMaps?GL_TRUE:GL_FALSE;
1589 texPri = tpNode->texturePriority;
1590 if ((texPri < 0.0) || (texPri>1.0)) {
1591 texPri = 0.0f;
1592 ConsoleMessage ("invalid texturePriority of %f",tpNode->texturePriority);
1593 }
1594 memcpy(&borderColour,&(tpNode->borderColor),sizeof(struct SFColorRGBA));
1595
1596 anisotropicDegree = tpNode->anisotropicDegree;
1597 if ((anisotropicDegree < 1.0) || (anisotropicDegree>rdr_caps->anisotropicDegree)) {
1598 /* we can be quiet here
1599 ConsoleMessage ("anisotropicDegree error %f, must be between 1.0 and %f",anisotropicDegree, gglobal()->display.rdr_caps.anisotropicDegree);
1600 */
1601 anisotropicDegree = rdr_caps->anisotropicDegree;
1602 }
1603
1604 borderWidth = tpNode->borderWidth;
1605 if (borderWidth < 0) borderWidth=0;
1606 if (borderWidth>1) borderWidth = 1;
1607
1608 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/texturing.html#t-TextureMagnificationModes
1609
1610 switch (findFieldInTEXTUREMAGNIFICATIONKEYWORDS(tpNode->magnificationFilter->strptr)) {
1611 case TMAG_AVG_PIXEL:
1612 magFilter = GL_LINEAR; break; // GL_NEAREST; break;
1613 case TMAG_DEFAULT: magFilter = GL_LINEAR; break;
1614 case TMAG_FASTEST: magFilter = GL_LINEAR; break; /* DEFAULT */
1615 case TMAG_NEAREST_PIXEL: magFilter = GL_NEAREST; break;
1616 case TMAG_NICEST: magFilter = GL_NEAREST; break;
1617 default: magFilter = GL_NEAREST; ConsoleMessage ("unknown magnification filter %s",
1618 tpNode->magnificationFilter->strptr);
1619 }
1620
1621 /* minFilter depends on Mipmapping */
1622 if (generateMipMaps) switch (findFieldInTEXTUREMINIFICATIONKEYWORDS(tpNode->minificationFilter->strptr)) {
1623 case TMIN_AVG_PIXEL: minFilter = GL_NEAREST; break;
1624 case TMIN_AVG_PIXEL_AVG_MIPMAP: minFilter = GL_NEAREST_MIPMAP_NEAREST; break;
1625 case TMIN_AVG_PIXEL_NEAREST_MIPMAP: minFilter = GL_NEAREST_MIPMAP_NEAREST; break;
1626 case TMIN_DEFAULT: minFilter = GL_NEAREST_MIPMAP_LINEAR; break;
1627 case TMIN_FASTEST: minFilter = GL_NEAREST_MIPMAP_LINEAR; break;
1628 case TMIN_NICEST: minFilter = GL_NEAREST_MIPMAP_NEAREST; break;
1629 case TMIN_NEAREST_PIXEL: minFilter = GL_NEAREST; break;
1630 case TMIN_NEAREST_PIXEL_NEAREST_MIPMAP: minFilter = GL_NEAREST_MIPMAP_LINEAR; break;
1631 default: minFilter = GL_NEAREST_MIPMAP_NEAREST;
1632 ConsoleMessage ("unknown minificationFilter of %s",
1633 tpNode->minificationFilter->strptr);
1634 }
1635 else switch (findFieldInTEXTUREMINIFICATIONKEYWORDS(tpNode->minificationFilter->strptr)) {
1636 case TMIN_AVG_PIXEL:
1637 case TMIN_AVG_PIXEL_AVG_MIPMAP:
1638 case TMIN_AVG_PIXEL_NEAREST_MIPMAP:
1639 case TMIN_DEFAULT:
1640 case TMIN_FASTEST:
1641 case TMIN_NICEST:
1642 case TMIN_NEAREST_PIXEL: minFilter = GL_NEAREST; break;
1643 case TMIN_NEAREST_PIXEL_NEAREST_MIPMAP: minFilter = GL_LINEAR; break;
1644 default: minFilter = GL_NEAREST;
1645 ConsoleMessage ("unknown minificationFilter of %s",
1646 tpNode->minificationFilter->strptr);
1647 }
1648
1649 switch (findFieldInTEXTURECOMPRESSIONKEYWORDS(tpNode->textureCompression->strptr)) {
1650 case TC_DEFAULT: compression = GL_FASTEST; break;
1651 case TC_FASTEST: compression = GL_NONE; break; /* DEFAULT */
1652 case TC_HIGH: compression = GL_FASTEST; break;
1653 case TC_LOW: compression = GL_NONE; break;
1654 case TC_MEDIUM: compression = GL_NICEST; break;
1655 case TC_NICEST: compression = GL_NICEST; break;
1656
1657 default: compression = GL_NEAREST_MIPMAP_NEAREST;
1658 ConsoleMessage ("unknown textureCompression of %s",
1659 tpNode->textureCompression->strptr);
1660 }
1661
1662 BOUNDARY_TO_GL(S);
1663 BOUNDARY_TO_GL(T);
1664 BOUNDARY_TO_GL(R);
1665 }
1666 }
1667
1668
1669
1670 if (!haveValidTexturePropertiesNode) {
1671
1672 /* convert TRUE/FALSE to GL_TRUE/GL_FALSE for wrapS and wrapT */
1673 Src = Src ? GL_REPEAT : GL_CLAMP_TO_EDGE; //GL_CLAMP; //du9 changed from CLAMP to CLAMP_TO_EDGE Sept18,2011 to fix panorama seamline visibility
1674 Trc = Trc ? GL_REPEAT : GL_CLAMP_TO_EDGE; //GL_CLAMP;
1675 Rrc = Rrc ? GL_REPEAT : GL_CLAMP_TO_EDGE; //GL_CLAMP
1676
1677 generateMipMaps = GL_TRUE;
1678
1679 if(me->x > 0 && me->y > 0)
1680 {
1681 // experimental code to deal with oblong texture images
1682 // The 'cause' of blurry oblong textures with GLES2 is the anisotropic
1683 // scaling of the image needed to square up the image for mipmapping.
1684 // For example if your texture image is oblong by a factor of 3, then
1685 // your avatar will need to be 3 times closer to the object to see the
1686 // same mipmap level as you would with an unscaled image.
1687 // (OpenGL redbook talks about MipMap levels and rho and lambda.)
1688 // here we detect if there's big anisotropic scaling/squaring coming up,
1689 // and if so turn off mipmapping and squaring
1690 // scene authors need to make their repeating textures (brick, siding,
1691 // shingles etc) squarish to get mipmapping and avoid moire/scintilation
1692 float ratio = 1.0f;
1693 if(me->x < me->y*me->z) ratio = (float)(me->y*me->z) / (float)me->x;
1694 else ratio = (float)me->x / (float)(me->y*me->z);
1695 if(ratio > 2.0f) generateMipMaps = GL_FALSE;
1696 }
1697
1698 /* choose smaller images to be NEAREST, larger ones to be LINEAR */
1699 if ((me->x<=256) || ((me->y*me->z)<=256)) {
1700 minFilter = GL_NEAREST_MIPMAP_NEAREST;
1701 if(!generateMipMaps) minFilter = GL_NEAREST;
1702 magFilter = GL_NEAREST;
1703 } else {
1704 minFilter = GL_LINEAR_MIPMAP_NEAREST;
1705 if(!generateMipMaps) minFilter = GL_LINEAR;
1706 magFilter = GL_LINEAR;
1707 }
1708 }
1709
1710 //ConsoleMessage ("move_texture_to_opengl cubeFace %x\n",getAppearanceProperties()->cubeFace);
1711
1712 /* is this a CubeMap? If so, lets try this... */
1713 //if(0){
1714 // printf("before texture to GPU and mipmapping thread=%x time = %lf\n",pthread_self().p,Time1970sec());
1715 //}
1716
1717
1718 if (getAppearanceProperties()->cubeFace != 0) {
1719 //this is a single cubmap face pixeltexture tti (ie from __subTextures in ImageCubemap)
1720 unsigned char *dest = me->texdata;
1721 uint32 *sp;
1722
1723 int cx;
1724
1725
1726 //#if defined (GL_BGRA)
1727 //iformat = GL_RGBA; format = GL_BGRA;
1728 //#else
1729 iformat = GL_RGBA; format = GL_RGBA;
1730 //#endif
1731
1732
1733 /* first image in the ComposedCubeMap, do some setups */
1734 if (getAppearanceProperties()->cubeFace == GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT) {
1735 FW_GL_TEXPARAMETERI(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1736 FW_GL_TEXPARAMETERI(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1737 FW_GL_TEXPARAMETERI(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1738 FW_GL_TEXPARAMETERI(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1739 FW_GL_TEXPARAMETERI(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
1740 }
1741
1742 rx = me->x;
1743 ry = me->y;
1744 dest = me->texdata;
1745 if(1){
1746 //flip cubemap textures to be y-down following opengl specs table 3-19
1747 //'renderman' convention
1748 //stack method: row chunks at a time
1749 uint32 tp[512];
1750 int cy, cyy, icsize;
1751 sp = (uint32 *) me->texdata;
1752 for (cy=0; cy<ry/2; cy++) {
1753 cyy = ry - cy -1;
1754 for(cx=0;cx<rx;cx+=512){
1755 icsize = min(512,rx-cx-1)*4;
1756 memcpy(tp,&sp[cy*rx + cx],icsize);
1757 memcpy(&sp[cy*rx + cx],&sp[cyy*rx + cx],icsize);
1758 memcpy(&sp[cyy*rx + cx],tp,icsize);
1759 }
1760 }
1761 //printf("__flipping__\n"); //are we in here on every frame? yes, for generatedcubemaptexture, no for other cubemaps
1762 }
1763 generateMipMaps = 0;
1764 myTexImage2D(generateMipMaps, getAppearanceProperties()->cubeFace, 0, iformat, rx, ry, 0, format, GL_UNSIGNED_BYTE, dest);
1765
1766 /* last thing to do at the end of the setup for the 6th face */
1767 if (getAppearanceProperties()->cubeFace == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) {
1768 glEnable(GL_TEXTURE_CUBE_MAP);
1769 glEnable(GL_TEXTURE_GEN_S);
1770 glEnable(GL_TEXTURE_GEN_T);
1771 glEnable(GL_TEXTURE_GEN_R);
1772 }
1773
1774 } else {
1775
1776 if (me->nodeType == NODE_ImageCubeMapTexture) {
1777 if(me->z == 1){
1778 /* if we have an single 2D image, ImageCubeMap, we have most likely got a png map;
1779 ________
1780 | T | - Top
1781 |L F R B| - Left, Front, Right, Back
1782 |__D____| - Down(bottom)
1783 let the render_ImageCubeMapTexture code unpack the maps from this one png */
1784 /* this is ok - what is happening is that we have one image, that needs to be
1785 split up into each face */
1786 /* this should print if we are actually working ok
1787 if (me->status != TEX_LOADED) {
1788 printf ("have ImageCubeMapTexture, but status != TEX_LOADED\n");
1789 }
1790 */
1791
1792 /* call the routine in Component_CubeMapTexturing.c to split this baby apart */
1793 unpackImageCubeMap(me);
1794 me->status = TEX_LOADED; /* finito */
1795 }else if(me->z == 6){
1796 //likely a .DDS (MS invention) or web3dit (dug9 invention)
1797 //order of images: +x,-x,+y,-y,+z,-z (or R,L,F,B,T,D)
1798 unpackImageCubeMap6(me);
1799 me->status = TEX_LOADED; /* finito */
1800 }
1801 //now the __subTextures individual face textures will show as single faces above
1802 } else if(me->nodeType == NODE_GeneratedCubeMapTexture){
1803 //already unpacked into 6 separate PixelTexture tti->texdata during cubemap generation
1804 me->status = TEX_LOADED; /* finito */
1805 } else {
1806 int npot;
1807 /* a pointer to the tex data. We increment the pointer for movie texures */
1808 mytexdata = me->texdata;
1809 if (mytexdata == NULL) {
1810 printf ("mytexdata is null, texture failed, put something here\n");
1811 }
1812
1813 glBindTexture (GL_TEXTURE_2D, me->OpenGLTexture);
1814
1815 /* save this to determine whether we need to do material node
1816 within appearance or not */
1817
1818 /*
1819 repeatS,repeatT,repeatR
1820 https://open.gl/textures
1821 how the texture should be sampled when a coordinate outside the range of 0to 1 is given
1822 - repeat (*1)
1823 - mirrored repeat
1824 - clamp to edge (*2)
1825 - clamp to border
1826 subset of opengl supported by web3d:
1827 http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/texturing.html#Texturecoordinates
1828 (*1) If repeatS is TRUE (the default), the texture map is repeated outside
1829 the [0.0, 1.0] texture coordinate range in the S direction so that it fills the shape.
1830 (*2) If repeatS is FALSE, the texture coordinates are clamped in the S direction to lie
1831 within the [0.0, 1.0] range.
1832 */
1833
1834 FW_GL_TEXPARAMETERI( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, Src);
1835 FW_GL_TEXPARAMETERI( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, Trc);
1836#if !defined(GL_ES_VERSION_2_0)
1837 FW_GL_TEXPARAMETERI( GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, Rrc);
1838 FW_GL_TEXPARAMETERF(GL_TEXTURE_2D,GL_TEXTURE_PRIORITY, texPri);
1839 FW_GL_TEXPARAMETERFV(GL_TEXTURE_2D,GL_TEXTURE_BORDER_COLOR,(GLfloat *)&borderColour);
1840#endif /* GL_ES_VERSION_2_0 */
1841
1842#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
1843 FW_GL_TEXPARAMETERF(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,anisotropicDegree);
1844#endif
1845
1846 if (compression != GL_NONE) {
1847 FW_GL_TEXPARAMETERI(GL_TEXTURE_2D, GL_TEXTURE_INTERNAL_FORMAT, GL_COMPRESSED_RGBA);
1848 glHint(GL_TEXTURE_COMPRESSION_HINT, compression);
1849 }
1850 npot = rdr_caps->av_npot_texture;
1851 x = me->x;
1852 y = me->y; // * me->z; //takes care of texture3D using strip image
1853 z = me->z;
1854
1855 FW_GL_TEXPARAMETERI( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
1856 FW_GL_TEXPARAMETERI( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
1857 me->magFilter = magFilter == GL_LINEAR ? 1 : 0; //needed in frag shader for TEX3D simulation of texture3D with texture2D
1858
1859 /* BGRA is seemingly faster on desktop machines... */
1860 //#if defined (GL_BGRA)
1861 //iformat = GL_RGBA; format = GL_BGRA;
1862 //#else
1863 iformat = GL_RGBA; format = GL_RGBA;
1864 //#endif
1865
1866 /* do the image. */
1867 if(x && y) {
1868 unsigned char *dest = mytexdata;
1869
1870 /* do we have to do power of two textures? */
1871 if (npot) { //rdr_caps->av_npot_texture) {
1872 rx = x; ry = y; rz = z;
1873 } else {
1874 /* find a power of two that fits */
1875 static int round_down = 1;
1876 static int trunc_down = 0;
1877 rx = 1;
1878 sx = x;
1879 while(sx) {sx /= 2; rx *= 2;}
1880 if(rx/2 == x) {rx /= 2;}
1881 //if its just a few pixels over a power of 2, round down
1882 if(round_down)
1883 if(x < rx && (float)(x - rx/2)/(float)(rx - rx/2) < .25) rx = rx/2;
1884 //or we might only scale down, never up, if we don't want to malloc again
1885 if(trunc_down)
1886 if(x < rx) rx = rx/2;
1887 ry = 1;
1888 sy = y;
1889 while(sy) {sy /= 2; ry *= 2;}
1890 if(ry/2 == y) {ry /= 2;}
1891 if(round_down)
1892 if(y < ry && (float)(y - ry/2)/(float)(ry - ry/2) < .25) ry = ry/2;
1893 if(trunc_down)
1894 if(y < ry) ry = ry/2;
1895
1896 rz = 1;
1897 sz = z;
1898 while(sz) {sz /= 2; rz *= 2;}
1899 if(rz/2 == z) {rz /= 2;}
1900 if(round_down)
1901 if(z < rz && (float)(z - rz/2)/(float)(rz - rz/2) < .25) rz = rz/2;
1902 if(trunc_down)
1903 if(z < rz) rz = rz/2;
1904 }
1905
1906 if (gglobal()->internalc.global_print_opengl_errors) {
1907 DEBUG_MSG("initial texture scale to %d %d\n",rx,ry);
1908 }
1909
1910 //ConsoleMessage ("loadTextureNode, runtime texture size %d",gglobal()->display.rdr_caps.runtime_max_texture_size);
1911 if(z > 1){
1912 //its a texture3D / volume image
1913 int emulating3D_TILED;
1914 emulating3D_TILED = TRUE;
1915 generateMipMaps = FALSE;
1916 if(emulating3D_TILED){
1917 //tiled uses more of the max_texture_size x max_texture_size
1918 // texture3D emulator via TILED texture2D
1919 // reason for emulating: 2016 GLES2 via ANGLEPROJECT(gles emulator over DirectX on windows)
1920 // doesn't have Texture3D or Texture3DOES or Texture3DEXT.
1921 // reason for TILES: an oblong Y-STRIP approach exceded max texture size in Y (but had lots left in X)
1922 // desktop computer max_size (of 2D image in one dimension) 16384
1923 // android phone max_size 4096
1924 // and so would be resampled (blurry) in y and good in x
1925 // using tiles means room for more full z slices ie 256x256x256 == 4096x4096 == 16M,
1926 // 512x512x512 == 134M == 16384x16384/2, and therefore less blurry images
1927 // tiles start in upper left with z=0, increase in y,
1928 // then when hit ny tiles in a y strip, move right one tile, and restart at top
1929 // uniform tex3dTiles[3] = {nx,ny,z}
1930 // example ny = 4, nx = 3, z = 11
1931 // 1 5 9
1932 // 2 6 10
1933 // 3 7 11
1934 // 4 8
1935 //
1936 //
1937 int rc,sc,c,cube_root, max_size;
1938 unsigned char *texdataTiles = NULL;
1939 uint32 *p2, *p1;
1940 int nx, ny, ix, iy, nxx, nyy;
1941 int iz,j,k;
1942
1943 max_size = rdr_caps->runtime_max_texture_size;
1944 //if(32bit) I find process doesn't have enough RAM left for opengl to malloc 512x512x512x4byte.
1945 //could try single channel, single byte textures, but for now we'll keep it under 17M pixels
1946 if(x * y * z > 256 * 256 * 256)
1947 max_size = min(max_size,4096);
1948 //max_size = 2048; //can re-set here for experiments
1949 cube_root = (int)pow( max_size * max_size + 3, 1.0/3.0);
1950 c = cube_root;
1951 //need lower-power-of-two so we squeeze into space available, and leave a little
1952 rc = 1;
1953 sc = c;
1954 while(sc) {sc /= 2; rc *= 2;}
1955 if(rc > c) {rc /= 2;}
1956 //ConsoleMessage("pow2 cube root %d\n",rc);
1957 cube_root = rc;
1958 if(rx != x || ry != y || rz != z || rx > cube_root || ry > cube_root || rz > cube_root) {
1959 /* do we have texture limits???
1960 dug9: windows intel i5: desktop opengl and uwp/angleproject 16384
1961 16384 x 16394 = 268M. cube-root 268M = 645.xx lets round down to pow2: 512
1962 android LG nexus 4096
1963 4096 x 4096 = 16.7M; cube-root 16.7M = 256.
1964 */
1965 if (rx > cube_root) rx = cube_root;
1966 if (ry > cube_root) ry = cube_root;
1967 if (rz > cube_root) rz = cube_root;
1968 }
1969
1970 if (gglobal()->internalc.global_print_opengl_errors) {
1971 DEBUG_MSG("texture size after maxTextureSize taken into account: %d %d, from %d %d\n",rx,ry,x,y);
1972 }
1973 //ConsoleMessage("texture size after maxTextureSize taken into account: %d %d %d, from %d %d %d\n",rx,ry,rz,x,y,z);
1974
1975 //rescale sub-images if/as needed
1976 dest = mytexdata;
1977 //if(rx != x || ry != y || rz != z){
1978 //if(rx > x || ry > y || rz > z){
1979 if(x > rx || y > ry || z > rz){
1980 int mx,my,mz;
1981 mx = min(x,rx);
1982 my = min(y,ry);
1983 mz = min(z,rz);
1984 dest = MALLOC(unsigned char *, 4 * rx * ry * rz);
1985 myScaleImage3D(x,y,z,mx,my,mz,mytexdata,dest);
1986 x = mx;
1987 y = my;
1988 z = mz;
1989 FREE_IF_NZ(me->texdata);
1990 }
1991
1992 //COMPUTE GRADIENT - we'll do unconditionally if channels == 1 for 3D image
1993 //and hope that the one info channel is alpha because we overwrite rgb
1994 if(me->channels == 1){
1995 //alpha only scalar image, RGB are free to hold gradient
1996 compute_3D_alpha_gradient_store_rgb((char *)dest,x,y,z);
1997 }
1998
1999 ny = (int) sqrt(z+1);
2000 nx = z / ny;
2001 nx = z - nx*ny > 0 ? nx+1 : nx;
2002
2003 me->tiles[0] = nx; //let the shader tiled emulator for texture3D know via uniform about the tile layout
2004 me->tiles[1] = ny;
2005 me->tiles[2] = z;
2006 //ConsoleMessage("Tiles ny %d nx %d zplanes %d\n",nx,ny,z);
2007 nxx = nx*rx;
2008 nyy = ny*ry;
2009
2010 //place in tile formation - a series of fullish y strips
2011 texdataTiles = MALLOC(unsigned char *,nxx * nyy * 4);
2012 p2 = (uint32 *)texdataTiles;
2013 p1 = (uint32 *)dest;
2014 for(iz=0;iz<z;iz++){
2015 iy = iz % ny;
2016 ix = iz / ny;
2017 for(j=0;j<y;j++){
2018 for(k=0;k<x;k++){
2019 int ifrom, ito;
2020 uint32 pixel;
2021 ifrom = (iz*y + j)*x + k;
2022 ito = (iy*y + j)*nxx + (ix*x) + k;
2023 pixel = p1[ifrom];
2024 p2[ito] = pixel;
2025 }
2026 }
2027 }
2028 if(0){
2029 //write out tiled image for inspection
2030 textureTableIndexStruct_s tti2, *tti3;
2031 tti3 = &tti2;
2032 tti3->x = nxx;
2033 tti3->y = nyy;
2034 tti3->z = 1;
2035 tti3->channels = 4;
2036 tti3->texdata = texdataTiles;
2037 saveImage_web3dit(tti3, "test_tiled_texture.web3dit");
2038 }
2039
2040 myTexImage2D(generateMipMaps, GL_TEXTURE_2D, 0, iformat, nxx, nyy, 0, format, GL_UNSIGNED_BYTE, texdataTiles);
2041 ConsoleMessage("final texture2D size %d %d\n",nxx,nyy);
2042 FREE_IF_NZ(texdataTiles);
2043 if(dest != me->texdata) FREE_IF_NZ(dest);
2044 }else{
2045 //use Texture3D which android and winRT/uwp don't have
2046 }
2047 }else{
2048 //ordinary 2D image textures
2049 if(rx != x || ry != y || rx > rdr_caps->runtime_max_texture_size || ry > rdr_caps->runtime_max_texture_size) {
2050 /* do we have texture limits???
2051 dug9: windows intel i5: desktop opengl and uwp/angleproject 16384
2052 16384 x 16394 = 268M. cube-root 268M = 645.xx lets round down to pow2: 512
2053 android LG nexus 4096
2054 4096 x 4096 = 16.7M; cube-root 16.7M = 256.
2055 */
2056 rx = min(rx,rdr_caps->runtime_max_texture_size);
2057 ry = min(ry,rdr_caps->runtime_max_texture_size);
2058 }
2059
2060 if (gglobal()->internalc.global_print_opengl_errors) {
2061 DEBUG_MSG("texture size after maxTextureSize taken into account: %d %d, from %d %d\n",rx,ry,x,y);
2062 }
2063 //ConsoleMessage("texture size after maxTextureSize taken into account: %d %d, from %d %d\n",rx,ry,x,y);
2064
2065 /* it is a power of 2, lets make sure it is square */
2066 /* ES 2.0 needs this for cross-platform; do not need to do this for desktops, but
2067 lets just keep things consistent
2068 But if not mipmapping, then (experience with win32 GLES2 emulator and QNX device)
2069 then it's not necessary to square the image, although current code will get here with
2070 generateMipMap always true.
2071 */
2072 if (rx != ry) {
2073 if(generateMipMaps){
2074 if (rx>ry)ry=rx;
2075 else rx=ry;
2076 }
2077 }
2078 /* if scaling is ok... */
2079 if ((x==rx) && (y==ry)) {
2080 dest = mytexdata;
2081 } else {
2082
2083 /* try this texture on for size, keep scaling down until we can do it */
2084 /* all textures are 4 bytes/pixel */
2085 size_t total_size = (size_t)4L * rx * ry;
2086 dest = MALLOC(unsigned char *, total_size); //4 * rx * ry);
2087
2088 myScaleImage(x,y,rx,ry,mytexdata,dest);
2089 }
2090 if(rx > 8192 || ry > 8192) ConsoleMessage("texture size rx %d ry %d\n",rx,ry);
2091 myTexImage2D(generateMipMaps, GL_TEXTURE_2D, 0, iformat, rx, ry, 0, format, GL_UNSIGNED_BYTE, dest);
2092 }
2093 if(mytexdata != dest) {
2094 FREE_IF_NZ(dest);
2095 }
2096 }
2097
2098 /* we can get rid of the original texture data here */
2099 FREE_IF_NZ (me->texdata);
2100 }
2101 }
2102
2103
2104 /* ensure this data is written to the driver for the rendering context */
2105 FW_GL_FLUSH();
2106
2107 /* and, now, the Texture is loaded */
2108 me->status = TEX_LOADED;
2109
2110 #ifdef PATH_PLANNER
2111 pthread_mutex_unlock( &gl_mutex1 );
2112 #endif //PATH_PLANNER
2113
2114}
2115
2116
2117/**********************************************************************************
2118 bind the image,
2119
2120 itype tells us whether it is a PixelTexture, ImageTexture or MovieTexture.
2121
2122 parenturl is a pointer to the url of the parent (for relative loads) OR
2123 a pointer to the image data (PixelTextures only)
2124
2125 url the list of urls from the VRML file, or NULL (for PixelTextures)
2126
2127 texture_num the OpenGL texture identifier
2128
2129 repeatS, repeatT VRML fields
2130
2131 param - vrml fields, but translated into GL_TEXTURE_ENV_MODE, GL_MODULATE, etc.
2132************************************************************************************/
2133
2134void new_bind_image(struct X3D_Node *node, struct multiTexParams *param) {
2135 int thisTexture;
2136 int thisTextureType;
2137 struct X3D_ImageTexture *it;
2138 struct X3D_PixelTexture *pt;
2139 struct X3D_MovieTexture *mt;
2140 struct X3D_ImageCubeMapTexture *ict;
2141 struct X3D_GeneratedCubeMapTexture *gct;
2142
2143 textureTableIndexStruct_s *myTableIndex;
2144 //float dcol[] = {0.8f, 0.8f, 0.8f, 1.0f};
2145 ppTextures p;
2146 struct Multi_String *mfurl = NULL;
2147 ttglobal tg = gglobal();
2148 p = (ppTextures)tg->Textures.prv;
2149 //#define DEBUG_TEX ConsoleMessage
2150
2151// GET_THIS_TEXTURE;
2152//#define GET_THIS_TEXTURE
2153 thisTextureType = node->_nodeType;
2154 if (thisTextureType==NODE_ImageTexture){
2155 it = (struct X3D_ImageTexture*) node;
2156 mfurl = &it->url;
2157 thisTexture = it->__textureTableIndex;
2158 } else if (thisTextureType==NODE_PixelTexture){
2159 pt = (struct X3D_PixelTexture*) node;
2160 thisTexture = pt->__textureTableIndex;
2161 } else if (thisTextureType==NODE_MovieTexture){
2162 mt = (struct X3D_MovieTexture*) node;
2163 thisTexture = mt->__textureTableIndex;
2164 mfurl = &mt->url;
2165 } else if (thisTextureType==NODE_ImageCubeMapTexture){
2166 ict = (struct X3D_ImageCubeMapTexture*) node;
2167 thisTexture = ict->__textureTableIndex;
2168 mfurl = &ict->url;
2169 } else if (thisTextureType==NODE_GeneratedCubeMapTexture){
2170 gct = (struct X3D_GeneratedCubeMapTexture*) node;
2171 thisTexture = gct->__textureTableIndex;
2172 } else if (thisTextureType==NODE_PixelTexture3D){
2173 struct X3D_PixelTexture3D *pt3d;
2174 pt3d = (struct X3D_PixelTexture3D*) node;
2175 thisTexture = pt3d->__textureTableIndex;
2176 } else if (thisTextureType==NODE_ImageTexture3D){
2177 struct X3D_ImageTexture3D *pt3d;
2178 pt3d = (struct X3D_ImageTexture3D*) node;
2179 thisTexture = pt3d->__textureTableIndex;
2180 mfurl = &pt3d->url;
2181 } else if (thisTextureType==NODE_ComposedTexture3D){
2182 struct X3D_ComposedTexture3D *pt3d;
2183 pt3d = (struct X3D_ComposedTexture3D*) node;
2184 thisTexture = pt3d->__textureTableIndex;
2185 } else {
2186 ConsoleMessage ("Invalid type for texture, %s\n",stringNodeType(thisTextureType));
2187 return;
2188 }
2189
2190 myTableIndex = getTableIndex(thisTexture);
2191 if (myTableIndex->status != TEX_LOADED) {
2192 DEBUG_TEX("new_bind_image, I am %p, textureStackTop %d, thisTexture is %d myTableIndex %p status %s\n",
2193 node,tg->RenderFuncs.textureStackTop,thisTexture,myTableIndex, texst(myTableIndex->status));
2194 //printf ("new_bind_image (%d), I am %p, textureStackTop %d, thisTexture is %d myTableIndex %p status %s\n",
2195 //__LINE__,node,tg->RenderFuncs.textureStackTop,thisTexture,myTableIndex, texst(myTableIndex->status));
2196 }
2197
2198 /* default here; this is just a blank texture */
2199 tg->RenderFuncs.boundTextureStack[tg->RenderFuncs.textureStackTop] = tg->Textures.defaultBlankTexture;
2200 switch (myTableIndex->status) {
2201 case TEX_NOTLOADED:
2202 DEBUG_TEX("feeding texture %p to texture thread...\n", myTableIndex);
2203 if(mfurl && mfurl->n == 0) {
2204 //for <ImageTexture /> with url not declared, we should get the default blank image
2205 myTableIndex->status = TEX_NEEDSBINDING;
2206 } else {
2207 myTableIndex->status = TEX_LOADING;
2208 send_texture_to_loader(myTableIndex);
2209 }
2210 break;
2211
2212 case TEX_LOADING:
2213 case TEX_READ:
2214 DEBUG_TEX("I've to wait for %p...\n", myTableIndex);
2215 break;
2216
2217 case TEX_NEEDSBINDING:
2218 DEBUG_TEX("texture loaded into memory... now lets load it into OpenGL...\n");
2219 move_texture_to_opengl(myTableIndex);
2220
2221 // do always #ifdef PATH_PLANNER
2222 // JAS - skipping a rendering loop
2223 // if we are ok, go direct to rendering this texture.
2224 if (myTableIndex->status != TEX_LOADED) {
2225 printf ("issue going from TEX_NEEDSBINDING to TEX_LOADED, is %s\n",
2226 texst(myTableIndex->status));
2227 break;
2228 }
2229 // do always #else
2230 // do always break;
2231 // do always #endif //PATH_PLANNER
2232
2233 case TEX_LOADED:
2234 //DEBUG_TEX("now binding to pre-bound tex %u\n", myTableIndex->OpenGLTexture);
2235
2236 /* set the texture depth - required for Material diffuseColor selection */
2237 if (myTableIndex->hasAlpha) tg->RenderFuncs.last_texture_type = TEXTURE_ALPHA;
2238 else tg->RenderFuncs.last_texture_type = TEXTURE_NO_ALPHA;
2239
2240//printf ("last_texture_type = TEXTURE_NO_ALPHA now\n"); last_texture_type=TEXTURE_NO_ALPHA;
2241
2242 if (myTableIndex->OpenGLTexture == TEXTURE_INVALID) {
2243
2244 DEBUG_TEX("no openGLtexture here status %s\n", texst(myTableIndex->status));
2245 return;
2246 }
2247
2248 tg->RenderFuncs.boundTextureStack[tg->RenderFuncs.textureStackTop] = myTableIndex->OpenGLTexture;
2249 //printf ("new_bind, boundTextureStack[%d] set to %d\n",tg->RenderFuncs.textureStackTop,myTableIndex->OpenGLTexture);
2250
2251
2252 /* save the texture params for when we go through the MultiTexture stack. Non
2253 MultiTextures should have this textureStackTop as 0 */
2254
2255 if (param != NULL) {
2256 struct multiTexParams *textureParameterStack = (struct multiTexParams *) tg->RenderTextures.textureParameterStack;
2257 memcpy(&(textureParameterStack[tg->RenderFuncs.textureStackTop]), param,sizeof (struct multiTexParams));
2258 //memcpy(&(tg->RenderTextures.textureParameterStack[tg->RenderFuncs.textureStackTop]), param,sizeof (struct multiTexParams));
2259 }
2260 p->textureInProcess = -1; /* we have finished the whole process */
2261 break;
2262
2263 case TEX_UNSQUASHED:
2264 default: {
2265 printf ("unknown texture status %d\n",myTableIndex->status);
2266 }
2267 }
2268 //#define DEBUG_TEX
2269}
2270
2271int get_bound_image(struct X3D_Node *node) {
2272 int thisTexture;
2273 int thisTextureType;
2274 struct X3D_ImageTexture *it;
2275 struct X3D_PixelTexture *pt;
2276 struct X3D_MovieTexture *mt;
2277 struct X3D_ImageCubeMapTexture *ict;
2278 struct X3D_GeneratedCubeMapTexture *gct;
2279
2280 textureTableIndexStruct_s *myTableIndex;
2281 //float dcol[] = {0.8f, 0.8f, 0.8f, 1.0f};
2282 ppTextures p;
2283 struct Multi_String *mfurl = NULL;
2284 ttglobal tg = gglobal();
2285 p = (ppTextures)tg->Textures.prv;
2286 //#define DEBUG_TEX ConsoleMessage
2287
2288// GET_THIS_TEXTURE;
2289//#define GET_THIS_TEXTURE
2290 thisTextureType = node->_nodeType;
2291 if (thisTextureType==NODE_ImageTexture){
2292 it = (struct X3D_ImageTexture*) node;
2293 mfurl = &it->url;
2294 thisTexture = it->__textureTableIndex;
2295 } else if (thisTextureType==NODE_PixelTexture){
2296 pt = (struct X3D_PixelTexture*) node;
2297 thisTexture = pt->__textureTableIndex;
2298 } else if (thisTextureType==NODE_MovieTexture){
2299 mt = (struct X3D_MovieTexture*) node;
2300 thisTexture = mt->__textureTableIndex;
2301 mfurl = &mt->url;
2302 } else if (thisTextureType==NODE_ImageCubeMapTexture){
2303 ict = (struct X3D_ImageCubeMapTexture*) node;
2304 thisTexture = ict->__textureTableIndex;
2305 mfurl = &ict->url;
2306 } else if (thisTextureType==NODE_GeneratedCubeMapTexture){
2307 gct = (struct X3D_GeneratedCubeMapTexture*) node;
2308 thisTexture = gct->__textureTableIndex;
2309 } else if (thisTextureType==NODE_PixelTexture3D){
2310 struct X3D_PixelTexture3D *pt3d;
2311 pt3d = (struct X3D_PixelTexture3D*) node;
2312 thisTexture = pt3d->__textureTableIndex;
2313 } else if (thisTextureType==NODE_ImageTexture3D){
2314 struct X3D_ImageTexture3D *pt3d;
2315 pt3d = (struct X3D_ImageTexture3D*) node;
2316 thisTexture = pt3d->__textureTableIndex;
2317 mfurl = &pt3d->url;
2318 } else if (thisTextureType==NODE_ComposedTexture3D){
2319 struct X3D_ComposedTexture3D *pt3d;
2320 pt3d = (struct X3D_ComposedTexture3D*) node;
2321 thisTexture = pt3d->__textureTableIndex;
2322 } else {
2323 ConsoleMessage ("Invalid type for texture, %s\n",stringNodeType(thisTextureType));
2324 return -1;
2325 }
2326
2327 myTableIndex = getTableIndex(thisTexture);
2328 return myTableIndex->OpenGLTexture;
2329}