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