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