boing.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. /*****************************************************************************
  2. * Title: GLBoing
  3. * Desc: Tribute to Amiga Boing.
  4. * Author: Jim Brooks <[email protected]>
  5. * Original Amiga authors were R.J. Mical and Dale Luck.
  6. * GLFW conversion by Marcus Geelnard
  7. * Notes: - 360' = 2*PI [radian]
  8. *
  9. * - Distances between objects are created by doing a relative
  10. * Z translations.
  11. *
  12. * - Although OpenGL enticingly supports alpha-blending,
  13. * the shadow of the original Boing didn't affect the color
  14. * of the grid.
  15. *
  16. * - [Marcus] Changed timing scheme from interval driven to frame-
  17. * time based animation steps (which results in much smoother
  18. * movement)
  19. *
  20. * History of Amiga Boing:
  21. *
  22. * Boing was demonstrated on the prototype Amiga (codenamed "Lorraine") in
  23. * 1985. According to legend, it was written ad-hoc in one night by
  24. * R. J. Mical and Dale Luck. Because the bouncing ball animation was so fast
  25. * and smooth, attendees did not believe the Amiga prototype was really doing
  26. * the rendering. Suspecting a trick, they began looking around the booth for
  27. * a hidden computer or VCR.
  28. *****************************************************************************/
  29. #if defined(_MSC_VER)
  30. // Make MS math.h define M_PI
  31. #define _USE_MATH_DEFINES
  32. #endif
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <math.h>
  36. #define GLAD_GL_IMPLEMENTATION
  37. #include <glad/gl.h>
  38. #define GLFW_INCLUDE_NONE
  39. #include <GLFW/glfw3.h>
  40. #include <linmath.h>
  41. /*****************************************************************************
  42. * Various declarations and macros
  43. *****************************************************************************/
  44. /* Prototypes */
  45. void init( void );
  46. void display( void );
  47. void reshape( GLFWwindow* window, int w, int h );
  48. void key_callback( GLFWwindow* window, int key, int scancode, int action, int mods );
  49. void mouse_button_callback( GLFWwindow* window, int button, int action, int mods );
  50. void cursor_position_callback( GLFWwindow* window, double x, double y );
  51. void DrawBoingBall( void );
  52. void BounceBall( double dt );
  53. void DrawBoingBallBand( GLfloat long_lo, GLfloat long_hi );
  54. void DrawGrid( void );
  55. #define RADIUS 70.f
  56. #define STEP_LONGITUDE 22.5f /* 22.5 makes 8 bands like original Boing */
  57. #define STEP_LATITUDE 22.5f
  58. #define DIST_BALL (RADIUS * 2.f + RADIUS * 0.1f)
  59. #define VIEW_SCENE_DIST (DIST_BALL * 3.f + 200.f)/* distance from viewer to middle of boing area */
  60. #define GRID_SIZE (RADIUS * 4.5f) /* length (width) of grid */
  61. #define BOUNCE_HEIGHT (RADIUS * 2.1f)
  62. #define BOUNCE_WIDTH (RADIUS * 2.1f)
  63. #define SHADOW_OFFSET_X -20.f
  64. #define SHADOW_OFFSET_Y 10.f
  65. #define SHADOW_OFFSET_Z 0.f
  66. #define WALL_L_OFFSET 0.f
  67. #define WALL_R_OFFSET 5.f
  68. /* Animation speed (50.0 mimics the original GLUT demo speed) */
  69. #define ANIMATION_SPEED 50.f
  70. /* Maximum allowed delta time per physics iteration */
  71. #define MAX_DELTA_T 0.02f
  72. /* Draw ball, or its shadow */
  73. typedef enum { DRAW_BALL, DRAW_BALL_SHADOW } DRAW_BALL_ENUM;
  74. /* Vertex type */
  75. typedef struct {float x; float y; float z;} vertex_t;
  76. /* Global vars */
  77. int windowed_xpos, windowed_ypos, windowed_width, windowed_height;
  78. int width, height;
  79. GLfloat deg_rot_y = 0.f;
  80. GLfloat deg_rot_y_inc = 2.f;
  81. int override_pos = GLFW_FALSE;
  82. GLfloat cursor_x = 0.f;
  83. GLfloat cursor_y = 0.f;
  84. GLfloat ball_x = -RADIUS;
  85. GLfloat ball_y = -RADIUS;
  86. GLfloat ball_x_inc = 1.f;
  87. GLfloat ball_y_inc = 2.f;
  88. DRAW_BALL_ENUM drawBallHow;
  89. double t;
  90. double t_old = 0.f;
  91. double dt;
  92. /* Random number generator */
  93. #ifndef RAND_MAX
  94. #define RAND_MAX 4095
  95. #endif
  96. /*****************************************************************************
  97. * Truncate a degree.
  98. *****************************************************************************/
  99. GLfloat TruncateDeg( GLfloat deg )
  100. {
  101. if ( deg >= 360.f )
  102. return (deg - 360.f);
  103. else
  104. return deg;
  105. }
  106. /*****************************************************************************
  107. * Convert a degree (360-based) into a radian.
  108. * 360' = 2 * PI
  109. *****************************************************************************/
  110. double deg2rad( double deg )
  111. {
  112. return deg / 360 * (2 * M_PI);
  113. }
  114. /*****************************************************************************
  115. * 360' sin().
  116. *****************************************************************************/
  117. double sin_deg( double deg )
  118. {
  119. return sin( deg2rad( deg ) );
  120. }
  121. /*****************************************************************************
  122. * 360' cos().
  123. *****************************************************************************/
  124. double cos_deg( double deg )
  125. {
  126. return cos( deg2rad( deg ) );
  127. }
  128. /*****************************************************************************
  129. * Compute a cross product (for a normal vector).
  130. *
  131. * c = a x b
  132. *****************************************************************************/
  133. void CrossProduct( vertex_t a, vertex_t b, vertex_t c, vertex_t *n )
  134. {
  135. GLfloat u1, u2, u3;
  136. GLfloat v1, v2, v3;
  137. u1 = b.x - a.x;
  138. u2 = b.y - a.y;
  139. u3 = b.y - a.z;
  140. v1 = c.x - a.x;
  141. v2 = c.y - a.y;
  142. v3 = c.z - a.z;
  143. n->x = u2 * v3 - v2 * u3;
  144. n->y = u3 * v1 - v3 * u1;
  145. n->z = u1 * v2 - v1 * u2;
  146. }
  147. #define BOING_DEBUG 0
  148. /*****************************************************************************
  149. * init()
  150. *****************************************************************************/
  151. void init( void )
  152. {
  153. /*
  154. * Clear background.
  155. */
  156. glClearColor( 0.55f, 0.55f, 0.55f, 0.f );
  157. glShadeModel( GL_FLAT );
  158. }
  159. /*****************************************************************************
  160. * display()
  161. *****************************************************************************/
  162. void display(void)
  163. {
  164. glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  165. glPushMatrix();
  166. drawBallHow = DRAW_BALL_SHADOW;
  167. DrawBoingBall();
  168. DrawGrid();
  169. drawBallHow = DRAW_BALL;
  170. DrawBoingBall();
  171. glPopMatrix();
  172. glFlush();
  173. }
  174. /*****************************************************************************
  175. * reshape()
  176. *****************************************************************************/
  177. void reshape( GLFWwindow* window, int w, int h )
  178. {
  179. mat4x4 projection, view;
  180. glViewport( 0, 0, (GLsizei)w, (GLsizei)h );
  181. glMatrixMode( GL_PROJECTION );
  182. mat4x4_perspective( projection,
  183. 2.f * (float) atan2( RADIUS, 200.f ),
  184. (float)w / (float)h,
  185. 1.f, VIEW_SCENE_DIST );
  186. glLoadMatrixf((const GLfloat*) projection);
  187. glMatrixMode( GL_MODELVIEW );
  188. {
  189. vec3 eye = { 0.f, 0.f, VIEW_SCENE_DIST };
  190. vec3 center = { 0.f, 0.f, 0.f };
  191. vec3 up = { 0.f, -1.f, 0.f };
  192. mat4x4_look_at( view, eye, center, up );
  193. }
  194. glLoadMatrixf((const GLfloat*) view);
  195. }
  196. void key_callback( GLFWwindow* window, int key, int scancode, int action, int mods )
  197. {
  198. if (action != GLFW_PRESS)
  199. return;
  200. if (key == GLFW_KEY_ESCAPE && mods == 0)
  201. glfwSetWindowShouldClose(window, GLFW_TRUE);
  202. if ((key == GLFW_KEY_ENTER && mods == GLFW_MOD_ALT) ||
  203. (key == GLFW_KEY_F11 && mods == GLFW_MOD_ALT))
  204. {
  205. if (glfwGetWindowMonitor(window))
  206. {
  207. glfwSetWindowMonitor(window, NULL,
  208. windowed_xpos, windowed_ypos,
  209. windowed_width, windowed_height, 0);
  210. }
  211. else
  212. {
  213. GLFWmonitor* monitor = glfwGetPrimaryMonitor();
  214. if (monitor)
  215. {
  216. const GLFWvidmode* mode = glfwGetVideoMode(monitor);
  217. glfwGetWindowPos(window, &windowed_xpos, &windowed_ypos);
  218. glfwGetWindowSize(window, &windowed_width, &windowed_height);
  219. glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
  220. }
  221. }
  222. }
  223. }
  224. static void set_ball_pos ( GLfloat x, GLfloat y )
  225. {
  226. ball_x = (width / 2) - x;
  227. ball_y = y - (height / 2);
  228. }
  229. void mouse_button_callback( GLFWwindow* window, int button, int action, int mods )
  230. {
  231. if (button != GLFW_MOUSE_BUTTON_LEFT)
  232. return;
  233. if (action == GLFW_PRESS)
  234. {
  235. override_pos = GLFW_TRUE;
  236. set_ball_pos(cursor_x, cursor_y);
  237. }
  238. else
  239. {
  240. override_pos = GLFW_FALSE;
  241. }
  242. }
  243. void cursor_position_callback( GLFWwindow* window, double x, double y )
  244. {
  245. cursor_x = (float) x;
  246. cursor_y = (float) y;
  247. if ( override_pos )
  248. set_ball_pos(cursor_x, cursor_y);
  249. }
  250. /*****************************************************************************
  251. * Draw the Boing ball.
  252. *
  253. * The Boing ball is sphere in which each facet is a rectangle.
  254. * Facet colors alternate between red and white.
  255. * The ball is built by stacking latitudinal circles. Each circle is composed
  256. * of a widely-separated set of points, so that each facet is noticeably large.
  257. *****************************************************************************/
  258. void DrawBoingBall( void )
  259. {
  260. GLfloat lon_deg; /* degree of longitude */
  261. double dt_total, dt2;
  262. glPushMatrix();
  263. glMatrixMode( GL_MODELVIEW );
  264. /*
  265. * Another relative Z translation to separate objects.
  266. */
  267. glTranslatef( 0.0, 0.0, DIST_BALL );
  268. /* Update ball position and rotation (iterate if necessary) */
  269. dt_total = dt;
  270. while( dt_total > 0.0 )
  271. {
  272. dt2 = dt_total > MAX_DELTA_T ? MAX_DELTA_T : dt_total;
  273. dt_total -= dt2;
  274. BounceBall( dt2 );
  275. deg_rot_y = TruncateDeg( deg_rot_y + deg_rot_y_inc*((float)dt2*ANIMATION_SPEED) );
  276. }
  277. /* Set ball position */
  278. glTranslatef( ball_x, ball_y, 0.0 );
  279. /*
  280. * Offset the shadow.
  281. */
  282. if ( drawBallHow == DRAW_BALL_SHADOW )
  283. {
  284. glTranslatef( SHADOW_OFFSET_X,
  285. SHADOW_OFFSET_Y,
  286. SHADOW_OFFSET_Z );
  287. }
  288. /*
  289. * Tilt the ball.
  290. */
  291. glRotatef( -20.0, 0.0, 0.0, 1.0 );
  292. /*
  293. * Continually rotate ball around Y axis.
  294. */
  295. glRotatef( deg_rot_y, 0.0, 1.0, 0.0 );
  296. /*
  297. * Set OpenGL state for Boing ball.
  298. */
  299. glCullFace( GL_FRONT );
  300. glEnable( GL_CULL_FACE );
  301. glEnable( GL_NORMALIZE );
  302. /*
  303. * Build a faceted latitude slice of the Boing ball,
  304. * stepping same-sized vertical bands of the sphere.
  305. */
  306. for ( lon_deg = 0;
  307. lon_deg < 180;
  308. lon_deg += STEP_LONGITUDE )
  309. {
  310. /*
  311. * Draw a latitude circle at this longitude.
  312. */
  313. DrawBoingBallBand( lon_deg,
  314. lon_deg + STEP_LONGITUDE );
  315. }
  316. glPopMatrix();
  317. return;
  318. }
  319. /*****************************************************************************
  320. * Bounce the ball.
  321. *****************************************************************************/
  322. void BounceBall( double delta_t )
  323. {
  324. GLfloat sign;
  325. GLfloat deg;
  326. if ( override_pos )
  327. return;
  328. /* Bounce on walls */
  329. if ( ball_x > (BOUNCE_WIDTH/2 + WALL_R_OFFSET ) )
  330. {
  331. ball_x_inc = -0.5f - 0.75f * (GLfloat)rand() / (GLfloat)RAND_MAX;
  332. deg_rot_y_inc = -deg_rot_y_inc;
  333. }
  334. if ( ball_x < -(BOUNCE_HEIGHT/2 + WALL_L_OFFSET) )
  335. {
  336. ball_x_inc = 0.5f + 0.75f * (GLfloat)rand() / (GLfloat)RAND_MAX;
  337. deg_rot_y_inc = -deg_rot_y_inc;
  338. }
  339. /* Bounce on floor / roof */
  340. if ( ball_y > BOUNCE_HEIGHT/2 )
  341. {
  342. ball_y_inc = -0.75f - 1.f * (GLfloat)rand() / (GLfloat)RAND_MAX;
  343. }
  344. if ( ball_y < -BOUNCE_HEIGHT/2*0.85 )
  345. {
  346. ball_y_inc = 0.75f + 1.f * (GLfloat)rand() / (GLfloat)RAND_MAX;
  347. }
  348. /* Update ball position */
  349. ball_x += ball_x_inc * ((float)delta_t*ANIMATION_SPEED);
  350. ball_y += ball_y_inc * ((float)delta_t*ANIMATION_SPEED);
  351. /*
  352. * Simulate the effects of gravity on Y movement.
  353. */
  354. if ( ball_y_inc < 0 ) sign = -1.0; else sign = 1.0;
  355. deg = (ball_y + BOUNCE_HEIGHT/2) * 90 / BOUNCE_HEIGHT;
  356. if ( deg > 80 ) deg = 80;
  357. if ( deg < 10 ) deg = 10;
  358. ball_y_inc = sign * 4.f * (float) sin_deg( deg );
  359. }
  360. /*****************************************************************************
  361. * Draw a faceted latitude band of the Boing ball.
  362. *
  363. * Parms: long_lo, long_hi
  364. * Low and high longitudes of slice, resp.
  365. *****************************************************************************/
  366. void DrawBoingBallBand( GLfloat long_lo,
  367. GLfloat long_hi )
  368. {
  369. vertex_t vert_ne; /* "ne" means south-east, so on */
  370. vertex_t vert_nw;
  371. vertex_t vert_sw;
  372. vertex_t vert_se;
  373. vertex_t vert_norm;
  374. GLfloat lat_deg;
  375. static int colorToggle = 0;
  376. /*
  377. * Iterate through the points of a latitude circle.
  378. * A latitude circle is a 2D set of X,Z points.
  379. */
  380. for ( lat_deg = 0;
  381. lat_deg <= (360 - STEP_LATITUDE);
  382. lat_deg += STEP_LATITUDE )
  383. {
  384. /*
  385. * Color this polygon with red or white.
  386. */
  387. if ( colorToggle )
  388. glColor3f( 0.8f, 0.1f, 0.1f );
  389. else
  390. glColor3f( 0.95f, 0.95f, 0.95f );
  391. #if 0
  392. if ( lat_deg >= 180 )
  393. if ( colorToggle )
  394. glColor3f( 0.1f, 0.8f, 0.1f );
  395. else
  396. glColor3f( 0.5f, 0.5f, 0.95f );
  397. #endif
  398. colorToggle = ! colorToggle;
  399. /*
  400. * Change color if drawing shadow.
  401. */
  402. if ( drawBallHow == DRAW_BALL_SHADOW )
  403. glColor3f( 0.35f, 0.35f, 0.35f );
  404. /*
  405. * Assign each Y.
  406. */
  407. vert_ne.y = vert_nw.y = (float) cos_deg(long_hi) * RADIUS;
  408. vert_sw.y = vert_se.y = (float) cos_deg(long_lo) * RADIUS;
  409. /*
  410. * Assign each X,Z with sin,cos values scaled by latitude radius indexed by longitude.
  411. * Eg, long=0 and long=180 are at the poles, so zero scale is sin(longitude),
  412. * while long=90 (sin(90)=1) is at equator.
  413. */
  414. vert_ne.x = (float) cos_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
  415. vert_se.x = (float) cos_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo ));
  416. vert_nw.x = (float) cos_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
  417. vert_sw.x = (float) cos_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo ));
  418. vert_ne.z = (float) sin_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
  419. vert_se.z = (float) sin_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo ));
  420. vert_nw.z = (float) sin_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
  421. vert_sw.z = (float) sin_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo ));
  422. /*
  423. * Draw the facet.
  424. */
  425. glBegin( GL_POLYGON );
  426. CrossProduct( vert_ne, vert_nw, vert_sw, &vert_norm );
  427. glNormal3f( vert_norm.x, vert_norm.y, vert_norm.z );
  428. glVertex3f( vert_ne.x, vert_ne.y, vert_ne.z );
  429. glVertex3f( vert_nw.x, vert_nw.y, vert_nw.z );
  430. glVertex3f( vert_sw.x, vert_sw.y, vert_sw.z );
  431. glVertex3f( vert_se.x, vert_se.y, vert_se.z );
  432. glEnd();
  433. #if BOING_DEBUG
  434. printf( "----------------------------------------------------------- \n" );
  435. printf( "lat = %f long_lo = %f long_hi = %f \n", lat_deg, long_lo, long_hi );
  436. printf( "vert_ne x = %.8f y = %.8f z = %.8f \n", vert_ne.x, vert_ne.y, vert_ne.z );
  437. printf( "vert_nw x = %.8f y = %.8f z = %.8f \n", vert_nw.x, vert_nw.y, vert_nw.z );
  438. printf( "vert_se x = %.8f y = %.8f z = %.8f \n", vert_se.x, vert_se.y, vert_se.z );
  439. printf( "vert_sw x = %.8f y = %.8f z = %.8f \n", vert_sw.x, vert_sw.y, vert_sw.z );
  440. #endif
  441. }
  442. /*
  443. * Toggle color so that next band will opposite red/white colors than this one.
  444. */
  445. colorToggle = ! colorToggle;
  446. /*
  447. * This circular band is done.
  448. */
  449. return;
  450. }
  451. /*****************************************************************************
  452. * Draw the purple grid of lines, behind the Boing ball.
  453. * When the Workbench is dropped to the bottom, Boing shows 12 rows.
  454. *****************************************************************************/
  455. void DrawGrid( void )
  456. {
  457. int row, col;
  458. const int rowTotal = 12; /* must be divisible by 2 */
  459. const int colTotal = rowTotal; /* must be same as rowTotal */
  460. const GLfloat widthLine = 2.0; /* should be divisible by 2 */
  461. const GLfloat sizeCell = GRID_SIZE / rowTotal;
  462. const GLfloat z_offset = -40.0;
  463. GLfloat xl, xr;
  464. GLfloat yt, yb;
  465. glPushMatrix();
  466. glDisable( GL_CULL_FACE );
  467. /*
  468. * Another relative Z translation to separate objects.
  469. */
  470. glTranslatef( 0.0, 0.0, DIST_BALL );
  471. /*
  472. * Draw vertical lines (as skinny 3D rectangles).
  473. */
  474. for ( col = 0; col <= colTotal; col++ )
  475. {
  476. /*
  477. * Compute co-ords of line.
  478. */
  479. xl = -GRID_SIZE / 2 + col * sizeCell;
  480. xr = xl + widthLine;
  481. yt = GRID_SIZE / 2;
  482. yb = -GRID_SIZE / 2 - widthLine;
  483. glBegin( GL_POLYGON );
  484. glColor3f( 0.6f, 0.1f, 0.6f ); /* purple */
  485. glVertex3f( xr, yt, z_offset ); /* NE */
  486. glVertex3f( xl, yt, z_offset ); /* NW */
  487. glVertex3f( xl, yb, z_offset ); /* SW */
  488. glVertex3f( xr, yb, z_offset ); /* SE */
  489. glEnd();
  490. }
  491. /*
  492. * Draw horizontal lines (as skinny 3D rectangles).
  493. */
  494. for ( row = 0; row <= rowTotal; row++ )
  495. {
  496. /*
  497. * Compute co-ords of line.
  498. */
  499. yt = GRID_SIZE / 2 - row * sizeCell;
  500. yb = yt - widthLine;
  501. xl = -GRID_SIZE / 2;
  502. xr = GRID_SIZE / 2 + widthLine;
  503. glBegin( GL_POLYGON );
  504. glColor3f( 0.6f, 0.1f, 0.6f ); /* purple */
  505. glVertex3f( xr, yt, z_offset ); /* NE */
  506. glVertex3f( xl, yt, z_offset ); /* NW */
  507. glVertex3f( xl, yb, z_offset ); /* SW */
  508. glVertex3f( xr, yb, z_offset ); /* SE */
  509. glEnd();
  510. }
  511. glPopMatrix();
  512. return;
  513. }
  514. /*======================================================================*
  515. * main()
  516. *======================================================================*/
  517. int main( void )
  518. {
  519. GLFWwindow* window;
  520. /* Init GLFW */
  521. if( !glfwInit() )
  522. exit( EXIT_FAILURE );
  523. window = glfwCreateWindow( 400, 400, "Boing (classic Amiga demo)", NULL, NULL );
  524. if (!window)
  525. {
  526. glfwTerminate();
  527. exit( EXIT_FAILURE );
  528. }
  529. glfwSetWindowAspectRatio(window, 1, 1);
  530. glfwSetFramebufferSizeCallback(window, reshape);
  531. glfwSetKeyCallback(window, key_callback);
  532. glfwSetMouseButtonCallback(window, mouse_button_callback);
  533. glfwSetCursorPosCallback(window, cursor_position_callback);
  534. glfwMakeContextCurrent(window);
  535. gladLoadGL(glfwGetProcAddress);
  536. glfwSwapInterval( 1 );
  537. glfwGetFramebufferSize(window, &width, &height);
  538. reshape(window, width, height);
  539. glfwSetTime( 0.0 );
  540. init();
  541. /* Main loop */
  542. for (;;)
  543. {
  544. /* Timing */
  545. t = glfwGetTime();
  546. dt = t - t_old;
  547. t_old = t;
  548. /* Draw one frame */
  549. display();
  550. /* Swap buffers */
  551. glfwSwapBuffers(window);
  552. glfwPollEvents();
  553. /* Check if we are still running */
  554. if (glfwWindowShouldClose(window))
  555. break;
  556. }
  557. glfwTerminate();
  558. exit( EXIT_SUCCESS );
  559. }