FreeWRL / FreeX3D 4.3.0
Component_PTM.c
1/*
2=INSERT_TEMPLATE_HERE=
3
4$Id: Component_Grouping.c,v 1.52 2013/08/01 12:55:35 crc_canada Exp $
5
6X3D Grouping Component
7
8*/
9
10
11/****************************************************************************
12This file is part of the FreeWRL/FreeX3D Distribution.
13
14Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
15
16FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
17it under the terms of the GNU Lesser Public License as published by
18the Free Software Foundation, either version 3 of the License, or
19(at your option) any later version.
20
21FreeWRL/FreeX3D is distributed in the hope that it will be useful,
22but WITHOUT ANY WARRANTY; without even the implied warranty of
23MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24GNU General Public License for more details.
25
26You should have received a copy of the GNU General Public License
27along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
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 "../vrml_parser/CRoutes.h"
40#include "../main/headers.h"
41
42#include "../opengl/OpenGL_Utils.h"
43#include "../opengl/Frustum.h"
44#include "../opengl/Material.h"
45#include "Component_Shape.h"
46#include "LinearAlgebra.h"
47#include "Vector.h"
48#include "Children.h"
49#include <stdlib.h>
50
51
52//we'll share VF_globalLight render pass with global lights
53// this filter will allow global=true on the VF_globalLight render_hier pass
54// and wll allow global=false on regular pass
55#define RETURN_IF_RENDER_STATE_NOT_US \
56 if (renderstate()->render_light== VF_globalLight) { \
57 if (!node->global) return;\
58 } else { \
59 if (node->global) return; \
60 if(renderstate()->render_geom != VF_Geom) return; \
61 }
62
63
64
65// camera space (-1,-1) to (1,1)
66// texture space (0,0) to (1,1)
67// convert: scale by .5, and add .5
68const GLDOUBLE bias[16] = { 0.5, 0.0, 0.0, 0.0,
690.0, 0.5, 0.0, 0.0,
700.0, 0.0, 0.5, 0.0,
710.5, 0.5, 0.5, 1.0 };
72
73
75 struct Uni_String *des;
76 GLDOUBLE TenLinearGexMat[16];
77};
78
80 struct Uni_String *des;
81 GLDOUBLE TenLinearGexMat[16];
82 int backCull;
83 int global;
84 int type; //0=perspective, 1=ortho/parallel
85 GLuint texture;
86 struct X3D_Node * textureNode;
87};
88
89typedef struct pComponent_PTM{
90 struct Vector *projector_stack; //activeProjectiveTextureTable;
91 //textureTableIndexStruct_s* loadThisProjectiveTexture;
92
93 /* current index into loadparams that texture thread is working on */
94 int currentlyWorkingOn;// = -1;
95 int textureInProcess;// = -1;
96 struct projective_Texdata data[4];
98
99void *Component_PTM_constructor(){
100 void *v = malloc(sizeof(struct pComponent_PTM));
101 memset(v,0,sizeof(struct pComponent_PTM));
102 return v;
103}
104void Component_PTM_init(struct tComponent_PTM *t){
105 //public
106
107 //private
108
109 t->prv = Component_PTM_constructor();
110 {
112 //p->activeProjectiveTextureTable = NULL;
113 p->projector_stack = newStack(struct projector_tuple);
114
115 //t->data = &p->data;
116 /* current index into loadparams that texture thread is working on */
117 p->currentlyWorkingOn = -1;
118
119 p->textureInProcess = -1;
120 }
121}
122
123void Component_PTM_clear(struct tComponent_PTM *t){
124 //public
125 //private
126 {
128 }
129}
130
131
132void projectorTable_clear(){
133 //called once per frame, before the search for global=true projectors
134 //will clear any global=true projectors from last frame
136 ttglobal tg = gglobal();
137 p = (ppComponent_PTM)tg->Component_PTM.prv;
138 clearStack(p->projector_stack);
139}
140void projectorTable_push(struct projector_tuple *ptuple ){
141 //called when we find a global=true, on=true projector, and
142 //called in sib_prep for a global=false, on=false projector
144 ttglobal tg = gglobal();
145 p = (ppComponent_PTM)tg->Component_PTM.prv;
146 //we need a deep copy because the ptm node can't hold it
147 // because it can be DEF/USED with different transform each use
148 stack_push(struct projector_tuple,p->projector_stack,*ptuple);
149
150}
151void projectorTable_pop(){
152 //called in sib_fin for a global=false, on=true projector
154 ttglobal tg = gglobal();
155 p = (ppComponent_PTM)tg->Component_PTM.prv;
156 if(p->projector_stack->n < 1)
157 printf("ouch from projectorTable_opo()\n");
158 stack_pop(struct projector_tuple,p->projector_stack);
159
160}
161void clear_bound_textures(){
162 for(int i=0;i<16;i++){
163 glActiveTexture(GL_TEXTURE0 + i);
164 glBindTexture(GL_TEXTURE_2D,0);
165 }
166}
167
168void print_bound_textures(char *str){
169 GLint whichID;
170 printf("ActiveTexture boundUnit %s\n",str);
171 for(int i=0;i<16;i++){
172 glActiveTexture(GL_TEXTURE0 + i);
173 glGetIntegerv(GL_TEXTURE_BINDING_2D, &whichID);
174 printf("%12d %12d\n",i,whichID);
175 }
176}
177
178int get_bound_image(struct X3D_Node *node);
179int getGlTextureNumberFromTextureNode(struct X3D_Node *textureNode);
180int getTextureSizeFromTextureNode(struct X3D_Node *textureNode, int *ixyz);
181int getTextureDescriptors(struct X3D_Node *textureNode, int *textures, int *modes, int *sources, int *funcs, int *width, int *height);
182void resend_textureprojector_matrix()
183{
184 //called from render_shape to refresh uniform before shade draw
185 int pcount,tcount;
187 struct projective_Texdata *data;
189 ttglobal tg = gglobal();
190 p = (ppComponent_PTM)tg->Component_PTM.prv;
191 data = p->data;
192
193 me = getAppearanceProperties()->currentShaderProperties;
194
195 // while the number of texture samplers are a limited resource in GLSL,
196 // there could be many projectors re-using the same sampler.
197 // to accommodate multitexture per projector, and avoid [][] 2 dimenstional arrays in GLSL
198 // we have a single list of texture descriptors, and a tcounts[] that says how many texture descriptors per projector
199 // per child_shape shader run:
200 // pcount; //number of projectors, <= MAX_PROJ
201 // per sampler2D:
202 // textureUnit[MAX_TEX]
203 // per projector:
204 // projTexGenMatCam[MAX_PROJ]
205 // backCull[MAX_PROJ]
206 // ntdesc[MAX_PROJ]
207 // per texture descriptor
208 //. tunits[MAX_TDESC] //indexes into textureUnit[] array
209 // modes[MAX_TDESC]
210 // sources[MAX_TDESC]
211 // funcs[MAX_TDESC]
212 int MAX_PROJ = 8;
213 int MAX_TDESC = 16;
214 int MAX_TEX = 4;
215 tcount = min(p->projector_stack->n,MAX_PROJ);
216 pcount = 0;
217 int nunit = 0;
218 int kdesc = 0;
219 int unitTextures[4];
220 for(int i=0;i<tcount;i++)
221 {
222 float TenLinearGexMatCam0f[16];
223 struct projector_tuple *ptuple;
224 GLint texture;
225 if(me->projTexGenMatCam[i] > -1){
226 ptuple = vector_get_ptr(struct projector_tuple, p->projector_stack, i);
227 double2float(TenLinearGexMatCam0f, ptuple->TenLinearGexMat,16);
228 GLUNIFORMMATRIX4FV (me->projTexGenMatCam[i],1,GL_FALSE, TenLinearGexMatCam0f);
229 //GLUNIFORM1I(me->projectorType[i],ptuple->type);
230 //backCull in theory could automatically always do it,
231 // or projector->backCull=TRUE default,
232 // and turn off when Gl_CULL_FACE is off, meaning web3d solid=FALSE
233 // X HOWEVER freewrl Feb 2020 isn't reliably discriminating solid=true/false for different geometry types
234 // - THEREFORE we will let projector->backCull be definitive and scene authors will set manually until freewrl solid is fixed
235 GLUNIFORM1I(me->pbackCull[i],ptuple->backCull);
236 //GLUNIFORM1I(me->pbackCull[i], (ptuple->backCull && getAppearanceProperties()->cullFace)?1:0);
237
238 int ntdesc = 0; //number of texture descriptors in this projector
239 struct X3D_NODE * tlist[4];
240 int modes[4];
241 int sources[4];
242 int funcs[4];
243 int textures[4];
244 int width[4], height[4];
245
246 int toffset = 4;
247 glActiveTexture(GL_TEXTURE0+toffset+pcount);
248 render_node(ptuple->textureNode);
249
250 ntdesc = getTextureDescriptors(ptuple->textureNode,textures, modes,sources, funcs, width, height);
251 GLUNIFORM1I(me->ntdesc[i],ntdesc);
252 for(int j=0;j<ntdesc;j++,kdesc++){
253 // re-use texture sampler if mulitple projectors and multitextures refer to same GLint texture 1:1 sampler2D
254 int kunit;
255 //texture = ptuple->texture;
256 texture = textures[j];
257 kunit = -1;
258 for(int k=0;k<nunit;k++){
259 if(unitTextures[k] == texture){
260 kunit = k;
261 break;
262 }
263 }
264 if(kunit == -1){
265 int toffset = 4;
266 nunit = min(nunit++,MAX_TEX); //for fun, if we go over MAX_TEX we'll just over-write last one
267 kunit = nunit-1;
268 //print_bound_textures("start");
269 glActiveTexture(GL_TEXTURE0+toffset+kunit);
270 glBindTexture(GL_TEXTURE_2D,texture);
271 glUniform1i(me->textureUnit[kunit],kunit+toffset);
272 glActiveTexture(GL_TEXTURE0);
273 //print_bound_textures("end");
274 }
275 unitTextures[kunit] = texture;
276 GLUNIFORM1I(me->tunits[kdesc],kunit);
277 GLUNIFORM1I(me->modes[kdesc],modes[j]);
278 GLUNIFORM1I(me->sources[kdesc],sources[j]);
279 GLUNIFORM1I(me->funcs[kdesc],funcs[j]);
280 }
281 pcount++;
282 tg->RenderFuncs.textureStackTop = 1; //keep this frmo building up
283 }
284 }
285 GLUNIFORM1I(me->pCount,pcount);
286
287}
288
289void compile_TextureProjectorPerspective (struct X3D_TextureProjectorPerspective *node) {
290
291
292 /* LookAt Matrix Complete */
293 float dir[3], up[3], cross1[3],cross2[3];
294 veccopy3f(node->_loc.c,node->location.c);
295 veccopy3f(dir,node->direction.c);
296 veccopy3f(up,node->upVector.c);
297 vecnormalize3f(dir,dir);
298 vecnormalize3f(up,up);
299 veccross3f(cross1,dir,up);
300 vecnormalize3f(cross1,cross1);
301 veccross3f(cross2,cross1,dir);
302 vecnormalize3f(cross2,cross2);
303 veccopy3f(node->_dir.c,dir);
304 node->_dir.c[3] = 0.0f;
305 veccopy3f(node->_upVec.c,up);
306 node->_upVec.c[3] = 0.0f;
307
308 MARK_NODE_COMPILED;
309}
310
311/* Projective Texture gluLookAt */
312void projLookAt(GLDOUBLE eyex, GLDOUBLE eyey, GLDOUBLE eyez,
313 GLDOUBLE centerx, GLDOUBLE centery, GLDOUBLE centerz,
314 GLDOUBLE upx, GLDOUBLE upy, GLDOUBLE upz, GLDOUBLE *matrix);
315void projPerspective(GLDOUBLE fovy, GLDOUBLE aspect, GLDOUBLE zNear, GLDOUBLE zFar, GLDOUBLE *matrix);
316void printmatrix2(GLDOUBLE* mat,char* description );
317void render_TextureProjectorPerspective (struct X3D_TextureProjectorPerspective *node) {
318 int i,j = 0;
319 int flag = 0;
320 static int datacount = 0;
321 float degree = node->fieldOfView* 180.0/3.141596;
322 GLDOUBLE cViewMat[16];
323 GLDOUBLE invcViewMat[16];
324 GLDOUBLE ViewMat[16];
325 GLDOUBLE ProjMat[16];
326 GLint tex1;
327 struct projective_Texdata *data;
329 ttglobal tg = gglobal();
330 p = (ppComponent_PTM)tg->Component_PTM.prv;
331 data = p->data;
332 //data = (struct projective_Texdata*)tg->Component_PTM.data;
333
334 RETURN_IF_RENDER_STATE_NOT_US
335 COMPILE_IF_REQUIRED;
336
337 if(node->on) {
338 double tempmat[16];
339 GLDOUBLE TenLinearGexMatCam0[16];
340 GLDOUBLE modelview[16], modelviewnode[16], eye2projector[16], modelviewinv[16];
341 struct X3D_Node *tmpN = NULL;
342
343 if(node->global) tg->Component_PTM.globalProjector = TRUE;
344
345 //A. COMPUTE NODE-POSE MATRIX FOR: .position, .dir, .upVector
346 //glMatrixMode(GL_MODELVIEW);
347 FW_GL_MATRIX_MODE(GL_MODELVIEW);
348 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, modelview);
349
350 {
351 double loc[3],dir[3],up[3],eye[3];
352 float2double(loc,node->_loc.c,3);
353 float2double(dir,node->_dir.c,3);
354 float2double(up,node->_upVec.c,3);
355 vecdifd(eye,loc,dir);
356 projLookAt(eye[0],eye[1],eye[2], loc[0],loc[1],loc[2], up[0],up[1],up[2],ViewMat);
357 }
358
359 //B. INVERT modelviewnode (which transforms projector to eye) to get eye-to-projector
360 matinverse(modelviewinv,modelview);
361 //C. COMBINE MODELVIEW MATRIX WITH NODE-POSE MATRIX
362 matmultiplyAFFINE(eye2projector,modelviewinv,ViewMat);
363
364 //C. COMPUTE A PROJECTION MATRIX THAT INCLUDES CAMERA SPACE TO TEXTURE SPACE BIAS
365 projPerspective((GLDOUBLE)degree,
366 (GLDOUBLE)node->aspectRatio, // aspectRatio = width/height see below, gets from image
367 (GLDOUBLE)node->nearDistance,(GLDOUBLE)node->farDistance, // near, far
368 ProjMat);
369
370 matidentity4d(tempmat);
371// matmultiplyFULL(tempmat,bias,tempmat);
372 matmultiplyFULL(tempmat,ProjMat,tempmat);
373
374 //D. COMBINE PROJECTION AND EYE-TO-PROJECTOR TRANSFORMS
375 matmultiplyFULL(TenLinearGexMatCam0,eye2projector,tempmat);
376
377
378 if(node->texture)
379 {
380 POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, node->texture,tmpN);
381 if(tmpN){
382 int ixyz[3];
383 float aspectRatio;
384 if(getTextureSizeFromTextureNode(tmpN, ixyz)){
385 if(ixyz[0] > 0 && ixyz[1] > 0){
386 aspectRatio = (float)ixyz[0]/(float)ixyz[1];
387 if(!APPROX(node->aspectRatio,aspectRatio)){
388 node->aspectRatio = aspectRatio;
389 MARK_EVENT (X3D_NODE(node), offsetof(struct X3D_TextureProjectorPerspective, aspectRatio));
390 //printf("aspectRatio= %f\n",node->aspectRatio);
391 }
392 }
393 }
394 }
395
396
397 }
398 {
399 GLuint texture;
400 struct projector_tuple ptuple;
401 ptuple.des = node->description;
402 memcpy(ptuple.TenLinearGexMat, TenLinearGexMatCam0,16*sizeof (GLDOUBLE));
403 ptuple.backCull = node->backCull == TRUE? 1 : 0;
404 //printf("peye = %lf %lf %lf\n",ptuple.peye[0],ptuple.peye[1],ptuple.peye[2]);
405 ptuple.global = node->global;
406 ptuple.type = 0; //0=perspective 1=ortho/parallel
407 texture = tg->RenderFuncs.boundTextureStack[tg->RenderFuncs.textureStackTop];
408 ptuple.texture = texture;
409 ptuple.textureNode = tmpN;
410 projectorTable_push(&ptuple);
411 }
412
413 } //if(node->on)
414 }
415
416
417void fin_TextureProjectorPerspective (struct X3D_TextureProjectorPerspective *node)
418{
419 RETURN_IF_RENDER_STATE_NOT_US
420 if(node->on)
421 if(!node->global)
422 projectorTable_pop(); //just pop local projectors that we pushed above - globals are cleared once per frame
423}
424
425void prep_TextureProjectorPerspective(struct X3D_TextureProjectorPerspective *node) {
426
427
428 if (!renderstate()->render_light) return;
429 /* this will be a global textureprojector here... */
430 render_TextureProjectorPerspective(node);
431
432}
433void child_TextureProjectorPerspective (struct X3D_TextureProjectorPerspective *node) {
434}
435
436
438
439
440
441void child_TextureProjectorParallel (struct X3D_TextureProjectorParallel *node) {
442}
443void fin_TextureProjectorParallel (struct X3D_TextureProjectorParallel *node) {
444
445 RETURN_IF_RENDER_STATE_NOT_US
446 if(node->on)
447 if(!node->global)
448 projectorTable_pop(); //just pop local projectors that we pushed above - globals are cleared once per frame
449
450}
451
452void compile_TextureProjectorParallel (struct X3D_TextureProjectorParallel *node) {
453
454 /* LookAt Matrix Complete */
455 float dir[3], up[3], cross1[3],cross2[3];
456 veccopy3f(node->_loc.c,node->location.c);
457 veccopy3f(dir,node->direction.c);
458 veccopy3f(up,node->upVector.c);
459 vecnormalize3f(dir,dir);
460 vecnormalize3f(up,up);
461 veccross3f(cross1,dir,up);
462 vecnormalize3f(cross1,cross1);
463 veccross3f(cross2,cross1,dir);
464 vecnormalize3f(cross2,cross2);
465 veccopy3f(node->_dir.c,dir);
466 node->_dir.c[3] = 0.0f;
467 veccopy3f(node->_upVec.c,up);
468 node->_upVec.c[3] = 0.0f;
469
470 MARK_NODE_COMPILED;
471
472}
473
474void projOrtho (GLDOUBLE l, GLDOUBLE r, GLDOUBLE b, GLDOUBLE t,
475 GLDOUBLE n, GLDOUBLE f,GLDOUBLE *matrix);
476void mesa_Ortho(GLDOUBLE left, GLDOUBLE right, GLDOUBLE bottom, GLDOUBLE top, GLDOUBLE nearZ, GLDOUBLE farZ, GLDOUBLE *m);
477void render_TextureProjectorParallel (struct X3D_TextureProjectorParallel *node) {
478 int i,j = 0;
479 int flag = 0;
480 static int datacount = 0;
481 //float degree = node->fieldOfView* 180/3.14;
482 GLDOUBLE cViewMat[16];
483 GLDOUBLE invcViewMat[16];
484 GLDOUBLE ViewMat[16];
485 GLDOUBLE orthoMat[16];
486 GLint tex1;
487 struct projective_Texdata *data;
489 ttglobal tg = gglobal();
490 p = (ppComponent_PTM)tg->Component_PTM.prv;
491 data = p->data;
492 //data = (struct projective_Texdata*)tg->Component_PTM.data;
493
494 RETURN_IF_RENDER_STATE_NOT_US
495 COMPILE_IF_REQUIRED;
496
497 if(node->on) {
498 double tempmat[16];
499 GLDOUBLE TenLinearGexMatCam0[16];
500 GLDOUBLE modelview[16], modelviewnode[16], eye2projector[16], modelviewinv[16];
501 struct X3D_Node *tmpN = NULL;
502
503 if(node->global) tg->Component_PTM.globalProjector = TRUE;
504
505 //A. COMPUTE NODE-POSE MATRIX FOR: .position, .dir, .upVector
506 //glMatrixMode(GL_MODELVIEW);
507 FW_GL_MATRIX_MODE(GL_MODELVIEW);
508 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, modelview);
509 {
510 double loc[3],dir[3],up[3],eye[3];
511 float2double(loc,node->_loc.c,3);
512 float2double(dir,node->_dir.c,3);
513 float2double(up,node->_upVec.c,3);
514 vecdifd(eye,loc,dir);
515 projLookAt(eye[0],eye[1],eye[2], loc[0],loc[1],loc[2], up[0],up[1],up[2],ViewMat);
516 }
517
518 //B. INVERT modelviewnode (which transforms projector to eye) to get eye-to-projector
519 matinverse(modelviewinv,modelview);
520 //C. COMBINE MODELVIEW MATRIX WITH NODE-POSE MATRIX
521 matmultiplyAFFINE(eye2projector,modelviewinv,ViewMat);
522
523
524 //C. COMPUTE A PROJECTION MATRIX THAT INCLUDES CAMERA SPACE TO TEXTURE SPACE BIAS
525 mesa_Ortho((GLDOUBLE)node->fieldOfView.p[0],(GLDOUBLE)node->fieldOfView.p[2],(GLDOUBLE)node->fieldOfView.p[1],(GLDOUBLE)node->fieldOfView.p[3],
526 (GLDOUBLE)node->nearDistance, (GLDOUBLE)node->farDistance,orthoMat);
527
528 matidentity4d(tempmat);
529// matmultiplyFULL(tempmat,bias,tempmat); //in shader now
530 matmultiplyFULL(tempmat,orthoMat,tempmat);
531
532 //D. COMBINE PROJECTION AND EYE-TO-PROJECTOR TRANSFORMS
533 matmultiplyFULL(TenLinearGexMatCam0,eye2projector,tempmat);
534
535 {
536 float aspectRatio, denom, *fov;
537 fov = node->fieldOfView.p;
538 denom = fov[3]-fov[1];
539 if(denom > 0.0){
540 aspectRatio = (fov[2]-fov[0])/denom;
541 if(!APPROX(node->aspectRatio,aspectRatio)){
542 node->aspectRatio = aspectRatio;
543 MARK_EVENT (X3D_NODE(node), offsetof(struct X3D_TextureProjectorParallel, aspectRatio));
544 //printf("aspectRatio= %f\n",node->aspectRatio);
545 }
546 }
547 }
548
549
550 if(node->texture)
551 {
552 POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, node->texture,tmpN);
553 }
554 {
555 GLuint texture;
556 struct projector_tuple ptuple;
557 ptuple.des = node->description;
558 memcpy(ptuple.TenLinearGexMat, TenLinearGexMatCam0,16*sizeof (GLDOUBLE));
559 ptuple.backCull = node->backCull == TRUE? 1 : 0;
560 ptuple.global = node->global;
561 ptuple.type = 1; //0=perspective, 1=ortho
562 texture = tg->RenderFuncs.boundTextureStack[tg->RenderFuncs.textureStackTop];
563 ptuple.texture = texture;
564 ptuple.textureNode = tmpN;
565 projectorTable_push(&ptuple);
566 }
567
568
569 } //if(node->on)
570}
571
572
573void prep_TextureProjectorParallel(struct X3D_TextureProjectorParallel *node)
574{
575 if (!renderstate()->render_light) return;
576 /* this will be a global textureprojector here... */
577 render_TextureProjectorParallel(node);
578}
579
580
581
582void render_TextureProjector(struct X3D_Node *sibAffector){
583 switch(sibAffector->_nodeType){
584 case NODE_TextureProjectorParallel:
585 render_TextureProjectorParallel((struct X3D_TextureProjectorParallel*)sibAffector);
586 break;
587 case NODE_TextureProjectorPerspective:
588 default:
589 render_TextureProjectorPerspective((struct X3D_TextureProjectorPerspective*)sibAffector);
590 break;
591 }
592}
593void fin_TextureProjector(struct X3D_Node *sibAffector){
594 switch(sibAffector->_nodeType){
595 case NODE_TextureProjectorParallel:
596 fin_TextureProjectorParallel((struct X3D_TextureProjectorParallel*)sibAffector);
597 break;
598 case NODE_TextureProjectorPerspective:
599 default:
600 fin_TextureProjectorPerspective((struct X3D_TextureProjectorPerspective*)sibAffector);
601 break;
602 }
603}
604
605void sib_prep_TextureProjector(struct X3D_Node *parent, struct X3D_Node *sibAffector){
606 if ( renderstate()->render_light != VF_globalLight){
607 shaderflagsstruct shaderflags;
608 shaderflags = getShaderFlags();
609 shaderflags.base |= HAVE_PROJECTIVETEXTURE;
610 pushShaderFlags(shaderflags);
611
612 render_TextureProjector(sibAffector);
613 }
614
615}
616
617void sib_fin_TextureProjector(struct X3D_Node *parent, struct X3D_Node *sibAffector){
618 if (renderstate()->render_light != VF_globalLight) {
619 fin_TextureProjector(sibAffector);
620 popShaderFlags();
621 }
622}
623
624