boing.c 19 KB

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