Camilla Berglund | 3249f81 | 2010-09-07 17:34:51 +0200 | [diff] [blame] | 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 | |
| 30 | #include <stdio.h> |
| 31 | #include <stdlib.h> |
| 32 | #include <math.h> |
Camilla Berglund | 2213450 | 2012-06-05 23:55:10 +0200 | [diff] [blame] | 33 | |
| 34 | #define GLFW_INCLUDE_GLU |
Camilla Berglund | cfbafc5 | 2010-09-10 13:16:03 +0200 | [diff] [blame] | 35 | #include <GL/glfw3.h> |
Camilla Berglund | 3249f81 | 2010-09-07 17:34:51 +0200 | [diff] [blame] | 36 | |
| 37 | |
| 38 | /***************************************************************************** |
| 39 | * Various declarations and macros |
| 40 | *****************************************************************************/ |
| 41 | |
| 42 | /* Prototypes */ |
| 43 | void init( void ); |
| 44 | void display( void ); |
Camilla Berglund | 9af960e | 2013-01-05 21:13:28 +0100 | [diff] [blame] | 45 | void reshape( GLFWwindow* window, int w, int h ); |
Camilla Berglund | 3249f81 | 2010-09-07 17:34:51 +0200 | [diff] [blame] | 46 | void DrawBoingBall( void ); |
| 47 | void BounceBall( double dt ); |
| 48 | void DrawBoingBallBand( GLfloat long_lo, GLfloat long_hi ); |
| 49 | void DrawGrid( void ); |
| 50 | |
| 51 | #define RADIUS 70.f |
| 52 | #define STEP_LONGITUDE 22.5f /* 22.5 makes 8 bands like original Boing */ |
| 53 | #define STEP_LATITUDE 22.5f |
| 54 | |
| 55 | #define DIST_BALL (RADIUS * 2.f + RADIUS * 0.1f) |
| 56 | |
| 57 | #define VIEW_SCENE_DIST (DIST_BALL * 3.f + 200.f)/* distance from viewer to middle of boing area */ |
| 58 | #define GRID_SIZE (RADIUS * 4.5f) /* length (width) of grid */ |
| 59 | #define BOUNCE_HEIGHT (RADIUS * 2.1f) |
| 60 | #define BOUNCE_WIDTH (RADIUS * 2.1f) |
| 61 | |
| 62 | #define SHADOW_OFFSET_X -20.f |
| 63 | #define SHADOW_OFFSET_Y 10.f |
| 64 | #define SHADOW_OFFSET_Z 0.f |
| 65 | |
| 66 | #define WALL_L_OFFSET 0.f |
| 67 | #define WALL_R_OFFSET 5.f |
| 68 | |
| 69 | /* Animation speed (50.0 mimics the original GLUT demo speed) */ |
| 70 | #define ANIMATION_SPEED 50.f |
| 71 | |
| 72 | /* Maximum allowed delta time per physics iteration */ |
| 73 | #define MAX_DELTA_T 0.02f |
| 74 | |
| 75 | /* Draw ball, or its shadow */ |
| 76 | typedef enum { DRAW_BALL, DRAW_BALL_SHADOW } DRAW_BALL_ENUM; |
| 77 | |
| 78 | /* Vertex type */ |
| 79 | typedef struct {float x; float y; float z;} vertex_t; |
| 80 | |
| 81 | /* Global vars */ |
| 82 | GLfloat deg_rot_y = 0.f; |
| 83 | GLfloat deg_rot_y_inc = 2.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 | |
| 93 | /* Random number generator */ |
| 94 | #ifndef RAND_MAX |
| 95 | #define RAND_MAX 4095 |
| 96 | #endif |
| 97 | |
| 98 | /* PI */ |
| 99 | #ifndef M_PI |
| 100 | #define M_PI 3.1415926535897932384626433832795 |
| 101 | #endif |
| 102 | |
| 103 | |
| 104 | /***************************************************************************** |
| 105 | * Truncate a degree. |
| 106 | *****************************************************************************/ |
| 107 | GLfloat TruncateDeg( GLfloat deg ) |
| 108 | { |
| 109 | if ( deg >= 360.f ) |
| 110 | return (deg - 360.f); |
| 111 | else |
| 112 | return deg; |
| 113 | } |
| 114 | |
| 115 | /***************************************************************************** |
| 116 | * Convert a degree (360-based) into a radian. |
| 117 | * 360' = 2 * PI |
| 118 | *****************************************************************************/ |
| 119 | double deg2rad( double deg ) |
| 120 | { |
| 121 | return deg / 360 * (2 * M_PI); |
| 122 | } |
| 123 | |
| 124 | /***************************************************************************** |
| 125 | * 360' sin(). |
| 126 | *****************************************************************************/ |
| 127 | double sin_deg( double deg ) |
| 128 | { |
| 129 | return sin( deg2rad( deg ) ); |
| 130 | } |
| 131 | |
| 132 | /***************************************************************************** |
| 133 | * 360' cos(). |
| 134 | *****************************************************************************/ |
| 135 | double cos_deg( double deg ) |
| 136 | { |
| 137 | return cos( deg2rad( deg ) ); |
| 138 | } |
| 139 | |
| 140 | /***************************************************************************** |
| 141 | * Compute a cross product (for a normal vector). |
| 142 | * |
| 143 | * c = a x b |
| 144 | *****************************************************************************/ |
| 145 | void CrossProduct( vertex_t a, vertex_t b, vertex_t c, vertex_t *n ) |
| 146 | { |
| 147 | GLfloat u1, u2, u3; |
| 148 | GLfloat v1, v2, v3; |
| 149 | |
| 150 | u1 = b.x - a.x; |
| 151 | u2 = b.y - a.y; |
| 152 | u3 = b.y - a.z; |
| 153 | |
| 154 | v1 = c.x - a.x; |
| 155 | v2 = c.y - a.y; |
| 156 | v3 = c.z - a.z; |
| 157 | |
| 158 | n->x = u2 * v3 - v2 * v3; |
| 159 | n->y = u3 * v1 - v3 * u1; |
| 160 | n->z = u1 * v2 - v1 * u2; |
| 161 | } |
| 162 | |
| 163 | /***************************************************************************** |
| 164 | * Calculate the angle to be passed to gluPerspective() so that a scene |
| 165 | * is visible. This function originates from the OpenGL Red Book. |
| 166 | * |
| 167 | * Parms : size |
| 168 | * The size of the segment when the angle is intersected at "dist" |
| 169 | * (ie at the outermost edge of the angle of vision). |
| 170 | * |
| 171 | * dist |
| 172 | * Distance from viewpoint to scene. |
| 173 | *****************************************************************************/ |
| 174 | GLfloat PerspectiveAngle( GLfloat size, |
| 175 | GLfloat dist ) |
| 176 | { |
| 177 | GLfloat radTheta, degTheta; |
| 178 | |
| 179 | radTheta = 2.f * (GLfloat) atan2( size / 2.f, dist ); |
| 180 | degTheta = (180.f * radTheta) / (GLfloat) M_PI; |
| 181 | return degTheta; |
| 182 | } |
| 183 | |
| 184 | |
| 185 | |
| 186 | #define BOING_DEBUG 0 |
| 187 | |
| 188 | |
| 189 | /***************************************************************************** |
| 190 | * init() |
| 191 | *****************************************************************************/ |
| 192 | void init( void ) |
| 193 | { |
| 194 | /* |
| 195 | * Clear background. |
| 196 | */ |
| 197 | glClearColor( 0.55f, 0.55f, 0.55f, 0.f ); |
| 198 | |
| 199 | glShadeModel( GL_FLAT ); |
| 200 | } |
| 201 | |
| 202 | |
| 203 | /***************************************************************************** |
| 204 | * display() |
| 205 | *****************************************************************************/ |
| 206 | void display(void) |
| 207 | { |
| 208 | glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); |
| 209 | glPushMatrix(); |
| 210 | |
| 211 | drawBallHow = DRAW_BALL_SHADOW; |
| 212 | DrawBoingBall(); |
| 213 | |
| 214 | DrawGrid(); |
| 215 | |
| 216 | drawBallHow = DRAW_BALL; |
| 217 | DrawBoingBall(); |
| 218 | |
| 219 | glPopMatrix(); |
| 220 | glFlush(); |
| 221 | } |
| 222 | |
| 223 | |
| 224 | /***************************************************************************** |
| 225 | * reshape() |
| 226 | *****************************************************************************/ |
Camilla Berglund | 9af960e | 2013-01-05 21:13:28 +0100 | [diff] [blame] | 227 | void reshape( GLFWwindow* window, int w, int h ) |
Camilla Berglund | 3249f81 | 2010-09-07 17:34:51 +0200 | [diff] [blame] | 228 | { |
| 229 | glViewport( 0, 0, (GLsizei)w, (GLsizei)h ); |
| 230 | |
| 231 | glMatrixMode( GL_PROJECTION ); |
| 232 | glLoadIdentity(); |
| 233 | |
| 234 | gluPerspective( PerspectiveAngle( RADIUS * 2, 200 ), |
| 235 | (GLfloat)w / (GLfloat)h, |
| 236 | 1.0, |
| 237 | VIEW_SCENE_DIST ); |
| 238 | |
| 239 | glMatrixMode( GL_MODELVIEW ); |
| 240 | glLoadIdentity(); |
| 241 | |
| 242 | gluLookAt( 0.0, 0.0, VIEW_SCENE_DIST,/* eye */ |
| 243 | 0.0, 0.0, 0.0, /* center of vision */ |
| 244 | 0.0, -1.0, 0.0 ); /* up vector */ |
| 245 | } |
| 246 | |
| 247 | |
| 248 | /***************************************************************************** |
| 249 | * Draw the Boing ball. |
| 250 | * |
| 251 | * The Boing ball is sphere in which each facet is a rectangle. |
| 252 | * Facet colors alternate between red and white. |
| 253 | * The ball is built by stacking latitudinal circles. Each circle is composed |
| 254 | * of a widely-separated set of points, so that each facet is noticably large. |
| 255 | *****************************************************************************/ |
| 256 | void DrawBoingBall( void ) |
| 257 | { |
| 258 | GLfloat lon_deg; /* degree of longitude */ |
| 259 | double dt_total, dt2; |
| 260 | |
| 261 | glPushMatrix(); |
| 262 | glMatrixMode( GL_MODELVIEW ); |
| 263 | |
| 264 | /* |
| 265 | * Another relative Z translation to separate objects. |
| 266 | */ |
| 267 | glTranslatef( 0.0, 0.0, DIST_BALL ); |
| 268 | |
| 269 | /* Update ball position and rotation (iterate if necessary) */ |
| 270 | dt_total = dt; |
| 271 | while( dt_total > 0.0 ) |
| 272 | { |
| 273 | dt2 = dt_total > MAX_DELTA_T ? MAX_DELTA_T : dt_total; |
| 274 | dt_total -= dt2; |
| 275 | BounceBall( dt2 ); |
| 276 | deg_rot_y = TruncateDeg( deg_rot_y + deg_rot_y_inc*((float)dt2*ANIMATION_SPEED) ); |
| 277 | } |
| 278 | |
| 279 | /* Set ball position */ |
| 280 | glTranslatef( ball_x, ball_y, 0.0 ); |
| 281 | |
| 282 | /* |
| 283 | * Offset the shadow. |
| 284 | */ |
| 285 | if ( drawBallHow == DRAW_BALL_SHADOW ) |
| 286 | { |
| 287 | glTranslatef( SHADOW_OFFSET_X, |
| 288 | SHADOW_OFFSET_Y, |
| 289 | SHADOW_OFFSET_Z ); |
| 290 | } |
| 291 | |
| 292 | /* |
| 293 | * Tilt the ball. |
| 294 | */ |
| 295 | glRotatef( -20.0, 0.0, 0.0, 1.0 ); |
| 296 | |
| 297 | /* |
| 298 | * Continually rotate ball around Y axis. |
| 299 | */ |
| 300 | glRotatef( deg_rot_y, 0.0, 1.0, 0.0 ); |
| 301 | |
| 302 | /* |
| 303 | * Set OpenGL state for Boing ball. |
| 304 | */ |
| 305 | glCullFace( GL_FRONT ); |
| 306 | glEnable( GL_CULL_FACE ); |
| 307 | glEnable( GL_NORMALIZE ); |
| 308 | |
| 309 | /* |
| 310 | * Build a faceted latitude slice of the Boing ball, |
| 311 | * stepping same-sized vertical bands of the sphere. |
| 312 | */ |
| 313 | for ( lon_deg = 0; |
| 314 | lon_deg < 180; |
| 315 | lon_deg += STEP_LONGITUDE ) |
| 316 | { |
| 317 | /* |
| 318 | * Draw a latitude circle at this longitude. |
| 319 | */ |
| 320 | DrawBoingBallBand( lon_deg, |
| 321 | lon_deg + STEP_LONGITUDE ); |
| 322 | } |
| 323 | |
| 324 | glPopMatrix(); |
| 325 | |
| 326 | return; |
| 327 | } |
| 328 | |
| 329 | |
| 330 | /***************************************************************************** |
| 331 | * Bounce the ball. |
| 332 | *****************************************************************************/ |
Lambert Clara | c272918 | 2012-08-12 13:24:21 +0200 | [diff] [blame] | 333 | void BounceBall( double delta_t ) |
Camilla Berglund | 3249f81 | 2010-09-07 17:34:51 +0200 | [diff] [blame] | 334 | { |
| 335 | GLfloat sign; |
| 336 | GLfloat deg; |
| 337 | |
| 338 | /* Bounce on walls */ |
| 339 | if ( ball_x > (BOUNCE_WIDTH/2 + WALL_R_OFFSET ) ) |
| 340 | { |
| 341 | ball_x_inc = -0.5f - 0.75f * (GLfloat)rand() / (GLfloat)RAND_MAX; |
| 342 | deg_rot_y_inc = -deg_rot_y_inc; |
| 343 | } |
| 344 | if ( ball_x < -(BOUNCE_HEIGHT/2 + WALL_L_OFFSET) ) |
| 345 | { |
| 346 | ball_x_inc = 0.5f + 0.75f * (GLfloat)rand() / (GLfloat)RAND_MAX; |
| 347 | deg_rot_y_inc = -deg_rot_y_inc; |
| 348 | } |
| 349 | |
| 350 | /* Bounce on floor / roof */ |
| 351 | if ( ball_y > BOUNCE_HEIGHT/2 ) |
| 352 | { |
| 353 | ball_y_inc = -0.75f - 1.f * (GLfloat)rand() / (GLfloat)RAND_MAX; |
| 354 | } |
| 355 | if ( ball_y < -BOUNCE_HEIGHT/2*0.85 ) |
| 356 | { |
| 357 | ball_y_inc = 0.75f + 1.f * (GLfloat)rand() / (GLfloat)RAND_MAX; |
| 358 | } |
| 359 | |
| 360 | /* Update ball position */ |
Lambert Clara | c272918 | 2012-08-12 13:24:21 +0200 | [diff] [blame] | 361 | ball_x += ball_x_inc * ((float)delta_t*ANIMATION_SPEED); |
| 362 | ball_y += ball_y_inc * ((float)delta_t*ANIMATION_SPEED); |
Camilla Berglund | 3249f81 | 2010-09-07 17:34:51 +0200 | [diff] [blame] | 363 | |
| 364 | /* |
| 365 | * Simulate the effects of gravity on Y movement. |
| 366 | */ |
| 367 | if ( ball_y_inc < 0 ) sign = -1.0; else sign = 1.0; |
| 368 | |
| 369 | deg = (ball_y + BOUNCE_HEIGHT/2) * 90 / BOUNCE_HEIGHT; |
| 370 | if ( deg > 80 ) deg = 80; |
| 371 | if ( deg < 10 ) deg = 10; |
| 372 | |
| 373 | ball_y_inc = sign * 4.f * (float) sin_deg( deg ); |
| 374 | } |
| 375 | |
| 376 | |
| 377 | /***************************************************************************** |
| 378 | * Draw a faceted latitude band of the Boing ball. |
| 379 | * |
| 380 | * Parms: long_lo, long_hi |
| 381 | * Low and high longitudes of slice, resp. |
| 382 | *****************************************************************************/ |
| 383 | void DrawBoingBallBand( GLfloat long_lo, |
| 384 | GLfloat long_hi ) |
| 385 | { |
| 386 | vertex_t vert_ne; /* "ne" means south-east, so on */ |
| 387 | vertex_t vert_nw; |
| 388 | vertex_t vert_sw; |
| 389 | vertex_t vert_se; |
| 390 | vertex_t vert_norm; |
| 391 | GLfloat lat_deg; |
| 392 | static int colorToggle = 0; |
| 393 | |
| 394 | /* |
| 395 | * Iterate thru the points of a latitude circle. |
| 396 | * A latitude circle is a 2D set of X,Z points. |
| 397 | */ |
| 398 | for ( lat_deg = 0; |
| 399 | lat_deg <= (360 - STEP_LATITUDE); |
| 400 | lat_deg += STEP_LATITUDE ) |
| 401 | { |
| 402 | /* |
| 403 | * Color this polygon with red or white. |
| 404 | */ |
| 405 | if ( colorToggle ) |
| 406 | glColor3f( 0.8f, 0.1f, 0.1f ); |
| 407 | else |
| 408 | glColor3f( 0.95f, 0.95f, 0.95f ); |
| 409 | #if 0 |
| 410 | if ( lat_deg >= 180 ) |
| 411 | if ( colorToggle ) |
| 412 | glColor3f( 0.1f, 0.8f, 0.1f ); |
| 413 | else |
| 414 | glColor3f( 0.5f, 0.5f, 0.95f ); |
| 415 | #endif |
| 416 | colorToggle = ! colorToggle; |
| 417 | |
| 418 | /* |
| 419 | * Change color if drawing shadow. |
| 420 | */ |
| 421 | if ( drawBallHow == DRAW_BALL_SHADOW ) |
| 422 | glColor3f( 0.35f, 0.35f, 0.35f ); |
| 423 | |
| 424 | /* |
| 425 | * Assign each Y. |
| 426 | */ |
| 427 | vert_ne.y = vert_nw.y = (float) cos_deg(long_hi) * RADIUS; |
| 428 | vert_sw.y = vert_se.y = (float) cos_deg(long_lo) * RADIUS; |
| 429 | |
| 430 | /* |
| 431 | * Assign each X,Z with sin,cos values scaled by latitude radius indexed by longitude. |
| 432 | * Eg, long=0 and long=180 are at the poles, so zero scale is sin(longitude), |
| 433 | * while long=90 (sin(90)=1) is at equator. |
| 434 | */ |
| 435 | vert_ne.x = (float) cos_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE )); |
| 436 | vert_se.x = (float) cos_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo )); |
| 437 | vert_nw.x = (float) cos_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE )); |
| 438 | vert_sw.x = (float) cos_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo )); |
| 439 | |
| 440 | vert_ne.z = (float) sin_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE )); |
| 441 | vert_se.z = (float) sin_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo )); |
| 442 | vert_nw.z = (float) sin_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE )); |
| 443 | vert_sw.z = (float) sin_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo )); |
| 444 | |
| 445 | /* |
| 446 | * Draw the facet. |
| 447 | */ |
| 448 | glBegin( GL_POLYGON ); |
| 449 | |
| 450 | CrossProduct( vert_ne, vert_nw, vert_sw, &vert_norm ); |
| 451 | glNormal3f( vert_norm.x, vert_norm.y, vert_norm.z ); |
| 452 | |
| 453 | glVertex3f( vert_ne.x, vert_ne.y, vert_ne.z ); |
| 454 | glVertex3f( vert_nw.x, vert_nw.y, vert_nw.z ); |
| 455 | glVertex3f( vert_sw.x, vert_sw.y, vert_sw.z ); |
| 456 | glVertex3f( vert_se.x, vert_se.y, vert_se.z ); |
| 457 | |
| 458 | glEnd(); |
| 459 | |
| 460 | #if BOING_DEBUG |
| 461 | printf( "----------------------------------------------------------- \n" ); |
| 462 | printf( "lat = %f long_lo = %f long_hi = %f \n", lat_deg, long_lo, long_hi ); |
| 463 | printf( "vert_ne x = %.8f y = %.8f z = %.8f \n", vert_ne.x, vert_ne.y, vert_ne.z ); |
| 464 | printf( "vert_nw x = %.8f y = %.8f z = %.8f \n", vert_nw.x, vert_nw.y, vert_nw.z ); |
| 465 | printf( "vert_se x = %.8f y = %.8f z = %.8f \n", vert_se.x, vert_se.y, vert_se.z ); |
| 466 | printf( "vert_sw x = %.8f y = %.8f z = %.8f \n", vert_sw.x, vert_sw.y, vert_sw.z ); |
| 467 | #endif |
| 468 | |
| 469 | } |
| 470 | |
| 471 | /* |
| 472 | * Toggle color so that next band will opposite red/white colors than this one. |
| 473 | */ |
| 474 | colorToggle = ! colorToggle; |
| 475 | |
| 476 | /* |
| 477 | * This circular band is done. |
| 478 | */ |
| 479 | return; |
| 480 | } |
| 481 | |
| 482 | |
| 483 | /***************************************************************************** |
| 484 | * Draw the purple grid of lines, behind the Boing ball. |
| 485 | * When the Workbench is dropped to the bottom, Boing shows 12 rows. |
| 486 | *****************************************************************************/ |
| 487 | void DrawGrid( void ) |
| 488 | { |
| 489 | int row, col; |
| 490 | const int rowTotal = 12; /* must be divisible by 2 */ |
| 491 | const int colTotal = rowTotal; /* must be same as rowTotal */ |
| 492 | const GLfloat widthLine = 2.0; /* should be divisible by 2 */ |
| 493 | const GLfloat sizeCell = GRID_SIZE / rowTotal; |
| 494 | const GLfloat z_offset = -40.0; |
| 495 | GLfloat xl, xr; |
| 496 | GLfloat yt, yb; |
| 497 | |
| 498 | glPushMatrix(); |
| 499 | glDisable( GL_CULL_FACE ); |
| 500 | |
| 501 | /* |
| 502 | * Another relative Z translation to separate objects. |
| 503 | */ |
| 504 | glTranslatef( 0.0, 0.0, DIST_BALL ); |
| 505 | |
| 506 | /* |
| 507 | * Draw vertical lines (as skinny 3D rectangles). |
| 508 | */ |
| 509 | for ( col = 0; col <= colTotal; col++ ) |
| 510 | { |
| 511 | /* |
| 512 | * Compute co-ords of line. |
| 513 | */ |
| 514 | xl = -GRID_SIZE / 2 + col * sizeCell; |
| 515 | xr = xl + widthLine; |
| 516 | |
| 517 | yt = GRID_SIZE / 2; |
| 518 | yb = -GRID_SIZE / 2 - widthLine; |
| 519 | |
| 520 | glBegin( GL_POLYGON ); |
| 521 | |
| 522 | glColor3f( 0.6f, 0.1f, 0.6f ); /* purple */ |
| 523 | |
| 524 | glVertex3f( xr, yt, z_offset ); /* NE */ |
| 525 | glVertex3f( xl, yt, z_offset ); /* NW */ |
| 526 | glVertex3f( xl, yb, z_offset ); /* SW */ |
| 527 | glVertex3f( xr, yb, z_offset ); /* SE */ |
| 528 | |
| 529 | glEnd(); |
| 530 | } |
| 531 | |
| 532 | /* |
| 533 | * Draw horizontal lines (as skinny 3D rectangles). |
| 534 | */ |
| 535 | for ( row = 0; row <= rowTotal; row++ ) |
| 536 | { |
| 537 | /* |
| 538 | * Compute co-ords of line. |
| 539 | */ |
| 540 | yt = GRID_SIZE / 2 - row * sizeCell; |
| 541 | yb = yt - widthLine; |
| 542 | |
| 543 | xl = -GRID_SIZE / 2; |
| 544 | xr = GRID_SIZE / 2 + widthLine; |
| 545 | |
| 546 | glBegin( GL_POLYGON ); |
| 547 | |
| 548 | glColor3f( 0.6f, 0.1f, 0.6f ); /* purple */ |
| 549 | |
| 550 | glVertex3f( xr, yt, z_offset ); /* NE */ |
| 551 | glVertex3f( xl, yt, z_offset ); /* NW */ |
| 552 | glVertex3f( xl, yb, z_offset ); /* SW */ |
| 553 | glVertex3f( xr, yb, z_offset ); /* SE */ |
| 554 | |
| 555 | glEnd(); |
| 556 | } |
| 557 | |
| 558 | glPopMatrix(); |
| 559 | |
| 560 | return; |
| 561 | } |
| 562 | |
| 563 | |
| 564 | /*======================================================================* |
| 565 | * main() |
| 566 | *======================================================================*/ |
| 567 | |
| 568 | int main( void ) |
| 569 | { |
Camilla Berglund | 9af960e | 2013-01-05 21:13:28 +0100 | [diff] [blame] | 570 | GLFWwindow* window; |
Camilla Berglund | 8ed66ea | 2012-08-07 12:14:58 +0200 | [diff] [blame] | 571 | int width, height; |
Camilla Berglund | 3249f81 | 2010-09-07 17:34:51 +0200 | [diff] [blame] | 572 | |
| 573 | /* Init GLFW */ |
Camilla Berglund | 0c3b1b5 | 2012-02-07 14:58:58 +0100 | [diff] [blame] | 574 | if( !glfwInit() ) |
Camilla Berglund | 3249f81 | 2010-09-07 17:34:51 +0200 | [diff] [blame] | 575 | exit( EXIT_FAILURE ); |
Camilla Berglund | 3249f81 | 2010-09-07 17:34:51 +0200 | [diff] [blame] | 576 | |
Camilla Berglund | aff30d0 | 2012-08-06 17:56:41 +0200 | [diff] [blame] | 577 | glfwWindowHint(GLFW_DEPTH_BITS, 16); |
Camilla Berglund | 950a3be | 2010-09-09 19:58:51 +0200 | [diff] [blame] | 578 | |
Camilla Berglund | 1be1636 | 2012-09-27 21:37:36 +0200 | [diff] [blame] | 579 | window = glfwCreateWindow( 400, 400, "Boing (classic Amiga demo)", NULL, NULL ); |
Camilla Berglund | 39fd7a5 | 2010-09-09 18:16:07 +0200 | [diff] [blame] | 580 | if (!window) |
Camilla Berglund | 3249f81 | 2010-09-07 17:34:51 +0200 | [diff] [blame] | 581 | { |
Camilla Berglund | 3249f81 | 2010-09-07 17:34:51 +0200 | [diff] [blame] | 582 | glfwTerminate(); |
| 583 | exit( EXIT_FAILURE ); |
| 584 | } |
| 585 | |
Camilla Berglund | 18d71c2 | 2012-10-28 13:45:11 +0100 | [diff] [blame] | 586 | glfwSetWindowSizeCallback(window, reshape); |
| 587 | |
Camilla Berglund | 2f095cc | 2012-08-10 15:29:45 +0200 | [diff] [blame] | 588 | glfwMakeContextCurrent(window); |
| 589 | glfwSwapInterval( 1 ); |
| 590 | |
Camilla Berglund | 8ed66ea | 2012-08-07 12:14:58 +0200 | [diff] [blame] | 591 | glfwGetWindowSize(window, &width, &height); |
| 592 | reshape(window, width, height); |
| 593 | |
Camilla Berglund | ce288a8 | 2012-02-04 00:51:35 +0100 | [diff] [blame] | 594 | glfwSetInputMode( window, GLFW_STICKY_KEYS, GL_TRUE ); |
Camilla Berglund | 3249f81 | 2010-09-07 17:34:51 +0200 | [diff] [blame] | 595 | glfwSetTime( 0.0 ); |
| 596 | |
| 597 | init(); |
| 598 | |
| 599 | /* Main loop */ |
Camilla Berglund | 2410e2a | 2012-08-10 13:31:15 +0200 | [diff] [blame] | 600 | for (;;) |
Camilla Berglund | 3249f81 | 2010-09-07 17:34:51 +0200 | [diff] [blame] | 601 | { |
| 602 | /* Timing */ |
| 603 | t = glfwGetTime(); |
| 604 | dt = t - t_old; |
| 605 | t_old = t; |
| 606 | |
| 607 | /* Draw one frame */ |
| 608 | display(); |
| 609 | |
| 610 | /* Swap buffers */ |
Camilla Berglund | 585a840 | 2012-08-06 18:13:37 +0200 | [diff] [blame] | 611 | glfwSwapBuffers(window); |
Camilla Berglund | 39fd7a5 | 2010-09-09 18:16:07 +0200 | [diff] [blame] | 612 | glfwPollEvents(); |
Camilla Berglund | 3249f81 | 2010-09-07 17:34:51 +0200 | [diff] [blame] | 613 | |
| 614 | /* Check if we are still running */ |
Camilla Berglund | 2972cdf | 2012-08-03 16:20:52 +0200 | [diff] [blame] | 615 | if (glfwGetKey( window, GLFW_KEY_ESCAPE )) |
Camilla Berglund | 2410e2a | 2012-08-10 13:31:15 +0200 | [diff] [blame] | 616 | break; |
Camilla Berglund | 21f41a2 | 2012-12-31 19:45:13 +0100 | [diff] [blame] | 617 | if (glfwGetWindowParam(window, GLFW_SHOULD_CLOSE)) |
Camilla Berglund | 2410e2a | 2012-08-10 13:31:15 +0200 | [diff] [blame] | 618 | break; |
Camilla Berglund | 3249f81 | 2010-09-07 17:34:51 +0200 | [diff] [blame] | 619 | } |
Camilla Berglund | 3249f81 | 2010-09-07 17:34:51 +0200 | [diff] [blame] | 620 | |
| 621 | glfwTerminate(); |
| 622 | exit( EXIT_SUCCESS ); |
| 623 | } |
| 624 | |