Merging r46111 through r46136 from trunk into soc-2011-tomato
[blender-staging.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 #include "MEM_guardedalloc.h"
35
36 #include "BLI_math.h"
37 #include "BLI_blenlib.h"
38 #include "BLI_threads.h"
39 #include "BLI_utildefines.h"
40
41 #include "IMB_imbuf_types.h"
42 #include "IMB_imbuf.h"        /* for rectcpy */
43
44 #include "DNA_group_types.h"
45 #include "DNA_image_types.h"
46 #include "DNA_object_types.h"
47 #include "DNA_scene_types.h"
48 #include "DNA_texture_types.h"
49
50 #include "BKE_library.h"
51 #include "BKE_main.h"
52 #include "BKE_image.h"   // BKE_write_ibuf 
53 #include "BKE_texture.h"
54
55
56
57
58 /* this module */
59 #include "render_types.h"
60 #include "renderpipeline.h"
61 #include "envmap.h"
62 #include "rendercore.h" 
63 #include "renderdatabase.h" 
64 #include "texture.h"
65 #include "zbuf.h"
66 #include "initrender.h"
67
68
69 /* ------------------------------------------------------------------------- */
70
71 static void envmap_split_ima(EnvMap *env, ImBuf *ibuf)
72 {
73         int dx, part;
74         
75         /* after lock we test cube[1], if set the other thread has done it fine */
76         BLI_lock_thread(LOCK_IMAGE);
77         if (env->cube[1]==NULL) {
78
79                 BKE_free_envmapdata(env);       
80         
81                 dx= ibuf->y;
82                 dx/= 2;
83                 if (3*dx == ibuf->x) {
84                         env->type = ENV_CUBE;
85                         env->ok= ENV_OSA;
86                 }
87                 else if (ibuf->x == ibuf->y) {
88                         env->type = ENV_PLANE;
89                         env->ok= ENV_OSA;
90                 }
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         float viewscale;
135         int cuberes;
136         
137         envre= RE_NewRender("Envmap");
138         
139         env->lastsize= re->r.size;
140         cuberes = (env->cuberes * re->r.size) / 100;
141         cuberes &= 0xFFFC;
142         
143         /* this flag has R_ZTRA in it for example */
144         envre->flag= re->flag;
145         
146         /* set up renderdata */
147         envre->r= re->r;
148         envre->r.mode &= ~(R_BORDER | R_PANORAMA | R_ORTHO | R_MBLUR);
149         envre->r.layers.first= envre->r.layers.last= NULL;
150         envre->r.filtertype= 0;
151         envre->r.xparts= envre->r.yparts= 2;
152         envre->r.size= 100;
153         envre->r.yasp= envre->r.xasp= 1;
154         
155         RE_InitState(envre, NULL, &envre->r, NULL, cuberes, cuberes, NULL);
156         envre->scene= re->scene;        /* unsure about this... */
157         envre->lay= re->lay;
158
159         /* view stuff in env render */
160         viewscale= (env->type == ENV_PLANE)? env->viewscale: 1.0f;
161         RE_SetEnvmapCamera(envre, env->object, viewscale, env->clipsta, env->clipend);
162         
163         /* callbacks */
164         envre->display_draw= re->display_draw;
165         envre->ddh= re->ddh;
166         envre->test_break= re->test_break;
167         envre->tbh= re->tbh;
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         envre->lights.first= envre->lights.last= NULL;
199         envre->objecttable.first= envre->objecttable.last= NULL;
200         envre->customdata_names.first= envre->customdata_names.last= NULL;
201         envre->raytree= NULL;
202         envre->instancetable.first= envre->instancetable.last= NULL;
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], 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                 ;
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_serie_m4(mat, tmat, rotmat,
242                      NULL, NULL, NULL,
243                      NULL, NULL, NULL);
244 }
245
246 /* ------------------------------------------------------------------------- */
247
248 static void env_rotate_scene(Render *re, float mat[][4], int mode)
249 {
250         GroupObject *go;
251         ObjectRen *obr;
252         ObjectInstanceRen *obi;
253         LampRen *lar = NULL;
254         HaloRen *har = NULL;
255         float imat[3][3], pmat[4][4], smat[4][4], tmat[4][4], cmat[3][3], tmpmat[4][4];
256         int a;
257         
258         if (mode==0) {
259                 invert_m4_m4(tmat, mat);
260                 copy_m3_m4(imat, tmat);
261         }
262         else {
263                 copy_m4_m4(tmat, mat);
264                 copy_m3_m4(imat, mat);
265         }
266
267         for (obi=re->instancetable.first; obi; obi=obi->next) {
268                 /* append or set matrix depending on dupli */
269                 if (obi->flag & R_DUPLI_TRANSFORMED) {
270                         copy_m4_m4(tmpmat, obi->mat);
271                         mult_m4_m4m4(obi->mat, tmat, tmpmat);
272                 }
273                 else if (mode==1)
274                         copy_m4_m4(obi->mat, tmat);
275                 else
276                         unit_m4(obi->mat);
277
278                 copy_m3_m4(cmat, obi->mat);
279                 invert_m3_m3(obi->nmat, cmat);
280                 transpose_m3(obi->nmat);
281
282                 /* indicate the renderer has to use transform matrices */
283                 if (mode==0)
284                         obi->flag &= ~R_ENV_TRANSFORMED;
285                 else
286                         obi->flag |= R_ENV_TRANSFORMED;
287         }
288         
289
290         for (obr=re->objecttable.first; obr; obr=obr->next) {
291                 for (a=0; a<obr->tothalo; a++) {
292                         if ((a & 255)==0) har= obr->bloha[a>>8];
293                         else har++;
294                 
295                         mul_m4_v3(tmat, har->co);
296                 }
297         }
298         
299         for (go=re->lights.first; go; go= go->next) {
300                 lar= go->lampren;
301                 
302                 /* removed here some horrible code of someone in NaN who tried to fix
303                  * prototypes... just solved by introducing a correct cmat[3][3] instead
304                  * of using smat. this works, check square spots in reflections  (ton) */
305                 copy_m3_m3(cmat, lar->imat); 
306                 mul_m3_m3m3(lar->imat, cmat, imat); 
307
308                 mul_m3_v3(imat, lar->vec);
309                 mul_m4_v3(tmat, lar->co);
310
311                 lar->sh_invcampos[0]= -lar->co[0];
312                 lar->sh_invcampos[1]= -lar->co[1];
313                 lar->sh_invcampos[2]= -lar->co[2];
314                 mul_m3_v3(lar->imat, lar->sh_invcampos);
315                 lar->sh_invcampos[2]*= lar->sh_zfac;
316                 
317                 if (lar->shb) {
318                         if (mode==1) {
319                                 invert_m4_m4(pmat, mat);
320                                 mult_m4_m4m4(smat, lar->shb->viewmat, pmat);
321                                 mult_m4_m4m4(lar->shb->persmat, lar->shb->winmat, smat);
322                         }
323                         else mult_m4_m4m4(lar->shb->persmat, lar->shb->winmat, lar->shb->viewmat);
324                 }
325         }
326         
327 }
328
329 /* ------------------------------------------------------------------------- */
330
331 static void env_layerflags(Render *re, unsigned int notlay)
332 {
333         ObjectRen *obr;
334         VlakRen *vlr = NULL;
335         int a;
336         
337         /* invert notlay, so if face is in multiple layers it will still be visible,
338          * unless all 'notlay' bits match the face bits.
339          * face: 0110
340          * not:  0100
341          * ~not: 1011
342          * now (face & ~not) is true
343          */
344         
345         notlay= ~notlay;
346         
347         for (obr=re->objecttable.first; obr; obr=obr->next) {
348                 if ((obr->lay & notlay)==0) {
349                         for (a=0; a<obr->totvlak; a++) {
350                                 if ((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
351                                 else vlr++;
352
353                                 vlr->flag |= R_HIDDEN;
354                         }
355                 }
356         }
357 }
358
359 static void env_hideobject(Render *re, Object *ob)
360 {
361         ObjectRen *obr;
362         VlakRen *vlr = NULL;
363         int a;
364         
365         for (obr=re->objecttable.first; obr; obr=obr->next) {
366                 for (a=0; a<obr->totvlak; a++) {
367                         if ((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
368                         else vlr++;
369
370                         if (obr->ob == ob)
371                                 vlr->flag |= R_HIDDEN;
372                 }
373         }
374 }
375
376 static void env_showobjects(Render *re)
377 {
378         ObjectRen *obr;
379         VlakRen *vlr = NULL;
380         int a;
381         
382         for (obr=re->objecttable.first; obr; obr=obr->next) {
383                 for (a=0; a<obr->totvlak; a++) {
384                         if ((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
385                         else vlr++;
386
387                         vlr->flag &= ~R_HIDDEN;
388                 }
389         }
390 }
391
392 /* ------------------------------------------------------------------------- */
393
394 static void env_set_imats(Render *re)
395 {
396         Base *base;
397         float mat[4][4];
398         
399         base= re->scene->base.first;
400         while (base) {
401                 mult_m4_m4m4(mat, re->viewmat, base->object->obmat);
402                 invert_m4_m4(base->object->imat, mat);
403                 
404                 base= base->next;
405         }
406
407 }       
408
409 /* ------------------------------------------------------------------------- */
410
411 static void render_envmap(Render *re, EnvMap *env)
412 {
413         /* only the cubemap and planar map is implemented */
414         Render *envre;
415         ImBuf *ibuf;
416         float orthmat[4][4];
417         float oldviewinv[4][4], mat[4][4], tmat[4][4];
418         short part;
419         
420         /* need a recalc: ortho-render has no correct viewinv */
421         invert_m4_m4(oldviewinv, re->viewmat);
422
423         envre= envmap_render_copy(re, env);
424         
425         /* precalc orthmat for object */
426         copy_m4_m4(orthmat, env->object->obmat);
427         normalize_m4(orthmat);
428         
429         /* need imat later for texture imat */
430         mult_m4_m4m4(mat, re->viewmat, orthmat);
431         invert_m4_m4(tmat, mat);
432         copy_m3_m4(env->obimat, tmat);
433
434         for (part=0; part<6; part++) {
435                 if (env->type==ENV_PLANE && part!=1)
436                         continue;
437                 
438                 re->display_clear(re->dch, envre->result);
439                 
440                 copy_m4_m4(tmat, orthmat);
441                 envmap_transmatrix(tmat, part);
442                 invert_m4_m4(mat, tmat);
443                 /* mat now is the camera 'viewmat' */
444
445                 copy_m4_m4(envre->viewmat, mat);
446                 copy_m4_m4(envre->viewinv, tmat);
447                 
448                 /* we have to correct for the already rotated vertexcoords */
449                 mult_m4_m4m4(tmat, envre->viewmat, oldviewinv);
450                 invert_m4_m4(env->imat, tmat);
451                 
452                 env_rotate_scene(envre, tmat, 1);
453                 init_render_world(envre);
454                 project_renderdata(envre, projectverto, 0, 0, 1);
455                 env_layerflags(envre, env->notlay);
456                 env_hideobject(envre, env->object);
457                 env_set_imats(envre);
458                                 
459                 if (re->test_break(re->tbh)==0) {
460                         RE_TileProcessor(envre);
461                 }
462                 
463                 /* rotate back */
464                 env_showobjects(envre);
465                 env_rotate_scene(envre, tmat, 0);
466
467                 if (re->test_break(re->tbh)==0) {
468                         RenderLayer *rl= envre->result->layers.first;
469                         int y;
470                         float *alpha;
471                         
472                         ibuf= IMB_allocImBuf(envre->rectx, envre->recty, 24, IB_rect|IB_rectfloat);
473                         memcpy(ibuf->rect_float, rl->rectf, ibuf->channels * ibuf->x * ibuf->y * sizeof(float));
474                         
475                         if (re->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)
476                                 ibuf->profile = IB_PROFILE_LINEAR_RGB;
477                         
478                         /* envmap renders without alpha */
479                         alpha= ((float *)ibuf->rect_float)+3;
480                         for (y= ibuf->x*ibuf->y - 1; y>=0; y--, alpha+=4)
481                                 *alpha= 1.0;
482                         
483                         env->cube[part]= ibuf;
484                 }
485                 
486                 if (re->test_break(re->tbh)) break;
487
488         }
489         
490         if (re->test_break(re->tbh)) BKE_free_envmapdata(env);
491         else {
492                 if (envre->r.mode & R_OSA) env->ok= ENV_OSA;
493                 else env->ok= ENV_NORMAL;
494                 env->lastframe= re->scene->r.cfra;
495         }
496         
497         /* restore */
498         envmap_free_render_copy(envre);
499         env_set_imats(re);
500
501 }
502
503 /* ------------------------------------------------------------------------- */
504
505 void make_envmaps(Render *re)
506 {
507         Tex *tex;
508         int do_init= 0, depth= 0, trace;
509         
510         if (!(re->r.mode & R_ENVMAP)) return;
511         
512         /* we don't raytrace, disabling the flag will cause ray_transp render solid */
513         trace= (re->r.mode & R_RAYTRACE);
514         re->r.mode &= ~R_RAYTRACE;
515
516         re->i.infostr= "Creating Environment maps";
517         re->stats_draw(re->sdh, &re->i);
518         
519         /* 5 = hardcoded max recursion level */
520         while (depth<5) {
521                 tex= re->main->tex.first;
522                 while (tex) {
523                         if (tex->id.us && tex->type==TEX_ENVMAP) {
524                                 if (tex->env && tex->env->object) {
525                                         EnvMap *env= tex->env;
526                                         
527                                         if (env->object->lay & re->lay) {
528                                                 if (env->stype==ENV_LOAD) {
529                                                         float orthmat[4][4], mat[4][4], tmat[4][4];
530                                                         
531                                                         /* precalc orthmat for object */
532                                                         copy_m4_m4(orthmat, env->object->obmat);
533                                                         normalize_m4(orthmat);
534                                                         
535                                                         /* need imat later for texture imat */
536                                                         mult_m4_m4m4(mat, re->viewmat, orthmat);
537                                                         invert_m4_m4(tmat, mat);
538                                                         copy_m3_m4(env->obimat, tmat);
539                                                 }
540                                                 else {
541                                                         
542                                                         /* decide if to render an envmap (again) */
543                                                         if (env->depth >= depth) {
544                                                                 
545                                                                 /* set 'recalc' to make sure it does an entire loop of recalcs */
546                                                                 
547                                                                 if (env->ok) {
548                                                                                 /* free when OSA, and old one isn't OSA */
549                                                                         if ((re->r.mode & R_OSA) && env->ok==ENV_NORMAL)
550                                                                                 BKE_free_envmapdata(env);
551                                                                                 /* free when size larger */
552                                                                         else if (env->lastsize < re->r.size)
553                                                                                 BKE_free_envmapdata(env);
554                                                                                 /* free when env is in recalcmode */
555                                                                         else if (env->recalc)
556                                                                                 BKE_free_envmapdata(env);
557                                                                 }
558                                                                 
559                                                                 if (env->ok==0 && depth==0) env->recalc= 1;
560                                                                 
561                                                                 if (env->ok==0) {
562                                                                         do_init= 1;
563                                                                         render_envmap(re, env);
564                                                                         
565                                                                         if (depth==env->depth) env->recalc= 0;
566                                                                 }
567                                                         }
568                                                 }
569                                         }
570                                 }
571                         }
572                         tex= tex->id.next;
573                 }
574                 depth++;
575         }
576
577         if (do_init) {
578                 re->display_init(re->dih, re->result);
579                 re->display_clear(re->dch, re->result);
580                 // re->flag |= R_REDRAW_PRV;
581         }       
582         // restore
583         re->r.mode |= trace;
584
585 }
586
587 /* ------------------------------------------------------------------------- */
588
589 static int envcube_isect(EnvMap *env, float *vec, float *answ)
590 {
591         float labda;
592         int face;
593         
594         if (env->type==ENV_PLANE) {
595                 face= 1;
596                 
597                 labda= 1.0f/vec[2];
598                 answ[0]= env->viewscale*labda*vec[0];
599                 answ[1]= -env->viewscale*labda*vec[1];
600         }
601         else {
602                 /* which face */
603                 if ( vec[2] <= -fabsf(vec[0]) && vec[2] <= -fabsf(vec[1]) ) {
604                         face= 0;
605                         labda= -1.0f/vec[2];
606                         answ[0]= labda*vec[0];
607                         answ[1]= labda*vec[1];
608                 }
609                 else if (vec[2] >= fabsf(vec[0]) && vec[2] >= fabsf(vec[1])) {
610                         face= 1;
611                         labda= 1.0f/vec[2];
612                         answ[0]= labda*vec[0];
613                         answ[1]= -labda*vec[1];
614                 }
615                 else if (vec[1] >= fabsf(vec[0])) {
616                         face= 2;
617                         labda= 1.0f/vec[1];
618                         answ[0]= labda*vec[0];
619                         answ[1]= labda*vec[2];
620                 }
621                 else if (vec[0] <= -fabsf(vec[1])) {
622                         face= 3;
623                         labda= -1.0f/vec[0];
624                         answ[0]= labda*vec[1];
625                         answ[1]= labda*vec[2];
626                 }
627                 else if (vec[1] <= -fabsf(vec[0])) {
628                         face= 4;
629                         labda= -1.0f/vec[1];
630                         answ[0]= -labda*vec[0];
631                         answ[1]= labda*vec[2];
632                 }
633                 else {
634                         face= 5;
635                         labda= 1.0f/vec[0];
636                         answ[0]= -labda*vec[1];
637                         answ[1]= labda*vec[2];
638                 }
639         }
640         
641         answ[0]= 0.5f+0.5f*answ[0];
642         answ[1]= 0.5f+0.5f*answ[1];
643         return face;
644 }
645
646 /* ------------------------------------------------------------------------- */
647
648 static void set_dxtdyt(float *dxts, float *dyts, float *dxt, float *dyt, int face)
649 {
650         if (face==2 || face==4) {
651                 dxts[0]= dxt[0];
652                 dyts[0]= dyt[0];
653                 dxts[1]= dxt[2];
654                 dyts[1]= dyt[2];
655         }
656         else if (face==3 || face==5) {
657                 dxts[0]= dxt[1];
658                 dxts[1]= dxt[2];
659                 dyts[0]= dyt[1];
660                 dyts[1]= dyt[2];
661         }
662         else {
663                 dxts[0]= dxt[0];
664                 dyts[0]= dyt[0];
665                 dxts[1]= dxt[1];
666                 dyts[1]= dyt[1];
667         }
668 }
669
670 /* ------------------------------------------------------------------------- */
671
672 int envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres)
673 {
674         extern Render R;                                /* only in this call */
675         /* texvec should be the already reflected normal */
676         EnvMap *env;
677         ImBuf *ibuf;
678         float fac, vec[3], sco[3], dxts[3], dyts[3];
679         int face, face1;
680         
681         env= tex->env;
682         if (env==NULL || (env->stype!=ENV_LOAD && env->object==NULL)) {
683                 texres->tin= 0.0;
684                 return 0;
685         }
686         
687         if (env->stype==ENV_LOAD) {
688                 env->ima= tex->ima;
689                 if (env->ima && env->ima->ok) {
690                         if (env->cube[1]==NULL) {
691                                 ImBuf *ibuf_ima= BKE_image_get_ibuf(env->ima, NULL);
692                                 if (ibuf_ima)
693                                         envmap_split_ima(env, ibuf_ima);
694                                 else
695                                         env->ok= 0;
696                         }
697                 }
698         }
699
700         if (env->ok==0) {
701                 texres->tin= 0.0;
702                 return 0;
703         }
704         
705         /* rotate to envmap space, if object is set */
706         copy_v3_v3(vec, texvec);
707         if (env->object) mul_m3_v3(env->obimat, vec);
708         else mul_mat3_m4_v3(R.viewinv, vec);
709         
710         face= envcube_isect(env, vec, sco);
711         ibuf= env->cube[face];
712         
713         if (osatex) {
714                 if (env->object) {
715                         mul_m3_v3(env->obimat, dxt);
716                         mul_m3_v3(env->obimat, dyt);
717                 }
718                 else {
719                         mul_mat3_m4_v3(R.viewinv, dxt);
720                         mul_mat3_m4_v3(R.viewinv, dyt);
721                 }
722                 set_dxtdyt(dxts, dyts, dxt, dyt, face);
723                 imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, texres);
724                 
725                 /* edges? */
726                 
727                 if (texres->ta<1.0f) {
728                         TexResult texr1, texr2;
729         
730                         texr1.nor= texr2.nor= NULL;
731                         texr1.talpha= texr2.talpha= texres->talpha; /* boxclip expects this initialized */
732
733                         add_v3_v3(vec, dxt);
734                         face1= envcube_isect(env, vec, sco);
735                         sub_v3_v3(vec, dxt);
736                         
737                         if (face!=face1) {
738                                 ibuf= env->cube[face1];
739                                 set_dxtdyt(dxts, dyts, dxt, dyt, face1);
740                                 imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr1);
741                         }
742                         else texr1.tr= texr1.tg= texr1.tb= texr1.ta= 0.0;
743                         
744                         /* here was the nasty bug! results were not zero-ed. FPE! */
745                         
746                         add_v3_v3(vec, dyt);
747                         face1= envcube_isect(env, vec, sco);
748                         sub_v3_v3(vec, dyt);
749                         
750                         if (face!=face1) {
751                                 ibuf= env->cube[face1];
752                                 set_dxtdyt(dxts, dyts, dxt, dyt, face1);
753                                 imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr2);
754                         }
755                         else texr2.tr= texr2.tg= texr2.tb= texr2.ta= 0.0;
756                         
757                         fac= (texres->ta+texr1.ta+texr2.ta);
758                         if (fac!=0.0f) {
759                                 fac= 1.0f/fac;
760
761                                 texres->tr= fac*(texres->ta*texres->tr + texr1.ta*texr1.tr + texr2.ta*texr2.tr );
762                                 texres->tg= fac*(texres->ta*texres->tg + texr1.ta*texr1.tg + texr2.ta*texr2.tg );
763                                 texres->tb= fac*(texres->ta*texres->tb + texr1.ta*texr1.tb + texr2.ta*texr2.tb );
764                         }
765                         texres->ta= 1.0;
766                 }
767         }
768         else {
769                 imagewrap(tex, NULL, ibuf, sco, texres);
770         }
771         
772         return 1;
773 }
774
775 /* ------------------------------------------------------------------------- */
776
777 /* eof */