TX Library Help – Version: 00173a, Revision: 174
 ALL  Windows graphics in a sandbox

PhongDemo.cpp

См. документацию.
00001 //{===========================================================================
00010 //          (C) Стас Артюхин, 9 класс, 2006
00011 //}===========================================================================
00012 
00013 #include "TXLib.h"
00014 
00015 #if !defined (_TX_VER) || (_TX_VER < 0x172a0000)
00016 #error Must use TXLib.h version >= 1.72 to compile this.
00017 #endif
00018 
00019 //============================================================================
00020 
00021 template <typename T = double>
00022 struct Vector
00023     {
00024     T x, y, z;
00025 
00026     Vector();
00027     explicit Vector (T xyz);
00028     Vector (T x0, T y0, T z0);
00029     };
00030 
00031 typedef Vector<> vec;
00032 
00033 //----------------------------------------------------------------------------
00034 
00035 template <typename T>
00036 inline Vector<T>::Vector() :
00037     x (0),
00038     y (0),
00039     z (0)
00040     {}
00041 
00042 //----------------------------------------------------------------------------
00043 
00044 template <typename T>
00045 inline Vector<T>::Vector (T x0, T y0, T z0) :
00046     x (x0),
00047     y (y0),
00048     z (z0)
00049     {}
00050 
00051 //----------------------------------------------------------------------------
00052 
00053 template <typename T>
00054 inline Vector<T>::Vector (T xyz) :
00055     x (xyz),
00056     y (xyz),
00057     z (xyz)
00058     {}
00059 
00060 //----------------------------------------------------------------------------
00061 // Normalization
00062 
00063 template <typename T>
00064 inline double len (const Vector<T>& v)
00065     {
00066     return sqrt (v.x*v.x + v.y*v.y + v.z*v.z);
00067     }
00068 
00069 template <typename T>
00070 inline Vector<T> operator ! (const Vector<T>& v)
00071     {
00072     return v / len (v);
00073     }
00074 
00075 //----------------------------------------------------------------------------
00076 
00077 template <typename T>
00078 inline Vector<T>& operator += (Vector<T>& a, const Vector<T>& b)
00079     {
00080     a.x += b.x; a.y += b.y; a.z += b.z;
00081     return a;
00082     }
00083 
00084 //----------------------------------------------------------------------------
00085 
00086 template <typename T>
00087 inline Vector<T> operator + (const Vector<T>& a, const Vector<T>& b)
00088     {
00089     return Vector<T> (a.x+b.x, a.y+b.y, a.z+b.z);
00090     }
00091 
00092 //----------------------------------------------------------------------------
00093 
00094 template <typename T>
00095 inline Vector<T> operator - (const Vector<T>& a, const Vector<T>& b)
00096     {
00097     return Vector<T> (a.x-b.x, a.y-b.y, a.z-b.z);
00098     }
00099 
00100 //----------------------------------------------------------------------------
00101 // Non-vector product
00102 
00103 template <typename T>
00104 inline Vector<T> operator * (const Vector<T>& a, const Vector<T>& b)
00105     {
00106     return Vector<T> (a.x*b.x, a.y*b.y, a.z*b.z);
00107     }
00108 
00109 //----------------------------------------------------------------------------
00110 // Scalar (dot) product
00111 
00112 template <typename T>
00113 inline T operator ^ (const Vector<T>& a, const Vector<T>& b)
00114     {
00115     return a.x*b.x + a.y*b.y + a.z*b.z;
00116     }
00117 
00118 //----------------------------------------------------------------------------
00119 
00120 template <typename T, typename T2>
00121 inline Vector<T> operator * (const Vector<T>& v, T2 val)
00122     {
00123     return Vector<T> (v.x*val, v.y*val, v.z*val);
00124     }
00125 
00126 template <typename T, typename T2>
00127 inline Vector<T> operator * (T2 val, const Vector<T>& v)
00128     {
00129     return v * val;
00130     }
00131 
00132 //----------------------------------------------------------------------------
00133 
00134 template <typename T>
00135 inline Vector<T> operator / (const Vector<T>& v, T val)
00136     {
00137     return Vector<T> (v.x/val, v.y/val, v.z/val);
00138     }
00139 
00140 //----------------------------------------------------------------------------
00141 
00142 template <typename T>
00143 inline std::ostream& operator << (std::ostream& o, const Vector<T>& v)
00144     {
00145     o << "Vector (" << v.x << ", " << v.y << ", " << v.z << ")";
00146     return o;
00147     }
00148 
00149 //----------------------------------------------------------------------------
00150 
00151 inline double Clamp (double value, double min, double max)
00152     {
00153     return (value < min)? min : (value > max)? max : value;
00154     }
00155 
00156 //----------------------------------------------------------------------------
00157 
00158 inline double Random (double min, double max)
00159     {
00160     return min + (max - min) * rand() / RAND_MAX;
00161     }
00162 
00163 //============================================================================
00164 
00165 void DrawScene (const vec& lightPos, double r);
00166 
00167 vec PhongLightning (const vec& p, const vec& N, const vec& V,
00168                     const vec& lightPos, const vec& lightColor,
00169                     const vec& materialColor,
00170                     const vec& ambientColor = vec (0, 0, 0));
00171 
00172 const vec Bump (const vec& p = vec(), double r = 0);
00173 
00174 void DrawPixel (double x, double y, Vector<double> color);
00175 
00176 //----------------------------------------------------------------------------
00177 
00178 bool UseTxPixel = false;
00179 
00180 //----------------------------------------------------------------------------
00181 
00182 int main()
00183     {
00184     double r = 200;
00185 
00186     txCreateWindow (800, 600);
00187     txTextCursor (false);
00188     txBegin();
00189 
00190     static double perf = txQueryPerformance();
00191     
00192     txSetTextAlign (TA_CENTER);
00193     txSetColor (TX_DARKGRAY);
00194     txSelectFont ("Lucida Console", 15, 0);
00195     txTextOut (txGetExtentX()/2, txGetExtentY()*19/20, "Press Z, R, X, H to bump, T to use txSetPixel(), "
00196                                                        "ESC to exit");
00197     for (double t = txPI/2; ; t += 0.1)
00198         {
00199         DrawScene (vec (-2*r * (1 + cos (t)),
00200                         -2*r *      cos (t),
00201                         +2*r *      sin (t)), r);
00202         txSleep ();
00203 
00204         if (GetAsyncKeyState (VK_ESCAPE) && GetForegroundWindow() == txWindow()) break;
00205 
00206         /* For FPS testing only: */
00207         
00208         if (GetAsyncKeyState (VK_SPACE)) continue;
00209         UseTxPixel = GetAsyncKeyState ('T');
00210 
00211         static char s [128] = "";
00212         sprintf (s, "tx[Q]ueryPerformance(): %.2f. FPS %.2f. Using %s",
00213                     perf, txGetFPS(), (UseTxPixel? "txSetPixel" : "direct memory access"));
00214         SetWindowText (txWindow(), s);
00215         }
00216 
00217     txEnd();
00218     return 0;
00219     }
00220 
00221 //----------------------------------------------------------------------------
00222 
00223 void DrawScene (const vec& lightPos, double r)
00224     {
00225     const vec viewPos       (   0,    0, +5*r);
00226 //  const vec lightPos      (-2*r, +2*r, +2*r);
00227 
00228     const vec materialColor (0.0, 1.0, 0.0);
00229     const vec lightColor    (1.0, 0.7, 0.0);
00230     const vec ambientColor  (0.2, 0.2, 0.2);
00231 
00232     for (double y = +r; y >= -r; y--)
00233     for (double x = -r; x <= +r; x++)
00234         {
00235         if (x*x + y*y > r*r) continue;
00236 
00237         vec p = vec (x, y, 0);
00238         p = p + Bump (p, r) * 100;
00239         if (p.x*p.x + p.y*p.y > r*r) { DrawPixel (x, y, vec (0)); continue; }
00240 
00241         p.z = sqrt (r*r - p.x*p.x - p.y*p.y);
00242         vec N = !p + Bump (p, r);
00243 
00244         vec V = !(viewPos  - p);
00245         vec L = !(lightPos - p);
00246 
00247         double diffuse = N ^ L;
00248         if (diffuse < 0) diffuse = 0;
00249 
00250         vec Lr = 2*(N^L)*N - L;
00251         double spec = Lr ^ V;
00252         if (spec < 0) spec = 0;
00253         double specular = pow (spec, 25);
00254 
00255         vec color = ambientColor * materialColor              +
00256 
00257                     diffuse      * materialColor * lightColor +
00258                     specular     *                 lightColor +
00259 
00260                     PhongLightning (p, N, V,
00261                                     vec (+2*r, -1*r,   0),
00262                                     vec ( 0.5,  0.5, 0.5),
00263                                     materialColor);
00264                                     
00265         DrawPixel (x, y, color);
00266         }
00267     }
00268 
00269 //----------------------------------------------------------------------------
00270 
00271 inline void DrawPixel (double x, double y, Vector<double> color)
00272     {
00273     static POINT scr = txGetExtent();
00274 
00275     POINT   p   = { (int) (x + scr.x/2 + 0.5),
00276                     (int) (y + scr.y/2 + 0.5) };
00277 
00278     RGBQUAD rgb = { (BYTE) (Clamp (color.x, 0, 1) * 255 + 0.5),
00279                     (BYTE) (Clamp (color.y, 0, 1) * 255 + 0.5),
00280                     (BYTE) (Clamp (color.z, 0, 1) * 255 + 0.5) };
00281 
00282     if (UseTxPixel)
00283          txSetPixel (p.x, p.y, RGB (rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue));
00284     else
00285          *(txVideoMemory() + p.x + (-p.y + scr.y) * scr.x) = rgb;
00286     }
00287 
00288 //----------------------------------------------------------------------------
00289 
00290 vec PhongLightning (const vec& p, const vec& N, const vec& V,
00291                     const vec& lightPos, const vec& lightColor,
00292                     const vec& materialColor,
00293                     const vec& ambientColor)
00294     {
00295     vec L = !(lightPos - p);
00296 
00297     double diffuse = N ^ L;
00298     if (diffuse < 0) return ambientColor;
00299 
00300     vec Lr = 2*diffuse*N - L;
00301     double specular = pow (Lr ^ V, 25);
00302 
00303     return diffuse  * lightColor * materialColor +
00304            specular * lightColor +
00305            ambientColor;
00306     }
00307 
00308 //----------------------------------------------------------------------------
00309 
00310 const vec Bump (const vec& p, double r)
00311     {
00312     bool bXY  = (GetAsyncKeyState ('X') != 0),
00313          bXY2 = (GetAsyncKeyState ('H') != 0),
00314          bZ   = (GetAsyncKeyState ('Z') != 0),
00315          bRnd = (GetAsyncKeyState ('R') != 0);
00316 
00317     if (!bXY && !bXY2 && !bZ && !bRnd) return vec (0);
00318 
00319     const int sz = 100;
00320     static vec env[sz][sz] = {};
00321 
00322     static bool init = false;
00323     if (!init)
00324         {
00325         for (int y = 0; y < sz; y++) for (int x = 0; x < sz; x++)
00326             env[y][x] = vec (Random (-1, +1), Random (-1, +1), Random (-1, +1));
00327             
00328         init = true;
00329         }
00330 
00331     vec bump (0);
00332 
00333     if (bXY)  bump += p * ((sin (p.x/4) + cos (p.y/4)) / 4 + 1.5) / 5000.0;
00334     if (bXY2) bump += p * ((cos (p.x/4) + sin (p.y/4)) / 2 + 1.0) / 3000.0;
00335     if (bZ)   bump += p * ( sin (p.z*p.z / 500)        / 2 + 1.5) / 5000.0;
00336     if (bRnd) bump += env [(unsigned) ROUND (p.y + r) % sz] [(unsigned) ROUND (p.x + r) % sz] / 100.0;
00337 
00338     return bump;
00339     }