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