Panda3D
 All Classes Functions Variables Enumerations
ztriangle.h
00001 /*
00002  * We draw a triangle with various interpolations
00003  */
00004 
00005 {
00006   ZBufferPoint *t,*pr1,*pr2,*l1,*l2;
00007   PN_stdfloat fdx1, fdx2, fdy1, fdy2, fz, d1, d2;
00008   ZPOINT *pz1;
00009   PIXEL *pp1;
00010   int part, update_left, update_right;
00011 
00012   int nb_lines, dx1, dy1, tmp, dx2, dy2;
00013 
00014   int error, derror;
00015   int x1, dxdy_min, dxdy_max;
00016   /* warning: x2 is multiplied by 2^16 */
00017   int x2, dx2dy2;  
00018 
00019 #ifdef INTERP_Z
00020   int z1 = 0, dzdx = 0, dzdy = 0, dzdl_min = 0, dzdl_max = 0;
00021 #endif
00022 #ifdef INTERP_RGB
00023   int r1 = 0, drdx = 0, drdy = 0, drdl_min = 0, drdl_max = 0;
00024   int g1 = 0, dgdx = 0, dgdy = 0, dgdl_min = 0, dgdl_max = 0;
00025   int b1 = 0, dbdx = 0, dbdy = 0, dbdl_min = 0, dbdl_max = 0;
00026   int a1 = 0, dadx = 0, dady = 0, dadl_min = 0, dadl_max = 0;
00027 #endif
00028 #ifdef INTERP_ST
00029   int s1 = 0, dsdx = 0, dsdy = 0, dsdl_min = 0, dsdl_max = 0;
00030   int t1 = 0, dtdx = 0, dtdy = 0, dtdl_min = 0, dtdl_max = 0;
00031 #endif
00032 #ifdef INTERP_STZ
00033   PN_stdfloat sz1 = 0, dszdx = 0, dszdy = 0, dszdl_min = 0, dszdl_max = 0;
00034   PN_stdfloat tz1 = 0, dtzdx = 0, dtzdy = 0, dtzdl_min = 0, dtzdl_max = 0;
00035 #endif
00036 #ifdef INTERP_STZA
00037   PN_stdfloat sza1 = 0, dszadx = 0, dszady = 0, dszadl_min = 0, dszadl_max = 0;
00038   PN_stdfloat tza1 = 0, dtzadx = 0, dtzady = 0, dtzadl_min = 0, dtzadl_max = 0;
00039 #endif
00040 #ifdef INTERP_STZB
00041   PN_stdfloat szb1 = 0, dszbdx = 0, dszbdy = 0, dszbdl_min = 0, dszbdl_max = 0;
00042   PN_stdfloat tzb1 = 0, dtzbdx = 0, dtzbdy = 0, dtzbdl_min = 0, dtzbdl_max = 0;
00043 #endif
00044 #if defined(INTERP_MIPMAP) && (defined(INTERP_ST) || defined(INTERP_STZ))
00045   unsigned int mipmap_dx = 0, mipmap_level = 0;
00046 #endif
00047 #if defined(INTERP_MIPMAP) && defined(INTERP_STZA)
00048   unsigned int mipmap_dxa = 0, mipmap_levela = 0;
00049 #endif
00050 #if defined(INTERP_MIPMAP) && defined(INTERP_STZB)
00051   unsigned int mipmap_dxb = 0, mipmap_levelb = 0;
00052 #endif
00053 
00054   EARLY_OUT();
00055 
00056   COUNT_PIXELS(PIXEL_COUNT, p0, p1, p2);
00057 
00058   /* we sort the vertex with increasing y */
00059   if (p1->y < p0->y) {
00060     t = p0;
00061     p0 = p1;
00062     p1 = t;
00063   }
00064   if (p2->y < p0->y) {
00065     t = p2;
00066     p2 = p1;
00067     p1 = p0;
00068     p0 = t;
00069   } else if (p2->y < p1->y) {
00070     t = p1;
00071     p1 = p2;
00072     p2 = t;
00073   }
00074 
00075   /* we compute dXdx and dXdy for all interpolated values */
00076   
00077   fdx1 = (PN_stdfloat) (p1->x - p0->x);
00078   fdy1 = (PN_stdfloat) (p1->y - p0->y);
00079 
00080   fdx2 = (PN_stdfloat) (p2->x - p0->x);
00081   fdy2 = (PN_stdfloat) (p2->y - p0->y);
00082 
00083   fz = fdx1 * fdy2 - fdx2 * fdy1;
00084   if (fz == 0)
00085     return;
00086   fz = 1.0f / fz;
00087 
00088   fdx1 *= fz;
00089   fdy1 *= fz;
00090   fdx2 *= fz;
00091   fdy2 *= fz;
00092 
00093 #ifdef INTERP_Z
00094   d1 = (PN_stdfloat) (p1->z - p0->z);
00095   d2 = (PN_stdfloat) (p2->z - p0->z);
00096   dzdx = (int) (fdy2 * d1 - fdy1 * d2);
00097   dzdy = (int) (fdx1 * d2 - fdx2 * d1);
00098 #endif
00099 
00100 #ifdef INTERP_RGB
00101   d1 = (PN_stdfloat) (p1->r - p0->r);
00102   d2 = (PN_stdfloat) (p2->r - p0->r);
00103   drdx = (int) (fdy2 * d1 - fdy1 * d2);
00104   drdy = (int) (fdx1 * d2 - fdx2 * d1);
00105 
00106   d1 = (PN_stdfloat) (p1->g - p0->g);
00107   d2 = (PN_stdfloat) (p2->g - p0->g);
00108   dgdx = (int) (fdy2 * d1 - fdy1 * d2);
00109   dgdy = (int) (fdx1 * d2 - fdx2 * d1);
00110 
00111   d1 = (PN_stdfloat) (p1->b - p0->b);
00112   d2 = (PN_stdfloat) (p2->b - p0->b);
00113   dbdx = (int) (fdy2 * d1 - fdy1 * d2);
00114   dbdy = (int) (fdx1 * d2 - fdx2 * d1);
00115 
00116   d1 = (PN_stdfloat) (p1->a - p0->a);
00117   d2 = (PN_stdfloat) (p2->a - p0->a);
00118   dadx = (int) (fdy2 * d1 - fdy1 * d2);
00119   dady = (int) (fdx1 * d2 - fdx2 * d1);
00120 
00121 #endif
00122   
00123 #ifdef INTERP_ST
00124   d1 = (PN_stdfloat) (p1->s - p0->s);
00125   d2 = (PN_stdfloat) (p2->s - p0->s);
00126   dsdx = (int) (fdy2 * d1 - fdy1 * d2);
00127   dsdy = (int) (fdx1 * d2 - fdx2 * d1);
00128   
00129   d1 = (PN_stdfloat) (p1->t - p0->t);
00130   d2 = (PN_stdfloat) (p2->t - p0->t);
00131   dtdx = (int) (fdy2 * d1 - fdy1 * d2);
00132   dtdy = (int) (fdx1 * d2 - fdx2 * d1);
00133 
00134   CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx);
00135 #endif
00136 
00137 #ifdef INTERP_STZ
00138   {
00139     PN_stdfloat zz;
00140     zz=(PN_stdfloat) p0->z;
00141     p0->sz= (PN_stdfloat) p0->s * zz;
00142     p0->tz= (PN_stdfloat) p0->t * zz;
00143     zz=(PN_stdfloat) p1->z;
00144     p1->sz= (PN_stdfloat) p1->s * zz;
00145     p1->tz= (PN_stdfloat) p1->t * zz;
00146     zz=(PN_stdfloat) p2->z;
00147     p2->sz= (PN_stdfloat) p2->s * zz;
00148     p2->tz= (PN_stdfloat) p2->t * zz;
00149 
00150     d1 = p1->sz - p0->sz;
00151     d2 = p2->sz - p0->sz;
00152     dszdx = (fdy2 * d1 - fdy1 * d2);
00153     dszdy = (fdx1 * d2 - fdx2 * d1);
00154     
00155     d1 = p1->tz - p0->tz;
00156     d2 = p2->tz - p0->tz;
00157     dtzdx = (fdy2 * d1 - fdy1 * d2);
00158     dtzdy = (fdx1 * d2 - fdx2 * d1);
00159   }
00160 #endif
00161 
00162 #ifdef INTERP_STZA
00163   {
00164     PN_stdfloat zz;
00165     zz=(PN_stdfloat) p0->z;
00166     p0->sza= (PN_stdfloat) p0->sa * zz;
00167     p0->tza= (PN_stdfloat) p0->ta * zz;
00168     zz=(PN_stdfloat) p1->z;
00169     p1->sza= (PN_stdfloat) p1->sa * zz;
00170     p1->tza= (PN_stdfloat) p1->ta * zz;
00171     zz=(PN_stdfloat) p2->z;
00172     p2->sza= (PN_stdfloat) p2->sa * zz;
00173     p2->tza= (PN_stdfloat) p2->ta * zz;
00174 
00175     d1 = p1->sza - p0->sza;
00176     d2 = p2->sza - p0->sza;
00177     dszadx = (fdy2 * d1 - fdy1 * d2);
00178     dszady = (fdx1 * d2 - fdx2 * d1);
00179     
00180     d1 = p1->tza - p0->tza;
00181     d2 = p2->tza - p0->tza;
00182     dtzadx = (fdy2 * d1 - fdy1 * d2);
00183     dtzady = (fdx1 * d2 - fdx2 * d1);
00184   }
00185 #endif
00186 
00187 #ifdef INTERP_STZB
00188   {
00189     PN_stdfloat zz;
00190     zz=(PN_stdfloat) p0->z;
00191     p0->szb= (PN_stdfloat) p0->sb * zz;
00192     p0->tzb= (PN_stdfloat) p0->tb * zz;
00193     zz=(PN_stdfloat) p1->z;
00194     p1->szb= (PN_stdfloat) p1->sb * zz;
00195     p1->tzb= (PN_stdfloat) p1->tb * zz;
00196     zz=(PN_stdfloat) p2->z;
00197     p2->szb= (PN_stdfloat) p2->sb * zz;
00198     p2->tzb= (PN_stdfloat) p2->tb * zz;
00199 
00200     d1 = p1->szb - p0->szb;
00201     d2 = p2->szb - p0->szb;
00202     dszbdx = (fdy2 * d1 - fdy1 * d2);
00203     dszbdy = (fdx1 * d2 - fdx2 * d1);
00204     
00205     d1 = p1->tzb - p0->tzb;
00206     d2 = p2->tzb - p0->tzb;
00207     dtzbdx = (fdy2 * d1 - fdy1 * d2);
00208     dtzbdy = (fdx1 * d2 - fdx2 * d1);
00209   }
00210 #endif
00211 
00212   /* screen coordinates */
00213 
00214   pp1 = (PIXEL *) ((char *) zb->pbuf + zb->linesize * p0->y);
00215   pz1 = zb->zbuf + p0->y * zb->xsize;
00216 
00217   DRAW_INIT();
00218 
00219   for(part=0;part<2;part++) {
00220     if (part == 0) {
00221       if (fz > 0) {
00222         update_left=1;
00223         update_right=1;
00224         l1=p0;
00225         l2=p2;
00226         pr1=p0;
00227         pr2=p1;
00228       } else {
00229         update_left=1;
00230         update_right=1;
00231         l1=p0;
00232         l2=p1;
00233         pr1=p0;
00234         pr2=p2;
00235       }
00236       nb_lines = p1->y - p0->y;
00237     } else {
00238       /* second part */
00239       if (fz > 0) {
00240         update_left=0;
00241         update_right=1;
00242         pr1=p1;
00243         pr2=p2;
00244       } else {
00245         update_left=1;
00246         update_right=0;
00247         l1=p1; 
00248         l2=p2;
00249       }
00250       nb_lines = p2->y - p1->y + 1;
00251     }
00252 
00253     /* compute the values for the left edge */
00254 
00255     if (update_left) {
00256       dy1 = l2->y - l1->y;
00257       dx1 = l2->x - l1->x;
00258       if (dy1 > 0) 
00259         tmp = (dx1 << 16) / dy1;
00260       else
00261         tmp = 0;
00262       x1 = l1->x;
00263       error = 0;
00264       derror = tmp & 0x0000ffff;
00265       dxdy_min = tmp >> 16;
00266       dxdy_max = dxdy_min + 1;
00267       
00268 #ifdef INTERP_Z
00269       z1=l1->z;
00270       dzdl_min=(dzdy + dzdx * dxdy_min); 
00271       dzdl_max=dzdl_min + dzdx;
00272 #endif
00273 #ifdef INTERP_RGB
00274       r1=l1->r;
00275       drdl_min=(drdy + drdx * dxdy_min);
00276       drdl_max=drdl_min + drdx;
00277       
00278       g1=l1->g;
00279       dgdl_min=(dgdy + dgdx * dxdy_min);
00280       dgdl_max=dgdl_min + dgdx;
00281       
00282       b1=l1->b;
00283       dbdl_min=(dbdy + dbdx * dxdy_min);
00284       dbdl_max=dbdl_min + dbdx;
00285       
00286       a1=l1->a;
00287       dadl_min=(dady + dadx * dxdy_min);
00288       dadl_max=dadl_min + dadx;
00289 #endif
00290 #ifdef INTERP_ST
00291       s1=l1->s;
00292       dsdl_min=(dsdy + dsdx * dxdy_min);
00293       dsdl_max=dsdl_min + dsdx;
00294       
00295       t1=l1->t;
00296       dtdl_min=(dtdy + dtdx * dxdy_min);
00297       dtdl_max=dtdl_min + dtdx;
00298 #endif
00299 #ifdef INTERP_STZ
00300       sz1=l1->sz;
00301       dszdl_min=(dszdy + dszdx * dxdy_min);
00302       dszdl_max=dszdl_min + dszdx;
00303       
00304       tz1=l1->tz;
00305       dtzdl_min=(dtzdy + dtzdx * dxdy_min);
00306       dtzdl_max=dtzdl_min + dtzdx;
00307 #endif
00308 #ifdef INTERP_STZA
00309       sza1=l1->sza;
00310       dszadl_min=(dszady + dszadx * dxdy_min);
00311       dszadl_max=dszadl_min + dszadx;
00312       
00313       tza1=l1->tza;
00314       dtzadl_min=(dtzady + dtzadx * dxdy_min);
00315       dtzadl_max=dtzadl_min + dtzadx;
00316 #endif
00317 #ifdef INTERP_STZB
00318       szb1=l1->szb;
00319       dszbdl_min=(dszbdy + dszbdx * dxdy_min);
00320       dszbdl_max=dszbdl_min + dszbdx;
00321       
00322       tzb1=l1->tzb;
00323       dtzbdl_min=(dtzbdy + dtzbdx * dxdy_min);
00324       dtzbdl_max=dtzbdl_min + dtzbdx;
00325 #endif
00326     }
00327 
00328     /* compute values for the right edge */
00329 
00330     if (update_right) {
00331       dx2 = (pr2->x - pr1->x);
00332       dy2 = (pr2->y - pr1->y);
00333       if (dy2>0) 
00334         dx2dy2 = ( dx2 << 16) / dy2;
00335       else
00336         dx2dy2 = 0;
00337       x2 = pr1->x << 16;
00338     }
00339 
00340     /* we draw all the scan line of the part */
00341 
00342     while (nb_lines>0) {
00343       nb_lines--;
00344 #ifndef DRAW_LINE
00345       /* generic draw line */
00346       {
00347         register PIXEL *pp;
00348         register int n;
00349 #ifdef INTERP_Z
00350         register ZPOINT *pz;
00351         register unsigned int z,zz;
00352 #endif
00353 #ifdef INTERP_RGB
00354         register unsigned int or1,og1,ob1,oa1;
00355 #endif
00356 #ifdef INTERP_ST
00357         register unsigned int s,t;
00358 #endif
00359 #ifdef INTERP_STZ
00360         PN_stdfloat sz,tz;
00361 #endif
00362 #ifdef INTERP_STZA
00363         PN_stdfloat sza,tza;
00364 #endif
00365 #ifdef INTERP_STZB
00366         PN_stdfloat szb,tzb;
00367 #endif
00368 
00369         n=(x2 >> 16) - x1;
00370         pp=(PIXEL *)((char *)pp1 + x1 * PSZB);
00371 #ifdef INTERP_Z
00372         pz=pz1+x1;
00373         z=z1;
00374 #endif
00375 #ifdef INTERP_RGB
00376         or1 = r1;
00377         og1 = g1;
00378         ob1 = b1;
00379         oa1 = a1;
00380 #endif
00381 #ifdef INTERP_ST
00382         s=s1;
00383         t=t1;
00384 #endif
00385 #ifdef INTERP_STZ
00386         sz=sz1;
00387         tz=tz1;
00388 #endif
00389 #ifdef INTERP_STZA
00390         sza=sza1;
00391         tza=tza1;
00392 #endif
00393 #ifdef INTERP_STZB
00394         szb=szb1;
00395         tzb=tzb1;
00396 #endif
00397         while (n>=3) {
00398           PUT_PIXEL(0);
00399           PUT_PIXEL(1);
00400           PUT_PIXEL(2);
00401           PUT_PIXEL(3);
00402 #ifdef INTERP_Z
00403           pz+=4;
00404 #endif
00405           pp=(PIXEL *)((char *)pp + 4 * PSZB);
00406           n-=4;
00407         }
00408         while (n>=0) {
00409           PUT_PIXEL(0);
00410 #ifdef INTERP_Z
00411           pz+=1;
00412 #endif
00413           pp=(PIXEL *)((char *)pp + PSZB);
00414           n-=1;
00415         }
00416       }
00417 #else
00418       DRAW_LINE();
00419 #endif
00420       
00421       /* left edge */
00422       error+=derror;
00423       if (error > 0) {
00424         error-=0x10000;
00425         x1+=dxdy_max;
00426 #ifdef INTERP_Z
00427         z1+=dzdl_max;
00428 #endif      
00429 #ifdef INTERP_RGB
00430         r1+=drdl_max;
00431         g1+=dgdl_max;
00432         b1+=dbdl_max;
00433         a1+=dadl_max;
00434 #endif
00435 #ifdef INTERP_ST
00436         s1+=dsdl_max;
00437         t1+=dtdl_max;
00438 #endif
00439 #ifdef INTERP_STZ
00440         sz1+=dszdl_max;
00441         tz1+=dtzdl_max;
00442 #endif
00443 #ifdef INTERP_STZA
00444         sza1+=dszadl_max;
00445         tza1+=dtzadl_max;
00446 #endif
00447 #ifdef INTERP_STZB
00448         szb1+=dszbdl_max;
00449         tzb1+=dtzbdl_max;
00450 #endif
00451       } else {
00452         x1+=dxdy_min;
00453 #ifdef INTERP_Z
00454         z1+=dzdl_min;
00455 #endif      
00456 #ifdef INTERP_RGB
00457         r1+=drdl_min;
00458         g1+=dgdl_min;
00459         b1+=dbdl_min;
00460         a1+=dadl_min;
00461 #endif
00462 #ifdef INTERP_ST
00463         s1+=dsdl_min;
00464         t1+=dtdl_min;
00465 #endif
00466 #ifdef INTERP_STZ
00467         sz1+=dszdl_min;
00468         tz1+=dtzdl_min;
00469 #endif
00470 #ifdef INTERP_STZA
00471         sza1+=dszadl_min;
00472         tza1+=dtzadl_min;
00473 #endif
00474 #ifdef INTERP_STZB
00475         szb1+=dszbdl_min;
00476         tzb1+=dtzbdl_min;
00477 #endif
00478       } 
00479       
00480       /* right edge */
00481       x2+=dx2dy2;
00482 
00483       /* screen coordinates */
00484       pp1=(PIXEL *)((char *)pp1 + zb->linesize);
00485       pz1+=zb->xsize;
00486     }
00487   }
00488 }
00489 
00490 #undef INTERP_Z
00491 #undef INTERP_RGB
00492 #undef INTERP_ST
00493 #undef INTERP_STZ
00494 #undef INTERP_STZA
00495 #undef INTERP_STZB
00496 
00497 #undef EARLY_OUT
00498 #undef EARLY_OUT_FZ
00499 #undef DRAW_INIT
00500 #undef DRAW_LINE  
00501 #undef PUT_PIXEL
00502 #undef PIXEL_COUNT
 All Classes Functions Variables Enumerations