Bugfix #3463
[blender.git] / source / blender / render / intern / source / imagetexture.c
1 /**
2  *
3  * $Id:
4  *
5  * ***** BEGIN GPL/BL DUAL 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. The Blender
11  * Foundation also sells licenses for use in proprietary software under
12  * the Blender License.  See http://www.blender.org/BL/ for information
13  * about this.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  *
24  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
25  * All rights reserved.
26  *
27  * The Original Code is: all of this file.
28  *
29  * Contributor(s): none yet.
30  *
31  * ***** END GPL/BL DUAL LICENSE BLOCK *****
32  */
33
34
35
36 #include <stdio.h>
37 #include <string.h>
38 #include <fcntl.h>
39 #include <math.h>
40 #ifndef WIN32 
41 #include <unistd.h>
42 #else
43 #include <io.h>
44 #endif
45
46 #include "MEM_guardedalloc.h"
47
48 #include "IMB_imbuf_types.h"
49 #include "IMB_imbuf.h"
50
51 #include "DNA_image_types.h"
52 #include "DNA_scene_types.h"
53 #include "DNA_texture_types.h"
54
55 #include "BLI_blenlib.h"
56
57 #include "BKE_utildefines.h"
58 #include "BKE_global.h"
59 #include "BKE_main.h"
60 #include "BKE_image.h"
61 #include "BKE_texture.h"
62 #include "BKE_library.h"
63
64 #include "SDL_thread.h"
65
66 #include "render.h"
67 #include "texture.h"
68
69
70 int imaprepeat, imapextend;
71
72
73 /* *********** IMAGEWRAPPING ****************** */
74
75
76 int imagewrap(Tex *tex, Image *ima, float *texvec, TexResult *texres)
77 {
78         struct ImBuf *ibuf;
79         float fx, fy, val1, val2, val3;
80         int ofs, x, y;
81         char *rect;
82
83         texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0;
84
85         if(ima==NULL || ima->ok== 0) {
86                 return 0;
87         }
88         
89         if(ima->ibuf==NULL) {
90                 extern SDL_mutex *load_ibuf_lock; // initrender.c
91                 if(load_ibuf_lock) SDL_mutexP(load_ibuf_lock);
92                 if(ima->ibuf==NULL) ima_ibuf_is_nul(tex, ima);
93                 if(load_ibuf_lock) SDL_mutexV(load_ibuf_lock);
94         }
95
96         if (ima->ok) {
97                 ibuf = ima->ibuf;
98
99                 if(tex->imaflag & TEX_IMAROT) {
100                         fy= texvec[0];
101                         fx= texvec[1];
102                 }
103                 else {
104                         fx= texvec[0];
105                         fy= texvec[1];
106                 }
107                 
108                 if(tex->extend == TEX_CHECKER) {
109                         int xs, ys;
110                         
111                         xs= (int)floor(fx);
112                         ys= (int)floor(fy);
113                         fx-= xs;
114                         fy-= ys;
115
116                         if( (tex->flag & TEX_CHECKER_ODD)==0) {
117                                 if((xs+ys) & 1);else return 0;
118                         }
119                         if( (tex->flag & TEX_CHECKER_EVEN)==0) {
120                                 if((xs+ys) & 1) return 0; 
121                         }
122                         /* scale around center, (0.5, 0.5) */
123                         if(tex->checkerdist<1.0) {
124                                 fx= (fx-0.5)/(1.0-tex->checkerdist) +0.5;
125                                 fy= (fy-0.5)/(1.0-tex->checkerdist) +0.5;
126                         }
127                 }
128
129                 x = (int)(fx*ibuf->x);
130                 y = (int)(fy*ibuf->y);
131
132                 if(tex->extend == TEX_CLIPCUBE) {
133                         if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0 || texvec[2]>1.0) {
134                                 return 0;
135                         }
136                 }
137                 else if( tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
138                         if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) {
139                                 return 0;
140                         }
141                 }
142                 else {
143                         if(tex->extend==TEX_EXTEND) {
144                                 if(x>=ibuf->x) x = ibuf->x-1;
145                                 else if(x<0) x= 0;
146                         }
147                         else {
148                                 x= x % ibuf->x;
149                                 if(x<0) x+= ibuf->x;
150                         }
151                         if(tex->extend==TEX_EXTEND) {
152                                 if(y>=ibuf->y) y = ibuf->y-1;
153                                 else if(y<0) y= 0;
154                         }
155                         else {
156                                 y= y % ibuf->y;
157                                 if(y<0) y+= ibuf->y;
158                         }
159                 }
160                 
161                 /* warning, no return before setting back! */
162                 if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
163                         ibuf->rect+= (ibuf->x*ibuf->y);
164                 }
165
166                 ofs = y * ibuf->x + x;
167                 rect = (char *)( ibuf->rect+ ofs);
168
169                 if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
170                         ibuf->rect-= (ibuf->x*ibuf->y);
171                 }
172
173                 if(tex->imaflag & TEX_USEALPHA) {
174                         if(tex->imaflag & TEX_CALCALPHA);
175                         else texres->talpha= 1;
176                 }
177
178                 texres->tr = ((float)rect[0])/255.0f;
179                 texres->tg = ((float)rect[1])/255.0f;
180                 texres->tb = ((float)rect[2])/255.0f;
181                 
182                 if(texres->nor) {
183                         if(tex->imaflag & TEX_NORMALMAP) {
184                                 texres->nor[0]= 0.5-texres->tr;
185                                 texres->nor[1]= 0.5-texres->tg;
186                                 texres->nor[2]= -texres->tb;
187                         }
188                         else {
189                                 /* bump: take three samples */
190                                 val1= texres->tr+texres->tg+texres->tb;
191
192                                 if(x<ibuf->x-1) {
193                                         rect+=4;
194                                         val2= ((float)(rect[0]+rect[1]+rect[2]))/255.0f;
195                                         rect-=4;
196                                 }
197                                 else val2= val1;
198
199                                 if(y<ibuf->y-1) {
200                                         rect+= 4*ibuf->x;
201                                         val3= ((float)(rect[0]+rect[1]+rect[2]))/255.0f;
202                                 }
203                                 else val3= val1;
204
205                                 /* do not mix up x and y here! */
206                                 texres->nor[0]= (val1-val2);
207                                 texres->nor[1]= (val1-val3);
208                         }
209                 }
210
211                 BRICONTRGB;
212
213                 if(texres->talpha) texres->ta= texres->tin= ((float)rect[3])/255.0f;
214                 else if(tex->imaflag & TEX_CALCALPHA) {
215                         texres->ta= texres->tin= MAX3(texres->tr, texres->tg, texres->tb);
216                 }
217                 else texres->ta= texres->tin= 1.0;
218                 
219                 if(tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta;
220
221         }
222
223         if(texres->nor) return 3;
224         else return 1;
225 }
226
227 static void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2)
228 {
229         rctf *rf, *newrct;
230         short a;
231
232         a= *count;
233         rf= stack;
234         for(;a>0;a--) {
235                 if(rf->xmin<x1) {
236                         if(rf->xmax<x1) {
237                                 rf->xmin+= (x2-x1);
238                                 rf->xmax+= (x2-x1);
239                         }
240                         else {
241                                 if(rf->xmax>x2) rf->xmax= x2;
242                                 newrct= stack+ *count;
243                                 (*count)++;
244
245                                 newrct->xmax= x2;
246                                 newrct->xmin= rf->xmin+(x2-x1);
247                                 newrct->ymin= rf->ymin;
248                                 newrct->ymax= rf->ymax;
249                                 
250                                 if(newrct->xmin==newrct->xmax) (*count)--;
251                                 
252                                 rf->xmin= x1;
253                         }
254                 }
255                 else if(rf->xmax>x2) {
256                         if(rf->xmin>x2) {
257                                 rf->xmin-= (x2-x1);
258                                 rf->xmax-= (x2-x1);
259                         }
260                         else {
261                                 if(rf->xmin<x1) rf->xmin= x1;
262                                 newrct= stack+ *count;
263                                 (*count)++;
264
265                                 newrct->xmin= x1;
266                                 newrct->xmax= rf->xmax-(x2-x1);
267                                 newrct->ymin= rf->ymin;
268                                 newrct->ymax= rf->ymax;
269
270                                 if(newrct->xmin==newrct->xmax) (*count)--;
271
272                                 rf->xmax= x2;
273                         }
274                 }
275                 rf++;
276         }
277
278 }
279
280 static void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2)
281 {
282         rctf *rf, *newrct;
283         short a;
284
285         a= *count;
286         rf= stack;
287         for(;a>0;a--) {
288                 if(rf->ymin<y1) {
289                         if(rf->ymax<y1) {
290                                 rf->ymin+= (y2-y1);
291                                 rf->ymax+= (y2-y1);
292                         }
293                         else {
294                                 if(rf->ymax>y2) rf->ymax= y2;
295                                 newrct= stack+ *count;
296                                 (*count)++;
297
298                                 newrct->ymax= y2;
299                                 newrct->ymin= rf->ymin+(y2-y1);
300                                 newrct->xmin= rf->xmin;
301                                 newrct->xmax= rf->xmax;
302
303                                 if(newrct->ymin==newrct->ymax) (*count)--;
304
305                                 rf->ymin= y1;
306                         }
307                 }
308                 else if(rf->ymax>y2) {
309                         if(rf->ymin>y2) {
310                                 rf->ymin-= (y2-y1);
311                                 rf->ymax-= (y2-y1);
312                         }
313                         else {
314                                 if(rf->ymin<y1) rf->ymin= y1;
315                                 newrct= stack+ *count;
316                                 (*count)++;
317
318                                 newrct->ymin= y1;
319                                 newrct->ymax= rf->ymax-(y2-y1);
320                                 newrct->xmin= rf->xmin;
321                                 newrct->xmax= rf->xmax;
322
323                                 if(newrct->ymin==newrct->ymax) (*count)--;
324
325                                 rf->ymax= y2;
326                         }
327                 }
328                 rf++;
329         }
330 }
331
332 static float square_rctf(rctf *rf)
333 {
334         float x, y;
335
336         x= rf->xmax- rf->xmin;
337         y= rf->ymax- rf->ymin;
338         return (x*y);
339 }
340
341 static float clipx_rctf(rctf *rf, float x1, float x2)
342 {
343         float size;
344
345         size= rf->xmax - rf->xmin;
346
347         if(rf->xmin<x1) {
348                 rf->xmin= x1;
349         }
350         if(rf->xmax>x2) {
351                 rf->xmax= x2;
352         }
353         if(rf->xmin > rf->xmax) {
354                 rf->xmin = rf->xmax;
355                 return 0.0;
356         }
357         else if(size!=0.0) {
358                 return (rf->xmax - rf->xmin)/size;
359         }
360         return 1.0;
361 }
362
363 static float clipy_rctf(rctf *rf, float y1, float y2)
364 {
365         float size;
366
367         size= rf->ymax - rf->ymin;
368
369         if(rf->ymin<y1) {
370                 rf->ymin= y1;
371         }
372         if(rf->ymax>y2) {
373                 rf->ymax= y2;
374         }
375
376         if(rf->ymin > rf->ymax) {
377                 rf->ymin = rf->ymax;
378                 return 0.0;
379         }
380         else if(size!=0.0) {
381                 return (rf->ymax - rf->ymin)/size;
382         }
383         return 1.0;
384
385 }
386
387 static void boxsampleclip(struct ImBuf *ibuf, rctf *rf, TexResult *texres)
388 {
389         /* sample box, is clipped already, and minx etc. have been set at ibuf size.
390        Enlarge with antialiased edges of the pixels */
391
392         float muly,mulx,div;
393         int ofs;
394         int x, y, startx, endx, starty, endy;
395         char *rect;
396
397         startx= (int)floor(rf->xmin);
398         endx= (int)floor(rf->xmax);
399         starty= (int)floor(rf->ymin);
400         endy= (int)floor(rf->ymax);
401
402         if(startx < 0) startx= 0;
403         if(starty < 0) starty= 0;
404         if(endx>=ibuf->x) endx= ibuf->x-1;
405         if(endy>=ibuf->y) endy= ibuf->y-1;
406
407         if(starty==endy && startx==endx) {
408
409                 ofs = starty*ibuf->x + startx;
410                 rect = (char *)(ibuf->rect +ofs);
411                 texres->tr= ((float)rect[0])/255.0f;
412                 texres->tg= ((float)rect[1])/255.0f;
413                 texres->tb= ((float)rect[2])/255.0f;
414                         /* alpha has been set in function imagewraposa() */
415                 if(texres->talpha) {
416                         texres->ta= ((float)rect[3])/255.0f;
417                 }
418         }
419         else {
420                 div= texres->tr= texres->tg= texres->tb= texres->ta= 0.0;
421                 for(y=starty;y<=endy;y++) {
422                         ofs = y*ibuf->x +startx;
423                         rect = (char *)(ibuf->rect+ofs);
424
425                         muly= 1.0;
426
427                         if(starty==endy);
428                         else {
429                                 if(y==starty) muly= 1.0f-(rf->ymin - y);
430                                 if(y==endy) muly= (rf->ymax - y);
431                         }
432                         if(startx==endx) {
433                                 mulx= muly;
434                                 if(texres->talpha) texres->ta+= mulx*rect[3];
435                                 texres->tr+= mulx*rect[0];
436                                 texres->tg+= mulx*rect[1];
437                                 texres->tb+= mulx*rect[2];
438                                 div+= mulx;
439                         }
440                         else {
441                                 for(x=startx;x<=endx;x++) {
442                                         mulx= muly;
443                                         if(x==startx) mulx*= 1.0f-(rf->xmin - x);
444                                         if(x==endx) mulx*= (rf->xmax - x);
445
446                                         if(mulx==1.0) {
447                                                 if(texres->talpha) texres->ta+= rect[3];
448                                                 texres->tr+= rect[0];
449                                                 texres->tg+= rect[1];
450                                                 texres->tb+= rect[2];
451                                                 div+= 1.0;
452                                         }
453                                         else {
454                                                 if(texres->talpha) texres->ta+= mulx*rect[3];
455                                                 texres->tr+= mulx*rect[0];
456                                                 texres->tg+= mulx*rect[1];
457                                                 texres->tb+= mulx*rect[2];
458                                                 div+= mulx;
459                                         }
460                                         rect+=4;
461                                 }
462                         }
463                 }
464                 if(div!=0.0) {
465                         div*= 255.0;
466         
467                         texres->tb/= div;
468                         texres->tg/= div;
469                         texres->tr/= div;
470                         
471                         if(texres->talpha) texres->ta/= div;
472                 }
473                 else {
474                         texres->tr= texres->tg= texres->tb= texres->ta= 0.0;
475                 }
476         }
477 }
478
479 static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, TexResult *texres)
480 {
481         /* Sample box, performs clip. minx etc are in range 0.0 - 1.0 .
482      * Enlarge with antialiased edges of pixels.
483      * If global variable 'imaprepeat' has been set, the
484      *  clipped-away parts are sampled as well.
485      */
486         /* note: actually minx etc isnt in the proper range... this due to filter size and offset vectors for bump */
487         TexResult texr;
488         rctf *rf, stack[8];
489         float opp, tot, alphaclip= 1.0;
490         short count=1;
491
492         rf= stack;
493         rf->xmin= minx*(ibuf->x);
494         rf->xmax= maxx*(ibuf->x);
495         rf->ymin= miny*(ibuf->y);
496         rf->ymax= maxy*(ibuf->y);
497
498         if(imapextend) {
499                 CLAMP(rf->xmin, 0.0f, ibuf->x-1);
500                 CLAMP(rf->xmax, 0.0f, ibuf->x-1);
501         }
502         else if(imaprepeat) clipx_rctf_swap(stack, &count, 0.0, (float)(ibuf->x));
503         else {
504                 alphaclip= clipx_rctf(rf, 0.0, (float)(ibuf->x));
505
506                 if(alphaclip<=0.0) {
507                         texres->tr= texres->tb= texres->tg= texres->ta= 0.0;
508                         return;
509                 }
510         }
511
512         if(imapextend) {
513                 CLAMP(rf->ymin, 0.0f, ibuf->y-1);
514                 CLAMP(rf->ymax, 0.0f, ibuf->y-1);
515         }
516         else if(imaprepeat) clipy_rctf_swap(stack, &count, 0.0, (float)(ibuf->y));
517         else {
518                 alphaclip*= clipy_rctf(rf, 0.0, (float)(ibuf->y));
519
520                 if(alphaclip<=0.0) {
521                         texres->tr= texres->tb= texres->tg= texres->ta= 0.0;
522                         return;
523                 }
524         }
525
526         if(count>1) {
527                 tot= texres->tr= texres->tb= texres->tg= texres->ta= 0.0;
528                 while(count--) {
529                         boxsampleclip(ibuf, rf, &texr);
530                         
531                         opp= square_rctf(rf);
532                         tot+= opp;
533
534                         texres->tr+= opp*texr.tr;
535                         texres->tg+= opp*texr.tg;
536                         texres->tb+= opp*texr.tb;
537                         if(texres->talpha) texres->ta+= opp*texr.ta;
538                         rf++;
539                 }
540                 if(tot!= 0.0) {
541                         texres->tr/= tot;
542                         texres->tg/= tot;
543                         texres->tb/= tot;
544                         if(texres->talpha) texres->ta/= tot;
545                 }
546         }
547         else {
548                 boxsampleclip(ibuf, rf, texres);
549         }
550
551         if(texres->talpha==0) texres->ta= 1.0;
552         
553         if(alphaclip!=1.0) {
554                 /* this is for laetr investigation, premul or not? */
555                 /* texres->tr*= alphaclip; */
556                 /* texres->tg*= alphaclip; */
557                 /* texres->tb*= alphaclip; */
558                 texres->ta*= alphaclip;
559         }
560 }       
561
562 static void makemipmap(Image *ima)
563 {
564         struct ImBuf *ibuf;
565         int minsize, curmap=0;
566         
567         ibuf= ima->ibuf;
568         minsize= MIN2(ibuf->x, ibuf->y);
569         
570         while(minsize>3 && curmap<BLI_ARRAY_NELEMS(ima->mipmap)) {
571                 
572                 ibuf= IMB_dupImBuf(ibuf);
573                 IMB_filter(ibuf);
574                 ima->mipmap[curmap]= (struct ImBuf *)IMB_onehalf(ibuf);
575                 IMB_freeImBuf(ibuf);
576                 ibuf= ima->mipmap[curmap];
577                 
578                 curmap++;
579                 minsize= MIN2(ibuf->x, ibuf->y);
580         }
581 }
582
583
584 int imagewraposa(Tex *tex, Image *ima, float *texvec, float *dxt, float *dyt, TexResult *texres)
585 {
586         extern SDL_mutex *load_ibuf_lock; // initrender.c
587         TexResult texr;
588         ImBuf *ibuf, *previbuf;
589         float fx, fy, minx, maxx, miny, maxy, dx, dy;
590         float maxd, pixsize, val1, val2, val3;
591         int curmap;
592
593         texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0;
594
595         if(ima==NULL || ima->ok== 0) {
596                 return 0;
597         }
598         
599         if(ima->ibuf==NULL) {
600                 if(load_ibuf_lock) SDL_mutexP(load_ibuf_lock);
601                 if(ima->ibuf==NULL) ima_ibuf_is_nul(tex, ima);
602                 if(load_ibuf_lock) SDL_mutexV(load_ibuf_lock);
603         }
604         
605         if (ima->ok) {
606         
607                 if(tex->imaflag & TEX_MIPMAP) {
608                         if(ima->mipmap[0]==NULL) {
609                                 if(load_ibuf_lock) SDL_mutexP(load_ibuf_lock);
610                                 if(ima->mipmap[0]==NULL) makemipmap(ima);
611                                 if(load_ibuf_lock) SDL_mutexV(load_ibuf_lock);
612                         }
613                 }
614         
615                 ibuf = ima->ibuf;
616                 
617                 if(tex->imaflag & TEX_USEALPHA) {
618                         if(tex->imaflag & TEX_CALCALPHA);
619                         else texres->talpha= 1;
620                 }
621                 
622                 texr.talpha= texres->talpha;
623                 
624                 if(tex->imaflag & TEX_IMAROT) {
625                         fy= texvec[0];
626                         fx= texvec[1];
627                 }
628                 else {
629                         fx= texvec[0];
630                         fy= texvec[1];
631                 }
632                 
633                 if(ibuf->flags & IB_fields) {
634                         if(R.r.mode & R_FIELDS) {                       /* field render */
635                                 if(R.flag & R_SEC_FIELD) {              /* correction for 2nd field */
636                                         /* fac1= 0.5/( (float)ibuf->y ); */
637                                         /* fy-= fac1; */
638                                 }
639                                 else {                          /* first field */
640                                         fy+= 0.5f/( (float)ibuf->y );
641                                 }
642                         }
643                 }
644                 
645                 /* pixel coordinates */
646
647                 minx= MIN3(dxt[0],dyt[0],dxt[0]+dyt[0] );
648                 maxx= MAX3(dxt[0],dyt[0],dxt[0]+dyt[0] );
649                 miny= MIN3(dxt[1],dyt[1],dxt[1]+dyt[1] );
650                 maxy= MAX3(dxt[1],dyt[1],dxt[1]+dyt[1] );
651
652                 /* tex_sharper has been removed */
653                 minx= tex->filtersize*(maxx-minx)/2.0f;
654                 miny= tex->filtersize*(maxy-miny)/2.0f;
655                 
656                 if(tex->filtersize!=1.0f) {
657                         dxt[0]*= tex->filtersize;
658                         dxt[1]*= tex->filtersize;
659                         dyt[0]*= tex->filtersize;
660                         dyt[1]*= tex->filtersize;
661                 }
662
663                 if(tex->imaflag & TEX_IMAROT) SWAP(float, minx, miny);
664                 
665                 if(minx>0.25) minx= 0.25;
666                 else if(minx<0.00001f) minx= 0.00001f;  /* side faces of unit-cube */
667                 if(miny>0.25) miny= 0.25;
668                 else if(miny<0.00001f) miny= 0.00001f;
669
670                 
671                 /* repeat and clip */
672                 
673                 /* watch it: imaprepeat is global value (see boxsample) */
674                 imaprepeat= (tex->extend==TEX_REPEAT);
675                 imapextend= (tex->extend==TEX_EXTEND);
676
677                 if(tex->extend == TEX_CHECKER) {
678                         int xs, ys, xs1, ys1, xs2, ys2, boundary;
679                         
680                         xs= (int)floor(fx);
681                         ys= (int)floor(fy);
682                         
683                         // both checkers available, no boundary exceptions, checkerdist will eat aliasing
684                         if( (tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN) ) {
685                                 fx-= xs;
686                                 fy-= ys;
687                         }
688                         else {
689                                 
690                                 xs1= (int)floor(fx-minx);
691                                 ys1= (int)floor(fy-miny);
692                                 xs2= (int)floor(fx+minx);
693                                 ys2= (int)floor(fy+miny);
694                                 boundary= (xs1!=xs2) || (ys1!=ys2);
695         
696                                 if(boundary==0) {
697                                         if( (tex->flag & TEX_CHECKER_ODD)==0) {
698                                                 if((xs+ys) & 1); 
699                                                 else return 0;
700                                         }
701                                         if( (tex->flag & TEX_CHECKER_EVEN)==0) {
702                                                 if((xs+ys) & 1) return 0;
703                                         }
704                                         fx-= xs;
705                                         fy-= ys;
706                                 }
707                                 else {
708                                         if(tex->flag & TEX_CHECKER_ODD) {
709                                                 if((xs1+ys) & 1) fx-= xs2;
710                                                 else fx-= xs1;
711                                                 
712                                                 if((ys1+xs) & 1) fy-= ys2;
713                                                 else fy-= ys1;
714                                         }
715                                         if(tex->flag & TEX_CHECKER_EVEN) {
716                                                 if((xs1+ys) & 1) fx-= xs1;
717                                                 else fx-= xs2;
718                                                 
719                                                 if((ys1+xs) & 1) fy-= ys1;
720                                                 else fy-= ys2;
721                                         }
722                                 }
723                         }
724
725                         /* scale around center, (0.5, 0.5) */
726                         if(tex->checkerdist<1.0) {
727                                 fx= (fx-0.5)/(1.0-tex->checkerdist) +0.5;
728                                 fy= (fy-0.5)/(1.0-tex->checkerdist) +0.5;
729                                 minx/= (1.0-tex->checkerdist);
730                                 miny/= (1.0-tex->checkerdist);
731                         }
732                 }
733
734                 if(tex->extend == TEX_CLIPCUBE) {
735                         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) {
736                                 return 0;
737                         }
738                 }
739                 else if(tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
740                         if(fx+minx<0.0 || fy+miny<0.0 || fx-minx>1.0 || fy-miny>1.0) {
741                                 return 0;
742                         }
743                 }
744                 else {
745                         if(tex->extend==TEX_EXTEND) {
746                                 if(fx>1.0) fx = 1.0;
747                                 else if(fx<0.0) fx= 0.0;
748                         }
749                         else {
750                                 if(fx>1.0) fx -= (int)(fx);
751                                 else if(fx<0.0) fx+= 1-(int)(fx);
752                         }
753                         
754                         if(tex->extend==TEX_EXTEND) {
755                                 if(fy>1.0) fy = 1.0;
756                                 else if(fy<0.0) fy= 0.0;
757                         }
758                         else {
759                                 if(fy>1.0) fy -= (int)(fy);
760                                 else if(fy<0.0) fy+= 1-(int)(fy);
761                         }
762                 }
763         
764                 /* warning no return! */
765                 if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
766                         ibuf->rect+= (ibuf->x*ibuf->y);
767                 }
768
769                 /* choice:  */
770                 if(tex->imaflag & TEX_MIPMAP) {
771                         
772                         dx= minx;
773                         dy= miny;
774                         maxd= MAX2(dx, dy);
775                         if(maxd>0.5) maxd= 0.5;
776
777                         pixsize = 1.0f/ (float) MIN2(ibuf->x, ibuf->y);
778                         
779                         curmap= 0;
780                         previbuf= ibuf;
781                         while(curmap<BLI_ARRAY_NELEMS(ima->mipmap) && ima->mipmap[curmap]) {
782                                 if(maxd < pixsize) break;
783                                 previbuf= ibuf;
784                                 ibuf= ima->mipmap[curmap];
785                                 pixsize= 1.0f / (float)MIN2(ibuf->x, ibuf->y); /* this used to be 1.0 */                
786                                 curmap++;
787                         }
788                         
789                         if(previbuf!=ibuf || (tex->imaflag & TEX_INTERPOL)) {
790                                 /* sample at least 1 pixel */
791                                 if (minx < 0.5f / ima->ibuf->x) minx = 0.5f / ima->ibuf->x;
792                                 if (miny < 0.5f / ima->ibuf->y) miny = 0.5f / ima->ibuf->y;
793                         }
794                         
795                         if(texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) {
796                                 /* a bit extra filter */
797                                 //minx*= 1.35f;
798                                 //miny*= 1.35f;
799                                 
800                                 boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres);
801                                 val1= texres->tr+texres->tg+texres->tb;
802                                 boxsample(ibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr);
803                                 val2= texr.tr + texr.tg + texr.tb;
804                                 boxsample(ibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr);
805                                 val3= texr.tr + texr.tg + texr.tb;
806         
807                                 if(previbuf!=ibuf) {  /* interpolate */
808                                         
809                                         boxsample(previbuf, fx-2.0f*minx, fy-2.0f*miny, fx+minx, fy+miny, &texr);
810                                         
811                                         /* calc rgb */
812                                         dx= 2.0f*(pixsize-maxd)/pixsize;
813                                         if(dx>=1.0f) {
814                                                 texres->ta= texr.ta; texres->tb= texr.tb;
815                                                 texres->tg= texr.tg; texres->tr= texr.tr;
816                                         }
817                                         else {
818                                                 dy= 1.0f-dx;
819                                                 texres->tb= dy*texres->tb+ dx*texr.tb;
820                                                 texres->tg= dy*texres->tg+ dx*texr.tg;
821                                                 texres->tr= dy*texres->tr+ dx*texr.tr;
822                                                 texres->ta= dy*texres->ta+ dx*texr.ta;
823                                         }
824                                         
825                                         val1= dy*val1+ dx*(texr.tr + texr.tg + texr.tb);
826                                         boxsample(previbuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr);
827                                         val2= dy*val2+ dx*(texr.tr + texr.tg + texr.tb);
828                                         boxsample(previbuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr);
829                                         val3= dy*val3+ dx*(texr.tr + texr.tg + texr.tb);
830                                 }
831
832                                 /* don't switch x or y! */
833                                 texres->nor[0]= (val1-val2);
834                                 texres->nor[1]= (val1-val3);
835                         }
836                         else {
837                                 maxx= fx+minx;
838                                 minx= fx-minx;
839                                 maxy= fy+miny;
840                                 miny= fy-miny;
841         
842                                 boxsample(ibuf, minx, miny, maxx, maxy, texres);
843         
844                                 if(previbuf!=ibuf) {  /* interpolate */
845                                         boxsample(previbuf, minx, miny, maxx, maxy, &texr);
846                                         
847                                         fx= 2.0f*(pixsize-maxd)/pixsize;
848                                         
849                                         if(fx>=1.0) {
850                                                 texres->ta= texr.ta; texres->tb= texr.tb;
851                                                 texres->tg= texr.tg; texres->tr= texr.tr;
852                                         } else {
853                                                 fy= 1.0f-fx;
854                                                 texres->tb= fy*texres->tb+ fx*texr.tb;
855                                                 texres->tg= fy*texres->tg+ fx*texr.tg;
856                                                 texres->tr= fy*texres->tr+ fx*texr.tr;
857                                                 texres->ta= fy*texres->ta+ fx*texr.ta;
858                                         }
859                                 }
860                         }
861                 }
862                 else {
863                         if((tex->imaflag & TEX_INTERPOL)) {
864                                 /* sample 1 pixel minimum */
865                                 if (minx < 0.5f / ima->ibuf->x) minx = 0.5f / ima->ibuf->x;
866                                 if (miny < 0.5f / ima->ibuf->y) miny = 0.5f / ima->ibuf->y;
867                         }
868
869                         if(texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) {
870                                 
871                                 /* a bit extra filter */
872                                 //minx*= 1.35f;
873                                 //miny*= 1.35f;
874                                 
875                                 boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres);
876                                 val1= texres->tr+texres->tg+texres->tb;
877                                 boxsample(ibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr);
878                                 val2= texr.tr + texr.tg + texr.tb;
879                                 boxsample(ibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr);
880                                 val3= texr.tr + texr.tg + texr.tb;
881                                 /* don't switch x or y! */
882                                 texres->nor[0]= (val1-val2);
883                                 texres->nor[1]= (val1-val3);
884                         }
885                         else {
886                                 boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres);
887                         }
888                 }
889                 
890                 BRICONTRGB;
891                 
892                 if(tex->imaflag & TEX_CALCALPHA) {
893                         texres->ta= texres->tin= texres->ta*MAX3(texres->tr, texres->tg, texres->tb);
894                 }
895                 else texres->tin= texres->ta;
896
897                 if(tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta;
898                 
899                 if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
900                         ibuf->rect-= (ibuf->x*ibuf->y);
901                 }
902
903                 if(texres->nor && (tex->imaflag & TEX_NORMALMAP)) {
904                         texres->nor[0]= 0.5-texres->tr;
905                         texres->nor[1]= 0.5-texres->tg;
906                         texres->nor[2]= -texres->tb;
907                 }
908         }
909         else {
910                 texres->tin= 0.0f;
911                 return 0;
912         }
913         
914         if(texres->nor) return 3;
915         else return 1;
916 }