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