Carefully went over all scanline updating while rendering, to ensure only
[blender-staging.git] / source / blender / render / intern / source / zbuf.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributors: Hos, RPW
24  *               2004-2006 Blender Foundation, full recode
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29
30 /*---------------------------------------------------------------------------*/
31 /* Common includes                                                           */
32 /*---------------------------------------------------------------------------*/
33
34 #include <math.h>
35 #include <float.h>
36 #include <stdlib.h>
37 #include <limits.h>
38 #include <string.h>
39
40 #include "BLI_blenlib.h"
41 #include "BLI_threads.h"
42 #include "BLI_jitter.h"
43
44 #include "MTC_matrixops.h"
45 #include "MEM_guardedalloc.h"
46
47 #include "DNA_lamp_types.h"
48 #include "DNA_mesh_types.h"
49 #include "DNA_node_types.h"
50 #include "DNA_meshdata_types.h"
51
52 #include "BKE_global.h"
53 #include "BKE_utildefines.h"
54
55 #include "radio_types.h"
56 #include "radio.h"  /* needs RG, some root data for radiosity */
57
58 #include "RE_render_ext.h"
59
60 /* local includes */
61 #include "gammaCorrectionTables.h"
62 #include "render_types.h"
63 #include "renderpipeline.h"
64 #include "renderdatabase.h"
65 #include "rendercore.h"
66 #include "pixelblending.h"
67
68 /* own includes */
69 #include "zbuf.h"
70
71 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
72 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
73 /* only to be used here in this file, it's for speed */
74 extern struct Render R;
75 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
76
77
78 /* ****************** Spans ******************************* */
79
80 /* each zbuffer has coordinates transformed to local rect coordinates, so we can simply clip */
81 void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty)
82 {
83         memset(zspan, 0, sizeof(ZSpan));
84         
85         zspan->rectx= rectx;
86         zspan->recty= recty;
87         
88         zspan->span1= MEM_mallocT(recty*sizeof(float), "zspan");
89         zspan->span2= MEM_mallocT(recty*sizeof(float), "zspan");
90 }
91
92 static void zbuf_free_span(ZSpan *zspan)
93 {
94         if(zspan) {
95                 if(zspan->span1) MEM_freeT(zspan->span1);
96                 if(zspan->span2) MEM_freeT(zspan->span2);
97                 zspan->span1= zspan->span2= NULL;
98         }
99 }
100
101 /* reset range for clipping */
102 static void zbuf_init_span(ZSpan *zspan)
103 {
104         zspan->miny1= zspan->miny2= zspan->recty+1;
105         zspan->maxy1= zspan->maxy2= -1;
106         zspan->minp1= zspan->maxp1= zspan->minp2= zspan->maxp2= NULL;
107 }
108
109 static void zbuf_add_to_span(ZSpan *zspan, float *v1, float *v2)
110 {
111         float *minv, *maxv, *span;
112         float xx1, dx0, xs0;
113         int y, my0, my2;
114         
115         if(v1[1]<v2[1]) {
116                 minv= v1; maxv= v2;
117         }
118         else {
119                 minv= v2; maxv= v1;
120         }
121         
122         my0= ceil(minv[1]);
123         my2= floor(maxv[1]);
124         
125         if(my2<0 || my0>= zspan->recty) return;
126         
127         /* clip top */
128         if(my2>=zspan->recty) my2= zspan->recty-1;
129         /* clip bottom */
130         if(my0<0) my0= 0;
131         
132         if(my0>my2) return;
133         /* if(my0>my2) should still fill in, that way we get spans that skip nicely */
134         
135         xx1= maxv[1]-minv[1];
136         if(xx1>FLT_EPSILON) {
137                 dx0= (minv[0]-maxv[0])/xx1;
138                 xs0= dx0*(minv[1]-my2) + minv[0];
139         }
140         else {
141                 dx0= 0.0f;
142                 xs0= MIN2(minv[0],maxv[0]);
143         }
144         
145         /* empty span */
146         if(zspan->maxp1 == NULL) {
147                 span= zspan->span1;
148         }
149         else {  /* does it complete left span? */
150                 if( maxv == zspan->minp1 || minv==zspan->maxp1) {
151                         span= zspan->span1;
152                 }
153                 else {
154                         span= zspan->span2;
155                 }
156         }
157
158         if(span==zspan->span1) {
159 //              printf("left span my0 %d my2 %d\n", my0, my2);
160                 if(zspan->minp1==NULL || zspan->minp1[1] > minv[1] ) {
161                         zspan->minp1= minv;
162                 }
163                 if(zspan->maxp1==NULL || zspan->maxp1[1] < maxv[1] ) {
164                         zspan->maxp1= maxv;
165                 }
166                 if(my0<zspan->miny1) zspan->miny1= my0;
167                 if(my2>zspan->maxy1) zspan->maxy1= my2;
168         }
169         else {
170 //              printf("right span my0 %d my2 %d\n", my0, my2);
171                 if(zspan->minp2==NULL || zspan->minp2[1] > minv[1] ) {
172                         zspan->minp2= minv;
173                 }
174                 if(zspan->maxp2==NULL || zspan->maxp2[1] < maxv[1] ) {
175                         zspan->maxp2= maxv;
176                 }
177                 if(my0<zspan->miny2) zspan->miny2= my0;
178                 if(my2>zspan->maxy2) zspan->maxy2= my2;
179         }
180
181         for(y=my2; y>=my0; y--, xs0+= dx0) {
182                 /* xs0 is the xcoord! */
183                 span[y]= xs0;
184         }
185 }
186
187 /*-----------------------------------------------------------*/ 
188 /* Functions                                                 */
189 /*-----------------------------------------------------------*/ 
190
191
192 void fillrect(int *rect, int x, int y, int val)
193 {
194         int len, *drect;
195
196         len= x*y;
197         drect= rect;
198         while(len>0) {
199                 len--;
200                 *drect= val;
201                 drect++;
202         }
203 }
204
205 /* based on Liang&Barsky, for clipping of pyramidical volume */
206 static short cliptestf(float p, float q, float *u1, float *u2)
207 {
208         float r;
209         
210         if(p<0.0) {
211                 if(q<p) return 0;
212                 else if(q<0.0) {
213                         r= q/p;
214                         if(r>*u2) return 0;
215                         else if(r>*u1) *u1=r;
216                 }
217         }
218         else {
219                 if(p>0.0) {
220                         if(q<0.0) return 0;
221                         else if(q<p) {
222                                 r= q/p;
223                                 if(r<*u1) return 0;
224                                 else if(r<*u2) *u2=r;
225                         }
226                 }
227                 else if(q<0.0) return 0;
228         }
229         return 1;
230 }
231
232 int testclip(float *v)
233 {
234         float abs4;     /* WATCH IT: this function should do the same as cliptestf, otherwise troubles in zbufclip()*/
235         short c=0;
236         
237         /* if we set clip flags, the clipping should be at least larger than epsilon. 
238            prevents issues with vertices lying exact on borders */
239         abs4= fabs(v[3]) + FLT_EPSILON;
240         
241         if(v[2]< -abs4) c=16;                   /* this used to be " if(v[2]<0) ", see clippz() */
242         else if(v[2]> abs4) c+= 32;
243         
244         if( v[0]>abs4) c+=2;
245         else if( v[0]< -abs4) c+=1;
246         
247         if( v[1]>abs4) c+=4;
248         else if( v[1]< -abs4) c+=8;
249         
250         return c;
251 }
252
253
254
255 /* *************  ACCUMULATION ZBUF ************ */
256
257
258 static APixstr *addpsmainA(ListBase *lb)
259 {
260         APixstrMain *psm;
261
262         psm= MEM_mallocT(sizeof(APixstrMain), "addpsmainA");
263         BLI_addtail(lb, psm);
264         psm->ps= MEM_callocT(4096*sizeof(APixstr),"pixstr");
265
266         return psm->ps;
267 }
268
269 static void freepsA(ListBase *lb)
270 {
271         APixstrMain *psm, *psmnext;
272
273         for(psm= lb->first; psm; psm= psmnext) {
274                 psmnext= psm->next;
275                 if(psm->ps)
276                         MEM_freeT(psm->ps);
277                 MEM_freeT(psm);
278         }
279 }
280
281 static APixstr *addpsA(ZSpan *zspan)
282 {
283         /* make new PS */
284         if(zspan->apsmcounter==0) {
285                 zspan->curpstr= addpsmainA(zspan->apsmbase);
286                 zspan->apsmcounter= 4095;
287         }
288         else {
289                 zspan->curpstr++;
290                 zspan->apsmcounter--;
291         }
292         return zspan->curpstr;
293 }
294
295 static void zbufinvulAc4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4)
296 {
297         APixstr *ap, *apofs, *apn;
298         double zxd, zyd, zy0, zverg;
299         float x0,y0,z0;
300         float x1,y1,z1,x2,y2,z2,xx1;
301         float *span1, *span2;
302         int *rz, x, y;
303         int sn1, sn2, rectx, *rectzofs, my0, my2, mask;
304         
305         /* init */
306         zbuf_init_span(zspan);
307         
308         /* set spans */
309         zbuf_add_to_span(zspan, v1, v2);
310         zbuf_add_to_span(zspan, v2, v3);
311         if(v4) {
312                 zbuf_add_to_span(zspan, v3, v4);
313                 zbuf_add_to_span(zspan, v4, v1);
314         }
315         else
316                 zbuf_add_to_span(zspan, v3, v1);
317         
318         /* clipped */
319         if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
320
321         if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
322         if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
323         
324         if(my2<my0) return;
325         
326         /* ZBUF DX DY, in floats still */
327         x1= v1[0]- v2[0];
328         x2= v2[0]- v3[0];
329         y1= v1[1]- v2[1];
330         y2= v2[1]- v3[1];
331         z1= v1[2]- v2[2];
332         z2= v2[2]- v3[2];
333         x0= y1*z2-z1*y2;
334         y0= z1*x2-x1*z2;
335         z0= x1*y2-y1*x2;
336         
337         if(z0==0.0) return;
338         
339         xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
340         
341         zxd= -(double)x0/(double)z0;
342         zyd= -(double)y0/(double)z0;
343         zy0= ((double)my2)*zyd + (double)xx1;
344         
345         /* start-offset in rect */
346         rectx= zspan->rectx;
347         rectzofs= (int *)(zspan->arectz+rectx*(my2));
348         apofs= (zspan->apixbuf+ rectx*(my2));
349         mask= zspan->mask;
350
351         /* correct span */
352         sn1= (my0 + my2)/2;
353         if(zspan->span1[sn1] < zspan->span2[sn1]) {
354                 span1= zspan->span1+my2;
355                 span2= zspan->span2+my2;
356         }
357         else {
358                 span1= zspan->span2+my2;
359                 span2= zspan->span1+my2;
360         }
361         
362         for(y=my2; y>=my0; y--, span1--, span2--) {
363                 
364                 sn1= floor(*span1);
365                 sn2= floor(*span2);
366                 sn1++; 
367                 
368                 if(sn2>=rectx) sn2= rectx-1;
369                 if(sn1<0) sn1= 0;
370                 
371                 if(sn2>=sn1) {
372                         zverg= (double)sn1*zxd + zy0;
373                         rz= rectzofs+sn1;
374                         ap= apofs+sn1;
375                         x= sn2-sn1;
376                         
377                         zverg-= zspan->polygon_offset;
378                         
379                         while(x>=0) {
380                                 if( (int)zverg < *rz) {
381 //                                      int i= zvlnr & 3;
382                                         
383                                         apn= ap;
384                                         while(apn) {
385                                                 if(apn->p[0]==0) {apn->p[0]= zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; }
386                                                 if(apn->p[0]==zvlnr) {apn->mask[0]|= mask; break; }
387                                                 if(apn->p[1]==0) {apn->p[1]= zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; }
388                                                 if(apn->p[1]==zvlnr) {apn->mask[1]|= mask; break; }
389                                                 if(apn->p[2]==0) {apn->p[2]= zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; }
390                                                 if(apn->p[2]==zvlnr) {apn->mask[2]|= mask; break; }
391                                                 if(apn->p[3]==0) {apn->p[3]= zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; }
392                                                 if(apn->p[3]==zvlnr) {apn->mask[3]|= mask; break; }
393 //                                              if(apn->p[i]==0) {apn->p[i]= zvlnr; apn->z[i]= zverg; apn->mask[i]= mask; break; }
394 //                                              if(apn->p[i]==zvlnr) {apn->mask[i]|= mask; break; }
395                                                 if(apn->next==NULL) apn->next= addpsA(zspan);
396                                                 apn= apn->next;
397                                         }                               
398                                 }
399                                 zverg+= zxd;
400                                 rz++; 
401                                 ap++; 
402                                 x--;
403                         }
404                 }
405                 
406                 zy0-=zyd;
407                 rectzofs-= rectx;
408                 apofs-= rectx;
409         }
410 }
411
412
413
414 static void zbuflineAc(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
415 {
416         APixstr *ap, *apn;
417         int *rectz;
418         int start, end, x, y, oldx, oldy, ofs;
419         int dz, vergz, mask, maxtest=0;
420         float dx, dy;
421         float v1[3], v2[3];
422         
423         dx= vec2[0]-vec1[0];
424         dy= vec2[1]-vec1[1];
425         
426         mask= zspan->mask;
427         
428         if(fabs(dx) > fabs(dy)) {
429
430                 /* all lines from left to right */
431                 if(vec1[0]<vec2[0]) {
432                         VECCOPY(v1, vec1);
433                         VECCOPY(v2, vec2);
434                 }
435                 else {
436                         VECCOPY(v2, vec1);
437                         VECCOPY(v1, vec2);
438                         dx= -dx; dy= -dy;
439                 }
440
441                 start= floor(v1[0]);
442                 end= start+floor(dx);
443                 if(end>=zspan->rectx) end= zspan->rectx-1;
444                 
445                 oldy= floor(v1[1]);
446                 dy/= dx;
447                 
448                 vergz= v1[2];
449                 vergz-= zspan->polygon_offset;
450                 dz= (v2[2]-v1[2])/dx;
451                 if(vergz>0x50000000 && dz>0) maxtest= 1;                // prevent overflow
452                 
453                 rectz= (int *)(zspan->arectz+zspan->rectx*(oldy) +start);
454                 ap= (zspan->apixbuf+ zspan->rectx*(oldy) +start);
455
456                 if(dy<0) ofs= -zspan->rectx;
457                 else ofs= zspan->rectx;
458                 
459                 for(x= start; x<=end; x++, rectz++, ap++) {
460                         
461                         y= floor(v1[1]);
462                         if(y!=oldy) {
463                                 oldy= y;
464                                 rectz+= ofs;
465                                 ap+= ofs;
466                         }
467                         
468                         if(x>=0 && y>=0 && y<zspan->recty) {
469                                 if(vergz<*rectz) {
470                                 
471                                         apn= ap;
472                                         while(apn) {    /* loop unrolled */
473                                                 if(apn->p[0]==0) {apn->p[0]= zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; }
474                                                 if(apn->p[0]==zvlnr) {apn->mask[0]|= mask; break; }
475                                                 if(apn->p[1]==0) {apn->p[1]= zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; }
476                                                 if(apn->p[1]==zvlnr) {apn->mask[1]|= mask; break; }
477                                                 if(apn->p[2]==0) {apn->p[2]= zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; }
478                                                 if(apn->p[2]==zvlnr) {apn->mask[2]|= mask; break; }
479                                                 if(apn->p[3]==0) {apn->p[3]= zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; }
480                                                 if(apn->p[3]==zvlnr) {apn->mask[3]|= mask; break; }
481                                                 if(apn->next==0) apn->next= addpsA(zspan);
482                                                 apn= apn->next;
483                                         }                               
484                                         
485                                 }
486                         }
487                         
488                         v1[1]+= dy;
489                         if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
490                         else vergz+= dz;
491                 }
492         }
493         else {
494         
495                 /* all lines from top to bottom */
496                 if(vec1[1]<vec2[1]) {
497                         VECCOPY(v1, vec1);
498                         VECCOPY(v2, vec2);
499                 }
500                 else {
501                         VECCOPY(v2, vec1);
502                         VECCOPY(v1, vec2);
503                         dx= -dx; dy= -dy;
504                 }
505
506                 start= floor(v1[1]);
507                 end= start+floor(dy);
508                 
509                 if(start>=zspan->recty || end<0) return;
510                 
511                 if(end>=zspan->recty) end= zspan->recty-1;
512                 
513                 oldx= floor(v1[0]);
514                 dx/= dy;
515                 
516                 vergz= v1[2];
517                 vergz-= zspan->polygon_offset;
518                 dz= (v2[2]-v1[2])/dy;
519                 if(vergz>0x50000000 && dz>0) maxtest= 1;                // prevent overflow
520
521                 rectz= (int *)( zspan->arectz+ (start)*zspan->rectx+ oldx );
522                 ap= (zspan->apixbuf+ zspan->rectx*(start) +oldx);
523                                 
524                 if(dx<0) ofs= -1;
525                 else ofs= 1;
526
527                 for(y= start; y<=end; y++, rectz+=zspan->rectx, ap+=zspan->rectx) {
528                         
529                         x= floor(v1[0]);
530                         if(x!=oldx) {
531                                 oldx= x;
532                                 rectz+= ofs;
533                                 ap+= ofs;
534                         }
535                         
536                         if(x>=0 && y>=0 && x<zspan->rectx) {
537                                 if(vergz<*rectz) {
538                                         
539                                         apn= ap;
540                                         while(apn) {    /* loop unrolled */
541                                                 if(apn->p[0]==0) {apn->p[0]= zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; }
542                                                 if(apn->p[0]==zvlnr) {apn->mask[0]|= mask; break; }
543                                                 if(apn->p[1]==0) {apn->p[1]= zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; }
544                                                 if(apn->p[1]==zvlnr) {apn->mask[1]|= mask; break; }
545                                                 if(apn->p[2]==0) {apn->p[2]= zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; }
546                                                 if(apn->p[2]==zvlnr) {apn->mask[2]|= mask; break; }
547                                                 if(apn->p[3]==0) {apn->p[3]= zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; }
548                                                 if(apn->p[3]==zvlnr) {apn->mask[3]|= mask; break; }
549                                                 if(apn->next==0) apn->next= addpsA(zspan);
550                                                 apn= apn->next;
551                                         }       
552                                         
553                                 }
554                         }
555                         
556                         v1[0]+= dx;
557                         if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
558                         else vergz+= dz;
559                 }
560         }
561 }
562
563 /* *************  NORMAL ZBUFFER ************ */
564
565 static void zbufline(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
566 {
567         int *rectz, *rectp;
568         int start, end, x, y, oldx, oldy, ofs;
569         int dz, vergz, maxtest= 0;
570         float dx, dy;
571         float v1[3], v2[3];
572         
573         dx= vec2[0]-vec1[0];
574         dy= vec2[1]-vec1[1];
575         
576         if(fabs(dx) > fabs(dy)) {
577
578                 /* all lines from left to right */
579                 if(vec1[0]<vec2[0]) {
580                         VECCOPY(v1, vec1);
581                         VECCOPY(v2, vec2);
582                 }
583                 else {
584                         VECCOPY(v2, vec1);
585                         VECCOPY(v1, vec2);
586                         dx= -dx; dy= -dy;
587                 }
588
589                 start= floor(v1[0]);
590                 end= start+floor(dx);
591                 if(end>=zspan->rectx) end= zspan->rectx-1;
592                 
593                 oldy= floor(v1[1]);
594                 dy/= dx;
595                 
596                 vergz= floor(v1[2]);
597                 dz= floor((v2[2]-v1[2])/dx);
598                 if(vergz>0x50000000 && dz>0) maxtest= 1;                // prevent overflow
599                 
600                 rectz= zspan->rectz + oldy*zspan->rectx+ start;
601                 rectp= zspan->rectp + oldy*zspan->rectx+ start;
602                 
603                 if(dy<0) ofs= -zspan->rectx;
604                 else ofs= zspan->rectx;
605                 
606                 for(x= start; x<=end; x++, rectz++, rectp++) {
607                         
608                         y= floor(v1[1]);
609                         if(y!=oldy) {
610                                 oldy= y;
611                                 rectz+= ofs;
612                                 rectp+= ofs;
613                         }
614                         
615                         if(x>=0 && y>=0 && y<zspan->recty) {
616                                 if(vergz<*rectz) {
617                                         *rectz= vergz;
618                                         *rectp= zvlnr;
619                                 }
620                         }
621                         
622                         v1[1]+= dy;
623                         
624                         if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
625                         else vergz+= dz;
626                 }
627         }
628         else {
629                 /* all lines from top to bottom */
630                 if(vec1[1]<vec2[1]) {
631                         VECCOPY(v1, vec1);
632                         VECCOPY(v2, vec2);
633                 }
634                 else {
635                         VECCOPY(v2, vec1);
636                         VECCOPY(v1, vec2);
637                         dx= -dx; dy= -dy;
638                 }
639
640                 start= floor(v1[1]);
641                 end= start+floor(dy);
642                 
643                 if(end>=zspan->recty) end= zspan->recty-1;
644                 
645                 oldx= floor(v1[0]);
646                 dx/= dy;
647                 
648                 vergz= floor(v1[2]);
649                 dz= floor((v2[2]-v1[2])/dy);
650                 if(vergz>0x50000000 && dz>0) maxtest= 1;                // prevent overflow
651                 
652                 rectz= zspan->rectz + start*zspan->rectx+ oldx;
653                 rectp= zspan->rectp + start*zspan->rectx+ oldx;
654                 
655                 if(dx<0) ofs= -1;
656                 else ofs= 1;
657
658                 for(y= start; y<=end; y++, rectz+=zspan->rectx, rectp+=zspan->rectx) {
659                         
660                         x= floor(v1[0]);
661                         if(x!=oldx) {
662                                 oldx= x;
663                                 rectz+= ofs;
664                                 rectp+= ofs;
665                         }
666                         
667                         if(x>=0 && y>=0 && x<zspan->rectx) {
668                                 if(vergz<*rectz) {
669                                         *rectz= vergz;
670                                         *rectp= zvlnr;
671                                 }
672                         }
673                         
674                         v1[0]+= dx;
675                         if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
676                         else vergz+= dz;
677                 }
678         }
679 }
680
681 static void zbufline_onlyZ(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
682 {
683         int *rectz;
684         int start, end, x, y, oldx, oldy, ofs;
685         int dz, vergz, maxtest= 0;
686         float dx, dy;
687         float v1[3], v2[3];
688         
689         dx= vec2[0]-vec1[0];
690         dy= vec2[1]-vec1[1];
691         
692         if(fabs(dx) > fabs(dy)) {
693                 
694                 /* all lines from left to right */
695                 if(vec1[0]<vec2[0]) {
696                         VECCOPY(v1, vec1);
697                         VECCOPY(v2, vec2);
698                 }
699                 else {
700                         VECCOPY(v2, vec1);
701                         VECCOPY(v1, vec2);
702                         dx= -dx; dy= -dy;
703                 }
704                 
705                 start= floor(v1[0]);
706                 end= start+floor(dx);
707                 if(end>=zspan->rectx) end= zspan->rectx-1;
708                 
709                 oldy= floor(v1[1]);
710                 dy/= dx;
711                 
712                 vergz= floor(v1[2]);
713                 dz= floor((v2[2]-v1[2])/dx);
714                 if(vergz>0x50000000 && dz>0) maxtest= 1;                // prevent overflow
715                 
716                 rectz= zspan->rectz + oldy*zspan->rectx+ start;
717                 
718                 if(dy<0) ofs= -zspan->rectx;
719                 else ofs= zspan->rectx;
720                 
721                 for(x= start; x<=end; x++, rectz++) {
722                         
723                         y= floor(v1[1]);
724                         if(y!=oldy) {
725                                 oldy= y;
726                                 rectz+= ofs;
727                         }
728                         
729                         if(x>=0 && y>=0 && y<zspan->recty) {
730                                 if(vergz<*rectz) {
731                                         *rectz= vergz;
732                                 }
733                         }
734                         
735                         v1[1]+= dy;
736                         
737                         if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
738                         else vergz+= dz;
739                 }
740         }
741         else {
742                 /* all lines from top to bottom */
743                 if(vec1[1]<vec2[1]) {
744                         VECCOPY(v1, vec1);
745                         VECCOPY(v2, vec2);
746                 }
747                 else {
748                         VECCOPY(v2, vec1);
749                         VECCOPY(v1, vec2);
750                         dx= -dx; dy= -dy;
751                 }
752                 
753                 start= floor(v1[1]);
754                 end= start+floor(dy);
755                 
756                 if(end>=zspan->recty) end= zspan->recty-1;
757                 
758                 oldx= floor(v1[0]);
759                 dx/= dy;
760                 
761                 vergz= floor(v1[2]);
762                 dz= floor((v2[2]-v1[2])/dy);
763                 if(vergz>0x50000000 && dz>0) maxtest= 1;                // prevent overflow
764                 
765                 rectz= zspan->rectz + start*zspan->rectx+ oldx;
766                 
767                 if(dx<0) ofs= -1;
768                 else ofs= 1;
769                 
770                 for(y= start; y<=end; y++, rectz+=zspan->rectx) {
771                         
772                         x= floor(v1[0]);
773                         if(x!=oldx) {
774                                 oldx= x;
775                                 rectz+= ofs;
776                         }
777                         
778                         if(x>=0 && y>=0 && x<zspan->rectx) {
779                                 if(vergz<*rectz) {
780                                         *rectz= vergz;
781                                 }
782                         }
783                         
784                         v1[0]+= dx;
785                         if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
786                         else vergz+= dz;
787                 }
788         }
789 }
790
791
792 static int clipline(float *v1, float *v2)       /* return 0: do not draw */
793 {
794         float dz,dw, u1=0.0, u2=1.0;
795         float dx, dy, v13;
796         
797         dz= v2[2]-v1[2];
798         dw= v2[3]-v1[3];
799         
800         /* this 1.01 is for clipping x and y just a tinsy larger. that way it is
801                 filled in with zbufwire correctly when rendering in parts. otherwise
802                 you see line endings at edges... */
803         
804         if(cliptestf(-dz-dw, v1[3]+v1[2], &u1,&u2)) {
805                 if(cliptestf(dz-dw, v1[3]-v1[2], &u1,&u2)) {
806                         
807                         dx= v2[0]-v1[0];
808                         dz= 1.01*(v2[3]-v1[3]);
809                         v13= 1.01*v1[3];
810                         
811                         if(cliptestf(-dx-dz, v1[0]+v13, &u1,&u2)) {
812                                 if(cliptestf(dx-dz, v13-v1[0], &u1,&u2)) {
813                                         
814                                         dy= v2[1]-v1[1];
815                                         
816                                         if(cliptestf(-dy-dz, v1[1]+v13, &u1,&u2)) {
817                                                 if(cliptestf(dy-dz, v13-v1[1], &u1,&u2)) {
818                                                         
819                                                         if(u2<1.0) {
820                                                                 v2[0]= v1[0]+u2*dx;
821                                                                 v2[1]= v1[1]+u2*dy;
822                                                                 v2[2]= v1[2]+u2*dz;
823                                                                 v2[3]= v1[3]+u2*dw;
824                                                         }
825                                                         if(u1>0.0) {
826                                                                 v1[0]= v1[0]+u1*dx;
827                                                                 v1[1]= v1[1]+u1*dy;
828                                                                 v1[2]= v1[2]+u1*dz;
829                                                                 v1[3]= v1[3]+u1*dw;
830                                                         }
831                                                         return 1;
832                                                 }
833                                         }
834                                 }
835                         }
836                 }
837         }
838         
839         return 0;
840 }
841
842 static void hoco_to_zco(ZSpan *zspan, float *zco, float *hoco)
843 {
844         float div;
845         
846         div= 1.0f/hoco[3];
847         zco[0]= zspan->zmulx*(1.0+hoco[0]*div) + zspan->zofsx;
848         zco[1]= zspan->zmuly*(1.0+hoco[1]*div) + zspan->zofsy;
849         zco[2]= 0x7FFFFFFF *(hoco[2]*div);
850 }
851
852 void zbufclipwire(ZSpan *zspan, int zvlnr, VlakRen *vlr)
853 {
854         float vez[20], *f1, *f2, *f3, *f4= 0;
855         int c1, c2, c3, c4, ec, and, or;
856
857         /* edgecode: 1= draw */
858         ec = vlr->ec;
859         if(ec==0) return;
860
861         c1= vlr->v1->clip;
862         c2= vlr->v2->clip;
863         c3= vlr->v3->clip;
864         f1= vlr->v1->ho;
865         f2= vlr->v2->ho;
866         f3= vlr->v3->ho;
867         
868         if(vlr->v4) {
869                 f4= vlr->v4->ho;
870                 c4= vlr->v4->clip;
871                 
872                 and= (c1 & c2 & c3 & c4);
873                 or= (c1 | c2 | c3 | c4);
874         }
875         else {
876                 and= (c1 & c2 & c3);
877                 or= (c1 | c2 | c3);
878         }
879         
880         if(or) {        /* not in the middle */
881                 if(and) {       /* out completely */
882                         return;
883                 }
884                 else {  /* clipping */
885
886                         if(ec & ME_V1V2) {
887                                 QUATCOPY(vez, f1);
888                                 QUATCOPY(vez+4, f2);
889                                 if( clipline(vez, vez+4)) {
890                                         hoco_to_zco(zspan, vez, vez);
891                                         hoco_to_zco(zspan, vez+4, vez+4);
892                                         zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4);
893                                 }
894                         }
895                         if(ec & ME_V2V3) {
896                                 QUATCOPY(vez, f2);
897                                 QUATCOPY(vez+4, f3);
898                                 if( clipline(vez, vez+4)) {
899                                         hoco_to_zco(zspan, vez, vez);
900                                         hoco_to_zco(zspan, vez+4, vez+4);
901                                         zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4);
902                                 }
903                         }
904                         if(vlr->v4) {
905                                 if(ec & ME_V3V4) {
906                                         QUATCOPY(vez, f3);
907                                         QUATCOPY(vez+4, f4);
908                                         if( clipline(vez, vez+4)) {
909                                                 hoco_to_zco(zspan, vez, vez);
910                                                 hoco_to_zco(zspan, vez+4, vez+4);
911                                                 zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4);
912                                         }
913                                 }
914                                 if(ec & ME_V4V1) {
915                                         QUATCOPY(vez, f4);
916                                         QUATCOPY(vez+4, f1);
917                                         if( clipline(vez, vez+4)) {
918                                                 hoco_to_zco(zspan, vez, vez);
919                                                 hoco_to_zco(zspan, vez+4, vez+4);
920                                                 zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4);
921                                         }
922                                 }
923                         }
924                         else {
925                                 if(ec & ME_V3V1) {
926                                         QUATCOPY(vez, f3);
927                                         QUATCOPY(vez+4, f1);
928                                         if( clipline(vez, vez+4)) {
929                                                 hoco_to_zco(zspan, vez, vez);
930                                                 hoco_to_zco(zspan, vez+4, vez+4);
931                                                 zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4);
932                                         }
933                                 }
934                         }
935                         
936                         return;
937                 }
938         }
939
940         hoco_to_zco(zspan, vez, f1);
941         hoco_to_zco(zspan, vez+4, f2);
942         hoco_to_zco(zspan, vez+8, f3);
943         if(vlr->v4) {
944                 hoco_to_zco(zspan, vez+12, f4);
945
946                 if(ec & ME_V3V4)  zspan->zbuflinefunc(zspan, zvlnr, vez+8, vez+12);
947                 if(ec & ME_V4V1)  zspan->zbuflinefunc(zspan, zvlnr, vez+12, vez);
948         }
949         else {
950                 if(ec & ME_V3V1)  zspan->zbuflinefunc(zspan, zvlnr, vez+8, vez);
951         }
952
953         if(ec & ME_V1V2)  zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4);
954         if(ec & ME_V2V3)  zspan->zbuflinefunc(zspan, zvlnr, vez+4, vez+8);
955
956 }
957
958 /**
959  * Fill the z buffer, but invert z order, and add the face index to
960  * the corresponing face buffer.
961  *
962  * This is one of the z buffer fill functions called in zbufclip() and
963  * zbufwireclip(). 
964  *
965  * @param v1 [4 floats, world coordinates] first vertex
966  * @param v2 [4 floats, world coordinates] second vertex
967  * @param v3 [4 floats, world coordinates] third vertex
968  */
969 static void zbufinvulGLinv4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4) 
970 {
971         double zxd, zyd, zy0, zverg;
972         float x0,y0,z0;
973         float x1,y1,z1,x2,y2,z2,xx1;
974         float *span1, *span2;
975         int *rectpofs, *rp;
976         int *rz, x, y;
977         int sn1, sn2, rectx, *rectzofs, my0, my2;
978         
979         /* init */
980         zbuf_init_span(zspan);
981         
982         /* set spans */
983         zbuf_add_to_span(zspan, v1, v2);
984         zbuf_add_to_span(zspan, v2, v3);
985         if(v4) {
986                 zbuf_add_to_span(zspan, v3, v4);
987                 zbuf_add_to_span(zspan, v4, v1);
988         }
989         else 
990                 zbuf_add_to_span(zspan, v3, v1);
991         
992         /* clipped */
993         if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
994         
995         if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
996         if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
997         
998         //      printf("my %d %d\n", my0, my2);
999         if(my2<my0) return;
1000         
1001         
1002         /* ZBUF DX DY, in floats still */
1003         x1= v1[0]- v2[0];
1004         x2= v2[0]- v3[0];
1005         y1= v1[1]- v2[1];
1006         y2= v2[1]- v3[1];
1007         z1= v1[2]- v2[2];
1008         z2= v2[2]- v3[2];
1009         x0= y1*z2-z1*y2;
1010         y0= z1*x2-x1*z2;
1011         z0= x1*y2-y1*x2;
1012         
1013         if(z0==0.0) return;
1014         
1015         xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
1016         
1017         zxd= -(double)x0/(double)z0;
1018         zyd= -(double)y0/(double)z0;
1019         zy0= ((double)my2)*zyd + (double)xx1;
1020         
1021         /* start-offset in rect */
1022         rectx= zspan->rectx;
1023         rectzofs= (zspan->rectz+rectx*my2);
1024         rectpofs= (zspan->rectp+rectx*my2);
1025         
1026         /* correct span */
1027         sn1= (my0 + my2)/2;
1028         if(zspan->span1[sn1] < zspan->span2[sn1]) {
1029                 span1= zspan->span1+my2;
1030                 span2= zspan->span2+my2;
1031         }
1032         else {
1033                 span1= zspan->span2+my2;
1034                 span2= zspan->span1+my2;
1035         }
1036         
1037         for(y=my2; y>=my0; y--, span1--, span2--) {
1038                 
1039                 sn1= floor(*span1);
1040                 sn2= floor(*span2);
1041                 sn1++; 
1042                 
1043                 if(sn2>=rectx) sn2= rectx-1;
1044                 if(sn1<0) sn1= 0;
1045                 
1046                 if(sn2>=sn1) {
1047                         zverg= (double)sn1*zxd + zy0;
1048                         rz= rectzofs+sn1;
1049                         rp= rectpofs+sn1;
1050                         x= sn2-sn1;
1051                         
1052                         while(x>=0) {
1053                                 if( (int)zverg > *rz || *rz==0x7FFFFFFF) {
1054                                         *rz= (int)zverg;
1055                                         *rp= zvlnr;
1056                                 }
1057                                 zverg+= zxd;
1058                                 rz++; 
1059                                 rp++; 
1060                                 x--;
1061                         }
1062                 }
1063                 
1064                 zy0-=zyd;
1065                 rectzofs-= rectx;
1066                 rectpofs-= rectx;
1067         }
1068 }
1069
1070 /* uses spanbuffers */
1071
1072 static void zbufinvulGL4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4)
1073 {
1074         double zxd, zyd, zy0, zverg;
1075         float x0,y0,z0;
1076         float x1,y1,z1,x2,y2,z2,xx1;
1077         float *span1, *span2;
1078         int *rectpofs, *rp;
1079         int *rz, x, y;
1080         int sn1, sn2, rectx, *rectzofs, my0, my2;
1081         
1082         /* init */
1083         zbuf_init_span(zspan);
1084         
1085         /* set spans */
1086         zbuf_add_to_span(zspan, v1, v2);
1087         zbuf_add_to_span(zspan, v2, v3);
1088         if(v4) {
1089                 zbuf_add_to_span(zspan, v3, v4);
1090                 zbuf_add_to_span(zspan, v4, v1);
1091         }
1092         else 
1093                 zbuf_add_to_span(zspan, v3, v1);
1094                 
1095         /* clipped */
1096         if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
1097         
1098         if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
1099         if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
1100         
1101 //      printf("my %d %d\n", my0, my2);
1102         if(my2<my0) return;
1103         
1104         
1105         /* ZBUF DX DY, in floats still */
1106         x1= v1[0]- v2[0];
1107         x2= v2[0]- v3[0];
1108         y1= v1[1]- v2[1];
1109         y2= v2[1]- v3[1];
1110         z1= v1[2]- v2[2];
1111         z2= v2[2]- v3[2];
1112         x0= y1*z2-z1*y2;
1113         y0= z1*x2-x1*z2;
1114         z0= x1*y2-y1*x2;
1115         
1116         if(z0==0.0) return;
1117
1118         xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
1119
1120         zxd= -(double)x0/(double)z0;
1121         zyd= -(double)y0/(double)z0;
1122         zy0= ((double)my2)*zyd + (double)xx1;
1123
1124         /* start-offset in rect */
1125         rectx= zspan->rectx;
1126         rectzofs= (zspan->rectz+rectx*my2);
1127         rectpofs= (zspan->rectp+rectx*my2);
1128
1129         /* correct span */
1130         sn1= (my0 + my2)/2;
1131         if(zspan->span1[sn1] < zspan->span2[sn1]) {
1132                 span1= zspan->span1+my2;
1133                 span2= zspan->span2+my2;
1134         }
1135         else {
1136                 span1= zspan->span2+my2;
1137                 span2= zspan->span1+my2;
1138         }
1139         
1140         for(y=my2; y>=my0; y--, span1--, span2--) {
1141                 
1142                 sn1= floor(*span1);
1143                 sn2= floor(*span2);
1144                 sn1++; 
1145                 
1146                 if(sn2>=rectx) sn2= rectx-1;
1147                 if(sn1<0) sn1= 0;
1148                 
1149                 if(sn2>=sn1) {
1150                         zverg= (double)sn1*zxd + zy0;
1151                         rz= rectzofs+sn1;
1152                         rp= rectpofs+sn1;
1153                         x= sn2-sn1;
1154                         
1155                         while(x>=0) {
1156                                 if( (int)zverg < *rz) {
1157                                         *rz= (int)zverg;
1158                                         *rp= zvlnr;
1159                                 }
1160                                 zverg+= zxd;
1161                                 rz++; 
1162                                 rp++; 
1163                                 x--;
1164                         }
1165                 }
1166                 
1167                 zy0-=zyd;
1168                 rectzofs-= rectx;
1169                 rectpofs-= rectx;
1170         }
1171 }
1172
1173 /**
1174  * Fill the z buffer. The face buffer is not operated on!
1175  *
1176  * This is one of the z buffer fill functions called in zbufclip() and
1177  * zbufwireclip(). 
1178  *
1179  * @param v1 [4 floats, world coordinates] first vertex
1180  * @param v2 [4 floats, world coordinates] second vertex
1181  * @param v3 [4 floats, world coordinates] third vertex
1182  */
1183
1184 static void zbufinvulGL_onlyZ(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4) 
1185 {
1186         double zxd, zyd, zy0, zverg;
1187         float x0,y0,z0;
1188         float x1,y1,z1,x2,y2,z2,xx1;
1189         float *span1, *span2;
1190         int *rz, x, y;
1191         int sn1, sn2, rectx, *rectzofs, my0, my2;
1192         
1193         /* init */
1194         zbuf_init_span(zspan);
1195         
1196         /* set spans */
1197         zbuf_add_to_span(zspan, v1, v2);
1198         zbuf_add_to_span(zspan, v2, v3);
1199         if(v4) {
1200                 zbuf_add_to_span(zspan, v3, v4);
1201                 zbuf_add_to_span(zspan, v4, v1);
1202         }
1203         else 
1204                 zbuf_add_to_span(zspan, v3, v1);
1205         
1206         /* clipped */
1207         if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
1208         
1209         if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
1210         if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
1211         
1212         //      printf("my %d %d\n", my0, my2);
1213         if(my2<my0) return;
1214         
1215         
1216         /* ZBUF DX DY, in floats still */
1217         x1= v1[0]- v2[0];
1218         x2= v2[0]- v3[0];
1219         y1= v1[1]- v2[1];
1220         y2= v2[1]- v3[1];
1221         z1= v1[2]- v2[2];
1222         z2= v2[2]- v3[2];
1223         x0= y1*z2-z1*y2;
1224         y0= z1*x2-x1*z2;
1225         z0= x1*y2-y1*x2;
1226         
1227         if(z0==0.0) return;
1228         
1229         xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
1230         
1231         zxd= -(double)x0/(double)z0;
1232         zyd= -(double)y0/(double)z0;
1233         zy0= ((double)my2)*zyd + (double)xx1;
1234         
1235         /* start-offset in rect */
1236         rectx= zspan->rectx;
1237         rectzofs= (zspan->rectz+rectx*my2);
1238         
1239         /* correct span */
1240         sn1= (my0 + my2)/2;
1241         if(zspan->span1[sn1] < zspan->span2[sn1]) {
1242                 span1= zspan->span1+my2;
1243                 span2= zspan->span2+my2;
1244         }
1245         else {
1246                 span1= zspan->span2+my2;
1247                 span2= zspan->span1+my2;
1248         }
1249         
1250         for(y=my2; y>=my0; y--, span1--, span2--) {
1251                 
1252                 sn1= floor(*span1);
1253                 sn2= floor(*span2);
1254                 sn1++; 
1255                 
1256                 if(sn2>=rectx) sn2= rectx-1;
1257                 if(sn1<0) sn1= 0;
1258                 
1259                 if(sn2>=sn1) {
1260                         zverg= (double)sn1*zxd + zy0;
1261                         rz= rectzofs+sn1;
1262                         x= sn2-sn1;
1263                         
1264                         while(x>=0) {
1265                                 if( (int)zverg < *rz) {
1266                                         *rz= (int)zverg;
1267                                 }
1268                                 zverg+= zxd;
1269                                 rz++; 
1270                                 x--;
1271                         }
1272                 }
1273                 
1274                 zy0-=zyd;
1275                 rectzofs-= rectx;
1276         }
1277 }
1278
1279
1280 /**
1281  * (clip pyramid)
1282  * Sets labda: flag, and parametrize the clipping of vertices in
1283  * viewspace coordinates. labda = -1 means no clipping, labda in [0,
1284          * 1] means a clipping.
1285  * Note: uses globals.
1286  * @param v1 start coordinate s
1287  * @param v2 target coordinate t
1288  * @param b1 
1289  * @param b2 
1290  * @param b3
1291  * @param a index for coordinate (x, y, or z)
1292  */
1293
1294 static void clippyra(float *labda, float *v1, float *v2, int *b2, int *b3, int a)
1295 {
1296         float da,dw,u1=0.0,u2=1.0;
1297         float v13;
1298         
1299         labda[0]= -1.0;
1300         labda[1]= -1.0;
1301
1302         da= v2[a]-v1[a];
1303         /* prob; we clip slightly larger, osa renders add 2 pixels on edges, should become variable? */
1304         /* or better; increase r.winx/y size, but thats quite a complex one. do it later */
1305         if(a==2) {
1306                 dw= (v2[3]-v1[3]);
1307                 v13= v1[3];
1308         }
1309         else {
1310                 dw= 1.005f*(v2[3]-v1[3]);
1311                 v13= 1.005f*v1[3];
1312         }       
1313         /* according the original article by Liang&Barsky, for clipping of
1314          * homogenous coordinates with viewplane, the value of "0" is used instead of "-w" .
1315          * This differs from the other clipping cases (like left or top) and I considered
1316          * it to be not so 'homogenic'. But later it has proven to be an error,
1317          * who would have thought that of L&B!
1318          */
1319
1320         if(cliptestf(-da-dw, v13+v1[a], &u1,&u2)) {
1321                 if(cliptestf(da-dw, v13-v1[a], &u1,&u2)) {
1322                         *b3=1;
1323                         if(u2<1.0) {
1324                                 labda[1]= u2;
1325                                 *b2=1;
1326                         }
1327                         else labda[1]=1.0;  /* u2 */
1328                         if(u1>0.0) {
1329                                 labda[0]= u1;
1330                                 *b2=1;
1331                         } else labda[0]=0.0;
1332                 }
1333         }
1334 }
1335
1336 /**
1337  * (make vertex pyramide clip)
1338  * Checks labda and uses this to make decision about clipping the line
1339  * segment from v1 to v2. labda is the factor by which the vector is
1340  * cut. ( calculate s + l * ( t - s )). The result is appended to the
1341  * vertex list of this face.
1342  * 
1343  * 
1344  * @param v1 start coordinate s
1345  * @param v2 target coordinate t
1346  * @param b1 
1347  * @param b2 
1348  * @param clve vertex vector.
1349  */
1350
1351 static void makevertpyra(float *vez, float *labda, float **trias, float *v1, float *v2, int *b1, int *clve)
1352 {
1353         float l1, l2, *adr;
1354
1355         l1= labda[0];
1356         l2= labda[1];
1357
1358         if(l1!= -1.0) {
1359                 if(l1!= 0.0) {
1360                         adr= vez+4*(*clve);
1361                         trias[*b1]=adr;
1362                         (*clve)++;
1363                         adr[0]= v1[0]+l1*(v2[0]-v1[0]);
1364                         adr[1]= v1[1]+l1*(v2[1]-v1[1]);
1365                         adr[2]= v1[2]+l1*(v2[2]-v1[2]);
1366                         adr[3]= v1[3]+l1*(v2[3]-v1[3]);
1367                 } 
1368                 else trias[*b1]= v1;
1369                 
1370                 (*b1)++;
1371         }
1372         if(l2!= -1.0) {
1373                 if(l2!= 1.0) {
1374                         adr= vez+4*(*clve);
1375                         trias[*b1]=adr;
1376                         (*clve)++;
1377                         adr[0]= v1[0]+l2*(v2[0]-v1[0]);
1378                         adr[1]= v1[1]+l2*(v2[1]-v1[1]);
1379                         adr[2]= v1[2]+l2*(v2[2]-v1[2]);
1380                         adr[3]= v1[3]+l2*(v2[3]-v1[3]);
1381                         (*b1)++;
1382                 }
1383         }
1384 }
1385
1386 /* ------------------------------------------------------------------------- */
1387
1388 void projectverto(float *v1, float winmat[][4], float *adr)
1389 {
1390         /* calcs homogenic coord of vertex v1 */
1391         float x,y,z;
1392
1393         x= v1[0]; 
1394         y= v1[1]; 
1395         z= v1[2];
1396         adr[0]= x*winmat[0][0]                          +       z*winmat[2][0] + winmat[3][0];
1397         adr[1]=                       y*winmat[1][1]    +       z*winmat[2][1] + winmat[3][1];
1398         adr[2]=                                                                         z*winmat[2][2] + winmat[3][2];
1399         adr[3]=                                                                         z*winmat[2][3] + winmat[3][3];
1400
1401         //printf("hoco %f %f %f %f\n", adr[0], adr[1], adr[2], adr[3]);
1402 }
1403
1404 /* ------------------------------------------------------------------------- */
1405
1406 void projectvert(float *v1, float winmat[][4], float *adr)
1407 {
1408         /* calcs homogenic coord of vertex v1 */
1409         float x,y,z;
1410
1411         x= v1[0]; 
1412         y= v1[1]; 
1413         z= v1[2];
1414         adr[0]= x*winmat[0][0]+ y*winmat[1][0]+ z*winmat[2][0]+ winmat[3][0];
1415         adr[1]= x*winmat[0][1]+ y*winmat[1][1]+ z*winmat[2][1]+ winmat[3][1];
1416         adr[2]= x*winmat[0][2]+ y*winmat[1][2]+ z*winmat[2][2]+ winmat[3][2];
1417         adr[3]= x*winmat[0][3]+ y*winmat[1][3]+ z*winmat[2][3]+ winmat[3][3];
1418 }
1419
1420 /* do zbuffering and clip, f1 f2 f3 are hocos, c1 c2 c3 are clipping flags */
1421
1422 void zbufclip(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1, int c2, int c3)
1423 {
1424         float *vlzp[32][3], labda[3][2];
1425         float vez[400], *trias[40];
1426
1427         if(c1 | c2 | c3) {      /* not in middle */
1428                 if(c1 & c2 & c3) {      /* completely out */
1429                         return;
1430                 } else {        /* clipping */
1431                         int arg, v, b, clipflag[3], b1, b2, b3, c4, clve=3, clvlo, clvl=1;
1432
1433                         vez[0]= f1[0]; vez[1]= f1[1]; vez[2]= f1[2]; vez[3]= f1[3];
1434                         vez[4]= f2[0]; vez[5]= f2[1]; vez[6]= f2[2]; vez[7]= f2[3];
1435                         vez[8]= f3[0]; vez[9]= f3[1]; vez[10]= f3[2];vez[11]= f3[3];
1436
1437                         vlzp[0][0]= vez;
1438                         vlzp[0][1]= vez+4;
1439                         vlzp[0][2]= vez+8;
1440
1441                         clipflag[0]= ( (c1 & 48) | (c2 & 48) | (c3 & 48) );
1442                         if(clipflag[0]==0) {    /* othwerwise it needs to be calculated again, after the first (z) clip */
1443                                 clipflag[1]= ( (c1 & 3) | (c2 & 3) | (c3 & 3) );
1444                                 clipflag[2]= ( (c1 & 12) | (c2 & 12) | (c3 & 12) );
1445                         }
1446                         
1447                         for(b=0;b<3;b++) {
1448                                 
1449                                 if(clipflag[b]) {
1450                                 
1451                                         clvlo= clvl;
1452                                         
1453                                         for(v=0; v<clvlo; v++) {
1454                                         
1455                                                 if(vlzp[v][0]!=0) {     /* face is still there */
1456                                                         b2= b3 =0;      /* clip flags */
1457
1458                                                         if(b==0) arg= 2;
1459                                                         else if (b==1) arg= 0;
1460                                                         else arg= 1;
1461                                                         
1462                                                         clippyra(labda[0], vlzp[v][0],vlzp[v][1], &b2,&b3, arg);
1463                                                         clippyra(labda[1], vlzp[v][1],vlzp[v][2], &b2,&b3, arg);
1464                                                         clippyra(labda[2], vlzp[v][2],vlzp[v][0], &b2,&b3, arg);
1465
1466                                                         if(b2==0 && b3==1) {
1467                                                                 /* completely 'in' */;
1468                                                                 vlzp[clvl][0]= vlzp[v][0];
1469                                                                 vlzp[clvl][1]= vlzp[v][1];
1470                                                                 vlzp[clvl][2]= vlzp[v][2];
1471                                                                 clvl++;
1472                                                         } else if(b3==0) {
1473                                                                 vlzp[v][0]=0;
1474                                                                 /* completely 'out' */;
1475                                                         } else {
1476                                                                 b1=0;
1477                                                                 makevertpyra(vez, labda[0], trias, vlzp[v][0],vlzp[v][1], &b1,&clve);
1478                                                                 makevertpyra(vez, labda[1], trias, vlzp[v][1],vlzp[v][2], &b1,&clve);
1479                                                                 makevertpyra(vez, labda[2], trias, vlzp[v][2],vlzp[v][0], &b1,&clve);
1480
1481                                                                 /* after front clip done: now set clip flags */
1482                                                                 if(b==0) {
1483                                                                         clipflag[1]= clipflag[2]= 0;
1484                                                                         f1= vez;
1485                                                                         for(b3=0; b3<clve; b3++) {
1486                                                                                 c4= testclip(f1);
1487                                                                                 clipflag[1] |= (c4 & 3);
1488                                                                                 clipflag[2] |= (c4 & 12);
1489                                                                                 f1+= 4;
1490                                                                         }
1491                                                                 }
1492                                                                 
1493                                                                 vlzp[v][0]=0;
1494                                                                 if(b1>2) {
1495                                                                         for(b3=3; b3<=b1; b3++) {
1496                                                                                 vlzp[clvl][0]= trias[0];
1497                                                                                 vlzp[clvl][1]= trias[b3-2];
1498                                                                                 vlzp[clvl][2]= trias[b3-1];
1499                                                                                 clvl++;
1500                                                                         }
1501                                                                 }
1502                                                         }
1503                                                 }
1504                                         }
1505                                 }
1506                         }
1507
1508             /* warning, this should never happen! */
1509                         if(clve>38 || clvl>31) printf("clip overflow: clve clvl %d %d\n",clve,clvl);
1510
1511             /* perspective division */
1512                         f1=vez;
1513                         for(c1=0;c1<clve;c1++) {
1514                                 hoco_to_zco(zspan, f1, f1);
1515                                 f1+=4;
1516                         }
1517                         for(b=1;b<clvl;b++) {
1518                                 if(vlzp[b][0]) {
1519                                         zspan->zbuffunc(zspan, zvlnr, vlzp[b][0],vlzp[b][1],vlzp[b][2], NULL);
1520                                 }
1521                         }
1522                         return;
1523                 }
1524         }
1525
1526         /* perspective division: HCS to ZCS */
1527         hoco_to_zco(zspan, vez, f1);
1528         hoco_to_zco(zspan, vez+4, f2);
1529         hoco_to_zco(zspan, vez+8, f3);
1530
1531         zspan->zbuffunc(zspan, zvlnr, vez,vez+4,vez+8, NULL);
1532 }
1533
1534 static void zbufclip4(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, float *f4, int c1, int c2, int c3, int c4)
1535 {
1536         float vez[16];
1537         
1538         if(c1 | c2 | c3 | c4) { /* not in middle */
1539                 if(c1 & c2 & c3 & c4) { /* completely out */
1540                         return;
1541                 } else {        /* clipping */
1542                         zbufclip(zspan, zvlnr, f1, f2, f3, c1, c2, c3);
1543                         zbufclip(zspan, zvlnr, f1, f3, f4, c1, c3, c4);
1544                 }
1545                 return;
1546         }
1547
1548         /* perspective division: HCS to ZCS */
1549         hoco_to_zco(zspan, vez, f1);
1550         hoco_to_zco(zspan, vez+4, f2);
1551         hoco_to_zco(zspan, vez+8, f3);
1552         hoco_to_zco(zspan, vez+12, f4);
1553
1554         zspan->zbuffunc(zspan, zvlnr, vez, vez+4, vez+8, vez+12);
1555 }
1556
1557
1558 /* ***************** ZBUFFER MAIN ROUTINES **************** */
1559
1560 void set_part_zbuf_clipflag(RenderPart *pa)
1561 {
1562         VertRen *ver=NULL;
1563         float minx, miny, maxx, maxy, wco;
1564         unsigned short clipclear;
1565         int v;
1566
1567         minx= (2*pa->disprect.xmin - R.winx-1)/(float)R.winx;
1568         maxx= (2*pa->disprect.xmax - R.winx+1)/(float)R.winx;
1569         miny= (2*pa->disprect.ymin - R.winy-1)/(float)R.winy;
1570         maxy= (2*pa->disprect.ymax - R.winy+1)/(float)R.winy;
1571         
1572         /* supports up to 4 threads this way */
1573         clipclear= ~(15 << 4*(pa->thread & 3));
1574         
1575         for(v=0; v<R.totvert; v++) {
1576                 if((v & 255)==0) ver= RE_findOrAddVert(&R, v);
1577                 else ver++;
1578                 
1579                 wco= ver->ho[3];
1580                 ver->flag &= clipclear;
1581                 
1582                 switch(pa->thread & 3) {
1583                         case 0:
1584                                 if( ver->ho[0] > maxx*wco) ver->flag |= 1;
1585                                 else if( ver->ho[0]< minx*wco) ver->flag |= 2;
1586                                 if( ver->ho[1] > maxy*wco) ver->flag |= 4;
1587                                 else if( ver->ho[1]< miny*wco) ver->flag |= 8;
1588                                 break;
1589                         case 1:
1590                                 if( ver->ho[0] > maxx*wco) ver->flag |= 16;
1591                                 else if( ver->ho[0]< minx*wco) ver->flag |= 32;
1592                                 if( ver->ho[1] > maxy*wco) ver->flag |= 64;
1593                                 else if( ver->ho[1]< miny*wco) ver->flag |= 128;
1594                                 break;
1595                         case 2:
1596                                 if( ver->ho[0] > maxx*wco) ver->flag |= 256;
1597                                 else if( ver->ho[0]< minx*wco) ver->flag |= 512;
1598                                 if( ver->ho[1] > maxy*wco) ver->flag |= 1024;
1599                                 else if( ver->ho[1]< miny*wco) ver->flag |= 2048;
1600                                 break;
1601                         case 3:
1602                                 if( ver->ho[0] > maxx*wco) ver->flag |= 4096;
1603                                 else if( ver->ho[0]< minx*wco) ver->flag |= 8192;
1604                                 if( ver->ho[1] > maxy*wco) ver->flag |= 16384;
1605                                 else if( ver->ho[1]< miny*wco) ver->flag |= 32768;
1606                                 break;
1607                 }
1608         }
1609 }
1610
1611 void zbuffer_solid(RenderPart *pa, unsigned int lay, short layflag)
1612 {
1613         ZSpan zspan;
1614         VlakRen *vlr= NULL;
1615         Material *ma=0;
1616         int v, zvlnr;
1617         unsigned short clipmask;
1618         short nofill=0, env=0, wire=0;
1619
1620         zbuf_alloc_span(&zspan, pa->rectx, pa->recty);
1621         
1622         /* needed for transform from hoco to zbuffer co */
1623         zspan.zmulx=  ((float)R.winx)/2.0;
1624         zspan.zmuly=  ((float)R.winy)/2.0;
1625         if(R.osa) {
1626                 zspan.zofsx= -pa->disprect.xmin - R.jit[pa->sample][0];
1627                 zspan.zofsy= -pa->disprect.ymin - R.jit[pa->sample][1];
1628         }
1629         else {
1630                 zspan.zofsx= -pa->disprect.xmin;
1631                 zspan.zofsy= -pa->disprect.ymin;
1632         }
1633         
1634         /* the buffers */
1635         zspan.rectz= pa->rectz;
1636         zspan.rectp= pa->rectp;
1637         fillrect(pa->rectp, pa->rectx, pa->recty, 0);
1638         fillrect(pa->rectz, pa->rectx, pa->recty, 0x7FFFFFFF);
1639         
1640         /* filling methods */
1641         zspan.zbuffunc= zbufinvulGL4;
1642         zspan.zbuflinefunc= zbufline;
1643
1644         /* part clipflag, threaded */
1645         clipmask= (15 << 4*(pa->thread & 3));
1646
1647         for(v=0; v<R.totvlak; v++) {
1648
1649                 if((v & 255)==0) vlr= R.blovl[v>>8];
1650                 else vlr++;
1651                 
1652                 if((vlr->flag & R_VISIBLE) && (vlr->lay & lay)) {
1653                         if(vlr->mat!=ma) {
1654                                 ma= vlr->mat;
1655                                 nofill= ma->mode & (MA_ZTRA|MA_ONLYCAST);
1656                                 env= (ma->mode & MA_ENV);
1657                                 wire= (ma->mode & MA_WIRE);
1658                                 
1659                                 if(ma->mode & MA_ZINV) zspan.zbuffunc= zbufinvulGLinv4;
1660                                 else zspan.zbuffunc= zbufinvulGL4;
1661                         }
1662                         
1663                         if(nofill==0) {
1664                                 unsigned short partclip;
1665                                 
1666                                 /* partclipping doesn't need viewplane clipping */
1667                                 if(vlr->v4) partclip= vlr->v1->flag & vlr->v2->flag & vlr->v3->flag & vlr->v4->flag;
1668                                 else partclip= vlr->v1->flag & vlr->v2->flag & vlr->v3->flag;
1669                                 
1670                                 if((partclip & clipmask)==0) {
1671                                         
1672                                         if(env) zvlnr= 0;
1673                                         else zvlnr= v+1;
1674                                         
1675                                         if(wire) zbufclipwire(&zspan, zvlnr, vlr);
1676                                         else {
1677                                                 /* strands allow to be filled in as quad */
1678                                                 if(vlr->v4 && (vlr->flag & R_STRAND)) {
1679                                                         zbufclip4(&zspan, zvlnr, vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip, vlr->v4->clip);
1680                                                 }
1681                                                 else {
1682                                                         zbufclip(&zspan, zvlnr, vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip);
1683                                                         if(vlr->v4) {
1684                                                                 if(zvlnr) zvlnr+= RE_QUAD_OFFS;
1685                                                                 zbufclip(&zspan, zvlnr, vlr->v1->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v3->clip, vlr->v4->clip);
1686                                                         }
1687                                                 }
1688                                         }
1689                                 }
1690                         }
1691                 }
1692         }
1693         
1694         zbuf_free_span(&zspan);
1695 }
1696
1697 typedef struct {
1698         float *vert;
1699         float hoco[4];
1700         int clip;
1701 } VertBucket;
1702
1703 /* warning, not threaded! */
1704 static int hashlist_projectvert(float *v1, float winmat[][4], float *hoco)
1705 {
1706         static VertBucket bucket[256], *buck;
1707         
1708         /* init static bucket */
1709         if(v1==NULL) {
1710                 memset(bucket, 0, 256*sizeof(VertBucket));
1711                 return 0;
1712         }
1713         
1714         buck= &bucket[ (((long)v1)/16) & 255 ];
1715         if(buck->vert==v1) {
1716                 QUATCOPY(hoco, buck->hoco);
1717                 return buck->clip;
1718         }
1719         
1720         projectvert(v1, winmat, hoco);
1721         buck->clip = testclip(hoco);
1722         buck->vert= v1;
1723         QUATCOPY(buck->hoco, hoco);
1724         return buck->clip;
1725 }
1726
1727 /* used for booth radio 'tool' as during render */
1728 void RE_zbufferall_radio(struct RadView *vw, RNode **rg_elem, int rg_totelem, Render *re)
1729 {
1730         ZSpan zspan;
1731         float hoco[4][4], winmat[4][4];
1732         int a, zvlnr;
1733         int c1, c2, c3, c4= 0;
1734
1735         if(rg_totelem==0) return;
1736
1737         hashlist_projectvert(NULL, winmat, NULL);
1738         
1739         /* needed for projectvert */
1740         MTC_Mat4MulMat4(winmat, vw->viewmat, vw->winmat);
1741
1742         zbuf_alloc_span(&zspan, vw->rectx, vw->recty);
1743         zspan.zmulx=  ((float)vw->rectx)/2.0;
1744         zspan.zmuly=  ((float)vw->recty)/2.0;
1745         zspan.zofsx= 0;
1746         zspan.zofsy= 0;
1747         
1748         /* the buffers */
1749         zspan.rectz= vw->rectz;
1750         zspan.rectp= vw->rect;
1751         fillrect(zspan.rectz, vw->rectx, vw->recty, 0x7FFFFFFF);
1752         fillrect(zspan.rectp, vw->rectx, vw->recty, 0xFFFFFF);
1753         
1754         /* filling methods */
1755         zspan.zbuffunc= zbufinvulGL4;
1756         
1757         if(rg_elem) {   /* radio tool */
1758                 RNode **re, *rn;
1759
1760                 re= rg_elem;
1761                 re+= (rg_totelem-1);
1762                 for(a= rg_totelem-1; a>=0; a--, re--) {
1763                         rn= *re;
1764                         if( (rn->f & RAD_SHOOT)==0 ) {    /* no shootelement */
1765                                 
1766                                 if( rn->f & RAD_TWOSIDED) zvlnr= a;
1767                                 else if( rn->f & RAD_BACKFACE) zvlnr= 0xFFFFFF; 
1768                                 else zvlnr= a;
1769                                 
1770                                 c1= hashlist_projectvert(rn->v1, winmat, hoco[0]);
1771                                 c2= hashlist_projectvert(rn->v2, winmat, hoco[1]);
1772                                 c3= hashlist_projectvert(rn->v3, winmat, hoco[2]);
1773                                 
1774                                 if(rn->v4) {
1775                                         c4= hashlist_projectvert(rn->v4, winmat, hoco[3]);
1776                                 }
1777         
1778                                 if(rn->v4)
1779                                         zbufclip4(&zspan, zvlnr, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4);
1780                                 else
1781                                         zbufclip(&zspan, zvlnr, hoco[0], hoco[1], hoco[2], c1, c2, c3);
1782                         }
1783                 }
1784         }
1785         else {  /* radio render */
1786                 VlakRen *vlr=NULL;
1787                 RadFace *rf;
1788                 int totface=0;
1789                 
1790                 for(a=0; a<re->totvlak; a++) {
1791                         if((a & 255)==0) vlr= re->blovl[a>>8]; else vlr++;
1792                 
1793                         if(vlr->radface) {
1794                                 rf= vlr->radface;
1795                                 if( (rf->flag & RAD_SHOOT)==0 ) {    /* no shootelement */
1796                                         
1797                                         if( rf->flag & RAD_TWOSIDED) zvlnr= totface;
1798                                         else if( rf->flag & RAD_BACKFACE) zvlnr= 0xFFFFFF;      /* receives no energy, but is zbuffered */
1799                                         else zvlnr= totface;
1800                                         
1801                                         c1= hashlist_projectvert(vlr->v1->co, winmat, hoco[0]);
1802                                         c2= hashlist_projectvert(vlr->v2->co, winmat, hoco[1]);
1803                                         c3= hashlist_projectvert(vlr->v3->co, winmat, hoco[2]);
1804                                         
1805                                         if(vlr->v4) {
1806                                                 c4= hashlist_projectvert(vlr->v4->co, winmat, hoco[3]);
1807                                         }
1808                 
1809                                         if(vlr->v4)
1810                                                 zbufclip4(&zspan, zvlnr, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4);
1811                                         else
1812                                                 zbufclip(&zspan, zvlnr, hoco[0], hoco[1], hoco[2], c1, c2, c3);
1813                                 }
1814                                 totface++;
1815                         }
1816                 }
1817         }
1818
1819         zbuf_free_span(&zspan);
1820 }
1821
1822 void zbuffer_shadow(Render *re, LampRen *lar, int *rectz, int size, float jitx, float jity)
1823 {
1824         ZSpan zspan;
1825         VlakRen *vlr= NULL;
1826         Material *ma=0;
1827         int a, ok=1, lay= -1;
1828
1829         if(lar->mode & LA_LAYER) lay= lar->lay;
1830
1831         zbuf_alloc_span(&zspan, size, size);
1832         zspan.zmulx=  ((float)size)/2.0;
1833         zspan.zmuly=  ((float)size)/2.0;
1834         zspan.zofsx= jitx;
1835         zspan.zofsy= jity;
1836         
1837         /* the buffers */
1838         zspan.rectz= rectz;
1839         fillrect(rectz, size, size, 0x7FFFFFFE);
1840         
1841         /* filling methods */
1842         zspan.zbuflinefunc= zbufline_onlyZ;
1843         zspan.zbuffunc= zbufinvulGL_onlyZ;
1844                                 
1845         for(a=0; a<re->totvlak; a++) {
1846
1847                 if((a & 255)==0) vlr= re->blovl[a>>8];
1848                 else vlr++;
1849
1850                 if(vlr->mat!= ma) {
1851                         ma= vlr->mat;
1852                         ok= 1;
1853                         if((ma->mode & MA_SHADBUF)==0) ok= 0;
1854                 }
1855                 
1856                 if(ok && (vlr->flag & R_VISIBLE) && (vlr->lay & lay)) {
1857                         if(ma->mode & MA_WIRE) zbufclipwire(&zspan, a+1, vlr);
1858                         else if(vlr->flag & R_STRAND) zbufclipwire(&zspan, a+1, vlr);
1859                         else {
1860                                 if(vlr->v4) 
1861                                         zbufclip4(&zspan, 0, vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip, vlr->v4->clip);
1862                                 else
1863                                         zbufclip(&zspan, 0, vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip);
1864                         }
1865                 }
1866         }
1867         zbuf_free_span(&zspan);
1868 }
1869
1870 /* ******************** VECBLUR ACCUM BUF ************************* */
1871
1872 typedef struct DrawBufPixel {
1873         float *colpoin;
1874         float alpha;
1875 } DrawBufPixel;
1876
1877
1878 static void zbuf_fill_in_rgba(ZSpan *zspan, DrawBufPixel *col, float *v1, float *v2, float *v3, float *v4)
1879 {
1880         DrawBufPixel *rectpofs, *rp;
1881         double zxd, zyd, zy0, zverg;
1882         float x0,y0,z0;
1883         float x1,y1,z1,x2,y2,z2,xx1;
1884         float *span1, *span2;
1885         float *rectzofs, *rz;
1886         int x, y;
1887         int sn1, sn2, rectx, my0, my2;
1888         
1889         /* init */
1890         zbuf_init_span(zspan);
1891         
1892         /* set spans */
1893         zbuf_add_to_span(zspan, v1, v2);
1894         zbuf_add_to_span(zspan, v2, v3);
1895         zbuf_add_to_span(zspan, v3, v4);
1896         zbuf_add_to_span(zspan, v4, v1);
1897         
1898         /* clipped */
1899         if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
1900         
1901         if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
1902         if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
1903         
1904         //      printf("my %d %d\n", my0, my2);
1905         if(my2<my0) return;
1906         
1907         /* ZBUF DX DY, in floats still */
1908         x1= v1[0]- v2[0];
1909         x2= v2[0]- v3[0];
1910         y1= v1[1]- v2[1];
1911         y2= v2[1]- v3[1];
1912         z1= v1[2]- v2[2];
1913         z2= v2[2]- v3[2];
1914         x0= y1*z2-z1*y2;
1915         y0= z1*x2-x1*z2;
1916         z0= x1*y2-y1*x2;
1917         
1918         if(z0==0.0) return;
1919         
1920         xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
1921         
1922         zxd= -(double)x0/(double)z0;
1923         zyd= -(double)y0/(double)z0;
1924         zy0= ((double)my2)*zyd + (double)xx1;
1925         
1926         /* start-offset in rect */
1927         rectx= zspan->rectx;
1928         rectzofs= (float *)(zspan->rectz + rectx*my2);
1929         rectpofs= ((DrawBufPixel *)zspan->rectp) + rectx*my2;
1930         
1931         /* correct span */
1932         sn1= (my0 + my2)/2;
1933         if(zspan->span1[sn1] < zspan->span2[sn1]) {
1934                 span1= zspan->span1+my2;
1935                 span2= zspan->span2+my2;
1936         }
1937         else {
1938                 span1= zspan->span2+my2;
1939                 span2= zspan->span1+my2;
1940         }
1941         
1942         for(y=my2; y>=my0; y--, span1--, span2--) {
1943                 
1944                 sn1= floor(*span1);
1945                 sn2= floor(*span2);
1946                 sn1++; 
1947                 
1948                 if(sn2>=rectx) sn2= rectx-1;
1949                 if(sn1<0) sn1= 0;
1950                 
1951                 if(sn2>=sn1) {
1952                         zverg= (double)sn1*zxd + zy0;
1953                         rz= rectzofs+sn1;
1954                         rp= rectpofs+sn1;
1955                         x= sn2-sn1;
1956                         
1957                         while(x>=0) {
1958                                 if( zverg < *rz) {
1959                                         *rz= zverg;
1960                                         *rp= *col;
1961                                 }
1962                                 zverg+= zxd;
1963                                 rz++; 
1964                                 rp++; 
1965                                 x--;
1966                         }
1967                 }
1968                 
1969                 zy0-=zyd;
1970                 rectzofs-= rectx;
1971                 rectpofs-= rectx;
1972         }
1973 }
1974
1975 static void antialias_tagbuf(int xsize, int ysize, char *rectmove)
1976 {
1977         char *row1, *row2, *row3;
1978         char prev, next;
1979         int a, x, y, step;
1980         
1981         /* 1: tag pixels to be candidate for AA */
1982         for(y=2; y<ysize; y++) {
1983                 /* setup rows */
1984                 row1= rectmove + (y-2)*xsize;
1985                 row2= row1 + xsize;
1986                 row3= row2 + xsize;
1987                 for(x=2; x<xsize; x++, row1++, row2++, row3++) {
1988                         if(row2[1]) {
1989                                 if(row2[0]==0 || row2[2]==0 || row1[1]==0 || row3[1]==0)
1990                                         row2[1]= 128;
1991                         }
1992                 }
1993         }
1994         /* 2: evaluate horizontal scanlines and calculate alphas */
1995         row1= rectmove;
1996         for(y=0; y<ysize; y++) {
1997                 row1++;
1998                 for(x=1; x<xsize; x++, row1++) {
1999                         if(row1[0]==128 && row1[1]==128) {
2000                                 /* find previous color and next color and amount of steps to blend */
2001                                 prev= row1[-1];
2002                                 step= 1;
2003                                 while(x+step<xsize && row1[step]==128)
2004                                         step++;
2005                                 
2006                                 if(x+step!=xsize) {
2007                                         /* now we can blend values */
2008                                         next= row1[step];
2009                                         if(prev!=next) {
2010                                                 for(a=0; a<step; a++) {
2011                                                         int fac, mfac;
2012                                                         
2013                                                         fac= ((a+1)<<8)/(step+1);
2014                                                         mfac= 255-fac;
2015                                                         
2016                                                         row1[a]= (prev*mfac + next*fac)>>8; 
2017                                                 }
2018                                         }
2019                                 }
2020                         }
2021                 }
2022         }
2023         /* 2: evaluate vertical scanlines and calculate alphas */
2024         for(x=0; x<xsize; x++) {
2025                 row1= rectmove + x+xsize;
2026                 
2027                 for(y=1; y<ysize; y++, row1+=xsize) {
2028                         if(row1[0]==128 && row1[xsize]==128) {
2029                                 /* find previous color and next color and amount of steps to blend */
2030                                 prev= row1[-xsize];
2031                                 step= 1;
2032                                 while(y+step<ysize && row1[step*xsize]==128)
2033                                         step++;
2034                                 
2035                                 if(y+step!=ysize) {
2036                                         /* now we can blend values */
2037                                         next= row1[step*xsize];
2038                                         if(prev!=next) {
2039                                                 for(a=0; a<step; a++) {
2040                                                         int fac, mfac;
2041                                                         
2042                                                         fac= ((a+1)<<8)/(step+1);
2043                                                         mfac= 255-fac;
2044                                                         
2045                                                         row1[a*xsize]= (prev*mfac + next*fac)>>8; 
2046                                                 }
2047                                         }
2048                                 }
2049                         }
2050                 }
2051         }
2052         
2053         
2054         /* last: pixels with 0 we fill in zbuffer, with 1 we skip for mask */
2055         for(y=2; y<ysize; y++) {
2056                 /* setup rows */
2057                 row1= rectmove + (y-2)*xsize;
2058                 row2= row1 + xsize;
2059                 row3= row2 + xsize;
2060                 for(x=2; x<xsize; x++, row1++, row2++, row3++) {
2061                         if(row2[1]==0) {
2062                                 if(row2[0]>1 || row2[2]>1 || row1[1]>1 || row3[1]>1)
2063                                         row2[1]= 1;
2064                         }
2065                 }
2066         }
2067 }
2068
2069 void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float *newrect, float *imgrect, float *vecbufrect, float *zbufrect)
2070 {
2071         ZSpan zspan;
2072         DrawBufPixel *rectdraw, *dr;
2073         float jit[16][2];
2074         float v1[3], v2[3], v3[3], v4[3], fx, fy;
2075         float *rectvz, *dvz, *dimg, *dvec1, *dvec2, *dz1, *dz2, *rectz, *minvecbufrect= NULL;
2076         float maxspeedsq= (float)nbd->maxspeed*nbd->maxspeed;
2077         int y, x, step, maxspeed=nbd->maxspeed, samples= nbd->samples;
2078         char *rectmove, *dm;
2079         
2080         zbuf_alloc_span(&zspan, xsize, ysize);
2081         zspan.zmulx=  ((float)xsize)/2.0;
2082         zspan.zmuly=  ((float)ysize)/2.0;
2083         zspan.zofsx= 0.0f;
2084         zspan.zofsy= 0.0f;
2085         
2086         /* the buffers */
2087         rectz= MEM_mapallocT(sizeof(float)*xsize*ysize, "zbuf accum");
2088         zspan.rectz= (int *)rectz;
2089         
2090         rectmove= MEM_mapallocT(xsize*ysize, "rectmove");
2091         rectdraw= MEM_mapallocT(sizeof(DrawBufPixel)*xsize*ysize, "rect draw");
2092         zspan.rectp= (int *)rectdraw;
2093         
2094         /* min speed? then copy speedbuffer to recalculate speed vectors */
2095         if(nbd->minspeed) {
2096                 float minspeed= (float)nbd->minspeed;
2097                 float minspeedsq= minspeed*minspeed;
2098                 
2099                 minvecbufrect= MEM_mapallocT(4*sizeof(float)*xsize*ysize, "minspeed buf");
2100                 
2101                 dvec1= vecbufrect;
2102                 dvec2= minvecbufrect;
2103                 for(x= 2*xsize*ysize; x>0; x--, dvec1+=2, dvec2+=2) {
2104                         if(dvec1[0]==0.0f && dvec1[1]==0.0f) {
2105                                 dvec2[0]= dvec1[0];
2106                                 dvec2[1]= dvec1[1];
2107                         }
2108                         else {
2109                                 float speedsq= dvec1[0]*dvec1[0] + dvec1[1]*dvec1[1];
2110                                 if(speedsq <= minspeedsq) {
2111                                         dvec2[0]= 0.0f;
2112                                         dvec2[1]= 0.0f;
2113                                 }
2114                                 else {
2115                                         speedsq= 1.0f - minspeed/sqrt(speedsq);
2116                                         dvec2[0]= speedsq*dvec1[0];
2117                                         dvec2[1]= speedsq*dvec1[1];
2118                                 }
2119                         }
2120                 }
2121                 SWAP(float *, minvecbufrect, vecbufrect);
2122         }
2123         
2124         /* make vertex buffer with averaged speed and zvalues */
2125         rectvz= MEM_mapallocT(5*sizeof(float)*(xsize+1)*(ysize+1), "vertices");
2126         dvz= rectvz;
2127         for(y=0; y<=ysize; y++) {
2128                 
2129                 if(y==0) {
2130                         dvec1= vecbufrect + 4*y*xsize;
2131                         dz1= zbufrect + y*xsize;
2132                 }
2133                 else {
2134                         dvec1= vecbufrect + 4*(y-1)*xsize;
2135                         dz1= zbufrect + (y-1)*xsize;
2136                 }
2137                 
2138                 if(y==ysize) {
2139                         dvec2= vecbufrect + 4*(y-1)*xsize;
2140                         dz2= zbufrect + (y-1)*xsize;
2141                 }
2142                 else {
2143                         dvec2= vecbufrect + 4*y*xsize;
2144                         dz2= zbufrect + y*xsize;
2145                 }
2146                 
2147                 for(x=0; x<=xsize; x++, dz1++, dz2++) {
2148                         
2149                         /* two vectors, so a step loop */
2150                         for(step=0; step<2; step++, dvec1+=2, dvec2+=2, dvz+=2) {
2151                                 /* average on minimal speed */
2152                                 int div= 0;
2153                                 
2154                                 if(x!=0) {
2155                                         if(dvec1[-4]!=0.0f || dvec1[-3]!=0.0f) {
2156                                                 dvz[0]= dvec1[-4];
2157                                                 dvz[1]= dvec1[-3];
2158                                                 div++;
2159                                         }
2160                                         if(dvec2[-4]!=0.0f || dvec2[-3]!=0.0f) {
2161                                                 if(div==0) {
2162                                                         dvz[0]= dvec2[-4];
2163                                                         dvz[1]= dvec2[-3];
2164                                                         div++;
2165                                                 }
2166                                                 else if( (ABS(dvec2[-4]) + ABS(dvec2[-3]))< (ABS(dvz[0]) + ABS(dvz[1])) ) {
2167                                                         dvz[0]= dvec2[-4];
2168                                                         dvz[1]= dvec2[-3];
2169                                                 }
2170                                         }
2171                                 }
2172
2173                                 if(x!=xsize) {
2174                                         if(dvec1[0]!=0.0f || dvec1[1]!=0.0f) {
2175                                                 if(div==0) {
2176                                                         dvz[0]= dvec1[0];
2177                                                         dvz[1]= dvec1[1];
2178                                                         div++;
2179                                                 }
2180                                                 else if( (ABS(dvec1[0]) + ABS(dvec1[1]))< (ABS(dvz[0]) + ABS(dvz[1])) ) {
2181                                                         dvz[0]= dvec1[0];
2182                                                         dvz[1]= dvec1[1];
2183                                                 }
2184                                         }
2185                                         if(dvec2[0]!=0.0f || dvec2[1]!=0.0f) {
2186                                                 if(div==0) {
2187                                                         dvz[0]= dvec2[0];
2188                                                         dvz[1]= dvec2[1];
2189                                                 }
2190                                                 else if( (ABS(dvec2[0]) + ABS(dvec2[1]))< (ABS(dvz[0]) + ABS(dvz[1])) ) {
2191                                                         dvz[0]= dvec2[0];
2192                                                         dvz[1]= dvec2[1];
2193                                                 }
2194                                         }
2195                                 }
2196                                 if(maxspeed) {
2197                                         float speedsq= dvz[0]*dvz[0] + dvz[1]*dvz[1];
2198                                         if(speedsq > maxspeedsq) {
2199                                                 speedsq= (float)maxspeed/sqrt(speedsq);
2200                                                 dvz[0]*= speedsq;
2201                                                 dvz[1]*= speedsq;
2202                                         }
2203                                 }
2204                         }
2205                         /* the z coordinate */
2206                         if(x!=0) {
2207                                 if(x!=xsize)
2208                                         dvz[0]= 0.25f*(dz1[-1] + dz2[-1] + dz1[0] + dz2[0]);
2209                                 else dvz[0]= 0.5f*(dz1[0] + dz2[0]);
2210                         }
2211                         else dvz[0]= 0.5f*(dz1[-1] + dz2[-1]);
2212                         
2213                         dvz++;
2214                 }
2215         }
2216         
2217         /* set border speeds to keep border speeds on border */
2218         dz1= rectvz;
2219         dz2= rectvz+5*(ysize)*(xsize+1);
2220         for(x=0; x<=xsize; x++, dz1+=5, dz2+=5) {
2221                 dz1[1]= 0.0f;
2222                 dz2[1]= 0.0f;
2223                 dz1[3]= 0.0f;
2224                 dz2[3]= 0.0f;
2225         }
2226         dz1= rectvz;
2227         dz2= rectvz+5*(xsize);
2228         for(y=0; y<=ysize; y++, dz1+=5*(xsize+1), dz2+=5*(xsize+1)) {
2229                 dz1[0]= 0.0f;
2230                 dz2[0]= 0.0f;
2231                 dz1[2]= 0.0f;
2232                 dz2[2]= 0.0f;
2233         }
2234         
2235         /* tag moving pixels, only these faces we draw */
2236         dm= rectmove;
2237         dvec1= vecbufrect;
2238         for(x=xsize*ysize; x>0; x--, dm++, dvec1+=4) {
2239                 if(dvec1[0]!=0.0f || dvec1[1]!=0.0f)
2240                         *dm= 255;
2241         }
2242         
2243         antialias_tagbuf(xsize, ysize, rectmove);
2244         
2245         BLI_initjit(jit[0], 16);
2246         
2247         
2248         /* accumulate */
2249         samples/= 2;
2250         for(step= 1; step<=samples; step++) {
2251                 float speedfac= 0.5f*nbd->fac*(float)step/(float)(samples+1);
2252                 float blendfac= 1.0f/(ABS(step)+1);
2253                 int side, z= 4;
2254                 
2255                 for(side=0; side<2; side++) {
2256                         
2257                         /* clear zbuf, if we draw future we fill in not moving pixels */
2258                         if(0)
2259                                 for(x= xsize*ysize-1; x>=0; x--) rectz[x]= 10e16;
2260                         else 
2261                                 for(x= xsize*ysize-1; x>=0; x--) {
2262                                         if(rectmove[x]==0)
2263                                                 rectz[x]= zbufrect[x];
2264                                         else
2265                                                 rectz[x]= 10e16;
2266                                 }
2267                         
2268                         /* clear drawing buffer */
2269                         for(x= xsize*ysize-1; x>=0; x--) rectdraw[x].colpoin= NULL;
2270                         
2271                         dimg= imgrect;
2272                         dm= rectmove;
2273                         dz1= rectvz;
2274                         dz2= rectvz + 5*(xsize + 1);
2275                         
2276                         if(side) {
2277                                 dz1+= 2;
2278                                 dz2+= 2;
2279                                 z= 2;
2280                                 speedfac= -speedfac;
2281                         }
2282
2283                         for(fy= -0.5f+jit[step & 15][0], y=0; y<ysize; y++, fy+=1.0f) {
2284                                 for(fx= -0.5f+jit[step & 15][1], x=0; x<xsize; x++, fx+=1.0f, dimg+=4, dz1+=5, dz2+=5, dm++) {
2285                                         if(*dm>1) {
2286                                                 DrawBufPixel col;
2287                                                 
2288                                                 /* make vertices */
2289                                                 v1[0]= speedfac*dz1[0]+fx;                      v1[1]= speedfac*dz1[1]+fy;                      v1[2]= dz1[z];
2290                                                 v2[0]= speedfac*dz1[5]+fx+1.0f;         v2[1]= speedfac*dz1[6]+fy;                      v2[2]= dz1[z+5];
2291                                                 v3[0]= speedfac*dz2[5]+fx+1.0f;         v3[1]= speedfac*dz2[6]+fy+1.0f;         v3[2]= dz2[z+5];
2292                                                 v4[0]= speedfac*dz2[0]+fx;                      v4[1]= speedfac*dz2[1]+fy+1.0f;         v4[2]= dz2[z];
2293                                                 
2294                                                 if(*dm==255) col.alpha= 1.0f;
2295                                                 else if(*dm<2) col.alpha= 0.0f;
2296                                                 else col.alpha= ((float)*dm)/255.0f;
2297                                                 col.colpoin= dimg;
2298                                                 
2299                                                 zbuf_fill_in_rgba(&zspan, &col, v1, v2, v3, v4);
2300                                         }
2301                                 }
2302                                 dz1+=5;
2303                                 dz2+=5;
2304                         }
2305                         
2306                         /* accum */
2307                         for(dr= rectdraw, dz2=newrect, x= xsize*ysize-1; x>=0; x--, dr++, dz2+=4) {
2308                                 if(dr->colpoin) {
2309                                         float bfac= dr->alpha*blendfac;
2310                                         float mf= 1.0f - bfac;
2311                                         
2312                                         dz2[0]= mf*dz2[0] + bfac*dr->colpoin[0];
2313                                         dz2[1]= mf*dz2[1] + bfac*dr->colpoin[1];
2314                                         dz2[2]= mf*dz2[2] + bfac*dr->colpoin[2];
2315                                         dz2[3]= mf*dz2[3] + bfac*dr->colpoin[3];
2316                                 }
2317                         }
2318                 }
2319         }
2320         
2321         MEM_freeT(rectz);
2322         MEM_freeT(rectmove);
2323         MEM_freeT(rectdraw);
2324         MEM_freeT(rectvz);
2325         if(minvecbufrect) MEM_freeT(vecbufrect);  /* rects were swapped! */
2326         zbuf_free_span(&zspan);
2327 }
2328
2329 /* ******************** ABUF ************************* */
2330
2331 /**
2332  * Copy results from the solid face z buffering to the transparent
2333  * buffer.
2334  */
2335 static void copyto_abufz(RenderPart *pa, int *arectz, int sample)
2336 {
2337         PixStr *ps;
2338         int x, y, *rza;
2339         long *rd;
2340         
2341         /* now, in OSA the pixstructs contain all faces filled in */
2342         if(R.osa) fillrect(arectz, pa->rectx, pa->recty, 0x7FFFFFFF);
2343         else {
2344                 memcpy(arectz, pa->rectz, 4*pa->rectx*pa->recty);
2345                 return;
2346         }
2347                 
2348         rza= arectz;
2349         rd= pa->rectdaps;
2350
2351         sample= (1<<sample);
2352         
2353         for(y=0; y<pa->recty; y++) {
2354                 for(x=0; x<pa->rectx; x++) {
2355                         
2356                         if(*rd) {       
2357                                 ps= (PixStr *)(*rd);
2358
2359                                 while(ps) {
2360                                         if(sample & ps->mask) {
2361                                                 //printf("filled xy %d %d mask %d\n", x, y, sample);
2362                                                 *rza= ps->z;
2363                                                 break;
2364                                         }
2365                                         ps= ps->next;
2366                                 }
2367                         }
2368                         
2369                         rd++; rza++;
2370                 }
2371         }
2372 }
2373
2374
2375 /* ------------------------------------------------------------------------ */
2376
2377 /**
2378  * Do accumulation z buffering.
2379  */
2380
2381 static void zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, unsigned int lay)
2382 {
2383         ZSpan zspan;
2384         Material *ma=NULL;
2385         VlakRen *vlr=NULL;
2386         float vec[3], hoco[4], mul, zval, fval;
2387         int v, zvlnr, zsample, dofill= 0;
2388         unsigned short clipmask;
2389         
2390         zbuf_alloc_span(&zspan, pa->rectx, pa->recty);
2391         
2392         /* needed for transform from hoco to zbuffer co */
2393         zspan.zmulx=  ((float)R.winx)/2.0;
2394         zspan.zmuly=  ((float)R.winy)/2.0;
2395         zspan.zofsx= -pa->disprect.xmin;
2396         zspan.zofsy= -pa->disprect.ymin;
2397         
2398         /* the buffers */
2399         zspan.arectz= MEM_mallocT(sizeof(int)*pa->rectx*pa->recty, "Arectz");
2400         zspan.apixbuf= APixbuf;
2401         zspan.apsmbase= apsmbase;
2402         
2403         /* filling methods */
2404         zspan.zbuffunc= zbufinvulAc4;
2405         zspan.zbuflinefunc= zbuflineAc;
2406         
2407         /* part clipflag, 4 threads */
2408         clipmask= (15 << 4*(pa->thread & 3));
2409         
2410         for(zsample=0; zsample<R.osa || R.osa==0; zsample++) {
2411                 
2412                 copyto_abufz(pa, zspan.arectz, zsample);        /* init zbuffer */
2413                 zspan.mask= 1<<zsample;
2414                 
2415                 if(R.osa) {
2416                         zspan.zofsx= -pa->disprect.xmin-R.jit[zsample][0];
2417                         zspan.zofsy= -pa->disprect.ymin-R.jit[zsample][1];
2418                 }
2419                 
2420                 for(v=0; v<R.totvlak; v++) {
2421                         if((v & 255)==0)
2422                                 vlr= R.blovl[v>>8];
2423                         else vlr++;
2424                         
2425                         if(vlr->mat!=ma) {
2426                                 ma= vlr->mat;
2427                                 dofill= (ma->mode & MA_ZTRA) && !(ma->mode & MA_ONLYCAST);
2428                         }
2429                         
2430                         if(dofill) {
2431                                 if((vlr->flag & R_VISIBLE) && (vlr->lay & lay)) {
2432                                         unsigned short partclip;
2433                                         
2434                                         /* partclipping doesn't need viewplane clipping */
2435                                         if(vlr->v4) partclip= vlr->v1->flag & vlr->v2->flag & vlr->v3->flag & vlr->v4->flag;
2436                                         else partclip= vlr->v1->flag & vlr->v2->flag & vlr->v3->flag;
2437                                         
2438                                         if((partclip & clipmask)==0) {
2439                                                 /* a little advantage for transp rendering (a z offset) */
2440                                                 if( ma->zoffs != 0.0) {
2441                                                         mul= 0x7FFFFFFF;
2442                                                         zval= mul*(1.0+vlr->v1->ho[2]/vlr->v1->ho[3]);
2443
2444                                                         VECCOPY(vec, vlr->v1->co);
2445                                                         /* z is negative, otherwise its being clipped */ 
2446                                                         vec[2]-= ma->zoffs;
2447                                                         projectverto(vec, R.winmat, hoco);
2448                                                         fval= mul*(1.0+hoco[2]/hoco[3]);
2449
2450                                                         zspan.polygon_offset= (int) fabs(zval - fval );
2451                                                 }
2452                                                 else zspan.polygon_offset= 0;
2453                                                 
2454                                                 zvlnr= v+1;
2455                         
2456                                                 if(ma->mode & (MA_WIRE)) zbufclipwire(&zspan, zvlnr, vlr);
2457                                                 else {
2458                                                         if(vlr->v4 && (vlr->flag & R_STRAND)) {
2459                                                                 zbufclip4(&zspan, zvlnr, vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip, vlr->v4->clip);
2460                                                         }
2461                                                         else {
2462                                                                 zbufclip(&zspan, zvlnr, vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip);
2463                                                                 if(vlr->v4) {
2464                                                                         zvlnr+= RE_QUAD_OFFS;
2465                                                                         zbufclip(&zspan, zvlnr, vlr->v1->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v3->clip, vlr->v4->clip);
2466                                                                 }
2467                                                         }
2468                                                 }
2469                                         }
2470                                 }
2471                                 if( (v & 255)==255) 
2472                                         if(R.test_break()) 
2473                                                 break; 
2474                         }
2475                 }
2476                 
2477                 if(R.osa==0) break;
2478                 if(R.test_break()) break;
2479         }
2480         
2481         MEM_freeT(zspan.arectz);
2482         zbuf_free_span(&zspan);
2483
2484 }
2485
2486 /* different rules for speed in transparent pass...  */
2487 /* if speed is zero or alpha small, we clear winspeed if it's initialized to max still */
2488
2489 static void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha)
2490 {
2491         RenderPass *rpass;
2492         
2493         for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
2494                 if(rpass->passtype==SCE_PASS_VECTOR) {
2495                         float *fp= rpass->rect + 4*offset;
2496                         
2497                         if(speed && alpha>0.95f) {
2498                                 QUATCOPY(fp, speed);
2499                         }
2500                         else {
2501                                 /* clear */
2502                                 if(fp[0]==PASS_VECTOR_MAX) fp[0]= 0.0f;
2503                                 if(fp[1]==PASS_VECTOR_MAX) fp[1]= 0.0f;
2504                                 if(fp[2]==PASS_VECTOR_MAX) fp[2]= 0.0f;
2505                                 if(fp[3]==PASS_VECTOR_MAX) fp[3]= 0.0f;
2506                         }
2507                 }
2508         }
2509 }
2510
2511 static void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float weight)
2512 {
2513         RenderPass *rpass;
2514         
2515         for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
2516                 float *fp, *col= NULL;
2517                 int a, pixsize= 3;
2518                 
2519                 switch(rpass->passtype) {
2520                         case SCE_PASS_RGBA:
2521                                 if(shr) col= shr->col;
2522                                 pixsize= 4;
2523                                 break;
2524                         case SCE_PASS_DIFFUSE:
2525                                 if(shr) col= shr->diff;
2526                                 break;
2527                         case SCE_PASS_SPEC:
2528                                 if(shr) col= shr->spec;
2529                                 break;
2530                         case SCE_PASS_SHADOW:
2531                                 if(shr) col= shr->shad;
2532                                 break;
2533                         case SCE_PASS_AO:
2534                                 if(shr) col= shr->ao;
2535                                 break;
2536                         case SCE_PASS_RAY:
2537                                 if(shr) col= shr->ray;
2538                                 break;
2539                         case SCE_PASS_NORMAL:
2540                                 if(shr) col= shr->nor;
2541                                 break;
2542                 }
2543                 if(col) {
2544                         fp= rpass->rect + pixsize*offset;
2545                         for(a=0; a<pixsize; a++)
2546                                 fp[a]+= weight*col[a];
2547                 }
2548         }
2549 }
2550
2551
2552 static int vergzvlak(const void *a1, const void *a2)
2553 {
2554         const int *x1=a1, *x2=a2;
2555
2556         if( x1[0] < x2[0] ) return 1;
2557         else if( x1[0] > x2[0]) return -1;
2558         return 0;
2559 }
2560
2561 /**
2562 * Shade this face at this location in SCS.
2563  */
2564 static void shadetrapixel(ShadePixelInfo *shpi, float x, float y, int z, int facenr, int mask)
2565 {
2566         float rco[3];
2567         
2568         if( (facenr & RE_QUAD_MASK) > R.totvlak) {
2569                 printf("error in shadetrapixel nr: %d\n", (facenr & RE_QUAD_MASK));
2570                 return;
2571         }
2572         if(R.osa) {
2573                 VlakRen *vlr= RE_findOrAddVlak(&R, (facenr-1) & RE_QUAD_MASK);
2574                 float accumcol[4]={0,0,0,0}, tot=0.0;
2575                 int a;
2576                 
2577                 if(vlr->flag & R_FULL_OSA) {
2578                         for(a=0; a<R.osa; a++) {
2579                                 if(mask & (1<<a)) {
2580                                         shadepixel(shpi, x+R.jit[a][0], y+R.jit[a][1], z, facenr, 1<<a, rco);
2581                                         accumcol[0]+= shpi->shr.combined[0];
2582                                         accumcol[1]+= shpi->shr.combined[1];
2583                                         accumcol[2]+= shpi->shr.combined[2];
2584                                         accumcol[3]+= shpi->shr.combined[3];
2585                                         tot+= 1.0;
2586                                 }
2587                         }
2588                         tot= 1.0/tot;
2589                         shpi->shr.combined[0]= accumcol[0]*tot;
2590                         shpi->shr.combined[1]= accumcol[1]*tot;
2591                         shpi->shr.combined[2]= accumcol[2]*tot;
2592                         shpi->shr.combined[3]= accumcol[3]*tot;
2593                 }
2594                 else {
2595                         int b= R.samples->centmask[mask];
2596                         x= x+R.samples->centLut[b & 15];
2597                         y= y+R.samples->centLut[b>>4];
2598                         shadepixel(shpi, x, y, z, facenr, mask, rco);
2599                 }
2600         }
2601         else {
2602                 shadepixel(shpi, x, y, z, facenr, mask, rco);
2603         }
2604 }
2605
2606 static int addtosamp_shr(ShadeResult *samp_shr, ShadeResult *shr, int mask, int addpassflag)
2607 {
2608         int a, retval = R.osa;
2609         
2610         for(a=0; a < R.osa; a++) {
2611                 if(mask & (1<<a)) {
2612                         addAlphaUnderFloat(samp_shr->combined, shr->combined);
2613                         
2614                         if(addpassflag & SCE_PASS_VECTOR) {
2615                                 QUATCOPY(samp_shr->winspeed, shr->winspeed);
2616                         }
2617                         else if(addpassflag & SCE_PASS_NORMAL) {
2618                                 VECCOPY(samp_shr->nor, shr->nor);
2619                         }
2620                 }
2621                 
2622                 if(samp_shr->combined[3]>0.999) retval--;
2623                 samp_shr++;
2624         }
2625         return retval;
2626 }
2627
2628 #define MAX_ZROW        2000
2629 /* main render call to fill in pass the full transparent layer */
2630
2631 void zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass)
2632 {
2633         RenderResult *rr= pa->result;
2634         ShadePixelInfo shpi;
2635         APixstr *APixbuf;      /* Zbuffer: linked list of face samples */
2636         APixstr *ap, *aprect, *apn;
2637         ListBase apsmbase={NULL, NULL};
2638         ShadeResult samp_shr[16];
2639         float fac, alpha[32], *passrect= pass;
2640         int x, y, crop=0, a, zrow[MAX_ZROW][3], totface;
2641         int sval, addpassflag, offs= 0, od, addzbuf;
2642
2643         /* looks nicer for calling code */
2644         if(R.test_break())
2645                 return;
2646         
2647         APixbuf= MEM_callocT(pa->rectx*pa->recty*sizeof(APixstr), "APixbuf");
2648         
2649         if(R.osa>16) {
2650                 printf("abufsetrow: osa too large\n");
2651                 G.afbreek= 1;
2652                 return;
2653         }
2654         
2655         /* fill shadepixel info struct */
2656         shpi.thread= pa->thread;
2657         shpi.lay= rl->lay;
2658         shpi.layflag= rl->layflag;
2659         shpi.passflag= 0;
2660         
2661         if(rl->passflag & ~(SCE_PASS_Z|SCE_PASS_NORMAL|SCE_PASS_VECTOR|SCE_PASS_COMBINED))
2662                 shpi.passflag= rl->passflag;
2663         addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED);
2664         addzbuf= rl->passflag & SCE_PASS_Z;
2665         
2666         /* alpha LUT */
2667         if(R.osa) {
2668                 fac= (1.0/(float)R.osa);
2669                 for(a=0; a<=R.osa; a++) {
2670                         alpha[a]= (float)a*fac;
2671                 }
2672         }
2673         
2674         /* fill the Apixbuf */
2675         zbuffer_abuf(pa, APixbuf, &apsmbase, rl->lay);
2676         aprect= APixbuf;
2677         
2678         /* filtered render, for now we assume only 1 filter size */
2679         if(pa->crop) {
2680                 crop= 1;
2681                 passrect+= 4*(pa->rectx + 1);
2682                 aprect+= pa->rectx + 1;
2683                 offs= pa->rectx + 1;
2684         }
2685         
2686         /* init scanline updates */
2687         rr->renrect.ymin= 0;
2688         rr->renrect.ymax= -pa->crop;
2689         rr->renlay= rl;
2690                                 
2691         /* render the tile */
2692         for(y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++, rr->renrect.ymax++) {
2693                 pass= passrect;
2694                 ap= aprect;
2695                 od= offs;
2696                 
2697                 if(R.test_break())
2698                         break;
2699                 
2700                 for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, ap++, pass+=4, od++) {
2701                         
2702                         if(ap->p[0]==NULL) {
2703                                 if(addpassflag & SCE_PASS_VECTOR) 
2704                                         add_transp_speed(rl, od, NULL, 0.0f);
2705                         }
2706                         else {
2707                                 /* sort in z */
2708                                 totface= 0;
2709                                 apn= ap;
2710                                 while(apn) {
2711                                         for(a=0; a<4; a++) {
2712                                                 if(apn->p[a]) {
2713                                                         zrow[totface][0]= apn->z[a];
2714                                                         zrow[totface][1]= apn->p[a];
2715                                                         zrow[totface][2]= apn->mask[a];
2716                                                         totface++;
2717                                                         if(totface>=MAX_ZROW) totface= MAX_ZROW-1;
2718                                                 }
2719                                                 else break;
2720                                         }
2721                                         apn= apn->next;
2722                                 }
2723                                 
2724                                 if(totface==1) {
2725                                         
2726                                         shadetrapixel(&shpi, (float)x, (float)y, zrow[0][0], zrow[0][1], zrow[0][2]);
2727                                         
2728                                         if(R.osa) {
2729                                                 add_filt_fmask(zrow[0][2], shpi.shr.combined, pass, rr->rectx);
2730                                         }
2731                                         else {
2732                                                 QUATCOPY(pass, shpi.shr.combined);
2733                                         }
2734                                         
2735                                         if(addpassflag) 
2736                                                 add_transp_passes(rl, od, &shpi.shr, 1.0f);
2737                                         
2738                                         if(addpassflag & SCE_PASS_VECTOR)
2739                                                 add_transp_speed(rl, od, shpi.shr.winspeed, pass[3]);
2740                                         
2741                                         if(addzbuf)
2742                                                 if(pa->rectz[od]>zrow[0][0])
2743                                                         pa->rectz[od]= zrow[0][0];
2744                                 }
2745                                 else {
2746                                         
2747                                         if(totface==2) {
2748                                                 if(zrow[0][0] < zrow[1][0]) {
2749                                                         a= zrow[0][0]; zrow[0][0]= zrow[1][0]; zrow[1][0]= a;
2750                                                         a= zrow[0][1]; zrow[0][1]= zrow[1][1]; zrow[1][1]= a;
2751                                                         a= zrow[0][2]; zrow[0][2]= zrow[1][2]; zrow[1][2]= a;
2752                                                 }
2753                                                 
2754                                         }
2755                                         else {  /* totface>2 */
2756                                                 qsort(zrow, totface, sizeof(int)*3, vergzvlak);
2757                                         }
2758                                         
2759                                         if(addzbuf)
2760                                                 if(pa->rectz[od]>zrow[totface-1][0])
2761                                                         pa->rectz[od]= zrow[totface-1][0];
2762                                         
2763                                         if(R.osa==0) {
2764                                                 while(totface>0) {
2765                                                         totface--;
2766                                                         
2767                                                         shadetrapixel(&shpi, (float)x, (float)y, zrow[totface][0], zrow[totface][1], zrow[totface][2]);
2768                                                         addAlphaUnderFloat(pass, shpi.shr.combined);
2769                                                         if(addpassflag) 
2770                                                                 add_transp_passes(rl, od, &shpi.shr, 1.0f);
2771                                                         
2772                                                         if(pass[3]>=0.999) break;
2773                                                 }
2774                                                 if(addpassflag & SCE_PASS_VECTOR)
2775                                                         add_transp_speed(rl, od, shpi.shr.winspeed, pass[3]);
2776                                         }
2777                                         else {
2778                                                 /* for each mask-sample we alpha-under colors. then in end it's added using filter */
2779                                                 memset(samp_shr, 0, sizeof(ShadeResult)*R.osa);
2780
2781                                                 while(totface>0) {
2782                                                         totface--;
2783                                                         
2784                                                         shadetrapixel(&shpi, (float)x, (float)y, zrow[totface][0], zrow[totface][1], zrow[totface][2]);
2785                                                         sval= addtosamp_shr(samp_shr, &shpi.shr, zrow[totface][2], addpassflag);
2786                                                         
2787                                                         if(sval==0) break;
2788                                                 }
2789                                                 
2790                                                 for(a=0; a<R.osa; a++) {
2791                                                         add_filt_fmask(1<<a, samp_shr[a].combined, pass, rr->rectx);
2792                                                 
2793                                                         if(addpassflag) 
2794                                                                 add_transp_passes(rl, od, samp_shr+a, alpha[1]);
2795                                                 }
2796                                                 
2797                                                 if(addpassflag & SCE_PASS_VECTOR) {
2798                                                         fac= 0.0f;
2799                                                         for(a=0; a<R.osa; a++) 
2800                                                                 fac+= samp_shr[a].combined[3];
2801                                                         fac*= alpha[1];
2802                                                         add_transp_speed(rl, od, samp_shr[0].winspeed, fac);
2803                                                 }
2804                                         }
2805                                 }
2806                                 //if(R.osa && R.do_gamma) {
2807                                 //      pass[0]= invGammaCorrect(pass[0]);
2808                                 //      pass[1]= invGammaCorrect(pass[1]);
2809                                 //      pass[2]= invGammaCorrect(pass[2]);