Blender V2.61 - r43446

imagetexture.c

Go to the documentation of this file.
00001 /*
00002  *
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/BL DUAL LICENSE BLOCK *****
00026  */
00027 
00035 #include <stdio.h>
00036 #include <string.h>
00037 #include <fcntl.h>
00038 #include <math.h>
00039 #include <float.h>
00040 #ifndef WIN32 
00041 #include <unistd.h>
00042 #else
00043 #include <io.h>
00044 #endif
00045 
00046 #include "MEM_guardedalloc.h"
00047 
00048 #include "IMB_imbuf_types.h"
00049 #include "IMB_imbuf.h"
00050 
00051 #include "DNA_image_types.h"
00052 #include "DNA_scene_types.h"
00053 #include "DNA_texture_types.h"
00054 
00055 #include "BLI_math.h"
00056 #include "BLI_blenlib.h"
00057 #include "BLI_threads.h"
00058 #include "BLI_utildefines.h"
00059 
00060 #include "BKE_global.h"
00061 #include "BKE_main.h"
00062 #include "BKE_image.h"
00063 #include "BKE_texture.h"
00064 #include "BKE_library.h"
00065 
00066 #include "RE_render_ext.h"
00067 
00068 #include "renderpipeline.h"
00069 #include "render_types.h"
00070 #include "texture.h"
00071 
00072 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
00073 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
00074 /* only to be used here in this file, it's for speed */
00075 extern struct Render R;
00076 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
00077 
00078 static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, TexResult *texres, const short imaprepeat, const short imapextend);
00079 
00080 /* *********** IMAGEWRAPPING ****************** */
00081 
00082 
00083 /* x and y have to be checked for image size */
00084 static void ibuf_get_color(float *col, struct ImBuf *ibuf, int x, int y)
00085 {
00086     int ofs = y * ibuf->x + x;
00087     
00088     if(ibuf->rect_float) {
00089         if(ibuf->channels==4) {
00090             float *fp= ibuf->rect_float + 4*ofs;
00091             copy_v4_v4(col, fp);
00092         }
00093         else if(ibuf->channels==3) {
00094             float *fp= ibuf->rect_float + 3*ofs;
00095             copy_v3_v3(col, fp);
00096             col[3]= 1.0f;
00097         }
00098         else {
00099             float *fp= ibuf->rect_float + ofs;
00100             col[0]= col[1]= col[2]= col[3]= *fp;
00101         }
00102     }
00103     else {
00104         char *rect = (char *)( ibuf->rect+ ofs);
00105 
00106         col[0] = ((float)rect[0])*(1.0f/255.0f);
00107         col[1] = ((float)rect[1])*(1.0f/255.0f);
00108         col[2] = ((float)rect[2])*(1.0f/255.0f);
00109         col[3] = ((float)rect[3])*(1.0f/255.0f);
00110     }   
00111 }
00112 
00113 int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResult *texres)
00114 {
00115     float fx, fy, val1, val2, val3;
00116     int x, y, retval;
00117     int xi, yi; /* original values */
00118 
00119     texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f;
00120     
00121     /* we need to set retval OK, otherwise texture code generates normals itself... */
00122     retval= texres->nor?3:1;
00123     
00124     /* quick tests */
00125     if(ibuf==NULL && ima==NULL)
00126         return retval;
00127     if(ima) {
00128         
00129         /* hack for icon render */
00130         if(ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD))
00131             return retval;
00132         
00133         ibuf= BKE_image_get_ibuf(ima, &tex->iuser);
00134     }
00135     if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL))
00136         return retval;
00137     
00138     /* setup mapping */
00139     if(tex->imaflag & TEX_IMAROT) {
00140         fy= texvec[0];
00141         fx= texvec[1];
00142     }
00143     else {
00144         fx= texvec[0];
00145         fy= texvec[1];
00146     }
00147     
00148     if(tex->extend == TEX_CHECKER) {
00149         int xs, ys;
00150         
00151         xs= (int)floor(fx);
00152         ys= (int)floor(fy);
00153         fx-= xs;
00154         fy-= ys;
00155 
00156         if( (tex->flag & TEX_CHECKER_ODD)==0) {
00157             if((xs+ys) & 1);else return retval;
00158         }
00159         if( (tex->flag & TEX_CHECKER_EVEN)==0) {
00160             if((xs+ys) & 1) return retval; 
00161         }
00162         /* scale around center, (0.5, 0.5) */
00163         if(tex->checkerdist<1.0f) {
00164             fx= (fx-0.5f)/(1.0f-tex->checkerdist) +0.5f;
00165             fy= (fy-0.5f)/(1.0f-tex->checkerdist) +0.5f;
00166         }
00167     }
00168 
00169     x= xi= (int)floorf(fx*ibuf->x);
00170     y= yi= (int)floorf(fy*ibuf->y);
00171 
00172     if(tex->extend == TEX_CLIPCUBE) {
00173         if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0f || texvec[2]>1.0f) {
00174             return retval;
00175         }
00176     }
00177     else if( tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
00178         if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) {
00179             return retval;
00180         }
00181     }
00182     else {
00183         if(tex->extend==TEX_EXTEND) {
00184             if(x>=ibuf->x) x = ibuf->x-1;
00185             else if(x<0) x= 0;
00186         }
00187         else {
00188             x= x % ibuf->x;
00189             if(x<0) x+= ibuf->x;
00190         }
00191         if(tex->extend==TEX_EXTEND) {
00192             if(y>=ibuf->y) y = ibuf->y-1;
00193             else if(y<0) y= 0;
00194         }
00195         else {
00196             y= y % ibuf->y;
00197             if(y<0) y+= ibuf->y;
00198         }
00199     }
00200     
00201     /* warning, no return before setting back! */
00202     if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
00203         ibuf->rect+= (ibuf->x*ibuf->y);
00204     }
00205 
00206     /* keep this before interpolation [#29761] */
00207     if (tex->imaflag & TEX_USEALPHA) {
00208         if ((tex->imaflag & TEX_CALCALPHA) == 0) {
00209             texres->talpha = TRUE;
00210         } 
00211     }
00212 
00213     /* interpolate */
00214     if (tex->imaflag & TEX_INTERPOL) {
00215         float filterx, filtery;
00216         filterx = (0.5f * tex->filtersize) / ibuf->x;
00217         filtery = (0.5f * tex->filtersize) / ibuf->y;
00218 
00219         /* important that this value is wrapped [#27782]
00220          * this applies the modifications made by the checks above,
00221          * back to the floating point values */
00222         fx -= (float)(xi - x) / (float)ibuf->x;
00223         fy -= (float)(yi - y) / (float)ibuf->y;
00224 
00225         boxsample(ibuf, fx-filterx, fy-filtery, fx+filterx, fy+filtery, texres, (tex->extend==TEX_REPEAT), (tex->extend==TEX_EXTEND));
00226     }
00227     else { /* no filtering */
00228         ibuf_get_color(&texres->tr, ibuf, x, y);
00229     }
00230     
00231     if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
00232         ibuf->rect-= (ibuf->x*ibuf->y);
00233     }
00234 
00235     if(texres->nor) {
00236         if(tex->imaflag & TEX_NORMALMAP) {
00237             // qdn: normal from color
00238             // The invert of the red channel is to make
00239             // the normal map compliant with the outside world.
00240             // It needs to be done because in Blender
00241             // the normal used in the renderer points inward. It is generated
00242             // this way in calc_vertexnormals(). Should this ever change
00243             // this negate must be removed.
00244             texres->nor[0] = -2.f*(texres->tr - 0.5f);
00245             texres->nor[1] = 2.f*(texres->tg - 0.5f);
00246             texres->nor[2] = 2.f*(texres->tb - 0.5f);
00247         }
00248         else {
00249             /* bump: take three samples */
00250             val1= texres->tr+texres->tg+texres->tb;
00251 
00252             if(x<ibuf->x-1) {
00253                 float col[4];
00254                 ibuf_get_color(col, ibuf, x+1, y);
00255                 val2= (col[0]+col[1]+col[2]);
00256             }
00257             else val2= val1;
00258 
00259             if(y<ibuf->y-1) {
00260                 float col[4];
00261                 ibuf_get_color(col, ibuf, x, y+1);
00262                 val3= (col[0]+col[1]+col[2]);
00263             }
00264             else val3= val1;
00265 
00266             /* do not mix up x and y here! */
00267             texres->nor[0]= (val1-val2);
00268             texres->nor[1]= (val1-val3);
00269         }
00270     }
00271 
00272     if(texres->talpha) texres->tin= texres->ta;
00273     else if(tex->imaflag & TEX_CALCALPHA) {
00274         texres->ta= texres->tin= MAX3(texres->tr, texres->tg, texres->tb);
00275     }
00276     else texres->ta= texres->tin= 1.0;
00277     
00278     if(tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta;
00279 
00280     /* de-premul, this is being premulled in shade_input_do_shade() */
00281     if(texres->ta!=1.0f && texres->ta>1e-4f) {
00282         fx= 1.0f/texres->ta;
00283         texres->tr*= fx;
00284         texres->tg*= fx;
00285         texres->tb*= fx;
00286     }
00287     
00288     BRICONTRGB;
00289     
00290     return retval;
00291 }
00292 
00293 static void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2)
00294 {
00295     rctf *rf, *newrct;
00296     short a;
00297 
00298     a= *count;
00299     rf= stack;
00300     for(;a>0;a--) {
00301         if(rf->xmin<x1) {
00302             if(rf->xmax<x1) {
00303                 rf->xmin+= (x2-x1);
00304                 rf->xmax+= (x2-x1);
00305             }
00306             else {
00307                 if(rf->xmax>x2) rf->xmax= x2;
00308                 newrct= stack+ *count;
00309                 (*count)++;
00310 
00311                 newrct->xmax= x2;
00312                 newrct->xmin= rf->xmin+(x2-x1);
00313                 newrct->ymin= rf->ymin;
00314                 newrct->ymax= rf->ymax;
00315                 
00316                 if(newrct->xmin==newrct->xmax) (*count)--;
00317                 
00318                 rf->xmin= x1;
00319             }
00320         }
00321         else if(rf->xmax>x2) {
00322             if(rf->xmin>x2) {
00323                 rf->xmin-= (x2-x1);
00324                 rf->xmax-= (x2-x1);
00325             }
00326             else {
00327                 if(rf->xmin<x1) rf->xmin= x1;
00328                 newrct= stack+ *count;
00329                 (*count)++;
00330 
00331                 newrct->xmin= x1;
00332                 newrct->xmax= rf->xmax-(x2-x1);
00333                 newrct->ymin= rf->ymin;
00334                 newrct->ymax= rf->ymax;
00335 
00336                 if(newrct->xmin==newrct->xmax) (*count)--;
00337 
00338                 rf->xmax= x2;
00339             }
00340         }
00341         rf++;
00342     }
00343 
00344 }
00345 
00346 static void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2)
00347 {
00348     rctf *rf, *newrct;
00349     short a;
00350 
00351     a= *count;
00352     rf= stack;
00353     for(;a>0;a--) {
00354         if(rf->ymin<y1) {
00355             if(rf->ymax<y1) {
00356                 rf->ymin+= (y2-y1);
00357                 rf->ymax+= (y2-y1);
00358             }
00359             else {
00360                 if(rf->ymax>y2) rf->ymax= y2;
00361                 newrct= stack+ *count;
00362                 (*count)++;
00363 
00364                 newrct->ymax= y2;
00365                 newrct->ymin= rf->ymin+(y2-y1);
00366                 newrct->xmin= rf->xmin;
00367                 newrct->xmax= rf->xmax;
00368 
00369                 if(newrct->ymin==newrct->ymax) (*count)--;
00370 
00371                 rf->ymin= y1;
00372             }
00373         }
00374         else if(rf->ymax>y2) {
00375             if(rf->ymin>y2) {
00376                 rf->ymin-= (y2-y1);
00377                 rf->ymax-= (y2-y1);
00378             }
00379             else {
00380                 if(rf->ymin<y1) rf->ymin= y1;
00381                 newrct= stack+ *count;
00382                 (*count)++;
00383 
00384                 newrct->ymin= y1;
00385                 newrct->ymax= rf->ymax-(y2-y1);
00386                 newrct->xmin= rf->xmin;
00387                 newrct->xmax= rf->xmax;
00388 
00389                 if(newrct->ymin==newrct->ymax) (*count)--;
00390 
00391                 rf->ymax= y2;
00392             }
00393         }
00394         rf++;
00395     }
00396 }
00397 
00398 static float square_rctf(rctf *rf)
00399 {
00400     float x, y;
00401 
00402     x= rf->xmax- rf->xmin;
00403     y= rf->ymax- rf->ymin;
00404     return (x*y);
00405 }
00406 
00407 static float clipx_rctf(rctf *rf, float x1, float x2)
00408 {
00409     float size;
00410 
00411     size= rf->xmax - rf->xmin;
00412 
00413     if(rf->xmin<x1) {
00414         rf->xmin= x1;
00415     }
00416     if(rf->xmax>x2) {
00417         rf->xmax= x2;
00418     }
00419     if(rf->xmin > rf->xmax) {
00420         rf->xmin = rf->xmax;
00421         return 0.0;
00422     }
00423     else if(size!=0.0f) {
00424         return (rf->xmax - rf->xmin)/size;
00425     }
00426     return 1.0;
00427 }
00428 
00429 static float clipy_rctf(rctf *rf, float y1, float y2)
00430 {
00431     float size;
00432 
00433     size= rf->ymax - rf->ymin;
00434 
00435     if(rf->ymin<y1) {
00436         rf->ymin= y1;
00437     }
00438     if(rf->ymax>y2) {
00439         rf->ymax= y2;
00440     }
00441 
00442     if(rf->ymin > rf->ymax) {
00443         rf->ymin = rf->ymax;
00444         return 0.0;
00445     }
00446     else if(size!=0.0f) {
00447         return (rf->ymax - rf->ymin)/size;
00448     }
00449     return 1.0;
00450 
00451 }
00452 
00453 static void boxsampleclip(struct ImBuf *ibuf, rctf *rf, TexResult *texres)
00454 {
00455     /* sample box, is clipped already, and minx etc. have been set at ibuf size.
00456        Enlarge with antialiased edges of the pixels */
00457 
00458     float muly, mulx, div, col[4];
00459     int x, y, startx, endx, starty, endy;
00460 
00461     startx= (int)floor(rf->xmin);
00462     endx= (int)floor(rf->xmax);
00463     starty= (int)floor(rf->ymin);
00464     endy= (int)floor(rf->ymax);
00465 
00466     if(startx < 0) startx= 0;
00467     if(starty < 0) starty= 0;
00468     if(endx>=ibuf->x) endx= ibuf->x-1;
00469     if(endy>=ibuf->y) endy= ibuf->y-1;
00470 
00471     if(starty==endy && startx==endx) {
00472         ibuf_get_color(&texres->tr, ibuf, startx, starty);
00473     }
00474     else {
00475         div= texres->tr= texres->tg= texres->tb= texres->ta= 0.0;
00476         for(y=starty; y<=endy; y++) {
00477             
00478             muly= 1.0;
00479 
00480             if(starty==endy);
00481             else {
00482                 if(y==starty) muly= 1.0f-(rf->ymin - y);
00483                 if(y==endy) muly= (rf->ymax - y);
00484             }
00485             
00486             if(startx==endx) {
00487                 mulx= muly;
00488                 
00489                 ibuf_get_color(col, ibuf, startx, y);
00490 
00491                 texres->ta+= mulx*col[3];
00492                 texres->tr+= mulx*col[0];
00493                 texres->tg+= mulx*col[1];
00494                 texres->tb+= mulx*col[2];
00495                 div+= mulx;
00496             }
00497             else {
00498                 for(x=startx; x<=endx; x++) {
00499                     mulx= muly;
00500                     if(x==startx) mulx*= 1.0f-(rf->xmin - x);
00501                     if(x==endx) mulx*= (rf->xmax - x);
00502 
00503                     ibuf_get_color(col, ibuf, x, y);
00504                     
00505                     if(mulx==1.0f) {
00506                         texres->ta+= col[3];
00507                         texres->tr+= col[0];
00508                         texres->tg+= col[1];
00509                         texres->tb+= col[2];
00510                         div+= 1.0f;
00511                     }
00512                     else {
00513                         texres->ta+= mulx*col[3];
00514                         texres->tr+= mulx*col[0];
00515                         texres->tg+= mulx*col[1];
00516                         texres->tb+= mulx*col[2];
00517                         div+= mulx;
00518                     }
00519                 }
00520             }
00521         }
00522 
00523         if(div!=0.0f) {
00524             div= 1.0f/div;
00525             texres->tb*= div;
00526             texres->tg*= div;
00527             texres->tr*= div;
00528             texres->ta*= div;
00529         }
00530         else {
00531             texres->tr= texres->tg= texres->tb= texres->ta= 0.0f;
00532         }
00533     }
00534 }
00535 
00536 static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, TexResult *texres, const short imaprepeat, const short imapextend)
00537 {
00538     /* Sample box, performs clip. minx etc are in range 0.0 - 1.0 .
00539      * Enlarge with antialiased edges of pixels.
00540      * If variable 'imaprepeat' has been set, the
00541      * clipped-away parts are sampled as well.
00542      */
00543     /* note: actually minx etc isnt in the proper range... this due to filter size and offset vectors for bump */
00544     /* note: talpha must be initialized */
00545     /* note: even when 'imaprepeat' is set, this can only repeate once in any direction.
00546      * the point which min/max is derived from is assumed to be wrapped */
00547     TexResult texr;
00548     rctf *rf, stack[8];
00549     float opp, tot, alphaclip= 1.0;
00550     short count=1;
00551 
00552     rf= stack;
00553     rf->xmin= minx*(ibuf->x);
00554     rf->xmax= maxx*(ibuf->x);
00555     rf->ymin= miny*(ibuf->y);
00556     rf->ymax= maxy*(ibuf->y);
00557 
00558     texr.talpha= texres->talpha;    /* is read by boxsample_clip */
00559     
00560     if(imapextend) {
00561         CLAMP(rf->xmin, 0.0f, ibuf->x-1);
00562         CLAMP(rf->xmax, 0.0f, ibuf->x-1);
00563     }
00564     else if(imaprepeat) 
00565         clipx_rctf_swap(stack, &count, 0.0, (float)(ibuf->x));
00566     else {
00567         alphaclip= clipx_rctf(rf, 0.0, (float)(ibuf->x));
00568 
00569         if(alphaclip<=0.0f) {
00570             texres->tr= texres->tb= texres->tg= texres->ta= 0.0;
00571             return;
00572         }
00573     }
00574 
00575     if(imapextend) {
00576         CLAMP(rf->ymin, 0.0f, ibuf->y-1);
00577         CLAMP(rf->ymax, 0.0f, ibuf->y-1);
00578     }
00579     else if(imaprepeat) 
00580         clipy_rctf_swap(stack, &count, 0.0, (float)(ibuf->y));
00581     else {
00582         alphaclip*= clipy_rctf(rf, 0.0, (float)(ibuf->y));
00583 
00584         if(alphaclip<=0.0f) {
00585             texres->tr= texres->tb= texres->tg= texres->ta= 0.0;
00586             return;
00587         }
00588     }
00589 
00590     if(count>1) {
00591         tot= texres->tr= texres->tb= texres->tg= texres->ta= 0.0;
00592         while(count--) {
00593             boxsampleclip(ibuf, rf, &texr);
00594             
00595             opp= square_rctf(rf);
00596             tot+= opp;
00597 
00598             texres->tr+= opp*texr.tr;
00599             texres->tg+= opp*texr.tg;
00600             texres->tb+= opp*texr.tb;
00601             if(texres->talpha) texres->ta+= opp*texr.ta;
00602             rf++;
00603         }
00604         if(tot!= 0.0f) {
00605             texres->tr/= tot;
00606             texres->tg/= tot;
00607             texres->tb/= tot;
00608             if(texres->talpha) texres->ta/= tot;
00609         }
00610     }
00611     else
00612         boxsampleclip(ibuf, rf, texres);
00613 
00614     if(texres->talpha==0) texres->ta= 1.0;
00615     
00616     if(alphaclip!=1.0f) {
00617         /* premul it all */
00618         texres->tr*= alphaclip;
00619         texres->tg*= alphaclip;
00620         texres->tb*= alphaclip;
00621         texres->ta*= alphaclip;
00622     }
00623 }   
00624 
00625 //-----------------------------------------------------------------------------------------------------------------
00626 // from here, some functions only used for the new filtering
00627 
00628 // anisotropic filters, data struct used instead of long line of (possibly unused) func args
00629 typedef struct afdata_t {
00630     float dxt[2], dyt[2];
00631     int intpol, extflag;
00632     // feline only
00633     float majrad, minrad, theta;
00634     int iProbes;
00635     float dusc, dvsc;
00636 } afdata_t;
00637 
00638 // this only used here to make it easier to pass extend flags as single int
00639 enum {TXC_XMIR=1, TXC_YMIR, TXC_REPT, TXC_EXTD};
00640 
00641 // similar to ibuf_get_color() but clips/wraps coords according to repeat/extend flags
00642 // returns true if out of range in clipmode
00643 static int ibuf_get_color_clip(float *col, ImBuf *ibuf, int x, int y, int extflag)
00644 {
00645     int clip = 0;
00646     switch (extflag) {
00647         case TXC_XMIR:  // y rep
00648             x %= 2*ibuf->x;
00649             x += x < 0 ? 2*ibuf->x : 0;
00650             x = x >= ibuf->x ? 2*ibuf->x - x - 1 : x;
00651             y %= ibuf->y;
00652             y += y < 0 ? ibuf->y : 0;
00653             break;
00654         case TXC_YMIR:  // x rep
00655             x %= ibuf->x;
00656             x += x < 0 ? ibuf->x : 0;
00657             y %= 2*ibuf->y;
00658             y += y < 0 ? 2*ibuf->y : 0;
00659             y = y >= ibuf->y ? 2*ibuf->y - y - 1 : y;
00660             break;
00661         case TXC_EXTD:
00662             x = (x < 0) ? 0 : ((x >= ibuf->x) ? (ibuf->x - 1) : x);
00663             y = (y < 0) ? 0 : ((y >= ibuf->y) ? (ibuf->y - 1) : y);
00664             break;
00665         case TXC_REPT:
00666             x %= ibuf->x;
00667             x += (x < 0) ? ibuf->x : 0;
00668             y %= ibuf->y;
00669             y += (y < 0) ? ibuf->y : 0;
00670             break;
00671         default:    {   // as extend, if clipped, set alpha to 0.0
00672             if (x < 0) { x = 0;  } // TXF alpha: clip = 1; }
00673             if (x >= ibuf->x) { x = ibuf->x - 1; } // TXF alpha:  clip = 1; }
00674             if (y < 0) { y = 0; } // TXF alpha:  clip = 1; }
00675             if (y >= ibuf->y) { y = ibuf->y - 1; } // TXF alpha:  clip = 1; }
00676         }
00677     }
00678 
00679     if (ibuf->rect_float) {
00680         const float* fp = ibuf->rect_float + (x + y*ibuf->x)*ibuf->channels;
00681         if (ibuf->channels == 1)
00682             col[0] = col[1] = col[2] = col[3] = *fp;
00683         else {
00684             col[0] = fp[0];
00685             col[1] = fp[1];
00686             col[2] = fp[2];
00687             col[3] = clip ? 0.f : (ibuf->channels == 4 ? fp[3] : 1.f);
00688         }
00689     }
00690     else {
00691         char* rect = (char*)(ibuf->rect + x + y*ibuf->x);
00692         col[0] = rect[0]*(1.f/255.f);
00693         col[1] = rect[1]*(1.f/255.f);
00694         col[2] = rect[2]*(1.f/255.f);
00695         col[3] = clip ? 0.f : rect[3]*(1.f/255.f);
00696     }
00697     return clip;
00698 }
00699 
00700 // as above + bilerp
00701 static int ibuf_get_color_clip_bilerp(float *col, ImBuf *ibuf, float u, float v, int intpol, int extflag)
00702 {
00703     if (intpol) {
00704         float c00[4], c01[4], c10[4], c11[4];
00705         const float ufl = floorf(u -= 0.5f), vfl = floorf(v -= 0.5f);
00706         const float uf = u - ufl, vf = v - vfl;
00707         const float w00=(1.f-uf)*(1.f-vf), w10=uf*(1.f-vf), w01=(1.f-uf)*vf, w11=uf*vf;
00708         const int x1 = (int)ufl, y1 = (int)vfl, x2 = x1 + 1, y2 = y1 + 1;
00709         int clip = ibuf_get_color_clip(c00, ibuf, x1, y1, extflag);
00710         clip |= ibuf_get_color_clip(c10, ibuf, x2, y1, extflag);
00711         clip |= ibuf_get_color_clip(c01, ibuf, x1, y2, extflag);
00712         clip |= ibuf_get_color_clip(c11, ibuf, x2, y2, extflag);
00713         col[0] = w00*c00[0] + w10*c10[0] + w01*c01[0] + w11*c11[0];
00714         col[1] = w00*c00[1] + w10*c10[1] + w01*c01[1] + w11*c11[1];
00715         col[2] = w00*c00[2] + w10*c10[2] + w01*c01[2] + w11*c11[2];
00716         col[3] = clip ? 0.f : w00*c00[3] + w10*c10[3] + w01*c01[3] + w11*c11[3];
00717         return clip;
00718     }
00719     return ibuf_get_color_clip(col, ibuf, (int)u, (int)v, extflag);
00720 }
00721 
00722 static void area_sample(TexResult* texr, ImBuf* ibuf, float fx, float fy, afdata_t* AFD)
00723 {
00724     int xs, ys, clip = 0;
00725     float tc[4], xsd, ysd, cw = 0.f;
00726     const float ux = ibuf->x*AFD->dxt[0], uy = ibuf->y*AFD->dxt[1];
00727     const float vx = ibuf->x*AFD->dyt[0], vy = ibuf->y*AFD->dyt[1];
00728     int xsam = (int)(0.5f*sqrtf(ux*ux + uy*uy) + 0.5f);
00729     int ysam = (int)(0.5f*sqrtf(vx*vx + vy*vy) + 0.5f);
00730     const int minsam = AFD->intpol ? 2 : 4;
00731     xsam = CLAMPIS(xsam, minsam, ibuf->x*2);
00732     ysam = CLAMPIS(ysam, minsam, ibuf->y*2);
00733     xsd = 1.f / xsam;
00734     ysd = 1.f / ysam;
00735     texr->tr = texr->tg = texr->tb = texr->ta = 0.f;
00736     for (ys=0; ys<ysam; ++ys) {
00737         for (xs=0; xs<xsam; ++xs) {
00738             const float su = (xs + ((ys & 1) + 0.5f)*0.5f)*xsd - 0.5f;
00739             const float sv = (ys + ((xs & 1) + 0.5f)*0.5f)*ysd - 0.5f;
00740             const float pu = fx + su*AFD->dxt[0] + sv*AFD->dyt[0];
00741             const float pv = fy + su*AFD->dxt[1] + sv*AFD->dyt[1];
00742             const int out = ibuf_get_color_clip_bilerp(tc, ibuf, pu*ibuf->x, pv*ibuf->y, AFD->intpol, AFD->extflag);
00743             clip |= out;
00744             cw += out ? 0.f : 1.f;
00745             texr->tr += tc[0];
00746             texr->tg += tc[1];
00747             texr->tb += tc[2];
00748             texr->ta += texr->talpha ? tc[3] : 0.f;
00749         }
00750     }
00751     xsd *= ysd;
00752     texr->tr *= xsd;
00753     texr->tg *= xsd;
00754     texr->tb *= xsd;
00755     // clipping can be ignored if alpha used, texr->ta already includes filtered edge
00756     texr->ta = texr->talpha ? texr->ta*xsd : (clip ? cw*xsd : 1.f);
00757 }
00758 
00759 // table of (exp(ar) - exp(a)) / (1 - exp(a)) for r in range [0, 1] and a = -2
00760 // used instead of actual gaussian, otherwise at high texture magnifications circular artifacts are visible
00761 #define EWA_MAXIDX 255
00762 static float EWA_WTS[EWA_MAXIDX + 1] =
00763 { 1.f, 0.990965f, 0.982f, 0.973105f, 0.96428f, 0.955524f, 0.946836f, 0.938216f, 0.929664f,
00764  0.921178f, 0.912759f, 0.904405f, 0.896117f, 0.887893f, 0.879734f, 0.871638f, 0.863605f,
00765  0.855636f, 0.847728f, 0.839883f, 0.832098f, 0.824375f, 0.816712f, 0.809108f, 0.801564f,
00766  0.794079f, 0.786653f, 0.779284f, 0.771974f, 0.76472f, 0.757523f, 0.750382f, 0.743297f,
00767  0.736267f, 0.729292f, 0.722372f, 0.715505f, 0.708693f, 0.701933f, 0.695227f, 0.688572f,
00768  0.68197f, 0.67542f, 0.66892f, 0.662471f, 0.656073f, 0.649725f, 0.643426f, 0.637176f,
00769  0.630976f, 0.624824f, 0.618719f, 0.612663f, 0.606654f, 0.600691f, 0.594776f, 0.588906f,
00770  0.583083f, 0.577305f, 0.571572f, 0.565883f, 0.56024f, 0.55464f, 0.549084f, 0.543572f,
00771  0.538102f, 0.532676f, 0.527291f, 0.521949f, 0.516649f, 0.511389f, 0.506171f, 0.500994f,
00772  0.495857f, 0.490761f, 0.485704f, 0.480687f, 0.475709f, 0.470769f, 0.465869f, 0.461006f,
00773  0.456182f, 0.451395f, 0.446646f, 0.441934f, 0.437258f, 0.432619f, 0.428017f, 0.42345f,
00774  0.418919f, 0.414424f, 0.409963f, 0.405538f, 0.401147f, 0.39679f, 0.392467f, 0.388178f,
00775  0.383923f, 0.379701f, 0.375511f, 0.371355f, 0.367231f, 0.363139f, 0.359079f, 0.355051f,
00776  0.351055f, 0.347089f, 0.343155f, 0.339251f, 0.335378f, 0.331535f, 0.327722f, 0.323939f,
00777  0.320186f, 0.316461f, 0.312766f, 0.3091f, 0.305462f, 0.301853f, 0.298272f, 0.294719f,
00778  0.291194f, 0.287696f, 0.284226f, 0.280782f, 0.277366f, 0.273976f, 0.270613f, 0.267276f,
00779  0.263965f, 0.26068f, 0.257421f, 0.254187f, 0.250979f, 0.247795f, 0.244636f, 0.241502f,
00780  0.238393f, 0.235308f, 0.232246f, 0.229209f, 0.226196f, 0.223206f, 0.220239f, 0.217296f,
00781  0.214375f, 0.211478f, 0.208603f, 0.20575f, 0.20292f, 0.200112f, 0.197326f, 0.194562f,
00782  0.191819f, 0.189097f, 0.186397f, 0.183718f, 0.18106f, 0.178423f, 0.175806f, 0.17321f,
00783  0.170634f, 0.168078f, 0.165542f, 0.163026f, 0.16053f, 0.158053f, 0.155595f, 0.153157f,
00784  0.150738f, 0.148337f, 0.145955f, 0.143592f, 0.141248f, 0.138921f, 0.136613f, 0.134323f,
00785  0.132051f, 0.129797f, 0.12756f, 0.125341f, 0.123139f, 0.120954f, 0.118786f, 0.116635f,
00786  0.114501f, 0.112384f, 0.110283f, 0.108199f, 0.106131f, 0.104079f, 0.102043f, 0.100023f,
00787  0.0980186f, 0.09603f, 0.094057f, 0.0920994f, 0.0901571f, 0.08823f, 0.0863179f, 0.0844208f,
00788  0.0825384f, 0.0806708f, 0.0788178f, 0.0769792f, 0.0751551f, 0.0733451f, 0.0715493f, 0.0697676f,
00789  0.0679997f, 0.0662457f, 0.0645054f, 0.0627786f, 0.0610654f, 0.0593655f, 0.0576789f, 0.0560055f,
00790  0.0543452f, 0.0526979f, 0.0510634f, 0.0494416f, 0.0478326f, 0.0462361f, 0.0446521f, 0.0430805f,
00791  0.0415211f, 0.039974f, 0.0384389f, 0.0369158f, 0.0354046f, 0.0339052f, 0.0324175f, 0.0309415f,
00792  0.029477f, 0.0280239f, 0.0265822f, 0.0251517f, 0.0237324f, 0.0223242f, 0.020927f, 0.0195408f,
00793  0.0181653f, 0.0168006f, 0.0154466f, 0.0141031f, 0.0127701f, 0.0114476f, 0.0101354f, 0.00883339f,
00794  0.00754159f, 0.00625989f, 0.00498819f, 0.00372644f, 0.00247454f, 0.00123242f, 0.f
00795 };
00796 
00797 // test if a float value is 'nan'
00798 // there is a C99 function for this: isnan(), but blender seems to use C90 (according to gcc warns),
00799 // and may not be supported by other compilers either
00800 #ifndef ISNAN
00801 #define ISNAN(x) ((x) != (x))
00802 #endif
00803 //static int ISNAN(float x) { return (x != x); }
00804 
00805 static void radangle2imp(float a2, float b2, float th, float* A, float* B, float* C, float* F)
00806 {
00807     float ct2 = cosf(th);
00808     const float st2 = 1.f - ct2*ct2;    // <- sin(th)^2
00809     ct2 *= ct2;
00810     *A = a2*st2 + b2*ct2;
00811     *B = (b2 - a2)*sinf(2.f*th);
00812     *C = a2*ct2 + b2*st2;
00813     *F = a2*b2;
00814 }
00815 
00816 // all tests here are done to make sure possible overflows are hopefully minimized
00817 static void imp2radangle(float A, float B, float C, float F, float* a, float* b, float* th, float* ecc)
00818 {
00819     if (F <= 1e-5f) {   // use arbitrary major radius, zero minor, infinite eccentricity
00820         *a = sqrtf(A > C ? A : C);
00821         *b = 0.f;
00822         *ecc = 1e10f;
00823         *th = 0.5f*(atan2f(B, A - C) + (float)M_PI);
00824     }
00825     else {
00826         const float AmC = A - C, ApC = A + C, F2 = F*2.f;
00827         const float r = sqrtf(AmC*AmC + B*B);
00828         float d = ApC - r;
00829         *a = (d <= 0.f) ? sqrtf(A > C ? A : C) : sqrtf(F2 / d);
00830         d = ApC + r;
00831         if (d <= 0.f) {
00832             *b = 0.f;
00833             *ecc = 1e10f;
00834         }
00835         else {
00836             *b = sqrtf(F2 / d);
00837             *ecc = *a / *b;
00838         }
00839         // incr theta by 0.5*pi (angle of major axis)
00840         *th = 0.5f*(atan2f(B, AmC) + (float)M_PI);
00841     }
00842 }
00843 
00844 static void ewa_eval(TexResult* texr, ImBuf* ibuf, float fx, float fy, afdata_t* AFD)
00845 {
00846     // scaling dxt/dyt by full resolution can cause overflow because of huge A/B/C and esp. F values,
00847     // scaling by aspect ratio alone does the opposite, so try something in between instead...
00848     const float ff2 = ibuf->x, ff = sqrtf(ff2), q = ibuf->y / ff;
00849     const float Ux = AFD->dxt[0]*ff, Vx = AFD->dxt[1]*q, Uy = AFD->dyt[0]*ff, Vy = AFD->dyt[1]*q;
00850     float A = Vx*Vx + Vy*Vy;
00851     float B = -2.f*(Ux*Vx + Uy*Vy);
00852     float C = Ux*Ux + Uy*Uy;
00853     float F = A*C - B*B*0.25f;
00854     float a, b, th, ecc, a2, b2, ue, ve, U0, V0, DDQ, U, ac1, ac2, BU, d; // TXF alpha: cw = 0.f;
00855     int u, v, u1, u2, v1, v2; // TXF alpha: clip = 0;
00856 
00857     // The so-called 'high' quality ewa method simply adds a constant of 1 to both A & C,
00858     // so the ellipse always covers at least some texels. But since the filter is now always larger,
00859     // it also means that everywhere else it's also more blurry then ideally should be the case.
00860     // So instead here the ellipse radii are modified instead whenever either is too low.
00861     // Use a different radius based on interpolation switch, just enough to anti-alias when interpolation is off,
00862     // and slightly larger to make result a bit smoother than bilinear interpolation when interpolation is on
00863     // (minimum values: const float rmin = intpol ? 1.f : 0.5f;)
00864     const float rmin = (AFD->intpol ? 1.5625f : 0.765625f)/ff2;
00865     imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
00866     if ((b2 = b*b) < rmin) {
00867         if ((a2 = a*a) < rmin) {
00868             B = 0.f;
00869             A = C = rmin;
00870             F = A*C;
00871         }
00872         else {
00873             b2 = rmin;
00874             radangle2imp(a2, b2, th, &A, &B, &C, &F);
00875         }
00876     }
00877 
00878     ue = ff*sqrtf(C);
00879     ve = ff*sqrtf(A);
00880     d = (float)(EWA_MAXIDX + 1) / (F*ff2);
00881     A *= d;
00882     B *= d;
00883     C *= d;
00884 
00885     U0 = fx*ibuf->x;
00886     V0 = fy*ibuf->y;
00887     u1 = (int)(floorf(U0 - ue));
00888     u2 = (int)(ceilf(U0 + ue));
00889     v1 = (int)(floorf(V0 - ve));
00890     v2 = (int)(ceilf(V0 + ve));
00891     U0 -= 0.5f;
00892     V0 -= 0.5f;
00893     DDQ = 2.f*A;
00894     U = u1 - U0;
00895     ac1 = A*(2.f*U + 1.f);
00896     ac2 = A*U*U;
00897     BU = B*U;
00898 
00899     d = texr->tr = texr->tb = texr->tg = texr->ta = 0.f;
00900     for (v=v1; v<=v2; ++v) {
00901         const float V = v - V0;
00902         float DQ = ac1 + B*V;
00903         float Q = (C*V + BU)*V + ac2;
00904         for (u=u1; u<=u2; ++u) {
00905             if (Q < (float)(EWA_MAXIDX + 1)) {
00906                 float tc[4];
00907                 const float wt = EWA_WTS[(Q < 0.f) ? 0 : (unsigned int)Q];
00908                 /*const int out =*/ ibuf_get_color_clip(tc, ibuf, u, v, AFD->extflag);
00909                 // TXF alpha: clip |= out;
00910                 // TXF alpha: cw += out ? 0.f : wt;
00911                 texr->tr += tc[0]*wt;
00912                 texr->tg += tc[1]*wt;
00913                 texr->tb += tc[2]*wt;
00914                 texr->ta += texr->talpha ? tc[3]*wt : 0.f;
00915                 d += wt;
00916             }
00917             Q += DQ;
00918             DQ += DDQ;
00919         }
00920     }
00921 
00922     // d should hopefully never be zero anymore
00923     d = 1.f/d;
00924     texr->tr *= d;
00925     texr->tg *= d;
00926     texr->tb *= d;
00927     // clipping can be ignored if alpha used, texr->ta already includes filtered edge
00928     texr->ta = texr->talpha ? texr->ta*d : 1.f; // TXF alpha (clip ? cw*d : 1.f);
00929 }
00930 
00931 static void feline_eval(TexResult* texr, ImBuf* ibuf, float fx, float fy, afdata_t* AFD)
00932 {
00933     const int maxn = AFD->iProbes - 1;
00934     const float ll = ((AFD->majrad == AFD->minrad) ? 2.f*AFD->majrad : 2.f*(AFD->majrad - AFD->minrad)) / (maxn ? (float)maxn : 1.f);
00935     float du = maxn ? cosf(AFD->theta)*ll : 0.f;
00936     float dv = maxn ? sinf(AFD->theta)*ll : 0.f;
00937     //const float D = -0.5f*(du*du + dv*dv) / (AFD->majrad*AFD->majrad);
00938     const float D = (EWA_MAXIDX + 1)*0.25f*(du*du + dv*dv) / (AFD->majrad*AFD->majrad);
00939     float d; // TXF alpha: cw = 0.f;
00940     int n; // TXF alpha: clip = 0;
00941     // have to use same scaling for du/dv here as for Ux/Vx/Uy/Vy (*after* D calc.)
00942     du *= AFD->dusc;
00943     dv *= AFD->dvsc;
00944     d = texr->tr = texr->tb = texr->tg = texr->ta = 0.f;
00945     for (n=-maxn; n<=maxn; n+=2) {
00946         float tc[4];
00947         const float hn = n*0.5f;
00948         const float u = fx + hn*du, v = fy + hn*dv;
00949         //const float wt = expf(n*n*D);
00950         // can use ewa table here too
00951         const float wt = EWA_WTS[(int)(n*n*D)];
00952         /*const int out =*/ ibuf_get_color_clip_bilerp(tc, ibuf, ibuf->x*u, ibuf->y*v, AFD->intpol, AFD->extflag);
00953         // TXF alpha: clip |= out;
00954         // TXF alpha: cw += out ? 0.f : wt;
00955         texr->tr += tc[0]*wt;
00956         texr->tg += tc[1]*wt;
00957         texr->tb += tc[2]*wt;
00958         texr->ta += texr->talpha ? tc[3]*wt : 0.f;
00959         d += wt;
00960     }
00961 
00962     d = 1.f/d;
00963     texr->tr *= d;
00964     texr->tg *= d;
00965     texr->tb *= d;
00966     // clipping can be ignored if alpha used, texr->ta already includes filtered edge
00967     texr->ta = texr->talpha ? texr->ta*d : 1.f; // TXF alpha: (clip ? cw*d : 1.f);
00968 }
00969 #undef EWA_MAXIDX
00970 
00971 static void alpha_clip_aniso(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, int extflag, TexResult *texres)
00972 {
00973     float alphaclip;
00974     rctf rf;
00975 
00976     // TXF apha: we're doing the same alphaclip here as boxsample, but i'm doubting
00977     // if this is actually correct for the all the filtering algorithms ..
00978 
00979     if(!(extflag == TXC_REPT || extflag == TXC_EXTD)) {
00980         rf.xmin= minx*(ibuf->x);
00981         rf.xmax= maxx*(ibuf->x);
00982         rf.ymin= miny*(ibuf->y);
00983         rf.ymax= maxy*(ibuf->y);
00984 
00985         alphaclip = clipx_rctf(&rf, 0.0, (float)(ibuf->x));
00986         alphaclip*= clipy_rctf(&rf, 0.0, (float)(ibuf->y));
00987         alphaclip= MAX2(alphaclip, 0.0f);
00988 
00989         if(alphaclip!=1.0f) {
00990             /* premul it all */
00991             texres->tr*= alphaclip;
00992             texres->tg*= alphaclip;
00993             texres->tb*= alphaclip;
00994             texres->ta*= alphaclip;
00995         }
00996     }
00997 }
00998 
00999 static void image_mipmap_test(Tex *tex, ImBuf *ibuf)
01000 {
01001     if (tex->imaflag & TEX_MIPMAP) {
01002         if ((ibuf->flags & IB_fields) == 0) {
01003             
01004             if (ibuf->mipmap[0] && (ibuf->userflags & IB_MIPMAP_INVALID)) {
01005                 BLI_lock_thread(LOCK_IMAGE);
01006                 if (ibuf->userflags & IB_MIPMAP_INVALID) {
01007                     IMB_remakemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
01008                     ibuf->userflags &= ~IB_MIPMAP_INVALID;
01009                 }               
01010                 BLI_unlock_thread(LOCK_IMAGE);
01011             }
01012             if (ibuf->mipmap[0] == NULL) {
01013                 BLI_lock_thread(LOCK_IMAGE);
01014                 if (ibuf->mipmap[0] == NULL) 
01015                     IMB_makemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
01016                 BLI_unlock_thread(LOCK_IMAGE);
01017             }
01018         }
01019     }
01020     
01021 }
01022 
01023 static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], float dxt[3], float dyt[3], TexResult *texres)
01024 {
01025     TexResult texr;
01026     float fx, fy, minx, maxx, miny, maxy;
01027     float maxd, val1, val2, val3;
01028     int curmap, retval, intpol, extflag = 0;
01029     afdata_t AFD;
01030 
01031     void (*filterfunc)(TexResult*, ImBuf*, float, float, afdata_t*);
01032     switch (tex->texfilter) {
01033         case TXF_EWA:
01034             filterfunc = ewa_eval;
01035             break;
01036         case TXF_FELINE:
01037             filterfunc = feline_eval;
01038             break;
01039         case TXF_AREA:
01040         default:
01041             filterfunc = area_sample;
01042     }
01043 
01044     texres->tin = texres->ta = texres->tr = texres->tg = texres->tb = 0.f;
01045 
01046     // we need to set retval OK, otherwise texture code generates normals itself...
01047     retval = texres->nor ? 3 : 1;
01048 
01049     // quick tests
01050     if (ibuf==NULL && ima==NULL) return retval;
01051 
01052     if (ima) {  // hack for icon render
01053         if ((ima->ibufs.first == NULL) && (R.r.scemode & R_NO_IMAGE_LOAD)) return retval;
01054         ibuf = BKE_image_get_ibuf(ima, &tex->iuser); 
01055     }
01056 
01057     if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) return retval;
01058 
01059     /* mipmap test */
01060     image_mipmap_test(tex, ibuf);
01061     
01062     if ((tex->imaflag & TEX_USEALPHA) && ((tex->imaflag & TEX_CALCALPHA) == 0)) texres->talpha = 1;
01063     texr.talpha = texres->talpha;
01064 
01065     if (tex->imaflag & TEX_IMAROT) {
01066         fy = texvec[0];
01067         fx = texvec[1];
01068     }
01069     else {
01070         fx = texvec[0];
01071         fy = texvec[1];
01072     }
01073 
01074     if (ibuf->flags & IB_fields) {
01075         if (R.r.mode & R_FIELDS) {          /* field render */
01076             if (R.flag & R_SEC_FIELD) {     /* correction for 2nd field */
01077                 /* fac1= 0.5/( (float)ibuf->y ); */
01078                 /* fy-= fac1; */
01079             }
01080             else    /* first field */
01081                 fy += 0.5f/( (float)ibuf->y );
01082         }
01083     }
01084 
01085     // pixel coordinates
01086     minx = MIN3(dxt[0], dyt[0], dxt[0] + dyt[0]);
01087     maxx = MAX3(dxt[0], dyt[0], dxt[0] + dyt[0]);
01088     miny = MIN3(dxt[1], dyt[1], dxt[1] + dyt[1]);
01089     maxy = MAX3(dxt[1], dyt[1], dxt[1] + dyt[1]);
01090 
01091     // tex_sharper has been removed
01092     minx = (maxx - minx)*0.5f;
01093     miny = (maxy - miny)*0.5f;
01094 
01095     if (tex->imaflag & TEX_FILTER_MIN) {
01096         // make sure the filtersize is minimal in pixels (normal, ref map can have miniature pixel dx/dy)
01097         const float addval = (0.5f * tex->filtersize) / (float)MIN2(ibuf->x, ibuf->y);
01098         if (addval > minx) minx = addval;
01099         if (addval > miny) miny = addval;
01100     }
01101     else if (tex->filtersize != 1.f) {
01102         minx *= tex->filtersize;
01103         miny *= tex->filtersize;
01104         dxt[0] *= tex->filtersize;
01105         dxt[1] *= tex->filtersize;
01106         dyt[0] *= tex->filtersize;
01107         dyt[1] *= tex->filtersize;
01108     }
01109 
01110     if (tex->imaflag & TEX_IMAROT) {
01111         float t;
01112         SWAP(float, minx, miny);
01113         // must rotate dxt/dyt 90 deg
01114         // yet another blender problem is that swapping X/Y axes (or any tex proj switches) should do something similar,
01115         // but it doesn't, it only swaps coords, so filter area will be incorrect in those cases.
01116         t = dxt[0];
01117         dxt[0] = dxt[1];
01118         dxt[1] = -t;
01119         t = dyt[0];
01120         dyt[0] = dyt[1];
01121         dyt[1] = -t;
01122     }
01123 
01124     // side faces of unit-cube
01125     minx = (minx > 0.25f) ? 0.25f : ((minx < 1e-5f) ? 1e-5f : minx);
01126     miny = (miny > 0.25f) ? 0.25f : ((miny < 1e-5f) ? 1e-5f : miny);
01127 
01128     // repeat and clip
01129 
01130     if (tex->extend == TEX_REPEAT) {
01131         if ((tex->flag & (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR)) == (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR))
01132             extflag = TXC_EXTD;
01133         else if (tex->flag & TEX_REPEAT_XMIR)
01134             extflag = TXC_XMIR;
01135         else if (tex->flag & TEX_REPEAT_YMIR)
01136             extflag = TXC_YMIR;
01137         else
01138             extflag = TXC_REPT;
01139     }
01140     else if (tex->extend == TEX_EXTEND)
01141         extflag = TXC_EXTD;
01142 
01143     if (tex->extend == TEX_CHECKER) {
01144         int xs = (int)floorf(fx), ys = (int)floorf(fy);
01145         // both checkers available, no boundary exceptions, checkerdist will eat aliasing
01146         if ((tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN)) {
01147             fx -= xs;
01148             fy -= ys;
01149         }
01150         else {
01151             int xs1 = (int)floorf(fx - minx);
01152             int ys1 = (int)floorf(fy - miny);
01153             int xs2 = (int)floorf(fx + minx);
01154             int ys2 = (int)floorf(fy + miny);
01155             if ((xs1 != xs2) || (ys1 != ys2)) {
01156                 if (tex->flag & TEX_CHECKER_ODD) {
01157                     fx -= ((xs1 + ys) & 1) ? xs2 : xs1;
01158                     fy -= ((ys1 + xs) & 1) ? ys2 : ys1;
01159                 }
01160                 if (tex->flag & TEX_CHECKER_EVEN) {
01161                     fx -= ((xs1 + ys) & 1) ? xs1 : xs2;
01162                     fy -= ((ys1 + xs) & 1) ? ys1 : ys2;
01163                 }
01164             }
01165             else {
01166                 if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) return retval;
01167                 if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) return retval;
01168                 fx -= xs;
01169                 fy -= ys;
01170             }
01171         }
01172         // scale around center, (0.5, 0.5)
01173         if (tex->checkerdist < 1.f) {
01174             const float omcd = 1.f / (1.f - tex->checkerdist);
01175             fx = (fx - 0.5f)*omcd + 0.5f;
01176             fy = (fy - 0.5f)*omcd + 0.5f;
01177             minx *= omcd;
01178             miny *= omcd;
01179         }
01180     }
01181 
01182     if (tex->extend == TEX_CLIPCUBE) {
01183         if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f || texvec[2] < -1.f || texvec[2] > 1.f) return retval;
01184     }
01185     else if (tex->extend == TEX_CLIP || tex->extend == TEX_CHECKER) {
01186         if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f) return retval;
01187     }
01188     else {
01189         if (tex->extend == TEX_EXTEND) {
01190             fx = (fx > 1.f) ? 1.f : ((fx < 0.f) ? 0.f : fx);
01191             fy = (fy > 1.f) ? 1.f : ((fy < 0.f) ? 0.f : fy);
01192         }
01193         else {
01194             fx -= floorf(fx);
01195             fy -= floorf(fy);
01196         }
01197     }
01198 
01199     intpol = tex->imaflag & TEX_INTERPOL;
01200 
01201     // warning no return!
01202     if ((R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields))
01203         ibuf->rect += ibuf->x*ibuf->y;
01204 
01205     // struct common data
01206     copy_v2_v2(AFD.dxt, dxt);
01207     copy_v2_v2(AFD.dyt, dyt);
01208     AFD.intpol = intpol;
01209     AFD.extflag = extflag;
01210 
01211     // brecht: added stupid clamping here, large dx/dy can give very large
01212     // filter sizes which take ages to render, it may be better to do this
01213     // more intelligently later in the code .. probably it's not noticeable
01214     if(AFD.dxt[0]*AFD.dxt[0] + AFD.dxt[1]*AFD.dxt[1] > 2.0f*2.0f)
01215         mul_v2_fl(AFD.dxt, 2.0f/len_v2(AFD.dxt));
01216     if(AFD.dyt[0]*AFD.dyt[0] + AFD.dyt[1]*AFD.dyt[1] > 2.0f*2.0f)
01217         mul_v2_fl(AFD.dyt, 2.0f/len_v2(AFD.dyt));
01218 
01219     // choice:
01220     if (tex->imaflag & TEX_MIPMAP) {
01221         ImBuf *previbuf, *curibuf;
01222         float levf;
01223         int maxlev;
01224         ImBuf* mipmaps[IB_MIPMAP_LEVELS + 1];
01225 
01226         // modify ellipse minor axis if too eccentric, use for area sampling as well
01227         // scaling dxt/dyt as done in pbrt is not the same
01228         // (as in ewa_eval(), scale by sqrt(ibuf->x) to maximize precision)
01229         const float ff = sqrtf(ibuf->x), q = ibuf->y/ff;
01230         const float Ux = dxt[0]*ff, Vx = dxt[1]*q, Uy = dyt[0]*ff, Vy = dyt[1]*q;
01231         const float A = Vx*Vx + Vy*Vy;
01232         const float B = -2.f*(Ux*Vx + Uy*Vy);
01233         const float C = Ux*Ux + Uy*Uy;
01234         const float F = A*C - B*B*0.25f;
01235         float a, b, th, ecc;
01236         imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
01237         if (tex->texfilter == TXF_FELINE) {
01238             float fProbes;
01239             a *= ff;
01240             b *= ff;
01241             a = MAX2(a, 1.f);
01242             b = MAX2(b, 1.f);
01243             fProbes = 2.f*(a / b) - 1.f;
01244             AFD.iProbes = (int)floorf(fProbes + 0.5f);
01245             AFD.iProbes = MIN2(AFD.iProbes, tex->afmax);
01246             if (AFD.iProbes < fProbes)
01247                 b = 2.f*a / (float)(AFD.iProbes + 1);
01248             AFD.majrad = a/ff;
01249             AFD.minrad = b/ff;
01250             AFD.theta = th;
01251             AFD.dusc = 1.f/ff;
01252             AFD.dvsc = ff / (float)ibuf->y;
01253         }
01254         else {  // EWA & area
01255             if (ecc > (float)tex->afmax) b = a / (float)tex->afmax;
01256             b *= ff;
01257         }
01258         maxd = MAX2(b, 1e-8f);
01259         levf = ((float)M_LOG2E)*logf(maxd);
01260 
01261         curmap = 0;
01262         maxlev = 1;
01263         mipmaps[0] = ibuf;
01264         while (curmap < IB_MIPMAP_LEVELS) {
01265             mipmaps[curmap + 1] = ibuf->mipmap[curmap];
01266             if (ibuf->mipmap[curmap]) maxlev++;
01267             curmap++;
01268         }
01269 
01270         // mipmap level
01271         if (levf < 0.f) {   // original image only
01272             previbuf = curibuf = mipmaps[0];
01273             levf = 0.f;
01274         }
01275         else if (levf >= maxlev - 1) {
01276             previbuf = curibuf = mipmaps[maxlev - 1];
01277             levf = 0.f;
01278             if (tex->texfilter == TXF_FELINE) AFD.iProbes = 1;
01279         }
01280         else {
01281             const int lev = ISNAN(levf) ? 0 : (int)levf;
01282             curibuf = mipmaps[lev];
01283             previbuf = mipmaps[lev + 1];
01284             levf -= floorf(levf);
01285         }
01286 
01287         // filter functions take care of interpolation themselves, no need to modify dxt/dyt here
01288 
01289         if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) {
01290             // color & normal
01291             filterfunc(texres, curibuf, fx, fy, &AFD);
01292             val1 = texres->tr + texres->tg + texres->tb;
01293             filterfunc(&texr, curibuf, fx + dxt[0], fy + dxt[1], &AFD);
01294             val2 = texr.tr + texr.tg + texr.tb;
01295             filterfunc(&texr, curibuf, fx + dyt[0], fy + dyt[1], &AFD);
01296             val3 = texr.tr + texr.tg + texr.tb;
01297             // don't switch x or y!
01298             texres->nor[0] = val1 - val2;
01299             texres->nor[1] = val1 - val3;
01300             if (previbuf != curibuf) {  // interpolate
01301                 filterfunc(&texr, previbuf, fx, fy, &AFD);
01302                 // rgb
01303                 texres->tr += levf*(texr.tr - texres->tr);
01304                 texres->tg += levf*(texr.tg - texres->tg);
01305                 texres->tb += levf*(texr.tb - texres->tb);
01306                 texres->ta += levf*(texr.ta - texres->ta);
01307                 // normal
01308                 val1 += levf*((texr.tr + texr.tg + texr.tb) - val1);
01309                 filterfunc(&texr, previbuf, fx + dxt[0], fy + dxt[1], &AFD);
01310                 val2 += levf*((texr.tr + texr.tg + texr.tb) - val2);
01311                 filterfunc(&texr, previbuf, fx + dyt[0], fy + dyt[1], &AFD);
01312                 val3 += levf*((texr.tr + texr.tg + texr.tb) - val3);
01313                 texres->nor[0] = val1 - val2;   // vals have been interpolated above!
01314                 texres->nor[1] = val1 - val3;
01315             }
01316         }
01317         else {  // color
01318             filterfunc(texres, curibuf, fx, fy, &AFD);
01319             if (previbuf != curibuf) {  // interpolate
01320                 filterfunc(&texr, previbuf, fx, fy, &AFD);
01321                 texres->tr += levf*(texr.tr - texres->tr);
01322                 texres->tg += levf*(texr.tg - texres->tg);
01323                 texres->tb += levf*(texr.tb - texres->tb);
01324                 texres->ta += levf*(texr.ta - texres->ta);
01325             }
01326 
01327             alpha_clip_aniso(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, extflag, texres);
01328         }
01329     }
01330     else {  // no mipmap
01331         // filter functions take care of interpolation themselves, no need to modify dxt/dyt here
01332         if (tex->texfilter == TXF_FELINE) {
01333             const float ff = sqrtf(ibuf->x), q = ibuf->y/ff;
01334             const float Ux = dxt[0]*ff, Vx = dxt[1]*q, Uy = dyt[0]*ff, Vy = dyt[1]*q;
01335             const float A = Vx*Vx + Vy*Vy;
01336             const float B = -2.f*(Ux*Vx + Uy*Vy);
01337             const float C = Ux*Ux + Uy*Uy;
01338             const float F = A*C - B*B*0.25f;
01339             float a, b, th, ecc, fProbes;
01340             imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
01341             a *= ff;
01342             b *= ff;
01343             a = MAX2(a, 1.f);
01344             b = MAX2(b, 1.f);
01345             fProbes = 2.f*(a / b) - 1.f;
01346             // no limit to number of Probes here
01347             AFD.iProbes = (int)floorf(fProbes + 0.5f);
01348             if (AFD.iProbes < fProbes) b = 2.f*a / (float)(AFD.iProbes + 1);
01349             AFD.majrad = a/ff;
01350             AFD.minrad = b/ff;
01351             AFD.theta = th;
01352             AFD.dusc = 1.f/ff;
01353             AFD.dvsc = ff / (float)ibuf->y;
01354         }
01355         if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) {
01356             // color & normal
01357             filterfunc(texres, ibuf, fx, fy, &AFD);
01358             val1 = texres->tr + texres->tg + texres->tb;
01359             filterfunc(&texr, ibuf, fx + dxt[0], fy + dxt[1], &AFD);
01360             val2 = texr.tr + texr.tg + texr.tb;
01361             filterfunc(&texr, ibuf, fx + dyt[0], fy + dyt[1], &AFD);
01362             val3 = texr.tr + texr.tg + texr.tb;
01363             // don't switch x or y!
01364             texres->nor[0] = val1 - val2;
01365             texres->nor[1] = val1 - val3;
01366         }
01367         else {
01368             filterfunc(texres, ibuf, fx, fy, &AFD);
01369             alpha_clip_aniso(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, extflag, texres);
01370         }
01371     }
01372 
01373     if (tex->imaflag & TEX_CALCALPHA)
01374         texres->ta = texres->tin = texres->ta * MAX3(texres->tr, texres->tg, texres->tb);
01375     else
01376         texres->tin = texres->ta;
01377     if (tex->flag & TEX_NEGALPHA) texres->ta = 1.f - texres->ta;
01378     
01379     if ((R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields))
01380         ibuf->rect -= ibuf->x*ibuf->y;
01381 
01382     if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) {    // normal from color
01383         // The invert of the red channel is to make
01384         // the normal map compliant with the outside world.
01385         // It needs to be done because in Blender
01386         // the normal used in the renderer points inward. It is generated
01387         // this way in calc_vertexnormals(). Should this ever change
01388         // this negate must be removed.
01389         texres->nor[0] = -2.f*(texres->tr - 0.5f);
01390         texres->nor[1] = 2.f*(texres->tg - 0.5f);
01391         texres->nor[2] = 2.f*(texres->tb - 0.5f);
01392     }
01393     
01394     // de-premul, this is being premulled in shade_input_do_shade()
01395     // TXF: this currently does not (yet?) work properly, destroys edge AA in clip/checker mode, so for now commented out
01396     // also disabled in imagewraposa() to be able to compare results with blender's default texture filtering
01397 
01398     // brecht: tried to fix this, see "TXF alpha" comments
01399 
01400     if (texres->ta != 1.f && (texres->ta > 1e-4f)) {
01401         fx = 1.f/texres->ta;
01402         texres->tr *= fx;
01403         texres->tg *= fx;
01404         texres->tb *= fx;
01405     }
01406 
01407     BRICONTRGB;
01408     
01409     return retval;
01410 }
01411 
01412 
01413 int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const float DXT[3], const float DYT[3], TexResult *texres)
01414 {
01415     TexResult texr;
01416     float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[3], dyt[3];
01417     float maxd, pixsize, val1, val2, val3;
01418     int curmap, retval, imaprepeat, imapextend;
01419 
01420     // TXF: since dxt/dyt might be modified here and since they might be needed after imagewraposa() call,
01421     // make a local copy here so that original vecs remain untouched
01422     copy_v3_v3(dxt, DXT);
01423     copy_v3_v3(dyt, DYT);
01424 
01425     // anisotropic filtering
01426     if (tex->texfilter != TXF_BOX)
01427         return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres);
01428 
01429     texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f;
01430     
01431     /* we need to set retval OK, otherwise texture code generates normals itself... */
01432     retval= texres->nor?3:1;
01433     
01434     /* quick tests */
01435     if(ibuf==NULL && ima==NULL)
01436         return retval;
01437     if(ima) {
01438 
01439         /* hack for icon render */
01440         if(ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD))
01441             return retval;
01442         
01443         ibuf= BKE_image_get_ibuf(ima, &tex->iuser); 
01444     }
01445     if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL))
01446         return retval;
01447     
01448     /* mipmap test */
01449     image_mipmap_test(tex, ibuf);
01450 
01451     if(tex->imaflag & TEX_USEALPHA) {
01452         if(tex->imaflag & TEX_CALCALPHA);
01453         else texres->talpha= 1;
01454     }
01455     
01456     texr.talpha= texres->talpha;
01457     
01458     if(tex->imaflag & TEX_IMAROT) {
01459         fy= texvec[0];
01460         fx= texvec[1];
01461     }
01462     else {
01463         fx= texvec[0];
01464         fy= texvec[1];
01465     }
01466     
01467     if(ibuf->flags & IB_fields) {
01468         if(R.r.mode & R_FIELDS) {           /* field render */
01469             if(R.flag & R_SEC_FIELD) {      /* correction for 2nd field */
01470                 /* fac1= 0.5/( (float)ibuf->y ); */
01471                 /* fy-= fac1; */
01472             }
01473             else {              /* first field */
01474                 fy+= 0.5f/( (float)ibuf->y );
01475             }
01476         }
01477     }
01478     
01479     /* pixel coordinates */
01480 
01481     minx= MIN3(dxt[0],dyt[0],dxt[0]+dyt[0] );
01482     maxx= MAX3(dxt[0],dyt[0],dxt[0]+dyt[0] );
01483     miny= MIN3(dxt[1],dyt[1],dxt[1]+dyt[1] );
01484     maxy= MAX3(dxt[1],dyt[1],dxt[1]+dyt[1] );
01485 
01486     /* tex_sharper has been removed */
01487     minx= (maxx-minx)/2.0f;
01488     miny= (maxy-miny)/2.0f;
01489     
01490     if(tex->imaflag & TEX_FILTER_MIN) {
01491         /* make sure the filtersize is minimal in pixels (normal, ref map can have miniature pixel dx/dy) */
01492         float addval= (0.5f * tex->filtersize) / (float) MIN2(ibuf->x, ibuf->y);
01493 
01494         if(addval > minx)
01495             minx= addval;
01496         if(addval > miny)
01497             miny= addval;
01498     }
01499     else if(tex->filtersize!=1.0f) {
01500         minx*= tex->filtersize;
01501         miny*= tex->filtersize;
01502         
01503         dxt[0]*= tex->filtersize;
01504         dxt[1]*= tex->filtersize;
01505         dyt[0]*= tex->filtersize;
01506         dyt[1]*= tex->filtersize;
01507     }
01508 
01509     if(tex->imaflag & TEX_IMAROT) SWAP(float, minx, miny);
01510     
01511     if(minx>0.25f) minx= 0.25f;
01512     else if(minx<0.00001f) minx= 0.00001f;  /* side faces of unit-cube */
01513     if(miny>0.25f) miny= 0.25f;
01514     else if(miny<0.00001f) miny= 0.00001f;
01515 
01516     
01517     /* repeat and clip */
01518     imaprepeat= (tex->extend==TEX_REPEAT);
01519     imapextend= (tex->extend==TEX_EXTEND);
01520 
01521     if(tex->extend == TEX_REPEAT) {
01522         if(tex->flag & (TEX_REPEAT_XMIR|TEX_REPEAT_YMIR)) {
01523             imaprepeat= 0;
01524             imapextend= 1;
01525         }
01526     }
01527 
01528     if(tex->extend == TEX_CHECKER) {
01529         int xs, ys, xs1, ys1, xs2, ys2, boundary;
01530         
01531         xs= (int)floor(fx);
01532         ys= (int)floor(fy);
01533         
01534         // both checkers available, no boundary exceptions, checkerdist will eat aliasing
01535         if( (tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN) ) {
01536             fx-= xs;
01537             fy-= ys;
01538         }
01539         else {
01540             
01541             xs1= (int)floor(fx-minx);
01542             ys1= (int)floor(fy-miny);
01543             xs2= (int)floor(fx+minx);
01544             ys2= (int)floor(fy+miny);
01545             boundary= (xs1!=xs2) || (ys1!=ys2);
01546 
01547             if(boundary==0) {
01548                 if( (tex->flag & TEX_CHECKER_ODD)==0) {
01549                     if((xs+ys) & 1); 
01550                     else return retval;
01551                 }
01552                 if( (tex->flag & TEX_CHECKER_EVEN)==0) {
01553                     if((xs+ys) & 1) return retval;
01554                 }
01555                 fx-= xs;
01556                 fy-= ys;
01557             }
01558             else {
01559                 if(tex->flag & TEX_CHECKER_ODD) {
01560                     if((xs1+ys) & 1) fx-= xs2;
01561                     else fx-= xs1;
01562                     
01563                     if((ys1+xs) & 1) fy-= ys2;
01564                     else fy-= ys1;
01565                 }
01566                 if(tex->flag & TEX_CHECKER_EVEN) {
01567                     if((xs1+ys) & 1) fx-= xs1;
01568                     else fx-= xs2;
01569                     
01570                     if((ys1+xs) & 1) fy-= ys1;
01571                     else fy-= ys2;
01572                 }
01573             }
01574         }
01575 
01576         /* scale around center, (0.5, 0.5) */
01577         if(tex->checkerdist<1.0f) {
01578             fx= (fx-0.5f)/(1.0f-tex->checkerdist) +0.5f;
01579             fy= (fy-0.5f)/(1.0f-tex->checkerdist) +0.5f;
01580             minx/= (1.0f-tex->checkerdist);
01581             miny/= (1.0f-tex->checkerdist);
01582         }
01583     }
01584 
01585     if(tex->extend == TEX_CLIPCUBE) {
01586         if(fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f || texvec[2]<-1.0f || texvec[2]>1.0f) {
01587             return retval;
01588         }
01589     }
01590     else if(tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
01591         if(fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f) {
01592             return retval;
01593         }
01594     }
01595     else {
01596         if(imapextend) {
01597             if(fx>1.0f) fx = 1.0f;
01598             else if(fx<0.0f) fx= 0.0f;
01599         }
01600         else {
01601             if(fx>1.0f) fx -= (int)(fx);
01602             else if(fx<0.0f) fx+= 1-(int)(fx);
01603         }
01604         
01605         if(imapextend) {
01606             if(fy>1.0f) fy = 1.0f;
01607             else if(fy<0.0f) fy= 0.0f;
01608         }
01609         else {
01610             if(fy>1.0f) fy -= (int)(fy);
01611             else if(fy<0.0f) fy+= 1-(int)(fy);
01612         }
01613     }
01614 
01615     /* warning no return! */
01616     if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
01617         ibuf->rect+= (ibuf->x*ibuf->y);
01618     }
01619 
01620     /* choice:  */
01621     if(tex->imaflag & TEX_MIPMAP) {
01622         ImBuf *previbuf, *curibuf;
01623         float bumpscale;
01624         
01625         dx= minx;
01626         dy= miny;
01627         maxd= MAX2(dx, dy);
01628         if(maxd>0.5f) maxd= 0.5f;
01629 
01630         pixsize = 1.0f/ (float) MIN2(ibuf->x, ibuf->y);
01631         
01632         bumpscale= pixsize/maxd;
01633         if(bumpscale>1.0f) bumpscale= 1.0f;
01634         else bumpscale*=bumpscale;
01635         
01636         curmap= 0;
01637         previbuf= curibuf= ibuf;
01638         while(curmap<IB_MIPMAP_LEVELS && ibuf->mipmap[curmap]) {
01639             if(maxd < pixsize) break;
01640             previbuf= curibuf;
01641             curibuf= ibuf->mipmap[curmap];
01642             pixsize= 1.0f / (float)MIN2(curibuf->x, curibuf->y);
01643             curmap++;
01644         }
01645 
01646         if(previbuf!=curibuf || (tex->imaflag & TEX_INTERPOL)) {
01647             /* sample at least 1 pixel */
01648             if (minx < 0.5f / ibuf->x) minx = 0.5f / ibuf->x;
01649             if (miny < 0.5f / ibuf->y) miny = 0.5f / ibuf->y;
01650         }
01651         
01652         if(texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) {
01653             /* a bit extra filter */
01654             //minx*= 1.35f;
01655             //miny*= 1.35f;
01656             
01657             boxsample(curibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend);
01658             val1= texres->tr+texres->tg+texres->tb;
01659             boxsample(curibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend);
01660             val2= texr.tr + texr.tg + texr.tb;
01661             boxsample(curibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend);
01662             val3= texr.tr + texr.tg + texr.tb;
01663 
01664             /* don't switch x or y! */
01665             texres->nor[0]= (val1-val2);
01666             texres->nor[1]= (val1-val3);
01667             
01668             if(previbuf!=curibuf) {  /* interpolate */
01669                 
01670                 boxsample(previbuf, fx-minx, fy-miny, fx+minx, fy+miny, &texr, imaprepeat, imapextend);
01671                 
01672                 /* calc rgb */
01673                 dx= 2.0f*(pixsize-maxd)/pixsize;
01674                 if(dx>=1.0f) {
01675                     texres->ta= texr.ta; texres->tb= texr.tb;
01676                     texres->tg= texr.tg; texres->tr= texr.tr;
01677                 }
01678                 else {
01679                     dy= 1.0f-dx;
01680                     texres->tb= dy*texres->tb+ dx*texr.tb;
01681                     texres->tg= dy*texres->tg+ dx*texr.tg;
01682                     texres->tr= dy*texres->tr+ dx*texr.tr;
01683                     texres->ta= dy*texres->ta+ dx*texr.ta;
01684                 }
01685                 
01686                 val1= dy*val1+ dx*(texr.tr + texr.tg + texr.tb);
01687                 boxsample(previbuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend);
01688                 val2= dy*val2+ dx*(texr.tr + texr.tg + texr.tb);
01689                 boxsample(previbuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend);
01690                 val3= dy*val3+ dx*(texr.tr + texr.tg + texr.tb);
01691                 
01692                 texres->nor[0]= (val1-val2);    /* vals have been interpolated above! */
01693                 texres->nor[1]= (val1-val3);
01694                 
01695                 if(dx<1.0f) {
01696                     dy= 1.0f-dx;
01697                     texres->tb= dy*texres->tb+ dx*texr.tb;
01698                     texres->tg= dy*texres->tg+ dx*texr.tg;
01699                     texres->tr= dy*texres->tr+ dx*texr.tr;
01700                     texres->ta= dy*texres->ta+ dx*texr.ta;
01701                 }
01702             }
01703             texres->nor[0]*= bumpscale;
01704             texres->nor[1]*= bumpscale;
01705         }
01706         else {
01707             maxx= fx+minx;
01708             minx= fx-minx;
01709             maxy= fy+miny;
01710             miny= fy-miny;
01711 
01712             boxsample(curibuf, minx, miny, maxx, maxy, texres, imaprepeat, imapextend);
01713 
01714             if(previbuf!=curibuf) {  /* interpolate */
01715                 boxsample(previbuf, minx, miny, maxx, maxy, &texr, imaprepeat, imapextend);
01716                 
01717                 fx= 2.0f*(pixsize-maxd)/pixsize;
01718                 
01719                 if(fx>=1.0f) {
01720                     texres->ta= texr.ta; texres->tb= texr.tb;
01721                     texres->tg= texr.tg; texres->tr= texr.tr;
01722                 } else {
01723                     fy= 1.0f-fx;
01724                     texres->tb= fy*texres->tb+ fx*texr.tb;
01725                     texres->tg= fy*texres->tg+ fx*texr.tg;
01726                     texres->tr= fy*texres->tr+ fx*texr.tr;
01727                     texres->ta= fy*texres->ta+ fx*texr.ta;
01728                 }
01729             }
01730         }
01731     }
01732     else {
01733         const int intpol = tex->imaflag & TEX_INTERPOL;
01734         if (intpol) {
01735             /* sample 1 pixel minimum */
01736             if (minx < 0.5f / ibuf->x) minx = 0.5f / ibuf->x;
01737             if (miny < 0.5f / ibuf->y) miny = 0.5f / ibuf->y;
01738         }
01739 
01740         if(texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) {
01741             boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend);
01742             val1= texres->tr+texres->tg+texres->tb;
01743             boxsample(ibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend);
01744             val2= texr.tr + texr.tg + texr.tb;
01745             boxsample(ibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend);
01746             val3= texr.tr + texr.tg + texr.tb;
01747 
01748             /* don't switch x or y! */
01749             texres->nor[0]= (val1-val2);
01750             texres->nor[1]= (val1-val3);
01751         }
01752         else
01753             boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend);
01754     }
01755     
01756     if(tex->imaflag & TEX_CALCALPHA) {
01757         texres->ta= texres->tin= texres->ta*MAX3(texres->tr, texres->tg, texres->tb);
01758     }
01759     else texres->tin= texres->ta;
01760 
01761     if(tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta;
01762     
01763     if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
01764         ibuf->rect-= (ibuf->x*ibuf->y);
01765     }
01766 
01767     if(texres->nor && (tex->imaflag & TEX_NORMALMAP)) {
01768         // qdn: normal from color
01769         // The invert of the red channel is to make
01770         // the normal map compliant with the outside world.
01771         // It needs to be done because in Blender
01772         // the normal used in the renderer points inward. It is generated
01773         // this way in calc_vertexnormals(). Should this ever change
01774         // this negate must be removed.
01775         texres->nor[0] = -2.f*(texres->tr - 0.5f);
01776         texres->nor[1] = 2.f*(texres->tg - 0.5f);
01777         texres->nor[2] = 2.f*(texres->tb - 0.5f);
01778     }
01779     
01780     /* de-premul, this is being premulled in shade_input_do_shade() */
01781     if(texres->ta!=1.0f && texres->ta>1e-4f) {
01782         fx= 1.0f/texres->ta;
01783         texres->tr*= fx;
01784         texres->tg*= fx;
01785         texres->tb*= fx;
01786     }
01787 
01788     BRICONTRGB;
01789     
01790     return retval;
01791 }
01792 
01793 void image_sample(Image *ima, float fx, float fy, float dx, float dy, float *result)
01794 {
01795     TexResult texres;
01796     ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
01797     
01798     if(ibuf==NULL) {
01799         result[0]= result[1]= result[2]= result[3]= 0.0f;
01800         return;
01801     }
01802     
01803     if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) )
01804         ibuf->rect+= (ibuf->x*ibuf->y);
01805 
01806     texres.talpha= 1; /* boxsample expects to be initialized */
01807     boxsample(ibuf, fx, fy, fx+dx, fy+dy, &texres, 0, 1);
01808     result[0]= texres.tr;
01809     result[1]= texres.tg;
01810     result[2]= texres.tb;
01811     result[3]= texres.ta;
01812     
01813     if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) )
01814         ibuf->rect-= (ibuf->x*ibuf->y);
01815 }
01816 
01817 void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float *result)
01818 {
01819     TexResult texres;
01820     afdata_t AFD;
01821     
01822     if(ibuf==NULL) {
01823         return;
01824     }
01825     
01826     AFD.dxt[0] = dx; AFD.dxt[1] = dx;
01827     AFD.dyt[0] = dy; AFD.dyt[1] = dy;
01828     //copy_v2_v2(AFD.dxt, dx);
01829     //copy_v2_v2(AFD.dyt, dy);
01830     
01831     AFD.intpol = 1;
01832     AFD.extflag = TXC_EXTD;
01833     
01834     memset(&texres, 0, sizeof(texres));
01835     ewa_eval(&texres, ibuf, fx, fy, &AFD);
01836     
01837     
01838     result[0]= texres.tr;
01839     result[1]= texres.tg;
01840     result[2]= texres.tb;
01841     result[3]= texres.ta;
01842 }