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