2 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * Contributors: Hos, RPW
22 * 2004-2006 Blender Foundation, full recode
24 * ***** END GPL LICENSE BLOCK *****
27 /** \file blender/render/intern/source/zbuf.c
33 /*---------------------------------------------------------------------------*/
35 /*---------------------------------------------------------------------------*/
44 #include "BLI_blenlib.h"
45 #include "BLI_jitter.h"
46 #include "BLI_threads.h"
47 #include "BLI_utildefines.h"
49 #include "MEM_guardedalloc.h"
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"
57 #include "BKE_global.h"
58 #include "BKE_material.h"
61 #include "RE_render_ext.h"
64 #include "pixelblending.h"
65 #include "render_result.h"
66 #include "render_types.h"
67 #include "renderpipeline.h"
68 #include "renderdatabase.h"
69 #include "rendercore.h"
78 /* could enable at some point but for now there are far too many conversions */
80 # pragma GCC diagnostic ignored "-Wdouble-promotion"
83 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
84 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
85 /* only to be used here in this file, it's for speed */
86 extern struct Render R;
87 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
90 /* ****************** Spans ******************************* */
92 /* each zbuffer has coordinates transformed to local rect coordinates, so we can simply clip */
93 void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty, float clipcrop)
95 memset(zspan, 0, sizeof(ZSpan));
100 zspan->span1= MEM_mallocN(recty*sizeof(float), "zspan");
101 zspan->span2= MEM_mallocN(recty*sizeof(float), "zspan");
103 zspan->clipcrop= clipcrop;
106 void zbuf_free_span(ZSpan *zspan)
109 if (zspan->span1) MEM_freeN(zspan->span1);
110 if (zspan->span2) MEM_freeN(zspan->span2);
111 zspan->span1= zspan->span2= NULL;
115 /* reset range for clipping */
116 static void zbuf_init_span(ZSpan *zspan)
118 zspan->miny1= zspan->miny2= zspan->recty+1;
119 zspan->maxy1= zspan->maxy2= -1;
120 zspan->minp1= zspan->maxp1= zspan->minp2= zspan->maxp2= NULL;
123 static void zbuf_add_to_span(ZSpan *zspan, const float v1[2], const float v2[2])
125 const float *minv, *maxv;
140 if (my2<0 || my0>= zspan->recty) return;
143 if (my2>=zspan->recty) my2= zspan->recty-1;
148 /* if (my0>my2) should still fill in, that way we get spans that skip nicely */
150 xx1= maxv[1]-minv[1];
151 if (xx1>FLT_EPSILON) {
152 dx0= (minv[0]-maxv[0])/xx1;
153 xs0= dx0*(minv[1]-my2) + minv[0];
157 xs0 = min_ff(minv[0], maxv[0]);
161 if (zspan->maxp1 == NULL) {
164 else { /* does it complete left span? */
165 if ( maxv == zspan->minp1 || minv==zspan->maxp1) {
173 if (span==zspan->span1) {
174 // printf("left span my0 %d my2 %d\n", my0, my2);
175 if (zspan->minp1==NULL || zspan->minp1[1] > minv[1] ) {
178 if (zspan->maxp1==NULL || zspan->maxp1[1] < maxv[1] ) {
181 if (my0<zspan->miny1) zspan->miny1= my0;
182 if (my2>zspan->maxy1) zspan->maxy1= my2;
185 // printf("right span my0 %d my2 %d\n", my0, my2);
186 if (zspan->minp2==NULL || zspan->minp2[1] > minv[1] ) {
189 if (zspan->maxp2==NULL || zspan->maxp2[1] < maxv[1] ) {
192 if (my0<zspan->miny2) zspan->miny2= my0;
193 if (my2>zspan->maxy2) zspan->maxy2= my2;
196 for (y=my2; y>=my0; y--, xs0+= dx0) {
197 /* xs0 is the xcoord! */
202 /*-----------------------------------------------------------*/
204 /*-----------------------------------------------------------*/
206 void fillrect(int *rect, int x, int y, int val)
219 /* based on Liang&Barsky, for clipping of pyramidical volume */
220 static short cliptestf(float a, float b, float c, float d, float *u1, float *u2)
222 float p= a + b, q= c + d, r;
229 else if (r>*u1) *u1=r;
234 if (q<0.0f) return 0;
238 else if (r<*u2) *u2=r;
241 else if (q<0.0f) return 0;
246 int testclip(const float v[4])
248 float abs4; /* WATCH IT: this function should do the same as cliptestf, otherwise troubles in zbufclip()*/
251 /* if we set clip flags, the clipping should be at least larger than epsilon.
252 * prevents issues with vertices lying exact on borders */
253 abs4= fabsf(v[3]) + FLT_EPSILON;
255 if ( v[0] < -abs4) c+=1;
256 else if ( v[0] > abs4) c+=2;
258 if ( v[1] > abs4) c+=4;
259 else if ( v[1] < -abs4) c+=8;
261 if (v[2] < -abs4) c+=16; /* this used to be " if (v[2]<0) ", see clippz() */
262 else if (v[2]> abs4) c+= 32;
269 /* ************* ACCUMULATION ZBUF ************ */
272 static APixstr *addpsmainA(ListBase *lb)
276 psm= MEM_mallocN(sizeof(APixstrMain), "addpsmainA");
277 BLI_addtail(lb, psm);
278 psm->ps= MEM_callocN(4096*sizeof(APixstr), "pixstr");
283 void freepsA(ListBase *lb)
285 APixstrMain *psm, *psmnext;
287 for (psm= lb->first; psm; psm= psmnext) {
295 static APixstr *addpsA(ZSpan *zspan)
298 if (zspan->apsmcounter==0) {
299 zspan->curpstr= addpsmainA(zspan->apsmbase);
300 zspan->apsmcounter= 4095;
304 zspan->apsmcounter--;
306 return zspan->curpstr;
309 static void zbuffillAc4(ZSpan *zspan, int obi, int zvlnr,
310 const float *v1, const float *v2, const float *v3, const float *v4)
312 APixstr *ap, *apofs, *apn;
313 double zxd, zyd, zy0, zverg;
315 float x1, y1, z1, x2, y2, z2, xx1;
316 float *span1, *span2;
318 int sn1, sn2, rectx, *rectzofs, *rectmaskofs, my0, my2, mask;
321 zbuf_init_span(zspan);
324 zbuf_add_to_span(zspan, v1, v2);
325 zbuf_add_to_span(zspan, v2, v3);
327 zbuf_add_to_span(zspan, v3, v4);
328 zbuf_add_to_span(zspan, v4, v1);
331 zbuf_add_to_span(zspan, v3, v1);
334 if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
336 if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
337 if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
341 /* ZBUF DX DY, in floats still */
352 if (z0==0.0f) return;
354 xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
356 zxd= -(double)x0/(double)z0;
357 zyd= -(double)y0/(double)z0;
358 zy0= ((double)my2)*zyd + (double)xx1;
360 /* start-offset in rect */
362 rectzofs= (int *)(zspan->arectz+rectx*(my2));
363 rectmaskofs= (int *)(zspan->rectmask+rectx*(my2));
364 apofs= (zspan->apixbuf+ rectx*(my2));
369 if (zspan->span1[sn1] < zspan->span2[sn1]) {
370 span1= zspan->span1+my2;
371 span2= zspan->span2+my2;
374 span1= zspan->span2+my2;
375 span2= zspan->span1+my2;
378 for (y=my2; y>=my0; y--, span1--, span2--) {
384 if (sn2>=rectx) sn2= rectx-1;
390 zverg= (double)sn1*zxd + zy0;
396 zverg-= zspan->polygon_offset;
399 intzverg= (int)CLAMPIS(zverg, INT_MIN, INT_MAX);
401 if ( intzverg < *rz) {
402 if (!zspan->rectmask || intzverg > *rm) {
406 if (apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= intzverg; apn->mask[0]= mask; break; }
407 if (apn->p[0]==zvlnr && apn->obi[0]==obi) {apn->mask[0]|= mask; break; }
408 if (apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= intzverg; apn->mask[1]= mask; break; }
409 if (apn->p[1]==zvlnr && apn->obi[1]==obi) {apn->mask[1]|= mask; break; }
410 if (apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= intzverg; apn->mask[2]= mask; break; }
411 if (apn->p[2]==zvlnr && apn->obi[2]==obi) {apn->mask[2]|= mask; break; }
412 if (apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= intzverg; apn->mask[3]= mask; break; }
413 if (apn->p[3]==zvlnr && apn->obi[3]==obi) {apn->mask[3]|= mask; break; }
414 if (apn->next==NULL) apn->next= addpsA(zspan);
436 static void zbuflineAc(ZSpan *zspan, int obi, int zvlnr, const float vec1[3], const float vec2[3])
439 int *rectz, *rectmask;
440 int start, end, x, y, oldx, oldy, ofs;
441 int dz, vergz, mask, maxtest=0;
450 if (fabsf(dx) > fabsf(dy)) {
452 /* all lines from left to right */
453 if (vec1[0]<vec2[0]) {
454 copy_v3_v3(v1, vec1);
455 copy_v3_v3(v2, vec2);
458 copy_v3_v3(v2, vec1);
459 copy_v3_v3(v1, vec2);
464 end= start+floor(dx);
465 if (end>=zspan->rectx) end= zspan->rectx-1;
471 vergz-= zspan->polygon_offset;
472 dz= (v2[2]-v1[2])/dx;
473 if (vergz>0x50000000 && dz>0) maxtest= 1; /* prevent overflow */
475 rectz= (int *)(zspan->arectz+zspan->rectx*(oldy) +start);
476 rectmask= (int *)(zspan->rectmask+zspan->rectx*(oldy) +start);
477 ap= (zspan->apixbuf+ zspan->rectx*(oldy) +start);
479 if (dy<0) ofs= -zspan->rectx;
480 else ofs= zspan->rectx;
482 for (x= start; x<=end; x++, rectz++, rectmask++, ap++) {
492 if (x>=0 && y>=0 && y<zspan->recty) {
494 if (!zspan->rectmask || vergz>*rectmask) {
497 while (apn) { /* loop unrolled */
498 if (apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; }
499 if (apn->p[0]==zvlnr && apn->obi[0]==obi) {apn->mask[0]|= mask; break; }
500 if (apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; }
501 if (apn->p[1]==zvlnr && apn->obi[1]==obi) {apn->mask[1]|= mask; break; }
502 if (apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; }
503 if (apn->p[2]==zvlnr && apn->obi[2]==obi) {apn->mask[2]|= mask; break; }
504 if (apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; }
505 if (apn->p[3]==zvlnr && apn->obi[3]==obi) {apn->mask[3]|= mask; break; }
506 if (apn->next == NULL) apn->next = addpsA(zspan);
514 if (maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
520 /* all lines from top to bottom */
521 if (vec1[1]<vec2[1]) {
522 copy_v3_v3(v1, vec1);
523 copy_v3_v3(v2, vec2);
526 copy_v3_v3(v2, vec1);
527 copy_v3_v3(v1, vec2);
532 end= start+floor(dy);
534 if (start>=zspan->recty || end<0) return;
536 if (end>=zspan->recty) end= zspan->recty-1;
542 vergz-= zspan->polygon_offset;
543 dz= (v2[2]-v1[2])/dy;
544 if (vergz>0x50000000 && dz>0) maxtest= 1; /* prevent overflow */
546 rectz= (int *)( zspan->arectz+ (start)*zspan->rectx+ oldx );
547 rectmask= (int *)( zspan->rectmask+ (start)*zspan->rectx+ oldx );
548 ap= (zspan->apixbuf+ zspan->rectx*(start) +oldx);
553 for (y= start; y<=end; y++, rectz+=zspan->rectx, rectmask+=zspan->rectx, ap+=zspan->rectx) {
563 if (x>=0 && y>=0 && x<zspan->rectx) {
565 if (!zspan->rectmask || vergz>*rectmask) {
568 while (apn) { /* loop unrolled */
569 if (apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; }
570 if (apn->p[0]==zvlnr) {apn->mask[0]|= mask; break; }
571 if (apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; }
572 if (apn->p[1]==zvlnr) {apn->mask[1]|= mask; break; }
573 if (apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; }
574 if (apn->p[2]==zvlnr) {apn->mask[2]|= mask; break; }
575 if (apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; }
576 if (apn->p[3]==zvlnr) {apn->mask[3]|= mask; break; }
577 if (apn->next == NULL) apn->next = addpsA(zspan);
585 if (maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
591 /* ************* NORMAL ZBUFFER ************ */
593 static void zbufline(ZSpan *zspan, int obi, int zvlnr, const float vec1[3], const float vec2[3])
595 int *rectz, *rectp, *recto, *rectmask;
596 int start, end, x, y, oldx, oldy, ofs;
597 int dz, vergz, maxtest= 0;
604 if (fabsf(dx) > fabsf(dy)) {
606 /* all lines from left to right */
607 if (vec1[0]<vec2[0]) {
608 copy_v3_v3(v1, vec1);
609 copy_v3_v3(v2, vec2);
612 copy_v3_v3(v2, vec1);
613 copy_v3_v3(v1, vec2);
618 end= start+floor(dx);
619 if (end>=zspan->rectx) end= zspan->rectx-1;
625 dz= floor((v2[2]-v1[2])/dx);
626 if (vergz>0x50000000 && dz>0) maxtest= 1; /* prevent overflow */
628 rectz= zspan->rectz + oldy*zspan->rectx+ start;
629 rectp= zspan->rectp + oldy*zspan->rectx+ start;
630 recto= zspan->recto + oldy*zspan->rectx+ start;
631 rectmask= zspan->rectmask + oldy*zspan->rectx+ start;
633 if (dy<0) ofs= -zspan->rectx;
634 else ofs= zspan->rectx;
636 for (x= start; x<=end; x++, rectz++, rectp++, recto++, rectmask++) {
647 if (x>=0 && y>=0 && y<zspan->recty) {
649 if (!zspan->rectmask || vergz>*rectmask) {
659 if (maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
664 /* all lines from top to bottom */
665 if (vec1[1]<vec2[1]) {
666 copy_v3_v3(v1, vec1);
667 copy_v3_v3(v2, vec2);
670 copy_v3_v3(v2, vec1);
671 copy_v3_v3(v1, vec2);
676 end= start+floor(dy);
678 if (end>=zspan->recty) end= zspan->recty-1;
684 dz= floor((v2[2]-v1[2])/dy);
685 if (vergz>0x50000000 && dz>0) maxtest= 1; /* prevent overflow */
687 rectz= zspan->rectz + start*zspan->rectx+ oldx;
688 rectp= zspan->rectp + start*zspan->rectx+ oldx;
689 recto= zspan->recto + start*zspan->rectx+ oldx;
690 rectmask= zspan->rectmask + start*zspan->rectx+ oldx;
695 for (y= start; y<=end; y++, rectz+=zspan->rectx, rectp+=zspan->rectx, recto+=zspan->rectx, rectmask+=zspan->rectx) {
706 if (x>=0 && y>=0 && x<zspan->rectx) {
708 if (!zspan->rectmask || vergz>*rectmask) {
717 if (maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
723 static void zbufline_onlyZ(ZSpan *zspan, int UNUSED(obi), int UNUSED(zvlnr), const float vec1[3], const float vec2[3])
725 int *rectz, *rectz1= NULL;
726 int start, end, x, y, oldx, oldy, ofs;
727 int dz, vergz, maxtest= 0;
734 if (fabsf(dx) > fabsf(dy)) {
736 /* all lines from left to right */
737 if (vec1[0]<vec2[0]) {
738 copy_v3_v3(v1, vec1);
739 copy_v3_v3(v2, vec2);
742 copy_v3_v3(v2, vec1);
743 copy_v3_v3(v1, vec2);
748 end= start+floor(dx);
749 if (end>=zspan->rectx) end= zspan->rectx-1;
755 dz= floor((v2[2]-v1[2])/dx);
756 if (vergz>0x50000000 && dz>0) maxtest= 1; /* prevent overflow */
758 rectz= zspan->rectz + oldy*zspan->rectx+ start;
760 rectz1= zspan->rectz1 + oldy*zspan->rectx+ start;
762 if (dy<0) ofs= -zspan->rectx;
763 else ofs= zspan->rectx;
765 for (x= start; x<=end; x++, rectz++) {
771 if (rectz1) rectz1+= ofs;
774 if (x>=0 && y>=0 && y<zspan->recty) {
775 if (vergz < *rectz) {
776 if (rectz1) *rectz1= *rectz;
779 else if (rectz1 && vergz < *rectz1)
785 if (maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
788 if (rectz1) rectz1++;
792 /* all lines from top to bottom */
793 if (vec1[1]<vec2[1]) {
794 copy_v3_v3(v1, vec1);
795 copy_v3_v3(v2, vec2);
798 copy_v3_v3(v2, vec1);
799 copy_v3_v3(v1, vec2);
804 end= start+floor(dy);
806 if (end>=zspan->recty) end= zspan->recty-1;
812 dz= floor((v2[2]-v1[2])/dy);
813 if (vergz>0x50000000 && dz>0) maxtest= 1; /* prevent overflow */
815 rectz= zspan->rectz + start*zspan->rectx+ oldx;
817 rectz1= zspan->rectz1 + start*zspan->rectx+ oldx;
822 for (y= start; y<=end; y++, rectz+=zspan->rectx) {
828 if (rectz1) rectz1+= ofs;
831 if (x>=0 && y>=0 && x<zspan->rectx) {
832 if (vergz < *rectz) {
833 if (rectz1) *rectz1= *rectz;
836 else if (rectz1 && vergz < *rectz1)
841 if (maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
845 rectz1+=zspan->rectx;
851 static int clipline(float v1[4], float v2[4]) /* return 0: do not draw */
853 float dz, dw, u1=0.0, u2=1.0;
859 /* this 1.01 is for clipping x and y just a tinsy larger. that way it is
860 * filled in with zbufwire correctly when rendering in parts. otherwise
861 * you see line endings at edges... */
863 if (cliptestf(-dz, -dw, v1[3], v1[2], &u1, &u2)) {
864 if (cliptestf(dz, -dw, v1[3], -v1[2], &u1, &u2)) {
867 dz= 1.01f*(v2[3]-v1[3]);
870 if (cliptestf(-dx, -dz, v1[0], v13, &u1, &u2)) {
871 if (cliptestf(dx, -dz, v13, -v1[0], &u1, &u2)) {
875 if (cliptestf(-dy, -dz, v1[1], v13, &u1, &u2)) {
876 if (cliptestf(dy, -dz, v13, -v1[1], &u1, &u2)) {
901 void hoco_to_zco(ZSpan *zspan, float zco[3], const float hoco[4])
906 zco[0]= zspan->zmulx*(1.0f+hoco[0]*div) + zspan->zofsx;
907 zco[1]= zspan->zmuly*(1.0f+hoco[1]*div) + zspan->zofsy;
908 zco[2]= 0x7FFFFFFF *(hoco[2]*div);
911 void zbufclipwire(ZSpan *zspan, int obi, int zvlnr, int ec,
912 const float ho1[4], const float ho2[4], const float ho3[4], const float ho4[4],
913 const int c1, const int c2, const int c3, const int c4)
918 /* edgecode: 1= draw */
922 and= (c1 & c2 & c3 & c4);
923 or= (c1 | c2 | c3 | c4);
930 if (or) { /* not in the middle */
931 if (and) { /* out completely */
934 else { /* clipping */
937 copy_v4_v4(vez, ho1);
938 copy_v4_v4(vez+4, ho2);
939 if ( clipline(vez, vez+4)) {
940 hoco_to_zco(zspan, vez, vez);
941 hoco_to_zco(zspan, vez+4, vez+4);
942 zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4);
946 copy_v4_v4(vez, ho2);
947 copy_v4_v4(vez+4, ho3);
948 if ( clipline(vez, vez+4)) {
949 hoco_to_zco(zspan, vez, vez);
950 hoco_to_zco(zspan, vez+4, vez+4);
951 zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4);
956 copy_v4_v4(vez, ho3);
957 copy_v4_v4(vez+4, ho4);
958 if ( clipline(vez, vez+4)) {
959 hoco_to_zco(zspan, vez, vez);
960 hoco_to_zco(zspan, vez+4, vez+4);
961 zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4);
965 copy_v4_v4(vez, ho4);
966 copy_v4_v4(vez+4, ho1);
967 if ( clipline(vez, vez+4)) {
968 hoco_to_zco(zspan, vez, vez);
969 hoco_to_zco(zspan, vez+4, vez+4);
970 zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4);
976 copy_v4_v4(vez, ho3);
977 copy_v4_v4(vez+4, ho1);
978 if ( clipline(vez, vez+4)) {
979 hoco_to_zco(zspan, vez, vez);
980 hoco_to_zco(zspan, vez+4, vez+4);
981 zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4);
990 hoco_to_zco(zspan, vez, ho1);
991 hoco_to_zco(zspan, vez+4, ho2);
992 hoco_to_zco(zspan, vez+8, ho3);
994 hoco_to_zco(zspan, vez+12, ho4);
996 if (ec & ME_V3V4) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+8, vez+12);
997 if (ec & ME_V4V1) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+12, vez);
1000 if (ec & ME_V3V1) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+8, vez);
1003 if (ec & ME_V1V2) zspan->zbuflinefunc(zspan, obi, zvlnr, vez, vez+4);
1004 if (ec & ME_V2V3) zspan->zbuflinefunc(zspan, obi, zvlnr, vez+4, vez+8);
1008 void zbufsinglewire(ZSpan *zspan, int obi, int zvlnr, const float ho1[4], const float ho2[4])
1016 if (c1 | c2) { /* not in the middle */
1017 if (!(c1 & c2)) { /* not out completely */
1018 copy_v4_v4(f1, ho1);
1019 copy_v4_v4(f2, ho2);
1021 if (clipline(f1, f2)) {
1022 hoco_to_zco(zspan, f1, f1);
1023 hoco_to_zco(zspan, f2, f2);
1024 zspan->zbuflinefunc(zspan, obi, zvlnr, f1, f2);
1029 hoco_to_zco(zspan, f1, ho1);
1030 hoco_to_zco(zspan, f2, ho2);
1032 zspan->zbuflinefunc(zspan, obi, zvlnr, f1, f2);
1037 * Fill the z buffer, but invert z order, and add the face index to
1038 * the corresponding face buffer.
1040 * This is one of the z buffer fill functions called in zbufclip() and
1043 * \param v1 [4 floats, world coordinates] first vertex
1044 * \param v2 [4 floats, world coordinates] second vertex
1045 * \param v3 [4 floats, world coordinates] third vertex
1048 /* WATCH IT: zbuffillGLinv4 and zbuffillGL4 are identical except for a 2 lines,
1049 * commented below */
1050 static void zbuffillGLinv4(ZSpan *zspan, int obi, int zvlnr,
1051 const float *v1, const float *v2, const float *v3, const float *v4)
1053 double zxd, zyd, zy0, zverg;
1055 float x1, y1, z1, x2, y2, z2, xx1;
1056 float *span1, *span2;
1059 int *rectmaskofs, *rm;
1061 int sn1, sn2, rectx, *rectzofs, my0, my2;
1064 zbuf_init_span(zspan);
1067 zbuf_add_to_span(zspan, v1, v2);
1068 zbuf_add_to_span(zspan, v2, v3);
1070 zbuf_add_to_span(zspan, v3, v4);
1071 zbuf_add_to_span(zspan, v4, v1);
1074 zbuf_add_to_span(zspan, v3, v1);
1077 if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
1079 if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
1080 if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
1082 // printf("my %d %d\n", my0, my2);
1083 if (my2<my0) return;
1086 /* ZBUF DX DY, in floats still */
1097 if (z0==0.0f) return;
1099 xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
1101 zxd= -(double)x0/(double)z0;
1102 zyd= -(double)y0/(double)z0;
1103 zy0= ((double)my2)*zyd + (double)xx1;
1105 /* start-offset in rect */
1106 rectx= zspan->rectx;
1107 rectzofs= (zspan->rectz+rectx*my2);
1108 rectpofs= (zspan->rectp+rectx*my2);
1109 rectoofs= (zspan->recto+rectx*my2);
1110 rectmaskofs= (zspan->rectmask+rectx*my2);
1114 if (zspan->span1[sn1] < zspan->span2[sn1]) {
1115 span1= zspan->span1+my2;
1116 span2= zspan->span2+my2;
1119 span1= zspan->span2+my2;
1120 span2= zspan->span1+my2;
1123 for (y=my2; y>=my0; y--, span1--, span2--) {
1129 if (sn2>=rectx) sn2= rectx-1;
1135 zverg= (double)sn1*zxd + zy0;
1139 rm= rectmaskofs+sn1;
1143 intzverg= (int)CLAMPIS(zverg, INT_MIN, INT_MAX);
1145 if ( intzverg > *rz || *rz==0x7FFFFFFF) { /* UNIQUE LINE: see comment above */
1146 if (!zspan->rectmask || intzverg > *rm) {
1147 *ro= obi; /* UNIQUE LINE: see comment above (order differs) */
1165 rectmaskofs-= rectx;
1169 /* uses spanbuffers */
1171 /* WATCH IT: zbuffillGLinv4 and zbuffillGL4 are identical except for a 2 lines,
1172 * commented below */
1173 static void zbuffillGL4(ZSpan *zspan, int obi, int zvlnr,
1174 const float *v1, const float *v2, const float *v3, const float *v4)
1176 double zxd, zyd, zy0, zverg;
1178 float x1, y1, z1, x2, y2, z2, xx1;
1179 float *span1, *span2;
1182 int *rectmaskofs, *rm;
1184 int sn1, sn2, rectx, *rectzofs, my0, my2;
1187 zbuf_init_span(zspan);
1190 zbuf_add_to_span(zspan, v1, v2);
1191 zbuf_add_to_span(zspan, v2, v3);
1193 zbuf_add_to_span(zspan, v3, v4);
1194 zbuf_add_to_span(zspan, v4, v1);
1197 zbuf_add_to_span(zspan, v3, v1);
1200 if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
1202 if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
1203 if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
1205 // printf("my %d %d\n", my0, my2);
1206 if (my2<my0) return;
1209 /* ZBUF DX DY, in floats still */
1220 if (z0==0.0f) return;
1222 xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
1224 zxd= -(double)x0/(double)z0;
1225 zyd= -(double)y0/(double)z0;
1226 zy0= ((double)my2)*zyd + (double)xx1;
1228 /* start-offset in rect */
1229 rectx= zspan->rectx;
1230 rectzofs= (zspan->rectz+rectx*my2);
1231 rectpofs= (zspan->rectp+rectx*my2);
1232 rectoofs= (zspan->recto+rectx*my2);
1233 rectmaskofs= (zspan->rectmask+rectx*my2);
1237 if (zspan->span1[sn1] < zspan->span2[sn1]) {
1238 span1= zspan->span1+my2;
1239 span2= zspan->span2+my2;
1242 span1= zspan->span2+my2;
1243 span2= zspan->span1+my2;
1246 for (y=my2; y>=my0; y--, span1--, span2--) {
1252 if (sn2>=rectx) sn2= rectx-1;
1258 zverg= (double)sn1*zxd + zy0;
1262 rm= rectmaskofs+sn1;
1266 intzverg= (int)CLAMPIS(zverg, INT_MIN, INT_MAX);
1268 if (intzverg < *rz) { /* ONLY UNIQUE LINE: see comment above */
1269 if (!zspan->rectmask || intzverg > *rm) {
1272 *ro= obi; /* UNIQUE LINE: see comment above (order differs) */
1288 rectmaskofs-= rectx;
1293 * Fill the z buffer. The face buffer is not operated on!
1295 * This is one of the z buffer fill functions called in zbufclip() and
1298 * \param v1 [4 floats, world coordinates] first vertex
1299 * \param v2 [4 floats, world coordinates] second vertex
1300 * \param v3 [4 floats, world coordinates] third vertex
1303 /* now: filling two Z values, the closest and 2nd closest */
1304 static void zbuffillGL_onlyZ(ZSpan *zspan, int UNUSED(obi), int UNUSED(zvlnr),
1305 const float *v1, const float *v2, const float *v3, const float *v4)
1307 double zxd, zyd, zy0, zverg;
1309 float x1, y1, z1, x2, y2, z2, xx1;
1310 float *span1, *span2;
1311 int *rz, *rz1, x, y;
1312 int sn1, sn2, rectx, *rectzofs, *rectzofs1= NULL, my0, my2;
1315 zbuf_init_span(zspan);
1318 zbuf_add_to_span(zspan, v1, v2);
1319 zbuf_add_to_span(zspan, v2, v3);
1321 zbuf_add_to_span(zspan, v3, v4);
1322 zbuf_add_to_span(zspan, v4, v1);
1325 zbuf_add_to_span(zspan, v3, v1);
1328 if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
1330 if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
1331 if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
1333 // printf("my %d %d\n", my0, my2);
1334 if (my2<my0) return;
1337 /* ZBUF DX DY, in floats still */
1348 if (z0==0.0f) return;
1350 xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
1352 zxd= -(double)x0/(double)z0;
1353 zyd= -(double)y0/(double)z0;
1354 zy0= ((double)my2)*zyd + (double)xx1;
1356 /* start-offset in rect */
1357 rectx= zspan->rectx;
1358 rectzofs= (zspan->rectz+rectx*my2);
1360 rectzofs1= (zspan->rectz1+rectx*my2);
1364 if (zspan->span1[sn1] < zspan->span2[sn1]) {
1365 span1= zspan->span1+my2;
1366 span2= zspan->span2+my2;
1369 span1= zspan->span2+my2;
1370 span2= zspan->span1+my2;
1373 for (y=my2; y>=my0; y--, span1--, span2--) {
1379 if (sn2>=rectx) sn2= rectx-1;
1383 zverg= (double)sn1*zxd + zy0;
1389 int zvergi= (int)CLAMPIS(zverg, INT_MIN, INT_MAX);
1391 /* option: maintain two depth values, closest and 2nd closest */
1393 if (rectzofs1) *rz1= *rz;
1396 else if (rectzofs1 && zvergi < *rz1)
1409 if (rectzofs1) rectzofs1-= rectx;
1413 /* 2d scanconvert for tria, calls func for each x, y coordinate and gives UV barycentrics */
1414 void zspan_scanconvert_strand(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float, float) )
1416 float x0, y0, x1, y1, x2, y2, z0, z1, z2, z;
1417 float u, v, uxd, uyd, vxd, vyd, uy0, vy0, zxd, zyd, zy0, xx1;
1418 float *span1, *span2;
1419 int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2;
1422 zbuf_init_span(zspan);
1425 zbuf_add_to_span(zspan, v1, v2);
1426 zbuf_add_to_span(zspan, v2, v3);
1427 zbuf_add_to_span(zspan, v3, v1);
1430 if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
1432 if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
1433 if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
1435 // printf("my %d %d\n", my0, my2);
1436 if (my2<my0) return;
1438 /* ZBUF DX DY, in floats still */
1450 if (z0==0.0f) return;
1452 xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
1453 zxd= -(double)x0/(double)z0;
1454 zyd= -(double)y0/(double)z0;
1455 zy0= ((double)my2)*zyd + (double)xx1;
1457 z1= 1.0f; /* (u1 - u2) */
1458 z2= 0.0f; /* (u2 - u3) */
1463 xx1= (x0*v1[0] + y0*v1[1])/z0 + 1.0f;
1464 uxd= -(double)x0/(double)z0;
1465 uyd= -(double)y0/(double)z0;
1466 uy0= ((double)my2)*uyd + (double)xx1;
1468 z1= -1.0f; /* (v1 - v2) */
1469 z2= 1.0f; /* (v2 - v3) */
1474 xx1= (x0*v1[0] + y0*v1[1])/z0;
1475 vxd= -(double)x0/(double)z0;
1476 vyd= -(double)y0/(double)z0;
1477 vy0= ((double)my2)*vyd + (double)xx1;
1481 if (zspan->span1[sn1] < zspan->span2[sn1]) {
1482 span1= zspan->span1+my2;
1483 span2= zspan->span2+my2;
1486 span1= zspan->span2+my2;
1487 span2= zspan->span1+my2;
1490 for (y=my2; y>=my0; y--, span1--, span2--) {
1496 if (sn2>=rectx) sn2= rectx-1;
1499 u= (double)sn1*uxd + uy0;
1500 v= (double)sn1*vxd + vy0;
1501 z= (double)sn1*zxd + zy0;
1503 for (x= sn1; x<=sn2; x++, u+=uxd, v+=vxd, z+=zxd)
1504 func(handle, x, y, u, v, z);
1512 /* scanconvert for strand triangles, calls func for each x, y coordinate and gives UV barycentrics and z */
1514 void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float) )
1516 float x0, y0, x1, y1, x2, y2, z0, z1, z2;
1517 float u, v, uxd, uyd, vxd, vyd, uy0, vy0, xx1;
1518 float *span1, *span2;
1519 int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2;
1522 zbuf_init_span(zspan);
1525 zbuf_add_to_span(zspan, v1, v2);
1526 zbuf_add_to_span(zspan, v2, v3);
1527 zbuf_add_to_span(zspan, v3, v1);
1530 if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
1532 if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
1533 if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
1535 // printf("my %d %d\n", my0, my2);
1536 if (my2<my0) return;
1538 /* ZBUF DX DY, in floats still */
1544 z1= 1.0f; /* (u1 - u2) */
1545 z2= 0.0f; /* (u2 - u3) */
1551 if (z0==0.0f) return;
1553 xx1= (x0*v1[0] + y0*v1[1])/z0 + 1.0f;
1554 uxd= -(double)x0/(double)z0;
1555 uyd= -(double)y0/(double)z0;
1556 uy0= ((double)my2)*uyd + (double)xx1;
1558 z1= -1.0f; /* (v1 - v2) */
1559 z2= 1.0f; /* (v2 - v3) */
1564 xx1= (x0*v1[0] + y0*v1[1])/z0;
1565 vxd= -(double)x0/(double)z0;
1566 vyd= -(double)y0/(double)z0;
1567 vy0= ((double)my2)*vyd + (double)xx1;
1571 if (zspan->span1[sn1] < zspan->span2[sn1]) {
1572 span1= zspan->span1+my2;
1573 span2= zspan->span2+my2;
1576 span1= zspan->span2+my2;
1577 span2= zspan->span1+my2;
1580 for (y=my2; y>=my0; y--, span1--, span2--) {
1586 if (sn2>=rectx) sn2= rectx-1;
1589 u= (double)sn1*uxd + uy0;
1590 v= (double)sn1*vxd + vy0;
1592 for (x= sn1; x<=sn2; x++, u+=uxd, v+=vxd)
1593 func(handle, x, y, u, v);
1604 * Sets lambda: flag, and parametrize the clipping of vertices in
1605 * viewspace coordinates. lambda = -1 means no clipping, lambda in [0, 1] means a clipping.
1606 * Note: uses globals.
1607 * \param v1 start coordinate s
1608 * \param v2 target coordinate t
1612 * \param a index for coordinate (x, y, or z)
1615 static void clippyra(float *lambda, float *v1, float *v2, int *b2, int *b3, int a, float clipcrop)
1617 float da, dw, u1=0.0, u2=1.0;
1624 /* prob; we clip slightly larger, osa renders add 2 pixels on edges, should become variable? */
1625 /* or better; increase r.winx/y size, but thats quite a complex one. do it later */
1631 dw= clipcrop*(v2[3]-v1[3]);
1632 v13= clipcrop*v1[3];
1634 /* according the original article by Liang&Barsky, for clipping of
1635 * homogeneous coordinates with viewplane, the value of "0" is used instead of "-w" .
1636 * This differs from the other clipping cases (like left or top) and I considered
1637 * it to be not so 'homogenic'. But later it has proven to be an error,
1638 * who would have thought that of L&B!
1641 if (cliptestf(-da, -dw, v13, v1[a], &u1, &u2)) {
1642 if (cliptestf(da, -dw, v13, -v1[a], &u1, &u2)) {
1648 else lambda[1]=1.0; /* u2 */
1661 * (make vertex pyramide clip)
1662 * Checks lambda and uses this to make decision about clipping the line
1663 * segment from v1 to v2. lambda is the factor by which the vector is
1664 * cut. ( calculate s + l * ( t - s )). The result is appended to the
1665 * vertex list of this face.
1668 * \param v1 start coordinate s
1669 * \param v2 target coordinate t
1672 * \param clve vertex vector.
1675 static void makevertpyra(float *vez, float *lambda, float **trias, float *v1, float *v2, int *b1, int *clve)
1687 adr[0]= v1[0]+l1*(v2[0]-v1[0]);
1688 adr[1]= v1[1]+l1*(v2[1]-v1[1]);
1689 adr[2]= v1[2]+l1*(v2[2]-v1[2]);
1690 adr[3]= v1[3]+l1*(v2[3]-v1[3]);
1692 else trias[*b1]= v1;
1701 adr[0]= v1[0]+l2*(v2[0]-v1[0]);
1702 adr[1]= v1[1]+l2*(v2[1]-v1[1]);
1703 adr[2]= v1[2]+l2*(v2[2]-v1[2]);
1704 adr[3]= v1[3]+l2*(v2[3]-v1[3]);
1710 /* ------------------------------------------------------------------------- */
1712 void projectverto(const float v1[3], float winmat[4][4], float adr[4])
1714 /* calcs homogenic coord of vertex v1 */
1720 adr[0] = x * winmat[0][0] + z * winmat[2][0] + winmat[3][0];
1721 adr[1] = y * winmat[1][1] + z * winmat[2][1] + winmat[3][1];
1722 adr[2] = z * winmat[2][2] + winmat[3][2];
1723 adr[3] = z * winmat[2][3] + winmat[3][3];
1725 //printf("hoco %f %f %f %f\n", adr[0], adr[1], adr[2], adr[3]);
1728 /* ------------------------------------------------------------------------- */
1730 void projectvert(const float v1[3], float winmat[4][4], float adr[4])
1732 /* calcs homogenic coord of vertex v1 */
1738 adr[0] = x * winmat[0][0] + y * winmat[1][0] + z * winmat[2][0] + winmat[3][0];
1739 adr[1] = x * winmat[0][1] + y * winmat[1][1] + z * winmat[2][1] + winmat[3][1];
1740 adr[2] = x * winmat[0][2] + y * winmat[1][2] + z * winmat[2][2] + winmat[3][2];
1741 adr[3] = x * winmat[0][3] + y * winmat[1][3] + z * winmat[2][3] + winmat[3][3];
1744 /* ------------------------------------------------------------------------- */
1746 #define ZBUF_PROJECT_CACHE_SIZE 256
1748 typedef struct ZbufProjectCache {
1753 static void zbuf_project_cache_clear(ZbufProjectCache *cache, int size)
1757 if (size > ZBUF_PROJECT_CACHE_SIZE)
1758 size= ZBUF_PROJECT_CACHE_SIZE;
1760 memset(cache, 0, sizeof(ZbufProjectCache)*size);
1761 for (i=0; i<size; i++)
1765 static int zbuf_shadow_project(ZbufProjectCache *cache, int index, float winmat[4][4], float *co, float *ho)
1767 int cindex= index & 255;
1769 if (cache[cindex].index == index) {
1770 copy_v4_v4(ho, cache[cindex].ho);
1771 return cache[cindex].clip;
1775 projectvert(co, winmat, ho);
1776 clipflag= testclip(ho);
1778 copy_v4_v4(cache[cindex].ho, ho);
1779 cache[cindex].clip= clipflag;
1780 cache[cindex].index= index;
1786 static void zbuffer_part_bounds(int winx, int winy, RenderPart *pa, float *bounds)
1788 bounds[0]= (2*pa->disprect.xmin - winx-1)/(float)winx;
1789 bounds[1]= (2*pa->disprect.xmax - winx+1)/(float)winx;
1790 bounds[2]= (2*pa->disprect.ymin - winy-1)/(float)winy;
1791 bounds[3]= (2*pa->disprect.ymax - winy+1)/(float)winy;
1794 static int zbuf_part_project(ZbufProjectCache *cache, int index, float winmat[4][4], float *bounds, float *co, float *ho)
1797 int cindex= index & 255;
1799 if (cache[cindex].index == index) {
1800 copy_v4_v4(ho, cache[cindex].ho);
1801 return cache[cindex].clip;
1806 copy_v3_v3(vec, co);
1807 projectvert(co, winmat, ho);
1810 if (ho[0] < bounds[0]*wco) clipflag |= 1;
1811 else if (ho[0] > bounds[1]*wco) clipflag |= 2;
1812 if (ho[1] > bounds[3]*wco) clipflag |= 4;
1813 else if (ho[1] < bounds[2]*wco) clipflag |= 8;
1815 copy_v4_v4(cache[cindex].ho, ho);
1816 cache[cindex].clip= clipflag;
1817 cache[cindex].index= index;
1823 void zbuf_render_project(float winmat[4][4], const float co[3], float ho[4])
1827 copy_v3_v3(vec, co);
1828 projectvert(vec, winmat, ho);
1831 void zbuf_make_winmat(Render *re, float winmat[4][4])
1833 if (re->r.mode & R_PANORAMA) {
1834 float panomat[4][4]= MAT4_UNITY;
1836 panomat[0][0]= re->panoco;
1837 panomat[0][2]= re->panosi;
1838 panomat[2][0]= -re->panosi;
1839 panomat[2][2]= re->panoco;
1841 mul_m4_m4m4(winmat, re->winmat, panomat);
1844 copy_m4_m4(winmat, re->winmat);
1847 /* do zbuffering and clip, f1 f2 f3 are hocos, c1 c2 c3 are clipping flags */
1849 void zbufclip(ZSpan *zspan, int obi, int zvlnr,
1850 const float f1[4], const float f2[4], const float f3[4],
1851 const int c1, const int c2, const int c3)
1853 float *vlzp[32][3], lambda[3][2];
1854 float vez[400], *trias[40];
1856 if (c1 | c2 | c3) { /* not in middle */
1857 if (c1 & c2 & c3) { /* completely out */
1860 else { /* clipping */
1861 int arg, v, b, clipflag[3], b1, b2, b3, c4, clve=3, clvlo, clvl=1;
1864 vez[0]= f1[0]; vez[1]= f1[1]; vez[2]= f1[2]; vez[3]= f1[3];
1865 vez[4]= f2[0]; vez[5]= f2[1]; vez[6]= f2[2]; vez[7]= f2[3];
1866 vez[8]= f3[0]; vez[9]= f3[1]; vez[10]= f3[2];vez[11]= f3[3];
1872 clipflag[0]= ( (c1 & 48) | (c2 & 48) | (c3 & 48) );
1873 if (clipflag[0]==0) { /* othwerwise it needs to be calculated again, after the first (z) clip */
1874 clipflag[1]= ( (c1 & 3) | (c2 & 3) | (c3 & 3) );
1875 clipflag[2]= ( (c1 & 12) | (c2 & 12) | (c3 & 12) );
1877 else clipflag[1]=clipflag[2]= 0;
1885 for (v=0; v<clvlo; v++) {
1887 if (vlzp[v][0]!=NULL) { /* face is still there */
1888 b2= b3 =0; /* clip flags */
1891 else if (b==1) arg= 0;
1894 clippyra(lambda[0], vlzp[v][0], vlzp[v][1], &b2, &b3, arg, zspan->clipcrop);
1895 clippyra(lambda[1], vlzp[v][1], vlzp[v][2], &b2, &b3, arg, zspan->clipcrop);
1896 clippyra(lambda[2], vlzp[v][2], vlzp[v][0], &b2, &b3, arg, zspan->clipcrop);
1898 if (b2==0 && b3==1) {
1899 /* completely 'in', but we copy because of last for () loop in this section */;
1900 vlzp[clvl][0]= vlzp[v][0];
1901 vlzp[clvl][1]= vlzp[v][1];
1902 vlzp[clvl][2]= vlzp[v][2];
1908 /* completely 'out' */;
1912 makevertpyra(vez, lambda[0], trias, vlzp[v][0], vlzp[v][1], &b1, &clve);
1913 makevertpyra(vez, lambda[1], trias, vlzp[v][1], vlzp[v][2], &b1, &clve);
1914 makevertpyra(vez, lambda[2], trias, vlzp[v][2], vlzp[v][0], &b1, &clve);
1916 /* after front clip done: now set clip flags */
1918 clipflag[1]= clipflag[2]= 0;
1920 for (b3=0; b3<clve; b3++) {
1922 clipflag[1] |= (c4 & 3);
1923 clipflag[2] |= (c4 & 12);
1930 for (b3=3; b3<=b1; b3++) {
1931 vlzp[clvl][0]= trias[0];
1932 vlzp[clvl][1]= trias[b3-2];
1933 vlzp[clvl][2]= trias[b3-1];
1943 /* warning, clip overflow, this should never happen! */
1944 BLI_assert(!(clve > 38 || clvl > 31));
1946 /* perspective division */
1948 for (b = 0; b < clve; b++) {
1949 hoco_to_zco(zspan, fp, fp);
1952 for (b = 1; b < clvl; b++) {
1954 zspan->zbuffunc(zspan, obi, zvlnr, vlzp[b][0], vlzp[b][1], vlzp[b][2], NULL);
1961 /* perspective division: HCS to ZCS */
1962 hoco_to_zco(zspan, vez, f1);
1963 hoco_to_zco(zspan, vez+4, f2);
1964 hoco_to_zco(zspan, vez+8, f3);
1965 zspan->zbuffunc(zspan, obi, zvlnr, vez, vez+4, vez+8, NULL);
1968 void zbufclip4(ZSpan *zspan, int obi, int zvlnr,
1969 const float f1[4], const float f2[4], const float f3[4], const float f4[4],
1970 const int c1, const int c2, const int c3, const int c4)
1974 if (c1 | c2 | c3 | c4) { /* not in middle */
1975 if (c1 & c2 & c3 & c4) { /* completely out */
1978 else { /* clipping */
1979 zbufclip(zspan, obi, zvlnr, f1, f2, f3, c1, c2, c3);
1980 zbufclip(zspan, obi, zvlnr, f1, f3, f4, c1, c3, c4);
1985 /* perspective division: HCS to ZCS */
1986 hoco_to_zco(zspan, vez, f1);
1987 hoco_to_zco(zspan, vez+4, f2);
1988 hoco_to_zco(zspan, vez+8, f3);
1989 hoco_to_zco(zspan, vez+12, f4);
1991 zspan->zbuffunc(zspan, obi, zvlnr, vez, vez+4, vez+8, vez+12);
1994 /* ************** ZMASK ******************************** */
1996 #define EXTEND_PIXEL(a) if (temprectp[a]) { z += rectz[a]; tot++; } (void)0
1998 /* changes the zbuffer to be ready for z-masking: applies an extend-filter, and then clears */
1999 static void zmask_rect(int *rectz, int *rectp, int xs, int ys, int neg)
2003 int row1, row2, row3, *curp, *curz;
2005 temprectp= MEM_dupallocN(rectp);
2007 /* extend: if pixel is not filled in, we check surrounding pixels and average z value */
2009 for (y=1; y<=ys; y++) {
2010 /* setup row indices */
2019 curp= rectp + (y-1)*xs;
2020 curz= rectz + (y-1)*xs;
2022 for (x=0; x<xs; x++, curp++, curz++) {
2030 EXTEND_PIXEL(row1 + 1);
2031 EXTEND_PIXEL(row3 + 1);
2033 EXTEND_PIXEL(row1 + 2);
2034 EXTEND_PIXEL(row2 + 2);
2035 EXTEND_PIXEL(row3 + 2);
2039 curz[0]= (int)(z/(float)tot);
2040 curp[0]= -1; /* env */
2045 row1++; row2++; row3++;
2050 MEM_freeN(temprectp);
2053 /* z values for negative are already correct */
2056 /* clear not filled z values */
2057 for (len= xs*ys -1; len>=0; len--) {
2058 if (rectp[len]==0) {
2059 rectz[len] = -0x7FFFFFFF;
2060 rectp[len]= -1; /* env code */
2069 /* ***************** ZBUFFER MAIN ROUTINES **************** */
2071 void zbuffer_solid(RenderPart *pa, RenderLayer *rl, void(*fillfunc)(RenderPart *, ZSpan *, int, void *), void *data)
2073 ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE];
2074 ZSpan zspans[16], *zspan; /* 16 = RE_MAX_OSA */
2076 VertRen *v1, *v2, *v3, *v4;
2077 Material *ma = NULL;
2078 ObjectInstanceRen *obi;
2080 float obwinmat[4][4], winmat[4][4], bounds[4];
2081 float ho1[4], ho2[4], ho3[4], ho4[4]={0};
2082 unsigned int lay= rl->lay, lay_zmask= rl->lay_zmask;
2083 int i, v, zvlnr, zsample, samples, c1, c2, c3, c4=0;
2084 short nofill=0, env=0, wire=0, zmaskpass=0;
2085 short all_z= (rl->layflag & SCE_LAY_ALL_Z) && !(rl->layflag & SCE_LAY_ZMASK);
2086 short neg_zmask= (rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK);
2088 zbuf_make_winmat(&R, winmat);
2090 samples= (R.osa? R.osa: 1);
2091 samples= MIN2(4, samples-pa->sample);
2093 for (zsample=0; zsample<samples; zsample++) {
2094 zspan= &zspans[zsample];
2096 zbuffer_part_bounds(R.winx, R.winy, pa, bounds);
2097 zbuf_alloc_span(zspan, pa->rectx, pa->recty, R.clipcrop);
2099 /* needed for transform from hoco to zbuffer co */
2100 zspan->zmulx= ((float)R.winx)/2.0f;
2101 zspan->zmuly= ((float)R.winy)/2.0f;
2104 zspan->zofsx= -pa->disprect.xmin - R.jit[pa->sample+zsample][0];
2105 zspan->zofsy= -pa->disprect.ymin - R.jit[pa->sample+zsample][1];
2107 else if (R.i.curblur) {
2108 zspan->zofsx= -pa->disprect.xmin - R.mblur_jit[R.i.curblur-1][0];
2109 zspan->zofsy= -pa->disprect.ymin - R.mblur_jit[R.i.curblur-1][1];
2112 zspan->zofsx= -pa->disprect.xmin;
2113 zspan->zofsy= -pa->disprect.ymin;
2115 /* to center the sample position */
2116 zspan->zofsx -= 0.5f;
2117 zspan->zofsy -= 0.5f;
2120 if (zsample == samples-1) {
2121 zspan->rectp= pa->rectp;
2122 zspan->recto= pa->recto;
2125 zspan->rectz= pa->rectmask;
2127 zspan->rectz= pa->rectz;
2130 zspan->recto= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "recto");
2131 zspan->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp");
2132 zspan->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
2135 fillrect(zspan->rectz, pa->rectx, pa->recty, 0x7FFFFFFF);
2136 fillrect(zspan->rectp, pa->rectx, pa->recty, 0);
2137 fillrect(zspan->recto, pa->rectx, pa->recty, 0);
2140 /* in case zmask we fill Z for objects in lay_zmask first, then clear Z, and then do normal zbuffering */
2141 if (rl->layflag & SCE_LAY_ZMASK)
2144 for (; zmaskpass >=0; zmaskpass--) {
2147 /* filling methods */
2148 for (zsample=0; zsample<samples; zsample++) {
2149 zspan= &zspans[zsample];
2151 if (zmaskpass && neg_zmask)
2152 zspan->zbuffunc= zbuffillGLinv4;
2154 zspan->zbuffunc= zbuffillGL4;
2155 zspan->zbuflinefunc= zbufline;
2158 /* regular zbuffering loop, does all sample buffers */
2159 for (i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) {
2162 /* continue happens in 2 different ways... zmaskpass only does lay_zmask stuff */
2164 if ((obi->lay & lay_zmask)==0)
2167 else if (!all_z && !(obi->lay & (lay|lay_zmask)))
2170 if (obi->flag & R_TRANSFORMED)
2171 mul_m4_m4m4(obwinmat, winmat, obi->mat);
2173 copy_m4_m4(obwinmat, winmat);
2175 if (clip_render_object(obi->obr->boundbox, bounds, obwinmat))
2178 zbuf_project_cache_clear(cache, obr->totvert);
2180 for (v=0; v<obr->totvlak; v++) {
2181 if ((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak;
2184 /* the cases: visible for render, only z values, zmask, nothing */
2185 if (obi->lay & lay) {
2188 nofill= (ma->mode & MA_ONLYCAST) || ((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP));
2189 env= (ma->mode & MA_ENV);
2190 wire= (ma->material_type == MA_TYPE_WIRE);
2192 for (zsample=0; zsample<samples; zsample++) {
2193 if (ma->mode & MA_ZINV || (zmaskpass && neg_zmask))
2194 zspans[zsample].zbuffunc= zbuffillGLinv4;
2196 zspans[zsample].zbuffunc= zbuffillGL4;
2200 else if (all_z || (obi->lay & lay_zmask)) {
2207 ma= NULL; /* otherwise nofill can hang */
2210 if (!(vlr->flag & R_HIDDEN) && nofill==0) {
2211 unsigned short partclip;
2218 c1= zbuf_part_project(cache, v1->index, obwinmat, bounds, v1->co, ho1);
2219 c2= zbuf_part_project(cache, v2->index, obwinmat, bounds, v2->co, ho2);
2220 c3= zbuf_part_project(cache, v3->index, obwinmat, bounds, v3->co, ho3);
2222 /* partclipping doesn't need viewplane clipping */
2223 partclip= c1 & c2 & c3;
2225 c4= zbuf_part_project(cache, v4->index, obwinmat, bounds, v4->co, ho4);
2240 for (zsample=0; zsample<samples; zsample++) {
2241 zspan= &zspans[zsample];
2245 zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
2247 zbufclipwire(zspan, i, zvlnr, vlr->ec, ho1, ho2, ho3, NULL, c1, c2, c3, 0);
2250 /* strands allow to be filled in as quad */
2251 if (v4 && (vlr->flag & R_STRAND)) {
2252 zbufclip4(zspan, i, zvlnr, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
2255 zbufclip(zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3);
2257 zbufclip(zspan, i, (env)? zvlnr: zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4);
2266 /* clear all z to close value, so it works as mask for next passes (ztra+strand) */
2268 for (zsample=0; zsample<samples; zsample++) {
2269 zspan= &zspans[zsample];
2272 zspan->rectmask= zspan->rectz;
2273 if (zsample == samples-1)
2274 zspan->rectz= pa->rectz;
2276 zspan->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz");
2277 fillrect(zspan->rectz, pa->rectx, pa->recty, 0x7FFFFFFF);
2279 zmask_rect(zspan->rectmask, zspan->rectp, pa->rectx, pa->recty, 1);
2282 zmask_rect(zspan->rectz, zspan->rectp, pa->rectx, pa->recty, 0);
2287 for (zsample=0; zsample<samples; zsample++) {
2288 zspan= &zspans[zsample];
2291 fillfunc(pa, zspan, pa->sample+zsample, data);
2293 if (zsample != samples-1) {
2294 MEM_freeN(zspan->rectz);
2295 MEM_freeN(zspan->rectp);
2296 MEM_freeN(zspan->recto);
2297 if (zspan->rectmask)
2298 MEM_freeN(zspan->rectmask);
2301 zbuf_free_span(zspan);
2305 void zbuffer_shadow(Render *re, float winmat[4][4], LampRen *lar, int *rectz, int size, float jitx, float jity)
2307 ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE];
2309 ObjectInstanceRen *obi;
2314 StrandRen *strand= NULL;
2316 StrandBound *sbound;
2317 float obwinmat[4][4], ho1[4], ho2[4], ho3[4], ho4[4];
2318 int a, b, c, i, c1, c2, c3, c4, ok=1, lay= -1;
2320 if (lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) lay= lar->lay;
2322 /* 1.0f for clipping in clippyra()... bad stuff actually */
2323 zbuf_alloc_span(&zspan, size, size, 1.0f);
2324 zspan.zmulx= ((float)size)/2.0f;
2325 zspan.zmuly= ((float)size)/2.0f;
2326 /* -0.5f to center the sample position */
2327 zspan.zofsx= jitx - 0.5f;
2328 zspan.zofsy= jity - 0.5f;
2332 fillrect(rectz, size, size, 0x7FFFFFFE);
2333 if (lar->buftype==LA_SHADBUF_HALFWAY) {
2334 zspan.rectz1= MEM_mallocN(size*size*sizeof(int), "seconday z buffer");
2335 fillrect(zspan.rectz1, size, size, 0x7FFFFFFE);
2338 /* filling methods */
2339 zspan.zbuflinefunc= zbufline_onlyZ;
2340 zspan.zbuffunc= zbuffillGL_onlyZ;
2342 for (i=0, obi=re->instancetable.first; obi; i++, obi=obi->next) {
2345 if (obr->ob==re->excludeob)
2347 else if (!(obi->lay & lay))
2350 if (obi->flag & R_TRANSFORMED)
2351 mul_m4_m4m4(obwinmat, winmat, obi->mat);
2353 copy_m4_m4(obwinmat, winmat);
2355 if (clip_render_object(obi->obr->boundbox, NULL, obwinmat))
2358 zbuf_project_cache_clear(cache, obr->totvert);
2361 for (a=0; a<obr->totvlak; a++) {
2363 if ((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
2366 /* note, these conditions are copied in shadowbuf_autoclip() */
2367 if (vlr->mat!= ma) {
2370 if ((ma->mode2 & MA_CASTSHADOW)==0 || (ma->mode & MA_SHADBUF)==0) ok= 0;
2373 if (ok && (obi->lay & lay) && !(vlr->flag & R_HIDDEN)) {
2374 c1= zbuf_shadow_project(cache, vlr->v1->index, obwinmat, vlr->v1->co, ho1);
2375 c2= zbuf_shadow_project(cache, vlr->v2->index, obwinmat, vlr->v2->co, ho2);
2376 c3= zbuf_shadow_project(cache, vlr->v3->index, obwinmat, vlr->v3->co, ho3);
2378 if ((ma->material_type == MA_TYPE_WIRE) || (vlr->flag & R_STRAND)) {
2380 c4= zbuf_shadow_project(cache, vlr->v4->index, obwinmat, vlr->v4->co, ho4);
2381 zbufclipwire(&zspan, 0, a+1, vlr->ec, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
2384 zbufclipwire(&zspan, 0, a+1, vlr->ec, ho1, ho2, ho3, NULL, c1, c2, c3, 0);
2388 c4= zbuf_shadow_project(cache, vlr->v4->index, obwinmat, vlr->v4->co, ho4);
2389 zbufclip4(&zspan, 0, 0, ho1, ho2, ho3, ho4, c1, c2, c3, c4);
2392 zbufclip(&zspan, 0, 0, ho1, ho2, ho3, c1, c2, c3);
2396 if ((a & 255)==255 && re->test_break(re->tbh))
2401 if (obr->strandbuf) {
2402 /* for each bounding box containing a number of strands */
2403 sbound= obr->strandbuf->bound;
2404 for (c=0; c<obr->strandbuf->totbound; c++, sbound++) {
2405 if (clip_render_object(sbound->boundbox, NULL, obwinmat))
2408 /* for each strand in this bounding box */
2409 for (a=sbound->start; a<sbound->end; a++) {
2410 strand= RE_findOrAddStrand(obr, a);
2413 sseg.buffer= strand->buffer;
2414 sseg.sqadaptcos= sseg.buffer->adaptcos;
2415 sseg.sqadaptcos *= sseg.sqadaptcos;
2416 sseg.strand= strand;
2417 svert= strand->vert;
2419 /* note, these conditions are copied in shadowbuf_autoclip() */
2420 if (sseg.buffer->ma!= ma) {
2421 ma= sseg.buffer->ma;
2423 if ((ma->mode2 & MA_CASTSHADOW)==0 || (ma->mode & MA_SHADBUF)==0) ok= 0;
2426 if (ok && (sseg.buffer->lay & lay)) {
2427 zbuf_project_cache_clear(cache, strand->totvert);
2429 for (b=0; b<strand->totvert-1; b++, svert++) {
2430 sseg.v[0]= (b > 0)? (svert-1): svert;
2433 sseg.v[3]= (b < strand->totvert-2)? svert+2: svert+1;
2435 c1= zbuf_shadow_project(cache, sseg.v[0]-strand->vert, obwinmat, sseg.v[0]->co, ho1);
2436 c2= zbuf_shadow_project(cache, sseg.v[1]-strand->vert, obwinmat, sseg.v[1]->co, ho2);
2437 c3= zbuf_shadow_project(cache, sseg.v[2]-strand->vert, obwinmat, sseg.v[2]->co, ho3);
2438 c4= zbuf_shadow_project(cache, sseg.v[3]-strand->vert, obwinmat, sseg.v[3]->co, ho4);
2440 if (!(c1 & c2 & c3 & c4))
2441 render_strand_segment(re, winmat, NULL, &zspan, 1, &sseg);
2445 if ((a & 255)==255 && re->test_break(re->tbh))
2451 if (re->test_break(re->tbh))
2456 if (lar->buftype==LA_SHADBUF_HALFWAY) {
2457 for (a=size*size -1; a>=0; a--)
2458 rectz[a]= (rectz[a]>>1) + (zspan.rectz1[a]>>1);
2460 MEM_freeN(zspan.rectz1);
2463 zbuf_free_span(&zspan);
2466 static void zbuffill_sss(ZSpan *zspan, int obi, int zvlnr,
2467 const float *v1, const float *v2, const float *v3, const float *v4)
2469 double zxd, zyd, zy0, z;
2470 float x0, y0, x1, y1, x2, y2, z0, z1, z2, xx1, *span1, *span2;
2471 int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2;
2473 zbuf_init_span(zspan);
2476 zbuf_add_to_span(zspan, v1, v2);
2477 zbuf_add_to_span(zspan, v2, v3);
2479 zbuf_add_to_span(zspan, v3, v4);
2480 zbuf_add_to_span(zspan, v4, v1);
2483 zbuf_add_to_span(zspan, v3, v1);
2486 if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
2488 if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
2489 if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
2491 if (my2<my0) return;
2493 /* ZBUF DX DY, in floats still */
2505 if (z0==0.0f) return;
2507 xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
2508 zxd= -(double)x0/(double)z0;
2509 zyd= -(double)y0/(double)z0;
2510 zy0= ((double)my2)*zyd + (double)xx1;
2514 if (zspan->span1[sn1] < zspan->span2[sn1]) {
2515 span1= zspan->span1+my2;
2516 span2= zspan->span2+my2;
2519 span1= zspan->span2+my2;
2520 span2= zspan->span1+my2;
2523 for (y=my2; y>=my0; y--, span1--, span2--) {
2528 if (sn2>=rectx) sn2= rectx-1;
2531 z= (double)sn1*zxd + zy0;
2533 for (x= sn1; x<=sn2; x++, z+=zxd)
2534 zspan->sss_func(zspan->sss_handle, obi, zvlnr, x, y, z);
2540 void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(void *, int, int, int, int, int))
2542 ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE];
2544 ObjectInstanceRen *obi;
2547 VertRen *v1, *v2, *v3, *v4;
2548 Material *ma = NULL, *sss_ma = R.sss_mat;
2549 float obwinmat[4][4], winmat[4][4], bounds[4];
2550 float ho1[4], ho2[4], ho3[4], ho4[4]={0};
2551 int i, v, zvlnr, c1, c2, c3, c4=0;
2552 short nofill=0, env=0, wire=0;
2554 zbuf_make_winmat(&R, winmat);
2555 zbuffer_part_bounds(R.winx, R.winy, pa, bounds);
2556 zbuf_alloc_span(&zspan, pa->rectx, pa->recty, R.clipcrop);
2558 zspan.sss_handle= handle;
2559 zspan.sss_func= func;
2561 /* needed for transform from hoco to zbuffer co */
2562 zspan.zmulx= ((float)R.winx)/2.0f;
2563 zspan.zmuly= ((float)R.winy)/2.0f;
2565 /* -0.5f to center the sample position */
2566 zspan.zofsx= -pa->disprect.xmin - 0.5f;
2567 zspan.zofsy= -pa->disprect.ymin - 0.5f;
2569 /* filling methods */
2570 zspan.zbuffunc= zbuffill_sss;
2572 /* fill front and back zbuffer */
2574 fillrect(pa->recto, pa->rectx, pa->recty, 0);
2575 fillrect(pa->rectp, pa->rectx, pa->recty, 0);
2576 fillrect(pa->rectz, pa->rectx, pa->recty, 0x7FFFFFFF);
2578 if (pa->rectbackz) {
2579 fillrect(pa->rectbacko, pa->rectx, pa->recty, 0);
2580 fillrect(pa->rectbackp, pa->rectx, pa->recty, 0);
2581 fillrect(pa->rectbackz, pa->rectx, pa->recty, -0x7FFFFFFF);
2584 for (i=0, obi=R.instancetable.first; obi; i++, obi=obi->next) {
2587 if (!(obi->lay & lay))
2590 if (obi->flag & R_TRANSFORMED)
2591 mul_m4_m4m4(obwinmat, winmat, obi->mat);
2593 copy_m4_m4(obwinmat, winmat);
2595 if (clip_render_object(obi->obr->boundbox, bounds, obwinmat))
2598 zbuf_project_cache_clear(cache, obr->totvert);
2600 for (v=0; v<obr->totvlak; v++) {
2601 if ((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak;
2604 if (material_in_material(vlr->mat, sss_ma)) {
2605 /* three cases, visible for render, only z values and nothing */
2606 if (obi->lay & lay) {
2609 nofill= ma->mode & MA_ONLYCAST;
2610 env= (ma->mode & MA_ENV);
2611 wire= (ma->material_type == MA_TYPE_WIRE);
2616 ma= NULL; /* otherwise nofill can hang */
2619 if (nofill==0 && wire==0 && env==0) {
2620 unsigned short partclip;
2627 c1= zbuf_part_project(cache, v1->index, obwinmat, bounds, v1->co, ho1);
2628 c2= zbuf_part_project(cache, v2->index, obwinmat, bounds, v2->co, ho2);
2629 c3= zbuf_part_project(cache, v3->index, obwinmat, bounds, v3->co, ho3);
2631 /* partclipping doesn't need viewplane clipping */
2632 partclip= c1 & c2 & c3;
2634 c4= zbuf_part_project(cache, v4->index, obwinmat, bounds, v4->co, ho4);
2644 zbufclip(&zspan, i, zvlnr, ho1, ho2, ho3, c1, c2, c3);
2647 zbufclip(&zspan, i, zvlnr+RE_QUAD_OFFS, ho1, ho3, ho4, c1, c3, c4);
2655 zbuf_free_span(&zspan);
2658 /* ******************** VECBLUR ACCUM BUF ************************* */
2660 typedef struct DrawBufPixel {
2666 static void zbuf_fill_in_rgba(ZSpan *zspan, DrawBufPixel *col, float *v1, float *v2, float *v3, float *v4)
2668 DrawBufPixel *rectpofs, *rp;
2669 double zxd, zyd, zy0, zverg;
2671 float x1, y1, z1, x2, y2, z2, xx1;
2672 float *span1, *span2;
2673 float *rectzofs, *rz;
2675 int sn1, sn2, rectx, my0, my2;
2678 zbuf_init_span(zspan);
2681 zbuf_add_to_span(zspan, v1, v2);
2682 zbuf_add_to_span(zspan, v2, v3);
2683 zbuf_add_to_span(zspan, v3, v4);
2684 zbuf_add_to_span(zspan, v4, v1);
2687 if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
2689 if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
2690 if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
2692 // printf("my %d %d\n", my0, my2);
2693 if (my2<my0) return;
2695 /* ZBUF DX DY, in floats still */
2706 if (z0==0.0f) return;
2708 xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
2710 zxd= -(double)x0/(double)z0;
2711 zyd= -(double)y0/(double)z0;
2712 zy0= ((double)my2)*zyd + (double)xx1;
2714 /* start-offset in rect */
2715 rectx= zspan->rectx;
2716 rectzofs= (float *)(zspan->rectz + rectx*my2);
2717 rectpofs= ((DrawBufPixel *)zspan->rectp) + rectx*my2;
2721 if (zspan->span1[sn1] < zspan->span2[sn1]) {
2722 span1= zspan->span1+my2;
2723 span2= zspan->span2+my2;
2726 span1= zspan->span2+my2;
2727 span2= zspan->span1+my2;
2730 for (y=my2; y>=my0; y--, span1--, span2--) {
2736 if (sn2>=rectx) sn2= rectx-1;
2740 zverg= (double)sn1*zxd + zy0;
2746 if (zverg < (double)*rz) {
2763 /* char value==255 is filled in, rest should be zero */
2764 /* returns alpha values, but sets alpha to 1 for zero alpha pixels that have an alpha value as neighbor */
2765 void antialias_tagbuf(int xsize, int ysize, char *rectmove)
2767 char *row1, *row2, *row3;
2771 /* 1: tag pixels to be candidate for AA */
2772 for (y=2; y<ysize; y++) {
2774 row1= rectmove + (y-2)*xsize;
2777 for (x=2; x<xsize; x++, row1++, row2++, row3++) {
2779 if (row2[0]==0 || row2[2]==0 || row1[1]==0 || row3[1]==0)
2785 /* 2: evaluate horizontal scanlines and calculate alphas */
2787 for (y=0; y<ysize; y++) {
2789 for (x=1; x<xsize; x++, row1++) {
2790 if (row1[0]==128 && row1[1]==128) {
2791 /* find previous color and next color and amount of steps to blend */
2794 while (x+step<xsize && row1[step]==128)
2797 if (x+step!=xsize) {
2798 /* now we can blend values */
2801 /* note, prev value can be next value, but we do this loop to clear 128 then */
2802 for (a=0; a<step; a++) {
2805 fac= ((a+1)<<8)/(step+1);
2808 row1[a]= (prev*mfac + next*fac)>>8;
2815 /* 3: evaluate vertical scanlines and calculate alphas */
2816 /* use for reading a copy of the original tagged buffer */
2817 for (x=0; x<xsize; x++) {
2818 row1= rectmove + x+xsize;
2820 for (y=1; y<ysize; y++, row1+=xsize) {
2821 if (row1[0]==128 && row1[xsize]==128) {
2822 /* find previous color and next color and amount of steps to blend */
2825 while (y+step<ysize && row1[step*xsize]==128)
2828 if (y+step!=ysize) {
2829 /* now we can blend values */
2830 next= row1[step*xsize];
2831 /* note, prev value can be next value, but we do this loop to clear 128 then */
2832 for (a=0; a<step; a++) {
2835 fac= ((a+1)<<8)/(step+1);
2838 row1[a*xsize]= (prev*mfac + next*fac)>>8;
2845 /* last: pixels with 0 we fill in zbuffer, with 1 we skip for mask */
2846 for (y=2; y<ysize; y++) {
2848 row1= rectmove + (y-2)*xsize;
2851 for (x=2; x<xsize; x++, row1++, row2++, row3++) {
2853 if (row2[0]>1 || row2[2]>1 || row1[1]>1 || row3[1]>1)
2860 /* in: two vectors, first vector points from origin back in time, 2nd vector points to future */
2861 /* we make this into 3 points, center point is (0, 0) */
2862 /* and offset the center point just enough to make curve go through midpoint */
2864 static void quad_bezier_2d(float *result, float *v1, float *v2, float *ipodata)
2866 float p1[2], p2[2], p3[2];
2874 /* official formula 2*p2 - 0.5*p1 - 0.5*p3 */
2875 p2[0]= -0.5f*p1[0] - 0.5f*p3[0];
2876 p2[1]= -0.5f*p1[1] - 0.5f*p3[1];
2878 result[0]= ipodata[0]*p1[0] + ipodata[1]*p2[0] + ipodata[2]*p3[0];
2879 result[1]= ipodata[0]*p1[1] + ipodata[1]*p2[1] + ipodata[2]*p3[1];
2882 static void set_quad_bezier_ipo(float fac, float *data)
2884 float mfac= (1.0f-fac);
2887 data[1]= 2.0f*mfac*fac;
2891 void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float *newrect, float *imgrect, float *vecbufrect, float *zbufrect)
2894 DrawBufPixel *rectdraw, *dr;
2895 static float jit[256][2];
2896 float v1[3], v2[3], v3[3], v4[3], fx, fy;
2897 float *rectvz, *dvz, *dimg, *dvec1, *dvec2, *dz, *dz1, *dz2, *rectz;
2898 float *minvecbufrect= NULL, *rectweight, *rw, *rectmax, *rm, *ro;
2899 float maxspeedsq= (float)nbd->maxspeed*nbd->maxspeed;
2900 int y, x, step, maxspeed=nbd->maxspeed, samples= nbd->samples;
2902 static int firsttime= 1;
2903 char *rectmove, *dm;
2905 zbuf_alloc_span(&zspan, xsize, ysize, 1.0f);
2906 zspan.zmulx= ((float)xsize)/2.0f;
2907 zspan.zmuly= ((float)ysize)/2.0f;
2912 rectz= MEM_mapallocN(sizeof(float)*xsize*ysize, "zbuf accum");
2913 zspan.rectz= (int *)rectz;
2915 rectmove= MEM_mapallocN(xsize*ysize, "rectmove");
2916 rectdraw= MEM_mapallocN(sizeof(DrawBufPixel)*xsize*ysize, "rect draw");
2917 zspan.rectp= (int *)rectdraw;
2919 rectweight= MEM_mapallocN(sizeof(float)*xsize*ysize, "rect weight");
2920 rectmax= MEM_mapallocN(sizeof(float)*xsize*ysize, "rect max");
2922 /* debug... check if PASS_VECTOR_MAX still is in buffers */
2924 for (x= 4*xsize*ysize; x>0; x--, dvec1++) {
2925 if (dvec1[0]==PASS_VECTOR_MAX) {
2930 if (tsktsk) printf("Found uninitialized speed in vector buffer... fixed.\n");
2932 /* min speed? then copy speedbuffer to recalculate speed vectors */
2933 if (nbd->minspeed) {
2934 float minspeed= (float)nbd->minspeed;
2935 float minspeedsq= minspeed*minspeed;
2937 minvecbufrect= MEM_mapallocN(4*sizeof(float)*xsize*ysize, "minspeed buf");
2940 dvec2= minvecbufrect;
2941 for (x= 2*xsize*ysize; x>0; x--, dvec1+=2, dvec2+=2) {
2942 if (dvec1[0]==0.0f && dvec1[1]==0.0f) {
2947 float speedsq= dvec1[0]*dvec1[0] + dvec1[1]*dvec1[1];
2948 if (speedsq <= minspeedsq) {
2953 speedsq= 1.0f - minspeed/sqrt(speedsq);
2954 dvec2[0]= speedsq*dvec1[0];