home *** CD-ROM | disk | FTP | other *** search
/ Cutting-Edge 3D Game Programming with C++ / CE3DC++.ISO / BOOK / CHAP12 / LINETYPE.HPP < prev    next >
C/C++ Source or Header  |  1996-01-24  |  5KB  |  165 lines

  1. //
  2. // File name: LineType.HPP
  3. //
  4. // Description: A fixed-point implementation of a polygon edge 
  5. //             algorithm
  6. //
  7. // Author: John De Goes
  8. //
  9. // Project: Cutting Edge 3D Game Programming
  10. //
  11.  
  12. #ifndef LINETYPEHPP
  13. #define LINETYPEHPP
  14.  
  15. const XSTEP_PREC = 10;
  16.  
  17. // TSTEP_PREC and ZSTEP_PREC must be equal:
  18. const ZSTEP_PREC = 26;
  19. const TSTEP_PREC = ZSTEP_PREC;
  20. const LSTEP_PREC = 16;
  21. const ISTEP_PREC = 8;
  22. const TMASK      = ( 0xFFFFFFFF << LSTEP_PREC );
  23. const IMASK      = ( 0xFFFFFFFF << ISTEP_PREC );
  24.  
  25. #include <Dos.H>
  26. #include <Math.H>
  27.  
  28. #include "Point2D.HPP"
  29. #include "3DClass.HPP"
  30.  
  31.  
  32. // Ceiling step constant:
  33. const long CEIL_FRACT = ( ( 1 << XSTEP_PREC ) - 1 );
  34.  
  35. // A class that steps on the ceiling of integers - always steps
  36. // on Y, rendering it useless for anything but polygon
  37. // rasterization:
  38. class CeilLine {
  39. protected:
  40.   long X1, X2, Y1, Y2;
  41.   long X, StepX, StepZ, Z, U, V, StepU, StepV, I, StepI;
  42.   long EdgeHeight, Y;
  43.   void inline Step ();
  44.   void inline Step ( long Amount );
  45. public:
  46.   CeilLine () { EdgeHeight = 0; }  // The constructor
  47.   void inline Init ( Point2D P1, Point2D P2 ); // The initialize function
  48.   void inline ClipTop ( const int Top );  // Object-precision clip 
  49.                                           // against top of viewport
  50.   void operator ++ () { Step (); }        // Steps polygon edge
  51.   void operator ++ ( int ) { Step (); }
  52.   void operator += ( long Amount ) { Step ( Amount ); } // Steps edge by "Amount"
  53.   Point2D inline operator + ( long Amount );   // Returns a point P + Amount
  54.   long GetX () { return ( X >> XSTEP_PREC ); } // Returns the current X coordinate
  55.   long GetY () { return Y; } // Returns the current Y coordinate
  56.   long GetZ () { return Z; } // Returns the current 1/Z coordinate
  57.   long GetU () { return U; } // Returns the current 1/U texture coordinate
  58.   long GetV () { return V; } // Returns the current 1/V texture coordinate
  59.   long GetI () { return I; } // Return the current intensity
  60.   long Height () { return EdgeHeight; } // Returns the current poly height
  61. };
  62.  
  63. void inline CeilLine::Init ( Point2D P1, Point2D P2 )
  64.    {
  65.    // Calculate initial values for polygon edge:
  66.    long FWidth, DeltaZ, DeltaU, DeltaV, Z1, Z2, DeltaI;
  67.    X1 = P1.X; X2 = P2.X;
  68.    Y1 = P1.Y; Y2 = P2.Y;
  69.    Z1 = P1.Z; Z2 = P2.Z;
  70.  
  71.    EdgeHeight = ( Y2 - Y1 );
  72.    FWidth = ( X2 - X1 ) << XSTEP_PREC;
  73.    DeltaZ = ( Z2 - Z1 );
  74.    // Calculate U/Z and V/Z deltas:
  75.    DeltaU = ( P2.U - P1.U );
  76.    DeltaV = ( P2.V - P1.V );
  77.  
  78.    // Calculate intensity delta:
  79.    DeltaI = ( P2.I - P1.I );
  80.  
  81.    X = ( X1 << XSTEP_PREC ) + CEIL_FRACT;
  82.    Y = Y1;
  83.    Z = Z1 + ZTrans;
  84.    // Store U/Z and V/Z values:
  85.    U = P1.U;
  86.    V = P1.V;
  87.    // Store intensity value:
  88.    I = P1.I;
  89.  
  90.    if ( EdgeHeight )
  91.       {
  92.       StepX = FWidth / EdgeHeight;
  93.       StepZ = DeltaZ / EdgeHeight;
  94.       StepU = DeltaU / EdgeHeight;
  95.       StepV = DeltaV / EdgeHeight;
  96.       StepI = DeltaI / EdgeHeight;
  97.       }
  98.    else {
  99.         StepX = 0;
  100.         StepZ = 0;
  101.         StepU = 0;
  102.         StepV = 0;
  103.         StepI = 0;
  104.         }
  105.    }
  106.  
  107. void inline CeilLine::Step ()
  108.    {
  109.    // Step the edge:
  110.    X += StepX;
  111.    ++Y; Z += StepZ;
  112.    U += StepU;
  113.    V += StepV;
  114.    I += StepI;
  115.    --EdgeHeight;
  116.    }
  117.  
  118. void inline CeilLine::Step ( long Amount )
  119.    {
  120.    // Step the edge by "Amount":
  121.    X += ( StepX * Amount );
  122.    Y += ( Amount );
  123.    Z += ( StepZ * Amount );
  124.    U += ( StepU * Amount );
  125.    V += ( StepV * Amount );
  126.    I += ( StepI * Amount );
  127.    EdgeHeight -= ( Amount );
  128.    }
  129.  
  130. Point2D inline CeilLine::operator + ( long Amount )
  131.    {
  132.    // Return a point P + Amount:
  133.    Point2D Temp;
  134.    Temp.X = X + ( StepX * Amount );
  135.    Temp.Y = Y + ( Amount );
  136.    Temp.Z = Z + ( StepZ * Amount );
  137.    Temp.U = U + ( StepU * Amount );
  138.    Temp.V = V + ( StepV * Amount );
  139.    Temp.I = I + ( StepI * Amount );
  140.    return Temp;
  141.    }
  142.  
  143. void CeilLine::ClipTop ( const int Top )
  144.    {
  145.    // Clip the polygon edge against the top of the viewport -
  146.    // Note: must be called directly after edge initialization:
  147.    double SlopeX;
  148.    long Step, Height = Y2 - Y1;
  149.    if ( ( Y < Top ) && ( Height ) )
  150.       {
  151.       Step = Top - Y;
  152.       SlopeX = ( double ) ( X2 - X1 ) / ( double ) Height;
  153.       X = ( X1 << XSTEP_PREC ) + 
  154.            ( ( long ) ( SlopeX * ( double ) Step ) << XSTEP_PREC ) + 
  155.           CEIL_FRACT;
  156.       Y = Top;
  157.       Z += StepZ * Step;
  158.       U += StepU * Step;
  159.       V += StepV * Step;
  160.       I += StepI * Step;
  161.       EdgeHeight -= Step;
  162.       }
  163.    }
  164.  
  165. #endif