a6c50ed6d5dc0827d60a1d5333899a623b7d184c
[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 "BKE_global.h"
45
46 #include "DNA_lamp_types.h"
47 #include "DNA_mesh_types.h"
48
49 #include "radio_types.h"
50 #include "radio.h"  /* needs RG, some root data for radiosity                */
51
52 #include "render.h"
53 #include "render_intern.h"
54 #include "RE_callbacks.h"
55 #include "old_zbuffer_types.h"
56 /* local includes */
57 /* can be removed when the old renderer disappears */
58 #include "rendercore.h"  /* shade_pixel and count_mask */
59 #include "pixelblending.h"
60 #include "jitter.h"
61
62 /* own includes */
63 #include "zbuf.h"
64 #include "zbuf_int.h"
65
66 #ifdef HAVE_CONFIG_H
67 #include <config.h>
68 #endif
69
70 /* crud */
71 #define MIN2(x,y)               ( (x)<(y) ? (x) : (y) )  
72 /*-----------------------------------------------------------*/ 
73 /* Globals for this file                                     */
74 /*-----------------------------------------------------------*/ 
75
76 extern float centLut[16];
77 extern char *centmask;
78
79 float *vlzp[32][3], labda[3][2], vez[400], *p[40];
80
81 float Zmulx; /* Half the screenwidth, in pixels. (used in render.c, */
82              /* zbuf.c)                                             */
83 float Zmuly; /* Half the screenheight, in pixels. (used in render.c,*/
84              /* zbuf.c)                                             */
85 float Zjitx; /* Jitter offset in x. When jitter is disabled, this   */
86              /* should be 0.5. (used in render.c, zbuf.c)           */
87 float Zjity; /* Jitter offset in y. When jitter is disabled, this   */
88              /* should be 0.5. (used in render.c, zbuf.c)           */
89
90 unsigned int Zvlnr, Zsample;
91 VlakRen *Zvlr;
92 void (*zbuffunc)(float *, float *, float *);
93 void (*zbuflinefunc)(float *, float *);
94
95 APixstr       *APixbuf;      /* Zbuffer: linked list of face indices       */
96 unsigned short        *Acolrow;      /* Zbuffer: colour buffer, one line high      */
97 int           *Arectz;       /* Zbuffer: distance buffer, almost obsolete  */
98 int            Aminy;        /* y value of first line in the accu buffer   */
99 int            Amaxy;        /* y value of last line in the accu buffer    */
100 int            Azvoordeel  = 0;
101 APixstrMain    apsmfirst;
102 short          apsmteller  = 0;
103
104 /*-----------------------------------------------------------*/ 
105 /* Functions                                                 */
106 /*-----------------------------------------------------------*/ 
107
108 void fillrect(unsigned int *rect, int x, unsigned int y, unsigned int val)
109 {
110         unsigned int len,*drect;
111
112         len= x*y;
113         drect= rect;
114         while(len>0) {
115                 len--;
116                 *drect= val;
117                 drect++;
118         }
119 }
120
121 /* *************  ACCUMULATION ZBUF ************ */
122
123 /*-APixstr---------------------(antialised pixel struct)------------------------------*/ 
124
125 APixstr *addpsmainA()
126 {
127         APixstrMain *psm;
128
129         psm= &apsmfirst;
130
131         while(psm->next) {
132                 psm= psm->next;
133         }
134
135         psm->next= MEM_mallocN(sizeof(APixstrMain), "addpsmainA");
136
137         psm= psm->next;
138         psm->next=0;
139         psm->ps= MEM_callocN(4096*sizeof(APixstr),"pixstr");
140         apsmteller= 0;
141
142         return psm->ps;
143 }
144
145 void freepsA()
146 {
147         APixstrMain *psm, *next;
148
149         psm= &apsmfirst;
150
151         while(psm) {
152                 next= psm->next;
153                 if(psm->ps) {
154                         MEM_freeN(psm->ps);
155                         psm->ps= 0;
156                 }
157                 if(psm!= &apsmfirst) MEM_freeN(psm);
158                 psm= next;
159         }
160
161         apsmfirst.next= 0;
162         apsmfirst.ps= 0;
163         apsmteller= 0;
164 }
165
166 APixstr *addpsA(void)
167 {
168         static APixstr *prev;
169
170         /* make first PS */
171         if((apsmteller & 4095)==0) prev= addpsmainA();
172         else prev++;
173         apsmteller++;
174         
175         return prev;
176 }
177
178 /* fills in color, with window coordinate, from Aminy->Amaxy */
179 void zbufinvulAc(float *v1, float *v2, float *v3)  
180 {
181         APixstr *ap, *apofs, *apn;
182         double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1;
183         double zxd,zyd,zy0, tmp;
184         float *minv,*maxv,*midv;
185         int *rz,zverg,x;
186         int my0,my2,sn1,sn2,rectx,zd,*rectzofs;
187         int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2, mask;
188         
189         /* MIN MAX */
190         if(v1[1]<v2[1]) {
191                 if(v2[1]<v3[1])         {
192                         minv=v1; midv=v2; maxv=v3;
193                 }
194                 else if(v1[1]<v3[1])    {
195                         minv=v1; midv=v3; maxv=v2;
196                 }
197                 else    {
198                         minv=v3; midv=v1; maxv=v2;
199                 }
200         }
201         else {
202                 if(v1[1]<v3[1])         {
203                         minv=v2; midv=v1; maxv=v3;
204                 }
205                 else if(v2[1]<v3[1])    {
206                         minv=v2; midv=v3; maxv=v1;
207                 }
208                 else    {
209                         minv=v3; midv=v2; maxv=v1;
210                 }
211         }
212
213         if(minv[1] == maxv[1]) return;  /* prevent 'zero' size faces */
214
215         my0= ceil(minv[1]);
216         my2= floor(maxv[1]);
217         omsl= floor(midv[1]);
218
219         if(my2<Aminy || my0> Amaxy) return;
220
221         if(my0<Aminy) my0= Aminy;
222
223         /* EDGES : LONGEST */
224         xx1= maxv[1]-minv[1];
225         if(xx1>2.0/65536.0) {
226                 z0= (maxv[0]-minv[0])/xx1;
227                 
228                 tmp= (-65536.0*z0);
229                 dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
230                 
231                 tmp= 65536.0*(z0*(my2-minv[1])+minv[0]);
232                 xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
233         }
234         else {
235                 dx0= 0;
236                 xs0= 65536.0*(MIN2(minv[0],maxv[0]));
237         }
238         /* EDGES : THE TOP ONE */
239         xx1= maxv[1]-midv[1];
240         if(xx1>2.0/65536.0) {
241                 z0= (maxv[0]-midv[0])/xx1;
242                 
243                 tmp= (-65536.0*z0);
244                 dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
245                 
246                 tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
247                 xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
248         }
249         else {
250                 dx1= 0;
251                 xs1= 65536.0*(MIN2(midv[0],maxv[0]));
252         }
253         /* EDGES : BOTTOM ONE */
254         xx1= midv[1]-minv[1];
255         if(xx1>2.0/65536.0) {
256                 z0= (midv[0]-minv[0])/xx1;
257                 
258                 tmp= (-65536.0*z0);
259                 dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
260                 
261                 tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
262                 xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
263         }
264         else {
265                 dx2= 0;
266                 xs2= 65536.0*(MIN2(minv[0],midv[0]));
267         }
268
269         /* ZBUF DX DY */
270         x1= v1[0]- v2[0];
271         x2= v2[0]- v3[0];
272         y1= v1[1]- v2[1];
273         y2= v2[1]- v3[1];
274         z1= v1[2]- v2[2];
275         z2= v2[2]- v3[2];
276         x0= y1*z2-z1*y2;
277         y0= z1*x2-x1*z2;
278         z0= x1*y2-y1*x2;
279         if(z0==0.0) return;
280
281         if(midv[1]==maxv[1]) omsl= my2;
282         if(omsl<Aminy) omsl= Aminy-1;  /* to make sure it does the first loop completely */
283
284         while (my2 > Amaxy) {  /* my2 can be larger */
285                 xs0+=dx0;
286                 if (my2<=omsl) {
287                         xs2+= dx2;
288                 }
289                 else{
290                         xs1+= dx1;
291                 }
292                 my2--;
293         }
294
295         xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2];
296
297         zxd= -x0/z0;
298         zyd= -y0/z0;
299         zy0= my2*zyd+xx1;
300         zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
301
302         /* start-offset in rect */
303         rectx= R.rectx;
304         rectzofs= (int *)(Arectz+rectx*(my2-Aminy));
305         apofs= (APixbuf+ rectx*(my2-Aminy));
306         mask= 1<<Zsample;
307
308         xs3= 0;         /* flag */
309         if(dx0>dx1) {
310                 xs3= xs0;
311                 xs0= xs1;
312                 xs1= xs3;
313                 xs3= dx0;
314                 dx0= dx1;
315                 dx1= xs3;
316                 xs3= 1; /* flag */
317
318         }
319
320         for(y=my2;y>omsl;y--) {
321
322                 sn1= xs0>>16;
323                 xs0+= dx0;
324
325                 sn2= xs1>>16;
326                 xs1+= dx1;
327
328                 sn1++;
329
330                 if(sn2>=rectx) sn2= rectx-1;
331                 if(sn1<0) sn1= 0;
332                 zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
333                 rz= rectzofs+sn1;
334                 ap= apofs+sn1;
335                 x= sn2-sn1;
336                 
337                 zverg-= Azvoordeel;
338                 
339                 while(x>=0) {
340                         if(zverg< *rz) {
341                                 apn= ap;
342                                 while(apn) {    /* loop unrolled */
343                                         if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; }
344                                         if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; }
345                                         if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; }
346                                         if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; }
347                                         if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; }
348                                         if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; }
349                                         if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; }
350                                         if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; }
351                                         if(apn->next==0) apn->next= addpsA();
352                                         apn= apn->next;
353                                 }                               
354                         }
355                         zverg+= zd;
356                         rz++; 
357                         ap++; 
358                         x--;
359                 }
360                 zy0-= zyd;
361                 rectzofs-= rectx;
362                 apofs-= rectx;
363         }
364
365         if(xs3) {
366                 xs0= xs1;
367                 dx0= dx1;
368         }
369         if(xs0>xs2) {
370                 xs3= xs0;
371                 xs0= xs2;
372                 xs2= xs3;
373                 xs3= dx0;
374                 dx0= dx2;
375                 dx2= xs3;
376         }
377
378         for(; y>=my0; y--) {
379
380                 sn1= xs0>>16;
381                 xs0+= dx0;
382
383                 sn2= xs2>>16;
384                 xs2+= dx2;
385
386                 sn1++;
387
388                 if(sn2>=rectx) sn2= rectx-1;
389                 if(sn1<0) sn1= 0;
390                 zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
391                 rz= rectzofs+sn1;
392                 ap= apofs+sn1;
393                 x= sn2-sn1;
394
395                 zverg-= Azvoordeel;
396
397                 while(x>=0) {
398                         if(zverg< *rz) {
399                                 apn= ap;
400                                 while(apn) {    /* loop unrolled */
401                                         if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; }
402                                         if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; }
403                                         if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; }
404                                         if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; }
405                                         if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; }
406                                         if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; }
407                                         if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; }
408                                         if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; }
409                                         if(apn->next==0) apn->next= addpsA();
410                                         apn= apn->next;
411                                 }
412                         }
413                         zverg+= zd;
414                         rz++; 
415                         ap++; 
416                         x--;
417                 }
418
419                 zy0-=zyd;
420                 rectzofs-= rectx;
421                 apofs-= rectx;
422         }
423 }
424
425 void zbuflineAc(float *vec1, float *vec2)
426 {
427         APixstr *ap, *apn;
428         unsigned int *rectz;
429         int start, end, x, y, oldx, oldy, ofs;
430         int dz, vergz, mask;
431         float dx, dy;
432         float v1[3], v2[3];
433         
434         dx= vec2[0]-vec1[0];
435         dy= vec2[1]-vec1[1];
436         
437         if(fabs(dx) > fabs(dy)) {
438
439                 /* all lines from left to right */
440                 if(vec1[0]<vec2[0]) {
441                         VECCOPY(v1, vec1);
442                         VECCOPY(v2, vec2);
443                 }
444                 else {
445                         VECCOPY(v2, vec1);
446                         VECCOPY(v1, vec2);
447                         dx= -dx; dy= -dy;
448                 }
449
450                 start= floor(v1[0]);
451                 end= start+floor(dx);
452                 if(end>=R.rectx) end= R.rectx-1;
453                 
454                 oldy= floor(v1[1]);
455                 dy/= dx;
456                 
457                 vergz= v1[2];
458                 vergz-= Azvoordeel;
459                 dz= (v2[2]-v1[2])/dx;
460                 
461                 rectz= (unsigned int *)(Arectz+R.rectx*(oldy-Aminy) +start);
462                 ap= (APixbuf+ R.rectx*(oldy-Aminy) +start);
463                 mask= 1<<Zsample;       
464                 
465                 if(dy<0) ofs= -R.rectx;
466                 else ofs= R.rectx;
467                 
468                 for(x= start; x<=end; x++, rectz++, ap++) {
469                         
470                         y= floor(v1[1]);
471                         if(y!=oldy) {
472                                 oldy= y;
473                                 rectz+= ofs;
474                                 ap+= ofs;
475                         }
476                         
477                         if(x>=0 && y>=Aminy && y<=Amaxy) {
478                                 if(vergz<*rectz) {
479                                 
480                                         apn= ap;
481                                         while(apn) {    /* loop unrolled */
482                                                 if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; }
483                                                 if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; }
484                                                 if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; }
485                                                 if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; }
486                                                 if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; }
487                                                 if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; }
488                                                 if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; }
489                                                 if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; }
490                                                 if(apn->next==0) apn->next= addpsA();
491                                                 apn= apn->next;
492                                         }                               
493                                         
494                                 }
495                         }
496                         
497                         v1[1]+= dy;
498                         vergz+= dz;
499                 }
500         }
501         else {
502         
503                 /* all lines from top to bottom */
504                 if(vec1[1]<vec2[1]) {
505                         VECCOPY(v1, vec1);
506                         VECCOPY(v2, vec2);
507                 }
508                 else {
509                         VECCOPY(v2, vec1);
510                         VECCOPY(v1, vec2);
511                         dx= -dx; dy= -dy;
512                 }
513
514                 start= floor(v1[1]);
515                 end= start+floor(dy);
516                 
517                 if(start>Amaxy || end<Aminy) return;
518                 
519                 if(end>Amaxy) end= Amaxy;
520                 
521                 oldx= floor(v1[0]);
522                 dx/= dy;
523                 
524                 vergz= v1[2];
525                 vergz-= Azvoordeel;
526                 dz= (v2[2]-v1[2])/dy;
527
528                 rectz= (unsigned int *)( Arectz+ (start-Aminy)*R.rectx+ oldx );
529                 ap= (APixbuf+ R.rectx*(start-Aminy) +oldx);
530                 mask= 1<<Zsample;
531                                 
532                 if(dx<0) ofs= -1;
533                 else ofs= 1;
534
535                 for(y= start; y<=end; y++, rectz+=R.rectx, ap+=R.rectx) {
536                         
537                         x= floor(v1[0]);
538                         if(x!=oldx) {
539                                 oldx= x;
540                                 rectz+= ofs;
541                                 ap+= ofs;
542                         }
543                         
544                         if(x>=0 && y>=Aminy && x<R.rectx) {
545                                 if(vergz<*rectz) {
546                                         
547                                         apn= ap;
548                                         while(apn) {    /* loop unrolled */
549                                                 if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; }
550                                                 if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; }
551                                                 if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; }
552                                                 if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; }
553                                                 if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; }
554                                                 if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; }
555                                                 if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; }
556                                                 if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; }
557                                                 if(apn->next==0) apn->next= addpsA();
558                                                 apn= apn->next;
559                                         }       
560                                         
561                                 }
562                         }
563                         
564                         v1[0]+= dx;
565                         vergz+= dz;
566                 }
567         }
568 }
569
570
571
572 /* *************  NORMAL ZBUFFER ************ */
573
574 void hoco_to_zco(float *zco, float *hoco)
575 {
576         float deler;
577
578         deler= hoco[3];
579         zco[0]= Zmulx*(1.0+hoco[0]/deler)+ Zjitx;
580         zco[1]= Zmuly*(1.0+hoco[1]/deler)+ Zjity;
581         zco[2]= 0x7FFFFFFF *(hoco[2]/deler);
582 }
583
584 void zbufline(vec1, vec2)
585 float *vec1, *vec2;
586 {
587         unsigned int *rectz, *rectp;
588         int start, end, x, y, oldx, oldy, ofs;
589         int dz, vergz;
590         float dx, dy;
591         float v1[3], v2[3];
592         
593         dx= vec2[0]-vec1[0];
594         dy= vec2[1]-vec1[1];
595         
596         if(fabs(dx) > fabs(dy)) {
597
598                 /* all lines from left to right */
599                 if(vec1[0]<vec2[0]) {
600                         VECCOPY(v1, vec1);
601                         VECCOPY(v2, vec2);
602                 }
603                 else {
604                         VECCOPY(v2, vec1);
605                         VECCOPY(v1, vec2);
606                         dx= -dx; dy= -dy;
607                 }
608
609                 start= floor(v1[0]);
610                 end= start+floor(dx);
611                 if(end>=R.rectx) end= R.rectx-1;
612                 
613                 oldy= floor(v1[1]);
614                 dy/= dx;
615                 
616                 vergz= v1[2];
617                 dz= (v2[2]-v1[2])/dx;
618                 
619                 rectz= R.rectz+ oldy*R.rectx+ start;
620                 rectp= R.rectot+ oldy*R.rectx+ start;
621                 
622                 if(dy<0) ofs= -R.rectx;
623                 else ofs= R.rectx;
624                 
625                 for(x= start; x<=end; x++, rectz++, rectp++) {
626                         
627                         y= floor(v1[1]);
628                         if(y!=oldy) {
629                                 oldy= y;
630                                 rectz+= ofs;
631                                 rectp+= ofs;
632                         }
633                         
634                         if(x>=0 && y>=0 && y<R.recty) {
635                                 if(vergz<*rectz) {
636                                         *rectz= vergz;
637                                         *rectp= Zvlnr;
638                                 }
639                         }
640                         
641                         v1[1]+= dy;
642                         vergz+= dz;
643                 }
644         }
645         else {
646                 /* all lines from top to bottom */
647                 if(vec1[1]<vec2[1]) {
648                         VECCOPY(v1, vec1);
649                         VECCOPY(v2, vec2);
650                 }
651                 else {
652                         VECCOPY(v2, vec1);
653                         VECCOPY(v1, vec2);
654                         dx= -dx; dy= -dy;
655                 }
656
657                 start= floor(v1[1]);
658                 end= start+floor(dy);
659                 
660                 if(end>=R.recty) end= R.recty-1;
661                 
662                 oldx= floor(v1[0]);
663                 dx/= dy;
664                 
665                 vergz= v1[2];
666                 dz= (v2[2]-v1[2])/dy;
667
668                 rectz= R.rectz+ start*R.rectx+ oldx;
669                 rectp= R.rectot+ start*R.rectx+ oldx;
670                 
671                 if(dx<0) ofs= -1;
672                 else ofs= 1;
673
674                 for(y= start; y<=end; y++, rectz+=R.rectx, rectp+=R.rectx) {
675                         
676                         x= floor(v1[0]);
677                         if(x!=oldx) {
678                                 oldx= x;
679                                 rectz+= ofs;
680                                 rectp+= ofs;
681                         }
682                         
683                         if(x>=0 && y>=0 && x<R.rectx) {
684                                 if(vergz<*rectz) {
685                                         *rectz= vergz;
686                                         *rectp= Zvlnr;
687                                 }
688                         }
689                         
690                         v1[0]+= dx;
691                         vergz+= dz;
692                 }
693         }
694 }
695
696
697 void zbufclipwire(VlakRen *vlr)
698 {
699         float *f1, *f2, *f3, *f4= 0,  deler;
700         int c1, c2, c3, c4, ec, and, or;
701
702         /* edgecode: 1= draw */
703         ec = vlr->ec;
704         if(ec==0) return;
705
706         c1= vlr->v1->clip;
707         c2= vlr->v2->clip;
708         c3= vlr->v3->clip;
709         f1= vlr->v1->ho;
710         f2= vlr->v2->ho;
711         f3= vlr->v3->ho;
712         
713         if(vlr->v4) {
714                 f4= vlr->v4->ho;
715                 c4= vlr->v4->clip;
716                 
717                 and= (c1 & c2 & c3 & c4);
718                 or= (c1 | c2 | c3 | c4);
719         }
720         else {
721                 and= (c1 & c2 & c3);
722                 or= (c1 | c2 | c3);
723         }
724         
725         if(or) {        /* not in the middle */
726                 if(and) {       /* out completely */
727                         return;
728                 }
729                 else {  /* clipping */
730
731                         if(ec & ME_V1V2) {
732                                 QUATCOPY(vez, f1);
733                                 QUATCOPY(vez+4, f2);
734                                 if( clipline(vez, vez+4)) {
735                                         hoco_to_zco(vez, vez);
736                                         hoco_to_zco(vez+4, vez+4);
737                                         zbuflinefunc(vez, vez+4);
738                                 }
739                         }
740                         if(ec & ME_V2V3) {
741                                 QUATCOPY(vez, f2);
742                                 QUATCOPY(vez+4, f3);
743                                 if( clipline(vez, vez+4)) {
744                                         hoco_to_zco(vez, vez);
745                                         hoco_to_zco(vez+4, vez+4);
746                                         zbuflinefunc(vez, vez+4);
747                                 }
748                         }
749                         if(vlr->v4) {
750                                 if(ec & ME_V3V4) {
751                                         QUATCOPY(vez, f3);
752                                         QUATCOPY(vez+4, f4);
753                                         if( clipline(vez, vez+4)) {
754                                                 hoco_to_zco(vez, vez);
755                                                 hoco_to_zco(vez+4, vez+4);
756                                                 zbuflinefunc(vez, vez+4);
757                                         }
758                                 }
759                                 if(ec & ME_V4V1) {
760                                         QUATCOPY(vez, f4);
761                                         QUATCOPY(vez+4, f1);
762                                         if( clipline(vez, vez+4)) {
763                                                 hoco_to_zco(vez, vez);
764                                                 hoco_to_zco(vez+4, vez+4);
765                                                 zbuflinefunc(vez, vez+4);
766                                         }
767                                 }
768                         }
769                         else {
770                                 if(ec & ME_V3V1) {
771                                         QUATCOPY(vez, f3);
772                                         QUATCOPY(vez+4, f1);
773                                         if( clipline(vez, vez+4)) {
774                                                 hoco_to_zco(vez, vez);
775                                                 hoco_to_zco(vez+4, vez+4);
776                                                 zbuflinefunc(vez, vez+4);
777                                         }
778                                 }
779                         }
780                         
781                         return;
782                 }
783         }
784
785         deler= f1[3];
786         vez[0]= Zmulx*(1.0+f1[0]/deler)+ Zjitx;
787         vez[1]= Zmuly*(1.0+f1[1]/deler)+ Zjity;
788         vez[2]= 0x7FFFFFFF *(f1[2]/deler);
789
790         deler= f2[3];
791         vez[4]= Zmulx*(1.0+f2[0]/deler)+ Zjitx;
792         vez[5]= Zmuly*(1.0+f2[1]/deler)+ Zjity;
793         vez[6]= 0x7FFFFFFF *(f2[2]/deler);
794
795         deler= f3[3];
796         vez[8]= Zmulx*(1.0+f3[0]/deler)+ Zjitx;
797         vez[9]= Zmuly*(1.0+f3[1]/deler)+ Zjity;
798         vez[10]= 0x7FFFFFFF *(f3[2]/deler);
799         
800         if(vlr->v4) {
801                 deler= f4[3];
802                 vez[12]= Zmulx*(1.0+f4[0]/deler)+ Zjitx;
803                 vez[13]= Zmuly*(1.0+f4[1]/deler)+ Zjity;
804                 vez[14]= 0x7FFFFFFF *(f4[2]/deler);
805
806                 if(ec & ME_V3V4)  zbuflinefunc(vez+8, vez+12);
807                 if(ec & ME_V4V1)  zbuflinefunc(vez+12, vez);
808         }
809         else {
810                 if(ec & ME_V3V1)  zbuflinefunc(vez+8, vez);
811         }
812
813         if(ec & ME_V1V2)  zbuflinefunc(vez, vez+4);
814         if(ec & ME_V2V3)  zbuflinefunc(vez+4, vez+8);
815         
816
817
818 }
819
820 void zbufinvulGLinv(v1,v2,v3) 
821 float *v1,*v2,*v3;
822 /* fills in R.rectot the value of Zvlnr using R.rectz */
823 /* INVERSE Z COMPARISION: BACKSIDE GETS VISIBLE */
824 {
825         double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1;
826         double zxd,zyd,zy0,tmp;
827         float *minv,*maxv,*midv;
828         unsigned int *rectpofs,*rp;
829         int *rz,zverg,zvlak,x;
830         int my0,my2,sn1,sn2,rectx,zd,*rectzofs;
831         int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2;
832         
833         /* MIN MAX */
834         if(v1[1]<v2[1]) {
835                 if(v2[1]<v3[1])         {
836                         minv=v1;  midv=v2;  maxv=v3;
837                 }
838                 else if(v1[1]<v3[1])    {
839                         minv=v1;  midv=v3;  maxv=v2;
840                 }
841                 else    {
842                         minv=v3;  midv=v1;  maxv=v2;
843                 }
844         }
845         else {
846                 if(v1[1]<v3[1])         {
847                         minv=v2;  midv=v1; maxv=v3;
848                 }
849                 else if(v2[1]<v3[1])    {
850                         minv=v2;  midv=v3;  maxv=v1;
851                 }
852                 else    {
853                         minv=v3;  midv=v2;  maxv=v1;
854                 }
855         }
856
857         my0= ceil(minv[1]);
858         my2= floor(maxv[1]);
859         omsl= floor(midv[1]);
860
861         if(my2<0 || my0> R.recty) return;
862
863         if(my0<0) my0=0;
864
865         /* EDGES : LONGEST */
866         xx1= maxv[1]-minv[1];
867         if(xx1>2.0/65536.0) {
868                 z0= (maxv[0]-minv[0])/xx1;
869                 
870                 tmp= (-65536.0*z0);
871                 dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
872                 
873                 tmp= 65536.0*(z0*(my2-minv[1])+minv[0]);
874                 xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
875         }
876         else {
877                 dx0= 0;
878                 xs0= 65536.0*(MIN2(minv[0],maxv[0]));
879         }
880         /* EDGES : THE TOP ONE */
881         xx1= maxv[1]-midv[1];
882         if(xx1>2.0/65536.0) {
883                 z0= (maxv[0]-midv[0])/xx1;
884                 
885                 tmp= (-65536.0*z0);
886                 dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
887                 
888                 tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
889                 xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
890         }
891         else {
892                 dx1= 0;
893                 xs1= 65536.0*(MIN2(midv[0],maxv[0]));
894         }
895         /* EDGES : THE BOTTOM ONE */
896         xx1= midv[1]-minv[1];
897         if(xx1>2.0/65536.0) {
898                 z0= (midv[0]-minv[0])/xx1;
899                 
900                 tmp= (-65536.0*z0);
901                 dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
902                 
903                 tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
904                 xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
905         }
906         else {
907                 dx2= 0;
908                 xs2= 65536.0*(MIN2(minv[0],midv[0]));
909         }
910
911         /* ZBUF DX DY */
912         x1= v1[0]- v2[0];
913         x2= v2[0]- v3[0];
914         y1= v1[1]- v2[1];
915         y2= v2[1]- v3[1];
916         z1= v1[2]- v2[2];
917         z2= v2[2]- v3[2];
918         x0= y1*z2-z1*y2;
919         y0= z1*x2-x1*z2;
920         z0= x1*y2-y1*x2;
921
922         if(z0==0.0) return;
923
924         if(midv[1]==maxv[1]) omsl= my2;
925         if(omsl<0) omsl= -1;  /* then it does the first loop entirely */
926
927         while (my2 >= R.recty) {  /* my2 can be larger */
928                 xs0+=dx0;
929                 if (my2<=omsl) {
930                         xs2+= dx2;
931                 }
932                 else{
933                         xs1+= dx1;
934                 }
935                 my2--;
936         }
937
938         xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2];
939
940         zxd= -x0/z0;
941         zyd= -y0/z0;
942         zy0= my2*zyd+xx1;
943         zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
944
945         /* start-offset in rect */
946         rectx= R.rectx;
947         rectzofs= (int *)(R.rectz+rectx*my2);
948         rectpofs= (R.rectot+rectx*my2);
949         zvlak= Zvlnr;
950
951         xs3= 0;         /* flag */
952         if(dx0>dx1) {
953                 xs3= xs0;
954                 xs0= xs1;
955                 xs1= xs3;
956                 xs3= dx0;
957                 dx0= dx1;
958                 dx1= xs3;
959                 xs3= 1; /* flag */
960
961         }
962
963         for(y=my2;y>omsl;y--) {
964
965                 sn1= xs0>>16;
966                 xs0+= dx0;
967
968                 sn2= xs1>>16;
969                 xs1+= dx1;
970
971                 sn1++;
972
973                 if(sn2>=rectx) sn2= rectx-1;
974                 if(sn1<0) sn1= 0;
975                 zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
976                 rz= rectzofs+sn1;
977                 rp= rectpofs+sn1;
978                 x= sn2-sn1;
979                 while(x>=0) {
980                         if(zverg> *rz || *rz==0x7FFFFFFF) {
981                                 *rz= zverg;
982                                 *rp= zvlak;
983                         }
984                         zverg+= zd;
985                         rz++; 
986                         rp++; 
987                         x--;
988                 }
989                 zy0-=zyd;
990                 rectzofs-= rectx;
991                 rectpofs-= rectx;
992         }
993
994         if(xs3) {
995                 xs0= xs1;
996                 dx0= dx1;
997         }
998         if(xs0>xs2) {
999                 xs3= xs0;
1000                 xs0= xs2;
1001                 xs2= xs3;
1002                 xs3= dx0;
1003                 dx0= dx2;
1004                 dx2= xs3;
1005         }
1006
1007         for(;y>=my0;y--) {
1008
1009                 sn1= xs0>>16;
1010                 xs0+= dx0;
1011
1012                 sn2= xs2>>16;
1013                 xs2+= dx2;
1014
1015                 sn1++;
1016
1017                 if(sn2>=rectx) sn2= rectx-1;
1018                 if(sn1<0) sn1= 0;
1019                 zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
1020                 rz= rectzofs+sn1;
1021                 rp= rectpofs+sn1;
1022                 x= sn2-sn1;
1023                 while(x>=0) {
1024                         if(zverg> *rz || *rz==0x7FFFFFFF) {
1025                                 *rz= zverg;
1026                                 *rp= zvlak;
1027                         }
1028                         zverg+= zd;
1029                         rz++; 
1030                         rp++; 
1031                         x--;
1032                 }
1033
1034                 zy0-=zyd;
1035                 rectzofs-= rectx;
1036                 rectpofs-= rectx;
1037         }
1038 }
1039
1040 void zbufinvulGL(float *v1, float *v2, float *v3)  /* fills in R.rectot the value Zvlnr using R.rectz */
1041 {
1042         double x0,y0,z0;
1043         double x1,y1,z1,x2,y2,z2,xx1;
1044         double zxd,zyd,zy0,tmp, zverg, zd;
1045         float *minv,*maxv,*midv;
1046         unsigned int *rectpofs,*rp;
1047         int *rz,zvlak,x;
1048         int my0,my2,sn1,sn2,rectx,*rectzofs;
1049         int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2;
1050
1051         /* MIN MAX */
1052         if(v1[1]<v2[1]) {
1053                 if(v2[1]<v3[1]) { minv=v1;  midv=v2;  maxv=v3; }
1054                 else if(v1[1]<v3[1]) { minv=v1;  midv=v3;  maxv=v2; }
1055                 else { minv=v3;  midv=v1;  maxv=v2; }
1056         }
1057         else {
1058                 if(v1[1]<v3[1]) { minv=v2;  midv=v1; maxv=v3; }
1059                 else if(v2[1]<v3[1]) { minv=v2;  midv=v3;  maxv=v1; }
1060                 else { minv=v3;  midv=v2;  maxv=v1; }
1061         }
1062
1063         if(minv[1] == maxv[1]) return;  /* no zero sized faces */
1064
1065         my0= ceil(minv[1]);
1066         my2= floor(maxv[1]);
1067         omsl= floor(midv[1]);
1068
1069         if(my2<0 || my0> R.recty) return;
1070
1071         if(my0<0) my0= 0;
1072
1073         /* EDGES : THE LONGEST */
1074         xx1= maxv[1]-minv[1];
1075         if(xx1>2.0/65536.0) {
1076                 z0= (maxv[0]-minv[0])/xx1;
1077                 
1078                 tmp= -65536.0*z0;
1079                 dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
1080                 
1081                 tmp= 65536.0*(z0*(my2-minv[1]) + minv[0]);
1082                 xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
1083         }
1084         else {
1085                 dx0= 0;
1086                 xs0= 65536.0*(MIN2(minv[0],maxv[0]));
1087         }
1088         /* EDGES : THE TOP ONE */
1089         xx1= maxv[1]-midv[1];
1090         if(xx1>2.0/65536.0) {
1091                 z0= (maxv[0]-midv[0])/xx1;
1092                 
1093                 tmp= -65536.0*z0;
1094                 dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
1095                 
1096                 tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
1097                 xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
1098         }
1099         else {
1100                 dx1= 0;
1101                 xs1= 65536.0*(MIN2(midv[0],maxv[0]));
1102         }
1103         /* EDGES : BOTTOM ONE */
1104         xx1= midv[1]-minv[1];
1105         if(xx1>2.0/65536.0) {
1106                 z0= (midv[0]-minv[0])/xx1;
1107                 
1108                 tmp= -65536.0*z0;
1109                 dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
1110                 
1111                 tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
1112                 xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
1113         }
1114         else {
1115                 dx2= 0;
1116                 xs2= 65536.0*(MIN2(minv[0],midv[0]));
1117         }
1118
1119         /* ZBUF DX DY */
1120         x1= v1[0]- v2[0];
1121         x2= v2[0]- v3[0];
1122         y1= v1[1]- v2[1];
1123         y2= v2[1]- v3[1];
1124         z1= v1[2]- v2[2];
1125         z2= v2[2]- v3[2];
1126         x0= y1*z2-z1*y2;
1127         y0= z1*x2-x1*z2;
1128         z0= x1*y2-y1*x2;
1129
1130         if(z0==0.0) return;
1131
1132         if(midv[1]==maxv[1]) omsl= my2;
1133         if(omsl<0) omsl= -1;  /* then it takes the first loop entirely */
1134
1135         while (my2 >= R.recty) {  /* my2 can be larger */
1136                 xs0+=dx0;
1137                 if (my2<=omsl) {
1138                         xs2+= dx2;
1139                 }
1140                 else{
1141                         xs1+= dx1;
1142                 }
1143                 my2--;
1144         }
1145
1146         xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2];
1147
1148         zxd= -x0/z0;
1149         zyd= -y0/z0;
1150         zy0= my2*zyd+xx1;
1151         zd= zxd;
1152
1153         /* start-offset in rect */
1154         rectx= R.rectx;
1155         rectzofs= (int *)(R.rectz+rectx*my2);
1156         rectpofs= (R.rectot+rectx*my2);
1157         zvlak= Zvlnr;
1158
1159         xs3= 0;         /* flag */
1160         if(dx0>dx1) {
1161                 xs3= xs0;
1162                 xs0= xs1;
1163                 xs1= xs3;
1164                 xs3= dx0;
1165                 dx0= dx1;
1166                 dx1= xs3;
1167                 xs3= 1; /* flag */
1168
1169         }
1170
1171         for(y=my2;y>omsl;y--) {
1172                 
1173                 /* endian insensitive */
1174                 sn1= xs0>>16;
1175                 xs0+= dx0;
1176
1177                 sn2= xs1>>16;
1178                 xs1+= dx1;
1179
1180                 sn1++;
1181
1182                 if(sn2>=rectx) sn2= rectx-1;
1183                 if(sn1<0) sn1= 0;
1184                 zverg= sn1*zxd+zy0;
1185                 rz= rectzofs+sn1;
1186                 rp= rectpofs+sn1;
1187                 x= sn2-sn1;
1188
1189                 while(x>=0) {
1190                         if(zverg< *rz) {
1191                                 *rz= floor(zverg);
1192                                 *rp= zvlak;
1193                         }
1194                         zverg+= zd;
1195                         rz++; 
1196                         rp++; 
1197                         x--;
1198                 }
1199                 zy0-=zyd;
1200                 rectzofs-= rectx;
1201                 rectpofs-= rectx;
1202         }
1203
1204         if(xs3) {
1205                 xs0= xs1;
1206                 dx0= dx1;
1207         }
1208         if(xs0>xs2) {
1209                 xs3= xs0;
1210                 xs0= xs2;
1211                 xs2= xs3;
1212                 xs3= dx0;
1213                 dx0= dx2;
1214                 dx2= xs3;
1215         }
1216
1217         for(;y>=my0;y--) {
1218
1219                 sn1= xs0>>16;
1220                 xs0+= dx0;
1221
1222                 sn2= xs2>>16;
1223                 xs2+= dx2;
1224
1225                 sn1++;
1226
1227                 if(sn2>=rectx) sn2= rectx-1;
1228                 if(sn1<0) sn1= 0;
1229                 zverg= sn1*zxd+zy0;
1230                 rz= rectzofs+sn1;
1231                 rp= rectpofs+sn1;
1232                 x= sn2-sn1;
1233                 while(x>=0) {
1234                         if(zverg< *rz) {
1235                                 *rz= floor(zverg);
1236                                 *rp= zvlak;
1237                         }
1238                         zverg+= zd;
1239                         rz++; 
1240                         rp++; 
1241                         x--;
1242                 }
1243
1244                 zy0-=zyd;
1245                 rectzofs-= rectx;
1246                 rectpofs-= rectx;
1247         }
1248 }
1249
1250
1251 void zbufinvulGL_onlyZ(float *v1, float *v2, float *v3)   /* only fills in R.rectz */
1252 {
1253         double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1;
1254         double zxd,zyd,zy0,tmp;
1255         float *minv,*maxv,*midv;
1256         int *rz,zverg,x;
1257         int my0,my2,sn1,sn2,rectx,zd,*rectzofs;
1258         int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2;
1259         
1260         /* MIN MAX */
1261         if(v1[1]<v2[1]) {
1262                 if(v2[1]<v3[1])         {
1263                         minv=v1; 
1264                         midv=v2; 
1265                         maxv=v3;
1266                 }
1267                 else if(v1[1]<v3[1])    {
1268                         minv=v1; 
1269                         midv=v3; 
1270                         maxv=v2;
1271                 }
1272                 else    {
1273                         minv=v3; 
1274                         midv=v1; 
1275                         maxv=v2;
1276                 }
1277         }
1278         else {
1279                 if(v1[1]<v3[1])         {
1280                         minv=v2; 
1281                         midv=v1; 
1282                         maxv=v3;
1283                 }
1284                 else if(v2[1]<v3[1])    {
1285                         minv=v2; 
1286                         midv=v3; 
1287                         maxv=v1;
1288                 }
1289                 else    {
1290                         minv=v3; 
1291                         midv=v2; 
1292                         maxv=v1;
1293                 }
1294         }
1295
1296         my0= ceil(minv[1]);
1297         my2= floor(maxv[1]);
1298         omsl= floor(midv[1]);
1299
1300         if(my2<0 || my0> R.recty) return;
1301
1302         if(my0<0) my0=0;
1303
1304         /* EDGES : LONGEST */
1305         xx1= maxv[1]-minv[1];
1306         if(xx1!=0.0) {
1307                 z0= (maxv[0]-minv[0])/xx1;
1308                 
1309                 tmp= (-65536.0*z0);
1310                 dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
1311                 
1312                 tmp= 65536.0*(z0*(my2-minv[1])+minv[0]);
1313                 xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
1314         }
1315         else {
1316                 dx0= 0;
1317                 xs0= 65536.0*(MIN2(minv[0],maxv[0]));
1318         }
1319         /* EDGES : TOP */
1320         xx1= maxv[1]-midv[1];
1321         if(xx1!=0.0) {
1322                 z0= (maxv[0]-midv[0])/xx1;
1323                 
1324                 tmp= (-65536.0*z0);
1325                 dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
1326                 
1327                 tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
1328                 xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
1329         }
1330         else {
1331                 dx1= 0;
1332                 xs1= 65536.0*(MIN2(midv[0],maxv[0]));
1333         }
1334         /* EDGES : BOTTOM */
1335         xx1= midv[1]-minv[1];
1336         if(xx1!=0.0) {
1337                 z0= (midv[0]-minv[0])/xx1;
1338                 
1339                 tmp= (-65536.0*z0);
1340                 dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
1341                 
1342                 tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
1343                 xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
1344         }
1345         else {
1346                 dx2= 0;
1347                 xs2= 65536.0*(MIN2(minv[0],midv[0]));
1348         }
1349
1350         /* ZBUF DX DY */
1351         x1= v1[0]- v2[0];
1352         x2= v2[0]- v3[0];
1353         y1= v1[1]- v2[1];
1354         y2= v2[1]- v3[1];
1355         z1= v1[2]- v2[2];
1356         z2= v2[2]- v3[2];
1357         x0= y1*z2-z1*y2;
1358         y0= z1*x2-x1*z2;
1359         z0= x1*y2-y1*x2;
1360
1361         if(z0==0.0) return;
1362
1363         if(midv[1]==maxv[1]) omsl= my2;
1364         if(omsl<0) omsl= -1;  /* then it takes first loop entirely */
1365
1366         while (my2 >= R.recty) {  /* my2 can be larger */
1367                 xs0+=dx0;
1368                 if (my2<=omsl) {
1369                         xs2+= dx2;
1370                 }
1371                 else{
1372                         xs1+= dx1;
1373                 }
1374                 my2--;
1375         }
1376
1377         xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2];
1378
1379         zxd= -x0/z0;
1380         zyd= -y0/z0;
1381         zy0= my2*zyd+xx1;
1382         zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
1383
1384         /* start-offset in rect */
1385         rectx= R.rectx;
1386         rectzofs= (int *)(R.rectz+rectx*my2);
1387
1388         xs3= 0;         /* flag */
1389         if(dx0>dx1) {
1390                 xs3= xs0;
1391                 xs0= xs1;
1392                 xs1= xs3;
1393                 xs3= dx0;
1394                 dx0= dx1;
1395                 dx1= xs3;
1396                 xs3= 1; /* flag */
1397
1398         }
1399
1400         for(y=my2;y>omsl;y--) {
1401
1402                 sn1= xs0>>16;
1403                 xs0+= dx0;
1404
1405                 sn2= xs1>>16;
1406                 xs1+= dx1;
1407
1408                 sn1++;
1409
1410                 if(sn2>=rectx) sn2= rectx-1;
1411                 if(sn1<0) sn1= 0;
1412                 zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
1413                 rz= rectzofs+sn1;
1414
1415                 x= sn2-sn1;
1416                 while(x>=0) {
1417                         if(zverg< *rz) {
1418                                 *rz= zverg;
1419                         }
1420                         zverg+= zd;
1421                         rz++; 
1422                         x--;
1423                 }
1424                 zy0-=zyd;
1425                 rectzofs-= rectx;
1426         }
1427
1428         if(xs3) {
1429                 xs0= xs1;
1430                 dx0= dx1;
1431         }
1432         if(xs0>xs2) {
1433                 xs3= xs0;
1434                 xs0= xs2;
1435                 xs2= xs3;
1436                 xs3= dx0;
1437                 dx0= dx2;
1438                 dx2= xs3;
1439         }
1440
1441         for(;y>=my0;y--) {
1442
1443                 sn1= xs0>>16;
1444                 xs0+= dx0;
1445
1446                 sn2= xs2>>16;
1447                 xs2+= dx2;
1448
1449                 sn1++;
1450
1451                 if(sn2>=rectx) sn2= rectx-1;
1452                 if(sn1<0) sn1= 0;
1453                 zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
1454                 rz= rectzofs+sn1;
1455
1456                 x= sn2-sn1;
1457                 while(x>=0) {
1458                         if(zverg< *rz) {
1459                                 *rz= zverg;
1460                         }
1461                         zverg+= zd;
1462                         rz++; 
1463                         x--;
1464                 }
1465
1466                 zy0-=zyd;
1467                 rectzofs-= rectx;
1468         }
1469 }
1470
1471 void print3floats(float *v1, float *v2, float *v3)
1472 {
1473         printf("1  %f %f %f %f\n", v1[0], v1[1], v1[2], v1[3]);
1474         printf("2  %f %f %f %f\n", v2[0], v2[1], v2[2], v2[3]);
1475         printf("3  %f %f %f %f\n", v3[0], v3[1], v3[2], v3[3]);
1476 }
1477
1478 static short cliptestf(float p, float q, float *u1, float *u2)
1479 {
1480         float r;
1481
1482         if(p<0.0) {
1483                 if(q<p) return 0;
1484                 else if(q<0.0) {
1485                         r= q/p;
1486                         if(r>*u2) return 0;
1487                         else if(r>*u1) *u1=r;
1488                 }
1489         }
1490         else {
1491                 if(p>0.0) {
1492                         if(q<0.0) return 0;
1493                         else if(q<p) {
1494                                 r= q/p;
1495                                 if(r<*u1) return 0;
1496                                 else if(r<*u2) *u2=r;
1497                         }
1498                 }
1499                 else if(q<0.0) return 0;
1500         }
1501         return 1;
1502 }
1503
1504 int RE_testclip(float *v)
1505 {
1506         float abs4;     /* WATCH IT: this function should do the same as cliptestf, otherwise troubles in zbufclip()*/
1507         short c=0;
1508
1509         abs4= fabs(v[3]);
1510
1511         if(v[2]< -abs4) c=16;                   /* this used to be " if(v[2]<0) ", see clippz() */
1512         else if(v[2]> abs4) c+= 32;
1513
1514         if( v[0]>abs4) c+=2;
1515         else if( v[0]< -abs4) c+=1;
1516
1517         if( v[1]>abs4) c+=4;
1518         else if( v[1]< -abs4) c+=8;
1519
1520         return c;
1521 }
1522
1523
1524 static void clipp(float *v1, float *v2, int b1, int *b2, int *b3, int a)
1525 {
1526         float da,db,u1=0.0,u2=1.0;
1527
1528         labda[b1][0]= -1.0;
1529         labda[b1][1]= -1.0;
1530
1531         da= v2[a]-v1[a];
1532         db= v2[3]-v1[3];
1533
1534         /* according the original article by Liang&Barsky, for clipping of
1535          * homeginic coordinates with viewplane, the value of "0" is used instead of "-w" .
1536          * This differs from the other clipping cases (like left or top) and I considered
1537          * it to be not so 'homogenic'. But later it has proven to be an error,
1538          * who would have thought that of L&B!
1539          */
1540
1541         if(cliptestf(-da-db, v1[3]+v1[a], &u1,&u2)) {
1542                 if(cliptestf(da-db, v1[3]-v1[a], &u1,&u2)) {
1543                         *b3=1;
1544                         if(u2<1.0) {
1545                                 labda[b1][1]= u2;
1546                                 *b2=1;
1547                         }
1548                         else labda[b1][1]=1.0;  /* u2 */
1549                         if(u1>0.0) {
1550                                 labda[b1][0]= u1;
1551                                 *b2=1;
1552                         } else labda[b1][0]=0.0;
1553                 }
1554         }
1555 }
1556
1557 static int clipline(float *v1, float *v2)       /* return 0: do not draw */
1558 {
1559         float dz,dw, u1=0.0, u2=1.0;
1560         float dx, dy, v13;
1561
1562         dz= v2[2]-v1[2];
1563         dw= v2[3]-v1[3];
1564
1565         /* this 1.01 is for clipping x and y just a tinsy larger. that way it is
1566            filled in with zbufwire correctly when rendering in parts. otherwise
1567            you see line endings at edges... */
1568
1569         if(cliptestf(-dz-dw, v1[3]+v1[2], &u1,&u2)) {
1570                 if(cliptestf(dz-dw, v1[3]-v1[2], &u1,&u2)) {
1571
1572                         dx= v2[0]-v1[0];
1573                         dz= 1.01*(v2[3]-v1[3]);
1574                         v13= 1.01*v1[3];
1575                         
1576                         if(cliptestf(-dx-dz, v1[0]+v13, &u1,&u2)) {
1577                                 if(cliptestf(dx-dz, v13-v1[0], &u1,&u2)) {
1578
1579                                         dy= v2[1]-v1[1];
1580                                 
1581                                         if(cliptestf(-dy-dz, v1[1]+v13, &u1,&u2)) {
1582                                                 if(cliptestf(dy-dz, v13-v1[1], &u1,&u2)) {
1583                                                         
1584                                                         if(u2<1.0) {
1585                                                                 v2[0]= v1[0]+u2*dx;
1586                                                                 v2[1]= v1[1]+u2*dy;
1587                                                                 v2[2]= v1[2]+u2*dz;
1588                                                                 v2[3]= v1[3]+u2*dw;
1589                                                         }
1590                                                         if(u1>0.0) {
1591                                                                 v1[0]= v1[0]+u1*dx;
1592                                                                 v1[1]= v1[1]+u1*dy;
1593                                                                 v1[2]= v1[2]+u1*dz;
1594                                                                 v1[3]= v1[3]+u1*dw;
1595                                                         }
1596                                                         return 1;
1597                                                 }
1598                                         }
1599                                 }
1600                         }
1601                 }
1602         }
1603         
1604         return 0;
1605 }
1606
1607
1608 static void maakvertpira(float *v1, float *v2, int *b1, int b2, int *clve)
1609 {
1610         float l1,l2,*adr;
1611
1612         l1= labda[b2][0];
1613         l2= labda[b2][1];
1614
1615         if(l1!= -1.0) {
1616                 if(l1!= 0.0) {
1617                         adr= vez+4*(*clve);
1618                         p[*b1]=adr;
1619                         (*clve)++;
1620                         adr[0]= v1[0]+l1*(v2[0]-v1[0]);
1621                         adr[1]= v1[1]+l1*(v2[1]-v1[1]);
1622                         adr[2]= v1[2]+l1*(v2[2]-v1[2]);
1623                         adr[3]= v1[3]+l1*(v2[3]-v1[3]);
1624                 } else p[*b1]= v1;
1625                 (*b1)++;
1626         }
1627         if(l2!= -1.0) {
1628                 if(l2!= 1.0) {
1629                         adr= vez+4*(*clve);
1630                         p[*b1]=adr;
1631                         (*clve)++;
1632                         adr[0]= v1[0]+l2*(v2[0]-v1[0]);
1633                         adr[1]= v1[1]+l2*(v2[1]-v1[1]);
1634                         adr[2]= v1[2]+l2*(v2[2]-v1[2]);
1635                         adr[3]= v1[3]+l2*(v2[3]-v1[3]);
1636                         (*b1)++;
1637                 }
1638         }
1639 }
1640
1641 /* ------------------------------------------------------------------------- */
1642
1643 void RE_projectverto(float *v1, float *adr)
1644 {
1645         /* calcs homogenic coord of vertex v1 */
1646         float x,y,z;
1647
1648         x= v1[0]; 
1649         y= v1[1]; 
1650         z= v1[2];
1651         adr[0]= x*R.winmat[0][0]          + z*R.winmat[2][0];
1652         adr[1]=                       y*R.winmat[1][1]+ z*R.winmat[2][1];
1653         adr[2]=                             z*R.winmat[2][2] + R.winmat[3][2];
1654         adr[3]=                             z*R.winmat[2][3] + R.winmat[3][3];
1655
1656 }
1657
1658 /* ------------------------------------------------------------------------- */
1659
1660 void projectvert(float *v1, float *adr)
1661 {
1662         /* calcs homogenic coord of vertex v1 */
1663         float x,y,z;
1664
1665         x= v1[0]; 
1666         y= v1[1]; 
1667         z= v1[2];
1668         adr[0]= x*R.winmat[0][0]+ y*R.winmat[1][0]+ z*R.winmat[2][0]+ R.winmat[3][0];
1669         adr[1]= x*R.winmat[0][1]+ y*R.winmat[1][1]+ z*R.winmat[2][1]+ R.winmat[3][1];
1670         adr[2]= x*R.winmat[0][2]+ y*R.winmat[1][2]+ z*R.winmat[2][2]+ R.winmat[3][2];
1671         adr[3]= x*R.winmat[0][3]+ y*R.winmat[1][3]+ z*R.winmat[2][3]+ R.winmat[3][3];
1672 }
1673
1674
1675 void zbufclip(float *f1, float *f2, float *f3, int c1, int c2, int c3)
1676 {
1677         float deler;
1678
1679         if(c1 | c2 | c3) {      /* not in middle */
1680                 if(c1 & c2 & c3) {      /* completely out */
1681                         return;
1682                 } else {        /* clipping */
1683                         int arg, v, b, clipflag[3], b1, b2, b3, c4, clve=3, clvlo, clvl=1;
1684
1685                         vez[0]= f1[0]; vez[1]= f1[1]; vez[2]= f1[2]; vez[3]= f1[3];
1686                         vez[4]= f2[0]; vez[5]= f2[1]; vez[6]= f2[2]; vez[7]= f2[3];
1687                         vez[8]= f3[0]; vez[9]= f3[1]; vez[10]= f3[2];vez[11]= f3[3];
1688
1689                         vlzp[0][0]= vez;
1690                         vlzp[0][1]= vez+4;
1691                         vlzp[0][2]= vez+8;
1692
1693                         clipflag[0]= ( (c1 & 48) | (c2 & 48) | (c3 & 48) );
1694                         if(clipflag[0]==0) {    /* othwerwise it needs to be calculated again, after the first (z) clip */
1695                                 clipflag[1]= ( (c1 & 3) | (c2 & 3) | (c3 & 3) );
1696                                 clipflag[2]= ( (c1 & 12) | (c2 & 12) | (c3 & 12) );
1697                         }
1698                         
1699                         for(b=0;b<3;b++) {
1700                                 
1701                                 if(clipflag[b]) {
1702                                 
1703                                         clvlo= clvl;
1704                                         
1705                                         for(v=0; v<clvlo; v++) {
1706                                         
1707                                                 if(vlzp[v][0]!=0) {     /* face is still there */
1708                                                         b2= b3 =0;      /* clip flags */
1709
1710                                                         if(b==0) arg= 2;
1711                                                         else if (b==1) arg= 0;
1712                                                         else arg= 1;
1713                                                         
1714                                                         clipp(vlzp[v][0],vlzp[v][1],0,&b2,&b3, arg);
1715                                                         clipp(vlzp[v][1],vlzp[v][2],1,&b2,&b3, arg);
1716                                                         clipp(vlzp[v][2],vlzp[v][0],2,&b2,&b3, arg);
1717
1718                                                         if(b2==0 && b3==1) {
1719                                                                 /* completely 'in' */;
1720                                                         } else if(b3==0) {
1721                                                                 vlzp[v][0]=0;
1722                                                                 /* completely 'out' */;
1723                                                         } else {
1724                                                                 b1=0;
1725                                                                 maakvertpira(vlzp[v][0],vlzp[v][1],&b1,0,&clve);
1726                                                                 maakvertpira(vlzp[v][1],vlzp[v][2],&b1,1,&clve);
1727                                                                 maakvertpira(vlzp[v][2],vlzp[v][0],&b1,2,&clve);
1728
1729                                                                 /* after front clip done: now set clip flags */
1730                                                                 if(b==0) {
1731                                                                         clipflag[1]= clipflag[2]= 0;
1732                                                                         f1= vez;
1733                                                                         for(b3=0; b3<clve; b3++) {
1734                                                                                 c4= RE_testclip(f1);
1735                                                                                 clipflag[1] |= (c4 & 3);
1736                                                                                 clipflag[2] |= (c4 & 12);
1737                                                                                 f1+= 4;
1738                                                                         }
1739                                                                 }
1740                                                                 
1741                                                                 vlzp[v][0]=0;
1742                                                                 if(b1>2) {
1743                                                                         for(b3=3; b3<=b1; b3++) {
1744                                                                                 vlzp[clvl][0]= p[0];
1745                                                                                 vlzp[clvl][1]= p[b3-2];
1746                                                                                 vlzp[clvl][2]= p[b3-1];
1747                                                                                 clvl++;
1748                                                                         }
1749                                                                 }
1750                                                         }
1751                                                 }
1752                                         }
1753                                 }
1754                         }
1755
1756             /* warning, this should never happen! */
1757                         if(clve>38) printf("clip overflow: clve clvl %d %d\n",clve,clvl);
1758
1759             /* perspective division */
1760                         f1=vez;
1761                         for(c1=0;c1<clve;c1++) {
1762                                 deler= f1[3];
1763                                 f1[0]= Zmulx*(1.0+f1[0]/deler)+ Zjitx;
1764                                 f1[1]= Zmuly*(1.0+f1[1]/deler)+ Zjity;
1765                                 f1[2]= 0x7FFFFFFF *(f1[2]/deler);
1766                                 f1+=4;
1767                         }
1768                         for(b=1;b<clvl;b++) {
1769                                 if(vlzp[b][0]) {
1770                                         zbuffunc(vlzp[b][0],vlzp[b][1],vlzp[b][2]);
1771                                 }
1772                         }
1773                         return;
1774                 }
1775         }
1776
1777         /* perspective division: HCS to ZCS */
1778         
1779         deler= f1[3];
1780         vez[0]= Zmulx*(1.0+f1[0]/deler)+ Zjitx;
1781         vez[1]= Zmuly*(1.0+f1[1]/deler)+ Zjity;
1782         vez[2]= 0x7FFFFFFF *(f1[2]/deler);
1783
1784         deler= f2[3];
1785         vez[4]= Zmulx*(1.0+f2[0]/deler)+ Zjitx;
1786         vez[5]= Zmuly*(1.0+f2[1]/deler)+ Zjity;
1787         vez[6]= 0x7FFFFFFF *(f2[2]/deler);
1788
1789         deler= f3[3];
1790         vez[8]= Zmulx*(1.0+f3[0]/deler)+ Zjitx;
1791         vez[9]= Zmuly*(1.0+f3[1]/deler)+ Zjity;
1792         vez[10]= 0x7FFFFFFF *(f3[2]/deler);
1793
1794         zbuffunc(vez,vez+4,vez+8);
1795 }
1796
1797 /* ***************** ZBUFFER MAIN ROUTINES **************** */
1798
1799
1800 void zbufferall(void)
1801 {
1802         VlakRen *vlr= NULL;
1803         Material *ma=0;
1804         int v;
1805         short transp=0, env=0, wire=0;
1806
1807         Zmulx= ((float)R.rectx)/2.0;
1808         Zmuly= ((float)R.recty)/2.0;
1809
1810         fillrect(R.rectz, R.rectx, R.recty, 0x7FFFFFFF);
1811
1812         Zvlnr= 0;
1813
1814         zbuffunc= zbufinvulGL;
1815         zbuflinefunc= zbufline;
1816
1817         for(v=0;v<R.totvlak;v++) {
1818
1819                 if((v & 255)==0) vlr= R.blovl[v>>8];
1820                 else vlr++;
1821                 
1822                 if(vlr->flag & R_VISIBLE) {
1823                         if(vlr->mat!=ma) {
1824                                 ma= vlr->mat;
1825                                 transp= ma->mode & MA_ZTRA;
1826                                 env= (ma->mode & MA_ENV);
1827                                 wire= (ma->mode & MA_WIRE);
1828                                 
1829                                 if(ma->mode & MA_ZINV) zbuffunc= zbufinvulGLinv;
1830                                 else zbuffunc= zbufinvulGL;
1831                         }
1832                         
1833                         if(transp==0) {
1834                                 if(env) Zvlnr= 0;
1835                                 else Zvlnr= v+1;
1836                                 
1837                                 if(wire) zbufclipwire(vlr);
1838                                 else {
1839                                         zbufclip(vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip);
1840                                         if(vlr->v4) {
1841                                                 if(Zvlnr) Zvlnr+= 0x800000;
1842                                                 zbufclip(vlr->v1->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v3->clip, vlr->v4->clip);
1843                                         }
1844                                 }
1845                         }
1846                 }
1847         }
1848 }
1849
1850 static int hashlist_projectvert(float *v1, float *hoco)
1851 {
1852         static VertBucket bucket[256], *buck;
1853         
1854         if(v1==0) {
1855                 memset(bucket, 0, 256*sizeof(VertBucket));
1856                 return 0;
1857         }
1858         
1859         buck= &bucket[ (((long)v1)/16) & 255 ];
1860         if(buck->vert==v1) {
1861                 COPY_16(hoco, buck->hoco);
1862                 return buck->clip;
1863         }
1864         
1865         projectvert(v1, hoco);
1866         buck->clip = RE_testclip(hoco);
1867         buck->vert= v1;
1868         COPY_16(buck->hoco, hoco);
1869         return buck->clip;
1870 }
1871
1872 /* used for booth radio 'tool' as during render */
1873 void RE_zbufferall_radio(struct RadView *vw, RNode **rg_elem, int rg_totelem)
1874 {
1875         float hoco[4][4];
1876         int a;
1877         int c1, c2, c3, c4= 0;
1878         unsigned int *rectoto, *rectzo;
1879         int rectxo, rectyo;
1880
1881         if(rg_totelem==0) return;
1882
1883         hashlist_projectvert(0, 0);
1884         
1885         rectxo= R.rectx;
1886         rectyo= R.recty;
1887         rectoto= R.rectot;
1888         rectzo= R.rectz;
1889         
1890         R.rectx= vw->rectx;
1891         R.recty= vw->recty;
1892         R.rectot= vw->rect;
1893         R.rectz= vw->rectz;
1894         
1895         Zmulx= ((float)R.rectx)/2.0;
1896         Zmuly= ((float)R.recty)/2.0;
1897
1898         /* needed for projectvert */
1899         MTC_Mat4MulMat4(R.winmat, vw->viewmat, vw->winmat);
1900
1901         fillrect(R.rectz, R.rectx, R.recty, 0x7FFFFFFF);
1902         fillrect(R.rectot, R.rectx, R.recty, 0xFFFFFF);
1903
1904         zbuffunc= zbufinvulGL;
1905         
1906         if(rg_elem) {   /* radio tool */
1907                 RNode **re, *rn;
1908
1909                 re= rg_elem;
1910                 re+= (rg_totelem-1);
1911                 for(a= rg_totelem-1; a>=0; a--, re--) {
1912                         rn= *re;
1913                         if( (rn->f & RAD_SHOOT)==0 ) {    /* no shootelement */
1914                                 
1915                                 if( rn->f & RAD_BACKFACE) Zvlnr= 0xFFFFFF;      
1916                                 else Zvlnr= a;
1917                                 
1918                                 c1= hashlist_projectvert(rn->v1, hoco[0]);
1919                                 c2= hashlist_projectvert(rn->v2, hoco[1]);
1920                                 c3= hashlist_projectvert(rn->v3, hoco[2]);
1921                                 
1922                                 if(rn->v4) {
1923                                         c4= hashlist_projectvert(rn->v4, hoco[3]);
1924                                 }
1925         
1926                                 zbufclip(hoco[0], hoco[1], hoco[2], c1, c2, c3);
1927                                 if(rn->v4) {
1928                                         zbufclip(hoco[0], hoco[2], hoco[3], c1, c3, c4);
1929                                 }
1930                         }
1931                 }
1932         }
1933         else {  /* radio render */
1934                 VlakRen *vlr=NULL;
1935                 RadFace *rf;
1936                 int totface=0;
1937                 
1938                 for(a=0; a<R.totvlak; a++) {
1939                         if((a & 255)==0) vlr= R.blovl[a>>8]; else vlr++;
1940                 
1941                         if(vlr->radface) {
1942                                 rf= vlr->radface;
1943                                 if( (rf->flag & RAD_SHOOT)==0 ) {    /* no shootelement */
1944                                         
1945                                         if( rf->flag & RAD_BACKFACE) Zvlnr= 0xFFFFFF;   /* receives no energy, but is zbuffered */
1946                                         else Zvlnr= totface;
1947                                         
1948                                         c1= hashlist_projectvert(vlr->v1->co, hoco[0]);
1949                                         c2= hashlist_projectvert(vlr->v2->co, hoco[1]);
1950                                         c3= hashlist_projectvert(vlr->v3->co, hoco[2]);
1951                                         
1952                                         if(vlr->v4) {
1953                                                 c4= hashlist_projectvert(vlr->v4->co, hoco[3]);
1954                                         }
1955                 
1956                                         zbufclip(hoco[0], hoco[1], hoco[2], c1, c2, c3);
1957                                         if(vlr->v4) {
1958                                                 zbufclip(hoco[0], hoco[2], hoco[3], c1, c3, c4);
1959                                         }
1960                                 }
1961                                 totface++;
1962                         }
1963                 }
1964         }
1965         
1966         /* restore */
1967         R.rectx= rectxo;
1968         R.recty= rectyo;
1969         R.rectot= rectoto;
1970         R.rectz= rectzo;
1971
1972 }
1973
1974 void zbuffershad(LampRen *lar)
1975 {
1976         VlakRen *vlr= NULL;
1977         Material *ma=0;
1978         int a, ok=1, lay= -1;
1979
1980         if(lar->mode & LA_LAYER) lay= lar->lay;
1981
1982         Zmulx= ((float)R.rectx)/2.0;
1983         Zmuly= ((float)R.recty)/2.0;
1984         Zjitx= Zjity= -0.5;
1985
1986         fillrect(R.rectz,R.rectx,R.recty,0x7FFFFFFE);
1987
1988         zbuffunc= zbufinvulGL_onlyZ;
1989
1990         for(a=0;a<R.totvlak;a++) {
1991
1992                 if((a & 255)==0) vlr= R.blovl[a>>8];
1993                 else vlr++;
1994
1995                 if(vlr->mat!= ma) {
1996                         ma= vlr->mat;
1997                         ok= 1;
1998                         if((ma->mode & MA_TRACEBLE)==0) ok= 0;
1999                 }
2000                 
2001                 if(ok && (vlr->flag & R_VISIBLE) && (vlr->lay & lay)) {
2002                         zbufclip(vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip);
2003                         if(vlr->v4) zbufclip(vlr->v1->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v3->clip, vlr->v4->clip);
2004                 }
2005         }
2006 }
2007
2008
2009
2010 /* ******************** ABUF ************************* */
2011
2012
2013 void bgnaccumbuf(void)
2014 {
2015         
2016         Acolrow= MEM_mallocN(4*sizeof(short)*R.rectx, "Acolrow");
2017         Arectz= MEM_mallocN(sizeof(int)*ABUFPART*R.rectx, "Arectz");
2018         APixbuf= MEM_mallocN(ABUFPART*R.rectx*sizeof(APixstr), "APixbuf");
2019
2020         Aminy= -1000;
2021         Amaxy= -1000;
2022         
2023         apsmteller= 0;
2024         apsmfirst.next= 0;
2025         apsmfirst.ps= 0;
2026
2027 /* ------------------------------------------------------------------------ */
2028
2029 void endaccumbuf(void)
2030 {
2031         
2032         MEM_freeN(Acolrow);
2033         MEM_freeN(Arectz);
2034         MEM_freeN(APixbuf);
2035         freepsA();
2036 }
2037
2038 /* ------------------------------------------------------------------------ */
2039
2040 void copyto_abufz(int sample)
2041 {
2042         PixStr *ps;
2043         int x, y, *rza;
2044         long *rd;
2045         
2046         memcpy(Arectz, R.rectz+ R.rectx*Aminy, 4*R.rectx*(Amaxy-Aminy+1));
2047
2048         if( (R.r.mode & R_OSA)==0 || sample==0) return;
2049                 
2050         rza= Arectz;
2051         rd= (R.rectdaps+ R.rectx*Aminy);
2052
2053         sample= (1<<sample);
2054         
2055         for(y=Aminy; y<=Amaxy; y++) {
2056                 for(x=0; x<R.rectx; x++) {
2057                         
2058                         if( IS_A_POINTER_CODE(*rd)) {   
2059                                 ps= (PixStr *) POINTER_FROM_CODE(*rd);
2060
2061                                 while(ps) {
2062                                         if(sample & ps->mask) {
2063                                                 *rza= ps->z;
2064                                                 break;
2065                                         }
2066                                         ps= ps->next;
2067                                 }
2068                         }
2069                         
2070                         rd++; rza++;
2071                 }
2072         }
2073 }
2074
2075
2076 /* ------------------------------------------------------------------------ */
2077
2078 void zbuffer_abuf()
2079 {
2080         float vec[3], hoco[4], mul, zval, fval;
2081         Material *ma=0;
2082         int v, len;
2083         
2084         Zjitx= Zjity= -0.5;
2085         Zmulx= ((float)R.rectx)/2.0;
2086         Zmuly= ((float)R.recty)/2.0;
2087
2088         /* clear APixstructs */
2089         len= sizeof(APixstr)*R.rectx*ABUFPART;
2090         memset(APixbuf, 0, len);
2091         
2092         zbuffunc= zbufinvulAc;
2093         zbuflinefunc= zbuflineAc;
2094
2095         for(Zsample=0; Zsample<R.osa || R.osa==0; Zsample++) {
2096                 
2097                 copyto_abufz(Zsample);  /* init zbuffer */
2098
2099                 if(R.r.mode & R_OSA) {
2100                         Zjitx= -jit[Zsample][0]-0.5;
2101                         Zjity= -jit[Zsample][1]-0.5;
2102                 }
2103                 
2104                 for(v=0; v<R.totvlak; v++) {
2105                         if((v & 255)==0) {
2106                                 Zvlr= R.blovl[v>>8];
2107                         }
2108                         else Zvlr++;
2109                         
2110                         ma= Zvlr->mat;
2111
2112                         if(ma->mode & (MA_ZTRA)) {
2113
2114                                                 /* a little advantage for transp rendering (a z offset) */
2115                                 if( ma->zoffs != 0.0) {
2116                                         mul= 0x7FFFFFFF;
2117                                         zval= mul*(1.0+Zvlr->v1->ho[2]/Zvlr->v1->ho[3]);
2118
2119                                         VECCOPY(vec, Zvlr->v1->co);
2120                                         /* z is negative, otherwise its being clipped */ 
2121                                         vec[2]-= ma->zoffs;
2122                                         RE_projectverto(vec, hoco);
2123                                         fval= mul*(1.0+hoco[2]/hoco[3]);
2124
2125                                         Azvoordeel= (int) fabs(zval - fval );
2126                                 }
2127                                 else Azvoordeel= 0;
2128                                 
2129                                 Zvlnr= v+1;
2130                 
2131                                 if(Zvlr->flag & R_VISIBLE) {
2132                                         
2133                                         if(ma->mode & (MA_WIRE)) zbufclipwire(Zvlr);
2134                                         else {
2135                                                 zbufclip(Zvlr->v1->ho, Zvlr->v2->ho, Zvlr->v3->ho, Zvlr->v1->clip, Zvlr->v2->clip, Zvlr->v3->clip);
2136                                                 if(Zvlr->v4) {
2137                                                         Zvlnr+= 0x800000;
2138                                                         zbufclip(Zvlr->v1->ho, Zvlr->v3->ho, Zvlr->v4->ho, Zvlr->v1->clip, Zvlr->v3->clip, Zvlr->v4->clip);
2139                                                 }
2140                                         }
2141                                 }
2142                         }
2143                         if(RE_local_test_break()) break; 
2144                 }
2145                 
2146                 if((R.r.mode & R_OSA)==0) break;
2147                 if(RE_local_test_break()) break;
2148         }
2149         
2150 }
2151
2152 int vergzvlak(const void *a1, const void *a2)
2153 {
2154         const int *x1=a1, *x2=a2;
2155
2156         if( x1[0] < x2[0] ) return 1;
2157         else if( x1[0] > x2[0]) return -1;
2158         return 0;
2159 }
2160
2161 void shadetrapixel(float x, float y, int vlak, int mask, unsigned short *shortcol)
2162 {
2163         
2164         if( (vlak & 0x7FFFFF) > R.totvlak) {
2165                 printf("error in shadetrapixel nr: %d\n", (vlak & 0x7FFFFF));
2166                 return;
2167         }
2168         if(R.r.mode & R_OSA) {
2169                 int intcol[4]={0,0,0,0};
2170                 int a, tot=0;
2171                 
2172                 for(a=0; a<R.osa; a++) {
2173                         if(mask & (1<<a)) {
2174                                 shadepixel_short(x+jit[a][0], y+jit[a][1], vlak, 1<<a, shortcol);
2175                                 intcol[0]+= shortcol[0];
2176                                 intcol[1]+= shortcol[1];
2177                                 intcol[2]+= shortcol[2];
2178                                 intcol[3]+= shortcol[3];
2179                                 tot++;
2180                         }
2181                 }
2182                 shortcol[0]= intcol[0]/tot;
2183                 shortcol[1]= intcol[1]/tot;
2184                 shortcol[2]= intcol[2]/tot;
2185                 shortcol[3]= intcol[3]/tot;
2186         }
2187         else shadepixel_short(x, y, vlak, mask, shortcol);
2188 }
2189
2190 extern unsigned short usegamtab;
2191 void abufsetrow(int y)
2192 {
2193         APixstr *ap, *apn;
2194         float xs, ys;
2195         int x, part, a, b, zrow[100][3], totvlak, alpha[32], tempgam, nr, intcol[4];
2196         int sval, tempRf;
2197         unsigned short *col, shortcol[4], tempcol[4], sampcol[16*4], *scol;
2198         
2199         if(y<0) return;
2200         if(R.osa>16) {
2201                 printf("abufsetrow: osa too large\n");
2202                 G.afbreek= 1;
2203                 return;
2204         }
2205
2206    tempRf= R.flag;
2207    R.flag &= ~R_LAMPHALO;
2208
2209         /* alpha LUT */
2210         if(R.r.mode & R_OSA ) {
2211                 x= (65536/R.osa);
2212                 for(a=0; a<=R.osa; a++) {
2213                         alpha[a]= a*x;
2214                 }
2215         }
2216         /* does a pixbuf has to be created? */
2217         if(y<Aminy || y>Amaxy) {
2218                 part= (y/ABUFPART);
2219                 Aminy= part*ABUFPART;
2220                 Amaxy= Aminy+ABUFPART-1;
2221                 if(Amaxy>=R.recty) Amaxy= R.recty-1;
2222                 freepsA();
2223                 zbuffer_abuf();
2224         }
2225         
2226         /* render row */
2227         col= Acolrow;
2228         memset(col, 0, 2*4*R.rectx);
2229         ap= APixbuf+R.rectx*(y-Aminy);
2230         ys= y;
2231         tempgam= usegamtab;
2232         usegamtab= 0;
2233         
2234         for(x=0; x<R.rectx; x++, col+=4, ap++) {
2235                 if(ap->p[0]) {
2236                         /* sort in z */
2237                         totvlak= 0;
2238                         apn= ap;
2239                         while(apn) {
2240                                 for(a=0; a<4; a++) {
2241                                         if(apn->p[a]) {
2242                                                 zrow[totvlak][0]= apn->z[a];
2243                                                 zrow[totvlak][1]= apn->p[a];
2244                                                 zrow[totvlak][2]= apn->mask[a];
2245                                                 totvlak++;
2246                                                 if(totvlak>99) totvlak= 99;
2247                                         }
2248                                         else break;
2249                                 }
2250                                 apn= apn->next;
2251                         }
2252                         if(totvlak==1) {
2253                                 
2254                                 shadetrapixel((float)x, (float)y, ap->p[0], ap->mask[0], shortcol);
2255         
2256                                 nr= count_mask(ap->mask[0]);
2257                                 if( (R.r.mode & R_OSA) && nr<R.osa) {
2258                                         a= alpha[ nr ];
2259                                         col[0]= (shortcol[0]*a)>>16;
2260                                         col[1]= (shortcol[1]*a)>>16;
2261                                         col[2]= (shortcol[2]*a)>>16;
2262                                         col[3]= (shortcol[3]*a)>>16;
2263                                 }
2264                                 else {
2265                                         col[0]= shortcol[0];
2266                                         col[1]= shortcol[1];
2267                                         col[2]= shortcol[2];
2268                                         col[3]= shortcol[3];
2269                                 }
2270                         }
2271                         else {
2272
2273                                 if(totvlak==2) {
2274                                         if(zrow[0][0] < zrow[1][0]) {
2275                                                 a= zrow[0][0]; zrow[0][0]= zrow[1][0]; zrow[1][0]= a;
2276                                                 a= zrow[0][1]; zrow[0][1]= zrow[1][1]; zrow[1][1]= a;
2277                                                 a= zrow[0][2]; zrow[0][2]= zrow[1][2]; zrow[1][2]= a;
2278                                         }
2279
2280                                 }
2281                                 else {  /* totvlak>2 */
2282                                         qsort(zrow, totvlak, sizeof(int)*3, vergzvlak);
2283                                 }
2284                                 
2285                                 /* join when pixels are adjacent */
2286                                 
2287                                 while(totvlak>0) {
2288                                         totvlak--;
2289                                         
2290                                         shadetrapixel((float)x, (float)y, zrow[totvlak][1], 0xFFFF, shortcol);
2291                                         
2292                                         a= count_mask(zrow[totvlak][2]);
2293                                         if( (R.r.mode & R_OSA ) && a<R.osa) {
2294                                                 if(totvlak>0) {
2295                                                         memset(sampcol, 0, 4*2*R.osa);
2296                                                         sval= addtosampcol(sampcol, shortcol, zrow[totvlak][2]);
2297
2298                                                         /* sval==0: alpha completely full */
2299                                                         while( (sval != 0) && (totvlak>0) ) {
2300                                                                 a= count_mask(zrow[totvlak-1][2]);
2301                                                                 if(a==R.osa) break;
2302                                                                 totvlak--;
2303                                                         
2304                                                                 shadetrapixel((float)x, (float)y, zrow[totvlak][1], zrow[totvlak][2], shortcol);
2305                                                                 sval= addtosampcol(sampcol, shortcol, zrow[totvlak][2]);
2306                                                         }
2307                                                         scol= sampcol;
2308                                                         intcol[0]= scol[0]; intcol[1]= scol[1];
2309                                                         intcol[2]= scol[2]; intcol[3]= scol[3];
2310                                                         scol+= 4;
2311                                                         for(a=1; a<R.osa; a++, scol+=4) {
2312                                                                 intcol[0]+= scol[0]; intcol[1]+= scol[1];
2313                                                                 intcol[2]+= scol[2]; intcol[3]+= scol[3];
2314                                                         }
2315                                                         tempcol[0]= intcol[0]/R.osa;
2316                                                         tempcol[1]= intcol[1]/R.osa;
2317                                                         tempcol[2]= intcol[2]/R.osa;
2318                                                         tempcol[3]= intcol[3]/R.osa;
2319                                                         
2320                                                         addAlphaUnderShort(col, tempcol);
2321                                                         
2322                                                 }
2323                                                 else {
2324                                                         a= alpha[a];
2325                                                         shortcol[0]= (shortcol[0]*a)>>16;
2326                                                         shortcol[1]= (shortcol[1]*a)>>16;
2327                                                         shortcol[2]= (shortcol[2]*a)>>16;
2328                                                         shortcol[3]= (shortcol[3]*a)>>16;
2329                                                         addAlphaUnderShort(col, shortcol);
2330                                                 }
2331                                         }       
2332                                         else addAlphaUnderShort(col, shortcol);
2333                                                         
2334                                         if(col[3]>=0xFFF0) break;
2335                                 }
2336                         }
2337                 }
2338         }
2339         
2340         usegamtab= tempgam;
2341         R.flag= tempRf;
2342 }
2343
2344 /* end of zbuf.c */
2345
2346
2347
2348