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