Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

578 lines
12 KiB

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <math.h>
  4. #include <string.h>
  5. #include <time.h>
  6. #include <assert.h>
  7. #include <windows.h>
  8. #include <gl\gl.h>
  9. #include <gl\glu.h>
  10. #include <gl\glaux.h>
  11. #include "mtk.hxx"
  12. #include "objects.hxx"
  13. #include "wave.hxx"
  14. #define WIDTH 256
  15. #define HEIGHT 256
  16. float fViewDist = 10.0f;
  17. float fTrans = 0.0f;
  18. //#define FTRANSINC 0.05f
  19. #define FTRANSINC 0.02f
  20. float fTransInc = -FTRANSINC;
  21. BOOL bDestAlpha;
  22. #define TESS_MIN 5
  23. #define TESS_MAX 100
  24. //int tessLevel = TESS_MAX / 2; // corresponds to # of rings/sections in object
  25. int tessLevel = 30; // corresponds to # of rings/sections in object
  26. int tessInc = 5;
  27. class DRAW_CONTROLLER {
  28. public:
  29. DRAW_CONTROLLER::DRAW_CONTROLLER();
  30. DRAW_CONTROLLER::~DRAW_CONTROLLER() {};
  31. void InitGL();
  32. void ToggleLighting() {bLighting = !bLighting; SetLighting(); }
  33. void SetLighting();
  34. void SetDrawObject( OBJECT *pObj, int objectType );
  35. void DrawObject();
  36. void NextRotation();
  37. //mf : this may move
  38. // Object rotation
  39. GLfloat fXr, fYr, fZr;
  40. GLfloat fDXr, fDYr, fDZr;
  41. private:
  42. void DrawVertexArray();
  43. BOOL bLighting;
  44. OBJECT *pObject; // Draw object
  45. int iObjectType;
  46. };
  47. class SCENE {
  48. public:
  49. SCENE();
  50. ~SCENE();
  51. void Draw();
  52. void DrawMembrane();
  53. void NewObject( int tessLevel );
  54. DRAW_CONTROLLER drawController;
  55. private:
  56. void DrawUsingAlphaBuffer();
  57. void DrawNormally();
  58. // Scene rotation
  59. GLfloat fXr, fYr, fZr;
  60. GLfloat fDXr, fDYr, fDZr;
  61. };
  62. // Global objects
  63. SCENE *scene;
  64. SPHERE *sphere;
  65. AVG_UPDATE_TIMER timer( 2.0f, 4 );
  66. #define RGB_COLOR(red, green, blue) \
  67. (((DWORD)(BYTE)(red) << 0) | \
  68. ((DWORD)(BYTE)(green) << 8) | \
  69. ((DWORD)(BYTE)(blue) << 16))
  70. #define RGBA_COLOR(red, green, blue, alpha) \
  71. (((DWORD)(BYTE)(red) << 0) | \
  72. ((DWORD)(BYTE)(green) << 8) | \
  73. ((DWORD)(BYTE)(blue) << 16) | \
  74. ((DWORD)(BYTE)(alpha) << 24))
  75. #define FRANDOM(x) (((float)rand() / RAND_MAX) * (x))
  76. #define DROT 10.0f
  77. BOOL fSingleBuf = FALSE;
  78. // forwards
  79. static void SetGLState(); // volatile state
  80. /****** DRAW_CONTROLLER *********************************************/
  81. DRAW_CONTROLLER::DRAW_CONTROLLER( )
  82. {
  83. bLighting = TRUE;
  84. // Init GL state
  85. InitGL();
  86. // Init object rotation and motion
  87. fXr = 0.0f;
  88. fYr = 0.0f;
  89. fZr = 0.0f;
  90. fDXr = DROT - FRANDOM(2 * DROT);
  91. fDYr = DROT - FRANDOM(2 * DROT);
  92. fDZr = DROT - FRANDOM(2 * DROT);
  93. }
  94. void
  95. DRAW_CONTROLLER::SetDrawObject( OBJECT *pObj, int objectType )
  96. {
  97. iObjectType = objectType;
  98. pObject = pObj;
  99. }
  100. void
  101. DRAW_CONTROLLER::DrawObject()
  102. {
  103. // Set object position, rotation, and draw it
  104. glPushMatrix();
  105. #if 0
  106. glTranslatef( 0.0f, 0.0f, -0.8f );
  107. #else
  108. glTranslatef( 0.0f, 0.0f, fTrans );
  109. #endif
  110. glRotatef(fXr, 1.0f, 0.0f, 0.0f);
  111. glRotatef(fYr, 0.0f, 1.0f, 0.0f);
  112. glRotatef(fZr, 0.0f, 0.0f, 1.0f);
  113. DrawVertexArray();
  114. glPopMatrix();
  115. }
  116. void
  117. DRAW_CONTROLLER::DrawVertexArray()
  118. {
  119. glDrawElements(GL_TRIANGLES,
  120. pObject->TriangleCount()*3,
  121. GL_UNSIGNED_INT,
  122. pObject->TriangleData() );
  123. }
  124. void
  125. DRAW_CONTROLLER::NextRotation()
  126. {
  127. // increment object rotation
  128. fXr += fDXr;
  129. fYr += fDYr;
  130. fZr += fDZr;
  131. }
  132. void
  133. DRAW_CONTROLLER::InitGL(void)
  134. {
  135. float fv4[4];
  136. int iv1[1];
  137. int i;
  138. fv4[0] = 0.05f;
  139. fv4[1] = 0.05f;
  140. fv4[2] = 0.05f;
  141. fv4[3] = 1.0f;
  142. glLightModelfv(GL_LIGHT_MODEL_AMBIENT, fv4);
  143. fv4[0] = 0.0f;
  144. fv4[1] = 1.0f;
  145. fv4[2] = 1.0f;
  146. fv4[3] = 0.0f;
  147. glLightfv(GL_LIGHT0, GL_POSITION, fv4);
  148. fv4[0] = 0.9f;
  149. fv4[1] = 0.9f;
  150. fv4[2] = 0.9f;
  151. fv4[3] = 1.0f;
  152. glLightfv(GL_LIGHT0, GL_DIFFUSE, fv4);
  153. glEnable(GL_LIGHT0);
  154. glEnable(GL_LIGHTING);
  155. fv4[0] = 0.6f;
  156. fv4[1] = 0.6f;
  157. fv4[2] = 0.6f;
  158. fv4[3] = 1.0f;
  159. glMaterialfv(GL_FRONT, GL_SPECULAR, fv4);
  160. iv1[0] = 40;
  161. glMaterialiv(GL_FRONT, GL_SHININESS, iv1);
  162. glEnable(GL_CULL_FACE);
  163. glEnableClientState(GL_VERTEX_ARRAY);
  164. glEnableClientState(GL_NORMAL_ARRAY);
  165. glEnableClientState(GL_COLOR_ARRAY);
  166. glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
  167. glEnable(GL_COLOR_MATERIAL);
  168. glMatrixMode(GL_PROJECTION);
  169. glLoadIdentity();
  170. gluPerspective(45, 1, .01, 15);
  171. gluLookAt(0, 0, fViewDist, 0, 0, 0, 0, 1, 0);
  172. glMatrixMode(GL_MODELVIEW);
  173. glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
  174. SetLighting();
  175. }
  176. void
  177. DRAW_CONTROLLER::SetLighting(void)
  178. {
  179. if( bLighting ) {
  180. glEnable( GL_LIGHTING );
  181. } else {
  182. glDisable( GL_LIGHTING );
  183. }
  184. }
  185. /****** SCENE *******************************************************/
  186. SCENE::SCENE()
  187. {
  188. srand(time(NULL));
  189. // Create sphere draw object for the scene
  190. NewObject( tessLevel );
  191. }
  192. void
  193. SCENE::NewObject( int tessLevel )
  194. {
  195. // Only one object allowed for now - delete any previous object
  196. if( sphere )
  197. delete sphere;
  198. // Create new sphere for the scene
  199. float fAlpha = 0.5f;
  200. sphere = new SPHERE( tessLevel, tessLevel, fAlpha );
  201. assert( sphere != NULL );
  202. // Inform DRAW_CONTROLLER about new object
  203. drawController.SetDrawObject( sphere, OBJECT_TYPE_SPHERE );
  204. // Initialize array pointer data
  205. SetGLState();
  206. VERTEX *pVertData = sphere->VertexData();
  207. glVertexPointer(3, GL_FLOAT, sizeof(VERTEX), &pVertData->fX);
  208. glNormalPointer(GL_FLOAT, sizeof(VERTEX), &pVertData->fNx);
  209. // Color pointer data is dependent on state...
  210. SetGLState();
  211. // Init scene rotation and motion
  212. fXr = 0.0f;
  213. fYr = 0.0f;
  214. fZr = 0.0f;
  215. fDXr = DROT - FRANDOM(2 * DROT);
  216. fDYr = DROT - FRANDOM(2 * DROT);
  217. fDZr = DROT - FRANDOM(2 * DROT);
  218. }
  219. SCENE::~SCENE()
  220. {
  221. // Delete any scene objects
  222. if( sphere )
  223. delete sphere;
  224. }
  225. /******************************Public*Routine******************************\
  226. * Draw
  227. *
  228. * Draw the scene using src or dst alpha blending.
  229. *
  230. \**************************************************************************/
  231. void
  232. SCENE::Draw()
  233. {
  234. if( bDestAlpha )
  235. DrawUsingAlphaBuffer();
  236. else
  237. DrawNormally();
  238. // Inrement object rotation
  239. drawController.NextRotation();
  240. if( fTrans < -1.2f ) {
  241. fTransInc = FTRANSINC;
  242. } else if( fTrans > 0.5f ) {
  243. fTransInc = -FTRANSINC;
  244. }
  245. fTrans += fTransInc;
  246. }
  247. /**************************************************************************\
  248. * DrawUsingAlphaBuffer
  249. *
  250. * The destination alpha buffer is used to optimize drawing. The optimization
  251. * is based on the fact that the objects cover a small area compared to the
  252. * entire window. Blending, which is slow, only occurs over the area occupied
  253. * by the object. Without the alpha buffer, blending must occur over the entire
  254. * window.
  255. \**************************************************************************/
  256. void
  257. SCENE::DrawUsingAlphaBuffer()
  258. {
  259. glClear( GL_DEPTH_BUFFER_BIT );
  260. glLoadIdentity();
  261. glEnable( GL_DEPTH_TEST );
  262. glDepthFunc( GL_ALWAYS );
  263. DrawMembrane();
  264. // Draw object's alpha values only on first pass
  265. glDepthFunc( GL_LEQUAL );
  266. //#define TURN_OFF_LIGHTING 1
  267. #if TURN_OFF_LIGHTING
  268. //mf: this makes it slower.. not sure why
  269. glDisable( GL_LIGHTING );
  270. #endif
  271. glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE );
  272. drawController.DrawObject();
  273. glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
  274. #if TURN_OFF_LIGHTING
  275. glEnable( GL_LIGHTING );
  276. #endif
  277. // set up dst alpha blending for next pass
  278. glBlendFunc( GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA );
  279. glEnable( GL_BLEND );
  280. glDisable( GL_DEPTH_TEST );
  281. // Draw object normally on second pass
  282. drawController.DrawObject();
  283. glDisable( GL_BLEND );
  284. }
  285. /**************************************************************************\
  286. * DrawNormally
  287. *
  288. * The scene is drawn without using destination alpha buffer. The objects are
  289. * drawn first, then the membrane is blended in afterwards.
  290. \**************************************************************************/
  291. void
  292. SCENE::DrawNormally()
  293. {
  294. glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
  295. glLoadIdentity();
  296. drawController.DrawObject();
  297. // Blend the membrane with the objects already drawn
  298. glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
  299. glEnable( GL_BLEND );
  300. DrawMembrane();
  301. glDisable( GL_BLEND );
  302. }
  303. void
  304. SCENE::DrawMembrane()
  305. {
  306. float fSize = fViewDist;
  307. glDisable( GL_LIGHTING );
  308. glColor4f( 0.0f, 0.5f, 0.9f, 0.5f );
  309. glBegin( GL_QUADS );
  310. glVertex3f( fSize, fSize, 0.0f );
  311. glVertex3f( -fSize, fSize, 0.0f );
  312. glVertex3f( -fSize, -fSize, 0.0f );
  313. glVertex3f( fSize, -fSize, 0.0f );
  314. glEnd();
  315. // Reinstate the current lighting model
  316. drawController.SetLighting();
  317. }
  318. /********************************************************************/
  319. void Reset()
  320. {
  321. // Called when display changes
  322. // Remove any timing info from title bar, and reset the timer
  323. SetWindowText(auxGetHWND(), "" );
  324. timer.Reset();
  325. timer.Start();
  326. }
  327. void NewTessLevel( int tessLevel )
  328. {
  329. static int oldTessLevel = 0; // to avoid unnecessary work
  330. // retesselate scene's object
  331. if( tessLevel == oldTessLevel )
  332. return;
  333. scene->NewObject( tessLevel );
  334. Reset();
  335. oldTessLevel = tessLevel;
  336. }
  337. void Draw(void)
  338. {
  339. DRAW_CONTROLLER *pDrawControl = &scene->drawController;
  340. float updatesPerSecond;
  341. // Draw the scene
  342. scene->Draw();
  343. if (fSingleBuf)
  344. glFlush();
  345. else
  346. auxSwapBuffers();
  347. // Print timing information if Stop returns TRUE
  348. if( timer.Update( 1, &updatesPerSecond ) ) {
  349. char szMsg[80];
  350. sprintf(szMsg, "%s: %.2lf frames/sec",
  351. "",
  352. updatesPerSecond );
  353. // Print timing info in title bar
  354. SetWindowText(auxGetHWND(), szMsg);
  355. }
  356. }
  357. static void
  358. SetGLState()
  359. {
  360. VERTEX *pVertData = sphere->VertexData();
  361. // Set vertex array pointers
  362. glVertexPointer(3, GL_FLOAT, sizeof(VERTEX), &pVertData->fX);
  363. glNormalPointer(GL_FLOAT, sizeof(VERTEX), &pVertData->fNx);
  364. // If using destination alpha blending, the object is drawn with alpha=1.0,
  365. // so specify 3-valued rgb colors (a defaults to 1.0). Otherwise,
  366. // the object is drawn using 4-valued rgba colors
  367. int colorDataSize = bDestAlpha ? 3 : 4;
  368. glColorPointer( colorDataSize, GL_UNSIGNED_BYTE, sizeof(VERTEX),
  369. &pVertData->dwColor);
  370. // Set other GL state
  371. if( bDestAlpha ) {
  372. glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
  373. } else {
  374. glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE );
  375. glClearColor( 0.0f, 0.5f, 0.9f, 0.0f );
  376. glEnable( GL_DEPTH_TEST );
  377. glDepthFunc( GL_LEQUAL );
  378. }
  379. }
  380. void Reshape(GLsizei w, GLsizei h)
  381. {
  382. glViewport(0, 0, w, h);
  383. Reset();
  384. }
  385. void Keya(void)
  386. {
  387. bDestAlpha = !bDestAlpha;
  388. SetGLState();
  389. Reset();
  390. }
  391. void Keyd(void)
  392. {
  393. }
  394. void Keyl(void)
  395. {
  396. scene->drawController.ToggleLighting();
  397. Reset();
  398. }
  399. void KeySPACE(void)
  400. {
  401. }
  402. void KeyUp(void)
  403. {
  404. // increase tesselation
  405. tessLevel += tessInc;
  406. if( tessLevel > TESS_MAX )
  407. tessLevel = TESS_MAX;
  408. NewTessLevel( tessLevel );
  409. }
  410. void KeyDown(void)
  411. {
  412. // decrease tesselation
  413. tessLevel -= tessInc;
  414. if( tessLevel < TESS_MIN )
  415. tessLevel = TESS_MIN;
  416. NewTessLevel( tessLevel );
  417. }
  418. void __cdecl main(int argc, char **argv)
  419. {
  420. GLenum eMode;
  421. while (--argc > 0)
  422. {
  423. argv++;
  424. if (!strcmp(*argv, "-sb"))
  425. fSingleBuf = TRUE;
  426. }
  427. auxInitPosition(10, 10, WIDTH, HEIGHT);
  428. // eMode = AUX_RGB | AUX_DEPTH16 | AUX_ALPHA;
  429. //mf: ??!! had to choose 32-bitz - don't know why, z-planes seem tight enough
  430. eMode = AUX_RGB | AUX_DEPTH24 | AUX_ALPHA;
  431. if (!fSingleBuf)
  432. {
  433. eMode |= AUX_DOUBLE;
  434. }
  435. auxInitDisplayMode(eMode);
  436. auxInitWindow("Insane in the Membrane");
  437. auxReshapeFunc(Reshape);
  438. auxIdleFunc(Draw);
  439. auxKeyFunc(AUX_a, Keya);
  440. auxKeyFunc(AUX_l, Keyl);
  441. auxKeyFunc(AUX_d, Keyd);
  442. auxKeyFunc(AUX_SPACE, KeySPACE);
  443. auxKeyFunc(AUX_UP, KeyUp);
  444. auxKeyFunc(AUX_DOWN, KeyDown);
  445. bDestAlpha = TRUE;
  446. // Create scene, with object(s)
  447. scene = new SCENE;
  448. // Start drawing
  449. timer.Start();
  450. auxMainLoop(Draw);
  451. // Party's over
  452. delete scene;
  453. }