Blender V2.61 - r43446

envmap.c

Go to the documentation of this file.
00001 /* 
00002  *
00003  * ***** BEGIN GPL LICENSE BLOCK *****
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  *
00019  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00020  * All rights reserved.
00021  *
00022  * Contributors: 2004/2005/2006 Blender Foundation, full recode
00023  *
00024  * ***** END GPL LICENSE BLOCK *****
00025  */
00026 
00032 #include <math.h>
00033 #include <string.h>
00034 
00035 /* external modules: */
00036 #include "MEM_guardedalloc.h"
00037 
00038 #include "BLI_math.h"
00039 #include "BLI_blenlib.h"
00040 #include "BLI_threads.h"
00041 #include "BLI_utildefines.h"
00042 
00043 #include "IMB_imbuf_types.h"
00044 #include "IMB_imbuf.h"        /* for rectcpy */
00045 
00046 #include "DNA_group_types.h"
00047 #include "DNA_image_types.h"
00048 #include "DNA_object_types.h"
00049 #include "DNA_scene_types.h"
00050 #include "DNA_texture_types.h"
00051 
00052 #include "BKE_library.h"
00053 #include "BKE_main.h"
00054 #include "BKE_image.h"   // BKE_write_ibuf 
00055 #include "BKE_texture.h"
00056 
00057 
00058 
00059 
00060 /* this module */
00061 #include "render_types.h"
00062 #include "renderpipeline.h"
00063 #include "envmap.h"
00064 #include "rendercore.h" 
00065 #include "renderdatabase.h" 
00066 #include "texture.h"
00067 #include "zbuf.h"
00068 #include "initrender.h"
00069 
00070 
00071 /* ------------------------------------------------------------------------- */
00072 
00073 static void envmap_split_ima(EnvMap *env, ImBuf *ibuf)
00074 {
00075     int dx, part;
00076     
00077     /* after lock we test cube[1], if set the other thread has done it fine */
00078     BLI_lock_thread(LOCK_IMAGE);
00079     if(env->cube[1]==NULL) {
00080 
00081         BKE_free_envmapdata(env);   
00082     
00083         dx= ibuf->y;
00084         dx/= 2;
00085         if (3*dx == ibuf->x) {
00086             env->type = ENV_CUBE;
00087             env->ok= ENV_OSA;
00088         } else if (ibuf->x == ibuf->y) {
00089             env->type = ENV_PLANE;
00090             env->ok= ENV_OSA;
00091         } else {
00092             printf("Incorrect envmap size\n");
00093             env->ok= 0;
00094             env->ima->ok= 0;
00095         }
00096         
00097         if(env->ok) {
00098             if (env->type == ENV_CUBE) {
00099                 for(part=0; part<6; part++) {
00100                     env->cube[part]= IMB_allocImBuf(dx, dx, 24, IB_rect|IB_rectfloat);
00101                 }
00102                 IMB_float_from_rect(ibuf);
00103                 
00104                 IMB_rectcpy(env->cube[0], ibuf, 
00105                     0, 0, 0, 0, dx, dx);
00106                 IMB_rectcpy(env->cube[1], ibuf, 
00107                     0, 0, dx, 0, dx, dx);
00108                 IMB_rectcpy(env->cube[2], ibuf, 
00109                     0, 0, 2*dx, 0, dx, dx);
00110                 IMB_rectcpy(env->cube[3], ibuf, 
00111                     0, 0, 0, dx, dx, dx);
00112                 IMB_rectcpy(env->cube[4], ibuf, 
00113                     0, 0, dx, dx, dx, dx);
00114                 IMB_rectcpy(env->cube[5], ibuf, 
00115                     0, 0, 2*dx, dx, dx, dx);
00116                 
00117             }
00118             else { /* ENV_PLANE */
00119                 env->cube[1]= IMB_dupImBuf(ibuf);
00120                 IMB_float_from_rect(env->cube[1]);
00121             }
00122         }
00123     }   
00124     BLI_unlock_thread(LOCK_IMAGE);
00125 }
00126 
00127 /* ------------------------------------------------------------------------- */
00128 /* ****************** RENDER ********************** */
00129 
00130 /* copy current render */
00131 static Render *envmap_render_copy(Render *re, EnvMap *env)
00132 {
00133     Render *envre;
00134     float viewscale;
00135     int cuberes;
00136     
00137     envre= RE_NewRender("Envmap");
00138     
00139     env->lastsize= re->r.size;
00140     cuberes = (env->cuberes * re->r.size) / 100;
00141     cuberes &= 0xFFFC;
00142     
00143     /* this flag has R_ZTRA in it for example */
00144     envre->flag= re->flag;
00145     
00146     /* set up renderdata */
00147     envre->r= re->r;
00148     envre->r.mode &= ~(R_BORDER | R_PANORAMA | R_ORTHO | R_MBLUR);
00149     envre->r.layers.first= envre->r.layers.last= NULL;
00150     envre->r.filtertype= 0;
00151     envre->r.xparts= envre->r.yparts= 2;
00152     envre->r.size= 100;
00153     envre->r.yasp= envre->r.xasp= 1;
00154     
00155     RE_InitState(envre, NULL, &envre->r, NULL, cuberes, cuberes, NULL);
00156     envre->scene= re->scene;    /* unsure about this... */
00157     envre->lay= re->lay;
00158 
00159     /* view stuff in env render */
00160     viewscale= (env->type == ENV_PLANE)? env->viewscale: 1.0f;
00161     RE_SetEnvmapCamera(envre, env->object, viewscale, env->clipsta, env->clipend);
00162     
00163     /* callbacks */
00164     envre->display_draw= re->display_draw;
00165     envre->ddh= re->ddh;
00166     envre->test_break= re->test_break;
00167     envre->tbh= re->tbh;
00168     
00169     /* and for the evil stuff; copy the database... */
00170     envre->totvlak= re->totvlak;
00171     envre->totvert= re->totvert;
00172     envre->tothalo= re->tothalo;
00173     envre->totstrand= re->totstrand;
00174     envre->totlamp= re->totlamp;
00175     envre->sortedhalos= re->sortedhalos;
00176     envre->lights= re->lights;
00177     envre->objecttable= re->objecttable;
00178     envre->customdata_names= re->customdata_names;
00179     envre->raytree= re->raytree;
00180     envre->totinstance= re->totinstance;
00181     envre->instancetable= re->instancetable;
00182     envre->objectinstance= re->objectinstance;
00183     envre->qmcsamplers= re->qmcsamplers;
00184     
00185     return envre;
00186 }
00187 
00188 static void envmap_free_render_copy(Render *envre)
00189 {
00190 
00191     envre->totvlak= 0;
00192     envre->totvert= 0;
00193     envre->tothalo= 0;
00194     envre->totstrand= 0;
00195     envre->totlamp= 0;
00196     envre->totinstance= 0;
00197     envre->sortedhalos= NULL;
00198     envre->lights.first= envre->lights.last= NULL;
00199     envre->objecttable.first= envre->objecttable.last= NULL;
00200     envre->customdata_names.first= envre->customdata_names.last= NULL;
00201     envre->raytree= NULL;
00202     envre->instancetable.first= envre->instancetable.last= NULL;
00203     envre->objectinstance= NULL;
00204     envre->qmcsamplers= NULL;
00205     
00206     RE_FreeRender(envre);
00207 }
00208 
00209 /* ------------------------------------------------------------------------- */
00210 
00211 static void envmap_transmatrix(float mat[][4], int part)
00212 {
00213     float tmat[4][4], eul[3], rotmat[4][4];
00214     
00215     eul[0]= eul[1]= eul[2]= 0.0;
00216     
00217     if(part==0) {           /* neg z */
00218         ;
00219     } else if(part==1) {    /* pos z */
00220         eul[0]= M_PI;
00221     } else if(part==2) {    /* pos y */
00222         eul[0]= M_PI/2.0;
00223     } else if(part==3) {    /* neg x */
00224         eul[0]= M_PI/2.0;
00225         eul[2]= M_PI/2.0;
00226     } else if(part==4) {    /* neg y */
00227         eul[0]= M_PI/2.0;
00228         eul[2]= M_PI;
00229     } else {                /* pos x */
00230         eul[0]= M_PI/2.0;
00231         eul[2]= -M_PI/2.0;
00232     }
00233     
00234     copy_m4_m4(tmat, mat);
00235     eul_to_mat4( rotmat,eul);
00236     mul_serie_m4(mat, tmat, rotmat,
00237                      NULL, NULL, NULL,
00238                      NULL, NULL, NULL);
00239 }
00240 
00241 /* ------------------------------------------------------------------------- */
00242 
00243 static void env_rotate_scene(Render *re, float mat[][4], int mode)
00244 {
00245     GroupObject *go;
00246     ObjectRen *obr;
00247     ObjectInstanceRen *obi;
00248     LampRen *lar = NULL;
00249     HaloRen *har = NULL;
00250     float imat[3][3], pmat[4][4], smat[4][4], tmat[4][4], cmat[3][3], tmpmat[4][4];
00251     int a;
00252     
00253     if(mode==0) {
00254         invert_m4_m4(tmat, mat);
00255         copy_m3_m4(imat, tmat);
00256     }
00257     else {
00258         copy_m4_m4(tmat, mat);
00259         copy_m3_m4(imat, mat);
00260     }
00261 
00262     for(obi=re->instancetable.first; obi; obi=obi->next) {
00263         /* append or set matrix depending on dupli */
00264         if(obi->flag & R_DUPLI_TRANSFORMED) {
00265             copy_m4_m4(tmpmat, obi->mat);
00266             mult_m4_m4m4(obi->mat, tmat, tmpmat);
00267         }
00268         else if(mode==1)
00269             copy_m4_m4(obi->mat, tmat);
00270         else
00271             unit_m4(obi->mat);
00272 
00273         copy_m3_m4(cmat, obi->mat);
00274         invert_m3_m3(obi->nmat, cmat);
00275         transpose_m3(obi->nmat);
00276 
00277         /* indicate the renderer has to use transform matrices */
00278         if(mode==0)
00279             obi->flag &= ~R_ENV_TRANSFORMED;
00280         else
00281             obi->flag |= R_ENV_TRANSFORMED;
00282     }
00283     
00284 
00285     for(obr=re->objecttable.first; obr; obr=obr->next) {
00286         for(a=0; a<obr->tothalo; a++) {
00287             if((a & 255)==0) har= obr->bloha[a>>8];
00288             else har++;
00289         
00290             mul_m4_v3(tmat, har->co);
00291         }
00292     }
00293     
00294     for(go=re->lights.first; go; go= go->next) {
00295         lar= go->lampren;
00296         
00297         /* removed here some horrible code of someone in NaN who tried to fix
00298            prototypes... just solved by introducing a correct cmat[3][3] instead
00299            of using smat. this works, check square spots in reflections  (ton) */
00300         copy_m3_m3(cmat, lar->imat); 
00301         mul_m3_m3m3(lar->imat, cmat, imat); 
00302 
00303         mul_m3_v3(imat, lar->vec);
00304         mul_m4_v3(tmat, lar->co);
00305 
00306         lar->sh_invcampos[0]= -lar->co[0];
00307         lar->sh_invcampos[1]= -lar->co[1];
00308         lar->sh_invcampos[2]= -lar->co[2];
00309         mul_m3_v3(lar->imat, lar->sh_invcampos);
00310         lar->sh_invcampos[2]*= lar->sh_zfac;
00311         
00312         if(lar->shb) {
00313             if(mode==1) {
00314                 invert_m4_m4(pmat, mat);
00315                 mult_m4_m4m4(smat, lar->shb->viewmat, pmat);
00316                 mult_m4_m4m4(lar->shb->persmat, lar->shb->winmat, smat);
00317             }
00318             else mult_m4_m4m4(lar->shb->persmat, lar->shb->winmat, lar->shb->viewmat);
00319         }
00320     }
00321     
00322 }
00323 
00324 /* ------------------------------------------------------------------------- */
00325 
00326 static void env_layerflags(Render *re, unsigned int notlay)
00327 {
00328     ObjectRen *obr;
00329     VlakRen *vlr = NULL;
00330     int a;
00331     
00332     /* invert notlay, so if face is in multiple layers it will still be visible,
00333        unless all 'notlay' bits match the face bits.
00334        face: 0110
00335        not:  0100
00336        ~not: 1011
00337        now (face & ~not) is true
00338     */
00339     
00340     notlay= ~notlay;
00341     
00342     for(obr=re->objecttable.first; obr; obr=obr->next) {
00343         if((obr->lay & notlay)==0) {
00344             for(a=0; a<obr->totvlak; a++) {
00345                 if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
00346                 else vlr++;
00347 
00348                 vlr->flag |= R_HIDDEN;
00349             }
00350         }
00351     }
00352 }
00353 
00354 static void env_hideobject(Render *re, Object *ob)
00355 {
00356     ObjectRen *obr;
00357     VlakRen *vlr = NULL;
00358     int a;
00359     
00360     for(obr=re->objecttable.first; obr; obr=obr->next) {
00361         for(a=0; a<obr->totvlak; a++) {
00362             if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
00363             else vlr++;
00364 
00365             if(obr->ob == ob)
00366                 vlr->flag |= R_HIDDEN;
00367         }
00368     }
00369 }
00370 
00371 static void env_showobjects(Render *re)
00372 {
00373     ObjectRen *obr;
00374     VlakRen *vlr = NULL;
00375     int a;
00376     
00377     for(obr=re->objecttable.first; obr; obr=obr->next) {
00378         for(a=0; a<obr->totvlak; a++) {
00379             if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
00380             else vlr++;
00381 
00382             vlr->flag &= ~R_HIDDEN;
00383         }
00384     }
00385 }
00386 
00387 /* ------------------------------------------------------------------------- */
00388 
00389 static void env_set_imats(Render *re)
00390 {
00391     Base *base;
00392     float mat[4][4];
00393     
00394     base= re->scene->base.first;
00395     while(base) {
00396         mult_m4_m4m4(mat, re->viewmat, base->object->obmat);
00397         invert_m4_m4(base->object->imat, mat);
00398         
00399         base= base->next;
00400     }
00401 
00402 }   
00403 
00404 /* ------------------------------------------------------------------------- */
00405 
00406 static void render_envmap(Render *re, EnvMap *env)
00407 {
00408     /* only the cubemap and planar map is implemented */
00409     Render *envre;
00410     ImBuf *ibuf;
00411     float orthmat[4][4];
00412     float oldviewinv[4][4], mat[4][4], tmat[4][4];
00413     short part;
00414     
00415     /* need a recalc: ortho-render has no correct viewinv */
00416     invert_m4_m4(oldviewinv, re->viewmat);
00417 
00418     envre= envmap_render_copy(re, env);
00419     
00420     /* precalc orthmat for object */
00421     copy_m4_m4(orthmat, env->object->obmat);
00422     normalize_m4(orthmat);
00423     
00424     /* need imat later for texture imat */
00425     mult_m4_m4m4(mat, re->viewmat, orthmat);
00426     invert_m4_m4(tmat, mat);
00427     copy_m3_m4(env->obimat, tmat);
00428 
00429     for(part=0; part<6; part++) {
00430         if(env->type==ENV_PLANE && part!=1)
00431             continue;
00432         
00433         re->display_clear(re->dch, envre->result);
00434         
00435         copy_m4_m4(tmat, orthmat);
00436         envmap_transmatrix(tmat, part);
00437         invert_m4_m4(mat, tmat);
00438         /* mat now is the camera 'viewmat' */
00439 
00440         copy_m4_m4(envre->viewmat, mat);
00441         copy_m4_m4(envre->viewinv, tmat);
00442         
00443         /* we have to correct for the already rotated vertexcoords */
00444         mult_m4_m4m4(tmat, envre->viewmat, oldviewinv);
00445         invert_m4_m4(env->imat, tmat);
00446         
00447         env_rotate_scene(envre, tmat, 1);
00448         init_render_world(envre);
00449         project_renderdata(envre, projectverto, 0, 0, 1);
00450         env_layerflags(envre, env->notlay);
00451         env_hideobject(envre, env->object);
00452         env_set_imats(envre);
00453                 
00454         if(re->test_break(re->tbh)==0) {
00455             RE_TileProcessor(envre);
00456         }
00457         
00458         /* rotate back */
00459         env_showobjects(envre);
00460         env_rotate_scene(envre, tmat, 0);
00461 
00462         if(re->test_break(re->tbh)==0) {
00463             RenderLayer *rl= envre->result->layers.first;
00464             int y;
00465             float *alpha;
00466             
00467             ibuf= IMB_allocImBuf(envre->rectx, envre->recty, 24, IB_rect|IB_rectfloat);
00468             memcpy(ibuf->rect_float, rl->rectf, ibuf->channels * ibuf->x * ibuf->y * sizeof(float));
00469             
00470             if (re->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)
00471                 ibuf->profile = IB_PROFILE_LINEAR_RGB;
00472             
00473             /* envmap renders without alpha */
00474             alpha= ((float *)ibuf->rect_float)+3;
00475             for(y= ibuf->x*ibuf->y - 1; y>=0; y--, alpha+=4)
00476                 *alpha= 1.0;
00477             
00478             env->cube[part]= ibuf;
00479         }
00480         
00481         if(re->test_break(re->tbh)) break;
00482 
00483     }
00484     
00485     if(re->test_break(re->tbh)) BKE_free_envmapdata(env);
00486     else {
00487         if(envre->r.mode & R_OSA) env->ok= ENV_OSA;
00488         else env->ok= ENV_NORMAL;
00489         env->lastframe= re->scene->r.cfra;
00490     }
00491     
00492     /* restore */
00493     envmap_free_render_copy(envre);
00494     env_set_imats(re);
00495 
00496 }
00497 
00498 /* ------------------------------------------------------------------------- */
00499 
00500 void make_envmaps(Render *re)
00501 {
00502     Tex *tex;
00503     int do_init= 0, depth= 0, trace;
00504     
00505     if (!(re->r.mode & R_ENVMAP)) return;
00506     
00507     /* we dont raytrace, disabling the flag will cause ray_transp render solid */
00508     trace= (re->r.mode & R_RAYTRACE);
00509     re->r.mode &= ~R_RAYTRACE;
00510 
00511     re->i.infostr= "Creating Environment maps";
00512     re->stats_draw(re->sdh, &re->i);
00513     
00514     /* 5 = hardcoded max recursion level */
00515     while(depth<5) {
00516         tex= re->main->tex.first;
00517         while(tex) {
00518             if(tex->id.us && tex->type==TEX_ENVMAP) {
00519                 if(tex->env && tex->env->object) {
00520                     EnvMap *env= tex->env;
00521                     
00522                     if(env->object->lay & re->lay) {
00523                         if(env->stype==ENV_LOAD) {
00524                             float orthmat[4][4], mat[4][4], tmat[4][4];
00525                             
00526                             /* precalc orthmat for object */
00527                             copy_m4_m4(orthmat, env->object->obmat);
00528                             normalize_m4(orthmat);
00529                             
00530                             /* need imat later for texture imat */
00531                             mult_m4_m4m4(mat, re->viewmat, orthmat);
00532                             invert_m4_m4(tmat, mat);
00533                             copy_m3_m4(env->obimat, tmat);
00534                         }
00535                         else {
00536                             
00537                             /* decide if to render an envmap (again) */
00538                             if(env->depth >= depth) {
00539                                 
00540                                 /* set 'recalc' to make sure it does an entire loop of recalcs */
00541                                 
00542                                 if(env->ok) {
00543                                         /* free when OSA, and old one isn't OSA */
00544                                     if((re->r.mode & R_OSA) && env->ok==ENV_NORMAL) 
00545                                         BKE_free_envmapdata(env);
00546                                         /* free when size larger */
00547                                     else if(env->lastsize < re->r.size) 
00548                                         BKE_free_envmapdata(env);
00549                                         /* free when env is in recalcmode */
00550                                     else if(env->recalc)
00551                                         BKE_free_envmapdata(env);
00552                                 }
00553                                 
00554                                 if(env->ok==0 && depth==0) env->recalc= 1;
00555                                 
00556                                 if(env->ok==0) {
00557                                     do_init= 1;
00558                                     render_envmap(re, env);
00559                                     
00560                                     if(depth==env->depth) env->recalc= 0;
00561                                 }
00562                             }
00563                         }
00564                     }
00565                 }
00566             }
00567             tex= tex->id.next;
00568         }
00569         depth++;
00570     }
00571 
00572     if(do_init) {
00573         re->display_init(re->dih, re->result);
00574         re->display_clear(re->dch, re->result);
00575         // re->flag |= R_REDRAW_PRV;
00576     }   
00577     // restore
00578     re->r.mode |= trace;
00579 
00580 }
00581 
00582 /* ------------------------------------------------------------------------- */
00583 
00584 static int envcube_isect(EnvMap *env, float *vec, float *answ)
00585 {
00586     float labda;
00587     int face;
00588     
00589     if(env->type==ENV_PLANE) {
00590         face= 1;
00591         
00592         labda= 1.0f/vec[2];
00593         answ[0]= env->viewscale*labda*vec[0];
00594         answ[1]= -env->viewscale*labda*vec[1];
00595     }
00596     else {
00597         /* which face */
00598         if( vec[2] <= -fabsf(vec[0]) && vec[2] <= -fabsf(vec[1]) ) {
00599             face= 0;
00600             labda= -1.0f/vec[2];
00601             answ[0]= labda*vec[0];
00602             answ[1]= labda*vec[1];
00603         }
00604         else if (vec[2] >= fabsf(vec[0]) && vec[2] >= fabsf(vec[1])) {
00605             face= 1;
00606             labda= 1.0f/vec[2];
00607             answ[0]= labda*vec[0];
00608             answ[1]= -labda*vec[1];
00609         }
00610         else if (vec[1] >= fabsf(vec[0])) {
00611             face= 2;
00612             labda= 1.0f/vec[1];
00613             answ[0]= labda*vec[0];
00614             answ[1]= labda*vec[2];
00615         }
00616         else if (vec[0] <= -fabsf(vec[1])) {
00617             face= 3;
00618             labda= -1.0f/vec[0];
00619             answ[0]= labda*vec[1];
00620             answ[1]= labda*vec[2];
00621         }
00622         else if (vec[1] <= -fabsf(vec[0])) {
00623             face= 4;
00624             labda= -1.0f/vec[1];
00625             answ[0]= -labda*vec[0];
00626             answ[1]= labda*vec[2];
00627         }
00628         else {
00629             face= 5;
00630             labda= 1.0f/vec[0];
00631             answ[0]= -labda*vec[1];
00632             answ[1]= labda*vec[2];
00633         }
00634     }
00635     
00636     answ[0]= 0.5f+0.5f*answ[0];
00637     answ[1]= 0.5f+0.5f*answ[1];
00638     return face;
00639 }
00640 
00641 /* ------------------------------------------------------------------------- */
00642 
00643 static void set_dxtdyt(float *dxts, float *dyts, float *dxt, float *dyt, int face)
00644 {
00645     if(face==2 || face==4) {
00646         dxts[0]= dxt[0];
00647         dyts[0]= dyt[0];
00648         dxts[1]= dxt[2];
00649         dyts[1]= dyt[2];
00650     }
00651     else if(face==3 || face==5) {
00652         dxts[0]= dxt[1];
00653         dxts[1]= dxt[2];
00654         dyts[0]= dyt[1];
00655         dyts[1]= dyt[2];
00656     }
00657     else {
00658         dxts[0]= dxt[0];
00659         dyts[0]= dyt[0];
00660         dxts[1]= dxt[1];
00661         dyts[1]= dyt[1];
00662     }
00663 }
00664 
00665 /* ------------------------------------------------------------------------- */
00666 
00667 int envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres)
00668 {
00669     extern Render R;                /* only in this call */
00670     /* texvec should be the already reflected normal */
00671     EnvMap *env;
00672     ImBuf *ibuf;
00673     float fac, vec[3], sco[3], dxts[3], dyts[3];
00674     int face, face1;
00675     
00676     env= tex->env;
00677     if(env==NULL || (env->stype!=ENV_LOAD && env->object==NULL)) {
00678         texres->tin= 0.0;
00679         return 0;
00680     }
00681     
00682     if(env->stype==ENV_LOAD) {
00683         env->ima= tex->ima;
00684         if(env->ima && env->ima->ok) {
00685             if(env->cube[1]==NULL) {
00686                 ImBuf *ibuf_ima= BKE_image_get_ibuf(env->ima, NULL);
00687                 if(ibuf_ima)
00688                     envmap_split_ima(env, ibuf_ima);
00689                 else
00690                     env->ok= 0;
00691             }
00692         }
00693     }
00694 
00695     if(env->ok==0) {
00696         texres->tin= 0.0;
00697         return 0;
00698     }
00699     
00700     /* rotate to envmap space, if object is set */
00701     copy_v3_v3(vec, texvec);
00702     if(env->object) mul_m3_v3(env->obimat, vec);
00703     else mul_mat3_m4_v3(R.viewinv, vec);
00704     
00705     face= envcube_isect(env, vec, sco);
00706     ibuf= env->cube[face];
00707     
00708     if(osatex) {
00709         if(env->object) {
00710             mul_m3_v3(env->obimat, dxt);
00711             mul_m3_v3(env->obimat, dyt);
00712         }
00713         else {
00714             mul_mat3_m4_v3(R.viewinv, dxt);
00715             mul_mat3_m4_v3(R.viewinv, dyt);
00716         }
00717         set_dxtdyt(dxts, dyts, dxt, dyt, face);
00718         imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, texres);
00719         
00720         /* edges? */
00721         
00722         if(texres->ta<1.0f) {
00723             TexResult texr1, texr2;
00724     
00725             texr1.nor= texr2.nor= NULL;
00726             texr1.talpha= texr2.talpha= texres->talpha; /* boxclip expects this initialized */
00727 
00728             add_v3_v3(vec, dxt);
00729             face1= envcube_isect(env, vec, sco);
00730             sub_v3_v3(vec, dxt);
00731             
00732             if(face!=face1) {
00733                 ibuf= env->cube[face1];
00734                 set_dxtdyt(dxts, dyts, dxt, dyt, face1);
00735                 imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr1);
00736             }
00737             else texr1.tr= texr1.tg= texr1.tb= texr1.ta= 0.0;
00738             
00739             /* here was the nasty bug! results were not zero-ed. FPE! */
00740             
00741             add_v3_v3(vec, dyt);
00742             face1= envcube_isect(env, vec, sco);
00743             sub_v3_v3(vec, dyt);
00744             
00745             if(face!=face1) {
00746                 ibuf= env->cube[face1];
00747                 set_dxtdyt(dxts, dyts, dxt, dyt, face1);
00748                 imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr2);
00749             }
00750             else texr2.tr= texr2.tg= texr2.tb= texr2.ta= 0.0;
00751             
00752             fac= (texres->ta+texr1.ta+texr2.ta);
00753             if(fac!=0.0f) {
00754                 fac= 1.0f/fac;
00755 
00756                 texres->tr= fac*(texres->ta*texres->tr + texr1.ta*texr1.tr + texr2.ta*texr2.tr );
00757                 texres->tg= fac*(texres->ta*texres->tg + texr1.ta*texr1.tg + texr2.ta*texr2.tg );
00758                 texres->tb= fac*(texres->ta*texres->tb + texr1.ta*texr1.tb + texr2.ta*texr2.tb );
00759             }
00760             texres->ta= 1.0;
00761         }
00762     }
00763     else {
00764         imagewrap(tex, NULL, ibuf, sco, texres);
00765     }
00766     
00767     return 1;
00768 }
00769 
00770 /* ------------------------------------------------------------------------- */
00771 
00772 /* eof */