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