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