![]() |
TX Library Help – Version: 00173a, Revision: 174
|
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 }