/** * $Id:$ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * The contents of this file may be used under the terms of either the GNU * General Public License Version 2 or later (the "GPL", see * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or * later (the "BL", see http://www.blender.org/BL/ ) which has to be * bought from the Blender Foundation to become active, in which case the * above mentioned GPL option does not apply. * * The Original Code is Copyright (C) 1997 by Ton Roosendaal, Frank van Beek and Joeri Kassenaar. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ /* zbuf.c */ /* bindkey -r f1,'make\n' bindkey -r f2,'/usr/people/trace/traces\n' void snijpz(v1,v2,v3,xs,dx,f1,omsl,min,max) void projectvert(v1, adr) void zbuf(vlr) short zbuffermetdehand() short zbuffermetdehandAli(xw,yw,xpart,ypart) */ #include #include #include #include #include "/usr/people/include/Trace.h" #define ABUFPART 64 struct APixstr { short mask[4]; long z[4]; long p[4]; struct APixstr *next; }; struct APixstrMain { struct APixstr *ps; struct APixstrMain *next; }; extern long count_mask(); extern float centLut[16]; extern char *centmask; float *vlzp[32][3], labda[3][2], vez[400], *p[40], Zmulx, Zmuly; float Zjitx, Zjity; ulong Zvlnr, Zsample; struct VlakRen *Zvlr; void (*zbuffunc)(); struct APixstr *APixbuf; ushort *Acolrow; long *Arectz; long Aminy, Amaxy, Azvoordeel; struct APixstrMain apsmfirst; short apsmteller= 0; void fillrect(rect,x,y,val) ulong *rect,x,y,val; { ulong len,len4,*drect; len= x*y; drect= rect; while(len>0) { len--; *drect= val; drect++; } } /* ************* ACCU ZBUF ************ */ struct APixstr *addpsmainA() { struct APixstrMain *psm; psm= &apsmfirst; while(psm->next) { psm= psm->next; } psm->next= mallocN(sizeof(struct APixstrMain), "addpsmainA"); psm= psm->next; psm->next=0; psm->ps= callocN(4096*sizeof(struct APixstr),"pixstr"); apsmteller= 0; return psm->ps; } void freepsA() { struct APixstrMain *psm, *next; psm= &apsmfirst; while(psm) { next= psm->next; if(psm->ps) { freeN(psm->ps); psm->ps= 0; } if(psm!= &apsmfirst) freeN(psm); psm= next; } apsmfirst.next= 0; apsmfirst.ps= 0; apsmteller= 0; } struct APixstr *addpsA() { static struct APixstr *prev; /* eerste PS maken */ if((apsmteller & 4095)==0) prev= addpsmainA(); else prev++; apsmteller++; return prev; } void zbufinvulAc(v1,v2,v3) /* vult kleur in, met windowcoordinaat, van Aminy->Amaxy */ float *v1,*v2,*v3; { struct APixstr *ap, *apofs, *apn; double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1; double zxd,zyd,zy0; float *minv,*maxv,*midv; register long *rz,zverg,zvlak,x; long my0,my2,sn1,sn2,rectx,zd,*rectzofs; long y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2, mask; /* MIN MAX */ if(v1[1] Amaxy) return; if(my0 Amaxy) { /* my2 kan groter zijn */ xs0+=dx0; if (my2<=omsl) { xs2+= dx2; } else{ xs1+= dx1; } my2--; } xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2]; zxd= -x0/z0; zyd= -y0/z0; zy0= my2*zyd+xx1; zd= (long)zxd; /* start-ofset in rect */ rectx= R.rectx; rectzofs= (long *)(Arectz+rectx*(my2-Aminy)); apofs= (APixbuf+ rectx*(my2-Aminy)); mask= 1<dx1) { xs3= xs0; xs0= xs1; xs1= xs3; xs3= dx0; dx0= dx1; dx1= xs3; xs3= 1; /* flag */ } for(y=my2;y>omsl;y--) { sn1= *((short *)&xs0); xs0+= dx0; sn2= *((short *)&xs1); xs1+= dx1; sn1++; if(sn2>=rectx) sn2= rectx-1; if(sn1<0) sn1= 0; zverg= (long) (sn1*zxd+zy0); rz= rectzofs+sn1; ap= apofs+sn1; x= sn2-sn1; zverg-= Azvoordeel; while(x>=0) { if(zverg< *rz) { apn= ap; while(apn) { /* loopunrolled */ if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; } if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; } if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; } if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; } if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; } if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; } if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; } if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; } if(apn->next==0) apn->next= addpsA(); apn= apn->next; } } zverg+= zd; rz++; ap++; x--; } zy0-= zyd; rectzofs-= rectx; apofs-= rectx; } if(xs3) { xs0= xs1; dx0= dx1; } if(xs0>xs2) { xs3= xs0; xs0= xs2; xs2= xs3; xs3= dx0; dx0= dx2; dx2= xs3; } for(; y>=my0; y--) { sn1= *((short *)&xs0); xs0+= dx0; sn2= *((short *)&xs2); xs2+= dx2; sn1++; if(sn2>=rectx) sn2= rectx-1; if(sn1<0) sn1= 0; zverg= (long) (sn1*zxd+zy0); rz= rectzofs+sn1; ap= apofs+sn1; x= sn2-sn1; zverg-= Azvoordeel; while(x>=0) { if(zverg< *rz) { apn= ap; while(apn) { /* loopunrolled */ if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; } if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; } if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; } if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; } if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; } if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; } if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; } if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; } if(apn->next==0) apn->next= addpsA(); apn= apn->next; } } zverg+= zd; rz++; ap++; x--; } zy0-=zyd; rectzofs-= rectx; apofs-= rectx; } } /* ************* NORMAL ZBUFFER ************ */ void hoco_to_zco(float *zco, float *hoco) { float deler; deler= hoco[3]; zco[0]= Zmulx*(1.0+hoco[0]/deler)+ Zjitx; zco[1]= Zmuly*(1.0+hoco[1]/deler)+ Zjity; zco[2]= 0x7FFFFFFF *(hoco[2]/deler); } void zbufline(vec1, vec2) float *vec1, *vec2; { ulong *rectz, *rectp; int start, end, x, y, oldx, oldy, ofs; int dz, vergz; float dx, dy; float v1[3], v2[3]; dx= vec2[0]-vec1[0]; dy= vec2[1]-vec1[1]; if(fabs(dx) > fabs(dy)) { /* alle lijnen van links naar rechts */ if(vec1[0]=R.rectx) end= R.rectx-1; oldy= ffloor(v1[1]); dy/= dx; vergz= v1[2]; dz= (v2[2]-v1[2])/dx; rectz= R.rectz+ oldy*R.rectx+ start; rectp= R.rectot+ oldy*R.rectx+ start; if(dy<0) ofs= -R.rectx; else ofs= R.rectx; for(x= start; x<=end; x++, rectz++, rectp++) { y= ffloor(v1[1]); if(y!=oldy) { oldy= y; rectz+= ofs; rectp+= ofs; } if(x>=0 && y>=0 && y=R.recty) end= R.recty-1; oldx= ffloor(v1[0]); dx/= dy; vergz= v1[2]; dz= (v2[2]-v1[2])/dy; rectz= R.rectz+ start*R.rectx+ oldx; rectp= R.rectot+ start*R.rectx+ oldx; if(dx<0) ofs= -1; else ofs= 1; for(y= start; y<=end; y++, rectz+=R.rectx, rectp+=R.rectx) { x= ffloor(v1[0]); if(x!=oldx) { oldx= x; rectz+= ofs; rectp+= ofs; } if(x>=0 && y>=0 && xv1->clip; c2= vlr->v2->clip; c3= vlr->v3->clip; f1= vlr->v1->ho; f2= vlr->v2->ho; f3= vlr->v3->ho; /* edgecode: 1=niet tekenen */ if (vlr->vl) ec = vlr->vl->ec >> 5; else ec = vlr->ec & 7; if(ec==7) return; if(c1 | c2 | c3) { /* niet in midden */ if(c1 & c2 & c3) { /* helemaal eruit */ return; } else { /* clippen */ vez[0]= f1[0]; vez[1]= f1[1]; vez[2]= f1[2]; vez[3]= f1[3]; vez[4]= f2[0]; vez[5]= f2[1]; vez[6]= f2[2]; vez[7]= f2[3]; if((ec & 4)==0) { if( clipline(vez, vez+4)==0) ec |= 4; } vzp= vez+ 8; vzp[0]= f2[0]; vzp[1]= f2[1]; vzp[2]= f2[2]; vzp[3]= f2[3]; vzp[4]= f3[0]; vzp[5]= f3[1]; vzp[6]= f3[2]; vzp[7]= f3[3]; if((ec & 2)==0) { if( clipline(vzp, vzp+4)==0) ec |= 2; } vzp= vez+16; vzp[0]= f3[0]; vzp[1]= f3[1]; vzp[2]= f3[2]; vzp[3]= f3[3]; vzp[4]= f1[0]; vzp[5]= f1[1]; vzp[6]= f1[2]; vzp[7]= f1[3]; if((ec & 1)==0) { if( clipline(vzp, vzp+4)==0) ec |= 1; } /* tekenen */ if((ec & 4)==0) { hoco_to_zco(vez, vez); hoco_to_zco(vez+4, vez+4); zbufline(vez, vez+4); } if((ec & 2)==0) { hoco_to_zco(vez+8, vez+8); hoco_to_zco(vez+12, vez+12); zbufline(vez+8, vez+12); } if((ec & 1)==0) { hoco_to_zco(vez+16, vez+16); hoco_to_zco(vez+20, vez+20); zbufline(vez+16, vez+20); } return; } } deler= f1[3]; vez[0]= Zmulx*(1.0+f1[0]/deler)+ Zjitx; vez[1]= Zmuly*(1.0+f1[1]/deler)+ Zjity; vez[2]= 0x7FFFFFFF *(f1[2]/deler); deler= f2[3]; vez[4]= Zmulx*(1.0+f2[0]/deler)+ Zjitx; vez[5]= Zmuly*(1.0+f2[1]/deler)+ Zjity; vez[6]= 0x7FFFFFFF *(f2[2]/deler); deler= f3[3]; vez[8]= Zmulx*(1.0+f3[0]/deler)+ Zjitx; vez[9]= Zmuly*(1.0+f3[1]/deler)+ Zjity; vez[10]= 0x7FFFFFFF *(f3[2]/deler); if((ec & 4)==0) zbufline(vez, vez+4); if((ec & 2)==0) zbufline(vez+4, vez+8); if((ec & 1)==0) zbufline(vez+8, vez); } void zbufinvulGLinv(v1,v2,v3) float *v1,*v2,*v3; /* vult in R.rectot de waarde Zvlnr in met R.rectz */ /* KEERT Z-VERGELIJKING OM: ALLES ACHTER IS ZICHTBAAR */ { double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1; double zxd,zyd,zy0; float *minv,*maxv,*midv; ulong *rectpofs,*rp; register long *rz,zverg,zvlak,x; long my0,my2,sn1,sn2,rectx,zd,*rectzofs; long y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2; /* MIN MAX */ if(v1[1] R.recty) return; if(my0<0) my0=0; /* EDGES : DE LANGSTE */ xx1= maxv[1]-minv[1]; if(xx1!=0) { z0= (maxv[0]-minv[0])/xx1; dx0= (-65536.0*z0); xs0= 65536.0*(z0*(my2-minv[1])+minv[0]); } else { dx0= 0; xs0= 65536.0*(MIN2(minv[0],maxv[0])); } /* EDGES : DE BOVENSTE */ xx1= maxv[1]-midv[1]; if(xx1!=0) { z0= (maxv[0]-midv[0])/xx1; dx1= (-65536.0*z0); xs1= 65536.0*(z0*(my2-midv[1])+midv[0]); } else { dx1= 0; xs1= 65536.0*(MIN2(midv[0],maxv[0])); } /* EDGES : DE ONDERSTE */ xx1= midv[1]-minv[1]; if(xx1!=0) { z0= (midv[0]-minv[0])/xx1; dx2= (-65536.0*z0); xs2= 65536.0*(z0*(omsl-minv[1])+minv[0]); } else { dx2= 0; xs2= 65536.0*(MIN2(minv[0],midv[0])); } /* ZBUF DX DY */ x1= v1[0]- v2[0]; x2= v2[0]- v3[0]; y1= v1[1]- v2[1]; y2= v2[1]- v3[1]; z1= v1[2]- v2[2]; z2= v2[2]- v3[2]; x0= y1*z2-z1*y2; y0= z1*x2-x1*z2; z0= x1*y2-y1*x2; /* printf("x0 %f y0 %f z0 %f\n", x0, y0, z0); */ if(z0==0.0) return; if(midv[1]==maxv[1]) omsl= my2; if(omsl<0) omsl= -1; /* dan neemt ie de eerste lus helemaal */ while (my2 >= R.recty) { /* my2 kan groter zijn */ xs0+=dx0; if (my2<=omsl) { xs2+= dx2; } else{ xs1+= dx1; } my2--; } xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2]; zxd= -x0/z0; zyd= -y0/z0; zy0= my2*zyd+xx1; zd= (long)zxd; /* start-ofset in rect */ rectx= R.rectx; rectzofs= (long *)(R.rectz+rectx*my2); rectpofs= (R.rectot+rectx*my2); zvlak= Zvlnr; xs3= 0; /* flag */ if(dx0>dx1) { xs3= xs0; xs0= xs1; xs1= xs3; xs3= dx0; dx0= dx1; dx1= xs3; xs3= 1; /* flag */ } for(y=my2;y>omsl;y--) { sn1= *((short *)&xs0); xs0+= dx0; sn2= *((short *)&xs1); xs1+= dx1; sn1++; if(sn2>=rectx) sn2= rectx-1; if(sn1<0) sn1= 0; zverg= (long) (sn1*zxd+zy0); rz= rectzofs+sn1; rp= rectpofs+sn1; x= sn2-sn1; while(x>=0) { if(zverg> *rz || *rz==0x7FFFFFFF) { *rz= zverg; *rp= zvlak; } zverg+= zd; rz++; rp++; x--; } zy0-=zyd; rectzofs-= rectx; rectpofs-= rectx; } if(xs3) { xs0= xs1; dx0= dx1; } if(xs0>xs2) { xs3= xs0; xs0= xs2; xs2= xs3; xs3= dx0; dx0= dx2; dx2= xs3; } for(;y>=my0;y--) { sn1= *((short *)&xs0); xs0+= dx0; sn2= *((short *)&xs2); xs2+= dx2; sn1++; if(sn2>=rectx) sn2= rectx-1; if(sn1<0) sn1= 0; zverg= (long) (sn1*zxd+zy0); rz= rectzofs+sn1; rp= rectpofs+sn1; x= sn2-sn1; while(x>=0) { if(zverg> *rz || *rz==0x7FFFFFFF) { *rz= zverg; *rp= zvlak; } zverg+= zd; rz++; rp++; x--; } zy0-=zyd; rectzofs-= rectx; rectpofs-= rectx; } } void zbufinvulGL(v1,v2,v3) /* vult in R.rectot de waarde Zvlnr in met R.rectz */ float *v1,*v2,*v3; { double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1; double zxd,zyd,zy0; float *minv,*maxv,*midv; ulong *rectpofs,*rp; register long *rz,zverg,zvlak,x; long my0,my2,sn1,sn2,rectx,zd,*rectzofs; long y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2; /* MIN MAX */ if(v1[1] R.recty) return; if(my0<0) my0=0; /* EDGES : DE LANGSTE */ xx1= maxv[1]-minv[1]; if(xx1!=0) { z0= (maxv[0]-minv[0])/xx1; dx0= (-65536.0*z0); xs0= 65536.0*(z0*(my2-minv[1])+minv[0]); } else { dx0= 0; xs0= 65536.0*(MIN2(minv[0],maxv[0])); } /* EDGES : DE BOVENSTE */ xx1= maxv[1]-midv[1]; if(xx1!=0) { z0= (maxv[0]-midv[0])/xx1; dx1= (-65536.0*z0); xs1= 65536.0*(z0*(my2-midv[1])+midv[0]); } else { dx1= 0; xs1= 65536.0*(MIN2(midv[0],maxv[0])); } /* EDGES : DE ONDERSTE */ xx1= midv[1]-minv[1]; if(xx1!=0) { z0= (midv[0]-minv[0])/xx1; dx2= (-65536.0*z0); xs2= 65536.0*(z0*(omsl-minv[1])+minv[0]); } else { dx2= 0; xs2= 65536.0*(MIN2(minv[0],midv[0])); } /* ZBUF DX DY */ x1= v1[0]- v2[0]; x2= v2[0]- v3[0]; y1= v1[1]- v2[1]; y2= v2[1]- v3[1]; z1= v1[2]- v2[2]; z2= v2[2]- v3[2]; x0= y1*z2-z1*y2; y0= z1*x2-x1*z2; z0= x1*y2-y1*x2; /* printf("x0 %f y0 %f z0 %f\n", x0, y0, z0); */ if(z0==0.0) return; if(midv[1]==maxv[1]) omsl= my2; if(omsl<0) omsl= -1; /* dan neemt ie de eerste lus helemaal */ while (my2 >= R.recty) { /* my2 kan groter zijn */ xs0+=dx0; if (my2<=omsl) { xs2+= dx2; } else{ xs1+= dx1; } my2--; } xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2]; zxd= -x0/z0; zyd= -y0/z0; zy0= my2*zyd+xx1; zd= (long)zxd; /* start-ofset in rect */ rectx= R.rectx; rectzofs= (long *)(R.rectz+rectx*my2); rectpofs= (R.rectot+rectx*my2); zvlak= Zvlnr; xs3= 0; /* flag */ if(dx0>dx1) { xs3= xs0; xs0= xs1; xs1= xs3; xs3= dx0; dx0= dx1; dx1= xs3; xs3= 1; /* flag */ } for(y=my2;y>omsl;y--) { sn1= *((short *)&xs0); xs0+= dx0; sn2= *((short *)&xs1); xs1+= dx1; sn1++; if(sn2>=rectx) sn2= rectx-1; if(sn1<0) sn1= 0; zverg= (long) (sn1*zxd+zy0); rz= rectzofs+sn1; rp= rectpofs+sn1; x= sn2-sn1; while(x>=0) { if(zverg< *rz) { *rz= zverg; *rp= zvlak; } zverg+= zd; rz++; rp++; x--; } zy0-=zyd; rectzofs-= rectx; rectpofs-= rectx; } if(xs3) { xs0= xs1; dx0= dx1; } if(xs0>xs2) { xs3= xs0; xs0= xs2; xs2= xs3; xs3= dx0; dx0= dx2; dx2= xs3; } for(;y>=my0;y--) { sn1= *((short *)&xs0); xs0+= dx0; sn2= *((short *)&xs2); xs2+= dx2; sn1++; if(sn2>=rectx) sn2= rectx-1; if(sn1<0) sn1= 0; zverg= (long) (sn1*zxd+zy0); rz= rectzofs+sn1; rp= rectpofs+sn1; x= sn2-sn1; while(x>=0) { if(zverg< *rz) { *rz= zverg; *rp= zvlak; } zverg+= zd; rz++; rp++; x--; } zy0-=zyd; rectzofs-= rectx; rectpofs-= rectx; } } void zbufinvulGL_onlyZ(v1,v2,v3) /* vult alleen R.rectz. oneven z= 1x ingevuld */ float *v1,*v2,*v3; { double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1; double zxd,zyd,zy0; float *minv,*maxv,*midv; register long *rz,zverg,x; long my0,my2,sn1,sn2,rectx,zd,*rectzofs; long y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2; /* MIN MAX */ if(v1[1] R.recty) return; if(my0<0) my0=0; /* EDGES : DE LANGSTE */ xx1= maxv[1]-minv[1]; if(xx1!=0) { z0= (maxv[0]-minv[0])/xx1; dx0= (-65536.0*z0); xs0= 65536.0*(z0*(my2-minv[1])+minv[0]); } else { dx0= 0; xs0= 65536.0*(MIN2(minv[0],maxv[0])); } /* EDGES : DE BOVENSTE */ xx1= maxv[1]-midv[1]; if(xx1!=0) { z0= (maxv[0]-midv[0])/xx1; dx1= (-65536.0*z0); xs1= 65536.0*(z0*(my2-midv[1])+midv[0]); } else { dx1= 0; xs1= 65536.0*(MIN2(midv[0],maxv[0])); } /* EDGES : DE ONDERSTE */ xx1= midv[1]-minv[1]; if(xx1!=0) { z0= (midv[0]-minv[0])/xx1; dx2= (-65536.0*z0); xs2= 65536.0*(z0*(omsl-minv[1])+minv[0]); } else { dx2= 0; xs2= 65536.0*(MIN2(minv[0],midv[0])); } /* ZBUF DX DY */ x1= v1[0]- v2[0]; x2= v2[0]- v3[0]; y1= v1[1]- v2[1]; y2= v2[1]- v3[1]; z1= v1[2]- v2[2]; z2= v2[2]- v3[2]; x0= y1*z2-z1*y2; y0= z1*x2-x1*z2; z0= x1*y2-y1*x2; /* printf("x0 %f y0 %f z0 %f\n", x0, y0, z0); */ if(z0==0.0) return; if(midv[1]==maxv[1]) omsl= my2; if(omsl<0) omsl= -1; /* dan neemt ie de eerste lus helemaal */ while (my2 >= R.recty) { /* my2 kan groter zijn */ xs0+=dx0; if (my2<=omsl) { xs2+= dx2; } else{ xs1+= dx1; } my2--; } xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2]; zxd= -x0/z0; zyd= -y0/z0; zy0= my2*zyd+xx1; zd= (long)zxd; /* start-ofset in rect */ rectx= R.rectx; rectzofs= (long *)(R.rectz+rectx*my2); xs3= 0; /* flag */ if(dx0>dx1) { xs3= xs0; xs0= xs1; xs1= xs3; xs3= dx0; dx0= dx1; dx1= xs3; xs3= 1; /* flag */ } for(y=my2;y>omsl;y--) { sn1= *((short *)&xs0); xs0+= dx0; sn2= *((short *)&xs1); xs1+= dx1; sn1++; if(sn2>=rectx) sn2= rectx-1; if(sn1<0) sn1= 0; zverg= (long) (sn1*zxd+zy0); rz= rectzofs+sn1; x= sn2-sn1; while(x>=0) { if(zverg< *rz) { *rz= zverg; } zverg+= zd; rz++; x--; } zy0-=zyd; rectzofs-= rectx; } if(xs3) { xs0= xs1; dx0= dx1; } if(xs0>xs2) { xs3= xs0; xs0= xs2; xs2= xs3; xs3= dx0; dx0= dx2; dx2= xs3; } for(;y>=my0;y--) { sn1= *((short *)&xs0); xs0+= dx0; sn2= *((short *)&xs2); xs2+= dx2; sn1++; if(sn2>=rectx) sn2= rectx-1; if(sn1<0) sn1= 0; zverg= (long) (sn1*zxd+zy0); rz= rectzofs+sn1; x= sn2-sn1; while(x>=0) { if(zverg< *rz) { *rz= zverg; } zverg+= zd; rz++; x--; } zy0-=zyd; rectzofs-= rectx; } } void print3floats(v1,v2,v3) float *v1,*v2,*v3; { printf("1 %f %f %f %f\n", v1[0], v1[1], v1[2], v1[3]); printf("2 %f %f %f %f\n", v2[0], v2[1], v2[2], v2[3]); printf("3 %f %f %f %f\n", v3[0], v3[1], v3[2], v3[3]); } short cliptestf(p,q,u1,u2) float p,q,*u1,*u2; { float r; if(p<0.0) { if(q*u2) return 0; else if(r>*u1) *u1=r; } } else { if(p>0.0) { if(q<0.0) return 0; else if(q abs4) c+= 32; if( v[0]>abs4) c+=2; else if( v[0]< -abs4) c+=1; if( v[1]>abs4) c+=4; else if( v[1]< -abs4) c+=8; return c; } void clippz(v1, v2, b1, b2, b3) float *v1,*v2; long b1,*b2,*b3; { float dz,dw,u1=0.0,u2=1.0; labda[b1][0]= -1.0; labda[b1][1]= -1.0; dz= v2[2]-v1[2]; dw= v2[3]-v1[3]; /* volgens het oorspronkelijke artikel van Liang Barsky, wordt bij het clippen van * hoco's met het viewplane, het getal "0" gebruikt ipv "-w" . * Dit wijkt af van de andere clipping (links en onder) en vond ik ook niet erg * 'homogeen'. Het is dus een fout, wie had dat gedacht van L&B! */ if(cliptestf(-dz-dw, v1[3]+v1[2], &u1,&u2)) { if(cliptestf(dz-dw, v1[3]-v1[2], &u1,&u2)) { *b3=1; if(u2<1.0) { labda[b1][1]= u2; *b2=1; } else labda[b1][1]=1.0; /* u2 */ if(u1>0.0) { labda[b1][0]= u1; *b2=1; } else labda[b1][0]=0.0; } } } void clippx(v1,v2,b1,b2,b3) float *v1,*v2; long b1,*b2,*b3; { float dx,dz,u1=0.0,u2=1.0; labda[b1][0]= -1.0; labda[b1][1]= -1.0; dx= v2[0]-v1[0]; dz= v2[3]-v1[3]; if(cliptestf(-dx-dz, v1[0]+v1[3], &u1,&u2)) { if(cliptestf(dx-dz, v1[3]-v1[0], &u1,&u2)) { *b3=1; if(u2<1.0) { labda[b1][1]=u2; *b2=1; } else labda[b1][1]=1.0; /* u2 */ if(u1>0.0) { labda[b1][0]=u1; *b2=1; } else labda[b1][0]=0.0; } } } void clippy(v1,v2,b1,b2,b3) float *v1,*v2; long b1,*b2,*b3; { float dy,dz,u1=0.0,u2=1.0; labda[b1][0]= -1.0; labda[b1][1]= -1.0; dy= v2[1]-v1[1]; dz= v2[3]-v1[3]; if(cliptestf(-dy-dz,v1[1]+v1[3],&u1,&u2)) { if(cliptestf(dy-dz,v1[3]-v1[1],&u1,&u2)) { *b3=1; if(u2<1.0) { labda[b1][1]=u2; *b2=1; } else labda[b1][1]=1.0; /* u2 */ if(u1>0.0) { labda[b1][0]=u1; *b2=1; } else labda[b1][0]=0.0; } } } int clipline(v1, v2) /* return 0: niet tekenen */ float *v1,*v2; { float dz,dw, u1=0.0, u2=1.0; float dx, dy; dz= v2[2]-v1[2]; dw= v2[3]-v1[3]; if(cliptestf(-dz-dw, v1[3]+v1[2], &u1,&u2)) { if(cliptestf(dz-dw, v1[3]-v1[2], &u1,&u2)) { dx= v2[0]-v1[0]; /* dz= v2[3]-v1[3]; */ if(cliptestf(-dx-dw, v1[0]+v1[3], &u1,&u2)) { if(cliptestf(dx-dw, v1[3]-v1[0], &u1,&u2)) { dy= v2[1]-v1[1]; if(cliptestf(-dy-dw,v1[1]+v1[3],&u1,&u2)) { if(cliptestf(dy-dw,v1[3]-v1[1],&u1,&u2)) { if(u2<1.0) { v2[0]= v1[0]+u2*dx; v2[1]= v1[1]+u2*dy; v2[2]= v1[2]+u2*dz; v2[3]= v1[3]+u2*dw; } if(u1>0.0) { v1[0]= v1[0]+u1*dx; v1[1]= v1[1]+u1*dy; v1[2]= v1[2]+u1*dz; v1[3]= v1[3]+u1*dw; } return 1; } } } } } } return 0; } void maakvertpira(v1,v2,b1,b2,clve) float *v1,*v2; long *b1,b2,*clve; { float l1,l2,*adr,min1= -1.0,nul=0.0; l1= labda[b2][0]; l2= labda[b2][1]; if(l1!= -1.0) { if(l1!= 0.0) { adr= vez+4*(*clve); p[*b1]=adr; (*clve)++; adr[0]= v1[0]+l1*(v2[0]-v1[0]); adr[1]= v1[1]+l1*(v2[1]-v1[1]); adr[2]= v1[2]+l1*(v2[2]-v1[2]); adr[3]= v1[3]+l1*(v2[3]-v1[3]); } else p[*b1]= v1; (*b1)++; } if(l2!= -1.0) { if(l2!= 1.0) { adr= vez+4*(*clve); p[*b1]=adr; (*clve)++; adr[0]= v1[0]+l2*(v2[0]-v1[0]); adr[1]= v1[1]+l2*(v2[1]-v1[1]); adr[2]= v1[2]+l2*(v2[2]-v1[2]); adr[3]= v1[3]+l2*(v2[3]-v1[3]); (*b1)++; } } } void projectholo(v1, adr) float *v1; float *adr; { static float d, zd, zy; float x,y,z; if(v1==0) { /* init */ if(view0.cambase) { d= view0.near; zd= d*0.01*(float)view0.cambase->len; if(view0.cambase->holo1) zy= zd+ (1.0+0.1*view0.cambase->holo1)*d; else zy= 0.0; } return; } x= v1[0]; y= v1[1]; z= v1[2]; if(G.holo==2 && view0.cambase) { if(z== -(zd+d)) z+= 0.001; x= (-z/view0.near)*(zd*x)/((zd+d) +z); if(zy!=0.0) { if(z== -(zy+d)) z+=0.001; y= (-z/view0.near)*(zy*y)/((zy+d) +z); } } adr[0]= x*G.winmat[0][0] +z*G.winmat[2][0]; adr[1]= y*G.winmat[1][1]+z*G.winmat[2][1]; adr[2]= z*G.winmat[2][2]+G.winmat[3][2]; adr[3]= -z; } void projectverto(v1,adr) float *v1; float *adr; { /* berekent homogene co van vertex v1 */ float x,y,z; if(G.holo==2) { projectholo(v1, adr); return; } x= v1[0]; y= v1[1]; z= v1[2]; adr[0]= x*G.winmat[0][0] +z*G.winmat[2][0]; adr[1]= y*G.winmat[1][1]+z*G.winmat[2][1]; adr[2]= z*G.winmat[2][2]+G.winmat[3][2]; adr[3]= z*G.winmat[2][3]+G.winmat[3][3]; } void projectvert(v1,adr) float *v1; float *adr; { /* berekent homogene co van vertex v1 */ register float x,y,z; x= v1[0]; y= v1[1]; z= v1[2]; adr[0]= x*G.winmat[0][0]+ y*G.winmat[1][0]+ z*G.winmat[2][0]+ G.winmat[3][0]; adr[1]= x*G.winmat[0][1]+ y*G.winmat[1][1]+ z*G.winmat[2][1]+ G.winmat[3][1]; adr[2]= x*G.winmat[0][2]+ y*G.winmat[1][2]+ z*G.winmat[2][2]+ G.winmat[3][2]; adr[3]= x*G.winmat[0][3]+ y*G.winmat[1][3]+ z*G.winmat[2][3]+ G.winmat[3][3]; } void zbufclip(f1, f2, f3, c1, c2, c3) float *f1, *f2, *f3; long c1, c2, c3; { float deler; if(c1 | c2 | c3) { /* niet in midden */ if(c1 & c2 & c3) { /* helemaal eruit */ return; } else { /* clippen */ long v, b, clipflag[3], b1, b2, b3, c4, clve=3, clvlo, clvl=1; vez[0]= f1[0]; vez[1]= f1[1]; vez[2]= f1[2]; vez[3]= f1[3]; vez[4]= f2[0]; vez[5]= f2[1]; vez[6]= f2[2]; vez[7]= f2[3]; vez[8]= f3[0]; vez[9]= f3[1]; vez[10]= f3[2];vez[11]= f3[3]; /* PRINT4(f, f, f, f, vez[0], vez[1], vez[2], vez[3]); */ /* PRINT4(f, f, f, f, vez[4], vez[5], vez[6], vez[7]); */ /* PRINT4(f, f, f, f, vez[8], vez[9], vez[10], vez[11]); */ vlzp[0][0]= vez; vlzp[0][1]= vez+4; vlzp[0][2]= vez+8; clipflag[0]= ( (c1 & 48) | (c2 & 48) | (c3 & 48) ); if(clipflag[0]==0) { /* anders opnieuw berekend verderop, na de eerste (z) clip */ clipflag[1]= ( (c1 & 3) | (c2 & 3) | (c3 & 3) ); clipflag[2]= ( (c1 & 12) | (c2 & 12) | (c3 & 12) ); } for(b=0;b<3;b++) { if(clipflag[b]) { clvlo= clvl; for(v=0; v2) { for(b3=3; b3<=b1; b3++) { vlzp[clvl][0]= p[0]; vlzp[clvl][1]= p[b3-2]; vlzp[clvl][2]= p[b3-1]; clvl++; } } } } } } /* printf("ronde %d clve %d clvl %d\n",b,clve,clvl); */ } /* persp deling */ /* valt hier nog te optimaliseren door alleen te gebruiken vertices te doen? */ if(clve>38) printf("clip overflow: clve clvl %d %d\n",clve,clvl); f1=vez; for(c1=0;c1firstface; for(v= 0; vpntsv-1; v++) { vs1= qs->verts+ v*qs->pntsu; vs2= vs1+ qs->pntsu; for(u= 0; upntsu-1; u++) { zbufclip(vs1->ho, (vs1+1)->ho, (vs2+1)->ho, vs1->clip, (vs1+1)->clip, (vs2+1)->clip); if(count) Zvlnr++; zbufclip(vs1->ho, (vs2+1)->ho, vs2->ho, vs1->clip, (vs2+1)->clip, vs2->clip); if(count) Zvlnr++; vs1++; vs2++; } } } void zbufferall(key) short key; { struct VlakRen *vlr; struct QStrip *qs; struct ColBlckF *cb=0; float *f1, *f2, *f3; long v,len; short transp=0, env=0, wire=0; Zmulx= ((float)R.rectx)/2.0; Zmuly= ((float)R.recty)/2.0; len= 4*R.rectx*R.recty; fillrect(R.rectz, R.rectx, R.recty, 0x7FFFFFFF); Zvlnr= 0; zbuffunc= zbufinvulGL; for(v=0;v>8]; else vlr++; Zvlnr= v+1; if(vlr->rt1) { if(vlr->col!=cb) { cb= vlr->col; transp= cb->mode & (64+128); env= (cb->mode & 32); wire= (cb->mode & 1024); if(cb->mode & 512) zbuffunc= zbufinvulGLinv; else zbuffunc= zbufinvulGL; } if(key) { if(env) Zvlnr= 0; else if(transp) Zvlnr= 0x010101*( (long) (255*(1.0-cb->tra)) ); else Zvlnr= 0xFFFFFF; if(wire) zbufclipwire(vlr); else zbufclip(vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip); } else if(transp==0) { if(env) Zvlnr= 0; if(wire) zbufclipwire(vlr); else zbufclip(vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip); } } } /* de QStrips */ /* qs= R.qstrip.first; while(qs) { Zvlnr= 0; if(R.f & (16+128) ) { transp= qs->col->mode & (64+128); env= qs->col->mode & 32; if(transp==0 || key) { if(env) Zvlnr= 0; else if(key) Zvlnr= (0x010101*(255- qs->col->tra)); zbufqstrip(qs); } else { if(key) Zvlnr= 0xFFFFFF; zbufqstrip(qs); } } qs= qs->next; } */ } void zbuffershad() { struct VlakRen *vlr; struct ColBlckF *col; long a,len, ok=1; Zmulx= ((float)R.rectx)/2.0; Zmuly= ((float)R.recty)/2.0; Zjitx= Zjity= -.5; len= 4*R.rectx*R.recty; fillrect(R.rectz,R.rectx,R.recty,0x7FFFFFFE); zbuffunc= zbufinvulGL_onlyZ; for(a=0;a>8]; else vlr++; if(vlr->col!= col) { col= vlr->col; ok= 1; if((col->mode & 4)==0) ok= 0; } /* traceble er weer in: automatische verwijdering niet geweldig */ if(vlr->rt1 && ok) { zbufclip(vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip); } } } /* ******************** ABUF ************************* */ void bgnaccumbuf() { Acolrow= mallocN(4*2*R.rectx, "Acolrow"); Arectz= mallocN(4*ABUFPART*R.rectx, "Arectz"); APixbuf= mallocN(ABUFPART*R.rectx*sizeof(struct APixstr), "APixbuf"); Aminy= -1000; Amaxy= -1000; apsmteller= 0; apsmfirst.next= 0; apsmfirst.ps= 0; } void endaccumbuf() { freeN(Acolrow); freeN(Arectz); freeN(APixbuf); freepsA(); } void copyto_abufz(sample) long sample; { struct PixStr *ps; long x, y, *rza; ulong *rd; memcpy(Arectz, R.rectz+ R.rectx*Aminy, 4*R.rectx*(Amaxy-Aminy+1)); if(G.ali==0 || sample==0) return; rza= Arectz; rd= (R.rectdaps+ R.rectx*Aminy); sample= (1<mask) { *rza= ps->z; break; } ps= ps->next; } } rd++; rza++; } } } void zbuffer_abuf() { /* gejitterd zbufferen met abufpixstructen */ extern float jit[64][2]; float vec[3], hoco[4], mul, zval, fval; struct ColBlckF *cb=0; long v, len; Zmulx= ((float)R.rectx)/2.0; Zmuly= ((float)R.recty)/2.0; /* clear APixstructen */ len= sizeof(struct APixstr)*R.rectx*ABUFPART; bzero(APixbuf, len); zbuffunc= zbufinvulAc; for(Zsample=0; Zsample>8]; } else Zvlr++; cb= Zvlr->col; if(cb->mode & (64+128)) { if( (cb->mode & 2) && cb->ang>0.0) { /* voordeeltje voor transp renderen */ mul= 0x7FFFFFFF; zval= mul*(1.0+Zvlr->v1->ho[2]/Zvlr->v1->ho[3]); VECCOPY(vec, Zvlr->v1->co); vec[2]-= 255.0*100.0*cb->ang; /* z is negatief, wordt anders geclipt */ projectverto(vec, hoco); fval= mul*(1.0+hoco[2]/hoco[3]); Azvoordeel= (long) fabs(zval - fval ); /* PATCH: als transp en niet transp dicht op elkaar liggen: Zbuf aliasing */ Azvoordeel+= 0xFFFF; } else Azvoordeel= 0xFFFF; Zvlnr= v+1; if(Zvlr->rt1) zbufclip(Zvlr->v1->ho, Zvlr->v2->ho, Zvlr->v3->ho, Zvlr->v1->clip, Zvlr->v2->clip, Zvlr->v3->clip); } if(G.afbreek) break; } if(G.ali==0) break; if(G.afbreek) break; } } void addAlphaOverShort(doel,bron) /* vult bron over doel in met alpha van bron */ register ushort *doel,*bron; /* controleert op overflow */ { register ulong c; register ulong mul; if( doel[0]==0 || bron[0]>=0xFFF0) { /* is getest, scheelt veel */ *((ulong *)doel)= *((ulong *)bron); *((ulong *)(doel+2))= *((ulong *)(bron+2)); return; } mul= 0xFFFF-bron[0]; c= ((mul*doel[3])>>16)+bron[3]; if(c>=0xFFF0) doel[3]=0xFFF0; else doel[3]= c; c= ((mul*doel[2])>>16)+bron[2]; if(c>=0xFFF0) doel[2]=0xFFF0; else doel[2]= c; c= ((mul*doel[1])>>16)+bron[1]; if(c>=0xFFF0) doel[1]=0xFFF0; else doel[1]= c; c= ((mul*doel[0])>>16)+bron[0]; if(c>=0xFFF0) doel[0]=0xFFF0; else doel[0]= c; } void addAlphaUnderShort(doel, bron) /* vult bron onder doel in met alpha van doel */ register ushort *doel, *bron; /* controleert op overflow */ { register ulong c; register ulong mul; if(doel[0]>=0xFFF0) return; if( doel[0]==0 ) { /* is getest, scheelt veel */ *((ulong *)doel)= *((ulong *)bron); *((ulong *)(doel+2))= *((ulong *)(bron+2)); return; } mul= 0xFFFF-doel[0]; c= ((mul*bron[3])>>16)+doel[3]; if(c>=0xFFF0) doel[3]=0xFFF0; else doel[3]= c; c= ((mul*bron[2])>>16)+doel[2]; if(c>=0xFFF0) doel[2]=0xFFF0; else doel[2]= c; c= ((mul*bron[1])>>16)+doel[1]; if(c>=0xFFF0) doel[1]=0xFFF0; else doel[1]= c; c= ((mul*bron[0])>>16)+doel[0]; if(c>=0xFFF0) doel[0]=0xFFF0; else doel[0]= c; } int addtosampcol(sampcol, shortcol, mask) ushort *sampcol, *shortcol; long mask; { int a, retval=G.osa; for(a=0; a0xFFF0) retval--; sampcol+= 4; } return retval; } long vergzvlak(x1,x2) long *x1,*x2; { if( x1[0] < x2[0] ) return 1; else if( x1[0] > x2[0]) return -1; return 0; } void shadetrapixel(x, y, vlak) float x, y; long vlak; { extern ushort shortcol[4]; struct VlakRen *addvlak(); long alpha; char charcol[12]; if(vlak<0 || vlak>G.totvlak) { printf("error in shadetrapixel nr: %d\n", vlak); return; } Zvlr= addvlak(vlak-1); if(Zvlr->col->mode & 64) { shadegour(Zvlr, charcol); shortcol[0]= 65535*(1.0-Zvlr->col->tra); alpha= shortcol[0]/(768); shortcol[1]= alpha*(charcol[1]+charcol[5]+charcol[9]); shortcol[2]= alpha*(charcol[2]+charcol[6]+charcol[10]); shortcol[3]= alpha*(charcol[3]+charcol[7]+charcol[11]); } else { shadepixel(x, y, vlak); } } void abufsetrow(y) long y; { extern ushort usegamtab; extern ushort shortcol[4]; struct APixstr *ap, *apn; float xs, ys; long x, part, a, b, zrow[100][3], totvlak, alpha[32], tempgam, nr, mask, longcol[4]; int tempRf, sval; ushort *col, tempcol[4], sampcol[16*4], *scol; if(y<0) return; tempRf= R.f; R.f &= ~4096; /* alpha LUT */ x= (65536/G.osa); for(a=0; a<=G.osa; a++) { alpha[a]= a*x; } /* moet pixbuf worden gemaakt? */ if(yAmaxy) { part= (y/ABUFPART); Aminy= part*ABUFPART; Amaxy= Aminy+ABUFPART-1; if(Amaxy>=R.recty) Amaxy= R.recty-1; freepsA(); zbuffer_abuf(); } /* render rij */ col= Acolrow; bzero(col, 2*4*R.rectx); ap= APixbuf+R.rectx*(y-Aminy); ys= y; tempgam= usegamtab; usegamtab= 0; for(x=0; xp[0]) { /* sorteer op z */ totvlak= 0; apn= ap; while(apn) { for(a=0; a<4; a++) { if(apn->p[a]) { zrow[totvlak][0]= apn->z[a]; zrow[totvlak][1]= apn->p[a]; zrow[totvlak][2]= apn->mask[a]; totvlak++; if(totvlak>99) totvlak= 99; } else break; } apn= apn->next; } if(totvlak==1) { if(G.ali) { b= centmask[ ap->mask[0] ]; xs= (float)x+centLut[b & 15]; ys= (float)y+centLut[b>>4]; } else { xs= x; ys= y; } shadetrapixel(xs, ys, ap->p[0]); nr= count_mask(ap->mask[0]); if(G.ali && nr>16; col[1]= (shortcol[1]*a)>>16; col[2]= (shortcol[2]*a)>>16; col[3]= (shortcol[3]*a)>>16; } else { col[0]= shortcol[0]; col[1]= shortcol[1]; col[2]= shortcol[2]; col[3]= shortcol[3]; } } else { if(totvlak==2) { if(zrow[0][0] < zrow[1][0]) { a= zrow[0][0]; zrow[0][0]= zrow[1][0]; zrow[1][0]= a; a= zrow[0][1]; zrow[0][1]= zrow[1][1]; zrow[1][1]= a; a= zrow[0][2]; zrow[0][2]= zrow[1][2]; zrow[1][2]= a; } } else { /* totvlak>2 */ qsort(zrow, totvlak, 12, vergzvlak); } /* samenvoegen als pixels aanvullen */ while(totvlak>0) { totvlak--; if(G.ali) { b= centmask[ zrow[totvlak][2] ]; xs= (float)x+centLut[b & 15]; ys= (float)y+centLut[b>>4]; } else { xs= x; ys= y; } shadetrapixel(xs, ys, zrow[totvlak][1]); a= count_mask(zrow[totvlak][2]); if(G.ali && a0) { bzero(sampcol, 4*2*G.osa); sval= addtosampcol(sampcol, shortcol, zrow[totvlak][2]); /* sval==0: alpha helemaal vol */ if(sval) { while(totvlak>0) { a= count_mask(zrow[totvlak-1][2]); if(a==G.osa) break; totvlak--; b= centmask[ zrow[totvlak][2] ]; xs= (float)x+centLut[b & 15]; ys= (float)y+centLut[b>>4]; shadetrapixel(xs, ys, zrow[totvlak][1]); sval= addtosampcol(sampcol, shortcol, zrow[totvlak][2]); if(sval==0) break; } } scol= sampcol; longcol[0]= scol[0]; longcol[1]= scol[1]; longcol[2]= scol[2]; longcol[3]= scol[3]; scol+= 4; for(a=1; a>16; shortcol[1]= (shortcol[1]*a)>>16; shortcol[2]= (shortcol[2]*a)>>16; shortcol[3]= (shortcol[3]*a)>>16; addAlphaUnderShort(col, shortcol); } } else addAlphaUnderShort(col, shortcol); if(col[0]>=0xFFF0) break; } } } } usegamtab= tempgam; R.f= tempRf; }