home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / FAQSYS18.ZIP / FAQS.DAT / HECKER.TXT < prev    next >
Text File  |  1996-01-11  |  7KB  |  266 lines

  1. Listing 1. Perspective Texture Mapper
  2. #include<windows.h>
  3. #include<math.h>
  4.  
  5. struct POINT3D {
  6.     float X, Y, Z;
  7.     float U, V;
  8. };
  9.  
  10. void TextureMapTriangle( BITMAPINFO const *pDestInfo,
  11.         BYTE *pDestBits, POINT3D const *pVertices,
  12.         BITMAPINFO const *pTextureInfo,
  13.         BYTE *pTextureBits );
  14.  
  15. /******** structures, inlines, and function declarations **********/
  16.  
  17. struct gradients {
  18.     gradients( POINT3D const *pVertices );
  19.     float aOneOverZ[3];                // 1/z for each vertex
  20.     float aUOverZ[3];                // u/z for each vertex
  21.     float aVOverZ[3];                // v/z for each vertex
  22.     float dOneOverZdX, dOneOverZdY;    // d(1/z)/dX, d(1/z)/dY
  23.     float dUOverZdX, dUOverZdY;        // d(u/z)/dX, d(u/z)/dY
  24.     float dVOverZdX, dVOverZdY;        // d(v/z)/dX, d(v/z)/dY
  25. };
  26.  
  27. struct edge {
  28.     edge(gradients const &Gradients,
  29.         POINT3D const *pVertices,
  30.         int Top, int Bottom );
  31.     inline int Step( void );
  32.  
  33.     float X, XStep;                    // fractional x and dX/dY
  34.     int Y, Height;                    // current y and vert count
  35.     float OneOverZ, OneOverZStep;        // 1/z and step
  36.     float UOverZ, UOverZStep;            // u/z and step
  37.     float VOverZ, VOverZStep;            // v/z and step
  38. };
  39.  
  40. inline int edge::Step( void ) {
  41.     X += XStep; Y++; HeightÑ;
  42.     UOverZ += UOverZStep; VOverZ += VOverZStep;
  43.     OneOverZ += OneOverZStep;
  44.     return Height;
  45. }
  46.  
  47. void DrawScanLine( BITMAPINFO const *pDestInfo,
  48.     BYTE *pDestBits, gradients const &Gradients,
  49.     edge *pLeft, edge *pRight,
  50.     BITMAPINFO const *pTextureInfo, BYTE *pTextureBits );
  51.  
  52. /******** TextureMapTriangle **********/
  53.  
  54. void TextureMapTriangle( BITMAPINFO const *pDestInfo,
  55.         BYTE *pDestBits, POINT3D const *pVertices,
  56.         BITMAPINFO const *pTextureInfo,
  57.         BYTE *pTextureBits )
  58. {
  59.     int Top, Middle, Bottom;
  60.     int MiddleCompare, BottomCompare;
  61.     float Y0 = pVertices[0].Y;
  62.     float Y1 = pVertices[1].Y;
  63.     float Y2 = pVertices[2].Y;
  64.  
  65.     // sort vertices in y
  66.     if(Y0 < Y1) {
  67.         if(Y2 < Y0) {
  68.             Top = 2; Middle = 0; Bottom = 1;
  69.             MiddleCompare = 0; BottomCompare = 1;
  70.         } else {
  71.             Top = 0;
  72.             if(Y1 < Y2) {
  73.                 Middle = 1; Bottom = 2;
  74.                 MiddleCompare = 1; BottomCompare = 2;
  75.             } else {
  76.                 Middle = 2; Bottom = 1;
  77.                 MiddleCompare = 2; BottomCompare = 1;
  78.             }
  79.         }
  80.     } else {
  81.         if(Y2 < Y1) {
  82.             Top = 2; Middle = 1; Bottom = 0;
  83.             MiddleCompare = 1; BottomCompare = 0;
  84.         } else {
  85.             Top = 1;
  86.             if(Y0 < Y2) {
  87.                 Middle = 0; Bottom = 2;
  88.                 MiddleCompare = 3; BottomCompare = 2;
  89.             } else {
  90.                 Middle = 2; Bottom = 0;
  91.                 MiddleCompare = 2; BottomCompare = 3;
  92.             }
  93.         }
  94.     }
  95.  
  96.     gradients Gradients(pVertices);
  97.     edge TopToBottom(Gradients,pVertices,Top,Bottom);
  98.     edge TopToMiddle(Gradients,pVertices,Top,Middle);
  99.     edge MiddleToBottom(Gradients,pVertices,Middle,Bottom);
  100.     edge *pLeft, *pRight;
  101.     int MiddleIsLeft;
  102.  
  103.     // the triangle is clockwise, so
  104.     // if bottom > middle then middle is right
  105.     if(BottomCompare > MiddleCompare) {
  106.         MiddleIsLeft = 0;
  107.         pLeft = &TopToBottom; pRight = &TopToMiddle;
  108.     } else {
  109.         MiddleIsLeft = 1;
  110.         pLeft = &TopToMiddle; pRight = &TopToBottom;
  111.     }
  112.  
  113.     int Height = TopToMiddle.Height;
  114.  
  115.     while(HeightÑ) {
  116.         DrawScanLine(pDestInfo,pDestBits,Gradients,
  117.             pLeft,pRight,pTextureInfo,pTextureBits);
  118.         TopToMiddle.Step(); TopToBottom.Step();
  119.     }
  120.  
  121.     Height = MiddleToBottom.Height;
  122.  
  123.     if(MiddleIsLeft) {
  124.         pLeft = &MiddleToBottom; pRight = &TopToBottom;
  125.     } else {
  126.         pLeft = &TopToBottom; pRight = &MiddleToBottom;
  127.     }
  128.     
  129.     while(HeightÑ) {
  130.         DrawScanLine(pDestInfo,pDestBits,Gradients,
  131.             pLeft,pRight,pTextureInfo,pTextureBits);
  132.         MiddleToBottom.Step(); TopToBottom.Step();
  133.     }
  134. }
  135.  
  136. /********** gradients constructor **********/
  137.  
  138. gradients::gradients( POINT3D const *pVertices )
  139. {
  140.     int Counter;
  141.     
  142.     float OneOverdX = 1 /(((pVertices[1].X - pVertices[2].X) *
  143.             (pVertices[0].Y - pVertices[2].Y)) -
  144.             ((pVertices[0].X - pVertices[2].X) *
  145.             (pVertices[1].Y - pVertices[2].Y)));
  146.  
  147.     float OneOverdY = -OneOverdX;
  148.  
  149.     for(Counter = 0;Counter < 3;Counter++) {
  150.         float const OneOverZ = 1/pVertices[Counter].Z;
  151.         aOneOverZ[Counter] = OneOverZ;
  152.         aUOverZ[Counter] = pVertices[Counter].U * OneOverZ;
  153.         aVOverZ[Counter] = pVertices[Counter].V * OneOverZ;
  154.     }
  155.  
  156.     dOneOverZdX = OneOverdX * (((aOneOverZ[1] - aOneOverZ[2]) *
  157.             (pVertices[0].Y - pVertices[2].Y)) -
  158.             ((aOneOverZ[0] - aOneOverZ[2]) *
  159.             (pVertices[1].Y - pVertices[2].Y)));
  160.     dOneOverZdY = OneOverdY * (((aOneOverZ[1] - aOneOverZ[2]) *
  161.             (pVertices[0].X - pVertices[2].X)) -
  162.             ((aOneOverZ[0] - aOneOverZ[2]) *
  163.             (pVertices[1].X - pVertices[2].X)));
  164.  
  165.     dUOverZdX = OneOverdX * (((aUOverZ[1] - aUOverZ[2]) *
  166.             (pVertices[0].Y - pVertices[2].Y)) -
  167.             ((aUOverZ[0] - aUOverZ[2]) *
  168.             (pVertices[1].Y - pVertices[2].Y)));
  169.     dUOverZdY = OneOverdY * (((aUOverZ[1] - aUOverZ[2]) *
  170.             (pVertices[0].X - pVertices[2].X)) -
  171.             ((aUOverZ[0] - aUOverZ[2]) *
  172.             (pVertices[1].X - pVertices[2].X)));
  173.  
  174.     dVOverZdX = OneOverdX * (((aVOverZ[1] - aVOverZ[2]) *
  175.             (pVertices[0].Y - pVertices[2].Y)) -
  176.             ((aVOverZ[0] - aVOverZ[2]) *
  177.             (pVertices[1].Y - pVertices[2].Y)));
  178.     dVOverZdY = OneOverdY * (((aVOverZ[1] - aVOverZ[2]) *
  179.             (pVertices[0].X - pVertices[2].X)) -
  180.             ((aVOverZ[0] - aVOverZ[2]) *
  181.             (pVertices[1].X - pVertices[2].X)));
  182. }
  183.  
  184. /********** edge constructor ***********/
  185.  
  186. edge::edge( gradients const &Gradients,
  187.         POINT3D const *pVertices, int Top, int Bottom )
  188. {
  189.     Y = ceil(pVertices[Top].Y);
  190.     int YEnd = ceil(pVertices[Bottom].Y);
  191.     Height = YEnd - Y;
  192.  
  193.     float YPrestep = Y - pVertices[Top].Y;
  194.     
  195.     float RealHeight = pVertices[Bottom].Y - pVertices[Top].Y;
  196.     float RealWidth = pVertices[Bottom].X - pVertices[Top].X;
  197.  
  198.     X = ((RealWidth * YPrestep)/RealHeight) + pVertices[Top].X;
  199.     XStep = RealWidth/RealHeight;
  200.     float XPrestep = X - pVertices[Top].X;
  201.  
  202.     OneOverZ = Gradients.aOneOverZ[Top] +
  203.         YPrestep * Gradients.dOneOverZdY +
  204.         XPrestep * Gradients.dOneOverZdX;
  205.     OneOverZStep = XStep *
  206.         Gradients.dOneOverZdX + Gradients.dOneOverZdY;
  207.  
  208.     UOverZ = Gradients.aUOverZ[Top] +
  209.         YPrestep * Gradients.dUOverZdY +
  210.         XPrestep * Gradients.dUOverZdX;
  211.     UOverZStep = XStep *
  212.         Gradients.dUOverZdX + Gradients.dUOverZdY;
  213.  
  214.     VOverZ = Gradients.aVOverZ[Top] +
  215.         YPrestep * Gradients.dVOverZdY +
  216.         XPrestep * Gradients.dVOverZdX;
  217.     VOverZStep = XStep *
  218.         Gradients.dVOverZdX + Gradients.dVOverZdY;
  219. }
  220.  
  221. /********** DrawScanLine ************/
  222.  
  223. void DrawScanLine( BITMAPINFO const *pDestInfo,
  224.         BYTE *pDestBits, gradients const &Gradients,
  225.         edge *pLeft, edge *pRight,
  226.         BITMAPINFO const *pTextureInfo,
  227.         BYTE *pTextureBits )
  228. {
  229.     // we assume dest and texture are top-down
  230.  
  231.     int DestWidthBytes =
  232.         (pDestInfo->bmiHeader.biWidth + 3) & ~3;
  233.     int TextureWidthBytes =
  234.         (pTextureInfo->bmiHeader.biWidth + 3) & ~3;
  235.  
  236.     int XStart = ceil(pLeft->X);
  237.     float XPrestep = XStart - pLeft->X;
  238.  
  239.     pDestBits += pLeft->Y * DestWidthBytes + XStart;
  240.  
  241.     int Width = ceil(pRight->X) - XStart;
  242.  
  243.     float OneOverZ = pLeft->OneOverZ +
  244.             XPrestep * Gradients.dOneOverZdX;
  245.     float UOverZ = pLeft->UOverZ +
  246.             XPrestep * Gradients.dUOverZdX;
  247.     float VOverZ = pLeft->VOverZ +
  248.             XPrestep * Gradients.dVOverZdX;
  249.  
  250.     if(Width > 0) {
  251.         while(WidthÑ) {
  252.             float Z = 1/OneOverZ;
  253.             int U = UOverZ * Z;
  254.             int V = VOverZ * Z;
  255.  
  256.             *(pDestBits++) = *(pTextureBits + U +
  257.                 (V * TextureWidthBytes));
  258.     
  259.             OneOverZ += Gradients.dOneOverZdX;
  260.             UOverZ += Gradients.dUOverZdX;
  261.             VOverZ += Gradients.dVOverZdX;
  262.         }
  263.     }
  264. }
  265.  
  266.