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