Initial revision
[blender.git] / source / blender / render / intern / source / envmap.c
1
2 /*  envmap.c        RENDER
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  * 
32  *  may 1999
33  * 
34  * $Id$
35  */
36
37 #include <math.h>
38 #include <string.h>
39
40 #ifdef WIN32
41 #include "BLI_winstuff.h"
42 #endif
43
44 /* external modules: */
45 #include "MEM_guardedalloc.h"
46 #include "BLI_arithb.h"
47 #include "BLI_blenlib.h"
48 #include "IMB_imbuf_types.h"
49 #include "IMB_imbuf.h"        /* for rectcpy */
50
51 #include "DNA_texture_types.h"
52 #include "DNA_image_types.h"
53 #include "DNA_object_types.h"
54 #include "DNA_scene_types.h"
55 #include "DNA_texture_types.h"
56
57 #include "BIF_space.h"
58 #include "BIF_toolbox.h"
59
60 #include "BKE_library.h"
61 #include "BKE_main.h"
62 #include "BKE_global.h"
63 #include "BKE_world.h"   // init_render_world
64 #include "BKE_image.h"   // BKE_write_ibuf 
65
66
67 /* this module */
68 #include "RE_callbacks.h"
69 #include "render.h"
70 #include "render_intern.h"
71 #include "envmap.h"
72 #include "mydevice.h"
73 #include "rendercore.h" /* calls zbufShade(DA).... I want to replace this with my own :)*/
74 #include "renderHelp.h"
75 #include "MTC_matrixops.h"
76 #include "zbuf.h"
77
78 /* ------------------------------------------------------------------------- */
79
80 void envmap_split_ima(EnvMap *env);
81 void envmap_renderdata(EnvMap *env);
82 void envmap_transmatrix(float mat[][4], int part);
83 void env_rotate_scene(float mat[][4], int mode);
84 void env_layerflags(unsigned int notlay);
85 void env_set_imats(void);
86 void render_envmap(EnvMap *env);
87 int envcube_isect(float *vec, float *answ);
88 static void set_dxtdyt(float *dxts, float *dyts, float *dxt, float *dyt, int face);
89
90 /* ------------------------------------------------------------------------- */
91
92 EnvMap *RE_add_envmap(void)
93 {
94         EnvMap *env;
95         
96         env= MEM_callocN(sizeof(EnvMap), "envmap");
97         env->type= ENV_CUBE;
98         env->stype= ENV_STATIC;
99         env->clipsta= 0.1;
100         env->clipend= 100.0;
101         env->cuberes= 100;
102         
103         return env;
104 } /* end of EnvMap *RE_add_envmap() */
105
106 /* ------------------------------------------------------------------------- */
107
108 EnvMap *RE_copy_envmap(EnvMap *env)
109 {
110         EnvMap *envn;
111         int a;
112         
113         envn= MEM_dupallocN(env);
114         envn->ok= 0;
115         for(a=0; a<6; a++) envn->cube[a]= 0;
116         if(envn->ima) id_us_plus((ID *)envn->ima);
117         
118         return envn;
119 }
120
121 /* ------------------------------------------------------------------------- */
122
123 void RE_free_envmapdata(EnvMap *env)
124 {
125         Image *ima;
126         int a, part;
127         
128         for(part=0; part<6; part++) {
129                 ima= env->cube[part];
130                 if(ima) {
131                         if(ima->ibuf) IMB_freeImBuf(ima->ibuf);
132
133                         for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) {
134                                 if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]);
135                         }
136                         MEM_freeN(ima);
137                         env->cube[part]= 0;
138                 }
139         }
140         env->ok= 0;
141 }
142
143 /* ------------------------------------------------------------------------- */
144
145 void RE_free_envmap(EnvMap *env)
146 {
147         
148         RE_free_envmapdata(env);
149         MEM_freeN(env);
150         
151 }
152
153 /* ------------------------------------------------------------------------- */
154
155 void envmap_split_ima(EnvMap *env)
156 {
157         ImBuf *ibuf;
158         Image *ima;
159 /*      extern rectcpy(); */
160         int dx, part;
161         
162         RE_free_envmapdata(env);        
163         
164         dx= env->ima->ibuf->y;
165         dx/= 2;
166         if(3*dx != env->ima->ibuf->x) {
167                 error("Incorrect envmap size");
168                 env->ok= 0;
169                 env->ima->ok= 0;
170         }
171         else {
172                 for(part=0; part<6; part++) {
173                         ibuf= IMB_allocImBuf(dx, dx, 24, IB_rect, 0);
174                         ima= MEM_callocN(sizeof(Image), "image");
175                         ima->ibuf= ibuf;
176                         ima->ok= 1;
177                         env->cube[part]= ima;
178                 }
179                 IMB_rectop(env->cube[0]->ibuf, env->ima->ibuf, 
180                         0, 0, 0, 0, dx, dx, IMB_rectcpy, 0);
181                 IMB_rectop(env->cube[1]->ibuf, env->ima->ibuf, 
182                         0, 0, dx, 0, dx, dx, IMB_rectcpy, 0);
183                 IMB_rectop(env->cube[2]->ibuf, env->ima->ibuf, 
184                         0, 0, 2*dx, 0, dx, dx, IMB_rectcpy, 0);
185                 IMB_rectop(env->cube[3]->ibuf, env->ima->ibuf, 
186                         0, 0, 0, dx, dx, dx, IMB_rectcpy, 0);
187                 IMB_rectop(env->cube[4]->ibuf, env->ima->ibuf, 
188                         0, 0, dx, dx, dx, dx, IMB_rectcpy, 0);
189                 IMB_rectop(env->cube[5]->ibuf, env->ima->ibuf, 
190                         0, 0, 2*dx, dx, dx, dx, IMB_rectcpy, 0);
191                 env->ok= 2;
192         }
193 }
194
195 /* ------------------------------------------------------------------------- */
196 /* ****************** RENDER ********************** */
197
198 void envmap_renderdata(EnvMap *env)
199 {
200         static RE_Render envR;
201         static Object *camera;
202         
203         if(env) {
204                 envR= R;
205                 camera= G.scene->camera;
206                 
207                 env->cuberes &= 0xFFFC;
208                 R.rectx= R.r.xsch= R.recty= R.r.ysch= env->cuberes;
209                 R.afmx= R.afmy= R.r.xsch/2;
210                 R.xstart= R.ystart= -R.afmx;
211                 R.xend= R.yend= R.xstart+R.rectx-1;
212
213                 R.r.mode &= ~(R_BORDER | R_PANORAMA | R_ORTHO | R_MBLUR);
214                 R.r.xparts= R.r.yparts= 1;
215                 R.r.bufflag= 0;
216                 R.r.size= 100;
217                 R.ycor= 1.0; 
218                 R.r.yasp= R.r.xasp= 1;
219                 
220                 R.near= env->clipsta;
221                 R.far= env->clipend;
222                 
223                 G.scene->camera= env->object;
224                 
225         }
226         else {
227                 /* this to make sure init_renderdisplay works */
228                 envR.winx= R.winx;
229                 envR.winy= R.winy;
230                 envR.winxof= R.winxof;
231                 envR.winyof= R.winyof;
232                 
233                 R= envR;
234                 G.scene->camera= camera;
235         }
236         
237 }
238
239 /* ------------------------------------------------------------------------- */
240
241 void envmap_transmatrix(float mat[][4], int part)
242 {
243         float tmat[4][4], eul[3], rotmat[4][4];
244         
245         eul[0]= eul[1]= eul[2]= 0.0;
246         
247         if(part==0) {                   /* neg z */
248                 ;
249         } else if(part==1) {    /* pos z */
250                 eul[0]= M_PI;
251         } else if(part==2) {    /* pos y */
252                 eul[0]= M_PI/2.0;
253         } else if(part==3) {    /* neg x */
254                 eul[0]= M_PI/2.0;
255                 eul[2]= M_PI/2.0;
256         } else if(part==4) {    /* neg y */
257                 eul[0]= M_PI/2.0;
258                 eul[2]= M_PI;
259         } else {                                /* pos x */
260                 eul[0]= M_PI/2.0;
261                 eul[2]= -M_PI/2.0;
262         }
263         
264         MTC_Mat4CpyMat4(tmat, mat);
265         EulToMat4(eul, rotmat);
266         MTC_Mat4MulSerie(mat, tmat, rotmat,
267                                          0,   0,    0,
268                                          0,   0,    0);
269 }
270
271 /* ------------------------------------------------------------------------- */
272
273 void env_rotate_scene(float mat[][4], int mode)
274 {
275         VlakRen *vlr = NULL;
276         VertRen *ver = NULL;
277         LampRen *lar = NULL;
278         HaloRen *har = NULL;
279         float xn, yn, zn, imat[3][3], pmat[4][4], smat[4][4], tmat[4][4];
280         int a;
281         
282         if(mode==0) {
283                 MTC_Mat4Invert(tmat, mat);
284                 MTC_Mat3CpyMat4(imat, tmat);
285         }
286         else {
287                 MTC_Mat4CpyMat4(tmat, mat);
288                 MTC_Mat3CpyMat4(imat, mat);
289         }
290         
291         for(a=0; a<R.totvert; a++) {
292                 if((a & 255)==0) ver= R.blove[a>>8];
293                 else ver++;
294                 
295                 MTC_Mat4MulVecfl(tmat, ver->co);
296                 
297                 xn= ver->n[0];
298                 yn= ver->n[1];
299                 zn= ver->n[2];
300                 /* geen transpose ! */
301                 ver->n[0]= imat[0][0]*xn+imat[1][0]*yn+imat[2][0]*zn;
302                 ver->n[1]= imat[0][1]*xn+imat[1][1]*yn+imat[2][1]*zn;
303                 ver->n[2]= imat[0][2]*xn+imat[1][2]*yn+imat[2][2]*zn;
304                 Normalise(ver->n);
305         }
306         
307         for(a=0; a<R.tothalo; a++) {
308                 if((a & 255)==0) har= R.bloha[a>>8];
309                 else har++;
310         
311                 MTC_Mat4MulVecfl(tmat, har->co);
312         }
313                 
314         for(a=0; a<R.totvlak; a++) {
315                 if((a & 255)==0) vlr= R.blovl[a>>8];
316                 else vlr++;
317                 
318                 xn= vlr->n[0];
319                 yn= vlr->n[1];
320                 zn= vlr->n[2];
321                 /* geen transpose ! */
322                 vlr->n[0]= imat[0][0]*xn+imat[1][0]*yn+imat[2][0]*zn;
323                 vlr->n[1]= imat[0][1]*xn+imat[1][1]*yn+imat[2][1]*zn;
324                 vlr->n[2]= imat[0][2]*xn+imat[1][2]*yn+imat[2][2]*zn;
325                 Normalise(vlr->n);
326         }
327         
328         set_normalflags();
329         
330         for(a=0; a<R.totlamp; a++) {
331                 lar= R.la[a];
332
333                 /* smat should actually be a 3x3 matrix, the 4x4 declaration is  */
334                 /* just for confusion.                                           */
335                 
336                 /* Only the left-top 3x3 is copied...? smat is 4by4! imat is 3x3 */
337                 /* Actually, it is not: Mat3CpyMat3 copies the first 9 floats!   */
338                 /* What should happen is mat4cpymat3                             */
339 /*          Mat3CpyMat3(smat, lar->imat); */
340                 MTC_Mat4CpyMat3nc(smat, lar->imat); 
341                 /* This would be lar->imat = smat * imat, so 3d = 4d * 3d?       */
342                 /* the mat3mulmat3 does a multiply on the wrong elements....     */
343 /*              Mat3MulMat3(lar->imat, smat, imat);  */
344                 MTC_Mat4MulMat33(lar->imat, smat, imat); 
345                 MTC_Mat3MulVecfl(imat, lar->vec);
346                 MTC_Mat4MulVecfl(tmat, lar->co);
347
348                 lar->sh_invcampos[0]= -lar->co[0];
349                 lar->sh_invcampos[1]= -lar->co[1];
350                 lar->sh_invcampos[2]= -lar->co[2];
351                 MTC_Mat3MulVecfl(lar->imat, lar->sh_invcampos);
352                 lar->sh_invcampos[2]*= lar->sh_zfac;
353                 
354                 if(lar->shb) {
355                         if(mode==1) {
356                                 MTC_Mat4Invert(pmat, mat);
357                                 MTC_Mat4MulMat4(smat, pmat, lar->shb->viewmat);
358                                 MTC_Mat4MulMat4(lar->shb->persmat, smat, lar->shb->winmat);
359                         }
360                         else MTC_Mat4MulMat4(lar->shb->persmat, lar->shb->viewmat, lar->shb->winmat);
361                 }
362         }
363         
364 }
365
366 /* ------------------------------------------------------------------------- */
367
368 void env_layerflags(unsigned int notlay)
369 {
370         VlakRen *vlr = NULL;
371         int a;
372         
373         for(a=0; a<R.totvlak; a++) {
374                 if((a & 255)==0) vlr= R.blovl[a>>8];
375                 else vlr++;
376                 if(vlr->lay & notlay) vlr->flag &= ~R_VISIBLE;
377         }
378 }
379
380 /* ------------------------------------------------------------------------- */
381
382 void env_set_imats()
383 {
384         Base *base;
385         float mat[4][4];
386         
387         base= G.scene->base.first;
388         while(base) {
389                 MTC_Mat4MulMat4(mat, base->object->obmat, R.viewmat);
390                 MTC_Mat4Invert(base->object->imat, mat);
391                 
392                 base= base->next;
393         }
394
395 }       
396
397 /* ------------------------------------------------------------------------- */
398
399 void render_envmap(EnvMap *env)
400 {
401         /* only the cubemap is implemented */
402         ImBuf *ibuf;
403         Image *ima;
404         float oldviewinv[4][4], mat[4][4], tmat[4][4];
405         short part;
406         
407         /* need a recalc: ortho-render has no correct viewinv */
408         MTC_Mat4Invert(oldviewinv, R.viewmat);
409
410         /* setup necessary globals */
411         envmap_renderdata(env);
412         
413         RE_local_init_render_display();
414
415         R.rectot= MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectot");
416         R.rectz=  MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectz");
417
418         for(part=0; part<6; part++) {
419
420                 RE_local_clear_render_display(R.win);
421                 fillrect(R.rectot, R.rectx, R.recty, 0);
422                 
423                 RE_setwindowclip(1,-1); /*  geen jit:(-1) */
424                 
425                 MTC_Mat4CpyMat4(tmat, G.scene->camera->obmat);
426                 MTC_Mat4Ortho(tmat);
427                 envmap_transmatrix(tmat, part);
428                 MTC_Mat4Invert(mat, tmat);
429                 /* mat now is the camera 'viewmat' */
430
431                 MTC_Mat4CpyMat4(R.viewmat, mat);
432                 MTC_Mat4CpyMat4(R.viewinv, tmat);
433                 
434                 /* we have to correct for the already rotated vertexcoords */
435                 MTC_Mat4MulMat4(tmat, oldviewinv, R.viewmat);
436                 MTC_Mat4Invert(env->imat, tmat);
437                 
438                 env_rotate_scene(tmat, 1);
439                 init_render_world();
440                 setzbufvlaggen(RE_projectverto);
441                 env_layerflags(env->notlay);
442                 env_set_imats();
443                                 
444                 if(RE_local_test_break()==0) {
445
446                         RE_local_printrenderinfo(0.0, part);
447
448                         if(R.r.mode & R_OSA) zbufshadeDA();
449                         else zbufshade();
450
451                 }
452                 
453                 /* rotate back */
454                 env_rotate_scene(tmat, 0);
455
456                 if(RE_local_test_break()==0) {
457                         ibuf= IMB_allocImBuf(R.rectx, R.recty, 24, IB_rect, 0);
458                         ima= MEM_callocN(sizeof(Image), "image");
459                         memcpy(ibuf->rect, R.rectot, 4*ibuf->x*ibuf->y);
460                         ima->ibuf= ibuf;
461                         ima->ok= 1;
462                         env->cube[part]= ima;
463                 }
464                 
465                 if(RE_local_test_break()) break;
466
467         }
468         
469         if(R.rectz) MEM_freeN(R.rectz); R.rectz= 0;
470         if(R.rectot) MEM_freeN(R.rectot); R.rectot= 0;
471         
472         if(RE_local_test_break()) RE_free_envmapdata(env);
473         else {
474                 if(R.r.mode & R_OSA) env->ok= ENV_OSA;
475                 else env->ok= ENV_NORMAL;
476                 env->lastframe= G.scene->r.cfra;
477         }
478         
479         /* restore */
480         envmap_renderdata(0);
481         env_set_imats();
482         init_render_world();
483
484 }
485
486 /* ------------------------------------------------------------------------- */
487
488 void make_envmaps()
489 {
490         Tex *tex;
491         int do_init= 0;
492         
493         tex= G.main->tex.first;
494         while(tex) {
495                 if(tex->id.us && tex->type==TEX_ENVMAP) {
496                         if(tex->env && tex->env->object) {
497                                 if(tex->env->object->lay & G.scene->lay) {
498                                         if(tex->env->stype!=ENV_LOAD) {
499                                                 
500                                                 if(tex->env->ok==0) {
501                                                         do_init= 1;
502                                                         render_envmap(tex->env);
503                                                 }
504                                                 else if((R.r.mode & R_OSA) && tex->env->ok==ENV_NORMAL) {
505                                                         do_init= 1;
506                                                         RE_free_envmapdata(tex->env);
507                                                         render_envmap(tex->env);
508                                                 }
509                                         }
510                                 }
511                         }
512                 }
513                 tex= tex->id.next;
514         }
515
516         if(do_init) {
517                 RE_local_init_render_display();
518                 RE_local_clear_render_display(R.win);
519                 allqueue(REDRAWBUTSTEX, 0);
520         }
521 }
522
523 /* ------------------------------------------------------------------------- */
524
525 int envcube_isect(float *vec, float *answ)
526 {
527         float labda;
528         int face;
529         
530         /* which face */
531         if( vec[2]<=-fabs(vec[0]) && vec[2]<=-fabs(vec[1]) ) {
532                 face= 0;
533                 labda= -1.0/vec[2];
534                 answ[0]= labda*vec[0];
535                 answ[1]= labda*vec[1];
536         }
537         else if( vec[2]>=fabs(vec[0]) && vec[2]>=fabs(vec[1]) ) {
538                 face= 1;
539                 labda= 1.0/vec[2];
540                 answ[0]= labda*vec[0];
541                 answ[1]= -labda*vec[1];
542         }
543         else if( vec[1]>=fabs(vec[0]) ) {
544                 face= 2;
545                 labda= 1.0/vec[1];
546                 answ[0]= labda*vec[0];
547                 answ[1]= labda*vec[2];
548         }
549         else if( vec[0]<=-fabs(vec[1]) ) {
550                 face= 3;
551                 labda= -1.0/vec[0];
552                 answ[0]= labda*vec[1];
553                 answ[1]= labda*vec[2];
554         }
555         else if( vec[1]<=-fabs(vec[0]) ) {
556                 face= 4;
557                 labda= -1.0/vec[1];
558                 answ[0]= -labda*vec[0];
559                 answ[1]= labda*vec[2];
560         }
561         else {
562                 face= 5;
563                 labda= 1.0/vec[0];
564                 answ[0]= -labda*vec[1];
565                 answ[1]= labda*vec[2];
566         }
567         answ[0]= 0.5+0.5*answ[0];
568         answ[1]= 0.5+0.5*answ[1];
569         return face;
570 }
571
572 /* ------------------------------------------------------------------------- */
573
574 static void set_dxtdyt(float *dxts, float *dyts, float *dxt, float *dyt, int face)
575 {
576         if(face==2 || face==4) {
577                 dxts[0]= dxt[0];
578                 dyts[0]= dyt[0];
579                 dxts[1]= dxt[2];
580                 dyts[1]= dyt[2];
581         }
582         else if(face==3 || face==5) {
583                 dxts[0]= dxt[1];
584                 dxts[1]= dxt[2];
585                 dyts[0]= dyt[1];
586                 dyts[1]= dyt[2];
587         }
588         else {
589                 dxts[0]= dxt[0];
590                 dyts[0]= dyt[0];
591                 dxts[1]= dxt[1];
592                 dyts[1]= dyt[1];
593         }
594 }
595
596 /* ------------------------------------------------------------------------- */
597
598 extern float Tin, Ta, Tr, Tg, Tb; /* texture.c */
599 int RE_envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt)
600 {
601         /* texvec should be the already reflected normal */
602         EnvMap *env;
603         float fac, vec[3], sco[3], col[20], dxts[3], dyts[3];
604         int face, face1;
605         
606         env= tex->env;
607         if(env==0 || env->object==0) return 0;
608         
609         if(env->stype==ENV_LOAD) {
610                 env->ima= tex->ima;
611                 if(env->ima && env->ima->ok) {
612                         if(env->ima->ibuf==0) ima_ibuf_is_nul(tex);
613                         if(env->ima->ok && env->ok==0) envmap_split_ima(env);
614                 }
615         }
616
617         if(env->ok==0) {
618                 
619                 Tin= 0.0;
620                 return 0;
621         }
622         
623         /* rotate to envmap space */
624         VECCOPY(vec, texvec);
625         MTC_Mat4Mul3Vecfl(env->object->imat, vec);
626         
627         face= envcube_isect(vec, sco);
628         tex->ima= env->cube[face];
629         
630         if(R.osatex) {
631                 MTC_Mat4Mul3Vecfl(env->object->imat, dxt);
632                 MTC_Mat4Mul3Vecfl(env->object->imat, dyt);
633                 
634                 set_dxtdyt(dxts, dyts, dxt, dyt, face);
635                 imagewraposa(tex, sco, dxts, dyts);
636                 
637                 /* edges? */
638                 
639                 if(Ta<1.0) {
640                         col[0]= Ta; col[1]= Tr; col[2]= Tg; col[3]= Tb;
641         
642                         VecAddf(vec, vec, dxt);
643                         face1= envcube_isect(vec, sco);
644                         VecSubf(vec, vec, dxt);
645                         
646                         if(face!=face1) {
647                                 tex->ima= env->cube[face1];
648                                 set_dxtdyt(dxts, dyts, dxt, dyt, face1);
649                                 imagewraposa(tex, sco, dxts, dyts);
650                                 col[4]= Ta; col[5]= Tr; col[6]= Tg; col[7]= Tb;
651                         }
652                         else col[4]= col[5]= col[6]= col[7]= 0.0;
653                         
654                         /* here was the nasty bug! col[5,6,7] were not zero-ed. FPE! */
655                         
656                         VecAddf(vec, vec, dyt);
657                         face1= envcube_isect(vec, sco);
658                         VecSubf(vec, vec, dyt);
659                         
660                         if(face!=face1) {
661                                 tex->ima= env->cube[face1];
662                                 set_dxtdyt(dxts, dyts, dxt, dyt, face1);
663                                 imagewraposa(tex, sco, dxts, dyts);
664                                 col[8]= Ta; col[9]= Tr; col[10]= Tg; col[11]= Tb;
665                         }
666                         else col[8]= col[9]= col[10]= col[11]= 0.0;
667                         
668                         fac= (col[0]+col[4]+col[8]);
669                         fac= 1.0/fac;
670                         
671                         Tr= fac*(col[0]*col[1] + col[4]*col[5] + col[8]*col[9] );
672                         Tg= fac*(col[0]*col[2] + col[4]*col[6] + col[8]*col[10] );
673                         Tb= fac*(col[0]*col[3] + col[4]*col[7] + col[8]*col[11] );
674                         Ta= 1.0;
675
676                 }
677         }
678         else {
679                 imagewrap(tex, sco);
680         }
681         
682         tex->ima= env->ima;
683         
684         return 1;
685 }
686
687 /* ------------------------------------------------------------------------- */
688
689 /* eof */