4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * Contributors: Hos, RPW
24 * 2004-2006 Blender Foundation, full recode
26 * ***** END GPL LICENSE BLOCK *****
30 /*---------------------------------------------------------------------------*/
32 /*---------------------------------------------------------------------------*/
40 #include "BLI_blenlib.h"
41 #include "MTC_matrixops.h"
42 #include "MEM_guardedalloc.h"
44 #include "DNA_lamp_types.h"
45 #include "DNA_mesh_types.h"
46 #include "DNA_meshdata_types.h"
48 #include "BKE_global.h"
49 #include "BKE_utildefines.h"
51 #include "radio_types.h"
52 #include "radio.h" /* needs RG, some root data for radiosity */
54 #include "SDL_thread.h"
56 #include "RE_render_ext.h"
59 #include "render_types.h"
60 #include "renderpipeline.h"
61 #include "renderdatabase.h"
62 #include "rendercore.h"
63 #include "pixelblending.h"
68 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
69 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
70 /* only to be used here in this file, it's for speed */
71 extern struct Render R;
72 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
75 /* ****************** Spans ******************************* */
77 /* each zbuffer has coordinates transformed to local rect coordinates, so we can simply clip */
78 void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty)
80 memset(zspan, 0, sizeof(ZSpan));
85 zspan->span1= RE_mallocN(recty*sizeof(float), "zspan");
86 zspan->span2= RE_mallocN(recty*sizeof(float), "zspan");
89 static void zbuf_free_span(ZSpan *zspan)
92 if(zspan->span1) RE_freeN(zspan->span1);
93 if(zspan->span2) RE_freeN(zspan->span2);
94 zspan->span1= zspan->span2= NULL;
98 /* reset range for clipping */
99 static void zbuf_init_span(ZSpan *zspan)
101 zspan->miny1= zspan->miny2= zspan->recty+1;
102 zspan->maxy1= zspan->maxy2= -1;
103 zspan->minp1= zspan->maxp1= zspan->minp2= zspan->maxp2= NULL;
106 static void zbuf_add_to_span(ZSpan *zspan, float *v1, float *v2)
108 float *minv, *maxv, *span;
122 if(my2<0 || my0>= zspan->recty) return;
125 if(my2>=zspan->recty) my2= zspan->recty-1;
130 /* if(my0>my2) should still fill in, that way we get spans that skip nicely */
132 xx1= maxv[1]-minv[1];
133 if(xx1>FLT_EPSILON) {
134 dx0= (minv[0]-maxv[0])/xx1;
135 xs0= dx0*(minv[1]-my2) + minv[0];
139 xs0= MIN2(minv[0],maxv[0]);
143 if(zspan->maxp1 == NULL) {
146 else { /* does it complete left span? */
147 if( maxv == zspan->minp1 || minv==zspan->maxp1) {
155 if(span==zspan->span1) {
156 // printf("left span my0 %d my2 %d\n", my0, my2);
157 if(zspan->minp1==NULL || zspan->minp1[1] > minv[1] ) {
160 if(zspan->maxp1==NULL || zspan->maxp1[1] < maxv[1] ) {
163 if(my0<zspan->miny1) zspan->miny1= my0;
164 if(my2>zspan->maxy1) zspan->maxy1= my2;
167 // printf("right span my0 %d my2 %d\n", my0, my2);
168 if(zspan->minp2==NULL || zspan->minp2[1] > minv[1] ) {
171 if(zspan->maxp2==NULL || zspan->maxp2[1] < maxv[1] ) {
174 if(my0<zspan->miny2) zspan->miny2= my0;
175 if(my2>zspan->maxy2) zspan->maxy2= my2;
178 for(y=my2; y>=my0; y--, xs0+= dx0) {
179 /* xs0 is the xcoord! */
184 /*-----------------------------------------------------------*/
186 /*-----------------------------------------------------------*/
189 void fillrect(int *rect, int x, int y, int val)
202 /* based on Liang&Barsky, for clipping of pyramidical volume */
203 static short cliptestf(float p, float q, float *u1, float *u2)
212 else if(r>*u1) *u1=r;
221 else if(r<*u2) *u2=r;
224 else if(q<0.0) return 0;
229 int testclip(float *v)
231 float abs4; /* WATCH IT: this function should do the same as cliptestf, otherwise troubles in zbufclip()*/
234 /* if we set clip flags, the clipping should be at least larger than epsilon.
235 prevents issues with vertices lying exact on borders */
236 abs4= fabs(v[3]) + FLT_EPSILON;
238 if(v[2]< -abs4) c=16; /* this used to be " if(v[2]<0) ", see clippz() */
239 else if(v[2]> abs4) c+= 32;
242 else if( v[0]< -abs4) c+=1;
245 else if( v[1]< -abs4) c+=8;
252 /* ************* ACCUMULATION ZBUF ************ */
255 static APixstr *addpsmainA(ListBase *lb)
259 psm= RE_mallocN(sizeof(APixstrMain), "addpsmainA");
260 BLI_addtail(lb, psm);
261 psm->ps= RE_mallocN(4096*sizeof(APixstr),"pixstr");
266 static void freepsA(ListBase *lb)
268 APixstrMain *psm, *psmnext;
270 for(psm= lb->first; psm; psm= psmnext) {
278 static APixstr *addpsA(ZSpan *zspan)
281 if(zspan->apsmcounter==0) {
282 zspan->curpstr= addpsmainA(zspan->apsmbase);
283 zspan->apsmcounter= 4095;
287 zspan->apsmcounter--;
289 return zspan->curpstr;
292 static void zbufinvulAc4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4)
294 APixstr *ap, *apofs, *apn;
295 double zxd, zyd, zy0, zverg;
297 float x1,y1,z1,x2,y2,z2,xx1;
298 float *span1, *span2;
300 int sn1, sn2, rectx, *rectzofs, my0, my2, mask;
303 zbuf_init_span(zspan);
306 zbuf_add_to_span(zspan, v1, v2);
307 zbuf_add_to_span(zspan, v2, v3);
309 zbuf_add_to_span(zspan, v3, v4);
310 zbuf_add_to_span(zspan, v4, v1);
313 zbuf_add_to_span(zspan, v3, v1);
316 if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
318 if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
319 if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
323 /* ZBUF DX DY, in floats still */
336 xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
338 zxd= -(double)x0/(double)z0;
339 zyd= -(double)y0/(double)z0;
340 zy0= ((double)my2)*zyd + (double)xx1;
342 /* start-offset in rect */
344 rectzofs= (int *)(zspan->arectz+rectx*(my2));
345 apofs= (zspan->apixbuf+ rectx*(my2));
350 if(zspan->span1[sn1] < zspan->span2[sn1]) {
351 span1= zspan->span1+my2;
352 span2= zspan->span2+my2;
355 span1= zspan->span2+my2;
356 span2= zspan->span1+my2;
359 for(y=my2; y>=my0; y--, span1--, span2--) {
365 if(sn2>=rectx) sn2= rectx-1;
369 zverg= (double)sn1*zxd + zy0;
374 zverg-= zspan->polygon_offset;
377 if( (int)zverg < *rz) {
382 if(apn->p[0]==0) {apn->p[0]= zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; }
383 if(apn->p[0]==zvlnr) {apn->mask[0]|= mask; break; }
384 if(apn->p[1]==0) {apn->p[1]= zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; }
385 if(apn->p[1]==zvlnr) {apn->mask[1]|= mask; break; }
386 if(apn->p[2]==0) {apn->p[2]= zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; }
387 if(apn->p[2]==zvlnr) {apn->mask[2]|= mask; break; }
388 if(apn->p[3]==0) {apn->p[3]= zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; }
389 if(apn->p[3]==zvlnr) {apn->mask[3]|= mask; break; }
390 // if(apn->p[i]==0) {apn->p[i]= zvlnr; apn->z[i]= zverg; apn->mask[i]= mask; break; }
391 // if(apn->p[i]==zvlnr) {apn->mask[i]|= mask; break; }
392 if(apn->next==NULL) apn->next= addpsA(zspan);
411 static void zbuflineAc(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
415 int start, end, x, y, oldx, oldy, ofs;
416 int dz, vergz, mask, maxtest=0;
425 if(fabs(dx) > fabs(dy)) {
427 /* all lines from left to right */
428 if(vec1[0]<vec2[0]) {
439 end= start+floor(dx);
440 if(end>=zspan->rectx) end= zspan->rectx-1;
446 vergz-= zspan->polygon_offset;
447 dz= (v2[2]-v1[2])/dx;
448 if(vergz>0x50000000 && dz>0) maxtest= 1; // prevent overflow
450 rectz= (int *)(zspan->arectz+zspan->rectx*(oldy) +start);
451 ap= (zspan->apixbuf+ zspan->rectx*(oldy) +start);
453 if(dy<0) ofs= -zspan->rectx;
454 else ofs= zspan->rectx;
456 for(x= start; x<=end; x++, rectz++, ap++) {
465 if(x>=0 && y>=0 && y<zspan->recty) {
469 while(apn) { /* loop unrolled */
470 if(apn->p[0]==0) {apn->p[0]= zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; }
471 if(apn->p[0]==zvlnr) {apn->mask[0]|= mask; break; }
472 if(apn->p[1]==0) {apn->p[1]= zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; }
473 if(apn->p[1]==zvlnr) {apn->mask[1]|= mask; break; }
474 if(apn->p[2]==0) {apn->p[2]= zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; }
475 if(apn->p[2]==zvlnr) {apn->mask[2]|= mask; break; }
476 if(apn->p[3]==0) {apn->p[3]= zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; }
477 if(apn->p[3]==zvlnr) {apn->mask[3]|= mask; break; }
478 if(apn->next==0) apn->next= addpsA(zspan);
486 if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
492 /* all lines from top to bottom */
493 if(vec1[1]<vec2[1]) {
504 end= start+floor(dy);
506 if(start>=zspan->recty || end<0) return;
508 if(end>=zspan->recty) end= zspan->recty-1;
514 vergz-= zspan->polygon_offset;
515 dz= (v2[2]-v1[2])/dy;
516 if(vergz>0x50000000 && dz>0) maxtest= 1; // prevent overflow
518 rectz= (int *)( zspan->arectz+ (start)*zspan->rectx+ oldx );
519 ap= (zspan->apixbuf+ zspan->rectx*(start) +oldx);
524 for(y= start; y<=end; y++, rectz+=zspan->rectx, ap+=zspan->rectx) {
533 if(x>=0 && y>=0 && x<zspan->rectx) {
537 while(apn) { /* loop unrolled */
538 if(apn->p[0]==0) {apn->p[0]= zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; }
539 if(apn->p[0]==zvlnr) {apn->mask[0]|= mask; break; }
540 if(apn->p[1]==0) {apn->p[1]= zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; }
541 if(apn->p[1]==zvlnr) {apn->mask[1]|= mask; break; }
542 if(apn->p[2]==0) {apn->p[2]= zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; }
543 if(apn->p[2]==zvlnr) {apn->mask[2]|= mask; break; }
544 if(apn->p[3]==0) {apn->p[3]= zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; }
545 if(apn->p[3]==zvlnr) {apn->mask[3]|= mask; break; }
546 if(apn->next==0) apn->next= addpsA(zspan);
554 if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
560 /* ************* NORMAL ZBUFFER ************ */
562 static void zbufline(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
565 int start, end, x, y, oldx, oldy, ofs;
566 int dz, vergz, maxtest= 0;
573 if(fabs(dx) > fabs(dy)) {
575 /* all lines from left to right */
576 if(vec1[0]<vec2[0]) {
587 end= start+floor(dx);
588 if(end>=zspan->rectx) end= zspan->rectx-1;
594 dz= floor((v2[2]-v1[2])/dx);
595 if(vergz>0x50000000 && dz>0) maxtest= 1; // prevent overflow
597 rectz= zspan->rectz + oldy*zspan->rectx+ start;
598 rectp= zspan->rectp + oldy*zspan->rectx+ start;
600 if(dy<0) ofs= -zspan->rectx;
601 else ofs= zspan->rectx;
603 for(x= start; x<=end; x++, rectz++, rectp++) {
612 if(x>=0 && y>=0 && y<zspan->recty) {
621 if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
626 /* all lines from top to bottom */
627 if(vec1[1]<vec2[1]) {
638 end= start+floor(dy);
640 if(end>=zspan->recty) end= zspan->recty-1;
646 dz= floor((v2[2]-v1[2])/dy);
647 if(vergz>0x50000000 && dz>0) maxtest= 1; // prevent overflow
649 rectz= zspan->rectz + start*zspan->rectx+ oldx;
650 rectp= zspan->rectp + start*zspan->rectx+ oldx;
655 for(y= start; y<=end; y++, rectz+=zspan->rectx, rectp+=zspan->rectx) {
664 if(x>=0 && y>=0 && x<zspan->rectx) {
672 if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
678 static void zbufline_onlyZ(ZSpan *zspan, int zvlnr, float *vec1, float *vec2)
681 int start, end, x, y, oldx, oldy, ofs;
682 int dz, vergz, maxtest= 0;
689 if(fabs(dx) > fabs(dy)) {
691 /* all lines from left to right */
692 if(vec1[0]<vec2[0]) {
703 end= start+floor(dx);
704 if(end>=zspan->rectx) end= zspan->rectx-1;
710 dz= floor((v2[2]-v1[2])/dx);
711 if(vergz>0x50000000 && dz>0) maxtest= 1; // prevent overflow
713 rectz= zspan->rectz + oldy*zspan->rectx+ start;
715 if(dy<0) ofs= -zspan->rectx;
716 else ofs= zspan->rectx;
718 for(x= start; x<=end; x++, rectz++) {
726 if(x>=0 && y>=0 && y<zspan->recty) {
734 if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
739 /* all lines from top to bottom */
740 if(vec1[1]<vec2[1]) {
751 end= start+floor(dy);
753 if(end>=zspan->recty) end= zspan->recty-1;
759 dz= floor((v2[2]-v1[2])/dy);
760 if(vergz>0x50000000 && dz>0) maxtest= 1; // prevent overflow
762 rectz= zspan->rectz + start*zspan->rectx+ oldx;
767 for(y= start; y<=end; y++, rectz+=zspan->rectx) {
775 if(x>=0 && y>=0 && x<zspan->rectx) {
782 if(maxtest && (vergz > 0x7FFFFFF0 - dz)) vergz= 0x7FFFFFF0;
789 static int clipline(float *v1, float *v2) /* return 0: do not draw */
791 float dz,dw, u1=0.0, u2=1.0;
797 /* this 1.01 is for clipping x and y just a tinsy larger. that way it is
798 filled in with zbufwire correctly when rendering in parts. otherwise
799 you see line endings at edges... */
801 if(cliptestf(-dz-dw, v1[3]+v1[2], &u1,&u2)) {
802 if(cliptestf(dz-dw, v1[3]-v1[2], &u1,&u2)) {
805 dz= 1.01*(v2[3]-v1[3]);
808 if(cliptestf(-dx-dz, v1[0]+v13, &u1,&u2)) {
809 if(cliptestf(dx-dz, v13-v1[0], &u1,&u2)) {
813 if(cliptestf(-dy-dz, v1[1]+v13, &u1,&u2)) {
814 if(cliptestf(dy-dz, v13-v1[1], &u1,&u2)) {
839 static void hoco_to_zco(ZSpan *zspan, float *zco, float *hoco)
844 zco[0]= zspan->zmulx*(1.0+hoco[0]*div) + zspan->zofsx;
845 zco[1]= zspan->zmuly*(1.0+hoco[1]*div) + zspan->zofsy;
846 zco[2]= 0x7FFFFFFF *(hoco[2]*div);
849 void zbufclipwire(ZSpan *zspan, int zvlnr, VlakRen *vlr)
851 float vez[20], *f1, *f2, *f3, *f4= 0;
852 int c1, c2, c3, c4, ec, and, or;
854 /* edgecode: 1= draw */
869 and= (c1 & c2 & c3 & c4);
870 or= (c1 | c2 | c3 | c4);
877 if(or) { /* not in the middle */
878 if(and) { /* out completely */
881 else { /* clipping */
886 if( clipline(vez, vez+4)) {
887 hoco_to_zco(zspan, vez, vez);
888 hoco_to_zco(zspan, vez+4, vez+4);
889 zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4);
895 if( clipline(vez, vez+4)) {
896 hoco_to_zco(zspan, vez, vez);
897 hoco_to_zco(zspan, vez+4, vez+4);
898 zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4);
905 if( clipline(vez, vez+4)) {
906 hoco_to_zco(zspan, vez, vez);
907 hoco_to_zco(zspan, vez+4, vez+4);
908 zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4);
914 if( clipline(vez, vez+4)) {
915 hoco_to_zco(zspan, vez, vez);
916 hoco_to_zco(zspan, vez+4, vez+4);
917 zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4);
925 if( clipline(vez, vez+4)) {
926 hoco_to_zco(zspan, vez, vez);
927 hoco_to_zco(zspan, vez+4, vez+4);
928 zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4);
937 hoco_to_zco(zspan, vez, f1);
938 hoco_to_zco(zspan, vez+4, f2);
939 hoco_to_zco(zspan, vez+8, f3);
941 hoco_to_zco(zspan, vez+12, f4);
943 if(ec & ME_V3V4) zspan->zbuflinefunc(zspan, zvlnr, vez+8, vez+12);
944 if(ec & ME_V4V1) zspan->zbuflinefunc(zspan, zvlnr, vez+12, vez);
947 if(ec & ME_V3V1) zspan->zbuflinefunc(zspan, zvlnr, vez+8, vez);
950 if(ec & ME_V1V2) zspan->zbuflinefunc(zspan, zvlnr, vez, vez+4);
951 if(ec & ME_V2V3) zspan->zbuflinefunc(zspan, zvlnr, vez+4, vez+8);
956 * Fill the z buffer, but invert z order, and add the face index to
957 * the corresponing face buffer.
959 * This is one of the z buffer fill functions called in zbufclip() and
962 * @param v1 [4 floats, world coordinates] first vertex
963 * @param v2 [4 floats, world coordinates] second vertex
964 * @param v3 [4 floats, world coordinates] third vertex
966 static void zbufinvulGLinv4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4)
968 double zxd, zyd, zy0, zverg;
970 float x1,y1,z1,x2,y2,z2,xx1;
971 float *span1, *span2;
974 int sn1, sn2, rectx, *rectzofs, my0, my2;
977 zbuf_init_span(zspan);
980 zbuf_add_to_span(zspan, v1, v2);
981 zbuf_add_to_span(zspan, v2, v3);
983 zbuf_add_to_span(zspan, v3, v4);
984 zbuf_add_to_span(zspan, v4, v1);
987 zbuf_add_to_span(zspan, v3, v1);
990 if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
992 if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
993 if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
995 // printf("my %d %d\n", my0, my2);
999 /* ZBUF DX DY, in floats still */
1012 xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
1014 zxd= -(double)x0/(double)z0;
1015 zyd= -(double)y0/(double)z0;
1016 zy0= ((double)my2)*zyd + (double)xx1;
1018 /* start-offset in rect */
1019 rectx= zspan->rectx;
1020 rectzofs= (zspan->rectz+rectx*my2);
1021 rectpofs= (zspan->rectp+rectx*my2);
1025 if(zspan->span1[sn1] < zspan->span2[sn1]) {
1026 span1= zspan->span1+my2;
1027 span2= zspan->span2+my2;
1030 span1= zspan->span2+my2;
1031 span2= zspan->span1+my2;
1034 for(y=my2; y>=my0; y--, span1--, span2--) {
1040 if(sn2>=rectx) sn2= rectx-1;
1044 zverg= (double)sn1*zxd + zy0;
1050 if( (int)zverg > *rz || *rz==0x7FFFFFFF) {
1067 /* uses spanbuffers */
1069 static void zbufinvulGL4(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4)
1071 double zxd, zyd, zy0, zverg;
1073 float x1,y1,z1,x2,y2,z2,xx1;
1074 float *span1, *span2;
1077 int sn1, sn2, rectx, *rectzofs, my0, my2;
1080 zbuf_init_span(zspan);
1083 zbuf_add_to_span(zspan, v1, v2);
1084 zbuf_add_to_span(zspan, v2, v3);
1086 zbuf_add_to_span(zspan, v3, v4);
1087 zbuf_add_to_span(zspan, v4, v1);
1090 zbuf_add_to_span(zspan, v3, v1);
1093 if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
1095 if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
1096 if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
1098 // printf("my %d %d\n", my0, my2);
1102 /* ZBUF DX DY, in floats still */
1115 xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
1117 zxd= -(double)x0/(double)z0;
1118 zyd= -(double)y0/(double)z0;
1119 zy0= ((double)my2)*zyd + (double)xx1;
1121 /* start-offset in rect */
1122 rectx= zspan->rectx;
1123 rectzofs= (zspan->rectz+rectx*my2);
1124 rectpofs= (zspan->rectp+rectx*my2);
1128 if(zspan->span1[sn1] < zspan->span2[sn1]) {
1129 span1= zspan->span1+my2;
1130 span2= zspan->span2+my2;
1133 span1= zspan->span2+my2;
1134 span2= zspan->span1+my2;
1137 for(y=my2; y>=my0; y--, span1--, span2--) {
1143 if(sn2>=rectx) sn2= rectx-1;
1147 zverg= (double)sn1*zxd + zy0;
1153 if( (int)zverg < *rz) {
1171 * Fill the z buffer. The face buffer is not operated on!
1173 * This is one of the z buffer fill functions called in zbufclip() and
1176 * @param v1 [4 floats, world coordinates] first vertex
1177 * @param v2 [4 floats, world coordinates] second vertex
1178 * @param v3 [4 floats, world coordinates] third vertex
1181 static void zbufinvulGL_onlyZ(ZSpan *zspan, int zvlnr, float *v1, float *v2, float *v3, float *v4)
1183 double zxd, zyd, zy0, zverg;
1185 float x1,y1,z1,x2,y2,z2,xx1;
1186 float *span1, *span2;
1188 int sn1, sn2, rectx, *rectzofs, my0, my2;
1191 zbuf_init_span(zspan);
1194 zbuf_add_to_span(zspan, v1, v2);
1195 zbuf_add_to_span(zspan, v2, v3);
1197 zbuf_add_to_span(zspan, v3, v4);
1198 zbuf_add_to_span(zspan, v4, v1);
1201 zbuf_add_to_span(zspan, v3, v1);
1204 if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
1206 if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
1207 if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
1209 // printf("my %d %d\n", my0, my2);
1213 /* ZBUF DX DY, in floats still */
1226 xx1= (x0*v1[0] + y0*v1[1])/z0 + v1[2];
1228 zxd= -(double)x0/(double)z0;
1229 zyd= -(double)y0/(double)z0;
1230 zy0= ((double)my2)*zyd + (double)xx1;
1232 /* start-offset in rect */
1233 rectx= zspan->rectx;
1234 rectzofs= (zspan->rectz+rectx*my2);
1238 if(zspan->span1[sn1] < zspan->span2[sn1]) {
1239 span1= zspan->span1+my2;
1240 span2= zspan->span2+my2;
1243 span1= zspan->span2+my2;
1244 span2= zspan->span1+my2;
1247 for(y=my2; y>=my0; y--, span1--, span2--) {
1253 if(sn2>=rectx) sn2= rectx-1;
1257 zverg= (double)sn1*zxd + zy0;
1262 if( (int)zverg < *rz) {
1279 * Sets labda: flag, and parametrize the clipping of vertices in
1280 * viewspace coordinates. labda = -1 means no clipping, labda in [0,
1281 * 1] means a clipping.
1282 * Note: uses globals.
1283 * @param v1 start coordinate s
1284 * @param v2 target coordinate t
1288 * @param a index for coordinate (x, y, or z)
1291 static void clippyra(float *labda, float *v1, float *v2, int *b2, int *b3, int a)
1293 float da,db,u1=0.0,u2=1.0;
1301 /* according the original article by Liang&Barsky, for clipping of
1302 * homogenous coordinates with viewplane, the value of "0" is used instead of "-w" .
1303 * This differs from the other clipping cases (like left or top) and I considered
1304 * it to be not so 'homogenic'. But later it has proven to be an error,
1305 * who would have thought that of L&B!
1308 if(cliptestf(-da-db, v1[3]+v1[a], &u1,&u2)) {
1309 if(cliptestf(da-db, v1[3]-v1[a], &u1,&u2)) {
1315 else labda[1]=1.0; /* u2 */
1319 } else labda[0]=0.0;
1325 * (make vertex pyramide clip)
1326 * Checks labda and uses this to make decision about clipping the line
1327 * segment from v1 to v2. labda is the factor by which the vector is
1328 * cut. ( calculate s + l * ( t - s )). The result is appended to the
1329 * vertex list of this face.
1332 * @param v1 start coordinate s
1333 * @param v2 target coordinate t
1336 * @param clve vertex vector.
1339 static void makevertpyra(float *vez, float *labda, float **trias, float *v1, float *v2, int *b1, int *clve)
1351 adr[0]= v1[0]+l1*(v2[0]-v1[0]);
1352 adr[1]= v1[1]+l1*(v2[1]-v1[1]);
1353 adr[2]= v1[2]+l1*(v2[2]-v1[2]);
1354 adr[3]= v1[3]+l1*(v2[3]-v1[3]);
1356 else trias[*b1]= v1;
1365 adr[0]= v1[0]+l2*(v2[0]-v1[0]);
1366 adr[1]= v1[1]+l2*(v2[1]-v1[1]);
1367 adr[2]= v1[2]+l2*(v2[2]-v1[2]);
1368 adr[3]= v1[3]+l2*(v2[3]-v1[3]);
1374 /* ------------------------------------------------------------------------- */
1376 void projectverto(float *v1, float winmat[][4], float *adr)
1378 /* calcs homogenic coord of vertex v1 */
1384 adr[0]= x*winmat[0][0] + z*winmat[2][0] + winmat[3][0];
1385 adr[1]= y*winmat[1][1] + z*winmat[2][1] + winmat[3][1];
1386 adr[2]= z*winmat[2][2] + winmat[3][2];
1387 adr[3]= z*winmat[2][3] + winmat[3][3];
1389 //printf("hoco %f %f %f %f\n", adr[0], adr[1], adr[2], adr[3]);
1392 /* ------------------------------------------------------------------------- */
1394 void projectvert(float *v1, float winmat[][4], float *adr)
1396 /* calcs homogenic coord of vertex v1 */
1402 adr[0]= x*winmat[0][0]+ y*winmat[1][0]+ z*winmat[2][0]+ winmat[3][0];
1403 adr[1]= x*winmat[0][1]+ y*winmat[1][1]+ z*winmat[2][1]+ winmat[3][1];
1404 adr[2]= x*winmat[0][2]+ y*winmat[1][2]+ z*winmat[2][2]+ winmat[3][2];
1405 adr[3]= x*winmat[0][3]+ y*winmat[1][3]+ z*winmat[2][3]+ winmat[3][3];
1408 /* do zbuffering and clip, f1 f2 f3 are hocos, c1 c2 c3 are clipping flags */
1410 void zbufclip(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1, int c2, int c3)
1412 float *vlzp[32][3], labda[3][2];
1413 float vez[400], *trias[40];
1415 if(c1 | c2 | c3) { /* not in middle */
1416 if(c1 & c2 & c3) { /* completely out */
1418 } else { /* clipping */
1419 int arg, v, b, clipflag[3], b1, b2, b3, c4, clve=3, clvlo, clvl=1;
1421 vez[0]= f1[0]; vez[1]= f1[1]; vez[2]= f1[2]; vez[3]= f1[3];
1422 vez[4]= f2[0]; vez[5]= f2[1]; vez[6]= f2[2]; vez[7]= f2[3];
1423 vez[8]= f3[0]; vez[9]= f3[1]; vez[10]= f3[2];vez[11]= f3[3];
1429 clipflag[0]= ( (c1 & 48) | (c2 & 48) | (c3 & 48) );
1430 if(clipflag[0]==0) { /* othwerwise it needs to be calculated again, after the first (z) clip */
1431 clipflag[1]= ( (c1 & 3) | (c2 & 3) | (c3 & 3) );
1432 clipflag[2]= ( (c1 & 12) | (c2 & 12) | (c3 & 12) );
1441 for(v=0; v<clvlo; v++) {
1443 if(vlzp[v][0]!=0) { /* face is still there */
1444 b2= b3 =0; /* clip flags */
1447 else if (b==1) arg= 0;
1450 clippyra(labda[0], vlzp[v][0],vlzp[v][1], &b2,&b3, arg);
1451 clippyra(labda[1], vlzp[v][1],vlzp[v][2], &b2,&b3, arg);
1452 clippyra(labda[2], vlzp[v][2],vlzp[v][0], &b2,&b3, arg);
1454 if(b2==0 && b3==1) {
1455 /* completely 'in' */;
1458 /* completely 'out' */;
1461 makevertpyra(vez, labda[0], trias, vlzp[v][0],vlzp[v][1], &b1,&clve);
1462 makevertpyra(vez, labda[1], trias, vlzp[v][1],vlzp[v][2], &b1,&clve);
1463 makevertpyra(vez, labda[2], trias, vlzp[v][2],vlzp[v][0], &b1,&clve);
1465 /* after front clip done: now set clip flags */
1467 clipflag[1]= clipflag[2]= 0;
1469 for(b3=0; b3<clve; b3++) {
1471 clipflag[1] |= (c4 & 3);
1472 clipflag[2] |= (c4 & 12);
1479 for(b3=3; b3<=b1; b3++) {
1480 vlzp[clvl][0]= trias[0];
1481 vlzp[clvl][1]= trias[b3-2];
1482 vlzp[clvl][2]= trias[b3-1];
1492 /* warning, this should never happen! */
1493 if(clve>38 || clvl>31) printf("clip overflow: clve clvl %d %d\n",clve,clvl);
1495 /* perspective division */
1497 for(c1=0;c1<clve;c1++) {
1498 hoco_to_zco(zspan, f1, f1);
1501 for(b=1;b<clvl;b++) {
1503 zspan->zbuffunc(zspan, zvlnr, vlzp[b][0],vlzp[b][1],vlzp[b][2], NULL);
1510 /* perspective division: HCS to ZCS */
1511 hoco_to_zco(zspan, vez, f1);
1512 hoco_to_zco(zspan, vez+4, f2);
1513 hoco_to_zco(zspan, vez+8, f3);
1515 zspan->zbuffunc(zspan, zvlnr, vez,vez+4,vez+8, NULL);
1518 static void zbufclip4(ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, float *f4, int c1, int c2, int c3, int c4)
1522 if(c1 | c2 | c3 | c4) { /* not in middle */
1523 if(c1 & c2 & c3 & c4) { /* completely out */
1525 } else { /* clipping */
1526 zbufclip(zspan, zvlnr, f1, f2, f3, c1, c2, c3);
1527 zbufclip(zspan, zvlnr, f1, f3, f4, c1, c3, c4);
1532 /* perspective division: HCS to ZCS */
1533 hoco_to_zco(zspan, vez, f1);
1534 hoco_to_zco(zspan, vez+4, f2);
1535 hoco_to_zco(zspan, vez+8, f3);
1536 hoco_to_zco(zspan, vez+12, f4);
1538 zspan->zbuffunc(zspan, zvlnr, vez, vez+4, vez+8, vez+12);
1542 /* ***************** ZBUFFER MAIN ROUTINES **************** */
1544 void set_part_zbuf_clipflag(RenderPart *pa)
1547 float minx, miny, maxx, maxy, wco;
1548 unsigned short clipclear;
1551 minx= (2*pa->disprect.xmin - R.winx-1)/(float)R.winx;
1552 maxx= (2*pa->disprect.xmax - R.winx+1)/(float)R.winx;
1553 miny= (2*pa->disprect.ymin - R.winy-1)/(float)R.winy;
1554 maxy= (2*pa->disprect.ymax - R.winy+1)/(float)R.winy;
1556 /* supports up to 4 threads this way */
1557 clipclear= ~(15 << 4*(pa->thread & 3));
1559 for(v=0; v<R.totvert; v++) {
1560 if((v & 255)==0) ver= RE_findOrAddVert(&R, v);
1564 ver->flag &= clipclear;
1566 switch(pa->thread & 3) {
1568 if( ver->ho[0] > maxx*wco) ver->flag |= 1;
1569 else if( ver->ho[0]< minx*wco) ver->flag |= 2;
1570 if( ver->ho[1] > maxy*wco) ver->flag |= 4;
1571 else if( ver->ho[1]< miny*wco) ver->flag |= 8;
1574 if( ver->ho[0] > maxx*wco) ver->flag |= 16;
1575 else if( ver->ho[0]< minx*wco) ver->flag |= 32;
1576 if( ver->ho[1] > maxy*wco) ver->flag |= 64;
1577 else if( ver->ho[1]< miny*wco) ver->flag |= 128;
1580 if( ver->ho[0] > maxx*wco) ver->flag |= 256;
1581 else if( ver->ho[0]< minx*wco) ver->flag |= 512;
1582 if( ver->ho[1] > maxy*wco) ver->flag |= 1024;
1583 else if( ver->ho[1]< miny*wco) ver->flag |= 2048;
1586 if( ver->ho[0] > maxx*wco) ver->flag |= 4096;
1587 else if( ver->ho[0]< minx*wco) ver->flag |= 8192;
1588 if( ver->ho[1] > maxy*wco) ver->flag |= 16384;
1589 else if( ver->ho[1]< miny*wco) ver->flag |= 32768;
1595 void zbuffer_solid(RenderPart *pa)
1601 unsigned short clipmask;
1602 short transp=0, env=0, wire=0;
1604 zbuf_alloc_span(&zspan, pa->rectx, pa->recty);
1606 /* needed for transform from hoco to zbuffer co */
1607 zspan.zmulx= ((float)R.winx)/2.0;
1608 zspan.zmuly= ((float)R.winy)/2.0;
1610 zspan.zofsx= -pa->disprect.xmin - R.jit[pa->sample][0];
1611 zspan.zofsy= -pa->disprect.ymin - R.jit[pa->sample][1];
1614 zspan.zofsx= -pa->disprect.xmin -0.5f;
1615 zspan.zofsy= -pa->disprect.ymin -0.5f;
1619 zspan.rectz= pa->rectz;
1620 zspan.rectp= pa->rectp;
1621 fillrect(pa->rectp, pa->rectx, pa->recty, 0);
1622 fillrect(pa->rectz, pa->rectx, pa->recty, 0x7FFFFFFF);
1624 /* filling methods */
1625 zspan.zbuffunc= zbufinvulGL4;
1626 zspan.zbuflinefunc= zbufline;
1628 /* part clipflag, threaded */
1629 clipmask= (15 << 4*(pa->thread & 3));
1631 for(v=0; v<R.totvlak; v++) {
1633 if((v & 255)==0) vlr= R.blovl[v>>8];
1636 if(vlr->flag & R_VISIBLE) {
1639 transp= ma->mode & MA_ZTRA;
1640 env= (ma->mode & MA_ENV);
1641 wire= (ma->mode & MA_WIRE);
1643 if(ma->mode & MA_ZINV) zspan.zbuffunc= zbufinvulGLinv4;
1644 else zspan.zbuffunc= zbufinvulGL4;
1648 unsigned short partclip;
1650 /* partclipping doesn't need viewplane clipping */
1651 if(vlr->v4) partclip= vlr->v1->flag & vlr->v2->flag & vlr->v3->flag & vlr->v4->flag;
1652 else partclip= vlr->v1->flag & vlr->v2->flag & vlr->v3->flag;
1654 if((partclip & clipmask)==0) {
1659 if(wire) zbufclipwire(&zspan, zvlnr, vlr);
1661 /* strands allow to be filled in as quad */
1662 if(vlr->v4 && (vlr->flag & R_STRAND)) {
1663 zbufclip4(&zspan, zvlnr, vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip, vlr->v4->clip);
1666 zbufclip(&zspan, zvlnr, vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip);
1668 if(zvlnr) zvlnr+= 0x800000;
1669 zbufclip(&zspan, zvlnr, vlr->v1->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v3->clip, vlr->v4->clip);
1678 zbuf_free_span(&zspan);
1687 /* warning, not threaded! */
1688 static int hashlist_projectvert(float *v1, float winmat[][4], float *hoco)
1690 static VertBucket bucket[256], *buck;
1692 /* init static bucket */
1694 memset(bucket, 0, 256*sizeof(VertBucket));
1698 buck= &bucket[ (((long)v1)/16) & 255 ];
1699 if(buck->vert==v1) {
1700 QUATCOPY(hoco, buck->hoco);
1704 projectvert(v1, winmat, hoco);
1705 buck->clip = testclip(hoco);
1707 QUATCOPY(buck->hoco, hoco);
1711 /* used for booth radio 'tool' as during render */
1712 void RE_zbufferall_radio(struct RadView *vw, RNode **rg_elem, int rg_totelem, Render *re)
1715 float hoco[4][4], winmat[4][4];
1717 int c1, c2, c3, c4= 0;
1719 if(rg_totelem==0) return;
1721 hashlist_projectvert(NULL, winmat, NULL);
1723 /* needed for projectvert */
1724 MTC_Mat4MulMat4(winmat, vw->viewmat, vw->winmat);
1726 zbuf_alloc_span(&zspan, vw->rectx, vw->recty);
1727 zspan.zmulx= ((float)vw->rectx)/2.0;
1728 zspan.zmuly= ((float)vw->recty)/2.0;
1733 zspan.rectz= vw->rectz;
1734 zspan.rectp= vw->rect;
1735 fillrect(zspan.rectz, vw->rectx, vw->recty, 0x7FFFFFFF);
1736 fillrect(zspan.rectp, vw->rectx, vw->recty, 0xFFFFFF);
1738 /* filling methods */
1739 zspan.zbuffunc= zbufinvulGL4;
1741 if(rg_elem) { /* radio tool */
1745 re+= (rg_totelem-1);
1746 for(a= rg_totelem-1; a>=0; a--, re--) {
1748 if( (rn->f & RAD_SHOOT)==0 ) { /* no shootelement */
1750 if( rn->f & RAD_TWOSIDED) zvlnr= a;
1751 else if( rn->f & RAD_BACKFACE) zvlnr= 0xFFFFFF;
1754 c1= hashlist_projectvert(rn->v1, winmat, hoco[0]);
1755 c2= hashlist_projectvert(rn->v2, winmat, hoco[1]);
1756 c3= hashlist_projectvert(rn->v3, winmat, hoco[2]);
1759 c4= hashlist_projectvert(rn->v4, winmat, hoco[3]);
1763 zbufclip4(&zspan, zvlnr, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4);
1765 zbufclip(&zspan, zvlnr, hoco[0], hoco[1], hoco[2], c1, c2, c3);
1769 else { /* radio render */
1774 for(a=0; a<re->totvlak; a++) {
1775 if((a & 255)==0) vlr= re->blovl[a>>8]; else vlr++;
1779 if( (rf->flag & RAD_SHOOT)==0 ) { /* no shootelement */
1781 if( rf->flag & RAD_TWOSIDED) zvlnr= totface;
1782 else if( rf->flag & RAD_BACKFACE) zvlnr= 0xFFFFFF; /* receives no energy, but is zbuffered */
1783 else zvlnr= totface;
1785 c1= hashlist_projectvert(vlr->v1->co, winmat, hoco[0]);
1786 c2= hashlist_projectvert(vlr->v2->co, winmat, hoco[1]);
1787 c3= hashlist_projectvert(vlr->v3->co, winmat, hoco[2]);
1790 c4= hashlist_projectvert(vlr->v4->co, winmat, hoco[3]);
1794 zbufclip4(&zspan, zvlnr, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4);
1796 zbufclip(&zspan, zvlnr, hoco[0], hoco[1], hoco[2], c1, c2, c3);
1803 zbuf_free_span(&zspan);
1806 void zbuffer_shadow(Render *re, LampRen *lar, int *rectz, int size)
1811 int a, ok=1, lay= -1;
1813 if(lar->mode & LA_LAYER) lay= lar->lay;
1815 zbuf_alloc_span(&zspan, size, size);
1816 zspan.zmulx= ((float)size)/2.0;
1817 zspan.zmuly= ((float)size)/2.0;
1823 fillrect(rectz, size, size, 0x7FFFFFFE);
1825 /* filling methods */
1826 zspan.zbuflinefunc= zbufline_onlyZ;
1827 zspan.zbuffunc= zbufinvulGL_onlyZ;
1829 for(a=0; a<re->totvlak; a++) {
1831 if((a & 255)==0) vlr= re->blovl[a>>8];
1837 if((ma->mode & MA_SHADBUF)==0) ok= 0;
1840 if(ok && (vlr->flag & R_VISIBLE) && (vlr->lay & lay)) {
1841 if(ma->mode & MA_WIRE) zbufclipwire(&zspan, a+1, vlr);
1842 else if(vlr->flag & R_STRAND) zbufclipwire(&zspan, a+1, vlr);
1845 zbufclip4(&zspan, 0, vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip, vlr->v4->clip);
1847 zbufclip(&zspan, 0, vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip);
1851 zbuf_free_span(&zspan);
1856 /* ******************** ABUF ************************* */
1859 * Copy results from the solid face z buffering to the transparent
1862 static void copyto_abufz(RenderPart *pa, int *arectz, int sample)
1868 /* now, in OSA the pixstructs contain all faces filled in */
1869 if(R.r.mode & R_OSA) fillrect(arectz, pa->rectx, pa->recty, 0x7FFFFFFF);
1871 memcpy(arectz, pa->rectz, 4*pa->rectx*pa->recty);
1874 if( (R.r.mode & R_OSA)==0 || sample==0) return;
1879 sample= (1<<sample);
1881 for(y=0; y<pa->recty; y++) {
1882 for(x=0; x<pa->rectx; x++) {
1885 ps= (PixStr *)(*rd);
1888 if(sample & ps->mask) {
1889 //printf("filled xy %d %d mask %d\n", x, y, sample);
1903 /* ------------------------------------------------------------------------ */
1906 * Do accumulation z buffering.
1909 static void zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase)
1914 float vec[3], hoco[4], mul, zval, fval;
1915 int v, zvlnr, zsample;
1916 unsigned short clipmask;
1918 zbuf_alloc_span(&zspan, pa->rectx, pa->recty);
1920 /* needed for transform from hoco to zbuffer co */
1921 zspan.zmulx= ((float)R.winx)/2.0;
1922 zspan.zmuly= ((float)R.winy)/2.0;
1923 zspan.zofsx= -pa->disprect.xmin -0.5f;
1924 zspan.zofsy= -pa->disprect.ymin -0.5f;
1927 zspan.arectz= RE_mallocN(sizeof(int)*pa->rectx*pa->recty, "Arectz");
1928 zspan.apixbuf= APixbuf;
1929 zspan.apsmbase= apsmbase;
1931 /* filling methods */
1932 zspan.zbuffunc= zbufinvulAc4;
1933 zspan.zbuflinefunc= zbuflineAc;
1935 /* part clipflag, 4 threads */
1936 clipmask= (15 << 4*(pa->thread & 3));
1938 for(zsample=0; zsample<R.osa || R.osa==0; zsample++) {
1940 copyto_abufz(pa, zspan.arectz, zsample); /* init zbuffer */
1941 zspan.mask= 1<<zsample;
1943 if(R.r.mode & R_OSA) {
1944 zspan.zofsx= -pa->disprect.xmin-R.jit[zsample][0]-0.5;
1945 zspan.zofsy= -pa->disprect.ymin-R.jit[zsample][1]-0.5;
1948 for(v=0; v<R.totvlak; v++) {
1954 if(ma->mode & (MA_ZTRA)) {
1955 if(vlr->flag & R_VISIBLE) {
1956 unsigned short partclip;
1958 /* partclipping doesn't need viewplane clipping */
1959 if(vlr->v4) partclip= vlr->v1->flag & vlr->v2->flag & vlr->v3->flag & vlr->v4->flag;
1960 else partclip= vlr->v1->flag & vlr->v2->flag & vlr->v3->flag;
1962 if((partclip & clipmask)==0) {
1963 /* a little advantage for transp rendering (a z offset) */
1964 if( ma->zoffs != 0.0) {
1966 zval= mul*(1.0+vlr->v1->ho[2]/vlr->v1->ho[3]);
1968 VECCOPY(vec, vlr->v1->co);
1969 /* z is negative, otherwise its being clipped */
1971 projectverto(vec, R.winmat, hoco);
1972 fval= mul*(1.0+hoco[2]/hoco[3]);
1974 zspan.polygon_offset= (int) fabs(zval - fval );
1976 else zspan.polygon_offset= 0;
1980 if(ma->mode & (MA_WIRE)) zbufclipwire(&zspan, zvlnr, vlr);
1982 if(vlr->v4 && (vlr->flag & R_STRAND)) {
1983 zbufclip4(&zspan, zvlnr, vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip, vlr->v4->clip);
1986 zbufclip(&zspan, zvlnr, vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip);
1989 zbufclip(&zspan, zvlnr, vlr->v1->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v3->clip, vlr->v4->clip);
2001 if((R.r.mode & R_OSA)==0) break;
2002 if(R.test_break()) break;
2005 RE_freeN(zspan.arectz);
2006 zbuf_free_span(&zspan);
2010 static int vergzvlak(const void *a1, const void *a2)
2012 const int *x1=a1, *x2=a2;
2014 if( x1[0] < x2[0] ) return 1;
2015 else if( x1[0] > x2[0]) return -1;
2020 * Shade this face at this location in SCS.
2022 static void shadetrapixel(RenderPart *pa, float x, float y, int z, int facenr, int mask, float *fcol)
2026 if( (facenr & 0x7FFFFF) > R.totvlak) {
2027 printf("error in shadetrapixel nr: %d\n", (facenr & 0x7FFFFF));
2030 if(R.r.mode & R_OSA) {
2031 VlakRen *vlr= RE_findOrAddVlak(&R, (facenr-1) & 0x7FFFFF);
2032 float accumcol[4]={0,0,0,0}, tot=0.0;
2035 if(vlr->flag & R_FULL_OSA) {
2036 for(a=0; a<R.osa; a++) {
2038 shadepixel(pa, x+R.jit[a][0], y+R.jit[a][1], z, facenr, 1<<a, fcol, rco);
2039 accumcol[0]+= fcol[0];
2040 accumcol[1]+= fcol[1];
2041 accumcol[2]+= fcol[2];
2042 accumcol[3]+= fcol[3];
2047 fcol[0]= accumcol[0]*tot;
2048 fcol[1]= accumcol[1]*tot;
2049 fcol[2]= accumcol[2]*tot;
2050 fcol[3]= accumcol[3]*tot;
2053 int b= R.samples->centmask[mask];
2054 x= x+R.samples->centLut[b & 15];
2055 y= y+R.samples->centLut[b>>4];
2056 shadepixel(pa, x, y, z, facenr, mask, fcol, rco);
2060 else shadepixel(pa, x, y, z, facenr, mask, fcol, rco);
2063 static int addtosampcol(float *sampcol, float *fcol, int mask)
2065 int a, retval = R.osa;
2067 for(a=0; a < R.osa; a++) {
2068 if(mask & (1<<a)) addAlphaUnderFloat(sampcol, fcol);
2069 if(sampcol[3]>0.999) retval--;
2075 #define MAX_ZROW 1000
2076 /* main render call to fill in pass the full transparent layer */
2078 void zbuffer_transp_shade(RenderPart *pa, float *pass)
2080 APixstr *APixbuf; /* Zbuffer: linked list of face samples */
2082 ListBase apsmbase={NULL, NULL};
2083 float col[4], fcol[4], tempcol[4], sampcol[16*4], *scol, accumcol[4];
2084 float fac, alpha[32];
2085 int x, y, a, zrow[MAX_ZROW][3], totface, nr;
2088 /* looks nicer for calling code */
2092 APixbuf= RE_callocN(pa->rectx*pa->recty*sizeof(APixstr), "APixbuf");
2095 printf("abufsetrow: osa too large\n");
2101 if(R.r.mode & R_OSA ) {
2102 fac= (1.0/(float)R.osa);
2103 for(a=0; a<=R.osa; a++) {
2104 alpha[a]= (float)a*fac;
2108 /* fill the Apixbuf */
2109 zbuffer_abuf(pa, APixbuf, &apsmbase);
2114 for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++) {
2115 for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, ap++, pass+=4) {
2122 for(a=0; a<4; a++) {
2124 zrow[totface][0]= apn->z[a];
2125 zrow[totface][1]= apn->p[a];
2126 zrow[totface][2]= apn->mask[a];
2128 if(totface>=MAX_ZROW) totface= MAX_ZROW-1;
2137 shadetrapixel(pa, (float)x, (float)y, zrow[0][0], zrow[0][1], zrow[0][2], fcol);
2139 nr= count_mask(zrow[0][2]);
2140 if( (R.r.mode & R_OSA) && nr<R.osa) {
2142 col[0]= (fcol[0]*fac);
2143 col[1]= (fcol[1]*fac);
2144 col[2]= (fcol[2]*fac);
2145 col[3]= (fcol[3]*fac);
2155 col[0]= col[1]= col[2]= col[3]= 0.0f;
2158 if(zrow[0][0] < zrow[1][0]) {
2159 a= zrow[0][0]; zrow[0][0]= zrow[1][0]; zrow[1][0]= a;
2160 a= zrow[0][1]; zrow[0][1]= zrow[1][1]; zrow[1][1]= a;
2161 a= zrow[0][2]; zrow[0][2]= zrow[1][2]; zrow[1][2]= a;
2165 else { /* totface>2 */
2166 qsort(zrow, totface, sizeof(int)*3, vergzvlak);
2169 /* join when pixels are adjacent */
2174 shadetrapixel(pa, (float)x, (float)y, zrow[totface][0], zrow[totface][1], zrow[totface][2], fcol);
2176 a= count_mask(zrow[totface][2]);
2177 if( (R.r.mode & R_OSA ) && a<R.osa) {
2179 memset(sampcol, 0, 4*sizeof(float)*R.osa);
2180 sval= addtosampcol(sampcol, fcol, zrow[totface][2]);
2182 /* sval==0: alpha completely full */
2183 while( (sval != 0) && (totface>0) ) {
2184 a= count_mask(zrow[totface-1][2]);
2188 shadetrapixel(pa, (float)x, (float)y, zrow[totface][0], zrow[totface][1], zrow[totface][2], fcol);
2189 sval= addtosampcol(sampcol, fcol, zrow[totface][2]);
2193 accumcol[0]= scol[0]; accumcol[1]= scol[1];
2194 accumcol[2]= scol[2]; accumcol[3]= scol[3];
2196 for(a=1; a<R.osa; a++, scol+=4) {
2197 accumcol[0]+= scol[0]; accumcol[1]+= scol[1];
2198 accumcol[2]+= scol[2]; accumcol[3]+= scol[3];
2200 tempcol[0]= accumcol[0]/R.osa;
2201 tempcol[1]= accumcol[1]/R.osa;
2202 tempcol[2]= accumcol[2]/R.osa;
2203 tempcol[3]= accumcol[3]/R.osa;
2205 addAlphaUnderFloat(col, tempcol);
2210 fcol[0]= (fcol[0]*fac);
2211 fcol[1]= (fcol[1]*fac);
2212 fcol[2]= (fcol[2]*fac);
2213 fcol[3]= (fcol[3]*fac);
2214 addAlphaUnderFloat(col, fcol);
2217 else addAlphaUnderFloat(col, fcol); /* no osa or full pixel with same face? */
2219 if(col[3]>=0.999) break;
2222 if(col[3]!=0.0) addAlphaOverFloat(pass, col);