Blender V2.61 - r43446

zbuf.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * Contributors: Hos, RPW
00022  *               2004-2006 Blender Foundation, full recode
00023  *
00024  * ***** END GPL LICENSE BLOCK *****
00025  */
00026 
00033 /*---------------------------------------------------------------------------*/
00034 /* Common includes                                                           */
00035 /*---------------------------------------------------------------------------*/
00036 
00037 #include <math.h>
00038 #include <float.h>
00039 #include <stdlib.h>
00040 #include <limits.h>
00041 #include <string.h>
00042 
00043 #include "BLI_math.h"
00044 #include "BLI_blenlib.h"
00045 #include "BLI_jitter.h"
00046 #include "BLI_threads.h"
00047 #include "BLI_utildefines.h"
00048 
00049 #include "MEM_guardedalloc.h"
00050 
00051 #include "DNA_lamp_types.h"
00052 #include "DNA_mesh_types.h"
00053 #include "DNA_node_types.h"
00054 #include "DNA_meshdata_types.h"
00055 #include "DNA_material_types.h"
00056 
00057 #include "BKE_global.h"
00058 #include "BKE_material.h"
00059 
00060 
00061 #include "RE_render_ext.h"
00062 
00063 /* local includes */
00064 #include "gammaCorrectionTables.h"
00065 #include "pixelblending.h"
00066 #include "render_result.h"
00067 #include "render_types.h"
00068 #include "renderpipeline.h"
00069 #include "renderdatabase.h"
00070 #include "rendercore.h"
00071 #include "shadbuf.h"
00072 #include "shading.h"
00073 #include "sss.h"
00074 #include "strand.h"
00075 
00076 /* own includes */
00077 #include "zbuf.h"
00078 
00079 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
00080 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
00081 /* only to be used here in this file, it's for speed */
00082 extern struct Render R;
00083 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
00084 
00085 
00086 /* ****************** Spans ******************************* */
00087 
00088 /* each zbuffer has coordinates transformed to local rect coordinates, so we can simply clip */
00089 void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty, float clipcrop)
00090 {
00091     memset(zspan, 0, sizeof(ZSpan));
00092     
00093     zspan->rectx= rectx;
00094     zspan->recty= recty;
00095     
00096     zspan->span1= MEM_mallocN(recty*sizeof(float), "zspan");
00097     zspan->span2= MEM_mallocN(recty*sizeof(float), "zspan");
00098 
00099     zspan->clipcrop= clipcrop;
00100 }
00101 
00102 void zbuf_free_span(ZSpan *zspan)
00103 {
00104     if(zspan) {
00105         if(zspan->span1) MEM_freeN(zspan->span1);
00106         if(zspan->span2) MEM_freeN(zspan->span2);
00107         zspan->span1= zspan->span2= NULL;
00108     }
00109 }
00110 
00111 /* reset range for clipping */
00112 static void zbuf_init_span(ZSpan *zspan)
00113 {
00114     zspan->miny1= zspan->miny2= zspan->recty+1;
00115     zspan->maxy1= zspan->maxy2= -1;
00116     zspan->minp1= zspan->maxp1= zspan->minp2= zspan->maxp2= NULL;
00117 }
00118 
00119 static void zbuf_add_to_span(ZSpan *zspan, float *v1, float *v2)
00120 {
00121     float *minv, *maxv, *span;
00122     float xx1, dx0, xs0;
00123     int y, my0, my2;
00124     
00125     if(v1[1]<v2[1]) {
00126         minv= v1; maxv= v2;
00127     }
00128     else {
00129         minv= v2; maxv= v1;
00130     }
00131     
00132     my0= ceil(minv[1]);
00133     my2= floor(maxv[1]);
00134     
00135     if(my2<0 || my0>= zspan->recty) return;
00136     
00137     /* clip top */
00138     if(my2>=zspan->recty) my2= zspan->recty-1;
00139     /* clip bottom */
00140     if(my0<0) my0= 0;
00141     
00142     if(my0>my2) return;
00143     /* if(my0>my2) should still fill in, that way we get spans that skip nicely */
00144     
00145     xx1= maxv[1]-minv[1];
00146     if(xx1>FLT_EPSILON) {
00147         dx0= (minv[0]-maxv[0])/xx1;
00148         xs0= dx0*(minv[1]-my2) + minv[0];
00149     }
00150     else {
00151         dx0= 0.0f;
00152         xs0= MIN2(minv[0],maxv[0]);
00153     }
00154     
00155     /* empty span */
00156     if(zspan->maxp1 == NULL) {
00157         span= zspan->span1;
00158     }
00159     else {  /* does it complete left span? */
00160         if( maxv == zspan->minp1 || minv==zspan->maxp1) {
00161             span= zspan->span1;
00162         }
00163         else {
00164             span= zspan->span2;
00165         }
00166     }
00167 
00168     if(span==zspan->span1) {
00169 //      printf("left span my0 %d my2 %d\n", my0, my2);
00170         if(zspan->minp1==NULL || zspan->minp1[1] > minv[1] ) {
00171             zspan->minp1= minv;
00172         }
00173         if(zspan->maxp1==NULL || zspan->maxp1[1] < maxv[1] ) {
00174             zspan->maxp1= maxv;
00175         }
00176         if(my0<zspan->miny1) zspan->miny1= my0;
00177         if(my2>zspan->maxy1) zspan->maxy1= my2;
00178     }
00179     else {
00180 //      printf("right span my0 %d my2 %d\n", my0, my2);
00181         if(zspan->minp2==NULL || zspan->minp2[1] > minv[1] ) {
00182             zspan->minp2= minv;
00183         }
00184         if(zspan->maxp2==NULL || zspan->maxp2[1] < maxv[1] ) {
00185             zspan->maxp2= maxv;
00186         }
00187         if(my0<zspan->miny2) zspan->miny2= my0;
00188         if(my2>zspan->maxy2) zspan->maxy2= my2;
00189     }
00190 
00191     for(y=my2; y>=my0; y--, xs0+= dx0) {
00192         /* xs0 is the xcoord! */
00193         span[y]= xs0;
00194     }
00195 }
00196 
00197 /*-----------------------------------------------------------*/ 
00198 /* Functions                                                 */
00199 /*-----------------------------------------------------------*/ 
00200 
00201 void fillrect(int *rect, int x, int y, int val)
00202 {
00203     int len, *drect;
00204 
00205     len= x*y;
00206     drect= rect;
00207     while(len>0) {
00208         len--;
00209         *drect= val;
00210         drect++;
00211     }
00212 }
00213 
00214 /* based on Liang&Barsky, for clipping of pyramidical volume */
00215 static short cliptestf(float p, float q, float *u1, float *u2)
00216 {
00217     float r;
00218     
00219     if(p<0.0f) {
00220         if(q<p) return 0;
00221         else if(q<0.0f) {
00222             r= q/p;
00223             if(r>*u2) return 0;
00224             else if(r>*u1) *u1=r;
00225         }
00226     }
00227     else {
00228         if(p>0.0f) {
00229             if(q<0.0f) return 0;
00230             else if(q<p) {
00231                 r= q/p;
00232                 if(r<*u1) return 0;
00233                 else if(r<*u2) *u2=r;
00234             }
00235         }
00236         else if(q<0.0f) return 0;
00237     }
00238     return 1;
00239 }
00240 
00241 int testclip(const float v[4])
00242 {
00243     float abs4; /* WATCH IT: this function should do the same as cliptestf, otherwise troubles in zbufclip()*/
00244     short c=0;
00245     
00246     /* if we set clip flags, the clipping should be at least larger than epsilon. 
00247        prevents issues with vertices lying exact on borders */
00248     abs4= fabs(v[3]) + FLT_EPSILON;
00249     
00250     if( v[0] < -abs4) c+=1;
00251     else if( v[0] > abs4) c+=2;
00252     
00253     if( v[1] > abs4) c+=4;
00254     else if( v[1] < -abs4) c+=8;
00255     
00256     if(v[2] < -abs4) c+=16;         /* this used to be " if(v[2]<0) ", see clippz() */
00257     else if(v[2]> abs4) c+= 32;
00258     
00259     return c;
00260 }
00261 
00262 
00263 
00264 /* *************  ACCUMULATION ZBUF ************ */
00265 
00266 
00267 static APixstr *addpsmainA(ListBase *lb)
00268 {
00269     APixstrMain *psm;
00270 
00271     psm= MEM_mallocN(sizeof(APixstrMain), "addpsmainA");
00272     BLI_addtail(lb, psm);
00273     psm->ps= MEM_callocN(4096*sizeof(APixstr),"pixstr");
00274 
00275     return psm->ps;
00276 }
00277 
00278 void freepsA(ListBase *lb)
00279 {
00280     APixstrMain *psm, *psmnext;
00281 
00282     for(psm= lb->first; psm; psm= psmnext) {
00283         psmnext= psm->next;
00284         if(psm->ps)
00285             MEM_freeN(psm->ps);
00286         MEM_freeN(psm);
00287     }
00288 }
00289 
00290 static APixstr *addpsA(ZSpan *zspan)
00291 {
00292     /* make new PS */
00293     if(zspan->apsmcounter==0) {
00294         zspan->curpstr= addpsmainA(zspan->apsmbase);
00295         zspan->apsmcounter= 4095;
00296     }
00297     else {
00298         zspan->curpstr++;
00299         zspan->apsmcounter--;
00300     }
00301     return zspan->curpstr;
00302 }
00303 
00304 static void zbuffillAc4(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4)
00305 {
00306     APixstr *ap, *apofs, *apn;
00307     double zxd, zyd, zy0, zverg;
00308     float x0,y0,z0;
00309     float x1,y1,z1,x2,y2,z2,xx1;
00310     float *span1, *span2;
00311     int *rz, *rm, x, y;
00312     int sn1, sn2, rectx, *rectzofs, *rectmaskofs, my0, my2, mask;
00313     
00314     /* init */
00315     zbuf_init_span(zspan);
00316     
00317     /* set spans */
00318     zbuf_add_to_span(zspan, v1, v2);
00319     zbuf_add_to_span(zspan, v2, v3);
00320     if(v4) {
00321         zbuf_add_to_span(zspan, v3, v4);
00322         zbuf_add_to_span(zspan, v4, v1);
00323     }
00324     else
00325         zbuf_add_to_span(zspan, v3, v1);
00326     
00327     /* clipped */
00328     if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
00329 
00330     if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
00331     if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
00332     
00333     if(my2<my0) return;
00334     
00335     /* ZBUF DX DY, in floats still */
00336     x1= v1[0]- v2[0];
00337     x2= v2[0]- v3[0];
00338     y1= v1[1]- v2[1];
00339     y2= v2[1]- v3[1];
00340     z1= v1[2]- v2[2];
00341     z2= v2[2]- v3[2];
00342     x0= y1*z2-z1*y2;
00343     y0= z1*x2-x1*z2;
00344     z0= x1*y2-y1*x2;
00345     
00346     if(z0==0.0f) return;
00347     
00348     xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
00349     
00350     zxd= -(double)x0/(double)z0;
00351     zyd= -(double)y0/(double)z0;
00352     zy0= ((double)my2)*zyd + (double)xx1;
00353     
00354     /* start-offset in rect */
00355     rectx= zspan->rectx;
00356     rectzofs= (int *)(zspan->arectz+rectx*(my2));
00357     rectmaskofs= (int *)(zspan->rectmask+rectx*(my2));
00358     apofs= (zspan->apixbuf+ rectx*(my2));
00359     mask= zspan->mask;
00360 
00361     /* correct span */
00362     sn1= (my0 + my2)/2;
00363     if(zspan->span1[sn1] < zspan->span2[sn1]) {
00364         span1= zspan->span1+my2;
00365         span2= zspan->span2+my2;
00366     }
00367     else {
00368         span1= zspan->span2+my2;
00369         span2= zspan->span1+my2;
00370     }
00371     
00372     for(y=my2; y>=my0; y--, span1--, span2--) {
00373         
00374         sn1= floor(*span1);
00375         sn2= floor(*span2);
00376         sn1++; 
00377         
00378         if(sn2>=rectx) sn2= rectx-1;
00379         if(sn1<0) sn1= 0;
00380         
00381         if(sn2>=sn1) {
00382             int intzverg;
00383             
00384             zverg= (double)sn1*zxd + zy0;
00385             rz= rectzofs+sn1;
00386             rm= rectmaskofs+sn1;
00387             ap= apofs+sn1;
00388             x= sn2-sn1;
00389             
00390             zverg-= zspan->polygon_offset;
00391             
00392             while(x>=0) {
00393                 intzverg= (int)CLAMPIS(zverg, INT_MIN, INT_MAX);
00394 
00395                 if( intzverg < *rz) {
00396                     if(!zspan->rectmask || intzverg > *rm) {
00397                         
00398                         apn= ap;
00399                         while(apn) {
00400                             if(apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= intzverg; apn->mask[0]= mask; break; }
00401                             if(apn->p[0]==zvlnr && apn->obi[0]==obi) {apn->mask[0]|= mask; break; }
00402                             if(apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= intzverg; apn->mask[1]= mask; break; }
00403                             if(apn->p[1]==zvlnr && apn->obi[1]==obi) {apn->mask[1]|= mask; break; }
00404                             if(apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= intzverg; apn->mask[2]= mask; break; }
00405                             if(apn->p[2]==zvlnr && apn->obi[2]==obi) {apn->mask[2]|= mask; break; }
00406                             if(apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= intzverg; apn->mask[3]= mask; break; }
00407                             if(apn->p[3]==zvlnr && apn->obi[3]==obi) {apn->mask[3]|= mask; break; }
00408                             if(apn->next==NULL) apn->next= addpsA(zspan);
00409                             apn= apn->next;
00410                         }               
00411                     }
00412                 }
00413                 zverg+= zxd;
00414                 rz++; 
00415                 rm++;
00416                 ap++; 
00417                 x--;
00418             }
00419         }
00420         
00421         zy0-=zyd;
00422         rectzofs-= rectx;
00423         rectmaskofs-= rectx;
00424         apofs-= rectx;
00425     }
00426 }
00427 
00428 
00429 
00430 static void zbuflineAc(ZSpan *zspan, int obi, int zvlnr, float *vec1, float *vec2)
00431 {
00432     APixstr *ap, *apn;
00433     int *rectz, *rectmask;
00434     int start, end, x, y, oldx, oldy, ofs;
00435     int dz, vergz, mask, maxtest=0;
00436     float dx, dy;
00437     float v1[3], v2[3];
00438     
00439     dx= vec2[0]-vec1[0];
00440     dy= vec2[1]-vec1[1];
00441     
00442     mask= zspan->mask;
00443     
00444     if(fabs(dx) > fabs(dy)) {
00445 
00446         /* all lines from left to right */
00447         if(vec1[0]<vec2[0]) {
00448             copy_v3_v3(v1, vec1);
00449             copy_v3_v3(v2, vec2);
00450         }
00451         else {
00452             copy_v3_v3(v2, vec1);
00453             copy_v3_v3(v1, vec2);
00454             dx= -dx; dy= -dy;
00455         }
00456 
00457         start= floor(v1[0]);
00458         end= start+floor(dx);
00459         if(end>=zspan->rectx) end= zspan->rectx-1;
00460         
00461         oldy= floor(v1[1]);
00462         dy/= dx;
00463         
00464         vergz= v1[2];
00465         vergz-= zspan->polygon_offset;
00466         dz= (v2[2]-v1[2])/dx;
00467         if(vergz>0x50000000 && dz>0) maxtest= 1;        // prevent overflow
00468         
00469         rectz= (int *)(zspan->arectz+zspan->rectx*(oldy) +start);
00470         rectmask= (int *)(zspan->rectmask+zspan->rectx*(oldy) +start);
00471         ap= (zspan->apixbuf+ zspan->rectx*(oldy) +start);
00472 
00473         if(dy<0) ofs= -zspan->rectx;
00474         else ofs= zspan->rectx;
00475         
00476         for(x= start; x<=end; x++, rectz++, rectmask++, ap++) {
00477             
00478             y= floor(v1[1]);
00479             if(y!=oldy) {
00480                 oldy= y;
00481                 rectz+= ofs;
00482                 rectmask+= ofs;
00483                 ap+= ofs;
00484             }
00485             
00486             if(x>=0 && y>=0 && y<zspan->recty) {
00487                 if(vergz<*rectz) {
00488                     if(!zspan->rectmask || vergz>*rectmask) {
00489                     
00490                         apn= ap;
00491                         while(apn) {    /* loop unrolled */
00492                             if(apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; }
00493                             if(apn->p[0]==zvlnr && apn->obi[0]==obi) {apn->mask[0]|= mask; break; }
00494                             if(apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; }
00495                             if(apn->p[1]==zvlnr && apn->obi[1]==obi) {apn->mask[1]|= mask; break; }
00496                             if(apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; }
00497                             if(apn->p[2]==zvlnr && apn->obi[2]==obi) {apn->mask[2]|= mask; break; }
00498                             if(apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; }
00499                             if(apn->p[3]==zvlnr && apn->obi[3]==obi) {apn->mask[3]|= mask; break; }
00500                             if(apn->next==0) apn->next= addpsA(zspan);
00501                             apn= apn->next;
00502                         }               
00503                     }
00504                 }
00505             }
00506             
00507             v1[1]+= dy;
00508             if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
00509             else vergz+= dz;
00510         }
00511     }
00512     else {
00513     
00514         /* all lines from top to bottom */
00515         if(vec1[1]<vec2[1]) {
00516             copy_v3_v3(v1, vec1);
00517             copy_v3_v3(v2, vec2);
00518         }
00519         else {
00520             copy_v3_v3(v2, vec1);
00521             copy_v3_v3(v1, vec2);
00522             dx= -dx; dy= -dy;
00523         }
00524 
00525         start= floor(v1[1]);
00526         end= start+floor(dy);
00527         
00528         if(start>=zspan->recty || end<0) return;
00529         
00530         if(end>=zspan->recty) end= zspan->recty-1;
00531         
00532         oldx= floor(v1[0]);
00533         dx/= dy;
00534         
00535         vergz= v1[2];
00536         vergz-= zspan->polygon_offset;
00537         dz= (v2[2]-v1[2])/dy;
00538         if(vergz>0x50000000 && dz>0) maxtest= 1;        // prevent overflow
00539 
00540         rectz= (int *)( zspan->arectz+ (start)*zspan->rectx+ oldx );
00541         rectmask= (int *)( zspan->rectmask+ (start)*zspan->rectx+ oldx );
00542         ap= (zspan->apixbuf+ zspan->rectx*(start) +oldx);
00543                 
00544         if(dx<0) ofs= -1;
00545         else ofs= 1;
00546 
00547         for(y= start; y<=end; y++, rectz+=zspan->rectx, rectmask+=zspan->rectx, ap+=zspan->rectx) {
00548             
00549             x= floor(v1[0]);
00550             if(x!=oldx) {
00551                 oldx= x;
00552                 rectz+= ofs;
00553                 rectmask+= ofs;
00554                 ap+= ofs;
00555             }
00556             
00557             if(x>=0 && y>=0 && x<zspan->rectx) {
00558                 if(vergz<*rectz) {
00559                     if(!zspan->rectmask || vergz>*rectmask) {
00560                         
00561                         apn= ap;
00562                         while(apn) {    /* loop unrolled */
00563                             if(apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; }
00564                             if(apn->p[0]==zvlnr) {apn->mask[0]|= mask; break; }
00565                             if(apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; }
00566                             if(apn->p[1]==zvlnr) {apn->mask[1]|= mask; break; }
00567                             if(apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; }
00568                             if(apn->p[2]==zvlnr) {apn->mask[2]|= mask; break; }
00569                             if(apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; }
00570                             if(apn->p[3]==zvlnr) {apn->mask[3]|= mask; break; }
00571                             if(apn->next==0) apn->next= addpsA(zspan);
00572                             apn= apn->next;
00573                         }   
00574                     }
00575                 }
00576             }
00577             
00578             v1[0]+= dx;
00579             if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
00580             else vergz+= dz;
00581         }
00582     }
00583 }
00584 
00585 /* *************  NORMAL ZBUFFER ************ */
00586 
00587 static void zbufline(ZSpan *zspan, int obi, int zvlnr, float *vec1, float *vec2)
00588 {
00589     int *rectz, *rectp, *recto, *rectmask;
00590     int start, end, x, y, oldx, oldy, ofs;
00591     int dz, vergz, maxtest= 0;
00592     float dx, dy;
00593     float v1[3], v2[3];
00594     
00595     dx= vec2[0]-vec1[0];
00596     dy= vec2[1]-vec1[1];
00597     
00598     if(fabs(dx) > fabs(dy)) {
00599 
00600         /* all lines from left to right */
00601         if(vec1[0]<vec2[0]) {
00602             copy_v3_v3(v1, vec1);
00603             copy_v3_v3(v2, vec2);
00604         }
00605         else {
00606             copy_v3_v3(v2, vec1);
00607             copy_v3_v3(v1, vec2);
00608             dx= -dx; dy= -dy;
00609         }
00610 
00611         start= floor(v1[0]);
00612         end= start+floor(dx);
00613         if(end>=zspan->rectx) end= zspan->rectx-1;
00614         
00615         oldy= floor(v1[1]);
00616         dy/= dx;
00617         
00618         vergz= floor(v1[2]);
00619         dz= floor((v2[2]-v1[2])/dx);
00620         if(vergz>0x50000000 && dz>0) maxtest= 1;        // prevent overflow
00621         
00622         rectz= zspan->rectz + oldy*zspan->rectx+ start;
00623         rectp= zspan->rectp + oldy*zspan->rectx+ start;
00624         recto= zspan->recto + oldy*zspan->rectx+ start;
00625         rectmask= zspan->rectmask + oldy*zspan->rectx+ start;
00626         
00627         if(dy<0) ofs= -zspan->rectx;
00628         else ofs= zspan->rectx;
00629         
00630         for(x= start; x<=end; x++, rectz++, rectp++, recto++, rectmask++) {
00631             
00632             y= floor(v1[1]);
00633             if(y!=oldy) {
00634                 oldy= y;
00635                 rectz+= ofs;
00636                 rectp+= ofs;
00637                 recto+= ofs;
00638                 rectmask+= ofs;
00639             }
00640             
00641             if(x>=0 && y>=0 && y<zspan->recty) {
00642                 if(vergz<*rectz) {
00643                     if(!zspan->rectmask || vergz>*rectmask) {
00644                         *recto= obi;
00645                         *rectz= vergz;
00646                         *rectp= zvlnr;
00647                     }
00648                 }
00649             }
00650             
00651             v1[1]+= dy;
00652             
00653             if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
00654             else vergz+= dz;
00655         }
00656     }
00657     else {
00658         /* all lines from top to bottom */
00659         if(vec1[1]<vec2[1]) {
00660             copy_v3_v3(v1, vec1);
00661             copy_v3_v3(v2, vec2);
00662         }
00663         else {
00664             copy_v3_v3(v2, vec1);
00665             copy_v3_v3(v1, vec2);
00666             dx= -dx; dy= -dy;
00667         }
00668 
00669         start= floor(v1[1]);
00670         end= start+floor(dy);
00671         
00672         if(end>=zspan->recty) end= zspan->recty-1;
00673         
00674         oldx= floor(v1[0]);
00675         dx/= dy;
00676         
00677         vergz= floor(v1[2]);
00678         dz= floor((v2[2]-v1[2])/dy);
00679         if(vergz>0x50000000 && dz>0) maxtest= 1;        // prevent overflow
00680         
00681         rectz= zspan->rectz + start*zspan->rectx+ oldx;
00682         rectp= zspan->rectp + start*zspan->rectx+ oldx;
00683         recto= zspan->recto + start*zspan->rectx+ oldx;
00684         rectmask= zspan->rectmask + start*zspan->rectx+ oldx;
00685         
00686         if(dx<0) ofs= -1;
00687         else ofs= 1;
00688 
00689         for(y= start; y<=end; y++, rectz+=zspan->rectx, rectp+=zspan->rectx, recto+=zspan->rectx, rectmask+=zspan->rectx) {
00690             
00691             x= floor(v1[0]);
00692             if(x!=oldx) {
00693                 oldx= x;
00694                 rectz+= ofs;
00695                 rectp+= ofs;
00696                 recto+= ofs;
00697                 rectmask+= ofs;
00698             }
00699             
00700             if(x>=0 && y>=0 && x<zspan->rectx) {
00701                 if(vergz<*rectz) {
00702                     if(!zspan->rectmask || vergz>*rectmask) {
00703                         *rectz= vergz;
00704                         *rectp= zvlnr;
00705                         *recto= obi;
00706                     }
00707                 }
00708             }
00709             
00710             v1[0]+= dx;
00711             if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
00712             else vergz+= dz;
00713         }
00714     }
00715 }
00716 
00717 static void zbufline_onlyZ(ZSpan *zspan, int UNUSED(obi), int UNUSED(zvlnr), float *vec1, float *vec2)
00718 {
00719     int *rectz, *rectz1= NULL;
00720     int start, end, x, y, oldx, oldy, ofs;
00721     int dz, vergz, maxtest= 0;
00722     float dx, dy;
00723     float v1[3], v2[3];
00724     
00725     dx= vec2[0]-vec1[0];
00726     dy= vec2[1]-vec1[1];
00727     
00728     if(fabs(dx) > fabs(dy)) {
00729         
00730         /* all lines from left to right */
00731         if(vec1[0]<vec2[0]) {
00732             copy_v3_v3(v1, vec1);
00733             copy_v3_v3(v2, vec2);
00734         }
00735         else {
00736             copy_v3_v3(v2, vec1);
00737             copy_v3_v3(v1, vec2);
00738             dx= -dx; dy= -dy;
00739         }
00740         
00741         start= floor(v1[0]);
00742         end= start+floor(dx);
00743         if(end>=zspan->rectx) end= zspan->rectx-1;
00744         
00745         oldy= floor(v1[1]);
00746         dy/= dx;
00747         
00748         vergz= floor(v1[2]);
00749         dz= floor((v2[2]-v1[2])/dx);
00750         if(vergz>0x50000000 && dz>0) maxtest= 1;        // prevent overflow
00751         
00752         rectz= zspan->rectz + oldy*zspan->rectx+ start;
00753         if(zspan->rectz1)
00754             rectz1= zspan->rectz1 + oldy*zspan->rectx+ start;
00755         
00756         if(dy<0) ofs= -zspan->rectx;
00757         else ofs= zspan->rectx;
00758         
00759         for(x= start; x<=end; x++, rectz++) {
00760             
00761             y= floor(v1[1]);
00762             if(y!=oldy) {
00763                 oldy= y;
00764                 rectz+= ofs;
00765                 if(rectz1) rectz1+= ofs;
00766             }
00767             
00768             if(x>=0 && y>=0 && y<zspan->recty) {
00769                 if(vergz < *rectz) {
00770                     if(rectz1) *rectz1= *rectz;
00771                     *rectz= vergz;
00772                 }
00773                 else if(rectz1 && vergz < *rectz1)
00774                     *rectz1= vergz;
00775             }
00776             
00777             v1[1]+= dy;
00778             
00779             if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
00780             else vergz+= dz;
00781             
00782             if(rectz1) rectz1++;
00783         }
00784     }
00785     else {
00786         /* all lines from top to bottom */
00787         if(vec1[1]<vec2[1]) {
00788             copy_v3_v3(v1, vec1);
00789             copy_v3_v3(v2, vec2);
00790         }
00791         else {
00792             copy_v3_v3(v2, vec1);
00793             copy_v3_v3(v1, vec2);
00794             dx= -dx; dy= -dy;
00795         }
00796         
00797         start= floor(v1[1]);
00798         end= start+floor(dy);
00799         
00800         if(end>=zspan->recty) end= zspan->recty-1;
00801         
00802         oldx= floor(v1[0]);
00803         dx/= dy;
00804         
00805         vergz= floor(v1[2]);
00806         dz= floor((v2[2]-v1[2])/dy);
00807         if(vergz>0x50000000 && dz>0) maxtest= 1;        // prevent overflow
00808         
00809         rectz= zspan->rectz + start*zspan->rectx+ oldx;
00810         if(zspan->rectz1)
00811             rectz1= zspan->rectz1 + start*zspan->rectx+ oldx;
00812         
00813         if(dx<0) ofs= -1;
00814         else ofs= 1;
00815         
00816         for(y= start; y<=end; y++, rectz+=zspan->rectx) {
00817             
00818             x= floor(v1[0]);
00819             if(x!=oldx) {
00820                 oldx= x;
00821                 rectz+= ofs;
00822                 if(rectz1) rectz1+= ofs;
00823             }
00824             
00825             if(x>=0 && y>=0 && x<zspan->rectx) {
00826                 if(vergz < *rectz) {
00827                     if(rectz1) *rectz1= *rectz;
00828                     *rectz= vergz;
00829                 }
00830                 else if(rectz1 && vergz < *rectz1)
00831                     *rectz1= vergz;
00832             }
00833             
00834             v1[0]+= dx;
00835             if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
00836             else vergz+= dz;
00837             
00838             if(rectz1)
00839                 rectz1+=zspan->rectx;
00840         }
00841     }
00842 }
00843 
00844 
00845 static int clipline(float v1[4], float v2[4])   /* return 0: do not draw */
00846 {
00847     float dz,dw, u1=0.0, u2=1.0;
00848     float dx, dy, v13;
00849     
00850     dz= v2[2]-v1[2];
00851     dw= v2[3]-v1[3];
00852     
00853     /* this 1.01 is for clipping x and y just a tinsy larger. that way it is
00854         filled in with zbufwire correctly when rendering in parts. otherwise
00855         you see line endings at edges... */
00856     
00857     if(cliptestf(-dz-dw, v1[3]+v1[2], &u1,&u2)) {
00858         if(cliptestf(dz-dw, v1[3]-v1[2], &u1,&u2)) {
00859             
00860             dx= v2[0]-v1[0];
00861             dz= 1.01f*(v2[3]-v1[3]);
00862             v13= 1.01f*v1[3];
00863             
00864             if(cliptestf(-dx-dz, v1[0]+v13, &u1,&u2)) {
00865                 if(cliptestf(dx-dz, v13-v1[0], &u1,&u2)) {
00866                     
00867                     dy= v2[1]-v1[1];
00868                     
00869                     if(cliptestf(-dy-dz, v1[1]+v13, &u1,&u2)) {
00870                         if(cliptestf(dy-dz, v13-v1[1], &u1,&u2)) {
00871                             
00872                             if(u2<1.0f) {
00873                                 v2[0]= v1[0]+u2*dx;
00874                                 v2[1]= v1[1]+u2*dy;
00875                                 v2[2]= v1[2]+u2*dz;
00876                                 v2[3]= v1[3]+u2*dw;
00877                             }
00878                             if(u1>0.0f) {
00879                                 v1[0]= v1[0]+u1*dx;
00880                                 v1[1]= v1[1]+u1*dy;
00881                                 v1[2]= v1[2]+u1*dz;
00882                                 v1[3]= v1[3]+u1*dw;
00883                             }
00884                             return 1;
00885                         }
00886                     }
00887                 }
00888             }
00889         }
00890     }
00891     
00892     return 0;
00893 }
00894 
00895 void hoco_to_zco(ZSpan *zspan, float zco[3], const float hoco[4])
00896 {
00897     float div;
00898     
00899     div= 1.0f/hoco[3];
00900     zco[0]= zspan->zmulx*(1.0f+hoco[0]*div) + zspan->zofsx;
00901     zco[1]= zspan->zmuly*(1.0f+hoco[1]*div) + zspan->zofsy;
00902     zco[2]= 0x7FFFFFFF *(hoco[2]*div);
00903 }
00904 
00905 void zbufclipwire(ZSpan *zspan, int obi, int zvlnr, int ec, float *ho1, float *ho2, float *ho3, float *ho4, int c1, int c2, int c3, int c4)
00906 {
00907     float vez[20];
00908     int and, or;
00909 
00910     /* edgecode: 1= draw */
00911     if(ec==0) return;
00912 
00913     if(ho4) {
00914         and= (c1 & c2 & c3 & c4);
00915         or= (c1 | c2 | c3 | c4);
00916     }
00917     else {
00918         and= (c1 & c2 & c3);
00919         or= (c1 | c2 | c3);
00920     }
00921     
00922     if(or) {    /* not in the middle */
00923         if(and) {   /* out completely */
00924             return;
00925         }
00926         else {  /* clipping */
00927 
00928             if(ec & ME_V1V2) {
00929                 copy_v4_v4(vez, ho1);
00930                 copy_v4_v4(vez+4, ho2);
00931                 if( clipline(vez, vez+4)) {
00932                     hoco_to_zco(zspan, vez, vez);
00933                     hoco_to_zco(zspan, vez+4, vez+4);
00934                     zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4);
00935                 }
00936             }
00937             if(ec & ME_V2V3) {
00938                 copy_v4_v4(vez, ho2);
00939                 copy_v4_v4(vez+4, ho3);
00940                 if( clipline(vez, vez+4)) {
00941                     hoco_to_zco(zspan, vez, vez);
00942                     hoco_to_zco(zspan, vez+4, vez+4);
00943                     zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4);
00944                 }
00945             }
00946             if(ho4) {
00947                 if(ec & ME_V3V4) {
00948                     copy_v4_v4(vez, ho3);
00949                     copy_v4_v4(vez+4, ho4);
00950                     if( clipline(vez, vez+4)) {
00951                         hoco_to_zco(zspan, vez, vez);
00952                         hoco_to_zco(zspan, vez+4, vez+4);
00953                         zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4);
00954                     }
00955                 }
00956                 if(ec & ME_V4V1) {
00957                     copy_v4_v4(vez, ho4);
00958                     copy_v4_v4(vez+4, ho1);
00959                     if( clipline(vez, vez+4)) {
00960                         hoco_to_zco(zspan, vez, vez);
00961                         hoco_to_zco(zspan, vez+4, vez+4);
00962                         zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4);
00963                     }
00964                 }
00965             }
00966             else {
00967                 if(ec & ME_V3V1) {
00968                     copy_v4_v4(vez, ho3);
00969                     copy_v4_v4(vez+4, ho1);
00970                     if( clipline(vez, vez+4)) {
00971                         hoco_to_zco(zspan, vez, vez);
00972                         hoco_to_zco(zspan, vez+4, vez+4);
00973                         zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4);
00974                     }
00975                 }
00976             }
00977             
00978             return;
00979         }
00980     }
00981 
00982     hoco_to_zco(zspan, vez, ho1);
00983     hoco_to_zco(zspan, vez+4, ho2);
00984     hoco_to_zco(zspan, vez+8, ho3);
00985     if(ho4) {
00986         hoco_to_zco(zspan, vez+12, ho4);
00987 
00988         if(ec & ME_V3V4)  zspan->zbuflinefunc(zspan, obi, zvlnr, vez+8, vez+12);
00989         if(ec & ME_V4V1)  zspan->zbuflinefunc(zspan, obi, zvlnr, vez+12, vez);
00990     }
00991     else {
00992         if(ec & ME_V3V1)  zspan->zbuflinefunc(zspan, obi, zvlnr, vez+8, vez);
00993     }
00994 
00995     if(ec & ME_V1V2)  zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4);
00996     if(ec & ME_V2V3)  zspan->zbuflinefunc(zspan, obi, zvlnr, vez+4, vez+8);
00997 
00998 }
00999 
01000 void zbufsinglewire(ZSpan *zspan, int obi, int zvlnr, const float ho1[4], const float ho2[4])
01001 {
01002     float f1[4], f2[4];
01003     int c1, c2;
01004 
01005     c1= testclip(ho1);
01006     c2= testclip(ho2);
01007 
01008     if(c1 | c2) {   /* not in the middle */
01009         if(!(c1 & c2)) {    /* not out completely */
01010             copy_v4_v4(f1, ho1);
01011             copy_v4_v4(f2, ho2);
01012 
01013             if(clipline(f1, f2)) {
01014                 hoco_to_zco(zspan, f1, f1);
01015                 hoco_to_zco(zspan, f2, f2);
01016                 zspan->zbuflinefunc(zspan, obi, zvlnr, f1, f2);
01017             }
01018         }
01019     }
01020     else {
01021         hoco_to_zco(zspan, f1, ho1);
01022         hoco_to_zco(zspan, f2, ho2);
01023 
01024         zspan->zbuflinefunc(zspan, obi, zvlnr, f1, f2);
01025     }
01026 }
01027 
01040 /* WATCH IT: zbuffillGLinv4 and zbuffillGL4 are identical except for a 2 lines,
01041  * commented below */
01042 static void zbuffillGLinv4(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4) 
01043 {
01044     double zxd, zyd, zy0, zverg;
01045     float x0,y0,z0;
01046     float x1,y1,z1,x2,y2,z2,xx1;
01047     float *span1, *span2;
01048     int *rectoofs, *ro;
01049     int *rectpofs, *rp;
01050     int *rectmaskofs, *rm;
01051     int *rz, x, y;
01052     int sn1, sn2, rectx, *rectzofs, my0, my2;
01053 
01054     /* init */
01055     zbuf_init_span(zspan);
01056 
01057     /* set spans */
01058     zbuf_add_to_span(zspan, v1, v2);
01059     zbuf_add_to_span(zspan, v2, v3);
01060     if(v4) {
01061         zbuf_add_to_span(zspan, v3, v4);
01062         zbuf_add_to_span(zspan, v4, v1);
01063     }
01064     else
01065         zbuf_add_to_span(zspan, v3, v1);
01066 
01067     /* clipped */
01068     if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
01069 
01070     if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
01071     if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
01072 
01073     //  printf("my %d %d\n", my0, my2);
01074     if(my2<my0) return;
01075 
01076 
01077     /* ZBUF DX DY, in floats still */
01078     x1= v1[0]- v2[0];
01079     x2= v2[0]- v3[0];
01080     y1= v1[1]- v2[1];
01081     y2= v2[1]- v3[1];
01082     z1= v1[2]- v2[2];
01083     z2= v2[2]- v3[2];
01084     x0= y1*z2-z1*y2;
01085     y0= z1*x2-x1*z2;
01086     z0= x1*y2-y1*x2;
01087 
01088     if(z0==0.0f) return;
01089 
01090     xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
01091 
01092     zxd= -(double)x0/(double)z0;
01093     zyd= -(double)y0/(double)z0;
01094     zy0= ((double)my2)*zyd + (double)xx1;
01095 
01096     /* start-offset in rect */
01097     rectx= zspan->rectx;
01098     rectzofs= (zspan->rectz+rectx*my2);
01099     rectpofs= (zspan->rectp+rectx*my2);
01100     rectoofs= (zspan->recto+rectx*my2);
01101     rectmaskofs= (zspan->rectmask+rectx*my2);
01102 
01103     /* correct span */
01104     sn1= (my0 + my2)/2;
01105     if(zspan->span1[sn1] < zspan->span2[sn1]) {
01106         span1= zspan->span1+my2;
01107         span2= zspan->span2+my2;
01108     }
01109     else {
01110         span1= zspan->span2+my2;
01111         span2= zspan->span1+my2;
01112     }
01113 
01114     for(y=my2; y>=my0; y--, span1--, span2--) {
01115 
01116         sn1= floor(*span1);
01117         sn2= floor(*span2);
01118         sn1++;
01119 
01120         if(sn2>=rectx) sn2= rectx-1;
01121         if(sn1<0) sn1= 0;
01122 
01123         if(sn2>=sn1) {
01124             int intzverg;
01125 
01126             zverg= (double)sn1*zxd + zy0;
01127             rz= rectzofs+sn1;
01128             rp= rectpofs+sn1;
01129             ro= rectoofs+sn1;
01130             rm= rectmaskofs+sn1;
01131             x= sn2-sn1;
01132 
01133             while(x>=0) {
01134                 intzverg= (int)CLAMPIS(zverg, INT_MIN, INT_MAX);
01135 
01136                 if( intzverg > *rz || *rz==0x7FFFFFFF) { /* UNIQUE LINE: see comment above */
01137                     if(!zspan->rectmask || intzverg > *rm) {
01138                         *ro= obi; /* UNIQUE LINE: see comment above (order differs) */
01139                         *rz= intzverg;
01140                         *rp= zvlnr;
01141                     }
01142                 }
01143                 zverg+= zxd;
01144                 rz++;
01145                 rp++;
01146                 ro++;
01147                 rm++;
01148                 x--;
01149             }
01150         }
01151 
01152         zy0-=zyd;
01153         rectzofs-= rectx;
01154         rectpofs-= rectx;
01155         rectoofs-= rectx;
01156         rectmaskofs-= rectx;
01157     }
01158 }
01159 
01160 /* uses spanbuffers */
01161 
01162 /* WATCH IT: zbuffillGLinv4 and zbuffillGL4 are identical except for a 2 lines,
01163  * commented below */
01164 static void zbuffillGL4(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4)
01165 {
01166     double zxd, zyd, zy0, zverg;
01167     float x0,y0,z0;
01168     float x1,y1,z1,x2,y2,z2,xx1;
01169     float *span1, *span2;
01170     int *rectoofs, *ro;
01171     int *rectpofs, *rp;
01172     int *rectmaskofs, *rm;
01173     int *rz, x, y;
01174     int sn1, sn2, rectx, *rectzofs, my0, my2;
01175 
01176     /* init */
01177     zbuf_init_span(zspan);
01178 
01179     /* set spans */
01180     zbuf_add_to_span(zspan, v1, v2);
01181     zbuf_add_to_span(zspan, v2, v3);
01182     if(v4) {
01183         zbuf_add_to_span(zspan, v3, v4);
01184         zbuf_add_to_span(zspan, v4, v1);
01185     }
01186     else
01187         zbuf_add_to_span(zspan, v3, v1);
01188 
01189     /* clipped */
01190     if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
01191 
01192     if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
01193     if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
01194 
01195     //  printf("my %d %d\n", my0, my2);
01196     if(my2<my0) return;
01197 
01198 
01199     /* ZBUF DX DY, in floats still */
01200     x1= v1[0]- v2[0];
01201     x2= v2[0]- v3[0];
01202     y1= v1[1]- v2[1];
01203     y2= v2[1]- v3[1];
01204     z1= v1[2]- v2[2];
01205     z2= v2[2]- v3[2];
01206     x0= y1*z2-z1*y2;
01207     y0= z1*x2-x1*z2;
01208     z0= x1*y2-y1*x2;
01209 
01210     if(z0==0.0f) return;
01211 
01212     xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
01213 
01214     zxd= -(double)x0/(double)z0;
01215     zyd= -(double)y0/(double)z0;
01216     zy0= ((double)my2)*zyd + (double)xx1;
01217 
01218     /* start-offset in rect */
01219     rectx= zspan->rectx;
01220     rectzofs= (zspan->rectz+rectx*my2);
01221     rectpofs= (zspan->rectp+rectx*my2);
01222     rectoofs= (zspan->recto+rectx*my2);
01223     rectmaskofs= (zspan->rectmask+rectx*my2);
01224 
01225     /* correct span */
01226     sn1= (my0 + my2)/2;
01227     if(zspan->span1[sn1] < zspan->span2[sn1]) {
01228         span1= zspan->span1+my2;
01229         span2= zspan->span2+my2;
01230     }
01231     else {
01232         span1= zspan->span2+my2;
01233         span2= zspan->span1+my2;
01234     }
01235 
01236     for(y=my2; y>=my0; y--, span1--, span2--) {
01237 
01238         sn1= floor(*span1);
01239         sn2= floor(*span2);
01240         sn1++;
01241 
01242         if(sn2>=rectx) sn2= rectx-1;
01243         if(sn1<0) sn1= 0;
01244 
01245         if(sn2>=sn1) {
01246             int intzverg;
01247 
01248             zverg= (double)sn1*zxd + zy0;
01249             rz= rectzofs+sn1;
01250             rp= rectpofs+sn1;
01251             ro= rectoofs+sn1;
01252             rm= rectmaskofs+sn1;
01253             x= sn2-sn1;
01254 
01255             while(x>=0) {
01256                 intzverg= (int)CLAMPIS(zverg, INT_MIN, INT_MAX);
01257 
01258                 if(intzverg < *rz) { /* ONLY UNIQUE LINE: see comment above */
01259                     if(!zspan->rectmask || intzverg > *rm) {
01260                         *rz= intzverg;
01261                         *rp= zvlnr;
01262                         *ro= obi; /* UNIQUE LINE: see comment above (order differs) */
01263                     }
01264                 }
01265                 zverg+= zxd;
01266                 rz++;
01267                 rp++;
01268                 ro++;
01269                 rm++;
01270                 x--;
01271             }
01272         }
01273 
01274         zy0-=zyd;
01275         rectzofs-= rectx;
01276         rectpofs-= rectx;
01277         rectoofs-= rectx;
01278         rectmaskofs-= rectx;
01279     }
01280 }
01281 
01293 /* now: filling two Z values, the closest and 2nd closest */
01294 static void zbuffillGL_onlyZ(ZSpan *zspan, int UNUSED(obi), int UNUSED(zvlnr), float *v1, float *v2, float *v3, float *v4)
01295 {
01296     double zxd, zyd, zy0, zverg;
01297     float x0,y0,z0;
01298     float x1,y1,z1,x2,y2,z2,xx1;
01299     float *span1, *span2;
01300     int *rz, *rz1, x, y;
01301     int sn1, sn2, rectx, *rectzofs, *rectzofs1= NULL, my0, my2;
01302     
01303     /* init */
01304     zbuf_init_span(zspan);
01305     
01306     /* set spans */
01307     zbuf_add_to_span(zspan, v1, v2);
01308     zbuf_add_to_span(zspan, v2, v3);
01309     if(v4) {
01310         zbuf_add_to_span(zspan, v3, v4);
01311         zbuf_add_to_span(zspan, v4, v1);
01312     }
01313     else 
01314         zbuf_add_to_span(zspan, v3, v1);
01315     
01316     /* clipped */
01317     if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
01318     
01319     if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
01320     if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
01321     
01322     //  printf("my %d %d\n", my0, my2);
01323     if(my2<my0) return;
01324     
01325     
01326     /* ZBUF DX DY, in floats still */
01327     x1= v1[0]- v2[0];
01328     x2= v2[0]- v3[0];
01329     y1= v1[1]- v2[1];
01330     y2= v2[1]- v3[1];
01331     z1= v1[2]- v2[2];
01332     z2= v2[2]- v3[2];
01333     x0= y1*z2-z1*y2;
01334     y0= z1*x2-x1*z2;
01335     z0= x1*y2-y1*x2;
01336     
01337     if(z0==0.0f) return;
01338     
01339     xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
01340     
01341     zxd= -(double)x0/(double)z0;
01342     zyd= -(double)y0/(double)z0;
01343     zy0= ((double)my2)*zyd + (double)xx1;
01344     
01345     /* start-offset in rect */
01346     rectx= zspan->rectx;
01347     rectzofs= (zspan->rectz+rectx*my2);
01348     if(zspan->rectz1)
01349         rectzofs1= (zspan->rectz1+rectx*my2);
01350     
01351     /* correct span */
01352     sn1= (my0 + my2)/2;
01353     if(zspan->span1[sn1] < zspan->span2[sn1]) {
01354         span1= zspan->span1+my2;
01355         span2= zspan->span2+my2;
01356     }
01357     else {
01358         span1= zspan->span2+my2;
01359         span2= zspan->span1+my2;
01360     }
01361     
01362     for(y=my2; y>=my0; y--, span1--, span2--) {
01363         
01364         sn1= floor(*span1);
01365         sn2= floor(*span2);
01366         sn1++; 
01367         
01368         if(sn2>=rectx) sn2= rectx-1;
01369         if(sn1<0) sn1= 0;
01370         
01371         if(sn2>=sn1) {
01372             zverg= (double)sn1*zxd + zy0;
01373             rz= rectzofs+sn1;
01374             rz1= rectzofs1+sn1;
01375             x= sn2-sn1;
01376             
01377             while(x>=0) {
01378                 int zvergi= (int)CLAMPIS(zverg, INT_MIN, INT_MAX);
01379 
01380                 /* option: maintain two depth values, closest and 2nd closest */
01381                 if(zvergi < *rz) {
01382                     if(rectzofs1) *rz1= *rz;
01383                     *rz= zvergi;
01384                 }
01385                 else if(rectzofs1 && zvergi < *rz1)
01386                     *rz1= zvergi;
01387 
01388                 zverg+= zxd;
01389                 
01390                 rz++; 
01391                 rz1++;
01392                 x--;
01393             }
01394         }
01395         
01396         zy0-=zyd;
01397         rectzofs-= rectx;
01398         if(rectzofs1) rectzofs1-= rectx;
01399     }
01400 }
01401 
01402 /* 2d scanconvert for tria, calls func for each x,y coordinate and gives UV barycentrics */
01403 void zspan_scanconvert_strand(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float, float) )
01404 {
01405     float x0, y0, x1, y1, x2, y2, z0, z1, z2, z;
01406     float u, v, uxd, uyd, vxd, vyd, uy0, vy0, zxd, zyd, zy0, xx1;
01407     float *span1, *span2;
01408     int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2;
01409     
01410     /* init */
01411     zbuf_init_span(zspan);
01412     
01413     /* set spans */
01414     zbuf_add_to_span(zspan, v1, v2);
01415     zbuf_add_to_span(zspan, v2, v3);
01416     zbuf_add_to_span(zspan, v3, v1);
01417     
01418     /* clipped */
01419     if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
01420     
01421     if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
01422     if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
01423     
01424     //  printf("my %d %d\n", my0, my2);
01425     if(my2<my0) return;
01426     
01427     /* ZBUF DX DY, in floats still */
01428     x1= v1[0]- v2[0];
01429     x2= v2[0]- v3[0];
01430     y1= v1[1]- v2[1];
01431     y2= v2[1]- v3[1];
01432     z1= v1[2]- v2[2];
01433     z2= v2[2]- v3[2];
01434 
01435     x0= y1*z2-z1*y2;
01436     y0= z1*x2-x1*z2;
01437     z0= x1*y2-y1*x2;
01438     
01439     if(z0==0.0f) return;
01440 
01441     xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
01442     zxd= -(double)x0/(double)z0;
01443     zyd= -(double)y0/(double)z0;
01444     zy0= ((double)my2)*zyd + (double)xx1;
01445     
01446     z1= 1.0f; // (u1 - u2)
01447     z2= 0.0f; // (u2 - u3)
01448 
01449     x0= y1*z2-z1*y2;
01450     y0= z1*x2-x1*z2;
01451     
01452     xx1= (x0*v1[0] + y0*v1[1])/z0 + 1.0f;   
01453     uxd= -(double)x0/(double)z0;
01454     uyd= -(double)y0/(double)z0;
01455     uy0= ((double)my2)*uyd + (double)xx1;
01456 
01457     z1= -1.0f; // (v1 - v2)
01458     z2= 1.0f;  // (v2 - v3)
01459     
01460     x0= y1*z2-z1*y2;
01461     y0= z1*x2-x1*z2;
01462     
01463     xx1= (x0*v1[0] + y0*v1[1])/z0;
01464     vxd= -(double)x0/(double)z0;
01465     vyd= -(double)y0/(double)z0;
01466     vy0= ((double)my2)*vyd + (double)xx1;
01467     
01468     /* correct span */
01469     sn1= (my0 + my2)/2;
01470     if(zspan->span1[sn1] < zspan->span2[sn1]) {
01471         span1= zspan->span1+my2;
01472         span2= zspan->span2+my2;
01473     }
01474     else {
01475         span1= zspan->span2+my2;
01476         span2= zspan->span1+my2;
01477     }
01478     
01479     for(y=my2; y>=my0; y--, span1--, span2--) {
01480         
01481         sn1= floor(*span1);
01482         sn2= floor(*span2);
01483         sn1++; 
01484         
01485         if(sn2>=rectx) sn2= rectx-1;
01486         if(sn1<0) sn1= 0;
01487         
01488         u= (double)sn1*uxd + uy0;
01489         v= (double)sn1*vxd + vy0;
01490         z= (double)sn1*zxd + zy0;
01491         
01492         for(x= sn1; x<=sn2; x++, u+=uxd, v+=vxd, z+=zxd)
01493             func(handle, x, y, u, v, z);
01494         
01495         uy0 -= uyd;
01496         vy0 -= vyd;
01497         zy0 -= zyd;
01498     }
01499 }
01500 
01501 /* scanconvert for strand triangles, calls func for each x,y coordinate and gives UV barycentrics and z */
01502 
01503 void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float) )
01504 {
01505     float x0, y0, x1, y1, x2, y2, z0, z1, z2;
01506     float u, v, uxd, uyd, vxd, vyd, uy0, vy0, xx1;
01507     float *span1, *span2;
01508     int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2;
01509     
01510     /* init */
01511     zbuf_init_span(zspan);
01512     
01513     /* set spans */
01514     zbuf_add_to_span(zspan, v1, v2);
01515     zbuf_add_to_span(zspan, v2, v3);
01516     zbuf_add_to_span(zspan, v3, v1);
01517     
01518     /* clipped */
01519     if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
01520     
01521     if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
01522     if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
01523     
01524     //  printf("my %d %d\n", my0, my2);
01525     if(my2<my0) return;
01526     
01527     /* ZBUF DX DY, in floats still */
01528     x1= v1[0]- v2[0];
01529     x2= v2[0]- v3[0];
01530     y1= v1[1]- v2[1];
01531     y2= v2[1]- v3[1];
01532     
01533     z1= 1.0f; // (u1 - u2)
01534     z2= 0.0f; // (u2 - u3)
01535     
01536     x0= y1*z2-z1*y2;
01537     y0= z1*x2-x1*z2;
01538     z0= x1*y2-y1*x2;
01539     
01540     if(z0==0.0f) return;
01541     
01542     xx1= (x0*v1[0] + y0*v1[1])/z0 + 1.0f;   
01543     uxd= -(double)x0/(double)z0;
01544     uyd= -(double)y0/(double)z0;
01545     uy0= ((double)my2)*uyd + (double)xx1;
01546 
01547     z1= -1.0f; // (v1 - v2)
01548     z2= 1.0f;  // (v2 - v3)
01549     
01550     x0= y1*z2-z1*y2;
01551     y0= z1*x2-x1*z2;
01552     
01553     xx1= (x0*v1[0] + y0*v1[1])/z0;
01554     vxd= -(double)x0/(double)z0;
01555     vyd= -(double)y0/(double)z0;
01556     vy0= ((double)my2)*vyd + (double)xx1;
01557     
01558     /* correct span */
01559     sn1= (my0 + my2)/2;
01560     if(zspan->span1[sn1] < zspan->span2[sn1]) {
01561         span1= zspan->span1+my2;
01562         span2= zspan->span2+my2;
01563     }
01564     else {
01565         span1= zspan->span2+my2;
01566         span2= zspan->span1+my2;
01567     }
01568     
01569     for(y=my2; y>=my0; y--, span1--, span2--) {
01570         
01571         sn1= floor(*span1);
01572         sn2= floor(*span2);
01573         sn1++; 
01574         
01575         if(sn2>=rectx) sn2= rectx-1;
01576         if(sn1<0) sn1= 0;
01577         
01578         u= (double)sn1*uxd + uy0;
01579         v= (double)sn1*vxd + vy0;
01580         
01581         for(x= sn1; x<=sn2; x++, u+=uxd, v+=vxd)
01582             func(handle, x, y, u, v);
01583         
01584         uy0 -= uyd;
01585         vy0 -= vyd;
01586     }
01587 }
01588 
01589 
01590 
01605 static void clippyra(float *labda, float *v1, float *v2, int *b2, int *b3, int a, float clipcrop)
01606 {
01607     float da,dw,u1=0.0,u2=1.0;
01608     float v13;
01609     
01610     labda[0]= -1.0;
01611     labda[1]= -1.0;
01612 
01613     da= v2[a]-v1[a];
01614     /* prob; we clip slightly larger, osa renders add 2 pixels on edges, should become variable? */
01615     /* or better; increase r.winx/y size, but thats quite a complex one. do it later */
01616     if(a==2) {
01617         dw= (v2[3]-v1[3]);
01618         v13= v1[3];
01619     }
01620     else {
01621         dw= clipcrop*(v2[3]-v1[3]);
01622         v13= clipcrop*v1[3];
01623     }   
01624     /* according the original article by Liang&Barsky, for clipping of
01625      * homogenous coordinates with viewplane, the value of "0" is used instead of "-w" .
01626      * This differs from the other clipping cases (like left or top) and I considered
01627      * it to be not so 'homogenic'. But later it has proven to be an error,
01628      * who would have thought that of L&B!
01629      */
01630 
01631     if(cliptestf(-da-dw, v13+v1[a], &u1,&u2)) {
01632         if(cliptestf(da-dw, v13-v1[a], &u1,&u2)) {
01633             *b3=1;
01634             if(u2<1.0f) {
01635                 labda[1]= u2;
01636                 *b2=1;
01637             }
01638             else labda[1]=1.0;  /* u2 */
01639             if(u1>0.0f) {
01640                 labda[0]= u1;
01641                 *b2=1;
01642             } else labda[0]=0.0;
01643         }
01644     }
01645 }
01646 
01662 static void makevertpyra(float *vez, float *labda, float **trias, float *v1, float *v2, int *b1, int *clve)
01663 {
01664     float l1, l2, *adr;
01665 
01666     l1= labda[0];
01667     l2= labda[1];
01668 
01669     if(l1!= -1.0f) {
01670         if(l1!= 0.0f) {
01671             adr= vez+4*(*clve);
01672             trias[*b1]=adr;
01673             (*clve)++;
01674             adr[0]= v1[0]+l1*(v2[0]-v1[0]);
01675             adr[1]= v1[1]+l1*(v2[1]-v1[1]);
01676             adr[2]= v1[2]+l1*(v2[2]-v1[2]);
01677             adr[3]= v1[3]+l1*(v2[3]-v1[3]);
01678         } 
01679         else trias[*b1]= v1;
01680         
01681         (*b1)++;
01682     }
01683     if(l2!= -1.0f) {
01684         if(l2!= 1.0f) {
01685             adr= vez+4*(*clve);
01686             trias[*b1]=adr;
01687             (*clve)++;
01688             adr[0]= v1[0]+l2*(v2[0]-v1[0]);
01689             adr[1]= v1[1]+l2*(v2[1]-v1[1]);
01690             adr[2]= v1[2]+l2*(v2[2]-v1[2]);
01691             adr[3]= v1[3]+l2*(v2[3]-v1[3]);
01692             (*b1)++;
01693         }
01694     }
01695 }
01696 
01697 /* ------------------------------------------------------------------------- */
01698 
01699 void projectverto(const float v1[3], float winmat[][4], float adr[4])
01700 {
01701     /* calcs homogenic coord of vertex v1 */
01702     float x,y,z;
01703 
01704     x= v1[0]; 
01705     y= v1[1]; 
01706     z= v1[2];
01707     adr[0]= x*winmat[0][0]              +   z*winmat[2][0] + winmat[3][0];
01708     adr[1]=               y*winmat[1][1]    +   z*winmat[2][1] + winmat[3][1];
01709     adr[2]=                                     z*winmat[2][2] + winmat[3][2];
01710     adr[3]=                                     z*winmat[2][3] + winmat[3][3];
01711 
01712     //printf("hoco %f %f %f %f\n", adr[0], adr[1], adr[2], adr[3]);
01713 }
01714 
01715 /* ------------------------------------------------------------------------- */
01716 
01717 void projectvert(const float v1[3], float winmat[][4], float adr[4])
01718 {
01719     /* calcs homogenic coord of vertex v1 */
01720     float x,y,z;
01721 
01722     x= v1[0]; 
01723     y= v1[1]; 
01724     z= v1[2];
01725     adr[0]= x*winmat[0][0]+ y*winmat[1][0]+ z*winmat[2][0]+ winmat[3][0];
01726     adr[1]= x*winmat[0][1]+ y*winmat[1][1]+ z*winmat[2][1]+ winmat[3][1];
01727     adr[2]= x*winmat[0][2]+ y*winmat[1][2]+ z*winmat[2][2]+ winmat[3][2];
01728     adr[3]= x*winmat[0][3]+ y*winmat[1][3]+ z*winmat[2][3]+ winmat[3][3];
01729 }
01730 
01731 /* ------------------------------------------------------------------------- */
01732 
01733 #define ZBUF_PROJECT_CACHE_SIZE 256
01734 
01735 typedef struct ZbufProjectCache {
01736     int index, clip;
01737     float ho[4];
01738 } ZbufProjectCache;
01739 
01740 static void zbuf_project_cache_clear(ZbufProjectCache *cache, int size)
01741 {
01742     int i;
01743 
01744     if(size > ZBUF_PROJECT_CACHE_SIZE)
01745         size= ZBUF_PROJECT_CACHE_SIZE;
01746 
01747     memset(cache, 0, sizeof(ZbufProjectCache)*size);
01748     for(i=0; i<size; i++)
01749         cache[i].index= -1;
01750 }
01751 
01752 static int zbuf_shadow_project(ZbufProjectCache *cache, int index, float winmat[][4], float *co, float *ho)
01753 {
01754     int cindex= index & 255;
01755 
01756     if(cache[cindex].index == index) {
01757         copy_v4_v4(ho, cache[cindex].ho);
01758         return cache[cindex].clip;
01759     }
01760     else {
01761         int clipflag;
01762         projectvert(co, winmat, ho);
01763         clipflag= testclip(ho);
01764 
01765         copy_v4_v4(cache[cindex].ho, ho);
01766         cache[cindex].clip= clipflag;
01767         cache[cindex].index= index;
01768 
01769         return clipflag;
01770     }
01771 }
01772 
01773 static void zbuffer_part_bounds(int winx, int winy, RenderPart *pa, float *bounds)
01774 {
01775     bounds[0]= (2*pa->disprect.xmin - winx-1)/(float)winx;
01776     bounds[1]= (2*pa->disprect.xmax - winx+1)/(float)winx;
01777     bounds[2]= (2*pa->disprect.ymin - winy-1)/(float)winy;
01778     bounds[3]= (2*pa->disprect.ymax - winy+1)/(float)winy;
01779 }
01780 
01781 static int zbuf_part_project(ZbufProjectCache *cache, int index, float winmat[][4], float *bounds, float *co, float *ho)
01782 {
01783     float vec[3];
01784     int cindex= index & 255;
01785 
01786     if(cache[cindex].index == index) {
01787         copy_v4_v4(ho, cache[cindex].ho);
01788         return cache[cindex].clip;
01789     }
01790     else {
01791         float wco;
01792         int clipflag= 0;
01793         copy_v3_v3(vec, co);
01794         projectvert(co, winmat, ho);
01795 
01796         wco= ho[3];
01797         if(ho[0] < bounds[0]*wco) clipflag |= 1;
01798         else if(ho[0] > bounds[1]*wco) clipflag |= 2;
01799         if(ho[1] > bounds[3]*wco) clipflag |= 4;
01800         else if(ho[1] < bounds[2]*wco) clipflag |= 8;
01801 
01802         copy_v4_v4(cache[cindex].ho, ho);
01803         cache[cindex].clip= clipflag;
01804         cache[cindex].index= index;
01805 
01806         return clipflag;
01807     }
01808 }
01809 
01810 void zbuf_render_project(float winmat[][4], const float co[3], float ho[4])
01811 {
01812     float vec[3];
01813 
01814     copy_v3_v3(vec, co);
01815     projectvert(vec, winmat, ho);
01816 }
01817 
01818 void zbuf_make_winmat(Render *re, float winmat[][4])
01819 {
01820     if(re->r.mode & R_PANORAMA) {
01821         float panomat[4][4]= MAT4_UNITY;
01822 
01823         panomat[0][0]= re->panoco;
01824         panomat[0][2]= re->panosi;
01825         panomat[2][0]= -re->panosi;
01826         panomat[2][2]= re->panoco;
01827 
01828         mult_m4_m4m4(winmat, re->winmat, panomat);
01829     }
01830     else
01831         copy_m4_m4(winmat, re->winmat);
01832 }
01833 
01834 /* do zbuffering and clip, f1 f2 f3 are hocos, c1 c2 c3 are clipping flags */
01835 
01836 void zbufclip(ZSpan *zspan, int obi, int zvlnr, float *f1, float *f2, float *f3, int c1, int c2, int c3)
01837 {
01838     float *vlzp[32][3], labda[3][2];
01839     float vez[400], *trias[40];
01840     
01841     if(c1 | c2 | c3) {  /* not in middle */
01842         if(c1 & c2 & c3) {  /* completely out */
01843             return;
01844         } else {    /* clipping */
01845             int arg, v, b, clipflag[3], b1, b2, b3, c4, clve=3, clvlo, clvl=1;
01846 
01847             vez[0]= f1[0]; vez[1]= f1[1]; vez[2]= f1[2]; vez[3]= f1[3];
01848             vez[4]= f2[0]; vez[5]= f2[1]; vez[6]= f2[2]; vez[7]= f2[3];
01849             vez[8]= f3[0]; vez[9]= f3[1]; vez[10]= f3[2];vez[11]= f3[3];
01850 
01851             vlzp[0][0]= vez;
01852             vlzp[0][1]= vez+4;
01853             vlzp[0][2]= vez+8;
01854 
01855             clipflag[0]= ( (c1 & 48) | (c2 & 48) | (c3 & 48) );
01856             if(clipflag[0]==0) {    /* othwerwise it needs to be calculated again, after the first (z) clip */
01857                 clipflag[1]= ( (c1 & 3) | (c2 & 3) | (c3 & 3) );
01858                 clipflag[2]= ( (c1 & 12) | (c2 & 12) | (c3 & 12) );
01859             }
01860             else clipflag[1]=clipflag[2]= 0;
01861             
01862             for(b=0;b<3;b++) {
01863                 
01864                 if(clipflag[b]) {
01865                 
01866                     clvlo= clvl;
01867                     
01868                     for(v=0; v<clvlo; v++) {
01869                     
01870                         if(vlzp[v][0]!=NULL) {  /* face is still there */
01871                             b2= b3 =0;  /* clip flags */
01872 
01873                             if(b==0) arg= 2;
01874                             else if (b==1) arg= 0;
01875                             else arg= 1;
01876                             
01877                             clippyra(labda[0], vlzp[v][0],vlzp[v][1], &b2,&b3, arg, zspan->clipcrop);
01878                             clippyra(labda[1], vlzp[v][1],vlzp[v][2], &b2,&b3, arg, zspan->clipcrop);
01879                             clippyra(labda[2], vlzp[v][2],vlzp[v][0], &b2,&b3, arg, zspan->clipcrop);
01880 
01881                             if(b2==0 && b3==1) {
01882                                 /* completely 'in', but we copy because of last for() loop in this section */;
01883                                 vlzp[clvl][0]= vlzp[v][0];
01884                                 vlzp[clvl][1]= vlzp[v][1];
01885                                 vlzp[clvl][2]= vlzp[v][2];
01886                                 vlzp[v][0]= NULL;
01887                                 clvl++;
01888                             } else if(b3==0) {
01889                                 vlzp[v][0]= NULL;
01890                                 /* completely 'out' */;
01891                             } else {
01892                                 b1=0;
01893                                 makevertpyra(vez, labda[0], trias, vlzp[v][0],vlzp[v][1], &b1,&clve);
01894                                 makevertpyra(vez, labda[1], trias, vlzp[v][1],vlzp[v][2], &b1,&clve);
01895                                 makevertpyra(vez, labda[2], trias, vlzp[v][2],vlzp[v][0], &b1,&clve);
01896 
01897                                 /* after front clip done: now set clip flags */
01898                                 if(b==0) {
01899                                     clipflag[1]= clipflag[2]= 0;
01900                                     f1= vez;
01901                                     for(b3=0; b3<clve; b3++) {
01902                                         c4= testclip(f1);
01903                                         clipflag[1] |= (c4 & 3);
01904                                         clipflag[2] |= (c4 & 12);
01905                                         f1+= 4;
01906                                     }
01907                                 }
01908                                 
01909                                 vlzp[v][0]= NULL;
01910                                 if(b1>2) {
01911                                     for(b3=3; b3<=b1; b3++) {
01912                                         vlzp[clvl][0]= trias[0];
01913                                         vlzp[clvl][1]= trias[b3-2];
01914                                         vlzp[clvl][2]= trias[b3-1];
01915                                         clvl++;
01916                                     }
01917                                 }
01918                             }
01919                         }
01920                     }
01921                 }
01922             }
01923 
01924             /* warning, this should never happen! */
01925             if(clve>38 || clvl>31) printf("clip overflow: clve clvl %d %d\n",clve,clvl);
01926 
01927             /* perspective division */
01928             f1=vez;
01929             for(c1=0;c1<clve;c1++) {
01930                 hoco_to_zco(zspan, f1, f1);
01931                 f1+=4;
01932             }
01933             for(b=1;b<clvl;b++) {
01934                 if(vlzp[b][0]) {
01935                     zspan->zbuffunc(zspan, obi, zvlnr, vlzp[b][0],vlzp[b][1],vlzp[b][2], NULL);
01936                 }
01937             }
01938             return;
01939         }
01940     }
01941 
01942     /* perspective division: HCS to ZCS */
01943     hoco_to_zco(zspan, vez, f1);
01944     hoco_to_zco(zspan, vez+4, f2);
01945     hoco_to_zco(zspan, vez+8, f3);
01946     zspan->zbuffunc(zspan, obi, zvlnr, vez,vez+4,vez+8, NULL);
01947 }
01948 
01949 void zbufclip4(ZSpan *zspan, int obi, int zvlnr, float *f1, float *f2, float *f3, float *f4, int c1, int c2, int c3, int c4)
01950 {
01951     float vez[16];
01952     
01953     if(c1 | c2 | c3 | c4) { /* not in middle */
01954         if(c1 & c2 & c3 & c4) { /* completely out */
01955             return;
01956         } else {    /* clipping */
01957             zbufclip(zspan, obi, zvlnr, f1, f2, f3, c1, c2, c3);
01958             zbufclip(zspan, obi, zvlnr, f1, f3, f4, c1, c3, c4);
01959         }
01960         return;
01961     }
01962 
01963     /* perspective division: HCS to ZCS */
01964     hoco_to_zco(zspan, vez, f1);
01965     hoco_to_zco(zspan, vez+4, f2);
01966     hoco_to_zco(zspan, vez+8, f3);
01967     hoco_to_zco(zspan, vez+12, f4);
01968 
01969     zspan->zbuffunc(zspan, obi, zvlnr, vez, vez+4, vez+8, vez+12);
01970 }
01971 
01972 /* ************** ZMASK ******************************** */
01973 
01974 #define EXTEND_PIXEL(a) if(temprectp[a]) {z+= rectz[a]; tot++;}
01975 
01976 /* changes the zbuffer to be ready for z-masking: applies an extend-filter, and then clears */
01977 static void zmask_rect(int *rectz, int *rectp, int xs, int ys, int neg)
01978 {
01979     int len=0, x, y;
01980     int *temprectp;
01981     int row1, row2, row3, *curp, *curz;
01982     
01983     temprectp= MEM_dupallocN(rectp);
01984     
01985     /* extend: if pixel is not filled in, we check surrounding pixels and average z value  */
01986     
01987     for(y=1; y<=ys; y++) {
01988         /* setup row indices */
01989         row1= (y-2)*xs;
01990         row2= row1 + xs;
01991         row3= row2 + xs;
01992         if(y==1)
01993             row1= row2;
01994         else if(y==ys)
01995             row3= row2;
01996         
01997         curp= rectp + (y-1)*xs;
01998         curz= rectz + (y-1)*xs;
01999         
02000         for(x=0; x<xs; x++, curp++, curz++) {
02001             if(curp[0]==0) {
02002                 int tot= 0;
02003                 float z= 0.0f;
02004                 
02005                 EXTEND_PIXEL(row1);
02006                 EXTEND_PIXEL(row2);
02007                 EXTEND_PIXEL(row3);
02008                 EXTEND_PIXEL(row1 + 1);
02009                 EXTEND_PIXEL(row3 + 1);
02010                 if(x!=xs-1) {
02011                     EXTEND_PIXEL(row1 + 2);
02012                     EXTEND_PIXEL(row2 + 2);
02013                     EXTEND_PIXEL(row3 + 2);
02014                 }                   
02015                 if(tot) {
02016                     len++;
02017                     curz[0]= (int)(z/(float)tot);
02018                     curp[0]= -1;    /* env */
02019                 }
02020             }
02021             
02022             if(x!=0) {
02023                 row1++; row2++; row3++;
02024             }
02025         }
02026     }
02027 
02028     MEM_freeN(temprectp);
02029     
02030     if(neg); /* z values for negative are already correct */
02031     else {
02032         /* clear not filled z values */
02033         for(len= xs*ys -1; len>=0; len--) {
02034             if(rectp[len]==0) {
02035                 rectz[len] = -0x7FFFFFFF;
02036                 rectp[len]= -1; /* env code */
02037             }   
02038         }
02039     }
02040 }
02041 
02042 
02043 
02044 
02045 /* ***************** ZBUFFER MAIN ROUTINES **************** */
02046 
02047 void zbuffer_solid(RenderPart *pa, RenderLayer *rl, void(*fillfunc)(RenderPart*, ZSpan*, int, void*), void *data)
02048 {
02049     ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE];
02050     ZSpan zspans[16], *zspan; /* 16 = RE_MAX_OSA */
02051     VlakRen *vlr= NULL;
02052     VertRen *v1, *v2, *v3, *v4;
02053     Material *ma=0;
02054     ObjectInstanceRen *obi;
02055     ObjectRen *obr;
02056     float obwinmat[4][4], winmat[4][4], bounds[4];
02057     float ho1[4], ho2[4], ho3[4], ho4[4]={0};
02058     unsigned int lay= rl->lay, lay_zmask= rl->lay_zmask;
02059     int i, v, zvlnr, zsample, samples, c1, c2, c3, c4=0;
02060     short nofill=0, env=0, wire=0, zmaskpass=0;
02061     short all_z= (rl->layflag & SCE_LAY_ALL_Z) && !(rl->layflag & SCE_LAY_ZMASK);
02062     short neg_zmask= (rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK);
02063 
02064     zbuf_make_winmat(&R, winmat);
02065     
02066     samples= (R.osa? R.osa: 1);
02067     samples= MIN2(4, samples-pa->sample);
02068 
02069     for(zsample=0; zsample<samples; zsample++) {
02070         zspan= &zspans[zsample];
02071 
02072         zbuffer_part_bounds(R.winx, R.winy, pa, bounds);
02073         zbuf_alloc_span(zspan, pa->rectx, pa->recty, R.clipcrop);
02074         
02075         /* needed for transform from hoco to zbuffer co */
02076         zspan->zmulx= ((float)R.winx)/2.0f;
02077         zspan->zmuly= ((float)R.winy)/2.0f;
02078         
02079         if(R.osa) {
02080             zspan->zofsx= -pa->disprect.xmin - R.jit[pa->sample+zsample][0];
02081             zspan->zofsy= -pa->disprect.ymin - R.jit[pa->sample+zsample][1];
02082         }
02083         else if(R.i.curblur) {
02084             zspan->zofsx= -pa->disprect.xmin - R.mblur_jit[R.i.curblur-1][0];
02085             zspan->zofsy= -pa->disprect.ymin - R.mblur_jit[R.i.curblur-1][1];
02086         }
02087         else {
02088             zspan->zofsx= -pa->disprect.xmin;
02089             zspan->zofsy= -pa->disprect.ymin;
02090         }
02091         /* to center the sample position */
02092         zspan->zofsx -= 0.5f;
02093         zspan->zofsy -= 0.5f;
02094         
02095         /* the buffers */
02096         if(zsample == samples-1) {
02097             zspan->rectp= pa->rectp;
02098             zspan->recto= pa->recto;
02099 
02100             if(neg_zmask)
02101                 zspan->rectz= pa->rectmask;
02102             else
02103                 zspan->rectz= pa->rectz;
02104         }
02105         else {
02106             zspan->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto");
02107             zspan->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
02108             zspan->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
02109         }
02110 
02111         fillrect(zspan->rectz, pa->rectx, pa->recty, 0x7FFFFFFF);
02112         fillrect(zspan->rectp, pa->rectx, pa->recty, 0);
02113         fillrect(zspan->recto, pa->rectx, pa->recty, 0);
02114     }
02115 
02116     /* in case zmask we fill Z for objects in lay_zmask first, then clear Z, and then do normal zbuffering */
02117     if(rl->layflag & SCE_LAY_ZMASK)
02118         zmaskpass= 1;
02119     
02120     for(; zmaskpass >=0; zmaskpass--) {
02121         ma= NULL;
02122 
02123         /* filling methods */
02124         for(zsample=0; zsample<samples; zsample++) {
02125             zspan= &zspans[zsample];
02126 
02127             if(zmaskpass && neg_zmask)
02128                 zspan->zbuffunc= zbuffillGLinv4;
02129             else
02130                 zspan->zbuffunc= zbuffillGL4;
02131             zspan->zbuflinefunc= zbufline;
02132         }
02133 
02134         /* regular zbuffering loop, does all sample buffers */
02135         for(i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) {
02136             obr= obi->obr;
02137 
02138             /* continue happens in 2 different ways... zmaskpass only does lay_zmask stuff */
02139             if(zmaskpass) {
02140                 if((obi->lay & lay_zmask)==0)
02141                     continue;
02142             }
02143             else if(!all_z && !(obi->lay & (lay|lay_zmask)))
02144                 continue;
02145             
02146             if(obi->flag & R_TRANSFORMED)
02147                 mult_m4_m4m4(obwinmat, winmat, obi->mat);
02148             else
02149                 copy_m4_m4(obwinmat, winmat);
02150 
02151             if(clip_render_object(obi->obr->boundbox, bounds, obwinmat))
02152                 continue;
02153 
02154             zbuf_project_cache_clear(cache, obr->totvert);
02155 
02156             for(v=0; v<obr->totvlak; v++) {
02157                 if((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak;
02158                 else vlr++;
02159 
02160                 /* the cases: visible for render, only z values, zmask, nothing */
02161                 if(obi->lay & lay) {
02162                     if(vlr->mat!=ma) {
02163                         ma= vlr->mat;
02164                         nofill= (ma->mode & MA_ONLYCAST) || ((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP));
02165                         env= (ma->mode & MA_ENV);
02166                         wire= (ma->material_type == MA_TYPE_WIRE);
02167                         
02168                         for(zsample=0; zsample<samples; zsample++) {
02169                             if(ma->mode & MA_ZINV || (zmaskpass && neg_zmask))
02170                                 zspans[zsample].zbuffunc= zbuffillGLinv4;
02171                             else
02172                                 zspans[zsample].zbuffunc= zbuffillGL4;
02173                         }
02174                     }
02175                 }
02176                 else if(all_z || (obi->lay & lay_zmask)) {
02177                     env= 1;
02178                     nofill= 0;
02179                     ma= NULL; 
02180                 }
02181                 else {
02182                     nofill= 1;
02183                     ma= NULL;   /* otherwise nofill can hang */
02184                 }
02185 
02186                 if(!(vlr->flag & R_HIDDEN) && nofill==0) {
02187                     unsigned short partclip;
02188                     
02189                     v1= vlr->v1;
02190                     v2= vlr->v2;
02191                     v3= vlr->v3;
02192                     v4= vlr->v4;
02193 
02194                     c1= zbuf_part_project(cache, v1->index, obwinmat, bounds, v1->co, ho1);
02195                     c2= zbuf_part_project(cache, v2->index, obwinmat, bounds, v2->co, ho2);
02196                     c3= zbuf_part_project(cache, v3->index, obwinmat, bounds, v3->co, ho3);
02197 
02198                     /* partclipping doesn't need viewplane clipping */
02199                     partclip= c1 & c2 & c3;
02200                     if(v4) {
02201                         c4= zbuf_part_project(cache, v4->index, obwinmat, bounds, v4->co, ho4);
02202                         partclip &= c4;
02203                     }
02204 
02205                     if(partclip==0) {
02206                         
02207                         if(env) zvlnr= -1;
02208                         else zvlnr= v+1;
02209 
02210                         c1= testclip(ho1);
02211                         c2= testclip(ho2);
02212                         c3= testclip(ho3);
02213                         if(v4)
02214                             c4= testclip(ho4);
02215 
02216                         for(zsample=0; zsample<samples; zsample++) {
02217                             zspan= &zspans[zsample];
02218 
02219                             if(wire) {
02220                                 if(v4)
02221                                     zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
02222                                 else
02223                                     zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, 0, c1, c2, c3, 0);
02224                             }
02225                             else {
02226                                 /* strands allow to be filled in as quad */
02227                                 if(v4 && (vlr->flag & R_STRAND)) {
02228                                     zbufclip4(zspan, i, zvlnr, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
02229                                 }
02230                                 else {
02231                                     zbufclip(zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3);
02232                                     if(v4)
02233                                         zbufclip(zspan, i, (env)? zvlnr: zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4);
02234                                 }
02235                             }
02236                         }
02237                     }
02238                 }
02239             }
02240         }
02241         
02242         /* clear all z to close value, so it works as mask for next passes (ztra+strand) */
02243         if(zmaskpass) {
02244             for(zsample=0; zsample<samples; zsample++) {
02245                 zspan= &zspans[zsample];
02246 
02247                 if(neg_zmask) {
02248                     zspan->rectmask= zspan->rectz;
02249                     if(zsample == samples-1)
02250                         zspan->rectz= pa->rectz;
02251                     else
02252                         zspan->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
02253                     fillrect(zspan->rectz, pa->rectx, pa->recty, 0x7FFFFFFF);
02254 
02255                     zmask_rect(zspan->rectmask, zspan->rectp, pa->rectx, pa->recty, 1);
02256                 }
02257                 else
02258                     zmask_rect(zspan->rectz, zspan->rectp, pa->rectx, pa->recty, 0);
02259             }
02260         }
02261     }
02262 
02263     for(zsample=0; zsample<samples; zsample++) {
02264         zspan= &zspans[zsample];
02265 
02266         if(fillfunc)
02267             fillfunc(pa, zspan, pa->sample+zsample, data);
02268 
02269         if(zsample != samples-1) {
02270             MEM_freeN(zspan->rectz);
02271             MEM_freeN(zspan->rectp);
02272             MEM_freeN(zspan->recto);
02273             if(zspan->rectmask)
02274                 MEM_freeN(zspan->rectmask);
02275         }
02276 
02277         zbuf_free_span(zspan);
02278     }
02279 }
02280 
02281 void zbuffer_shadow(Render *re, float winmat[][4], LampRen *lar, int *rectz, int size, float jitx, float jity)
02282 {
02283     ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE];
02284     ZSpan zspan;
02285     ObjectInstanceRen *obi;
02286     ObjectRen *obr;
02287     VlakRen *vlr= NULL;
02288     Material *ma= NULL;
02289     StrandSegment sseg;
02290     StrandRen *strand= NULL;
02291     StrandVert *svert;
02292     StrandBound *sbound;
02293     float obwinmat[4][4], ho1[4], ho2[4], ho3[4], ho4[4];
02294     int a, b, c, i, c1, c2, c3, c4, ok=1, lay= -1;
02295 
02296     if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) lay= lar->lay;
02297 
02298     /* 1.0f for clipping in clippyra()... bad stuff actually */
02299     zbuf_alloc_span(&zspan, size, size, 1.0f);
02300     zspan.zmulx=  ((float)size)/2.0f;
02301     zspan.zmuly=  ((float)size)/2.0f;
02302     /* -0.5f to center the sample position */
02303     zspan.zofsx= jitx - 0.5f;
02304     zspan.zofsy= jity - 0.5f;
02305     
02306     /* the buffers */
02307     zspan.rectz= rectz;
02308     fillrect(rectz, size, size, 0x7FFFFFFE);
02309     if(lar->buftype==LA_SHADBUF_HALFWAY) {
02310         zspan.rectz1= MEM_mallocN(size*size*sizeof(int), "seconday z buffer");
02311         fillrect(zspan.rectz1, size, size, 0x7FFFFFFE);
02312     }
02313     
02314     /* filling methods */
02315     zspan.zbuflinefunc= zbufline_onlyZ;
02316     zspan.zbuffunc= zbuffillGL_onlyZ;
02317 
02318     for(i=0, obi=re->instancetable.first; obi; i++, obi=obi->next) {
02319         obr= obi->obr;
02320 
02321         if(obr->ob==re->excludeob)
02322             continue;
02323         else if(!(obi->lay & lay))
02324             continue;
02325 
02326         if(obi->flag & R_TRANSFORMED)
02327             mult_m4_m4m4(obwinmat, winmat, obi->mat);
02328         else
02329             copy_m4_m4(obwinmat, winmat);
02330 
02331         if(clip_render_object(obi->obr->boundbox, NULL, obwinmat))
02332             continue;
02333 
02334         zbuf_project_cache_clear(cache, obr->totvert);
02335 
02336         /* faces */
02337         for(a=0; a<obr->totvlak; a++) {
02338 
02339             if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
02340             else vlr++;
02341 
02342             /* note, these conditions are copied in shadowbuf_autoclip() */
02343             if(vlr->mat!= ma) {
02344                 ma= vlr->mat;
02345                 ok= 1;
02346                 if((ma->mode & MA_SHADBUF)==0) ok= 0;
02347             }
02348 
02349             if(ok && (obi->lay & lay) && !(vlr->flag & R_HIDDEN)) {
02350                 c1= zbuf_shadow_project(cache, vlr->v1->index, obwinmat, vlr->v1->co, ho1);
02351                 c2= zbuf_shadow_project(cache, vlr->v2->index, obwinmat, vlr->v2->co, ho2);
02352                 c3= zbuf_shadow_project(cache, vlr->v3->index, obwinmat, vlr->v3->co, ho3);
02353 
02354                 if((ma->material_type == MA_TYPE_WIRE) || (vlr->flag & R_STRAND)) {
02355                     if(vlr->v4) {
02356                         c4= zbuf_shadow_project(cache, vlr->v4->index, obwinmat, vlr->v4->co, ho4);
02357                         zbufclipwire(&zspan, 0, a+1, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
02358                     }
02359                     else
02360                         zbufclipwire(&zspan, 0, a+1, vlr->ec, ho1, ho2, ho3, 0, c1, c2, c3, 0);
02361                 }
02362                 else {
02363                     if(vlr->v4) {
02364                         c4= zbuf_shadow_project(cache, vlr->v4->index, obwinmat, vlr->v4->co, ho4);
02365                         zbufclip4(&zspan, 0, 0, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
02366                     }
02367                     else
02368                         zbufclip(&zspan, 0, 0, ho1, ho2, ho3, c1, c2, c3);
02369                 }
02370             }
02371 
02372             if((a & 255)==255 && re->test_break(re->tbh)) 
02373                 break;
02374         }
02375 
02376         /* strands */
02377         if(obr->strandbuf) {
02378             /* for each bounding box containing a number of strands */
02379             sbound= obr->strandbuf->bound;
02380             for(c=0; c<obr->strandbuf->totbound; c++, sbound++) {
02381                 if(clip_render_object(sbound->boundbox, NULL, obwinmat))
02382                     continue;
02383 
02384                 /* for each strand in this bounding box */
02385                 for(a=sbound->start; a<sbound->end; a++) {
02386                     strand= RE_findOrAddStrand(obr, a);
02387 
02388                     sseg.obi= obi;
02389                     sseg.buffer= strand->buffer;
02390                     sseg.sqadaptcos= sseg.buffer->adaptcos;
02391                     sseg.sqadaptcos *= sseg.sqadaptcos;
02392                     sseg.strand= strand;
02393                     svert= strand->vert;
02394 
02395                     /* note, these conditions are copied in shadowbuf_autoclip() */
02396                     if(sseg.buffer->ma!= ma) {
02397                         ma= sseg.buffer->ma;
02398                         ok= 1;
02399                         if((ma->mode & MA_SHADBUF)==0) ok= 0;
02400                     }
02401 
02402                     if(ok && (sseg.buffer->lay & lay)) {
02403                         zbuf_project_cache_clear(cache, strand->totvert);
02404 
02405                         for(b=0; b<strand->totvert-1; b++, svert++) {
02406                             sseg.v[0]= (b > 0)? (svert-1): svert;
02407                             sseg.v[1]= svert;
02408                             sseg.v[2]= svert+1;
02409                             sseg.v[3]= (b < strand->totvert-2)? svert+2: svert+1;
02410 
02411                             c1= zbuf_shadow_project(cache, sseg.v[0]-strand->vert, obwinmat, sseg.v[0]->co, ho1);
02412                             c2= zbuf_shadow_project(cache, sseg.v[1]-strand->vert, obwinmat, sseg.v[1]->co, ho2);
02413                             c3= zbuf_shadow_project(cache, sseg.v[2]-strand->vert, obwinmat, sseg.v[2]->co, ho3);
02414                             c4= zbuf_shadow_project(cache, sseg.v[3]-strand->vert, obwinmat, sseg.v[3]->co, ho4);
02415 
02416                             if(!(c1 & c2 & c3 & c4))
02417                                 render_strand_segment(re, winmat, NULL, &zspan, 1, &sseg);
02418                         }
02419                     }
02420 
02421                     if((a & 255)==255 && re->test_break(re->tbh)) 
02422                         break;
02423                 }
02424             }
02425         }
02426 
02427         if(re->test_break(re->tbh)) 
02428             break;
02429     }
02430     
02431     /* merge buffers */
02432     if(lar->buftype==LA_SHADBUF_HALFWAY) {
02433         for(a=size*size -1; a>=0; a--)
02434             rectz[a]= (rectz[a]>>1) + (zspan.rectz1[a]>>1);
02435         
02436         MEM_freeN(zspan.rectz1);
02437     }
02438     
02439     zbuf_free_span(&zspan);
02440 }
02441 
02442 static void zbuffill_sss(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, float *v3, float *v4)
02443 {
02444     double zxd, zyd, zy0, z;
02445     float x0, y0, x1, y1, x2, y2, z0, z1, z2, xx1, *span1, *span2;
02446     int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2;
02447     /* init */
02448     zbuf_init_span(zspan);
02449     
02450     /* set spans */
02451     zbuf_add_to_span(zspan, v1, v2);
02452     zbuf_add_to_span(zspan, v2, v3);
02453     if(v4) {
02454         zbuf_add_to_span(zspan, v3, v4);
02455         zbuf_add_to_span(zspan, v4, v1);
02456     }
02457     else 
02458         zbuf_add_to_span(zspan, v3, v1);
02459     
02460     /* clipped */
02461     if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
02462     
02463     if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
02464     if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
02465     
02466     if(my2<my0) return;
02467     
02468     /* ZBUF DX DY, in floats still */
02469     x1= v1[0]- v2[0];
02470     x2= v2[0]- v3[0];
02471     y1= v1[1]- v2[1];
02472     y2= v2[1]- v3[1];
02473     z1= v1[2]- v2[2];
02474     z2= v2[2]- v3[2];
02475     
02476     x0= y1*z2-z1*y2;
02477     y0= z1*x2-x1*z2;
02478     z0= x1*y2-y1*x2;
02479     
02480     if(z0==0.0f) return;
02481     
02482     xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
02483     zxd= -(double)x0/(double)z0;
02484     zyd= -(double)y0/(double)z0;
02485     zy0= ((double)my2)*zyd + (double)xx1;
02486     
02487     /* correct span */
02488     sn1= (my0 + my2)/2;
02489     if(zspan->span1[sn1] < zspan->span2[sn1]) {
02490         span1= zspan->span1+my2;
02491         span2= zspan->span2+my2;
02492     }
02493     else {
02494         span1= zspan->span2+my2;
02495         span2= zspan->span1+my2;
02496     }
02497     
02498     for(y=my2; y>=my0; y--, span1--, span2--) {
02499         sn1= floor(*span1);
02500         sn2= floor(*span2);
02501         sn1++; 
02502         
02503         if(sn2>=rectx) sn2= rectx-1;
02504         if(sn1<0) sn1= 0;
02505         
02506         z= (double)sn1*zxd + zy0;
02507         
02508         for(x= sn1; x<=sn2; x++, z+=zxd)
02509             zspan->sss_func(zspan->sss_handle, obi, zvlnr, x, y, z);
02510         
02511         zy0 -= zyd;
02512     }
02513 }
02514 
02515 void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(void*, int, int, int, int, int))
02516 {
02517     ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE];
02518     ZSpan zspan;
02519     ObjectInstanceRen *obi;
02520     ObjectRen *obr;
02521     VlakRen *vlr= NULL;
02522     VertRen *v1, *v2, *v3, *v4;
02523     Material *ma=0, *sss_ma= R.sss_mat;
02524     float obwinmat[4][4], winmat[4][4], bounds[4];
02525     float ho1[4], ho2[4], ho3[4], ho4[4]={0};
02526     int i, v, zvlnr, c1, c2, c3, c4=0;
02527     short nofill=0, env=0, wire=0;
02528     
02529     zbuf_make_winmat(&R, winmat);
02530     zbuffer_part_bounds(R.winx, R.winy, pa, bounds);
02531     zbuf_alloc_span(&zspan, pa->rectx, pa->recty, R.clipcrop);
02532 
02533     zspan.sss_handle= handle;
02534     zspan.sss_func= func;
02535     
02536     /* needed for transform from hoco to zbuffer co */
02537     zspan.zmulx=  ((float)R.winx)/2.0f;
02538     zspan.zmuly=  ((float)R.winy)/2.0f;
02539     
02540     /* -0.5f to center the sample position */
02541     zspan.zofsx= -pa->disprect.xmin - 0.5f;
02542     zspan.zofsy= -pa->disprect.ymin - 0.5f;
02543     
02544     /* filling methods */
02545     zspan.zbuffunc= zbuffill_sss;
02546 
02547     /* fill front and back zbuffer */
02548     if(pa->rectz) {
02549         fillrect(pa->recto, pa->rectx, pa->recty, 0); 
02550         fillrect(pa->rectp, pa->rectx, pa->recty, 0); 
02551         fillrect(pa->rectz, pa->rectx, pa->recty, 0x7FFFFFFF);
02552     }
02553     if(pa->rectbackz) {
02554         fillrect(pa->rectbacko, pa->rectx, pa->recty, 0); 
02555         fillrect(pa->rectbackp, pa->rectx, pa->recty, 0); 
02556         fillrect(pa->rectbackz, pa->rectx, pa->recty, -0x7FFFFFFF);
02557     }
02558 
02559     for(i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) {
02560         obr= obi->obr;
02561 
02562         if(!(obi->lay & lay))
02563             continue;
02564 
02565         if(obi->flag & R_TRANSFORMED)
02566             mult_m4_m4m4(obwinmat, winmat, obi->mat);
02567         else
02568             copy_m4_m4(obwinmat, winmat);
02569 
02570         if(clip_render_object(obi->obr->boundbox, bounds, obwinmat))
02571             continue;
02572 
02573         zbuf_project_cache_clear(cache, obr->totvert);
02574 
02575         for(v=0; v<obr->totvlak; v++) {
02576             if((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak;
02577             else vlr++;
02578             
02579             if(material_in_material(vlr->mat, sss_ma)) {
02580                 /* three cases, visible for render, only z values and nothing */
02581                 if(obi->lay & lay) {
02582                     if(vlr->mat!=ma) {
02583                         ma= vlr->mat;
02584                         nofill= ma->mode & MA_ONLYCAST;
02585                         env= (ma->mode & MA_ENV);
02586                         wire= (ma->material_type == MA_TYPE_WIRE);
02587                     }
02588                 }
02589                 else {
02590                     nofill= 1;
02591                     ma= NULL;   /* otherwise nofill can hang */
02592                 }
02593                 
02594                 if(nofill==0 && wire==0 && env==0) {
02595                     unsigned short partclip;
02596                     
02597                     v1= vlr->v1;
02598                     v2= vlr->v2;
02599                     v3= vlr->v3;
02600                     v4= vlr->v4;
02601 
02602                     c1= zbuf_part_project(cache, v1->index, obwinmat, bounds, v1->co, ho1);
02603                     c2= zbuf_part_project(cache, v2->index, obwinmat, bounds, v2->co, ho2);
02604                     c3= zbuf_part_project(cache, v3->index, obwinmat, bounds, v3->co, ho3);
02605 
02606                     /* partclipping doesn't need viewplane clipping */
02607                     partclip= c1 & c2 & c3;
02608                     if(v4) {
02609                         c4= zbuf_part_project(cache, v4->index, obwinmat, bounds, v4->co, ho4);
02610                         partclip &= c4;
02611                     }
02612 
02613                     if(partclip==0) {
02614                         c1= testclip(ho1);
02615                         c2= testclip(ho2);
02616                         c3= testclip(ho3);
02617 
02618                         zvlnr= v+1;
02619                         zbufclip(&zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3);
02620                         if(v4) {
02621                             c4= testclip(ho4);
02622                             zbufclip(&zspan, i, zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4);
02623                         }
02624                     }
02625                 }
02626             }
02627         }
02628     }
02629         
02630     zbuf_free_span(&zspan);
02631 }
02632 
02633 /* ******************** VECBLUR ACCUM BUF ************************* */
02634 
02635 typedef struct DrawBufPixel {
02636     float *colpoin;
02637     float alpha;
02638 } DrawBufPixel;
02639 
02640 
02641 static void zbuf_fill_in_rgba(ZSpan *zspan, DrawBufPixel *col, float *v1, float *v2, float *v3, float *v4)
02642 {
02643     DrawBufPixel *rectpofs, *rp;
02644     double zxd, zyd, zy0, zverg;
02645     float x0,y0,z0;
02646     float x1,y1,z1,x2,y2,z2,xx1;
02647     float *span1, *span2;
02648     float *rectzofs, *rz;
02649     int x, y;
02650     int sn1, sn2, rectx, my0, my2;
02651     
02652     /* init */
02653     zbuf_init_span(zspan);
02654     
02655     /* set spans */
02656     zbuf_add_to_span(zspan, v1, v2);
02657     zbuf_add_to_span(zspan, v2, v3);
02658     zbuf_add_to_span(zspan, v3, v4);
02659     zbuf_add_to_span(zspan, v4, v1);
02660     
02661     /* clipped */
02662     if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
02663     
02664     if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
02665     if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
02666     
02667     //  printf("my %d %d\n", my0, my2);
02668     if(my2<my0) return;
02669     
02670     /* ZBUF DX DY, in floats still */
02671     x1= v1[0]- v2[0];
02672     x2= v2[0]- v3[0];
02673     y1= v1[1]- v2[1];
02674     y2= v2[1]- v3[1];
02675     z1= v1[2]- v2[2];
02676     z2= v2[2]- v3[2];
02677     x0= y1*z2-z1*y2;
02678     y0= z1*x2-x1*z2;
02679     z0= x1*y2-y1*x2;
02680     
02681     if(z0==0.0f) return;
02682     
02683     xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
02684     
02685     zxd= -(double)x0/(double)z0;
02686     zyd= -(double)y0/(double)z0;
02687     zy0= ((double)my2)*zyd + (double)xx1;
02688     
02689     /* start-offset in rect */
02690     rectx= zspan->rectx;
02691     rectzofs= (float *)(zspan->rectz + rectx*my2);
02692     rectpofs= ((DrawBufPixel *)zspan->rectp) + rectx*my2;
02693     
02694     /* correct span */
02695     sn1= (my0 + my2)/2;
02696     if(zspan->span1[sn1] < zspan->span2[sn1]) {
02697         span1= zspan->span1+my2;
02698         span2= zspan->span2+my2;
02699     }
02700     else {
02701         span1= zspan->span2+my2;
02702         span2= zspan->span1+my2;
02703     }
02704     
02705     for(y=my2; y>=my0; y--, span1--, span2--) {
02706         
02707         sn1= floor(*span1);
02708         sn2= floor(*span2);
02709         sn1++; 
02710         
02711         if(sn2>=rectx) sn2= rectx-1;
02712         if(sn1<0) sn1= 0;
02713         
02714         if(sn2>=sn1) {
02715             zverg= (double)sn1*zxd + zy0;
02716             rz= rectzofs+sn1;
02717             rp= rectpofs+sn1;
02718             x= sn2-sn1;
02719             
02720             while(x>=0) {
02721                 if( zverg < *rz) {
02722                     *rz= zverg;
02723                     *rp= *col;
02724                 }
02725                 zverg+= zxd;
02726                 rz++; 
02727                 rp++; 
02728                 x--;
02729             }
02730         }
02731         
02732         zy0-=zyd;
02733         rectzofs-= rectx;
02734         rectpofs-= rectx;
02735     }
02736 }
02737 
02738 /* char value==255 is filled in, rest should be zero */
02739 /* returns alpha values, but sets alpha to 1 for zero alpha pixels that have an alpha value as neighbour */
02740 void antialias_tagbuf(int xsize, int ysize, char *rectmove)
02741 {
02742     char *row1, *row2, *row3;
02743     char prev, next;
02744     int a, x, y, step;
02745     
02746     /* 1: tag pixels to be candidate for AA */
02747     for(y=2; y<ysize; y++) {
02748         /* setup rows */
02749         row1= rectmove + (y-2)*xsize;
02750         row2= row1 + xsize;
02751         row3= row2 + xsize;
02752         for(x=2; x<xsize; x++, row1++, row2++, row3++) {
02753             if(row2[1]) {
02754                 if(row2[0]==0 || row2[2]==0 || row1[1]==0 || row3[1]==0)
02755                     row2[1]= 128;
02756             }
02757         }
02758     }
02759     
02760     /* 2: evaluate horizontal scanlines and calculate alphas */
02761     row1= rectmove;
02762     for(y=0; y<ysize; y++) {
02763         row1++;
02764         for(x=1; x<xsize; x++, row1++) {
02765             if(row1[0]==128 && row1[1]==128) {
02766                 /* find previous color and next color and amount of steps to blend */
02767                 prev= row1[-1];
02768                 step= 1;
02769                 while(x+step<xsize && row1[step]==128)
02770                     step++;
02771                 
02772                 if(x+step!=xsize) {
02773                     /* now we can blend values */
02774                     next= row1[step];
02775 
02776                     /* note, prev value can be next value, but we do this loop to clear 128 then */
02777                     for(a=0; a<step; a++) {
02778                         int fac, mfac;
02779                         
02780                         fac= ((a+1)<<8)/(step+1);
02781                         mfac= 255-fac;
02782                         
02783                         row1[a]= (prev*mfac + next*fac)>>8; 
02784                     }
02785                 }
02786             }
02787         }
02788     }
02789     
02790     /* 3: evaluate vertical scanlines and calculate alphas */
02791     /*    use for reading a copy of the original tagged buffer */
02792     for(x=0; x<xsize; x++) {
02793         row1= rectmove + x+xsize;
02794         
02795         for(y=1; y<ysize; y++, row1+=xsize) {
02796             if(row1[0]==128 && row1[xsize]==128) {
02797                 /* find previous color and next color and amount of steps to blend */
02798                 prev= row1[-xsize];
02799                 step= 1;
02800                 while(y+step<ysize && row1[step*xsize]==128)
02801                     step++;
02802                 
02803                 if(y+step!=ysize) {
02804                     /* now we can blend values */
02805                     next= row1[step*xsize];
02806                     /* note, prev value can be next value, but we do this loop to clear 128 then */
02807                     for(a=0; a<step; a++) {
02808                         int fac, mfac;
02809                         
02810                         fac= ((a+1)<<8)/(step+1);
02811                         mfac= 255-fac;
02812                         
02813                         row1[a*xsize]= (prev*mfac + next*fac)>>8; 
02814                     }
02815                 }
02816             }
02817         }
02818     }
02819     
02820     /* last: pixels with 0 we fill in zbuffer, with 1 we skip for mask */
02821     for(y=2; y<ysize; y++) {
02822         /* setup rows */
02823         row1= rectmove + (y-2)*xsize;
02824         row2= row1 + xsize;
02825         row3= row2 + xsize;
02826         for(x=2; x<xsize; x++, row1++, row2++, row3++) {
02827             if(row2[1]==0) {
02828                 if(row2[0]>1 || row2[2]>1 || row1[1]>1 || row3[1]>1)
02829                     row2[1]= 1;
02830             }
02831         }
02832     }
02833 }
02834 
02835 /* in: two vectors, first vector points from origin back in time, 2nd vector points to future */
02836 /* we make this into 3 points, center point is (0,0) */
02837 /* and offset the center point just enough to make curve go through midpoint */
02838 
02839 static void quad_bezier_2d(float *result, float *v1, float *v2, float *ipodata)
02840 {
02841     float p1[2], p2[2], p3[2];
02842     
02843     p3[0]= -v2[0];
02844     p3[1]= -v2[1];
02845     
02846     p1[0]= v1[0];
02847     p1[1]= v1[1];
02848     
02849     /* official formula 2*p2 - .5*p1 - .5*p3 */
02850     p2[0]= -0.5f*p1[0] - 0.5f*p3[0];
02851     p2[1]= -0.5f*p1[1] - 0.5f*p3[1];
02852     
02853     result[0]= ipodata[0]*p1[0] + ipodata[1]*p2[0] + ipodata[2]*p3[0];
02854     result[1]= ipodata[0]*p1[1] + ipodata[1]*p2[1] + ipodata[2]*p3[1];
02855 }
02856 
02857 static void set_quad_bezier_ipo(float fac, float *data)
02858 {
02859     float mfac= (1.0f-fac);
02860     
02861     data[0]= mfac*mfac;
02862     data[1]= 2.0f*mfac*fac;
02863     data[2]= fac*fac;
02864 }
02865 
02866 void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float *newrect, float *imgrect, float *vecbufrect, float *zbufrect)
02867 {
02868     ZSpan zspan;
02869     DrawBufPixel *rectdraw, *dr;
02870     static float jit[256][2];
02871     float v1[3], v2[3], v3[3], v4[3], fx, fy;
02872     float *rectvz, *dvz, *dimg, *dvec1, *dvec2, *dz, *dz1, *dz2, *rectz;
02873     float *minvecbufrect= NULL, *rectweight, *rw, *rectmax, *rm, *ro;
02874     float maxspeedsq= (float)nbd->maxspeed*nbd->maxspeed;
02875     int y, x, step, maxspeed=nbd->maxspeed, samples= nbd->samples;
02876     int tsktsk= 0;
02877     static int firsttime= 1;
02878     char *rectmove, *dm;
02879     
02880     zbuf_alloc_span(&zspan, xsize, ysize, 1.0f);
02881     zspan.zmulx=  ((float)xsize)/2.0f;
02882     zspan.zmuly=  ((float)ysize)/2.0f;
02883     zspan.zofsx= 0.0f;
02884     zspan.zofsy= 0.0f;
02885     
02886     /* the buffers */
02887     rectz= MEM_mapallocN(sizeof(float)*xsize*ysize, "zbuf accum");
02888     zspan.rectz= (int *)rectz;
02889     
02890     rectmove= MEM_mapallocN(xsize*ysize, "rectmove");
02891     rectdraw= MEM_mapallocN(sizeof(DrawBufPixel)*xsize*ysize, "rect draw");
02892     zspan.rectp= (int *)rectdraw;
02893 
02894     rectweight= MEM_mapallocN(sizeof(float)*xsize*ysize, "rect weight");
02895     rectmax= MEM_mapallocN(sizeof(float)*xsize*ysize, "rect max");
02896     
02897     /* debug... check if PASS_VECTOR_MAX still is in buffers */
02898     dvec1= vecbufrect;
02899     for(x= 4*xsize*ysize; x>0; x--, dvec1++) {
02900         if(dvec1[0]==PASS_VECTOR_MAX) {
02901             dvec1[0]= 0.0f;
02902             tsktsk= 1;
02903         }
02904     }
02905     if(tsktsk) printf("Found uninitialized speed in vector buffer... fixed.\n");
02906     
02907     /* min speed? then copy speedbuffer to recalculate speed vectors */
02908     if(nbd->minspeed) {
02909         float minspeed= (float)nbd->minspeed;
02910         float minspeedsq= minspeed*minspeed;
02911         
02912         minvecbufrect= MEM_mapallocN(4*sizeof(float)*xsize*ysize, "minspeed buf");
02913         
02914         dvec1= vecbufrect;
02915         dvec2= minvecbufrect;
02916         for(x= 2*xsize*ysize; x>0; x--, dvec1+=2, dvec2+=2) {
02917             if(dvec1[0]==0.0f && dvec1[1]==0.0f) {
02918                 dvec2[0]= dvec1[0];
02919                 dvec2[1]= dvec1[1];
02920             }
02921             else {
02922                 float speedsq= dvec1[0]*dvec1[0] + dvec1[1]*dvec1[1];
02923                 if(speedsq <= minspeedsq) {
02924                     dvec2[0]= 0.0f;
02925                     dvec2[1]= 0.0f;
02926                 }
02927                 else {
02928                     speedsq= 1.0f - minspeed/sqrt(speedsq);
02929                     dvec2[0]= speedsq*dvec1[0];
02930                     dvec2[1]= speedsq*dvec1[1];
02931                 }
02932             }
02933         }
02934         SWAP(float *, minvecbufrect, vecbufrect);
02935     }
02936     
02937     /* make vertex buffer with averaged speed and zvalues */
02938     rectvz= MEM_mapallocN(4*sizeof(float)*(xsize+1)*(ysize+1), "vertices");
02939     dvz= rectvz;
02940     for(y=0; y<=ysize; y++) {
02941         
02942         if(y==0)
02943             dvec1= vecbufrect + 4*y*xsize;
02944         else
02945             dvec1= vecbufrect + 4*(y-1)*xsize;
02946         
02947         if(y==ysize)
02948             dvec2= vecbufrect + 4*(y-1)*xsize;
02949         else
02950             dvec2= vecbufrect + 4*y*xsize;
02951         
02952         for(x=0; x<=xsize; x++) {
02953             
02954             /* two vectors, so a step loop */
02955             for(step=0; step<2; step++, dvec1+=2, dvec2+=2, dvz+=2) {
02956                 /* average on minimal speed */
02957                 int div= 0;
02958                 
02959                 if(x!=0) {
02960                     if(dvec1[-4]!=0.0f || dvec1[-3]!=0.0f) {
02961                         dvz[0]= dvec1[-4];
02962                         dvz[1]= dvec1[-3];
02963                         div++;
02964                     }
02965                     if(dvec2[-4]!=0.0f || dvec2[-3]!=0.0f) {
02966                         if(div==0) {
02967                             dvz[0]= dvec2[-4];
02968                             dvz[1]= dvec2[-3];
02969                             div++;
02970                         }
02971                         else if( (ABS(dvec2[-4]) + ABS(dvec2[-3]))< (ABS(dvz[0]) + ABS(dvz[1])) ) {
02972                             dvz[0]= dvec2[-4];
02973                             dvz[1]= dvec2[-3];
02974                         }
02975                     }
02976                 }
02977 
02978                 if(x!=xsize) {
02979                     if(dvec1[0]!=0.0f || dvec1[1]!=0.0f) {
02980                         if(div==0) {
02981                             dvz[0]= dvec1[0];
02982                             dvz[1]= dvec1[1];
02983                             div++;
02984                         }
02985                         else if( (ABS(dvec1[0]) + ABS(dvec1[1]))< (ABS(dvz[0]) + ABS(dvz[1])) ) {
02986                             dvz[0]= dvec1[0];
02987                             dvz[1]= dvec1[1];
02988                         }
02989                     }
02990                     if(dvec2[0]!=0.0f || dvec2[1]!=0.0f) {
02991                         if(div==0) {
02992                             dvz[0]= dvec2[0];
02993                             dvz[1]= dvec2[1];
02994                         }
02995                         else if( (ABS(dvec2[0]) + ABS(dvec2[1]))< (ABS(dvz[0]) + ABS(dvz[1])) ) {
02996                             dvz[0]= dvec2[0];
02997                             dvz[1]= dvec2[1];
02998                         }
02999                     }
03000                 }
03001                 if(maxspeed) {
03002                     float speedsq= dvz[0]*dvz[0] + dvz[1]*dvz[1];
03003                     if(speedsq > maxspeedsq) {
03004                         speedsq= (float)maxspeed/sqrt(speedsq);
03005                         dvz[0]*= speedsq;
03006                         dvz[1]*= speedsq;
03007                     }
03008                 }
03009             }
03010         }
03011     }
03012     
03013     /* set border speeds to keep border speeds on border */
03014     dz1= rectvz;
03015     dz2= rectvz+4*(ysize)*(xsize+1);
03016     for(x=0; x<=xsize; x++, dz1+=4, dz2+=4) {
03017         dz1[1]= 0.0f;
03018         dz2[1]= 0.0f;
03019         dz1[3]= 0.0f;
03020         dz2[3]= 0.0f;
03021     }
03022     dz1= rectvz;
03023     dz2= rectvz+4*(xsize);
03024     for(y=0; y<=ysize; y++, dz1+=4*(xsize+1), dz2+=4*(xsize+1)) {
03025         dz1[0]= 0.0f;
03026         dz2[0]= 0.0f;
03027         dz1[2]= 0.0f;
03028         dz2[2]= 0.0f;
03029     }
03030     
03031     /* tag moving pixels, only these faces we draw */
03032     dm= rectmove;
03033     dvec1= vecbufrect;
03034     for(x=xsize*ysize; x>0; x--, dm++, dvec1+=4) {
03035         if((dvec1[0]!=0.0f || dvec1[1]!=0.0f || dvec1[2]!=0.0f || dvec1[3]!=0.0f))
03036             *dm= 255;
03037     }
03038     
03039     antialias_tagbuf(xsize, ysize, rectmove);
03040     
03041     /* has to become static, the init-jit calls a random-seed, screwing up texture noise node */
03042     if(firsttime) {
03043         firsttime= 0;
03044         BLI_initjit(jit[0], 256);
03045     }
03046     
03047     memset(newrect, 0, sizeof(float)*xsize*ysize*4);
03048 
03049     /* accumulate */
03050     samples/= 2;
03051     for(step= 1; step<=samples; step++) {
03052         float speedfac= 0.5f*nbd->fac*(float)step/(float)(samples+1);
03053         int side;
03054         
03055         for(side=0; side<2; side++) {
03056             float blendfac, ipodata[4];
03057             
03058             /* clear zbuf, if we draw future we fill in not moving pixels */
03059             if(0)
03060                 for(x= xsize*ysize-1; x>=0; x--) rectz[x]= 10e16;
03061             else 
03062                 for(x= xsize*ysize-1; x>=0; x--) {
03063                     if(rectmove[x]==0)
03064                         rectz[x]= zbufrect[x];
03065                     else
03066                         rectz[x]= 10e16;
03067                 }
03068             
03069             /* clear drawing buffer */
03070             for(x= xsize*ysize-1; x>=0; x--) rectdraw[x].colpoin= NULL;
03071             
03072             dimg= imgrect;
03073             dm= rectmove;
03074             dz= zbufrect;
03075             dz1= rectvz;
03076             dz2= rectvz + 4*(xsize + 1);
03077             
03078             if(side) {
03079                 if(nbd->curved==0) {
03080                     dz1+= 2;
03081                     dz2+= 2;
03082                 }
03083                 speedfac= -speedfac;
03084             }
03085             
03086             set_quad_bezier_ipo(0.5f + 0.5f*speedfac, ipodata);
03087             
03088             for(fy= -0.5f+jit[step & 255][0], y=0; y<ysize; y++, fy+=1.0f) {
03089                 for(fx= -0.5f+jit[step & 255][1], x=0; x<xsize; x++, fx+=1.0f, dimg+=4, dz1+=4, dz2+=4, dm++, dz++) {
03090                     if(*dm>1) {
03091                         float jfx = fx + 0.5f;
03092                         float jfy = fy + 0.5f;
03093                         DrawBufPixel col;
03094                         
03095                         /* make vertices */
03096                         if(nbd->curved) {   /* curved */
03097                             quad_bezier_2d(v1, dz1, dz1+2, ipodata);
03098                             v1[0]+= jfx; v1[1]+= jfy; v1[2]= *dz;
03099 
03100                             quad_bezier_2d(v2, dz1+4, dz1+4+2, ipodata);
03101                             v2[0]+= jfx+1.0f; v2[1]+= jfy; v2[2]= *dz;
03102 
03103                             quad_bezier_2d(v3, dz2+4, dz2+4+2, ipodata);
03104                             v3[0]+= jfx+1.0f; v3[1]+= jfy+1.0f; v3[2]= *dz;
03105                             
03106                             quad_bezier_2d(v4, dz2, dz2+2, ipodata);
03107                             v4[0]+= jfx; v4[1]+= jfy+1.0f; v4[2]= *dz;
03108                         }
03109                         else {
03110                             v1[0]= speedfac*dz1[0]+jfx;         v1[1]= speedfac*dz1[1]+jfy;         v1[2]= *dz;
03111                             v2[0]= speedfac*dz1[4]+jfx+1.0f;        v2[1]= speedfac*dz1[5]+jfy;         v2[2]= *dz;
03112                             v3[0]= speedfac*dz2[4]+jfx+1.0f;        v3[1]= speedfac*dz2[5]+jfy+1.0f;        v3[2]= *dz;
03113                             v4[0]= speedfac*dz2[0]+jfx;         v4[1]= speedfac*dz2[1]+jfy+1.0f;        v4[2]= *dz;
03114                         }
03115                         if(*dm==255) col.alpha= 1.0f;
03116                         else if(*dm<2) col.alpha= 0.0f;
03117                         else col.alpha= ((float)*dm)/255.0f;
03118                         col.colpoin= dimg;
03119 
03120                         zbuf_fill_in_rgba(&zspan, &col, v1, v2, v3, v4);
03121                     }
03122                 }
03123                 dz1+=4;
03124                 dz2+=4;
03125             }
03126 
03127             /* blend with a falloff. this fixes the ugly effect you get with
03128              * a fast moving object. then it looks like a solid object overlayed
03129              * over a very transparent moving version of itself. in reality, the
03130              * whole object should become transparent if it is moving fast, be
03131              * we don't know what is behind it so we don't do that. this hack
03132              * overestimates the contribution of foreground pixels but looks a
03133              * bit better without a sudden cutoff. */
03134             blendfac= ((samples - step)/(float)samples);
03135             /* smoothstep to make it look a bit nicer as well */
03136             blendfac= 3.0f*pow(blendfac, 2.0f) - 2.0f*pow(blendfac, 3.0f);
03137 
03138             /* accum */
03139             rw= rectweight;
03140             rm= rectmax;
03141             for(dr= rectdraw, dz2=newrect, x= xsize*ysize-1; x>=0; x--, dr++, dz2+=4, rw++, rm++) {
03142                 if(dr->colpoin) {
03143                     float bfac= dr->alpha*blendfac;
03144                     
03145                     dz2[0] += bfac*dr->colpoin[0];
03146                     dz2[1] += bfac*dr->colpoin[1];
03147                     dz2[2] += bfac*dr->colpoin[2];
03148                     dz2[3] += bfac*dr->colpoin[3];
03149 
03150                     *rw += bfac;
03151                     *rm= MAX2(*rm, bfac);
03152                 }
03153             }
03154         }
03155     }
03156     
03157     /* blend between original images and accumulated image */
03158     rw= rectweight;
03159     rm= rectmax;
03160     ro= imgrect;
03161     dm= rectmove;
03162     for(dz2=newrect, x= xsize*ysize-1; x>=0; x--, dz2+=4, ro+=4, rw++, rm++, dm++) {
03163         float mfac = *rm;
03164         float fac = (*rw == 0.0f)? 0.0f: mfac/(*rw);
03165         float nfac = 1.0f - mfac;
03166 
03167         dz2[0]= fac*dz2[0] + nfac*ro[0];
03168         dz2[1]= fac*dz2[1] + nfac*ro[1];
03169         dz2[2]= fac*dz2[2] + nfac*ro[2];
03170         dz2[3]= fac*dz2[3] + nfac*ro[3];
03171     }
03172 
03173     MEM_freeN(rectz);
03174     MEM_freeN(rectmove);
03175     MEM_freeN(rectdraw);
03176     MEM_freeN(rectvz);
03177     MEM_freeN(rectweight);
03178     MEM_freeN(rectmax);
03179     if(minvecbufrect) MEM_freeN(vecbufrect);  /* rects were swapped! */
03180     zbuf_free_span(&zspan);
03181 }
03182 
03183 /* ******************** ABUF ************************* */
03184 
03189 static void copyto_abufz(RenderPart *pa, int *arectz, int *rectmask, int sample)
03190 {
03191     PixStr *ps;
03192     int x, y, *rza, *rma;
03193     intptr_t *rd;
03194     
03195     if(R.osa==0) {
03196         if(!pa->rectz)
03197             fillrect(arectz, pa->rectx, pa->recty, 0x7FFFFFFE);
03198         else
03199             memcpy(arectz, pa->rectz, sizeof(int)*pa->rectx*pa->recty);
03200 
03201         if(rectmask && pa->rectmask)
03202             memcpy(rectmask, pa->rectmask, sizeof(int)*pa->rectx*pa->recty);
03203 
03204         return;
03205     }
03206     else if(!pa->rectdaps) {
03207         fillrect(arectz, pa->rectx, pa->recty, 0x7FFFFFFE);
03208         return;
03209     }
03210     
03211     rza= arectz;
03212     rma= rectmask;
03213     rd= pa->rectdaps;
03214 
03215     sample= (1<<sample);
03216     
03217     for(y=0; y<pa->recty; y++) {
03218         for(x=0; x<pa->rectx; x++) {
03219             
03220             *rza= 0x7FFFFFFF;
03221             if(rectmask) *rma= 0x7FFFFFFF;
03222             if(*rd) {   
03223                 /* when there's a sky pixstruct, fill in sky-Z, otherwise solid Z */
03224                 for(ps= (PixStr *)(*rd); ps; ps= ps->next) {
03225                     if(sample & ps->mask) {
03226                         *rza= ps->z;
03227                         if(rectmask) *rma= ps->maskz;
03228                         break;
03229                     }
03230                 }
03231             }
03232             
03233             rd++; rza++, rma++;
03234         }
03235     }
03236 }
03237 
03238 
03239 /* ------------------------------------------------------------------------ */
03240 
03245 static int zbuffer_abuf(Render *re, RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, unsigned int lay, int negzmask, float winmat[][4], int winx, int winy, int samples, float (*jit)[2], float UNUSED(clipcrop), int shadow)
03246 {
03247     ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE];
03248     ZSpan zspans[16], *zspan;   /* MAX_OSA */
03249     Material *ma=NULL;
03250     ObjectInstanceRen *obi;
03251     ObjectRen *obr;
03252     VlakRen *vlr=NULL;
03253     VertRen *v1, *v2, *v3, *v4;
03254     float vec[3], hoco[4], mul, zval, fval;
03255     float obwinmat[4][4], bounds[4], ho1[4], ho2[4], ho3[4], ho4[4]={0};
03256     int i, v, zvlnr, c1, c2, c3, c4=0, dofill= 0;
03257     int zsample, polygon_offset;
03258 
03259     zbuffer_part_bounds(winx, winy, pa, bounds);
03260 
03261     for(zsample=0; zsample<samples; zsample++) {
03262         zspan= &zspans[zsample];
03263 
03264         zbuf_alloc_span(zspan, pa->rectx, pa->recty, re->clipcrop);
03265         
03266         /* needed for transform from hoco to zbuffer co */
03267         zspan->zmulx=  ((float)winx)/2.0f;
03268         zspan->zmuly=  ((float)winy)/2.0f;
03269         
03270         /* the buffers */
03271         zspan->arectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "Arectz");
03272         zspan->apixbuf= APixbuf;
03273         zspan->apsmbase= apsmbase;
03274         
03275         if(negzmask)
03276             zspan->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "Arectmask");
03277 
03278         /* filling methods */
03279         zspan->zbuffunc= zbuffillAc4;
03280         zspan->zbuflinefunc= zbuflineAc;
03281 
03282         copyto_abufz(pa, zspan->arectz, zspan->rectmask, zsample);  /* init zbuffer */
03283         zspan->mask= 1<<zsample;
03284 
03285         if(jit) {
03286             zspan->zofsx= -pa->disprect.xmin - jit[zsample][0];
03287             zspan->zofsy= -pa->disprect.ymin - jit[zsample][1];
03288         }
03289         else {
03290             zspan->zofsx= -pa->disprect.xmin;
03291             zspan->zofsy= -pa->disprect.ymin;
03292         }
03293 
03294         /* to center the sample position */
03295         zspan->zofsx -= 0.5f;
03296         zspan->zofsy -= 0.5f;
03297     }
03298     
03299     /* we use this to test if nothing was filled in */
03300     zvlnr= 0;
03301         
03302     for(i=0, obi=re->instancetable.first; obi; i++, obi=obi->next) {
03303         obr= obi->obr;
03304 
03305         if(!(obi->lay & lay))
03306             continue;
03307 
03308         if(obi->flag & R_TRANSFORMED)
03309             mult_m4_m4m4(obwinmat, winmat, obi->mat);
03310         else
03311             copy_m4_m4(obwinmat, winmat);
03312 
03313         if(clip_render_object(obi->obr->boundbox, bounds, obwinmat))
03314             continue;
03315 
03316         zbuf_project_cache_clear(cache, obr->totvert);
03317 
03318         for(v=0; v<obr->totvlak; v++) {
03319             if((v & 255)==0)
03320                 vlr= obr->vlaknodes[v>>8].vlak;
03321             else vlr++;
03322             
03323             if(vlr->mat!=ma) {
03324                 ma= vlr->mat;
03325                 if(shadow)
03326                     dofill= (ma->mode & MA_SHADBUF);
03327                 else
03328                     dofill= (((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP)) && !(ma->mode & MA_ONLYCAST));
03329             }
03330             
03331             if(dofill) {
03332                 if(!(vlr->flag & R_HIDDEN) && (obi->lay & lay)) {
03333                     unsigned short partclip;
03334                     
03335                     v1= vlr->v1;
03336                     v2= vlr->v2;
03337                     v3= vlr->v3;
03338                     v4= vlr->v4;
03339 
03340                     c1= zbuf_part_project(cache, v1->index, obwinmat, bounds, v1->co, ho1);
03341                     c2= zbuf_part_project(cache, v2->index, obwinmat, bounds, v2->co, ho2);
03342                     c3= zbuf_part_project(cache, v3->index, obwinmat, bounds, v3->co, ho3);
03343 
03344                     /* partclipping doesn't need viewplane clipping */
03345                     partclip= c1 & c2 & c3;
03346                     if(v4) {
03347                         c4= zbuf_part_project(cache, v4->index, obwinmat, bounds, v4->co, ho4);
03348                         partclip &= c4;
03349                     }
03350 
03351                     if(partclip==0) {
03352                         /* a little advantage for transp rendering (a z offset) */
03353                         if(!shadow && ma->zoffs != 0.0f) {
03354                             mul= 0x7FFFFFFF;
03355                             zval= mul*(1.0f+ho1[2]/ho1[3]);
03356 
03357                             copy_v3_v3(vec, v1->co);
03358                             /* z is negative, otherwise its being clipped */ 
03359                             vec[2]-= ma->zoffs;
03360                             projectverto(vec, obwinmat, hoco);
03361                             fval= mul*(1.0f+hoco[2]/hoco[3]);
03362 
03363                             polygon_offset= (int) fabs(zval - fval );
03364                         }
03365                         else polygon_offset= 0;
03366                         
03367                         zvlnr= v+1;
03368 
03369                         c1= testclip(ho1);
03370                         c2= testclip(ho2);
03371                         c3= testclip(ho3);
03372                         if(v4)
03373                             c4= testclip(ho4);
03374 
03375                         for(zsample=0; zsample<samples; zsample++) {
03376                             zspan= &zspans[zsample];
03377                             zspan->polygon_offset= polygon_offset;
03378                 
03379                             if(ma->material_type == MA_TYPE_WIRE) {
03380                                 if(v4)
03381                                     zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
03382                                 else
03383                                     zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, 0, c1, c2, c3, 0);
03384                             }
03385                             else {
03386                                 if(v4 && (vlr->flag & R_STRAND)) {
03387                                     zbufclip4(zspan, i, zvlnr, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
03388                                 }
03389                                 else {
03390                                     zbufclip(zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3);
03391                                     if(v4)
03392                                         zbufclip(zspan, i, zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4);
03393                                 }
03394                             }
03395                         }
03396                     }
03397                     if((v & 255)==255) 
03398                         if(re->test_break(re->tbh)) 
03399                             break; 
03400                 }
03401             }
03402         }
03403 
03404         if(re->test_break(re->tbh)) break;
03405     }
03406     
03407     for(zsample=0; zsample<samples; zsample++) {
03408         zspan= &zspans[zsample];
03409         MEM_freeN(zspan->arectz);
03410         if(zspan->rectmask)
03411             MEM_freeN(zspan->rectmask);
03412         zbuf_free_span(zspan);
03413     }
03414     
03415     return zvlnr;
03416 }
03417 
03418 static int zbuffer_abuf_render(RenderPart *pa, APixstr *APixbuf, APixstrand *APixbufstrand, ListBase *apsmbase, RenderLayer *rl, StrandShadeCache *sscache)
03419 {
03420     float winmat[4][4], (*jit)[2];
03421     int samples, negzmask, doztra= 0;
03422 
03423     samples= (R.osa)? R.osa: 1;
03424     negzmask= ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK));
03425 
03426     if(R.osa)
03427         jit= R.jit;
03428     else if(R.i.curblur)
03429         jit= &R.mblur_jit[R.i.curblur-1];
03430     else
03431         jit= NULL;
03432     
03433     zbuf_make_winmat(&R, winmat);
03434 
03435     if(rl->layflag & SCE_LAY_ZTRA)
03436         doztra+= zbuffer_abuf(&R, pa, APixbuf, apsmbase, rl->lay, negzmask, winmat, R.winx, R.winy, samples, jit, R.clipcrop, 0);
03437     if((rl->layflag & SCE_LAY_STRAND) && APixbufstrand)
03438         doztra+= zbuffer_strands_abuf(&R, pa, APixbufstrand, apsmbase, rl->lay, negzmask, winmat, R.winx, R.winy, samples, jit, R.clipcrop, 0, sscache);
03439 
03440     return doztra;
03441 }
03442 
03443 void zbuffer_abuf_shadow(Render *re, LampRen *lar, float winmat[][4], APixstr *APixbuf, APixstrand *APixbufstrand, ListBase *apsmbase, int size, int samples, float (*jit)[2])
03444 {
03445     RenderPart pa;
03446     int lay= -1;
03447 
03448     if(lar->mode & LA_LAYER) lay= lar->lay;
03449 
03450     memset(&pa, 0, sizeof(RenderPart));
03451     pa.rectx= size;
03452     pa.recty= size;
03453     pa.disprect.xmin= 0;
03454     pa.disprect.ymin= 0;
03455     pa.disprect.xmax= size;
03456     pa.disprect.ymax= size;
03457 
03458     zbuffer_abuf(re, &pa, APixbuf, apsmbase, lay, 0, winmat, size, size, samples, jit, 1.0f, 1);
03459     if(APixbufstrand)
03460         zbuffer_strands_abuf(re, &pa, APixbufstrand, apsmbase, lay, 0, winmat, size, size, samples, jit, 1.0f, 1, NULL);
03461 }
03462 
03463 /* different rules for speed in transparent pass...  */
03464 /* speed pointer NULL = sky, we clear */
03465 /* else if either alpha is full or no solid was filled in: copy speed */
03466 /* else fill in minimum speed */
03467 void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha, intptr_t *rdrect)
03468 {
03469     RenderPass *rpass;
03470     
03471     for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
03472         if(rpass->passtype==SCE_PASS_VECTOR) {
03473             float *fp= rpass->rect + 4*offset;
03474             
03475             if(speed==NULL) {
03476                 /* clear */
03477                 if(fp[0]==PASS_VECTOR_MAX) fp[0]= 0.0f;
03478                 if(fp[1]==PASS_VECTOR_MAX) fp[1]= 0.0f;
03479                 if(fp[2]==PASS_VECTOR_MAX) fp[2]= 0.0f;
03480                 if(fp[3]==PASS_VECTOR_MAX) fp[3]= 0.0f;
03481             }
03482             else if(rdrect==NULL || rdrect[offset]==0 || alpha>0.95f) {
03483                 copy_v4_v4(fp, speed);
03484             }
03485             else {
03486                 /* add minimum speed in pixel */
03487                 if( (ABS(speed[0]) + ABS(speed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) {
03488                     fp[0]= speed[0];
03489                     fp[1]= speed[1];
03490                 }
03491                 if( (ABS(speed[2]) + ABS(speed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) {
03492                     fp[2]= speed[2];
03493                     fp[3]= speed[3];
03494                 }
03495             }
03496             break;
03497         }
03498     }
03499 }
03500 
03501 static void add_transp_obindex(RenderLayer *rl, int offset, Object *ob)
03502 {
03503     RenderPass *rpass;
03504     
03505     for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
03506         if(rpass->passtype == SCE_PASS_INDEXOB||rpass->passtype == SCE_PASS_INDEXMA) {
03507             float *fp= rpass->rect + offset;
03508             *fp= (float)ob->index;
03509             break;
03510         }
03511     }
03512 }
03513 
03514 /* ONLY OSA! merge all shaderesult samples to one */
03515 /* target should have been cleared */
03516 void merge_transp_passes(RenderLayer *rl, ShadeResult *shr)
03517 {
03518     RenderPass *rpass;
03519     float weight= 1.0f/((float)R.osa);
03520     int delta= sizeof(ShadeResult)/4;
03521     
03522     for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
03523         float *col= NULL;
03524         int pixsize= 3;
03525         
03526         switch(rpass->passtype) {
03527             case SCE_PASS_RGBA:
03528                 col= shr->col;
03529                 pixsize= 4;
03530                 break;
03531             case SCE_PASS_EMIT:
03532                 col= shr->emit;
03533                 break;
03534             case SCE_PASS_DIFFUSE:
03535                 col= shr->diff;
03536                 break;
03537             case SCE_PASS_SPEC:
03538                 col= shr->spec;
03539                 break;
03540             case SCE_PASS_SHADOW:
03541                 col= shr->shad;
03542                 break;
03543             case SCE_PASS_AO:
03544                 col= shr->ao;
03545                 break;
03546             case SCE_PASS_ENVIRONMENT:
03547                 col= shr->env;
03548                 break;
03549             case SCE_PASS_INDIRECT:
03550                 col= shr->indirect;
03551                 break;
03552             case SCE_PASS_REFLECT:
03553                 col= shr->refl;
03554                 break;
03555             case SCE_PASS_REFRACT:
03556                 col= shr->refr;
03557                 break;
03558             case SCE_PASS_NORMAL:
03559                 col= shr->nor;
03560                 break;
03561             case SCE_PASS_MIST:
03562                 col= &shr->mist;
03563                 pixsize= 1;
03564                 break;
03565             case SCE_PASS_Z:
03566                 col= &shr->z;
03567                 pixsize= 1;
03568                 break;
03569             case SCE_PASS_VECTOR:
03570                 
03571                 {
03572                     ShadeResult *shr_t= shr+1;
03573                     float *fp= shr->winspeed;   /* was initialized */
03574                     int samp;
03575                     
03576                     /* add minimum speed in pixel */
03577                     for(samp= 1; samp<R.osa; samp++, shr_t++) {
03578                         
03579                         if(shr_t->combined[3] > 0.0f) {
03580                             float *speed= shr_t->winspeed;
03581                             
03582                             if( (ABS(speed[0]) + ABS(speed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) {
03583                                 fp[0]= speed[0];
03584                                 fp[1]= speed[1];
03585                             }
03586                             if( (ABS(speed[2]) + ABS(speed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) {
03587                                 fp[2]= speed[2];
03588                                 fp[3]= speed[3];
03589                             }
03590                         }
03591                     }
03592                 }
03593                 break;
03594         }
03595         if(col) {
03596             float *fp= col+delta;
03597             int samp;
03598             
03599             for(samp= 1; samp<R.osa; samp++, fp+=delta) {
03600                 col[0]+= fp[0];
03601                 if(pixsize>1) {
03602                     col[1]+= fp[1];
03603                     col[2]+= fp[2];
03604                     if(pixsize==4) col[3]+= fp[3];
03605                 }
03606             }
03607             col[0]*= weight;
03608             if(pixsize>1) {
03609                 col[1]*= weight;
03610                 col[2]*= weight;
03611                 if(pixsize==4) col[3]*= weight;
03612             }
03613         }
03614     }
03615                 
03616 }
03617 
03618 void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alpha)
03619 {
03620     RenderPass *rpass;
03621     
03622     for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
03623         float *fp, *col= NULL;
03624         int pixsize= 3;
03625         
03626         switch(rpass->passtype) {
03627             case SCE_PASS_Z:
03628                 fp= rpass->rect + offset;
03629                 if(shr->z < *fp)
03630                     *fp= shr->z;
03631                 break;
03632             case SCE_PASS_RGBA:
03633                 fp= rpass->rect + 4*offset;
03634                 addAlphaOverFloat(fp, shr->col);
03635                 break;
03636             case SCE_PASS_EMIT:
03637                 col= shr->emit;
03638                 break;
03639             case SCE_PASS_DIFFUSE:
03640                 col= shr->diff;
03641                 break;
03642             case SCE_PASS_SPEC:
03643                 col= shr->spec;
03644                 break;
03645             case SCE_PASS_SHADOW:
03646                 col= shr->shad;
03647                 break;
03648             case SCE_PASS_AO:
03649                 col= shr->ao;
03650                 break;
03651             case SCE_PASS_ENVIRONMENT:
03652                 col= shr->env;
03653                 break;
03654             case SCE_PASS_INDIRECT:
03655                 col= shr->indirect;
03656                 break;
03657             case SCE_PASS_REFLECT:
03658                 col= shr->refl;
03659                 break;
03660             case SCE_PASS_REFRACT:
03661                 col= shr->refr;
03662                 break;
03663             case SCE_PASS_NORMAL:
03664                 col= shr->nor;
03665                 break;
03666             case SCE_PASS_MIST:
03667                 col= &shr->mist;
03668                 pixsize= 1;
03669                 break;
03670         }
03671         if(col) {
03672 
03673             fp= rpass->rect + pixsize*offset;
03674             fp[0]= col[0] + (1.0f-alpha)*fp[0];
03675             if(pixsize==3) {
03676                 fp[1]= col[1] + (1.0f-alpha)*fp[1];
03677                 fp[2]= col[2] + (1.0f-alpha)*fp[2];
03678             }
03679         }
03680     }
03681 }
03682 
03683 typedef struct ZTranspRow {
03684     int obi;
03685     int z;
03686     int p;
03687     int mask;
03688     int segment;
03689     float u, v;
03690 } ZTranspRow;
03691 
03692 static int vergzvlak(const void *a1, const void *a2)
03693 {
03694     const ZTranspRow *r1 = a1, *r2 = a2;
03695 
03696     if(r1->z < r2->z) return 1;
03697     else if(r1->z > r2->z) return -1;
03698     return 0;
03699 }
03700 
03701 static void shade_strand_samples(StrandShadeCache *cache, ShadeSample *ssamp, int UNUSED(x), int UNUSED(y), ZTranspRow *row, int addpassflag)
03702 {
03703     StrandSegment sseg;
03704     StrandVert *svert;
03705     ObjectInstanceRen *obi;
03706     ObjectRen *obr;
03707 
03708     obi= R.objectinstance + row->obi;
03709     obr= obi->obr;
03710 
03711     sseg.obi= obi;
03712     sseg.strand= RE_findOrAddStrand(obr, row->p-1);
03713     sseg.buffer= sseg.strand->buffer;
03714 
03715     svert= sseg.strand->vert + row->segment;
03716     sseg.v[0]= (row->segment > 0)? (svert-1): svert;
03717     sseg.v[1]= svert;
03718     sseg.v[2]= svert+1;
03719     sseg.v[3]= (row->segment < sseg.strand->totvert-2)? svert+2: svert+1;
03720 
03721     ssamp->tot= 1;
03722     strand_shade_segment(&R, cache, &sseg, ssamp, row->v, row->u, addpassflag);
03723     ssamp->shi[0].mask= row->mask;
03724 }
03725 
03726 static void unref_strand_samples(StrandShadeCache *cache, ZTranspRow *row, int totface)
03727 {
03728     StrandVert *svert;
03729     ObjectInstanceRen *obi;
03730     ObjectRen *obr;
03731     StrandRen *strand;
03732 
03733     /* remove references to samples that are not being rendered, but we still
03734      * need to remove them so that the reference count of strand vertex shade
03735      * samples correctly drops to zero */
03736     while(totface > 0) {
03737         totface--;
03738 
03739         if(row[totface].segment != -1) {
03740             obi= R.objectinstance + row[totface].obi;
03741             obr= obi->obr;
03742             strand= RE_findOrAddStrand(obr, row[totface].p-1);
03743             svert= strand->vert + row[totface].segment;
03744 
03745             strand_shade_unref(cache, svert);
03746             strand_shade_unref(cache, svert+1);
03747         }
03748     }
03749 }
03750 
03751 static void shade_tra_samples_fill(ShadeSample *ssamp, int x, int y, int z, int obi, int facenr, int curmask)
03752 {
03753     ShadeInput *shi= ssamp->shi;
03754     float xs, ys;
03755     
03756     ssamp->tot= 0;
03757 
03758     shade_input_set_triangle(shi, obi, facenr, 1);
03759         
03760     /* officially should always be true... we have no sky info */
03761     if(shi->vlr) {
03762         
03763         /* full osa is only set for OSA renders */
03764         if(shi->vlr->flag & R_FULL_OSA) {
03765             short shi_inc= 0, samp;
03766             
03767             for(samp=0; samp<R.osa; samp++) {
03768                 if(curmask & (1<<samp)) {
03769                     xs= (float)x + R.jit[samp][0] + 0.5f;   /* zbuffer has this inverse corrected, ensures xs,ys are inside pixel */
03770                     ys= (float)y + R.jit[samp][1] + 0.5f;
03771                     
03772                     if(shi_inc) {
03773                         shade_input_copy_triangle(shi+1, shi);
03774                         shi++;
03775                     }
03776                     shi->mask= (1<<samp);
03777                     shi->samplenr= R.shadowsamplenr[shi->thread]++;
03778                     shade_input_set_viewco(shi, x, y, xs, ys, (float)z);
03779                     shade_input_set_uv(shi);
03780                     if(shi_inc==0)
03781                         shade_input_set_normals(shi);
03782                     else /* XXX shi->flippednor messes up otherwise */
03783                         shade_input_set_vertex_normals(shi);
03784                     
03785                     shi_inc= 1;
03786                 }
03787             }
03788         }
03789         else {
03790             if(R.osa) {
03791                 short b= R.samples->centmask[curmask];
03792                 xs= (float)x + R.samples->centLut[b & 15] + 0.5f;
03793                 ys= (float)y + R.samples->centLut[b>>4] + 0.5f;
03794             }
03795             else {
03796                 xs= (float)x + 0.5f;
03797                 ys= (float)y + 0.5f;
03798             }
03799             shi->mask= curmask;
03800             shi->samplenr= R.shadowsamplenr[shi->thread]++;
03801             shade_input_set_viewco(shi, x, y, xs, ys, (float)z);
03802             shade_input_set_uv(shi);
03803             shade_input_set_normals(shi);
03804         }
03805         
03806         /* total sample amount, shi->sample is static set in initialize */
03807         ssamp->tot= shi->sample+1;
03808     }
03809 }
03810 
03811 static int shade_tra_samples(ShadeSample *ssamp, StrandShadeCache *cache, int x, int y, ZTranspRow *row, int addpassflag)
03812 {
03813     if(row->segment != -1) {
03814         shade_strand_samples(cache, ssamp, x, y, row, addpassflag);
03815         return 1;
03816     }
03817 
03818     shade_tra_samples_fill(ssamp, x, y, row->z, row->obi, row->p, row->mask);
03819     
03820     if(ssamp->tot) {
03821         ShadeInput *shi= ssamp->shi;
03822         ShadeResult *shr= ssamp->shr;
03823         int samp;
03824         
03825         /* if AO? */
03826         shade_samples_do_AO(ssamp);
03827         
03828         /* if shade (all shadepinputs have same passflag) */
03829         if(shi->passflag & ~(SCE_PASS_Z|SCE_PASS_INDEXOB|SCE_PASS_INDEXMA)) {
03830             for(samp=0; samp<ssamp->tot; samp++, shi++, shr++) {
03831                 shade_input_set_shade_texco(shi);
03832                 shade_input_do_shade(shi, shr);
03833                 
03834                 /* include lamphalos for ztra, since halo layer was added already */
03835                 if(R.flag & R_LAMPHALO)
03836                     if(shi->layflag & SCE_LAY_HALO)
03837                         renderspothalo(shi, shr->combined, shr->combined[3]);
03838             }
03839         }
03840         else if(shi->passflag & SCE_PASS_Z) {
03841             for(samp=0; samp<ssamp->tot; samp++, shi++, shr++)
03842                 shr->z= -shi->co[2];
03843         }
03844 
03845         return 1;
03846     }
03847     return 0;
03848 }
03849 
03850 static void addvecmul(float *v1, float *v2, float fac)
03851 {
03852     v1[0]= v1[0]+fac*v2[0];
03853     v1[1]= v1[1]+fac*v2[1];
03854     v1[2]= v1[2]+fac*v2[2];
03855 }
03856 
03857 static int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassflag)
03858 {
03859     int a, sample, osa = (R.osa? R.osa: 1), retval = osa;
03860     
03861     for(a=0; a < osa; a++, samp_shr++) {
03862         ShadeInput *shi= ssamp->shi;
03863         ShadeResult *shr= ssamp->shr;
03864         
03865         for(sample=0; sample<ssamp->tot; sample++, shi++, shr++) {
03866         
03867             if(shi->mask & (1<<a)) {
03868                 float fac= (1.0f - samp_shr->combined[3])*shr->combined[3];
03869                 
03870                 addAlphaUnderFloat(samp_shr->combined, shr->combined);
03871                 
03872                 samp_shr->z= MIN2(samp_shr->z, shr->z);
03873 
03874                 if(addpassflag & SCE_PASS_VECTOR) {
03875                     copy_v4_v4(samp_shr->winspeed, shr->winspeed);
03876                 }
03877                 /* optim... */
03878                 if(addpassflag & ~(SCE_PASS_VECTOR)) {
03879                     
03880                     if(addpassflag & SCE_PASS_RGBA)
03881                         addAlphaUnderFloat(samp_shr->col, shr->col);
03882                     
03883                     if(addpassflag & SCE_PASS_NORMAL)
03884                         addvecmul(samp_shr->nor, shr->nor, fac);
03885 
03886                     if(addpassflag & SCE_PASS_EMIT)
03887                         addvecmul(samp_shr->emit, shr->emit, fac);
03888 
03889                     if(addpassflag & SCE_PASS_DIFFUSE)
03890                         addvecmul(samp_shr->diff, shr->diff, fac);
03891                     
03892                     if(addpassflag & SCE_PASS_SPEC)
03893                         addvecmul(samp_shr->spec, shr->spec, fac);
03894 
03895                     if(addpassflag & SCE_PASS_SHADOW)
03896                         addvecmul(samp_shr->shad, shr->shad, fac);
03897 
03898                     if(addpassflag & SCE_PASS_AO)
03899                         addvecmul(samp_shr->ao, shr->ao, fac);
03900 
03901                     if(addpassflag & SCE_PASS_ENVIRONMENT)
03902                         addvecmul(samp_shr->env, shr->env, fac);
03903 
03904                     if(addpassflag & SCE_PASS_INDIRECT)
03905                         addvecmul(samp_shr->indirect, shr->indirect, fac);
03906 
03907                     if(addpassflag & SCE_PASS_REFLECT)
03908                         addvecmul(samp_shr->refl, shr->refl, fac);
03909                     
03910                     if(addpassflag & SCE_PASS_REFRACT)
03911                         addvecmul(samp_shr->refr, shr->refr, fac);
03912                     
03913                     if(addpassflag & SCE_PASS_MIST)
03914                         samp_shr->mist= samp_shr->mist+fac*shr->mist;
03915 
03916                 }
03917             }
03918         }
03919         
03920         if(samp_shr->combined[3]>0.999f) retval--;
03921     }
03922     return retval;
03923 }
03924 
03925 static void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf)
03926 {
03927     /* speed vector exception... if solid render was done, sky pixels are set to zero already */
03928     /* for all pixels with alpha zero, we re-initialize speed again then */
03929     float *fp, *col;
03930     int a;
03931     
03932     fp= RE_RenderLayerGetPass(rl, SCE_PASS_VECTOR);
03933     if(fp==NULL) return;
03934     col= rectf+3;
03935     
03936     for(a= 4*pa->rectx*pa->recty -4; a>=0; a-=4) {
03937         if(col[a]==0.0f) {
03938             fp[a]= PASS_VECTOR_MAX;
03939             fp[a+1]= PASS_VECTOR_MAX;
03940             fp[a+2]= PASS_VECTOR_MAX;
03941             fp[a+3]= PASS_VECTOR_MAX;
03942         }
03943     }
03944 }
03945 
03946 #define MAX_ZROW    2000
03947 
03948 /* main render call to do the z-transparent layer */
03949 /* returns a mask, only if a) transp rendered and b) solid was rendered */
03950 unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass, ListBase *UNUSED(psmlist))
03951 {
03952     RenderResult *rr= pa->result;
03953     ShadeSample ssamp;
03954     APixstr *APixbuf;      /* Zbuffer: linked list of face samples */
03955     APixstrand *APixbufstrand = NULL;
03956     APixstr *ap, *aprect, *apn;
03957     APixstrand *apstrand, *aprectstrand, *apnstrand;
03958     ListBase apsmbase={NULL, NULL};
03959     ShadeResult samp_shr[16];       /* MAX_OSA */
03960     ZTranspRow zrow[MAX_ZROW];
03961     StrandShadeCache *sscache= NULL;
03962     RenderLayer *rlpp[RE_MAX_OSA];
03963     float sampalpha, alpha, *passrect= pass;
03964     intptr_t *rdrect;
03965     int x, y, crop=0, a, b, totface, totfullsample, totsample, doztra;
03966     int addpassflag, offs= 0, od, osa = (R.osa? R.osa: 1);
03967     unsigned short *ztramask= NULL, filled;
03968 
03969     /* looks nicer for calling code */
03970     if(R.test_break(R.tbh))
03971         return NULL;
03972     
03973     if(R.osa>16) { /* MAX_OSA */
03974         printf("zbuffer_transp_shade: osa too large\n");
03975         G.afbreek= 1;
03976         return NULL;
03977     }
03978     
03979     APixbuf= MEM_callocN(pa->rectx*pa->recty*sizeof(APixstr), "APixbuf");
03980     if(R.totstrand && (rl->layflag & SCE_LAY_STRAND)) {
03981         APixbufstrand= MEM_callocN(pa->rectx*pa->recty*sizeof(APixstrand), "APixbufstrand");
03982         sscache= strand_shade_cache_create();
03983     }
03984 
03985     /* general shader info, passes */
03986     shade_sample_initialize(&ssamp, pa, rl);
03987     addpassflag= rl->passflag & ~(SCE_PASS_COMBINED);
03988     
03989     if(R.osa)
03990         sampalpha= 1.0f/(float)R.osa;
03991     else
03992         sampalpha= 1.0f;
03993     
03994     /* fill the Apixbuf */
03995     doztra= zbuffer_abuf_render(pa, APixbuf, APixbufstrand, &apsmbase, rl, sscache);
03996 
03997     if(doztra == 0) {
03998         /* nothing filled in */
03999         MEM_freeN(APixbuf);
04000         if(APixbufstrand)
04001             MEM_freeN(APixbufstrand);
04002         if(sscache)
04003             strand_shade_cache_free(sscache);
04004         freepsA(&apsmbase);
04005         return NULL;
04006     }
04007 
04008     aprect= APixbuf;
04009     aprectstrand= APixbufstrand;
04010     rdrect= pa->rectdaps;
04011 
04012     /* needed for correct zbuf/index pass */
04013     totfullsample= get_sample_layers(pa, rl, rlpp);
04014     
04015     /* irregular shadowb buffer creation */
04016     if(R.r.mode & R_SHADOW)
04017         ISB_create(pa, APixbuf);
04018 
04019     /* masks, to have correct alpha combine */
04020     if(R.osa && (rl->layflag & SCE_LAY_SOLID) && pa->fullresult.first==NULL)
04021         ztramask= MEM_callocN(pa->rectx*pa->recty*sizeof(short), "ztramask");
04022 
04023     /* zero alpha pixels get speed vector max again */
04024     if(addpassflag & SCE_PASS_VECTOR)
04025         if(rl->layflag & SCE_LAY_SOLID)
04026             reset_sky_speedvectors(pa, rl, rl->acolrect?rl->acolrect:rl->rectf);    /* if acolrect is set we use it */
04027 
04028     /* filtered render, for now we assume only 1 filter size */
04029     if(pa->crop) {
04030         crop= 1;
04031         offs= pa->rectx + 1;
04032         passrect+= 4*offs;
04033         aprect+= offs;
04034         aprectstrand+= offs;
04035     }
04036     
04037     /* init scanline updates */
04038     rr->renrect.ymin= 0;
04039     rr->renrect.ymax= -pa->crop;
04040     rr->renlay= rl;
04041                 
04042     /* render the tile */
04043     for(y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++, rr->renrect.ymax++) {
04044         pass= passrect;
04045         ap= aprect;
04046         apstrand= aprectstrand;
04047         od= offs;
04048         
04049         if(R.test_break(R.tbh))
04050             break;
04051         
04052         for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, ap++, apstrand++, pass+=4, od++) {
04053             
04054             if(ap->p[0]==0 && (!APixbufstrand || apstrand->p[0]==0)) {
04055                 if(addpassflag & SCE_PASS_VECTOR) 
04056                     add_transp_speed(rl, od, NULL, 0.0f, rdrect);
04057             }
04058             else {
04059                 /* sort in z */
04060                 totface= 0;
04061                 apn= ap;
04062                 while(apn) {
04063                     for(a=0; a<4; a++) {
04064                         if(apn->p[a]) {
04065                             zrow[totface].obi= apn->obi[a];
04066                             zrow[totface].z= apn->z[a];
04067                             zrow[totface].p= apn->p[a];
04068                             zrow[totface].mask= apn->mask[a];
04069                             zrow[totface].segment= -1;
04070                             totface++;
04071                             if(totface>=MAX_ZROW) totface= MAX_ZROW-1;
04072                         }
04073                         else break;
04074                     }
04075                     apn= apn->next;
04076                 }
04077 
04078                 apnstrand= (APixbufstrand)? apstrand: NULL;
04079                 while(apnstrand) {
04080                     for(a=0; a<4; a++) {
04081                         if(apnstrand->p[a]) {
04082                             zrow[totface].obi= apnstrand->obi[a];
04083                             zrow[totface].z= apnstrand->z[a];
04084                             zrow[totface].p= apnstrand->p[a];
04085                             zrow[totface].mask= apnstrand->mask[a];
04086                             zrow[totface].segment= apnstrand->seg[a];
04087 
04088                             if(R.osa) {
04089                                 totsample= 0;
04090                                 for(b=0; b<R.osa; b++)
04091                                     if(zrow[totface].mask & (1<<b))
04092                                         totsample++;
04093                             }
04094                             else
04095                                 totsample= 1;
04096 
04097                             zrow[totface].u= apnstrand->u[a]/totsample;
04098                             zrow[totface].v= apnstrand->v[a]/totsample;
04099                             totface++;
04100                             if(totface>=MAX_ZROW) totface= MAX_ZROW-1;
04101                         }
04102                     }
04103                     apnstrand= apnstrand->next;
04104                 }
04105 
04106                 if(totface==2) {
04107                     if(zrow[0].z < zrow[1].z) {
04108                         SWAP(ZTranspRow, zrow[0], zrow[1]);
04109                     }
04110                     
04111                 }
04112                 else if(totface>2) {
04113                     qsort(zrow, totface, sizeof(ZTranspRow), vergzvlak);
04114                 }
04115                 
04116                 /* front face does index pass for transparent, no AA or filters, but yes FSA */
04117                 if(addpassflag & SCE_PASS_INDEXOB) {
04118                     ObjectRen *obr= R.objectinstance[zrow[totface-1].obi].obr;
04119                     if(obr->ob) {
04120                         for(a= 0; a<totfullsample; a++)
04121                             add_transp_obindex(rlpp[a], od, obr->ob);
04122                     }
04123                 }
04124                 if(addpassflag & SCE_PASS_INDEXMA) {
04125                     ObjectRen *obr= R.objectinstance[zrow[totface-1].obi].obr;
04126                     if(obr->ob) {
04127                         for(a= 0; a<totfullsample; a++)
04128                             add_transp_obindex(rlpp[a], od, obr->ob);
04129                     }
04130                 }
04131 
04132                 /* for each mask-sample we alpha-under colors. then in end it's added using filter */
04133                 memset(samp_shr, 0, sizeof(ShadeResult)*osa);
04134                 for(a=0; a<osa; a++) {
04135                     samp_shr[a].z= 10e10f;
04136                     if(addpassflag & SCE_PASS_VECTOR) {
04137                         samp_shr[a].winspeed[0]= PASS_VECTOR_MAX;
04138                         samp_shr[a].winspeed[1]= PASS_VECTOR_MAX;
04139                         samp_shr[a].winspeed[2]= PASS_VECTOR_MAX;
04140                         samp_shr[a].winspeed[3]= PASS_VECTOR_MAX;
04141                     }
04142                 }
04143 
04144                 if(R.osa==0) {
04145                     while(totface>0) {
04146                         totface--;
04147                         
04148                         if(shade_tra_samples(&ssamp, sscache, x, y, &zrow[totface], addpassflag)) {
04149                             filled= addtosamp_shr(samp_shr, &ssamp, addpassflag);
04150                             addAlphaUnderFloat(pass, ssamp.shr[0].combined);
04151                             
04152                             if(filled == 0) {
04153                                 if(sscache)
04154                                     unref_strand_samples(sscache, zrow, totface);
04155                                 break;
04156                             }
04157                         }
04158                     }
04159 
04160                     alpha= samp_shr->combined[3];
04161                     if(alpha!=0.0f) {
04162                         add_transp_passes(rl, od, samp_shr, alpha);
04163                         if(addpassflag & SCE_PASS_VECTOR)
04164                             add_transp_speed(rl, od, samp_shr->winspeed, alpha, rdrect);
04165                     }
04166                 }
04167                 else {
04168                     short *sp= (short *)(ztramask+od);
04169                     
04170                     while(totface>0) {
04171                         totface--;
04172                         
04173                         if(shade_tra_samples(&ssamp, sscache, x, y, &zrow[totface], addpassflag)) {
04174                             filled= addtosamp_shr(samp_shr, &ssamp, addpassflag);
04175                             
04176                             if(ztramask)
04177                                 *sp |= zrow[totface].mask;
04178                             if(filled==0) {
04179                                 if(sscache)
04180                                     unref_strand_samples(sscache, zrow, totface);
04181                                 break;
04182                             }
04183                         }
04184                     }
04185                     
04186                     /* multisample buffers or filtered mask filling? */
04187                     if(pa->fullresult.first) {
04188                         for(a=0; a<R.osa; a++) {
04189                             alpha= samp_shr[a].combined[3];
04190                             if(alpha!=0.0f) {
04191                                 RenderLayer *rl= ssamp.rlpp[a];
04192                                 
04193                                 addAlphaOverFloat(rl->rectf + 4*od, samp_shr[a].combined);
04194                 
04195                                 add_transp_passes(rl, od, &samp_shr[a], alpha);
04196                                 if(addpassflag & SCE_PASS_VECTOR)
04197                                     add_transp_speed(rl, od, samp_shr[a].winspeed, alpha, rdrect);
04198                             }
04199                         }
04200                     }
04201                     else {
04202                         alpha= 0.0f;
04203 
04204                         /* note; cannot use pass[3] for alpha due to filtermask */
04205                         for(a=0; a<R.osa; a++) {
04206                             add_filt_fmask(1<<a, samp_shr[a].combined, pass, rr->rectx);
04207                             alpha+= samp_shr[a].combined[3];
04208                         }
04209                         
04210                         if(addpassflag) {
04211                             alpha*= sampalpha;
04212                             
04213                             /* merge all in one, and then add */
04214                             merge_transp_passes(rl, samp_shr);
04215                             add_transp_passes(rl, od, samp_shr, alpha);
04216 
04217                             if(addpassflag & SCE_PASS_VECTOR)
04218                                 add_transp_speed(rl, od, samp_shr[0].winspeed, alpha, rdrect);
04219                         }
04220                     }
04221                 }
04222             }
04223         }
04224         
04225         aprect+= pa->rectx;
04226         aprectstrand+= pa->rectx;
04227         passrect+= 4*pa->rectx;
04228         offs+= pa->rectx;
04229     }
04230 
04231     /* disable scanline updating */
04232     rr->renlay= NULL;
04233 
04234     MEM_freeN(APixbuf);
04235     if(APixbufstrand)
04236         MEM_freeN(APixbufstrand);
04237     if(sscache)
04238         strand_shade_cache_free(sscache);
04239     freepsA(&apsmbase); 
04240 
04241     if(R.r.mode & R_SHADOW)
04242         ISB_free(pa);
04243 
04244     return ztramask;
04245 }
04246 
04247 
04248 /* end of zbuf.c */