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