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