home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C ++ / Applications / Venus 3.5 / FlightView.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-10  |  4.0 KB  |  112 lines  |  [TEXT/CWIE]

  1. /*
  2.  ***********************************************************************
  3.  *
  4.  *                                FlightView
  5.  * A particular version of a generic ThreeDView optimized to flight through
  6.  * "periodic" clouds 
  7.  *
  8.  * Drawing the sky
  9.  * For the sky, we use the same image (only viewed "upside down") and project
  10.  * it using the formulas in view_3d.cc. The only trick is that we assume that
  11.  * the sky is _very high above_, that is, the distance from the observer to
  12.  * the sky is much bigger compared to the relative size (elevation) of separate
  13.  * cloud "particles"
  14.  *
  15.  * We will start the derivation from the projection formulas of "view_3d.cc"
  16.  * that project a point (x,y,z) of an elevation map onto
  17.  *
  18.  *     u = beta/d(A) * (-gy*(x-xe) + gx*(y-ye))/|g| + Ou
  19.  *     v = beta/d(A) * (z-ze) + Ov
  20.  *     d(A) = (gx*(x-xe) + gy*(y-ye))/|g|
  21.  * point on the screen. Let's lose some of the generality and require that
  22.  * the gaze be strictly forward, that is, gx = 0 and gy = |g|. This simplifies
  23.  * the formulas to
  24.  *    u = Ou - beta/d * (x-xe)
  25.  *  v = Ov + beta/d * (z-ze)
  26.  *  d = y - ye
  27.  * Note that ze-z is the distance from a particular point on the elevation map
  28.  * to the observer. Since the observer is far below, the elevation z of a
  29.  * point on the map doesn't matter too much, so it can be assumed that
  30.  * ze-z = const (which we called Zc). That simplifies fromulas to
  31.  *    u = Ou - beta/d * (x-xe)
  32.  *  v = Ov - beta/d * Zc
  33.  *  d = y - ye
  34.  * To show that the sky is "above" us (as opposite to the elevation map which
  35.  * is "below") we flip the sign in the formula for v:
  36.  *  v = Ov + beta/d * Zc
  37.  * Thus v = Ov when d = infinity, and increases (towards the top edge of the
  38.  * screen port) when d, the depth, decreases. Ov is the really horizon then.
  39.  * The formulas above are easily invertible:
  40.  *  d = (Zc*beta)/(v-Ov)
  41.  *  y = d + ye
  42.  *  x = xe + (Ou-u)*d/beta
  43.  * Thus, given a scanline with v > Ov, we scan it from u=0 through u=umax and
  44.  * assign each pixel (u,v) the color off the elevation's map point
  45.  *    x = xe + Ou*Zc/(v-Ov) - u*Zc/(v-Ov)
  46.  *  y = ye + beta*Zc/(v-Ov)
  47.  * Note that y does not actually depend on u.
  48.  * We can choose parameter Zc so that the at the point right "above" us, that
  49.  * is, at the top edge of the screen v=vmax, the increment in x we move to the next
  50.  * scan point be exactly one. That means, Zc = vmax-Ov. Parameter beta above is
  51.  * arbitrary as well (it doesn't have to be the same as the one used in 3D projection).
  52.  * So, we'll choose it to be, say, 1/2.
  53.  * 
  54.  ***********************************************************************
  55.  */
  56.  
  57. #include "FlightWindow.h"
  58. #include "view_3d.cc"
  59.  
  60.                         // Quickly computes x % n, that is, adds or subtracts n until
  61.                         // the result (x) falls within [0,n-1]
  62.                         // We assume that x hasn't fall too far out of this interval to start
  63.                         // with
  64. static inline int fast_mod(int x, const int n)
  65. {
  66.   while( x < 0 )
  67.    x += n;
  68.   while( x >= n )
  69.    x -= n;
  70.   return x;
  71. }
  72.  
  73. class ThreeDProjector_PeriodicMap : public ThreeDProjectorCached
  74. {
  75. public:
  76.     ThreeDProjector_PeriodicMap(const ElevationMap& _map, const ViewerPosition& viewer_pos,
  77.                     const ProjectionParameters& projp)
  78.     : ThreeDProjectorCached(_map,viewer_pos,projp) {}
  79.  
  80.  inline void operator () (ThreeDViewBase::OneViewScanline::ScanPoint& point)
  81.  {
  82.    xu = fast_mod(xu,map_width_u);
  83.    yu = fast_mod(yu,map_height_u);
  84.    ThreeDProjectorCached::operator ()(point);
  85.  }
  86. };
  87.  
  88.  
  89.                                 // Draw the sky (as a background image)
  90. void FlightView::prepaint(void)
  91. {
  92. #if 1
  93.     PixMapHandle pixmap = get_pixmap();
  94.     const int bytes_per_row = OffScreenBuffer::bytes_per_row();
  95.     const int nrows = height();
  96.     assert( LockPixels(pixmap) );
  97.     unsigned char * pixels_ptr = (unsigned char *)GetPixBaseAddr(pixmap);
  98.     const int background_pixel = 0;            // Clear the canvas before we start drawing
  99.     const int scan_width = width();
  100.     register unsigned char * rp = pixels_ptr;
  101.     for(register int i=0; i < nrows; i++, rp += bytes_per_row)
  102.        memset(rp,background_pixel,scan_width);
  103.     UnlockPixels(pixmap);
  104. #else
  105.  clear();
  106. #endif
  107. }
  108.  
  109.  
  110.                             // Force compilation of the template
  111. template class ThreeDView<ThreeDProjector_PeriodicMap>;
  112.