0,0 → 1,363 |
/* |
* 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 |
|
/* 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 |