Color Management: fixed color management-less texture rendering
[blender.git] / source / blender / render / intern / source / envmap.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributors: 2004/2005/2006 Blender Foundation, full recode
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/render/intern/source/envmap.c
27  *  \ingroup render
28  */
29
30 #include <math.h>
31 #include <string.h>
32
33 /* external modules: */
34 #include "MEM_guardedalloc.h"
35
36 #include "BLI_math.h"
37 #include "BLI_blenlib.h"
38 #include "BLI_threads.h"
39 #include "BLI_utildefines.h"
40
41 #include "IMB_imbuf_types.h"
42 #include "IMB_imbuf.h"        /* for rectcpy */
43
44 #include "DNA_group_types.h"
45 #include "DNA_image_types.h"
46 #include "DNA_object_types.h"
47 #include "DNA_scene_types.h"
48 #include "DNA_texture_types.h"
49
50 #include "BKE_library.h"
51 #include "BKE_main.h"
52 #include "BKE_image.h"   /* BKE_imbuf_write */
53 #include "BKE_texture.h"
54
55
56
57
58 /* this module */
59 #include "render_types.h"
60 #include "renderpipeline.h"
61 #include "envmap.h"
62 #include "rendercore.h" 
63 #include "renderdatabase.h" 
64 #include "texture.h"
65 #include "zbuf.h"
66 #include "initrender.h"
67
68
69 /* ------------------------------------------------------------------------- */
70
71 static void envmap_split_ima(EnvMap *env, ImBuf *ibuf)
72 {
73         int dx, part;
74         
75         /* after lock we test cube[1], if set the other thread has done it fine */
76         BLI_lock_thread(LOCK_IMAGE);
77         if (env->cube[1] == NULL) {
78
79                 BKE_free_envmapdata(env);       
80         
81                 dx = ibuf->y;
82                 dx /= 2;
83                 if (3 * dx == ibuf->x) {
84                         env->type = ENV_CUBE;
85                         env->ok = ENV_OSA;
86                 }
87                 else if (ibuf->x == ibuf->y) {
88                         env->type = ENV_PLANE;
89                         env->ok = ENV_OSA;
90                 }
91                 else {
92                         printf("Incorrect envmap size\n");
93                         env->ok = 0;
94                         env->ima->ok = 0;
95                 }
96                 
97                 if (env->ok) {
98                         if (env->type == ENV_CUBE) {
99                                 for (part = 0; part < 6; part++) {
100                                         env->cube[part] = IMB_allocImBuf(dx, dx, 24, IB_rect | IB_rectfloat);
101                                 }
102                                 IMB_float_from_rect(ibuf);
103                                 
104                                 IMB_rectcpy(env->cube[0], ibuf, 
105                                             0, 0, 0, 0, dx, dx);
106                                 IMB_rectcpy(env->cube[1], ibuf, 
107                                             0, 0, dx, 0, dx, dx);
108                                 IMB_rectcpy(env->cube[2], ibuf, 
109                                             0, 0, 2 * dx, 0, dx, dx);
110                                 IMB_rectcpy(env->cube[3], ibuf, 
111                                             0, 0, 0, dx, dx, dx);
112                                 IMB_rectcpy(env->cube[4], ibuf, 
113                                             0, 0, dx, dx, dx, dx);
114                                 IMB_rectcpy(env->cube[5], ibuf, 
115                                             0, 0, 2 * dx, dx, dx, dx);
116                                 
117                         }
118                         else { /* ENV_PLANE */
119                                 env->cube[1] = IMB_dupImBuf(ibuf);
120                                 IMB_float_from_rect(env->cube[1]);
121                         }
122                 }
123         }       
124         BLI_unlock_thread(LOCK_IMAGE);
125 }
126
127 /* ------------------------------------------------------------------------- */
128 /* ****************** RENDER ********************** */
129
130 /* copy current render */
131 static Render *envmap_render_copy(Render *re, EnvMap *env)
132 {
133         Render *envre;
134         float viewscale;
135         int cuberes;
136         
137         envre = RE_NewRender("Envmap");
138         
139         env->lastsize = re->r.size;
140         cuberes = (env->cuberes * re->r.size) / 100;
141         cuberes &= 0xFFFC;
142         
143         /* this flag has R_ZTRA in it for example */
144         envre->flag = re->flag;
145         
146         /* set up renderdata */
147         envre->r = re->r;
148         envre->r.mode &= ~(R_BORDER | R_PANORAMA | R_ORTHO | R_MBLUR);
149         envre->r.layers.first = envre->r.layers.last = NULL;
150         envre->r.filtertype = 0;
151         envre->r.xparts = envre->r.yparts = 2;
152         envre->r.size = 100;
153         envre->r.yasp = envre->r.xasp = 1;
154         
155         RE_InitState(envre, NULL, &envre->r, NULL, cuberes, cuberes, NULL);
156         envre->scene = re->scene;    /* unsure about this... */
157         envre->scene_color_manage = re->scene_color_manage;
158         envre->lay = re->lay;
159
160         /* view stuff in env render */
161         viewscale = (env->type == ENV_PLANE) ? env->viewscale : 1.0f;
162         RE_SetEnvmapCamera(envre, env->object, viewscale, env->clipsta, env->clipend);
163         
164         /* callbacks */
165         envre->display_draw = re->display_draw;
166         envre->ddh = re->ddh;
167         envre->test_break = re->test_break;
168         envre->tbh = re->tbh;
169         
170         /* and for the evil stuff; copy the database... */
171         envre->totvlak = re->totvlak;
172         envre->totvert = re->totvert;
173         envre->tothalo = re->tothalo;
174         envre->totstrand = re->totstrand;
175         envre->totlamp = re->totlamp;
176         envre->sortedhalos = re->sortedhalos;
177         envre->lights = re->lights;
178         envre->objecttable = re->objecttable;
179         envre->customdata_names = re->customdata_names;
180         envre->raytree = re->raytree;
181         envre->totinstance = re->totinstance;
182         envre->instancetable = re->instancetable;
183         envre->objectinstance = re->objectinstance;
184         envre->qmcsamplers = re->qmcsamplers;
185         
186         return envre;
187 }
188
189 static void envmap_free_render_copy(Render *envre)
190 {
191
192         envre->totvlak = 0;
193         envre->totvert = 0;
194         envre->tothalo = 0;
195         envre->totstrand = 0;
196         envre->totlamp = 0;
197         envre->totinstance = 0;
198         envre->sortedhalos = NULL;
199         envre->lights.first = envre->lights.last = NULL;
200         envre->objecttable.first = envre->objecttable.last = NULL;
201         envre->customdata_names.first = envre->customdata_names.last = NULL;
202         envre->raytree = NULL;
203         envre->instancetable.first = envre->instancetable.last = NULL;
204         envre->objectinstance = NULL;
205         envre->qmcsamplers = NULL;
206         
207         RE_FreeRender(envre);
208 }
209
210 /* ------------------------------------------------------------------------- */
211
212 static void envmap_transmatrix(float mat[][4], int part)
213 {
214         float tmat[4][4], eul[3], rotmat[4][4];
215         
216         eul[0] = eul[1] = eul[2] = 0.0;
217         
218         if (part == 0) {          /* neg z */
219                 ;
220         }
221         else if (part == 1) { /* pos z */
222                 eul[0] = M_PI;
223         }
224         else if (part == 2) { /* pos y */
225                 eul[0] = M_PI / 2.0;
226         }
227         else if (part == 3) { /* neg x */
228                 eul[0] = M_PI / 2.0;
229                 eul[2] = M_PI / 2.0;
230         }
231         else if (part == 4) { /* neg y */
232                 eul[0] = M_PI / 2.0;
233                 eul[2] = M_PI;
234         }
235         else {              /* pos x */
236                 eul[0] = M_PI / 2.0;
237                 eul[2] = -M_PI / 2.0;
238         }
239         
240         copy_m4_m4(tmat, mat);
241         eul_to_mat4(rotmat, eul);
242         mul_serie_m4(mat, tmat, rotmat,
243                      NULL, NULL, NULL,
244                      NULL, NULL, NULL);
245 }
246
247 /* ------------------------------------------------------------------------- */
248
249 static void env_rotate_scene(Render *re, float mat[][4], int mode)
250 {
251         GroupObject *go;
252         ObjectRen *obr;
253         ObjectInstanceRen *obi;
254         LampRen *lar = NULL;
255         HaloRen *har = NULL;
256         float imat[3][3], pmat[4][4], smat[4][4], tmat[4][4], cmat[3][3], tmpmat[4][4];
257         int a;
258         
259         if (mode == 0) {
260                 invert_m4_m4(tmat, mat);
261                 copy_m3_m4(imat, tmat);
262         }
263         else {
264                 copy_m4_m4(tmat, mat);
265                 copy_m3_m4(imat, mat);
266         }
267
268         for (obi = re->instancetable.first; obi; obi = obi->next) {
269                 /* append or set matrix depending on dupli */
270                 if (obi->flag & R_DUPLI_TRANSFORMED) {
271                         copy_m4_m4(tmpmat, obi->mat);
272                         mult_m4_m4m4(obi->mat, tmat, tmpmat);
273                 }
274                 else if (mode == 1)
275                         copy_m4_m4(obi->mat, tmat);
276                 else
277                         unit_m4(obi->mat);
278
279                 copy_m3_m4(cmat, obi->mat);
280                 invert_m3_m3(obi->nmat, cmat);
281                 transpose_m3(obi->nmat);
282
283                 /* indicate the renderer has to use transform matrices */
284                 if (mode == 0)
285                         obi->flag &= ~R_ENV_TRANSFORMED;
286                 else
287                         obi->flag |= R_ENV_TRANSFORMED;
288         }
289         
290
291         for (obr = re->objecttable.first; obr; obr = obr->next) {
292                 for (a = 0; a < obr->tothalo; a++) {
293                         if ((a & 255) == 0) har = obr->bloha[a >> 8];
294                         else har++;
295                 
296                         mul_m4_v3(tmat, har->co);
297                 }
298         }
299         
300         for (go = re->lights.first; go; go = go->next) {
301                 lar = go->lampren;
302                 
303                 /* removed here some horrible code of someone in NaN who tried to fix
304                  * prototypes... just solved by introducing a correct cmat[3][3] instead
305                  * of using smat. this works, check square spots in reflections  (ton) */
306                 copy_m3_m3(cmat, lar->imat); 
307                 mul_m3_m3m3(lar->imat, cmat, imat); 
308
309                 mul_m3_v3(imat, lar->vec);
310                 mul_m4_v3(tmat, lar->co);
311
312                 lar->sh_invcampos[0] = -lar->co[0];
313                 lar->sh_invcampos[1] = -lar->co[1];
314                 lar->sh_invcampos[2] = -lar->co[2];
315                 mul_m3_v3(lar->imat, lar->sh_invcampos);
316                 lar->sh_invcampos[2] *= lar->sh_zfac;
317                 
318                 if (lar->shb) {
319                         if (mode == 1) {
320                                 invert_m4_m4(pmat, mat);
321                                 mult_m4_m4m4(smat, lar->shb->viewmat, pmat);
322                                 mult_m4_m4m4(lar->shb->persmat, lar->shb->winmat, smat);
323                         }
324                         else mult_m4_m4m4(lar->shb->persmat, lar->shb->winmat, lar->shb->viewmat);
325                 }
326         }
327         
328 }
329
330 /* ------------------------------------------------------------------------- */
331
332 static void env_layerflags(Render *re, unsigned int notlay)
333 {
334         ObjectRen *obr;
335         VlakRen *vlr = NULL;
336         int a;
337         
338         /* invert notlay, so if face is in multiple layers it will still be visible,
339          * unless all 'notlay' bits match the face bits.
340          * face: 0110
341          * not:  0100
342          * ~not: 1011
343          * now (face & ~not) is true
344          */
345         
346         notlay = ~notlay;
347         
348         for (obr = re->objecttable.first; obr; obr = obr->next) {
349                 if ((obr->lay & notlay) == 0) {
350                         for (a = 0; a < obr->totvlak; a++) {
351                                 if ((a & 255) == 0) vlr = obr->vlaknodes[a >> 8].vlak;
352                                 else vlr++;
353
354                                 vlr->flag |= R_HIDDEN;
355                         }
356                 }
357         }
358 }
359
360 static void env_hideobject(Render *re, Object *ob)
361 {
362         ObjectRen *obr;
363         VlakRen *vlr = NULL;
364         int a;
365         
366         for (obr = re->objecttable.first; obr; obr = obr->next) {
367                 for (a = 0; a < obr->totvlak; a++) {
368                         if ((a & 255) == 0) vlr = obr->vlaknodes[a >> 8].vlak;
369                         else vlr++;
370
371                         if (obr->ob == ob)
372                                 vlr->flag |= R_HIDDEN;
373                 }
374         }
375 }
376
377 static void env_showobjects(Render *re)
378 {
379         ObjectRen *obr;
380         VlakRen *vlr = NULL;
381         int a;
382         
383         for (obr = re->objecttable.first; obr; obr = obr->next) {
384                 for (a = 0; a < obr->totvlak; a++) {
385                         if ((a & 255) == 0) vlr = obr->vlaknodes[a >> 8].vlak;
386                         else vlr++;
387
388                         vlr->flag &= ~R_HIDDEN;
389                 }
390         }
391 }
392
393 /* ------------------------------------------------------------------------- */
394
395 static void env_set_imats(Render *re)
396 {
397         Base *base;
398         float mat[4][4];
399         
400         base = re->scene->base.first;
401         while (base) {
402                 mult_m4_m4m4(mat, re->viewmat, base->object->obmat);
403                 invert_m4_m4(base->object->imat, mat);
404                 
405                 base = base->next;
406         }
407
408 }       
409
410 /* ------------------------------------------------------------------------- */
411
412 static void render_envmap(Render *re, EnvMap *env)
413 {
414         /* only the cubemap and planar map is implemented */
415         Render *envre;
416         ImBuf *ibuf;
417         float orthmat[4][4];
418         float oldviewinv[4][4], mat[4][4], tmat[4][4];
419         short part;
420         
421         /* need a recalc: ortho-render has no correct viewinv */
422         invert_m4_m4(oldviewinv, re->viewmat);
423
424         envre = envmap_render_copy(re, env);
425         
426         /* precalc orthmat for object */
427         copy_m4_m4(orthmat, env->object->obmat);
428         normalize_m4(orthmat);
429         
430         /* need imat later for texture imat */
431         mult_m4_m4m4(mat, re->viewmat, orthmat);
432         invert_m4_m4(tmat, mat);
433         copy_m3_m4(env->obimat, tmat);
434
435         for (part = 0; part < 6; part++) {
436                 if (env->type == ENV_PLANE && part != 1)
437                         continue;
438                 
439                 re->display_clear(re->dch, envre->result);
440                 
441                 copy_m4_m4(tmat, orthmat);
442                 envmap_transmatrix(tmat, part);
443                 invert_m4_m4(mat, tmat);
444                 /* mat now is the camera 'viewmat' */
445
446                 copy_m4_m4(envre->viewmat, mat);
447                 copy_m4_m4(envre->viewinv, tmat);
448                 
449                 /* we have to correct for the already rotated vertexcoords */
450                 mult_m4_m4m4(tmat, envre->viewmat, oldviewinv);
451                 invert_m4_m4(env->imat, tmat);
452                 
453                 env_rotate_scene(envre, tmat, 1);
454                 init_render_world(envre);
455                 project_renderdata(envre, projectverto, 0, 0, 1);
456                 env_layerflags(envre, env->notlay);
457                 env_hideobject(envre, env->object);
458                 env_set_imats(envre);
459                                 
460                 if (re->test_break(re->tbh) == 0) {
461                         RE_TileProcessor(envre);
462                 }
463                 
464                 /* rotate back */
465                 env_showobjects(envre);
466                 env_rotate_scene(envre, tmat, 0);
467
468                 if (re->test_break(re->tbh) == 0) {
469                         RenderLayer *rl = envre->result->layers.first;
470                         int y;
471                         float *alpha;
472                         
473                         ibuf = IMB_allocImBuf(envre->rectx, envre->recty, 24, IB_rect | IB_rectfloat);
474                         memcpy(ibuf->rect_float, rl->rectf, ibuf->channels * ibuf->x * ibuf->y * sizeof(float));
475                         
476                         /* envmap renders without alpha */
477                         alpha = ibuf->rect_float + 3;
478                         for (y = ibuf->x * ibuf->y - 1; y >= 0; y--, alpha += 4)
479                                 *alpha = 1.0;
480                         
481                         env->cube[part] = ibuf;
482                 }
483                 
484                 if (re->test_break(re->tbh)) break;
485
486         }
487         
488         if (re->test_break(re->tbh)) BKE_free_envmapdata(env);
489         else {
490                 if (envre->r.mode & R_OSA) env->ok = ENV_OSA;
491                 else env->ok = ENV_NORMAL;
492                 env->lastframe = re->scene->r.cfra;
493         }
494         
495         /* restore */
496         envmap_free_render_copy(envre);
497         env_set_imats(re);
498
499 }
500
501 /* ------------------------------------------------------------------------- */
502
503 void make_envmaps(Render *re)
504 {
505         Tex *tex;
506         int do_init = FALSE, depth = 0, trace;
507         
508         if (!(re->r.mode & R_ENVMAP)) return;
509         
510         /* we don't raytrace, disabling the flag will cause ray_transp render solid */
511         trace = (re->r.mode & R_RAYTRACE);
512         re->r.mode &= ~R_RAYTRACE;
513
514         re->i.infostr = "Creating Environment maps";
515         re->stats_draw(re->sdh, &re->i);
516         
517         /* 5 = hardcoded max recursion level */
518         while (depth < 5) {
519                 tex = re->main->tex.first;
520                 while (tex) {
521                         if (tex->id.us && tex->type == TEX_ENVMAP) {
522                                 if (tex->env && tex->env->object) {
523                                         EnvMap *env = tex->env;
524                                         
525                                         if (env->object->lay & re->lay) {
526                                                 if (env->stype == ENV_LOAD) {
527                                                         float orthmat[4][4], mat[4][4], tmat[4][4];
528                                                         
529                                                         /* precalc orthmat for object */
530                                                         copy_m4_m4(orthmat, env->object->obmat);
531                                                         normalize_m4(orthmat);
532                                                         
533                                                         /* need imat later for texture imat */
534                                                         mult_m4_m4m4(mat, re->viewmat, orthmat);
535                                                         invert_m4_m4(tmat, mat);
536                                                         copy_m3_m4(env->obimat, tmat);
537                                                 }
538                                                 else {
539                                                         
540                                                         /* decide if to render an envmap (again) */
541                                                         if (env->depth >= depth) {
542                                                                 
543                                                                 /* set 'recalc' to make sure it does an entire loop of recalcs */
544                                                                 
545                                                                 if (env->ok) {
546                                                                         /* free when OSA, and old one isn't OSA */
547                                                                         if ((re->r.mode & R_OSA) && env->ok == ENV_NORMAL)
548                                                                                 BKE_free_envmapdata(env);
549                                                                         /* free when size larger */
550                                                                         else if (env->lastsize < re->r.size)
551                                                                                 BKE_free_envmapdata(env);
552                                                                         /* free when env is in recalcmode */
553                                                                         else if (env->recalc)
554                                                                                 BKE_free_envmapdata(env);
555                                                                 }
556                                                                 
557                                                                 if (env->ok == 0 && depth == 0) env->recalc = 1;
558                                                                 
559                                                                 if (env->ok == 0) {
560                                                                         do_init = TRUE;
561                                                                         render_envmap(re, env);
562                                                                         
563                                                                         if (depth == env->depth) env->recalc = 0;
564                                                                 }
565                                                         }
566                                                 }
567                                         }
568                                 }
569                         }
570                         tex = tex->id.next;
571                 }
572                 depth++;
573         }
574
575         if (do_init) {
576                 re->display_init(re->dih, re->result);
577                 re->display_clear(re->dch, re->result);
578                 // re->flag |= R_REDRAW_PRV;
579         }       
580         /* restore */
581         re->r.mode |= trace;
582
583 }
584
585 /* ------------------------------------------------------------------------- */
586
587 static int envcube_isect(EnvMap *env, const float vec[3], float answ[2])
588 {
589         float labda;
590         int face;
591         
592         if (env->type == ENV_PLANE) {
593                 face = 1;
594                 
595                 labda = 1.0f / vec[2];
596                 answ[0] = env->viewscale * labda * vec[0];
597                 answ[1] = -env->viewscale * labda * vec[1];
598         }
599         else {
600                 /* which face */
601                 if (vec[2] <= -fabsf(vec[0]) && vec[2] <= -fabsf(vec[1]) ) {
602                         face = 0;
603                         labda = -1.0f / vec[2];
604                         answ[0] = labda * vec[0];
605                         answ[1] = labda * vec[1];
606                 }
607                 else if (vec[2] >= fabsf(vec[0]) && vec[2] >= fabsf(vec[1])) {
608                         face = 1;
609                         labda = 1.0f / vec[2];
610                         answ[0] = labda * vec[0];
611                         answ[1] = -labda * vec[1];
612                 }
613                 else if (vec[1] >= fabsf(vec[0])) {
614                         face = 2;
615                         labda = 1.0f / vec[1];
616                         answ[0] = labda * vec[0];
617                         answ[1] = labda * vec[2];
618                 }
619                 else if (vec[0] <= -fabsf(vec[1])) {
620                         face = 3;
621                         labda = -1.0f / vec[0];
622                         answ[0] = labda * vec[1];
623                         answ[1] = labda * vec[2];
624                 }
625                 else if (vec[1] <= -fabsf(vec[0])) {
626                         face = 4;
627                         labda = -1.0f / vec[1];
628                         answ[0] = -labda * vec[0];
629                         answ[1] = labda * vec[2];
630                 }
631                 else {
632                         face = 5;
633                         labda = 1.0f / vec[0];
634                         answ[0] = -labda * vec[1];
635                         answ[1] = labda * vec[2];
636                 }
637         }
638         
639         answ[0] = 0.5f + 0.5f * answ[0];
640         answ[1] = 0.5f + 0.5f * answ[1];
641         return face;
642 }
643
644 /* ------------------------------------------------------------------------- */
645
646 static void set_dxtdyt(float *dxts, float *dyts, float *dxt, float *dyt, int face)
647 {
648         if (face == 2 || face == 4) {
649                 dxts[0] = dxt[0];
650                 dyts[0] = dyt[0];
651                 dxts[1] = dxt[2];
652                 dyts[1] = dyt[2];
653         }
654         else if (face == 3 || face == 5) {
655                 dxts[0] = dxt[1];
656                 dxts[1] = dxt[2];
657                 dyts[0] = dyt[1];
658                 dyts[1] = dyt[2];
659         }
660         else {
661                 dxts[0] = dxt[0];
662                 dyts[0] = dyt[0];
663                 dxts[1] = dxt[1];
664                 dyts[1] = dyt[1];
665         }
666 }
667
668 /* ------------------------------------------------------------------------- */
669
670 int envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres)
671 {
672         extern Render R;                /* only in this call */
673         /* texvec should be the already reflected normal */
674         EnvMap *env;
675         ImBuf *ibuf;
676         float fac, vec[3], sco[3], dxts[3], dyts[3];
677         int face, face1;
678         
679         env = tex->env;
680         if (env == NULL || (env->stype != ENV_LOAD && env->object == NULL)) {
681                 texres->tin = 0.0;
682                 return 0;
683         }
684         
685         if (env->stype == ENV_LOAD) {
686                 env->ima = tex->ima;
687                 if (env->ima && env->ima->ok) {
688                         if (env->cube[1] == NULL) {
689                                 ImBuf *ibuf_ima = BKE_image_get_ibuf(env->ima, NULL);
690                                 if (ibuf_ima)
691                                         envmap_split_ima(env, ibuf_ima);
692                                 else
693                                         env->ok = 0;
694                         }
695                 }
696         }
697
698         if (env->ok == 0) {
699                 texres->tin = 0.0;
700                 return 0;
701         }
702         
703         /* rotate to envmap space, if object is set */
704         copy_v3_v3(vec, texvec);
705         if (env->object) mul_m3_v3(env->obimat, vec);
706         else mul_mat3_m4_v3(R.viewinv, vec);
707         
708         face = envcube_isect(env, vec, sco);
709         ibuf = env->cube[face];
710         
711         if (osatex) {
712                 if (env->object) {
713                         mul_m3_v3(env->obimat, dxt);
714                         mul_m3_v3(env->obimat, dyt);
715                 }
716                 else {
717                         mul_mat3_m4_v3(R.viewinv, dxt);
718                         mul_mat3_m4_v3(R.viewinv, dyt);
719                 }
720                 set_dxtdyt(dxts, dyts, dxt, dyt, face);
721                 imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, texres);
722                 
723                 /* edges? */
724                 
725                 if (texres->ta < 1.0f) {
726                         TexResult texr1, texr2;
727         
728                         texr1.nor = texr2.nor = NULL;
729                         texr1.talpha = texr2.talpha = texres->talpha; /* boxclip expects this initialized */
730
731                         add_v3_v3(vec, dxt);
732                         face1 = envcube_isect(env, vec, sco);
733                         sub_v3_v3(vec, dxt);
734                         
735                         if (face != face1) {
736                                 ibuf = env->cube[face1];
737                                 set_dxtdyt(dxts, dyts, dxt, dyt, face1);
738                                 imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr1);
739                         }
740                         else texr1.tr = texr1.tg = texr1.tb = texr1.ta = 0.0;
741                         
742                         /* here was the nasty bug! results were not zero-ed. FPE! */
743                         
744                         add_v3_v3(vec, dyt);
745                         face1 = envcube_isect(env, vec, sco);
746                         sub_v3_v3(vec, dyt);
747                         
748                         if (face != face1) {
749                                 ibuf = env->cube[face1];
750                                 set_dxtdyt(dxts, dyts, dxt, dyt, face1);
751                                 imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr2);
752                         }
753                         else texr2.tr = texr2.tg = texr2.tb = texr2.ta = 0.0;
754                         
755                         fac = (texres->ta + texr1.ta + texr2.ta);
756                         if (fac != 0.0f) {
757                                 fac = 1.0f / fac;
758
759                                 texres->tr = fac * (texres->ta * texres->tr + texr1.ta * texr1.tr + texr2.ta * texr2.tr);
760                                 texres->tg = fac * (texres->ta * texres->tg + texr1.ta * texr1.tg + texr2.ta * texr2.tg);
761                                 texres->tb = fac * (texres->ta * texres->tb + texr1.ta * texr1.tb + texr2.ta * texr2.tb);
762                         }
763                         texres->ta = 1.0;
764                 }
765         }
766         else {
767                 imagewrap(tex, NULL, ibuf, sco, texres);
768         }
769         
770         return 1;
771 }