/* * We draw a triangle with various interpolations */ { ZBufferPoint *t,*pr1,*pr2,*l1,*l2; float fdx1, fdx2, fdy1, fdy2, fz, d1, d2; unsigned short *pz1; PIXEL *pp1; int part,update_left,update_right; int nb_lines,dx1,dy1,tmp,dx2,dy2; int error,derror; int x1,dxdy_min,dxdy_max; /* warning: x2 is multiplied by 2^16 */ int x2,dx2dy2; #ifdef INTERP_Z int z1,dzdx,dzdy,dzdl_min,dzdl_max; #endif #ifdef INTERP_RGB int r1,drdx,drdy,drdl_min,drdl_max; int g1,dgdx,dgdy,dgdl_min,dgdl_max; int b1,dbdx,dbdy,dbdl_min,dbdl_max; #endif #ifdef INTERP_ST int s1,dsdx,dsdy,dsdl_min,dsdl_max; int t1,dtdx,dtdy,dtdl_min,dtdl_max; #endif #ifdef INTERP_STZ float sz1,dszdx,dszdy,dszdl_min,dszdl_max; float tz1,dtzdx,dtzdy,dtzdl_min,dtzdl_max; #endif t = pr1 = pr2 = l1 = l2 = NULL; x1 = dxdy_min = dxdy_max = error = derror = 0; x2 = dx2dy2 = 0; #ifdef INTERP_Z z1 = dzdl_min = dzdl_max = 0; #endif #ifdef INTERP_RGB r1 = drdl_min = drdl_max = g1 = b1 = dgdl_min = dgdl_max = 0; dbdl_min = dbdl_max = 0; #endif #ifdef INTERP_ST s1 = t1 = dsdl_min = dtdl_min = dsdl_max = dtdl_max = 0; #endif #ifdef INTERP_STZ sz1 = tz1 = dszdl_max = dszdl_min = dtzdl_min = dtzdl_max = 0; #endif /* we sort the vertex with increasing y */ if (p1->y < p0->y) { t = p0; p0 = p1; p1 = t; } if (p2->y < p0->y) { t = p2; p2 = p1; p1 = p0; p0 = t; } else if (p2->y < p1->y) { t = p1; p1 = p2; p2 = t; } /* we compute dXdx and dXdy for all interpolated values */ fdx1 = p1->x - p0->x; fdy1 = p1->y - p0->y; fdx2 = p2->x - p0->x; fdy2 = p2->y - p0->y; fz = fdx1 * fdy2 - fdx2 * fdy1; if (fz == 0) return; fz = 1.0 / fz; fdx1 *= fz; fdy1 *= fz; fdx2 *= fz; fdy2 *= fz; #ifdef INTERP_Z d1 = p1->z - p0->z; d2 = p2->z - p0->z; dzdx = (int) (fdy2 * d1 - fdy1 * d2); dzdy = (int) (fdx1 * d2 - fdx2 * d1); #endif #ifdef INTERP_RGB d1 = p1->r - p0->r; d2 = p2->r - p0->r; drdx = (int) (fdy2 * d1 - fdy1 * d2); drdy = (int) (fdx1 * d2 - fdx2 * d1); d1 = p1->g - p0->g; d2 = p2->g - p0->g; dgdx = (int) (fdy2 * d1 - fdy1 * d2); dgdy = (int) (fdx1 * d2 - fdx2 * d1); d1 = p1->b - p0->b; d2 = p2->b - p0->b; dbdx = (int) (fdy2 * d1 - fdy1 * d2); dbdy = (int) (fdx1 * d2 - fdx2 * d1); #endif #ifdef INTERP_ST d1 = p1->s - p0->s; d2 = p2->s - p0->s; dsdx = (int) (fdy2 * d1 - fdy1 * d2); dsdy = (int) (fdx1 * d2 - fdx2 * d1); d1 = p1->t - p0->t; d2 = p2->t - p0->t; dtdx = (int) (fdy2 * d1 - fdy1 * d2); dtdy = (int) (fdx1 * d2 - fdx2 * d1); #endif #ifdef INTERP_STZ { float zz; zz=(float) p0->z; p0->sz= (float) p0->s * zz; p0->tz= (float) p0->t * zz; zz=(float) p1->z; p1->sz= (float) p1->s * zz; p1->tz= (float) p1->t * zz; zz=(float) p2->z; p2->sz= (float) p2->s * zz; p2->tz= (float) p2->t * zz; d1 = p1->sz - p0->sz; d2 = p2->sz - p0->sz; dszdx = (fdy2 * d1 - fdy1 * d2); dszdy = (fdx1 * d2 - fdx2 * d1); d1 = p1->tz - p0->tz; d2 = p2->tz - p0->tz; dtzdx = (fdy2 * d1 - fdy1 * d2); dtzdy = (fdx1 * d2 - fdx2 * d1); } #endif /* screen coordinates */ pp1 = (PIXEL *) ((char *) zb->pbuf + zb->linesize * p0->y); pz1 = zb->zbuf + p0->y * zb->xsize; DRAW_INIT(); for(part=0;part<2;part++) { if (part == 0) { if (fz > 0) { update_left=1; update_right=1; l1=p0; l2=p2; pr1=p0; pr2=p1; } else { update_left=1; update_right=1; l1=p0; l2=p1; pr1=p0; pr2=p2; } nb_lines = p1->y - p0->y; } else { /* second part */ if (fz > 0) { update_left=0; update_right=1; pr1=p1; pr2=p2; } else { update_left=1; update_right=0; l1=p1; l2=p2; } nb_lines = p2->y - p1->y + 1; } /* compute the values for the left edge */ if (update_left) { dy1 = l2->y - l1->y; dx1 = l2->x - l1->x; if (dy1 > 0) tmp = (dx1 << 16) / dy1; else tmp = 0; x1 = l1->x; error = 0; derror = tmp & 0x0000ffff; dxdy_min = tmp >> 16; dxdy_max = dxdy_min + 1; #ifdef INTERP_Z z1=l1->z; dzdl_min=(dzdy + dzdx * dxdy_min); dzdl_max=dzdl_min + dzdx; #endif #ifdef INTERP_RGB r1=l1->r; drdl_min=(drdy + drdx * dxdy_min); drdl_max=drdl_min + drdx; g1=l1->g; dgdl_min=(dgdy + dgdx * dxdy_min); dgdl_max=dgdl_min + dgdx; b1=l1->b; dbdl_min=(dbdy + dbdx * dxdy_min); dbdl_max=dbdl_min + dbdx; #endif #ifdef INTERP_ST s1=l1->s; dsdl_min=(dsdy + dsdx * dxdy_min); dsdl_max=dsdl_min + dsdx; t1=l1->t; dtdl_min=(dtdy + dtdx * dxdy_min); dtdl_max=dtdl_min + dtdx; #endif #ifdef INTERP_STZ sz1=l1->sz; dszdl_min=(dszdy + dszdx * dxdy_min); dszdl_max=dszdl_min + dszdx; tz1=l1->tz; dtzdl_min=(dtzdy + dtzdx * dxdy_min); dtzdl_max=dtzdl_min + dtzdx; #endif } /* compute values for the right edge */ if (update_right) { dx2 = (pr2->x - pr1->x); dy2 = (pr2->y - pr1->y); if (dy2>0) dx2dy2 = ( dx2 << 16) / dy2; else dx2dy2 = 0; x2 = pr1->x << 16; } /* we draw all the scan line of the part */ while (nb_lines>0) { nb_lines--; #ifndef DRAW_LINE /* generic draw line */ { register PIXEL *pp; register int n; #ifdef INTERP_Z register unsigned short *pz; register unsigned int z,zz; #endif #ifdef INTERP_RGB register unsigned int or1,og1,ob1; #endif #ifdef INTERP_ST register unsigned int s,t; #endif #ifdef INTERP_STZ float sz,tz; #endif n=(x2 >> 16) - x1; pp=(PIXEL *)((char *)pp1 + x1 * PSZB); #ifdef INTERP_Z pz=pz1+x1; z=z1; #endif #ifdef INTERP_RGB or1 = r1; og1 = g1; ob1 = b1; #endif #ifdef INTERP_ST s=s1; t=t1; #endif #ifdef INTERP_STZ sz=sz1; tz=tz1; #endif while (n>=3) { PUT_PIXEL(0); PUT_PIXEL(1); PUT_PIXEL(2); PUT_PIXEL(3); #ifdef INTERP_Z pz+=4; #endif pp=(PIXEL *)((char *)pp + 4 * PSZB); n-=4; } while (n>=0) { PUT_PIXEL(0); #ifdef INTERP_Z pz+=1; #endif pp=(PIXEL *)((char *)pp + PSZB); n-=1; } } #else DRAW_LINE(); #endif /* left edge */ error+=derror; if (error > 0) { error-=0x10000; x1+=dxdy_max; #ifdef INTERP_Z z1+=dzdl_max; #endif #ifdef INTERP_RGB r1+=drdl_max; g1+=dgdl_max; b1+=dbdl_max; #endif #ifdef INTERP_ST s1+=dsdl_max; t1+=dtdl_max; #endif #ifdef INTERP_STZ sz1+=dszdl_max; tz1+=dtzdl_max; #endif } else { x1+=dxdy_min; #ifdef INTERP_Z z1+=dzdl_min; #endif #ifdef INTERP_RGB r1+=drdl_min; g1+=dgdl_min; b1+=dbdl_min; #endif #ifdef INTERP_ST s1+=dsdl_min; t1+=dtdl_min; #endif #ifdef INTERP_STZ sz1+=dszdl_min; tz1+=dtzdl_min; #endif } /* right edge */ x2+=dx2dy2; /* screen coordinates */ pp1=(PIXEL *)((char *)pp1 + zb->linesize); pz1+=zb->xsize; } } } #undef INTERP_Z #undef INTERP_RGB #undef INTERP_ST #undef INTERP_STZ #undef DRAW_INIT #undef DRAW_LINE #undef PUT_PIXEL