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