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