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