8abde533028b04cb66e46993da60272222c1a3ac
[blender-staging.git] / source / blender / render / intern / source / imagetexture.c
1 /**
2  *
3  * $Id:
4  *
5  * ***** BEGIN GPL LICENSE BLOCK *****
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version. 
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
22  * All rights reserved.
23  *
24  * Contributors: 2004/2005/2006 Blender Foundation, full recode
25  *
26  * ***** END GPL/BL DUAL LICENSE BLOCK *****
27  */
28
29
30
31 #include <stdio.h>
32 #include <string.h>
33 #include <fcntl.h>
34 #include <math.h>
35 #include <float.h>
36 #ifndef WIN32 
37 #include <unistd.h>
38 #else
39 #include <io.h>
40 #endif
41
42 #include "MEM_guardedalloc.h"
43
44 #include "IMB_imbuf_types.h"
45 #include "IMB_imbuf.h"
46
47 #include "DNA_image_types.h"
48 #include "DNA_scene_types.h"
49 #include "DNA_texture_types.h"
50
51 #include "BLI_math.h"
52 #include "BLI_blenlib.h"
53 #include "BLI_threads.h"
54
55 #include "BKE_utildefines.h"
56 #include "BKE_global.h"
57 #include "BKE_main.h"
58 #include "BKE_image.h"
59 #include "BKE_texture.h"
60 #include "BKE_library.h"
61
62 #include "renderpipeline.h"
63 #include "render_types.h"
64 #include "texture.h"
65
66 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
67 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
68 /* only to be used here in this file, it's for speed */
69 extern struct Render R;
70 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
71
72 /* *********** IMAGEWRAPPING ****************** */
73
74
75 /* x and y have to be checked for image size */
76 static void ibuf_get_color(float *col, struct ImBuf *ibuf, int x, int y)
77 {
78         int ofs = y * ibuf->x + x;
79         
80         if(ibuf->rect_float) {
81                 if(ibuf->channels==4) {
82                         float *fp= ibuf->rect_float + 4*ofs;
83                         QUATCOPY(col, fp);
84                 }
85                 else if(ibuf->channels==3) {
86                         float *fp= ibuf->rect_float + 3*ofs;
87                         VECCOPY(col, fp);
88                         col[3]= 1.0f;
89                 }
90                 else {
91                         float *fp= ibuf->rect_float + ofs;
92                         col[0]= col[1]= col[2]= col[3]= *fp;
93                 }
94         }
95         else {
96                 char *rect = (char *)( ibuf->rect+ ofs);
97
98                 col[0] = ((float)rect[0])*(1.0f/255.0f);
99                 col[1] = ((float)rect[1])*(1.0f/255.0f);
100                 col[2] = ((float)rect[2])*(1.0f/255.0f);
101                 col[3] = ((float)rect[3])*(1.0f/255.0f);
102         }       
103 }
104
105 int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, float *texvec, TexResult *texres)
106 {
107         float fx, fy, val1, val2, val3;
108         int x, y, retval;
109
110         texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f;
111         
112         /* we need to set retval OK, otherwise texture code generates normals itself... */
113         retval= texres->nor?3:1;
114         
115         /* quick tests */
116         if(ibuf==NULL && ima==NULL)
117                 return retval;
118         if(ima) {
119                 
120                 /* hack for icon render */
121                 if(ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD))
122                         return retval;
123                 
124                 ibuf= BKE_image_get_ibuf(ima, &tex->iuser);
125         }
126         if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL))
127                 return retval;
128         
129         /* setup mapping */
130         if(tex->imaflag & TEX_IMAROT) {
131                 fy= texvec[0];
132                 fx= texvec[1];
133         }
134         else {
135                 fx= texvec[0];
136                 fy= texvec[1];
137         }
138         
139         if(tex->extend == TEX_CHECKER) {
140                 int xs, ys;
141                 
142                 xs= (int)floor(fx);
143                 ys= (int)floor(fy);
144                 fx-= xs;
145                 fy-= ys;
146
147                 if( (tex->flag & TEX_CHECKER_ODD)==0) {
148                         if((xs+ys) & 1);else return retval;
149                 }
150                 if( (tex->flag & TEX_CHECKER_EVEN)==0) {
151                         if((xs+ys) & 1) return retval; 
152                 }
153                 /* scale around center, (0.5, 0.5) */
154                 if(tex->checkerdist<1.0) {
155                         fx= (fx-0.5)/(1.0-tex->checkerdist) +0.5;
156                         fy= (fy-0.5)/(1.0-tex->checkerdist) +0.5;
157                 }
158         }
159
160         x = (int)(fx*ibuf->x);
161         y = (int)(fy*ibuf->y);
162
163         if(tex->extend == TEX_CLIPCUBE) {
164                 if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0 || texvec[2]>1.0) {
165                         return retval;
166                 }
167         }
168         else if( tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
169                 if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) {
170                         return retval;
171                 }
172         }
173         else {
174                 if(tex->extend==TEX_EXTEND) {
175                         if(x>=ibuf->x) x = ibuf->x-1;
176                         else if(x<0) x= 0;
177                 }
178                 else {
179                         x= x % ibuf->x;
180                         if(x<0) x+= ibuf->x;
181                 }
182                 if(tex->extend==TEX_EXTEND) {
183                         if(y>=ibuf->y) y = ibuf->y-1;
184                         else if(y<0) y= 0;
185                 }
186                 else {
187                         y= y % ibuf->y;
188                         if(y<0) y+= ibuf->y;
189                 }
190         }
191         
192         /* warning, no return before setting back! */
193         if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
194                 ibuf->rect+= (ibuf->x*ibuf->y);
195         }
196
197         ibuf_get_color(&texres->tr, ibuf, x, y);
198         
199         if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
200                 ibuf->rect-= (ibuf->x*ibuf->y);
201         }
202
203         if(tex->imaflag & TEX_USEALPHA) {
204                 if(tex->imaflag & TEX_CALCALPHA);
205                 else texres->talpha= 1;
206         }
207         
208         if(texres->nor) {
209                 if(tex->imaflag & TEX_NORMALMAP) {
210                         // qdn: normal from color
211                         texres->nor[0] = 2.f*(texres->tr - 0.5f);
212                         texres->nor[1] = 2.f*(0.5f - texres->tg);
213                         texres->nor[2] = 2.f*(texres->tb - 0.5f);
214                 }
215                 else {
216                         /* bump: take three samples */
217                         val1= texres->tr+texres->tg+texres->tb;
218
219                         if(x<ibuf->x-1) {
220                                 float col[4];
221                                 ibuf_get_color(col, ibuf, x+1, y);
222                                 val2= (col[0]+col[1]+col[2]);
223                         }
224                         else val2= val1;
225
226                         if(y<ibuf->y-1) {
227                                 float col[4];
228                                 ibuf_get_color(col, ibuf, x, y+1);
229                                 val3= (col[0]+col[1]+col[2]);
230                         }
231                         else val3= val1;
232
233                         /* do not mix up x and y here! */
234                         texres->nor[0]= (val1-val2);
235                         texres->nor[1]= (val1-val3);
236                 }
237         }
238
239         BRICONTRGB;
240
241         if(texres->talpha) texres->tin= texres->ta;
242         else if(tex->imaflag & TEX_CALCALPHA) {
243                 texres->ta= texres->tin= MAX3(texres->tr, texres->tg, texres->tb);
244         }
245         else texres->ta= texres->tin= 1.0;
246         
247         if(tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta;
248
249         /* de-premul, this is being premulled in shade_input_do_shade() */
250         if(texres->ta!=1.0f && texres->ta>FLT_EPSILON) {
251                 fx= 1.0f/texres->ta;
252                 texres->tr*= fx;
253                 texres->tg*= fx;
254                 texres->tb*= fx;
255         }
256         
257         return retval;
258 }
259
260 static void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2)
261 {
262         rctf *rf, *newrct;
263         short a;
264
265         a= *count;
266         rf= stack;
267         for(;a>0;a--) {
268                 if(rf->xmin<x1) {
269                         if(rf->xmax<x1) {
270                                 rf->xmin+= (x2-x1);
271                                 rf->xmax+= (x2-x1);
272                         }
273                         else {
274                                 if(rf->xmax>x2) rf->xmax= x2;
275                                 newrct= stack+ *count;
276                                 (*count)++;
277
278                                 newrct->xmax= x2;
279                                 newrct->xmin= rf->xmin+(x2-x1);
280                                 newrct->ymin= rf->ymin;
281                                 newrct->ymax= rf->ymax;
282                                 
283                                 if(newrct->xmin==newrct->xmax) (*count)--;
284                                 
285                                 rf->xmin= x1;
286                         }
287                 }
288                 else if(rf->xmax>x2) {
289                         if(rf->xmin>x2) {
290                                 rf->xmin-= (x2-x1);
291                                 rf->xmax-= (x2-x1);
292                         }
293                         else {
294                                 if(rf->xmin<x1) rf->xmin= x1;
295                                 newrct= stack+ *count;
296                                 (*count)++;
297
298                                 newrct->xmin= x1;
299                                 newrct->xmax= rf->xmax-(x2-x1);
300                                 newrct->ymin= rf->ymin;
301                                 newrct->ymax= rf->ymax;
302
303                                 if(newrct->xmin==newrct->xmax) (*count)--;
304
305                                 rf->xmax= x2;
306                         }
307                 }
308                 rf++;
309         }
310
311 }
312
313 static void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2)
314 {
315         rctf *rf, *newrct;
316         short a;
317
318         a= *count;
319         rf= stack;
320         for(;a>0;a--) {
321                 if(rf->ymin<y1) {
322                         if(rf->ymax<y1) {
323                                 rf->ymin+= (y2-y1);
324                                 rf->ymax+= (y2-y1);
325                         }
326                         else {
327                                 if(rf->ymax>y2) rf->ymax= y2;
328                                 newrct= stack+ *count;
329                                 (*count)++;
330
331                                 newrct->ymax= y2;
332                                 newrct->ymin= rf->ymin+(y2-y1);
333                                 newrct->xmin= rf->xmin;
334                                 newrct->xmax= rf->xmax;
335
336                                 if(newrct->ymin==newrct->ymax) (*count)--;
337
338                                 rf->ymin= y1;
339                         }
340                 }
341                 else if(rf->ymax>y2) {
342                         if(rf->ymin>y2) {
343                                 rf->ymin-= (y2-y1);
344                                 rf->ymax-= (y2-y1);
345                         }
346                         else {
347                                 if(rf->ymin<y1) rf->ymin= y1;
348                                 newrct= stack+ *count;
349                                 (*count)++;
350
351                                 newrct->ymin= y1;
352                                 newrct->ymax= rf->ymax-(y2-y1);
353                                 newrct->xmin= rf->xmin;
354                                 newrct->xmax= rf->xmax;
355
356                                 if(newrct->ymin==newrct->ymax) (*count)--;
357
358                                 rf->ymax= y2;
359                         }
360                 }
361                 rf++;
362         }
363 }
364
365 static float square_rctf(rctf *rf)
366 {
367         float x, y;
368
369         x= rf->xmax- rf->xmin;
370         y= rf->ymax- rf->ymin;
371         return (x*y);
372 }
373
374 static float clipx_rctf(rctf *rf, float x1, float x2)
375 {
376         float size;
377
378         size= rf->xmax - rf->xmin;
379
380         if(rf->xmin<x1) {
381                 rf->xmin= x1;
382         }
383         if(rf->xmax>x2) {
384                 rf->xmax= x2;
385         }
386         if(rf->xmin > rf->xmax) {
387                 rf->xmin = rf->xmax;
388                 return 0.0;
389         }
390         else if(size!=0.0) {
391                 return (rf->xmax - rf->xmin)/size;
392         }
393         return 1.0;
394 }
395
396 static float clipy_rctf(rctf *rf, float y1, float y2)
397 {
398         float size;
399
400         size= rf->ymax - rf->ymin;
401
402         if(rf->ymin<y1) {
403                 rf->ymin= y1;
404         }
405         if(rf->ymax>y2) {
406                 rf->ymax= y2;
407         }
408
409         if(rf->ymin > rf->ymax) {
410                 rf->ymin = rf->ymax;
411                 return 0.0;
412         }
413         else if(size!=0.0) {
414                 return (rf->ymax - rf->ymin)/size;
415         }
416         return 1.0;
417
418 }
419
420 static void boxsampleclip(struct ImBuf *ibuf, rctf *rf, TexResult *texres)
421 {
422         /* sample box, is clipped already, and minx etc. have been set at ibuf size.
423        Enlarge with antialiased edges of the pixels */
424
425         float muly, mulx, div, col[4];
426         int x, y, startx, endx, starty, endy;
427
428         startx= (int)floor(rf->xmin);
429         endx= (int)floor(rf->xmax);
430         starty= (int)floor(rf->ymin);
431         endy= (int)floor(rf->ymax);
432
433         if(startx < 0) startx= 0;
434         if(starty < 0) starty= 0;
435         if(endx>=ibuf->x) endx= ibuf->x-1;
436         if(endy>=ibuf->y) endy= ibuf->y-1;
437
438         if(starty==endy && startx==endx) {
439                 ibuf_get_color(&texres->tr, ibuf, startx, starty);
440         }
441         else {
442                 div= texres->tr= texres->tg= texres->tb= texres->ta= 0.0;
443                 for(y=starty; y<=endy; y++) {
444                         
445                         muly= 1.0;
446
447                         if(starty==endy);
448                         else {
449                                 if(y==starty) muly= 1.0f-(rf->ymin - y);
450                                 if(y==endy) muly= (rf->ymax - y);
451                         }
452                         
453                         if(startx==endx) {
454                                 mulx= muly;
455                                 
456                                 ibuf_get_color(col, ibuf, startx, y);
457
458                                 texres->ta+= mulx*col[3];
459                                 texres->tr+= mulx*col[0];
460                                 texres->tg+= mulx*col[1];
461                                 texres->tb+= mulx*col[2];
462                                 div+= mulx;
463                         }
464                         else {
465                                 for(x=startx; x<=endx; x++) {
466                                         mulx= muly;
467                                         if(x==startx) mulx*= 1.0f-(rf->xmin - x);
468                                         if(x==endx) mulx*= (rf->xmax - x);
469
470                                         ibuf_get_color(col, ibuf, x, y);
471                                         
472                                         if(mulx==1.0) {
473                                                 texres->ta+= col[3];
474                                                 texres->tr+= col[0];
475                                                 texres->tg+= col[1];
476                                                 texres->tb+= col[2];
477                                                 div+= 1.0;
478                                         }
479                                         else {
480                                                 texres->ta+= mulx*col[3];
481                                                 texres->tr+= mulx*col[0];
482                                                 texres->tg+= mulx*col[1];
483                                                 texres->tb+= mulx*col[2];
484                                                 div+= mulx;
485                                         }
486                                 }
487                         }
488                 }
489
490                 if(div!=0.0) {
491                         div= 1.0f/div;
492                         texres->tb*= div;
493                         texres->tg*= div;
494                         texres->tr*= div;
495                         texres->ta*= div;
496                 }
497                 else {
498                         texres->tr= texres->tg= texres->tb= texres->ta= 0.0f;
499                 }
500         }
501 }
502
503 static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, TexResult *texres, int imaprepeat, int imapextend, int intpol)
504 {
505         /* Sample box, performs clip. minx etc are in range 0.0 - 1.0 .
506    * Enlarge with antialiased edges of pixels.
507    * If variable 'imaprepeat' has been set, the
508    * clipped-away parts are sampled as well.
509    */
510         /* note: actually minx etc isnt in the proper range... this due to filter size and offset vectors for bump */
511         TexResult texr;
512         rctf *rf, stack[8];
513         float opp, tot, alphaclip= 1.0;
514         short count=1;
515
516         rf= stack;
517         rf->xmin= minx*(ibuf->x);
518         rf->xmax= maxx*(ibuf->x);
519         rf->ymin= miny*(ibuf->y);
520         rf->ymax= maxy*(ibuf->y);
521
522         texr.talpha= texres->talpha;    /* is read by boxsample_clip */
523         
524         if(imapextend) {
525                 CLAMP(rf->xmin, 0.0f, ibuf->x-1);
526                 CLAMP(rf->xmax, 0.0f, ibuf->x-1);
527         }
528         else if(imaprepeat) 
529                 clipx_rctf_swap(stack, &count, 0.0, (float)(ibuf->x));
530         else {
531                 alphaclip= clipx_rctf(rf, 0.0, (float)(ibuf->x));
532
533                 if(alphaclip<=0.0) {
534                         texres->tr= texres->tb= texres->tg= texres->ta= 0.0;
535                         return;
536                 }
537         }
538
539         if(imapextend) {
540                 CLAMP(rf->ymin, 0.0f, ibuf->y-1);
541                 CLAMP(rf->ymax, 0.0f, ibuf->y-1);
542         }
543         else if(imaprepeat) 
544                 clipy_rctf_swap(stack, &count, 0.0, (float)(ibuf->y));
545         else {
546                 alphaclip*= clipy_rctf(rf, 0.0, (float)(ibuf->y));
547
548                 if(alphaclip<=0.0) {
549                         texres->tr= texres->tb= texres->tg= texres->ta= 0.0;
550                         return;
551                 }
552         }
553
554         if(count>1) {
555                 tot= texres->tr= texres->tb= texres->tg= texres->ta= 0.0;
556                 while(count--) {
557                         boxsampleclip(ibuf, rf, &texr);
558                         
559                         opp= square_rctf(rf);
560                         tot+= opp;
561
562                         texres->tr+= opp*texr.tr;
563                         texres->tg+= opp*texr.tg;
564                         texres->tb+= opp*texr.tb;
565                         if(texres->talpha) texres->ta+= opp*texr.ta;
566                         rf++;
567                 }
568                 if(tot!= 0.0) {
569                         texres->tr/= tot;
570                         texres->tg/= tot;
571                         texres->tb/= tot;
572                         if(texres->talpha) texres->ta/= tot;
573                 }
574         }
575         else
576                 boxsampleclip(ibuf, rf, texres);
577
578         if(texres->talpha==0) texres->ta= 1.0;
579         
580         if(alphaclip!=1.0) {
581                 /* premul it all */
582                 texres->tr*= alphaclip;
583                 texres->tg*= alphaclip;
584                 texres->tb*= alphaclip;
585                 texres->ta*= alphaclip;
586         }
587 }       
588
589 void image_sample(Image *ima, float fx, float fy, float dx, float dy, float *result)
590 {
591         TexResult texres;
592         ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
593         
594         if(ibuf==NULL) {
595                 result[0]= result[1]= result[2]= result[3]= 0.0f;
596                 return;
597         }
598         
599         if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) )
600                 ibuf->rect+= (ibuf->x*ibuf->y);
601         
602         boxsample(ibuf, fx, fy, fx+dx, fy+dy, &texres, 0, 1, 0);
603         result[0]= texres.tr;
604         result[1]= texres.tg;
605         result[2]= texres.tb;
606         result[3]= texres.ta;
607
608         if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) )
609                 ibuf->rect-= (ibuf->x*ibuf->y);
610 }
611
612 void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float *result)
613 {
614         TexResult texres;
615         
616         if(ibuf==NULL) {
617                 return;
618         }
619         
620         memset(&texres, 0, sizeof(texres));
621         boxsample(ibuf, fx, fy, fx+dx, fy+dy, &texres, 0, 1, 0);
622         result[0]= texres.tr;
623         result[1]= texres.tg;
624         result[2]= texres.tb;
625         result[3]= texres.ta;
626 }
627
628
629 //-----------------------------------------------------------------------------------------------------------------
630 // from here, some functions only used for the new filtering
631
632 // this only used here to make it easier to pass extend flags as single int
633 enum {TXC_XMIR=1, TXC_YMIR, TXC_REPT, TXC_EXTD};
634
635 // similar to ibuf_get_color() but clips/wraps coords according to repeat/extend flags
636 // returns true if out of range in clipmode
637 static int ibuf_get_color_clip(float *col, ImBuf *ibuf, int x, int y, int extflag)
638 {
639         int clip = 0;
640         switch (extflag) {
641                 case TXC_XMIR:  // y rep
642                         x %= 2*ibuf->x;
643                         x += x < 0 ? 2*ibuf->x : 0;
644                         x = x >= ibuf->x ? 2*ibuf->x - x - 1 : x;
645                         y %= ibuf->y;
646                         y += y < 0 ? ibuf->y : 0;
647                         break;
648                 case TXC_YMIR:  // x rep
649                         x %= ibuf->x;
650                         x += x < 0 ? ibuf->x : 0;
651                         y %= 2*ibuf->y;
652                         y += y < 0 ? 2*ibuf->y : 0;
653                         y = y >= ibuf->y ? 2*ibuf->y - y - 1 : y;
654                         break;
655                 case TXC_EXTD:
656                         x = (x < 0) ? 0 : ((x >= ibuf->x) ? (ibuf->x - 1) : x);
657                         y = (y < 0) ? 0 : ((y >= ibuf->y) ? (ibuf->y - 1) : y);
658                         break;
659                 case TXC_REPT:
660                         x %= ibuf->x;
661                         x += (x < 0) ? ibuf->x : 0;
662                         y %= ibuf->y;
663                         y += (y < 0) ? ibuf->y : 0;
664                         break;
665                 default:        {       // as extend, if clipped, set alpha to 0.0
666                         if (x < 0) { x = 0;  } // TXF alpha: clip = 1; }
667                         if (x >= ibuf->x) { x = ibuf->x - 1; } // TXF alpha:  clip = 1; }
668                         if (y < 0) { y = 0; } // TXF alpha:  clip = 1; }
669                         if (y >= ibuf->y) { y = ibuf->y - 1; } // TXF alpha:  clip = 1; }
670                 }
671         }
672
673         if (ibuf->rect_float) {
674                 const float* fp = ibuf->rect_float + (x + y*ibuf->x)*ibuf->channels;
675                 if (ibuf->channels == 1)
676                         col[0] = col[1] = col[2] = col[3] = *fp;
677                 else {
678                         col[0] = fp[0];
679                         col[1] = fp[1];
680                         col[2] = fp[2];
681                         col[3] = clip ? 0.f : (ibuf->channels == 4 ? fp[3] : 1.f);
682                 }
683         }
684         else {
685                 char* rect = (char*)(ibuf->rect + x + y*ibuf->x);
686                 col[0] = rect[0]*(1.f/255.f);
687                 col[1] = rect[1]*(1.f/255.f);
688                 col[2] = rect[2]*(1.f/255.f);
689                 col[3] = clip ? 0.f : rect[3]*(1.f/255.f);
690         }
691         return clip;
692 }
693
694 // as above + bilerp
695 static int ibuf_get_color_clip_bilerp(float *col, ImBuf *ibuf, float u, float v, int intpol, int extflag)
696 {
697         if (intpol) {
698                 float c00[4], c01[4], c10[4], c11[4];
699                 const float ufl = floorf(u -= 0.5f), vfl = floorf(v -= 0.5f);
700                 const float uf = u - ufl, vf = v - vfl;
701                 const float w00=(1.f-uf)*(1.f-vf), w10=uf*(1.f-vf), w01=(1.f-uf)*vf, w11=uf*vf;
702                 const int x1 = (int)ufl, y1 = (int)vfl, x2 = x1 + 1, y2 = y1 + 1;
703                 int clip = ibuf_get_color_clip(c00, ibuf, x1, y1, extflag);
704                 clip |= ibuf_get_color_clip(c10, ibuf, x2, y1, extflag);
705                 clip |= ibuf_get_color_clip(c01, ibuf, x1, y2, extflag);
706                 clip |= ibuf_get_color_clip(c11, ibuf, x2, y2, extflag);
707                 col[0] = w00*c00[0] + w10*c10[0] + w01*c01[0] + w11*c11[0];
708                 col[1] = w00*c00[1] + w10*c10[1] + w01*c01[1] + w11*c11[1];
709                 col[2] = w00*c00[2] + w10*c10[2] + w01*c01[2] + w11*c11[2];
710                 col[3] = clip ? 0.f : w00*c00[3] + w10*c10[3] + w01*c01[3] + w11*c11[3];
711                 return clip;
712         }
713         return ibuf_get_color_clip(col, ibuf, (int)u, (int)v, extflag);
714 }
715
716 // anisotropic filters, data struct used instead of long line of (possibly unused) func args
717 typedef struct afdata_t {
718         float dxt[2], dyt[2];
719         int intpol, extflag;
720         // feline only
721         float majrad, minrad, theta;
722         int iProbes;
723         float dusc, dvsc;
724 } afdata_t;
725
726 static void area_sample(TexResult* texr, ImBuf* ibuf, float fx, float fy, afdata_t* AFD)
727 {
728         int xs, ys, clip = 0;
729         float tc[4], xsd, ysd, cw = 0.f;
730         const float ux = ibuf->x*AFD->dxt[0], uy = ibuf->y*AFD->dxt[1];
731         const float vx = ibuf->x*AFD->dyt[0], vy = ibuf->y*AFD->dyt[1];
732         int xsam = (int)(0.5f*sqrtf(ux*ux + uy*uy) + 0.5f);
733         int ysam = (int)(0.5f*sqrtf(vx*vx + vy*vy) + 0.5f);
734         const int minsam = AFD->intpol ? 2 : 4;
735         xsam = CLAMPIS(xsam, minsam, ibuf->x*2);
736         ysam = CLAMPIS(ysam, minsam, ibuf->y*2);
737         xsd = 1.f / xsam;
738         ysd = 1.f / ysam;
739         texr->tr = texr->tg = texr->tb = texr->ta = 0.f;
740         for (ys=0; ys<ysam; ++ys) {
741                 for (xs=0; xs<xsam; ++xs) {
742                         const float su = (xs + ((ys & 1) + 0.5f)*0.5f)*xsd - 0.5f;
743                         const float sv = (ys + ((xs & 1) + 0.5f)*0.5f)*ysd - 0.5f;
744                         const float pu = fx + su*AFD->dxt[0] + sv*AFD->dyt[0];
745                         const float pv = fy + su*AFD->dxt[1] + sv*AFD->dyt[1];
746                         const int out = ibuf_get_color_clip_bilerp(tc, ibuf, pu*ibuf->x, pv*ibuf->y, AFD->intpol, AFD->extflag);
747                         clip |= out;
748                         cw += out ? 0.f : 1.f;
749                         texr->tr += tc[0];
750                         texr->tg += tc[1];
751                         texr->tb += tc[2];
752                         texr->ta += texr->talpha ? tc[3] : 0.f;
753                 }
754         }
755         xsd *= ysd;
756         texr->tr *= xsd;
757         texr->tg *= xsd;
758         texr->tb *= xsd;
759         // clipping can be ignored if alpha used, texr->ta already includes filtered edge
760         texr->ta = texr->talpha ? texr->ta*xsd : (clip ? cw*xsd : 1.f);
761 }
762
763 // table of (exp(ar) - exp(a)) / (1 - exp(a)) for r in range [0, 1] and a = -2
764 // used instead of actual gaussian, otherwise at high texture magnifications circular artifacts are visible
765 #define EWA_MAXIDX 255
766 static float EWA_WTS[EWA_MAXIDX + 1] =
767 { 1.f, 0.990965f, 0.982f, 0.973105f, 0.96428f, 0.955524f, 0.946836f, 0.938216f, 0.929664f,
768  0.921178f, 0.912759f, 0.904405f, 0.896117f, 0.887893f, 0.879734f, 0.871638f, 0.863605f,
769  0.855636f, 0.847728f, 0.839883f, 0.832098f, 0.824375f, 0.816712f, 0.809108f, 0.801564f,
770  0.794079f, 0.786653f, 0.779284f, 0.771974f, 0.76472f, 0.757523f, 0.750382f, 0.743297f,
771  0.736267f, 0.729292f, 0.722372f, 0.715505f, 0.708693f, 0.701933f, 0.695227f, 0.688572f,
772  0.68197f, 0.67542f, 0.66892f, 0.662471f, 0.656073f, 0.649725f, 0.643426f, 0.637176f,
773  0.630976f, 0.624824f, 0.618719f, 0.612663f, 0.606654f, 0.600691f, 0.594776f, 0.588906f,
774  0.583083f, 0.577305f, 0.571572f, 0.565883f, 0.56024f, 0.55464f, 0.549084f, 0.543572f,
775  0.538102f, 0.532676f, 0.527291f, 0.521949f, 0.516649f, 0.511389f, 0.506171f, 0.500994f,
776  0.495857f, 0.490761f, 0.485704f, 0.480687f, 0.475709f, 0.470769f, 0.465869f, 0.461006f,
777  0.456182f, 0.451395f, 0.446646f, 0.441934f, 0.437258f, 0.432619f, 0.428017f, 0.42345f,
778  0.418919f, 0.414424f, 0.409963f, 0.405538f, 0.401147f, 0.39679f, 0.392467f, 0.388178f,
779  0.383923f, 0.379701f, 0.375511f, 0.371355f, 0.367231f, 0.363139f, 0.359079f, 0.355051f,
780  0.351055f, 0.347089f, 0.343155f, 0.339251f, 0.335378f, 0.331535f, 0.327722f, 0.323939f,
781  0.320186f, 0.316461f, 0.312766f, 0.3091f, 0.305462f, 0.301853f, 0.298272f, 0.294719f,
782  0.291194f, 0.287696f, 0.284226f, 0.280782f, 0.277366f, 0.273976f, 0.270613f, 0.267276f,
783  0.263965f, 0.26068f, 0.257421f, 0.254187f, 0.250979f, 0.247795f, 0.244636f, 0.241502f,
784  0.238393f, 0.235308f, 0.232246f, 0.229209f, 0.226196f, 0.223206f, 0.220239f, 0.217296f,
785  0.214375f, 0.211478f, 0.208603f, 0.20575f, 0.20292f, 0.200112f, 0.197326f, 0.194562f,
786  0.191819f, 0.189097f, 0.186397f, 0.183718f, 0.18106f, 0.178423f, 0.175806f, 0.17321f,
787  0.170634f, 0.168078f, 0.165542f, 0.163026f, 0.16053f, 0.158053f, 0.155595f, 0.153157f,
788  0.150738f, 0.148337f, 0.145955f, 0.143592f, 0.141248f, 0.138921f, 0.136613f, 0.134323f,
789  0.132051f, 0.129797f, 0.12756f, 0.125341f, 0.123139f, 0.120954f, 0.118786f, 0.116635f,
790  0.114501f, 0.112384f, 0.110283f, 0.108199f, 0.106131f, 0.104079f, 0.102043f, 0.100023f,
791  0.0980186f, 0.09603f, 0.094057f, 0.0920994f, 0.0901571f, 0.08823f, 0.0863179f, 0.0844208f,
792  0.0825384f, 0.0806708f, 0.0788178f, 0.0769792f, 0.0751551f, 0.0733451f, 0.0715493f, 0.0697676f,
793  0.0679997f, 0.0662457f, 0.0645054f, 0.0627786f, 0.0610654f, 0.0593655f, 0.0576789f, 0.0560055f,
794  0.0543452f, 0.0526979f, 0.0510634f, 0.0494416f, 0.0478326f, 0.0462361f, 0.0446521f, 0.0430805f,
795  0.0415211f, 0.039974f, 0.0384389f, 0.0369158f, 0.0354046f, 0.0339052f, 0.0324175f, 0.0309415f,
796  0.029477f, 0.0280239f, 0.0265822f, 0.0251517f, 0.0237324f, 0.0223242f, 0.020927f, 0.0195408f,
797  0.0181653f, 0.0168006f, 0.0154466f, 0.0141031f, 0.0127701f, 0.0114476f, 0.0101354f, 0.00883339f,
798  0.00754159f, 0.00625989f, 0.00498819f, 0.00372644f, 0.00247454f, 0.00123242f, 0.f
799 };
800
801 // test if a float value is 'nan'
802 // there is a C99 function for this: isnan(), but blender seems to use C90 (according to gcc warns),
803 // and may not be supported by other compilers either
804 #ifndef ISNAN
805 #define ISNAN(x) ((x) != (x))
806 #endif
807 //static int ISNAN(float x) { return (x != x); }
808
809 static void radangle2imp(float a2, float b2, float th, float* A, float* B, float* C, float* F)
810 {
811         float ct2 = cosf(th);
812         const float st2 = 1.f - ct2*ct2;        // <- sin(th)^2
813         ct2 *= ct2;
814         *A = a2*st2 + b2*ct2;
815         *B = (b2 - a2)*sinf(2.f*th);
816         *C = a2*ct2 + b2*st2;
817         *F = a2*b2;
818 }
819
820 // all tests here are done to make sure possible overflows are hopefully minimized
821 static void imp2radangle(float A, float B, float C, float F, float* a, float* b, float* th, float* ecc)
822 {
823         if (F <= 1e-5f) {       // use arbitrary major radius, zero minor, infinite eccentricity
824                 *a = sqrtf(A > C ? A : C);
825                 *b = 0.f;
826                 *ecc = 1e10f;
827                 *th = 0.5f*(atan2f(B, A - C) + (float)M_PI);
828         }
829         else {
830                 const float AmC = A - C, ApC = A + C, F2 = F*2.f;
831                 const float r = sqrtf(AmC*AmC + B*B);
832                 float d = ApC - r;
833                 *a = (d <= 0.f) ? sqrtf(A > C ? A : C) : sqrtf(F2 / d);
834                 d = ApC + r;
835                 if (d <= 0.f) {
836                         *b = 0.f;
837                         *ecc = 1e10f;
838                 }
839                 else {
840                         *b = sqrtf(F2 / d);
841                         *ecc = *a / *b;
842                 }
843                 // incr theta by 0.5*pi (angle of major axis)
844                 *th = 0.5f*(atan2f(B, AmC) + (float)M_PI);
845         }
846 }
847
848 static void ewa_eval(TexResult* texr, ImBuf* ibuf, float fx, float fy, afdata_t* AFD)
849 {
850         // scaling dxt/dyt by full resolution can cause overflow because of huge A/B/C and esp. F values,
851         // scaling by aspect ratio alone does the opposite, so try something inbetween instead...
852         const float ff2 = ibuf->x, ff = sqrtf(ff2), q = ibuf->y / ff;
853         const float Ux = AFD->dxt[0]*ff, Vx = AFD->dxt[1]*q, Uy = AFD->dyt[0]*ff, Vy = AFD->dyt[1]*q;
854         float A = Vx*Vx + Vy*Vy;
855         float B = -2.f*(Ux*Vx + Uy*Vy);
856         float C = Ux*Ux + Uy*Uy;
857         float F = A*C - B*B*0.25f;
858         float a, b, th, ecc, a2, b2, ue, ve, U0, V0, DDQ, U, ac1, ac2, BU, d; // TXF alpha: cw = 0.f;
859         int u, v, u1, u2, v1, v2; // TXF alpha: clip = 0;
860
861         // The so-called 'high' quality ewa method simply adds a constant of 1 to both A & C,
862         // so the ellipse always covers at least some texels. But since the filter is now always larger,
863         // it also means that everywhere else it's also more blurry then ideally should be the case.
864         // So instead here the ellipse radii are modified instead whenever either is too low.
865         // Use a different radius based on interpolation switch, just enough to anti-alias when interpolation is off,
866         // and slightly larger to make result a bit smoother than bilinear interpolation when interpolation is on
867         // (minimum values: const float rmin = intpol ? 1.f : 0.5f;)
868         const float rmin = (AFD->intpol ? 1.5625f : 0.765625f)/ff2;
869         imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
870         if ((b2 = b*b) < rmin) {
871                 if ((a2 = a*a) < rmin) {
872                         B = 0.f;
873                         A = C = rmin;
874                         F = A*C;
875                 }
876                 else {
877                         b2 = rmin;
878                         radangle2imp(a2, b2, th, &A, &B, &C, &F);
879                 }
880         }
881
882         ue = ff*sqrtf(C);
883         ve = ff*sqrtf(A);
884         d = (float)(EWA_MAXIDX + 1) / (F*ff2);
885         A *= d;
886         B *= d;
887         C *= d;
888
889         U0 = fx*ibuf->x;
890         V0 = fy*ibuf->y;
891         u1 = (int)(floorf(U0 - ue));
892         u2 = (int)(ceilf(U0 + ue));
893         v1 = (int)(floorf(V0 - ve));
894         v2 = (int)(ceilf(V0 + ve));
895         U0 -= 0.5f;
896         V0 -= 0.5f;
897         DDQ = 2.f*A;
898         U = u1 - U0;
899         ac1 = A*(2.f*U + 1.f);
900         ac2 = A*U*U;
901         BU = B*U;
902
903         d = texr->tr = texr->tb = texr->tg = texr->ta = 0.f;
904         for (v=v1; v<=v2; ++v) {
905                 const float V = v - V0;
906                 float DQ = ac1 + B*V;
907                 float Q = (C*V + BU)*V + ac2;
908                 for (u=u1; u<=u2; ++u) {
909                         if (Q < (float)(EWA_MAXIDX + 1)) {
910                                 float tc[4];
911                                 const float wt = EWA_WTS[(Q < 0.f) ? 0 : (unsigned int)Q];
912                                 /*const int out =*/ ibuf_get_color_clip(tc, ibuf, u, v, AFD->extflag);
913                                 // TXF alpha: clip |= out;
914                                 // TXF alpha: cw += out ? 0.f : wt;
915                                 texr->tr += tc[0]*wt;
916                                 texr->tg += tc[1]*wt;
917                                 texr->tb += tc[2]*wt;
918                                 texr->ta += texr->talpha ? tc[3]*wt : 0.f;
919                                 d += wt;
920                         }
921                         Q += DQ;
922                         DQ += DDQ;
923                 }
924         }
925
926         // d should hopefully never be zero anymore
927         d = 1.f/d;
928         texr->tr *= d;
929         texr->tg *= d;
930         texr->tb *= d;
931         // clipping can be ignored if alpha used, texr->ta already includes filtered edge
932         texr->ta = texr->talpha ? texr->ta*d : 1.f; // TXF alpha (clip ? cw*d : 1.f);
933 }
934
935 static void feline_eval(TexResult* texr, ImBuf* ibuf, float fx, float fy, afdata_t* AFD)
936 {
937         const int maxn = AFD->iProbes - 1;
938         const float ll = ((AFD->majrad == AFD->minrad) ? 2.f*AFD->majrad : 2.f*(AFD->majrad - AFD->minrad)) / (maxn ? (float)maxn : 1.f);
939         float du = maxn ? cosf(AFD->theta)*ll : 0.f;
940         float dv = maxn ? sinf(AFD->theta)*ll : 0.f;
941         //const float D = -0.5f*(du*du + dv*dv) / (AFD->majrad*AFD->majrad);
942         const float D = (EWA_MAXIDX + 1)*0.25f*(du*du + dv*dv) / (AFD->majrad*AFD->majrad);
943         float d; // TXF alpha: cw = 0.f;
944         int n; // TXF alpha: clip = 0;
945         // have to use same scaling for du/dv here as for Ux/Vx/Uy/Vy (*after* D calc.)
946         du *= AFD->dusc;
947         dv *= AFD->dvsc;
948         d = texr->tr = texr->tb = texr->tg = texr->ta = 0.f;
949         for (n=-maxn; n<=maxn; n+=2) {
950                 float tc[4];
951                 const float hn = n*0.5f;
952                 const float u = fx + hn*du, v = fy + hn*dv;
953                 //const float wt = expf(n*n*D);
954                 // can use ewa table here too
955                 const float wt = EWA_WTS[(int)(n*n*D)];
956                 /*const int out =*/ ibuf_get_color_clip_bilerp(tc, ibuf, ibuf->x*u, ibuf->y*v, AFD->intpol, AFD->extflag);
957                 // TXF alpha: clip |= out;
958                 // TXF alpha: cw += out ? 0.f : wt;
959                 texr->tr += tc[0]*wt;
960                 texr->tg += tc[1]*wt;
961                 texr->tb += tc[2]*wt;
962                 texr->ta += texr->talpha ? tc[3]*wt : 0.f;
963                 d += wt;
964         }
965
966         d = 1.f/d;
967         texr->tr *= d;
968         texr->tg *= d;
969         texr->tb *= d;
970         // clipping can be ignored if alpha used, texr->ta already includes filtered edge
971         texr->ta = texr->talpha ? texr->ta*d : 1.f; // TXF alpha: (clip ? cw*d : 1.f);
972 }
973 #undef EWA_MAXIDX
974
975 static void alpha_clip_aniso(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, int extflag, TexResult *texres)
976 {
977         float alphaclip;
978         rctf rf;
979
980         // TXF apha: we're doing the same alphaclip here as boxsample, but i'm doubting
981         // if this is actually correct for the all the filtering algorithms ..
982
983         if(!(extflag == TXC_REPT || extflag == TXC_EXTD)) {
984                 rf.xmin= minx*(ibuf->x);
985                 rf.xmax= maxx*(ibuf->x);
986                 rf.ymin= miny*(ibuf->y);
987                 rf.ymax= maxy*(ibuf->y);
988    
989                 alphaclip = clipx_rctf(&rf, 0.0, (float)(ibuf->x));
990                 alphaclip*= clipy_rctf(&rf, 0.0, (float)(ibuf->y));
991                 alphaclip= MAX2(alphaclip, 0.0f);
992
993                 if(alphaclip!=1.0) {
994                         /* premul it all */
995                         texres->tr*= alphaclip;
996                         texres->tg*= alphaclip;
997                         texres->tb*= alphaclip;
998                         texres->ta*= alphaclip;
999                 }
1000         }
1001 }
1002
1003 static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, float *texvec, float *dxt, float *dyt, TexResult *texres)
1004 {
1005         TexResult texr;
1006         float fx, fy, minx, maxx, miny, maxy;
1007         float maxd, val1, val2, val3;
1008         int curmap, retval, intpol, extflag = 0;
1009         afdata_t AFD;
1010
1011         void (*filterfunc)(TexResult*, ImBuf*, float, float, afdata_t*);
1012         switch (tex->texfilter) {
1013                 case TXF_EWA:
1014                         filterfunc = ewa_eval;
1015                         break;
1016                 case TXF_FELINE:
1017                         filterfunc = feline_eval;
1018                         break;
1019                 case TXF_AREA:
1020                 default:
1021                         filterfunc = area_sample;
1022         }
1023
1024         texres->tin = texres->ta = texres->tr = texres->tg = texres->tb = 0.f;
1025
1026         // we need to set retval OK, otherwise texture code generates normals itself...
1027         retval = texres->nor ? 3 : 1;
1028
1029         // quick tests
1030         if (ibuf==NULL && ima==NULL) return retval;
1031
1032         if (ima) {      // hack for icon render
1033                 if ((ima->ibufs.first == NULL) && (R.r.scemode & R_NO_IMAGE_LOAD)) return retval;
1034                 ibuf = BKE_image_get_ibuf(ima, &tex->iuser); 
1035         }
1036
1037         if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) return retval;
1038
1039         // mipmap test
1040         if (tex->imaflag & TEX_MIPMAP) {
1041                 if (((ibuf->flags & IB_fields) == 0) && (ibuf->mipmap[0] == NULL)) {
1042                         BLI_lock_thread(LOCK_IMAGE);
1043                         if (ibuf->mipmap[0] == NULL) IMB_makemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
1044                         BLI_unlock_thread(LOCK_IMAGE);
1045                 }
1046         }
1047
1048         if ((tex->imaflag & TEX_USEALPHA) && ((tex->imaflag & TEX_CALCALPHA) == 0)) texres->talpha = 1;
1049         texr.talpha = texres->talpha;
1050
1051         if (tex->imaflag & TEX_IMAROT) {
1052                 fy = texvec[0];
1053                 fx = texvec[1];
1054         }
1055         else {
1056                 fx = texvec[0];
1057                 fy = texvec[1];
1058         }
1059
1060         if (ibuf->flags & IB_fields) {
1061                 if (R.r.mode & R_FIELDS) {                      /* field render */
1062                         if (R.flag & R_SEC_FIELD) {             /* correction for 2nd field */
1063                                 /* fac1= 0.5/( (float)ibuf->y ); */
1064                                 /* fy-= fac1; */
1065                         }
1066                         else    /* first field */
1067                                 fy += 0.5f/( (float)ibuf->y );
1068                 }
1069         }
1070
1071         // pixel coordinates
1072         minx = MIN3(dxt[0], dyt[0], dxt[0] + dyt[0]);
1073         maxx = MAX3(dxt[0], dyt[0], dxt[0] + dyt[0]);
1074         miny = MIN3(dxt[1], dyt[1], dxt[1] + dyt[1]);
1075         maxy = MAX3(dxt[1], dyt[1], dxt[1] + dyt[1]);
1076
1077         // tex_sharper has been removed
1078         minx = (maxx - minx)*0.5f;
1079         miny = (maxy - miny)*0.5f;
1080
1081         if (tex->imaflag & TEX_FILTER_MIN) {
1082                 // make sure the filtersize is minimal in pixels (normal, ref map can have miniature pixel dx/dy)
1083                 const float addval = (0.5f * tex->filtersize) / (float)MIN2(ibuf->x, ibuf->y);
1084                 if (addval > minx) minx = addval;
1085                 if (addval > miny) miny = addval;
1086         }
1087         else if (tex->filtersize != 1.f) {
1088                 minx *= tex->filtersize;
1089                 miny *= tex->filtersize;
1090                 dxt[0] *= tex->filtersize;
1091                 dxt[1] *= tex->filtersize;
1092                 dyt[0] *= tex->filtersize;
1093                 dyt[1] *= tex->filtersize;
1094         }
1095
1096         if (tex->imaflag & TEX_IMAROT) {
1097                 float t;
1098                 SWAP(float, minx, miny);
1099                 // must rotate dxt/dyt 90 deg
1100                 // yet another blender problem is that swapping X/Y axes (or any tex proj switches) should do something similar,
1101                 // but it doesn't, it only swaps coords, so filter area will be incorrect in those cases.
1102                 t = dxt[0];
1103                 dxt[0] = dxt[1];
1104                 dxt[1] = -t;
1105                 t = dyt[0];
1106                 dyt[0] = dyt[1];
1107                 dyt[1] = -t;
1108         }
1109
1110         // side faces of unit-cube
1111         minx = (minx > 0.25f) ? 0.25f : ((minx < 1e-5f) ? 1e-5 : minx);
1112         miny = (miny > 0.25f) ? 0.25f : ((miny < 1e-5f) ? 1e-5 : miny);
1113
1114         // repeat and clip
1115
1116         if (tex->extend == TEX_REPEAT) {
1117                 if ((tex->flag & (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR)) == (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR))
1118                         extflag = TXC_EXTD;
1119                 else if (tex->flag & TEX_REPEAT_XMIR)
1120                         extflag = TXC_XMIR;
1121                 else if (tex->flag & TEX_REPEAT_YMIR)
1122                         extflag = TXC_YMIR;
1123                 else
1124                         extflag = TXC_REPT;
1125         }
1126         else if (tex->extend == TEX_EXTEND)
1127                 extflag = TXC_EXTD;
1128
1129         if (tex->extend == TEX_CHECKER) {
1130                 int xs = (int)floorf(fx), ys = (int)floorf(fy);
1131                 // both checkers available, no boundary exceptions, checkerdist will eat aliasing
1132                 if ((tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN)) {
1133                         fx -= xs;
1134                         fy -= ys;
1135                 }
1136                 else {
1137                         int xs1 = (int)floorf(fx - minx);
1138                         int ys1 = (int)floorf(fy - miny);
1139                         int xs2 = (int)floorf(fx + minx);
1140                         int ys2 = (int)floorf(fy + miny);
1141                         if ((xs1 != xs2) || (ys1 != ys2)) {
1142                                 if (tex->flag & TEX_CHECKER_ODD) {
1143                                         fx -= ((xs1 + ys) & 1) ? xs2 : xs1;
1144                                         fy -= ((ys1 + xs) & 1) ? ys2 : ys1;
1145                                 }
1146                                 if (tex->flag & TEX_CHECKER_EVEN) {
1147                                         fx -= ((xs1 + ys) & 1) ? xs1 : xs2;
1148                                         fy -= ((ys1 + xs) & 1) ? ys1 : ys2;
1149                                 }
1150                         }
1151                         else {
1152                                 if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) return retval;
1153                                 if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) return retval;
1154                                 fx -= xs;
1155                                 fy -= ys;
1156                         }
1157                 }
1158                 // scale around center, (0.5, 0.5)
1159                 if (tex->checkerdist < 1.f) {
1160                         const float omcd = 1.f / (1.f - tex->checkerdist);
1161                         fx = (fx - 0.5f)*omcd + 0.5f;
1162                         fy = (fy - 0.5f)*omcd + 0.5f;
1163                         minx *= omcd;
1164                         miny *= omcd;
1165                 }
1166         }
1167
1168         if (tex->extend == TEX_CLIPCUBE) {
1169                 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;
1170         }
1171         else if (tex->extend == TEX_CLIP || tex->extend == TEX_CHECKER) {
1172                 if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f) return retval;
1173         }
1174         else {
1175                 if (tex->extend == TEX_EXTEND) {
1176                         fx = (fx > 1.f) ? 1.f : ((fx < 0.f) ? 0.f : fx);
1177                         fy = (fy > 1.f) ? 1.f : ((fy < 0.f) ? 0.f : fy);
1178                 }
1179                 else {
1180                         fx -= floorf(fx);
1181                         fy -= floorf(fy);
1182                 }
1183         }
1184
1185         intpol = tex->imaflag & TEX_INTERPOL;
1186
1187         // warning no return!
1188         if ((R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields))
1189                 ibuf->rect += ibuf->x*ibuf->y;
1190
1191         // struct common data
1192         copy_v2_v2(AFD.dxt, dxt);
1193         copy_v2_v2(AFD.dyt, dyt);
1194         AFD.intpol = intpol;
1195         AFD.extflag = extflag;
1196
1197         // brecht: added stupid clamping here, large dx/dy can give very large
1198         // filter sizes which take ages to render, it may be better to do this
1199         // more intelligently later in the code .. probably it's not noticeable
1200         if(AFD.dxt[0]*AFD.dxt[0] + AFD.dxt[1]*AFD.dxt[1] > 2.0f*2.0f) {
1201                 mul_v2_fl(AFD.dxt, 2.0f/len_v2(AFD.dxt));
1202                 mul_v2_fl(AFD.dyt, 2.0f/len_v2(AFD.dyt));
1203         }
1204         if(AFD.dyt[0]*AFD.dyt[0] + AFD.dyt[1]*AFD.dyt[1] > 2.0f*2.0f)
1205                 mul_v2_fl(AFD.dyt, 2.0f/len_v2(AFD.dyt));
1206
1207         // choice:
1208         if (tex->imaflag & TEX_MIPMAP) {
1209                 ImBuf *previbuf, *curibuf;
1210                 float levf;
1211                 int maxlev;
1212                 ImBuf* mipmaps[IB_MIPMAP_LEVELS + 1];
1213
1214                 // modify ellipse minor axis if too eccentric, use for area sampling as well
1215                 // scaling dxt/dyt as done in pbrt is not the same
1216                 // (as in ewa_eval(), scale by sqrt(ibuf->x) to maximize precision)
1217                 const float ff = sqrtf(ibuf->x), q = ibuf->y/ff;
1218                 const float Ux = dxt[0]*ff, Vx = dxt[1]*q, Uy = dyt[0]*ff, Vy = dyt[1]*q;
1219                 const float A = Vx*Vx + Vy*Vy;
1220                 const float B = -2.f*(Ux*Vx + Uy*Vy);
1221                 const float C = Ux*Ux + Uy*Uy;
1222                 const float F = A*C - B*B*0.25f;
1223                 float a, b, th, ecc;
1224                 imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
1225                 if (tex->texfilter == TXF_FELINE) {
1226                         float fProbes;
1227                         a *= ff;
1228                         b *= ff;
1229                         a = MAX2(a, 1.f);
1230                         b = MAX2(b, 1.f);
1231                         fProbes = 2.f*(a / b) - 1.f;
1232                         AFD.iProbes = (int)floorf(fProbes + 0.5f);
1233                         AFD.iProbes = MIN2(AFD.iProbes, tex->afmax);
1234                         if (AFD.iProbes < fProbes)
1235                                 b = 2.f*a / (float)(AFD.iProbes + 1);
1236                         AFD.majrad = a/ff;
1237                         AFD.minrad = b/ff;
1238                         AFD.theta = th;
1239                         AFD.dusc = 1.f/ff;
1240                         AFD.dvsc = ff / (float)ibuf->y;
1241                 }
1242                 else {  // EWA & area
1243                         if (ecc > (float)tex->afmax) b = a / (float)tex->afmax;
1244                         b *= ff;
1245                 }
1246                 maxd = MAX2(b, 1e-8f);
1247                 levf = ((float)M_LOG2E)*logf(maxd);
1248
1249                 curmap = 0;
1250                 maxlev = 1;
1251                 mipmaps[0] = ibuf;
1252                 while (curmap < IB_MIPMAP_LEVELS) {
1253                         mipmaps[curmap + 1] = ibuf->mipmap[curmap];
1254                         if (ibuf->mipmap[curmap]) maxlev++;
1255                         curmap++;
1256                 }
1257
1258                 // mipmap level
1259                 if (levf < 0.f) {       // original image only
1260                         previbuf = curibuf = mipmaps[0];
1261                         levf = 0.f;
1262                 }
1263                 else if (levf >= maxlev - 1) {
1264                         previbuf = curibuf = mipmaps[maxlev - 1];
1265                         levf = 0.f;
1266                         if (tex->texfilter == TXF_FELINE) AFD.iProbes = 1;
1267                 }
1268                 else {
1269                         const int lev = ISNAN(levf) ? 0 : (int)levf;
1270                         curibuf = mipmaps[lev];
1271                         previbuf = mipmaps[lev + 1];
1272                         levf -= floorf(levf);
1273                 }
1274
1275                 // filter functions take care of interpolation themselves, no need to modify dxt/dyt here
1276
1277                 if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) {
1278                         // color & normal
1279                         filterfunc(texres, curibuf, fx, fy, &AFD);
1280                         val1 = texres->tr + texres->tg + texres->tb;
1281                         filterfunc(&texr, curibuf, fx + dxt[0], fy + dxt[1], &AFD);
1282                         val2 = texr.tr + texr.tg + texr.tb;
1283                         filterfunc(&texr, curibuf, fx + dyt[0], fy + dyt[1], &AFD);
1284                         val3 = texr.tr + texr.tg + texr.tb;
1285                         // don't switch x or y!
1286                         texres->nor[0] = val1 - val2;
1287                         texres->nor[1] = val1 - val3;
1288                         if (previbuf != curibuf) {  // interpolate
1289                                 filterfunc(&texr, previbuf, fx, fy, &AFD);
1290                                 // rgb
1291                                 texres->tr += levf*(texr.tr - texres->tr);
1292                                 texres->tg += levf*(texr.tg - texres->tg);
1293                                 texres->tb += levf*(texr.tb - texres->tb);
1294                                 texres->ta += levf*(texr.ta - texres->ta);
1295                                 // normal
1296                                 val1 += levf*((texr.tr + texr.tg + texr.tb) - val1);
1297                                 filterfunc(&texr, previbuf, fx + dxt[0], fy + dxt[1], &AFD);
1298                                 val2 += levf*((texr.tr + texr.tg + texr.tb) - val2);
1299                                 filterfunc(&texr, previbuf, fx + dyt[0], fy + dyt[1], &AFD);
1300                                 val3 += levf*((texr.tr + texr.tg + texr.tb) - val3);
1301                                 texres->nor[0] = val1 - val2;   // vals have been interpolated above!
1302                                 texres->nor[1] = val1 - val3;
1303                         }
1304                 }
1305                 else {  // color
1306                         filterfunc(texres, curibuf, fx, fy, &AFD);
1307                         if (previbuf != curibuf) {  // interpolate
1308                                 filterfunc(&texr, previbuf, fx, fy, &AFD);
1309                                 texres->tr += levf*(texr.tr - texres->tr);
1310                                 texres->tg += levf*(texr.tg - texres->tg);
1311                                 texres->tb += levf*(texr.tb - texres->tb);
1312                                 texres->ta += levf*(texr.ta - texres->ta);
1313                         }
1314
1315                         alpha_clip_aniso(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, extflag, texres);
1316                 }
1317         }
1318         else {  // no mipmap
1319                 // filter functions take care of interpolation themselves, no need to modify dxt/dyt here
1320                 if (tex->texfilter == TXF_FELINE) {
1321                         const float ff = sqrtf(ibuf->x), q = ibuf->y/ff;
1322                         const float Ux = dxt[0]*ff, Vx = dxt[1]*q, Uy = dyt[0]*ff, Vy = dyt[1]*q;
1323                         const float A = Vx*Vx + Vy*Vy;
1324                         const float B = -2.f*(Ux*Vx + Uy*Vy);
1325                         const float C = Ux*Ux + Uy*Uy;
1326                         const float F = A*C - B*B*0.25f;
1327                         float a, b, th, ecc, fProbes;
1328                         imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
1329                         a *= ff;
1330                         b *= ff;
1331                         a = MAX2(a, 1.f);
1332                         b = MAX2(b, 1.f);
1333                         fProbes = 2.f*(a / b) - 1.f;
1334                         // no limit to number of Probes here
1335                         AFD.iProbes = (int)floorf(fProbes + 0.5f);
1336                         if (AFD.iProbes < fProbes) b = 2.f*a / (float)(AFD.iProbes + 1);
1337                         AFD.majrad = a/ff;
1338                         AFD.minrad = b/ff;
1339                         AFD.theta = th;
1340                         AFD.dusc = 1.f/ff;
1341                         AFD.dvsc = ff / (float)ibuf->y;
1342                 }
1343                 if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) {
1344                         // color & normal
1345                         filterfunc(texres, ibuf, fx, fy, &AFD);
1346                         val1 = texres->tr + texres->tg + texres->tb;
1347                         filterfunc(&texr, ibuf, fx + dxt[0], fy + dxt[1], &AFD);
1348                         val2 = texr.tr + texr.tg + texr.tb;
1349                         filterfunc(&texr, ibuf, fx + dyt[0], fy + dyt[1], &AFD);
1350                         val3 = texr.tr + texr.tg + texr.tb;
1351                         // don't switch x or y!
1352                         texres->nor[0] = val1 - val2;
1353                         texres->nor[1] = val1 - val3;
1354                 }
1355                 else {
1356                         filterfunc(texres, ibuf, fx, fy, &AFD);
1357                         alpha_clip_aniso(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, extflag, texres);
1358                 }
1359         }
1360
1361         BRICONTRGB;
1362
1363         if (tex->imaflag & TEX_CALCALPHA)
1364                 texres->ta = texres->tin = texres->ta * MAX3(texres->tr, texres->tg, texres->tb);
1365         else
1366                 texres->tin = texres->ta;
1367         if (tex->flag & TEX_NEGALPHA) texres->ta = 1.f - texres->ta;
1368         
1369         if ((R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields))
1370                 ibuf->rect -= ibuf->x*ibuf->y;
1371
1372         if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) {    // normal from color
1373                 texres->nor[0] = 2.f*(texres->tr - 0.5f);
1374                 texres->nor[1] = 2.f*(0.5f - texres->tg);
1375                 texres->nor[2] = 2.f*(texres->tb - 0.5f);
1376         }
1377         
1378         // de-premul, this is being premulled in shade_input_do_shade()
1379         // TXF: this currently does not (yet?) work properly, destroys edge AA in clip/checker mode, so for now commented out
1380         // also disabled in imagewraposa() to be able to compare results with blender's default texture filtering
1381
1382         // brecht: tried to fix this, see "TXF alpha" comments
1383
1384         if (texres->ta != 1.f && (texres->ta > FLT_EPSILON)) {
1385                 fx = 1.f/texres->ta;
1386                 texres->tr *= fx;
1387                 texres->tg *= fx;
1388                 texres->tb *= fx;
1389         }
1390
1391         return retval;
1392 }
1393
1394
1395 int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, float *texvec, float *DXT, float *DYT, TexResult *texres)
1396 {
1397         TexResult texr;
1398         float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[3], dyt[3];
1399         float maxd, pixsize, val1, val2, val3;
1400         int curmap, retval, imaprepeat, imapextend;
1401
1402         // TXF: since dxt/dyt might be modified here and since they might be needed after imagewraposa() call,
1403         // make a local copy here so that original vecs remain untouched
1404         VECCOPY(dxt, DXT);
1405         VECCOPY(dyt, DYT);
1406
1407         // anisotropic filtering
1408         if (tex->texfilter != TXF_BOX)
1409                 return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres);
1410
1411         texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f;
1412         
1413         /* we need to set retval OK, otherwise texture code generates normals itself... */
1414         retval= texres->nor?3:1;
1415         
1416         /* quick tests */
1417         if(ibuf==NULL && ima==NULL)
1418                 return retval;
1419         if(ima) {
1420
1421                 /* hack for icon render */
1422                 if(ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD))
1423                         return retval;
1424                 
1425                 ibuf= BKE_image_get_ibuf(ima, &tex->iuser); 
1426         }
1427         if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL))
1428            return retval;
1429         
1430         /* mipmap test */
1431         if (tex->imaflag & TEX_MIPMAP) {
1432                 if(ibuf->flags & IB_fields);
1433                 else if(ibuf->mipmap[0]==NULL) {
1434                         BLI_lock_thread(LOCK_IMAGE);
1435                         
1436                         if(ibuf->mipmap[0]==NULL)
1437                                 IMB_makemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
1438
1439                         BLI_unlock_thread(LOCK_IMAGE);
1440                 }
1441         }
1442
1443         if(tex->imaflag & TEX_USEALPHA) {
1444                 if(tex->imaflag & TEX_CALCALPHA);
1445                 else texres->talpha= 1;
1446         }
1447         
1448         texr.talpha= texres->talpha;
1449         
1450         if(tex->imaflag & TEX_IMAROT) {
1451                 fy= texvec[0];
1452                 fx= texvec[1];
1453         }
1454         else {
1455                 fx= texvec[0];
1456                 fy= texvec[1];
1457         }
1458         
1459         if(ibuf->flags & IB_fields) {
1460                 if(R.r.mode & R_FIELDS) {                       /* field render */
1461                         if(R.flag & R_SEC_FIELD) {              /* correction for 2nd field */
1462                                 /* fac1= 0.5/( (float)ibuf->y ); */
1463                                 /* fy-= fac1; */
1464                         }
1465                         else {                          /* first field */
1466                                 fy+= 0.5f/( (float)ibuf->y );
1467                         }
1468                 }
1469         }
1470         
1471         /* pixel coordinates */
1472
1473         minx= MIN3(dxt[0],dyt[0],dxt[0]+dyt[0] );
1474         maxx= MAX3(dxt[0],dyt[0],dxt[0]+dyt[0] );
1475         miny= MIN3(dxt[1],dyt[1],dxt[1]+dyt[1] );
1476         maxy= MAX3(dxt[1],dyt[1],dxt[1]+dyt[1] );
1477
1478         /* tex_sharper has been removed */
1479         minx= (maxx-minx)/2.0f;
1480         miny= (maxy-miny)/2.0f;
1481         
1482         if(tex->imaflag & TEX_FILTER_MIN) {
1483                 /* make sure the filtersize is minimal in pixels (normal, ref map can have miniature pixel dx/dy) */
1484                 float addval= (0.5f * tex->filtersize) / (float) MIN2(ibuf->x, ibuf->y);
1485                 
1486                 if(addval > minx)
1487                         minx= addval;
1488                 if(addval > miny)
1489                         miny= addval;
1490         }
1491         else if(tex->filtersize!=1.0f) {
1492                 minx*= tex->filtersize;
1493                 miny*= tex->filtersize;
1494                 
1495                 dxt[0]*= tex->filtersize;
1496                 dxt[1]*= tex->filtersize;
1497                 dyt[0]*= tex->filtersize;
1498                 dyt[1]*= tex->filtersize;
1499         }
1500
1501         if(tex->imaflag & TEX_IMAROT) SWAP(float, minx, miny);
1502         
1503         if(minx>0.25) minx= 0.25;
1504         else if(minx<0.00001f) minx= 0.00001f;  /* side faces of unit-cube */
1505         if(miny>0.25) miny= 0.25;
1506         else if(miny<0.00001f) miny= 0.00001f;
1507
1508         
1509         /* repeat and clip */
1510         imaprepeat= (tex->extend==TEX_REPEAT);
1511         imapextend= (tex->extend==TEX_EXTEND);
1512
1513         if(tex->extend == TEX_REPEAT) {
1514                 if(tex->flag & (TEX_REPEAT_XMIR|TEX_REPEAT_YMIR)) {
1515                         imaprepeat= 0;
1516                         imapextend= 1;
1517                 }
1518         }
1519
1520         if(tex->extend == TEX_CHECKER) {
1521                 int xs, ys, xs1, ys1, xs2, ys2, boundary;
1522                 
1523                 xs= (int)floor(fx);
1524                 ys= (int)floor(fy);
1525                 
1526                 // both checkers available, no boundary exceptions, checkerdist will eat aliasing
1527                 if( (tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN) ) {
1528                         fx-= xs;
1529                         fy-= ys;
1530                 }
1531                 else {
1532                         
1533                         xs1= (int)floor(fx-minx);
1534                         ys1= (int)floor(fy-miny);
1535                         xs2= (int)floor(fx+minx);
1536                         ys2= (int)floor(fy+miny);
1537                         boundary= (xs1!=xs2) || (ys1!=ys2);
1538
1539                         if(boundary==0) {
1540                                 if( (tex->flag & TEX_CHECKER_ODD)==0) {
1541                                         if((xs+ys) & 1); 
1542                                         else return retval;
1543                                 }
1544                                 if( (tex->flag & TEX_CHECKER_EVEN)==0) {
1545                                         if((xs+ys) & 1) return retval;
1546                                 }
1547                                 fx-= xs;
1548                                 fy-= ys;
1549                         }
1550                         else {
1551                                 if(tex->flag & TEX_CHECKER_ODD) {
1552                                         if((xs1+ys) & 1) fx-= xs2;
1553                                         else fx-= xs1;
1554                                         
1555                                         if((ys1+xs) & 1) fy-= ys2;
1556                                         else fy-= ys1;
1557                                 }
1558                                 if(tex->flag & TEX_CHECKER_EVEN) {
1559                                         if((xs1+ys) & 1) fx-= xs1;
1560                                         else fx-= xs2;
1561                                         
1562                                         if((ys1+xs) & 1) fy-= ys1;
1563                                         else fy-= ys2;
1564                                 }
1565                         }
1566                 }
1567
1568                 /* scale around center, (0.5, 0.5) */
1569                 if(tex->checkerdist<1.0) {
1570                         fx= (fx-0.5)/(1.0-tex->checkerdist) +0.5;
1571                         fy= (fy-0.5)/(1.0-tex->checkerdist) +0.5;
1572                         minx/= (1.0-tex->checkerdist);
1573                         miny/= (1.0-tex->checkerdist);
1574                 }
1575         }
1576
1577         if(tex->extend == TEX_CLIPCUBE) {
1578                 if(fx+minx<0.0 || fy+miny<0.0 || fx-minx>1.0 || fy-miny>1.0 || texvec[2]<-1.0 || texvec[2]>1.0) {
1579                         return retval;
1580                 }
1581         }
1582         else if(tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
1583                 if(fx+minx<0.0 || fy+miny<0.0 || fx-minx>1.0 || fy-miny>1.0) {
1584                         return retval;
1585                 }
1586         }
1587         else {
1588                 if(imapextend) {
1589                         if(fx>1.0) fx = 1.0;
1590                         else if(fx<0.0) fx= 0.0;
1591                 }
1592                 else {
1593                         if(fx>1.0) fx -= (int)(fx);
1594                         else if(fx<0.0) fx+= 1-(int)(fx);
1595                 }
1596                 
1597                 if(imapextend) {
1598                         if(fy>1.0) fy = 1.0;
1599                         else if(fy<0.0) fy= 0.0;
1600                 }
1601                 else {
1602                         if(fy>1.0) fy -= (int)(fy);
1603                         else if(fy<0.0) fy+= 1-(int)(fy);
1604                 }
1605         }
1606
1607         /* warning no return! */
1608         if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
1609                 ibuf->rect+= (ibuf->x*ibuf->y);
1610         }
1611
1612         /* choice:  */
1613         if(tex->imaflag & TEX_MIPMAP) {
1614                 ImBuf *previbuf, *curibuf;
1615                 float bumpscale;
1616                 
1617                 dx= minx;
1618                 dy= miny;
1619                 maxd= MAX2(dx, dy);
1620                 if(maxd>0.5) maxd= 0.5;
1621
1622                 pixsize = 1.0f/ (float) MIN2(ibuf->x, ibuf->y);
1623                 
1624                 bumpscale= pixsize/maxd;
1625                 if(bumpscale>1.0f) bumpscale= 1.0f;
1626                 else bumpscale*=bumpscale;
1627                 
1628                 curmap= 0;
1629                 previbuf= curibuf= ibuf;
1630                 while(curmap<IB_MIPMAP_LEVELS && ibuf->mipmap[curmap]) {
1631                         if(maxd < pixsize) break;
1632                         previbuf= curibuf;
1633                         curibuf= ibuf->mipmap[curmap];
1634                         pixsize= 1.0f / (float)MIN2(curibuf->x, curibuf->y);
1635                         curmap++;
1636                 }
1637
1638                 if(previbuf!=curibuf || (tex->imaflag & TEX_INTERPOL)) {
1639                         /* sample at least 1 pixel */
1640                         if (minx < 0.5f / ibuf->x) minx = 0.5f / ibuf->x;
1641                         if (miny < 0.5f / ibuf->y) miny = 0.5f / ibuf->y;
1642                 }
1643                 
1644                 if(texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) {
1645                         /* a bit extra filter */
1646                         //minx*= 1.35f;
1647                         //miny*= 1.35f;
1648                         
1649                         boxsample(curibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend, 0);
1650                         val1= texres->tr+texres->tg+texres->tb;
1651                         boxsample(curibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend, 0);
1652                         val2= texr.tr + texr.tg + texr.tb;
1653                         boxsample(curibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend, 0);
1654                         val3= texr.tr + texr.tg + texr.tb;
1655
1656                         /* don't switch x or y! */
1657                         texres->nor[0]= (val1-val2);
1658                         texres->nor[1]= (val1-val3);
1659                         
1660                         if(previbuf!=curibuf) {  /* interpolate */
1661                                 
1662                                 boxsample(previbuf, fx-minx, fy-miny, fx+minx, fy+miny, &texr, imaprepeat, imapextend, 0);
1663                                 
1664                                 /* calc rgb */
1665                                 dx= 2.0f*(pixsize-maxd)/pixsize;
1666                                 if(dx>=1.0f) {
1667                                         texres->ta= texr.ta; texres->tb= texr.tb;
1668                                         texres->tg= texr.tg; texres->tr= texr.tr;
1669                                 }
1670                                 else {
1671                                         dy= 1.0f-dx;
1672                                         texres->tb= dy*texres->tb+ dx*texr.tb;
1673                                         texres->tg= dy*texres->tg+ dx*texr.tg;
1674                                         texres->tr= dy*texres->tr+ dx*texr.tr;
1675                                         texres->ta= dy*texres->ta+ dx*texr.ta;
1676                                 }
1677                                 
1678                                 val1= dy*val1+ dx*(texr.tr + texr.tg + texr.tb);
1679                                 boxsample(previbuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend, 0);
1680                                 val2= dy*val2+ dx*(texr.tr + texr.tg + texr.tb);
1681                                 boxsample(previbuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend, 0);
1682                                 val3= dy*val3+ dx*(texr.tr + texr.tg + texr.tb);
1683                                 
1684                                 texres->nor[0]= (val1-val2);    /* vals have been interpolated above! */
1685                                 texres->nor[1]= (val1-val3);
1686                                 
1687                                 if(dx<1.0f) {
1688                                         dy= 1.0f-dx;
1689                                         texres->tb= dy*texres->tb+ dx*texr.tb;
1690                                         texres->tg= dy*texres->tg+ dx*texr.tg;
1691                                         texres->tr= dy*texres->tr+ dx*texr.tr;
1692                                         texres->ta= dy*texres->ta+ dx*texr.ta;
1693                                 }
1694                         }
1695                         texres->nor[0]*= bumpscale;
1696                         texres->nor[1]*= bumpscale;
1697                 }
1698                 else {
1699                         maxx= fx+minx;
1700                         minx= fx-minx;
1701                         maxy= fy+miny;
1702                         miny= fy-miny;
1703
1704                         boxsample(curibuf, minx, miny, maxx, maxy, texres, imaprepeat, imapextend, 0);
1705
1706                         if(previbuf!=curibuf) {  /* interpolate */
1707                                 boxsample(previbuf, minx, miny, maxx, maxy, &texr, imaprepeat, imapextend, 0);
1708                                 
1709                                 fx= 2.0f*(pixsize-maxd)/pixsize;
1710                                 
1711                                 if(fx>=1.0) {
1712                                         texres->ta= texr.ta; texres->tb= texr.tb;
1713                                         texres->tg= texr.tg; texres->tr= texr.tr;
1714                                 } else {
1715                                         fy= 1.0f-fx;
1716                                         texres->tb= fy*texres->tb+ fx*texr.tb;
1717                                         texres->tg= fy*texres->tg+ fx*texr.tg;
1718                                         texres->tr= fy*texres->tr+ fx*texr.tr;
1719                                         texres->ta= fy*texres->ta+ fx*texr.ta;
1720                                 }
1721                         }
1722                 }
1723         }
1724         else {
1725                 const int intpol = tex->imaflag & TEX_INTERPOL;
1726                 if (intpol) {
1727                         /* sample 1 pixel minimum */
1728                         if (minx < 0.5f / ibuf->x) minx = 0.5f / ibuf->x;
1729                         if (miny < 0.5f / ibuf->y) miny = 0.5f / ibuf->y;
1730                 }
1731
1732                 if(texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) {
1733                         boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend, 0);
1734                         val1= texres->tr+texres->tg+texres->tb;
1735                         boxsample(ibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend, 0);
1736                         val2= texr.tr + texr.tg + texr.tb;
1737                         boxsample(ibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend, 0);
1738                         val3= texr.tr + texr.tg + texr.tb;
1739
1740                         /* don't switch x or y! */
1741                         texres->nor[0]= (val1-val2);
1742                         texres->nor[1]= (val1-val3);
1743                 }
1744                 else
1745                         boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend, 0);
1746         }
1747         
1748         BRICONTRGB;
1749         
1750         if(tex->imaflag & TEX_CALCALPHA) {
1751                 texres->ta= texres->tin= texres->ta*MAX3(texres->tr, texres->tg, texres->tb);
1752         }
1753         else texres->tin= texres->ta;
1754
1755         if(tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta;
1756         
1757         if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
1758                 ibuf->rect-= (ibuf->x*ibuf->y);
1759         }
1760
1761         if(texres->nor && (tex->imaflag & TEX_NORMALMAP)) {
1762                 // qdn: normal from color
1763                 texres->nor[0] = 2.f*(texres->tr - 0.5f);
1764                 texres->nor[1] = 2.f*(0.5f - texres->tg);
1765                 texres->nor[2] = 2.f*(texres->tb - 0.5f);
1766         }
1767         
1768         /* de-premul, this is being premulled in shade_input_do_shade() */
1769         if(texres->ta!=1.0f && texres->ta>FLT_EPSILON) {
1770                 fx= 1.0f/texres->ta;
1771                 texres->tr*= fx;
1772                 texres->tg*= fx;
1773                 texres->tb*= fx;
1774         }
1775
1776         return retval;
1777 }