f5a87ba7ae7914f6203d9fbfcca24c440d020a35
[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 HAVE_CONFIG_H
41 #include <config.h>
42 #endif
43
44 #ifdef WIN32
45 #include "BLI_winstuff.h"
46 #endif
47
48 /* external modules: */
49 #include "MEM_guardedalloc.h"
50 #include "BLI_arithb.h"
51 #include "BLI_blenlib.h"
52 #include "IMB_imbuf_types.h"
53 #include "IMB_imbuf.h"        /* for rectcpy */
54
55 #include "DNA_texture_types.h"
56 #include "DNA_image_types.h"
57 #include "DNA_object_types.h"
58 #include "DNA_scene_types.h"
59 #include "DNA_texture_types.h"
60
61 #include "BIF_space.h"
62 #include "BIF_toolbox.h"
63
64 #include "BKE_library.h"
65 #include "BKE_main.h"
66 #include "BKE_global.h"
67 #include "BKE_world.h"   // init_render_world
68 #include "BKE_image.h"   // BKE_write_ibuf 
69
70
71 /* this module */
72 #include "RE_callbacks.h"
73 #include "render.h"
74 #include "render_intern.h"
75 #include "envmap.h"
76 #include "mydevice.h"
77 #include "rendercore.h" /* calls zbufShade(DA).... I want to replace this with my own :)*/
78 #include "renderHelp.h"
79 #include "MTC_matrixops.h"
80 #include "zbuf.h"
81
82 /* ------------------------------------------------------------------------- */
83
84 void envmap_split_ima(EnvMap *env);
85 void envmap_renderdata(EnvMap *env);
86 void envmap_transmatrix(float mat[][4], int part);
87 void env_rotate_scene(float mat[][4], int mode);
88 void env_layerflags(unsigned int notlay);
89 void env_set_imats(void);
90 void render_envmap(EnvMap *env);
91 int envcube_isect(float *vec, float *answ);
92 static void set_dxtdyt(float *dxts, float *dyts, float *dxt, float *dyt, int face);
93
94 /* ------------------------------------------------------------------------- */
95
96 EnvMap *RE_add_envmap(void)
97 {
98         EnvMap *env;
99         
100         env= MEM_callocN(sizeof(EnvMap), "envmap");
101         env->type= ENV_CUBE;
102         env->stype= ENV_STATIC;
103         env->clipsta= 0.1;
104         env->clipend= 100.0;
105         env->cuberes= 100;
106         
107         return env;
108 } /* end of EnvMap *RE_add_envmap() */
109
110 /* ------------------------------------------------------------------------- */
111
112 EnvMap *RE_copy_envmap(EnvMap *env)
113 {
114         EnvMap *envn;
115         int a;
116         
117         envn= MEM_dupallocN(env);
118         envn->ok= 0;
119         for(a=0; a<6; a++) envn->cube[a]= 0;
120         if(envn->ima) id_us_plus((ID *)envn->ima);
121         
122         return envn;
123 }
124
125 /* ------------------------------------------------------------------------- */
126
127 void RE_free_envmapdata(EnvMap *env)
128 {
129         Image *ima;
130         int a, part;
131         
132         for(part=0; part<6; part++) {
133                 ima= env->cube[part];
134                 if(ima) {
135                         if(ima->ibuf) IMB_freeImBuf(ima->ibuf);
136
137                         for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) {
138                                 if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]);
139                         }
140                         MEM_freeN(ima);
141                         env->cube[part]= 0;
142                 }
143         }
144         env->ok= 0;
145 }
146
147 /* ------------------------------------------------------------------------- */
148
149 void RE_free_envmap(EnvMap *env)
150 {
151         
152         RE_free_envmapdata(env);
153         MEM_freeN(env);
154         
155 }
156
157 /* ------------------------------------------------------------------------- */
158
159 void envmap_split_ima(EnvMap *env)
160 {
161         ImBuf *ibuf;
162         Image *ima;
163 /*      extern rectcpy(); */
164         int dx, part;
165         
166         RE_free_envmapdata(env);        
167         
168         dx= env->ima->ibuf->y;
169         dx/= 2;
170         if(3*dx != env->ima->ibuf->x) {
171                 error("Incorrect envmap size");
172                 env->ok= 0;
173                 env->ima->ok= 0;
174         }
175         else {
176                 for(part=0; part<6; part++) {
177                         ibuf= IMB_allocImBuf(dx, dx, 24, IB_rect, 0);
178                         ima= MEM_callocN(sizeof(Image), "image");
179                         ima->ibuf= ibuf;
180                         ima->ok= 1;
181                         env->cube[part]= ima;
182                 }
183                 IMB_rectop(env->cube[0]->ibuf, env->ima->ibuf, 
184                         0, 0, 0, 0, dx, dx, IMB_rectcpy, 0);
185                 IMB_rectop(env->cube[1]->ibuf, env->ima->ibuf, 
186                         0, 0, dx, 0, dx, dx, IMB_rectcpy, 0);
187                 IMB_rectop(env->cube[2]->ibuf, env->ima->ibuf, 
188                         0, 0, 2*dx, 0, dx, dx, IMB_rectcpy, 0);
189                 IMB_rectop(env->cube[3]->ibuf, env->ima->ibuf, 
190                         0, 0, 0, dx, dx, dx, IMB_rectcpy, 0);
191                 IMB_rectop(env->cube[4]->ibuf, env->ima->ibuf, 
192                         0, 0, dx, dx, dx, dx, IMB_rectcpy, 0);
193                 IMB_rectop(env->cube[5]->ibuf, env->ima->ibuf, 
194                         0, 0, 2*dx, dx, dx, dx, IMB_rectcpy, 0);
195                 env->ok= 2;
196         }
197 }
198
199 /* ------------------------------------------------------------------------- */
200 /* ****************** RENDER ********************** */
201
202 void envmap_renderdata(EnvMap *env)
203 {
204         static RE_Render envR;
205         static Object *camera;
206         int cuberes;
207         
208         if(env) {
209                 envR= R;
210                 camera= G.scene->camera;
211                 
212                 cuberes = (env->cuberes * R.r.size) / 100;
213                 cuberes &= 0xFFFC;
214                 env->lastsize= R.r.size;
215                 R.rectx= R.r.xsch= R.recty= R.r.ysch= cuberes;
216                 R.afmx= R.afmy= R.r.xsch/2;
217                 R.xstart= R.ystart= -R.afmx;
218                 R.xend= R.yend= R.xstart+R.rectx-1;
219
220                 R.r.mode &= ~(R_BORDER | R_PANORAMA | R_ORTHO | R_MBLUR);
221                 R.r.xparts= R.r.yparts= 1;
222                 R.r.bufflag= 0;
223                 R.r.size= 100;
224                 R.ycor= 1.0; 
225                 R.r.yasp= R.r.xasp= 1;
226                 
227                 R.near= env->clipsta;
228                 R.far= env->clipend;
229                 
230                 G.scene->camera= env->object;
231                 
232         }
233         else {
234                 /* this to make sure init_renderdisplay works */
235                 envR.winx= R.winx;
236                 envR.winy= R.winy;
237                 envR.winxof= R.winxof;
238                 envR.winyof= R.winyof;
239                 
240                 R= envR;
241                 G.scene->camera= camera;
242         }
243         
244 }
245
246 /* ------------------------------------------------------------------------- */
247
248 void envmap_transmatrix(float mat[][4], int part)
249 {
250         float tmat[4][4], eul[3], rotmat[4][4];
251         
252         eul[0]= eul[1]= eul[2]= 0.0;
253         
254         if(part==0) {                   /* neg z */
255                 ;
256         } else if(part==1) {    /* pos z */
257                 eul[0]= M_PI;
258         } else if(part==2) {    /* pos y */
259                 eul[0]= M_PI/2.0;
260         } else if(part==3) {    /* neg x */
261                 eul[0]= M_PI/2.0;
262                 eul[2]= M_PI/2.0;
263         } else if(part==4) {    /* neg y */
264                 eul[0]= M_PI/2.0;
265                 eul[2]= M_PI;
266         } else {                                /* pos x */
267                 eul[0]= M_PI/2.0;
268                 eul[2]= -M_PI/2.0;
269         }
270         
271         MTC_Mat4CpyMat4(tmat, mat);
272         EulToMat4(eul, rotmat);
273         MTC_Mat4MulSerie(mat, tmat, rotmat,
274                                          0,   0,    0,
275                                          0,   0,    0);
276 }
277
278 /* ------------------------------------------------------------------------- */
279
280 void env_rotate_scene(float mat[][4], int mode)
281 {
282         VlakRen *vlr = NULL;
283         VertRen *ver = NULL;
284         LampRen *lar = NULL;
285         HaloRen *har = NULL;
286         float xn, yn, zn, imat[3][3], pmat[4][4], smat[4][4], tmat[4][4], cmat[3][3];
287         int a;
288         
289         if(mode==0) {
290                 MTC_Mat4Invert(tmat, mat);
291                 MTC_Mat3CpyMat4(imat, tmat);
292         }
293         else {
294                 MTC_Mat4CpyMat4(tmat, mat);
295                 MTC_Mat3CpyMat4(imat, mat);
296         }
297         
298         for(a=0; a<R.totvert; a++) {
299                 if((a & 255)==0) ver= R.blove[a>>8];
300                 else ver++;
301                 
302                 MTC_Mat4MulVecfl(tmat, ver->co);
303                 
304                 xn= ver->n[0];
305                 yn= ver->n[1];
306                 zn= ver->n[2];
307                 /* no transpose ! */
308                 ver->n[0]= imat[0][0]*xn+imat[1][0]*yn+imat[2][0]*zn;
309                 ver->n[1]= imat[0][1]*xn+imat[1][1]*yn+imat[2][1]*zn;
310                 ver->n[2]= imat[0][2]*xn+imat[1][2]*yn+imat[2][2]*zn;
311                 Normalise(ver->n);
312         }
313         
314         for(a=0; a<R.tothalo; a++) {
315                 if((a & 255)==0) har= R.bloha[a>>8];
316                 else har++;
317         
318                 MTC_Mat4MulVecfl(tmat, har->co);
319         }
320                 
321         for(a=0; a<R.totvlak; a++) {
322                 if((a & 255)==0) vlr= R.blovl[a>>8];
323                 else vlr++;
324                 
325                 xn= vlr->n[0];
326                 yn= vlr->n[1];
327                 zn= vlr->n[2];
328                 /* no transpose ! */
329                 vlr->n[0]= imat[0][0]*xn+imat[1][0]*yn+imat[2][0]*zn;
330                 vlr->n[1]= imat[0][1]*xn+imat[1][1]*yn+imat[2][1]*zn;
331                 vlr->n[2]= imat[0][2]*xn+imat[1][2]*yn+imat[2][2]*zn;
332                 Normalise(vlr->n);
333         }
334         
335         set_normalflags();
336         
337         for(a=0; a<R.totlamp; a++) {
338                 lar= R.la[a];
339                 
340                 /* removed here some horrible code of someone in NaN who tried to fix
341                    prototypes... just solved by introducing a correct cmat[3][3] instead
342                    of using smat. this works, check square spots in reflections  (ton) */
343                 Mat3CpyMat3(cmat, lar->imat); 
344                 Mat3MulMat3(lar->imat, cmat, imat); 
345
346                 MTC_Mat3MulVecfl(imat, lar->vec);
347                 MTC_Mat4MulVecfl(tmat, lar->co);
348
349                 lar->sh_invcampos[0]= -lar->co[0];
350                 lar->sh_invcampos[1]= -lar->co[1];
351                 lar->sh_invcampos[2]= -lar->co[2];
352                 MTC_Mat3MulVecfl(lar->imat, lar->sh_invcampos);
353                 lar->sh_invcampos[2]*= lar->sh_zfac;
354                 
355                 if(lar->shb) {
356                         if(mode==1) {
357                                 MTC_Mat4Invert(pmat, mat);
358                                 MTC_Mat4MulMat4(smat, pmat, lar->shb->viewmat);
359                                 MTC_Mat4MulMat4(lar->shb->persmat, smat, lar->shb->winmat);
360                         }
361                         else MTC_Mat4MulMat4(lar->shb->persmat, lar->shb->viewmat, lar->shb->winmat);
362                 }
363         }
364         
365 }
366
367 /* ------------------------------------------------------------------------- */
368
369 void env_layerflags(unsigned int notlay)
370 {
371         VlakRen *vlr = NULL;
372         int a;
373         
374         for(a=0; a<R.totvlak; a++) {
375                 if((a & 255)==0) vlr= R.blovl[a>>8];
376                 else vlr++;
377                 if(vlr->lay & notlay) vlr->flag &= ~R_VISIBLE;
378         }
379 }
380
381 void env_hideobject(Object *ob)
382 {
383         VlakRen *vlr = NULL;
384         int a;
385         
386         for(a=0; a<R.totvlak; a++) {
387                 if((a & 255)==0) vlr= R.blovl[a>>8];
388                 else vlr++;
389                 if(vlr->ob == ob) vlr->flag &= ~R_VISIBLE;
390         }
391 }
392
393 /* ------------------------------------------------------------------------- */
394
395 void env_set_imats()
396 {
397         Base *base;
398         float mat[4][4];
399         
400         base= G.scene->base.first;
401         while(base) {
402                 MTC_Mat4MulMat4(mat, base->object->obmat, R.viewmat);
403                 MTC_Mat4Invert(base->object->imat, mat);
404                 
405                 base= base->next;
406         }
407
408 }       
409
410 /* ------------------------------------------------------------------------- */
411
412 void render_envmap(EnvMap *env)
413 {
414         /* only the cubemap is implemented */
415         ImBuf *ibuf;
416         Image *ima;
417         float oldviewinv[4][4], mat[4][4], tmat[4][4];
418         short part;
419         
420         /* need a recalc: ortho-render has no correct viewinv */
421         MTC_Mat4Invert(oldviewinv, R.viewmat);
422
423         /* setup necessary globals */
424         envmap_renderdata(env);
425         
426         RE_local_init_render_display();
427
428         R.rectot= MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectot");
429         R.rectz=  MEM_mallocN(sizeof(int)*R.rectx*R.recty, "rectz");
430
431         for(part=0; part<6; part++) {
432
433                 RE_local_clear_render_display(R.win);
434                 fillrect(R.rectot, R.rectx, R.recty, 0);
435                 
436                 RE_setwindowclip(1,-1); /*  no jit:(-1) */
437                 
438                 MTC_Mat4CpyMat4(tmat, G.scene->camera->obmat);
439                 MTC_Mat4Ortho(tmat);
440                 envmap_transmatrix(tmat, part);
441                 MTC_Mat4Invert(mat, tmat);
442                 /* mat now is the camera 'viewmat' */
443
444                 MTC_Mat4CpyMat4(R.viewmat, mat);
445                 MTC_Mat4CpyMat4(R.viewinv, tmat);
446                 
447                 /* we have to correct for the already rotated vertexcoords */
448                 MTC_Mat4MulMat4(tmat, oldviewinv, R.viewmat);
449                 MTC_Mat4Invert(env->imat, tmat);
450                 
451                 env_rotate_scene(tmat, 1);
452                 init_render_world();
453                 setzbufvlaggen(RE_projectverto);
454                 env_layerflags(env->notlay);
455                 env_hideobject(env->object);
456                 env_set_imats();
457                                 
458                 if(RE_local_test_break()==0) {
459
460                         RE_local_printrenderinfo(0.0, part);
461
462                         if(R.r.mode & R_OSA) zbufshadeDA();
463                         else zbufshade();
464
465                 }
466                 
467                 /* rotate back */
468                 env_rotate_scene(tmat, 0);
469
470                 if(RE_local_test_break()==0) {
471                         ibuf= IMB_allocImBuf(R.rectx, R.recty, 24, IB_rect, 0);
472                         ima= MEM_callocN(sizeof(Image), "image");
473                         memcpy(ibuf->rect, R.rectot, 4*ibuf->x*ibuf->y);
474                         ima->ibuf= ibuf;
475                         ima->ok= 1;
476                         env->cube[part]= ima;
477                 }
478                 
479                 if(RE_local_test_break()) break;
480
481         }
482         
483         if(R.rectz) MEM_freeN(R.rectz); R.rectz= 0;
484         if(R.rectot) MEM_freeN(R.rectot); R.rectot= 0;
485         
486         if(RE_local_test_break()) RE_free_envmapdata(env);
487         else {
488                 if(R.r.mode & R_OSA) env->ok= ENV_OSA;
489                 else env->ok= ENV_NORMAL;
490                 env->lastframe= G.scene->r.cfra;
491         }
492         
493         /* restore */
494         envmap_renderdata(0);
495         env_set_imats();
496         init_render_world();
497
498 }
499
500 /* ------------------------------------------------------------------------- */
501
502 void make_envmaps()
503 {
504         Tex *tex;
505         int do_init= 0, depth= 0, trace;
506         
507         if (!(R.r.mode & R_ENVMAP)) return;
508         
509         /* we dont raytrace, disabling the flag will cause ray_transp render solid */
510         trace= (R.r.mode & R_RAYTRACE);
511         R.r.mode &= ~R_RAYTRACE;
512
513         /* 5 = hardcoded max recursion level */
514         while(depth<5) {
515                 tex= G.main->tex.first;
516                 while(tex) {
517                         if(tex->id.us && tex->type==TEX_ENVMAP) {
518                                 if(tex->env && tex->env->object) {
519                                         if(tex->env->object->lay & G.scene->lay) {
520                                                 if(tex->env->stype!=ENV_LOAD) {
521                                                         
522                                                         /* decide if to render an envmap (again) */
523                                                         if(tex->env->depth >= depth) {
524                                                                 
525                                                                 /* set 'recalc' to make sure it does an entire loop of recalcs */
526                                                                 
527                                                                 if(tex->env->ok) {
528                                                                                 /* free when OSA, and old one isn't OSA */
529                                                                         if((R.r.mode & R_OSA) && tex->env->ok==ENV_NORMAL) 
530                                                                                 RE_free_envmapdata(tex->env);
531                                                                                 /* free when size larger */
532                                                                         else if(tex->env->lastsize < R.r.size) 
533                                                                                 RE_free_envmapdata(tex->env);
534                                                                                 /* free when env is in recalcmode */
535                                                                         else if(tex->env->recalc)
536                                                                                 RE_free_envmapdata(tex->env);
537                                                                 }
538                                                                 
539                                                                 if(tex->env->ok==0 && depth==0) tex->env->recalc= 1;
540                                                                 
541                                                                 if(tex->env->ok==0) {
542                                                                         do_init= 1;
543                                                                         render_envmap(tex->env);
544                                                                         
545                                                                         if(depth==tex->env->depth) tex->env->recalc= 0;
546                                                                 }
547                                                         }
548                                                 }
549                                         }
550                                 }
551                         }
552                         tex= tex->id.next;
553                 }
554                 depth++;
555         }
556
557         if(do_init) {
558                 RE_local_init_render_display();
559                 RE_local_clear_render_display(R.win);
560                 allqueue(REDRAWBUTSSHADING, 0);                 // bad!
561         }       
562         // restore
563         R.r.mode |= trace;
564
565 }
566
567 /* ------------------------------------------------------------------------- */
568
569 int envcube_isect(float *vec, float *answ)
570 {
571         float labda;
572         int face;
573         
574         /* which face */
575         if( vec[2]<=-fabs(vec[0]) && vec[2]<=-fabs(vec[1]) ) {
576                 face= 0;
577                 labda= -1.0/vec[2];
578                 answ[0]= labda*vec[0];
579                 answ[1]= labda*vec[1];
580         }
581         else if( vec[2]>=fabs(vec[0]) && vec[2]>=fabs(vec[1]) ) {
582                 face= 1;
583                 labda= 1.0/vec[2];
584                 answ[0]= labda*vec[0];
585                 answ[1]= -labda*vec[1];
586         }
587         else if( vec[1]>=fabs(vec[0]) ) {
588                 face= 2;
589                 labda= 1.0/vec[1];
590                 answ[0]= labda*vec[0];
591                 answ[1]= labda*vec[2];
592         }
593         else if( vec[0]<=-fabs(vec[1]) ) {
594                 face= 3;
595                 labda= -1.0/vec[0];
596                 answ[0]= labda*vec[1];
597                 answ[1]= labda*vec[2];
598         }
599         else if( vec[1]<=-fabs(vec[0]) ) {
600                 face= 4;
601                 labda= -1.0/vec[1];
602                 answ[0]= -labda*vec[0];
603                 answ[1]= labda*vec[2];
604         }
605         else {
606                 face= 5;
607                 labda= 1.0/vec[0];
608                 answ[0]= -labda*vec[1];
609                 answ[1]= labda*vec[2];
610         }
611         answ[0]= 0.5+0.5*answ[0];
612         answ[1]= 0.5+0.5*answ[1];
613         return face;
614 }
615
616 /* ------------------------------------------------------------------------- */
617
618 static void set_dxtdyt(float *dxts, float *dyts, float *dxt, float *dyt, int face)
619 {
620         if(face==2 || face==4) {
621                 dxts[0]= dxt[0];
622                 dyts[0]= dyt[0];
623                 dxts[1]= dxt[2];
624                 dyts[1]= dyt[2];
625         }
626         else if(face==3 || face==5) {
627                 dxts[0]= dxt[1];
628                 dxts[1]= dxt[2];
629                 dyts[0]= dyt[1];
630                 dyts[1]= dyt[2];
631         }
632         else {
633                 dxts[0]= dxt[0];
634                 dyts[0]= dyt[0];
635                 dxts[1]= dxt[1];
636                 dyts[1]= dyt[1];
637         }
638 }
639
640 /* ------------------------------------------------------------------------- */
641
642 extern float Tin, Ta, Tr, Tg, Tb; /* texture.c */
643 int envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex)
644 {
645         /* texvec should be the already reflected normal */
646         EnvMap *env;
647         float fac, vec[3], sco[3], col[20], dxts[3], dyts[3];
648         int face, face1;
649         
650         env= tex->env;
651         if(env==0 || env->object==0) {
652                 Tin= 0.0;
653                 return 0;
654         }
655         if(env->stype==ENV_LOAD) {
656                 env->ima= tex->ima;
657                 if(env->ima && env->ima->ok) {
658                         if(env->ima->ibuf==0) ima_ibuf_is_nul(tex);
659                         if(env->ima->ok && env->ok==0) envmap_split_ima(env);
660                 }
661         }
662
663         if(env->ok==0) {
664                 
665                 Tin= 0.0;
666                 return 0;
667         }
668         
669         /* rotate to envmap space */
670         VECCOPY(vec, texvec);
671         MTC_Mat4Mul3Vecfl(env->object->imat, vec);
672         
673         face= envcube_isect(vec, sco);
674         tex->ima= env->cube[face];
675         
676         if(osatex) {
677                 MTC_Mat4Mul3Vecfl(env->object->imat, dxt);
678                 MTC_Mat4Mul3Vecfl(env->object->imat, dyt);
679                 
680                 set_dxtdyt(dxts, dyts, dxt, dyt, face);
681                 imagewraposa(tex, sco, dxts, dyts);
682                 
683                 /* edges? */
684                 
685                 if(Ta<1.0) {
686                         col[0]= Ta; col[1]= Tr; col[2]= Tg; col[3]= Tb;
687         
688                         VecAddf(vec, vec, dxt);
689                         face1= envcube_isect(vec, sco);
690                         VecSubf(vec, vec, dxt);
691                         
692                         if(face!=face1) {
693                                 tex->ima= env->cube[face1];
694                                 set_dxtdyt(dxts, dyts, dxt, dyt, face1);
695                                 imagewraposa(tex, sco, dxts, dyts);
696                                 col[4]= Ta; col[5]= Tr; col[6]= Tg; col[7]= Tb;
697                         }
698                         else col[4]= col[5]= col[6]= col[7]= 0.0;
699                         
700                         /* here was the nasty bug! col[5,6,7] were not zero-ed. FPE! */
701                         
702                         VecAddf(vec, vec, dyt);
703                         face1= envcube_isect(vec, sco);
704                         VecSubf(vec, vec, dyt);
705                         
706                         if(face!=face1) {
707                                 tex->ima= env->cube[face1];
708                                 set_dxtdyt(dxts, dyts, dxt, dyt, face1);
709                                 imagewraposa(tex, sco, dxts, dyts);
710                                 col[8]= Ta; col[9]= Tr; col[10]= Tg; col[11]= Tb;
711                         }
712                         else col[8]= col[9]= col[10]= col[11]= 0.0;
713                         
714                         fac= (col[0]+col[4]+col[8]);
715                         fac= 1.0/fac;
716                         
717                         Tr= fac*(col[0]*col[1] + col[4]*col[5] + col[8]*col[9] );
718                         Tg= fac*(col[0]*col[2] + col[4]*col[6] + col[8]*col[10] );
719                         Tb= fac*(col[0]*col[3] + col[4]*col[7] + col[8]*col[11] );
720                         Ta= 1.0;
721
722                 }
723         }
724         else {
725                 imagewrap(tex, sco);
726         }
727         
728         tex->ima= env->ima;
729         
730         return 1;
731 }
732
733 /* ------------------------------------------------------------------------- */
734
735 /* eof */