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