1 2/* 3 * Display an isosurface of 3-D wind speed volume. 4 * 5 * Command line options: 6 * -info print GL implementation information 7 * 8 * Brian Paul This file in public domain. 9 */ 10 11 12/* Keys: 13 * ===== 14 * 15 * - Arrow keys to rotate 16 * - 's' toggles smooth shading 17 * - 'l' toggles lighting 18 * - 'f' toggles fog 19 * - 'I' and 'i' zoom in and out 20 * - 'c' toggles a user clip plane 21 * - 'm' toggles colorful materials in GL_TRIANGLES modes. 22 * - '+' and '-' move the user clip plane 23 * 24 * Other options are available via the popup menu. 25 */ 26 27#include <stdio.h> 28#include <string.h> 29#include <stdlib.h> 30#include <math.h> 31#ifdef _WIN32 32#include <windows.h> 33#undef CLIP_MASK 34#endif 35#include <GL/glew.h> 36#include "glut_wrap.h" 37 38#include "readtex.h" 39#define TEXTURE_FILE DEMOS_DATA_DIR "reflect.rgb" 40 41#define LIT 0x00000001 42#define UNLIT 0x00000002 43#define REFLECT 0x00000004 44#define POINT_FILTER 0x00000008 45#define LINEAR_FILTER 0x00000010 46#define GLVERTEX 0x00000020 47#define DRAW_ELTS 0x00000040 48#define DRAW_ARRAYS 0x00000080 49#define ARRAY_ELT 0x00000100 50#define LOCKED 0x00000200 51#define UNLOCKED 0x00000400 52#define IMMEDIATE 0x00000800 53#define DISPLAYLIST 0x00001000 54#define SHADE_SMOOTH 0x00002000 55#define SHADE_FLAT 0x00004000 56#define TRIANGLES 0x00008000 57#define STRIPS 0x00010000 58#define POINTS 0x00020000 59#define USER_CLIP 0x00040000 60#define NO_USER_CLIP 0x00080000 61#define MATERIALS 0x00100000 62#define NO_MATERIALS 0x00200000 63#define FOG 0x00400000 64#define NO_FOG 0x00800000 65#define QUIT 0x01000000 66#define GLINFO 0x02000000 67#define STIPPLE 0x04000000 68#define NO_STIPPLE 0x08000000 69#define POLYGON_FILL 0x10000000 70#define POLYGON_LINE 0x20000000 71#define POLYGON_POINT 0x40000000 72 73#define LIGHT_MASK (LIT|UNLIT|REFLECT) 74#define FILTER_MASK (POINT_FILTER|LINEAR_FILTER) 75#define RENDER_STYLE_MASK (GLVERTEX|DRAW_ARRAYS|DRAW_ELTS|ARRAY_ELT) 76#define DLIST_MASK (IMMEDIATE|DISPLAYLIST) 77#define LOCK_MASK (LOCKED|UNLOCKED) 78#define MATERIAL_MASK (MATERIALS|NO_MATERIALS) 79#define PRIMITIVE_MASK (TRIANGLES|STRIPS|POINTS) 80#define CLIP_MASK (USER_CLIP|NO_USER_CLIP) 81#define SHADE_MASK (SHADE_SMOOTH|SHADE_FLAT) 82#define FOG_MASK (FOG|NO_FOG) 83#define STIPPLE_MASK (STIPPLE|NO_STIPPLE) 84#define POLYGON_MASK (POLYGON_FILL|POLYGON_LINE|POLYGON_POINT) 85 86#define MAXVERTS 10000 87static GLint maxverts = MAXVERTS; 88static float data[MAXVERTS][6]; 89static float compressed_data[MAXVERTS][6]; 90static float expanded_data[MAXVERTS*3][6]; 91static GLuint indices[MAXVERTS]; 92static GLuint tri_indices[MAXVERTS*3]; 93static GLuint strip_indices[MAXVERTS]; 94static GLfloat col[100][4]; 95static GLint numverts, num_tri_verts, numuniq; 96 97static GLfloat xrot; 98static GLfloat yrot; 99static GLfloat dist; 100static GLint state, allowed = ~0; 101static GLboolean doubleBuffer = GL_TRUE; 102static GLdouble plane[4]; 103static GLuint surf1, dlist_state; 104 105static GLboolean PrintInfo = GL_FALSE; 106 107 108static GLubyte halftone[] = { 109 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 110 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 111 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 112 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 113 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 114 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 115 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 116 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 117 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 118 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 119 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55}; 120 121 122static void read_surface( char *filename ) 123{ 124 FILE *f; 125 126 f = fopen(filename,"r"); 127 if (!f) { 128 printf("couldn't read %s\n", filename); 129 exit(1); 130 } 131 132 numverts = 0; 133 while (!feof(f) && numverts<maxverts) { 134 int result; 135 result = fscanf( f, "%f %f %f %f %f %f", 136 &data[numverts][0], &data[numverts][1], &data[numverts][2], 137 &data[numverts][3], &data[numverts][4], &data[numverts][5] ); 138 (void) result; 139 numverts++; 140 } 141 numverts--; 142 143 printf("%d vertices, %d triangles\n", numverts, numverts-2); 144 fclose(f); 145} 146 147 148 149static void print_flags( const char *msg, GLuint flags ) 150{ 151 fprintf(stderr, 152 "%s (0x%x): %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", 153 msg, flags, 154 (flags & GLVERTEX) ? "glVertex, " : "", 155 (flags & DRAW_ARRAYS) ? "glDrawArrays, " : "", 156 (flags & DRAW_ELTS) ? "glDrawElements, " : "", 157 (flags & ARRAY_ELT) ? "glArrayElement, " : "", 158 (flags & LOCKED) ? "locked arrays, " : "", 159 (flags & TRIANGLES) ? "GL_TRIANGLES, " : "", 160 (flags & STRIPS) ? "GL_TRIANGLE_STRIP, " : "", 161 (flags & POINTS) ? "GL_POINTS, " : "", 162 (flags & DISPLAYLIST) ? "as a displaylist, " : "", 163 (flags & LIT) ? "lit, " : "", 164 (flags & UNLIT) ? "unlit, " : "", 165 (flags & REFLECT) ? "reflect, " : "", 166 (flags & SHADE_FLAT) ? "flat-shaded, " : "", 167 (flags & USER_CLIP) ? "user_clip, " : "", 168 (flags & MATERIALS) ? "materials, " : "", 169 (flags & FOG) ? "fog, " : "", 170 (flags & STIPPLE) ? "stipple, " : "", 171 (flags & POLYGON_LINE) ? "polygon mode line, " : "", 172 (flags & POLYGON_POINT) ? "polygon mode point, " : ""); 173} 174 175 176 177struct data_idx { 178 float *data; 179 int idx; 180 int uniq_idx; 181}; 182 183 184#define COMPARE_FUNC( AXIS ) \ 185static int compare_axis_##AXIS( const void *a, const void *b ) \ 186{ \ 187 float t = ( (*(struct data_idx *)a).data[AXIS] - \ 188 (*(struct data_idx *)b).data[AXIS] ); \ 189 \ 190 if (t < 0) return -1; \ 191 if (t > 0) return 1; \ 192 return 0; \ 193} 194 195COMPARE_FUNC(0) 196COMPARE_FUNC(1) 197COMPARE_FUNC(2) 198COMPARE_FUNC(3) 199COMPARE_FUNC(4) 200COMPARE_FUNC(5) 201COMPARE_FUNC(6) 202 203int (*(compare[7]))( const void *a, const void *b ) = 204{ 205 compare_axis_0, 206 compare_axis_1, 207 compare_axis_2, 208 compare_axis_3, 209 compare_axis_4, 210 compare_axis_5, 211 compare_axis_6, 212}; 213 214 215#define VEC_ELT(f, s, i) (float *)(((char *)f) + s * i) 216 217static int sort_axis( int axis, 218 int vec_size, 219 int vec_stride, 220 struct data_idx *indices, 221 int start, 222 int finish, 223 float *out, 224 int uniq, 225 const float fudge ) 226{ 227 int i; 228 229 if (finish-start > 2) 230 { 231 qsort( indices+start, finish-start, sizeof(*indices), compare[axis] ); 232 } 233 else if (indices[start].data[axis] > indices[start+1].data[axis]) 234 { 235 struct data_idx tmp = indices[start]; 236 indices[start] = indices[start+1]; 237 indices[start+1] = tmp; 238 } 239 240 if (axis == vec_size-1) { 241 for (i = start ; i < finish ; ) { 242 float max = indices[i].data[axis] + fudge; 243 float *dest = VEC_ELT(out, vec_stride, uniq); 244 int j; 245 246 for (j = 0 ; j < vec_size ; j++) 247 dest[j] = indices[i].data[j]; 248 249 for ( ; i < finish && max >= indices[i].data[axis]; i++) 250 indices[i].uniq_idx = uniq; 251 252 uniq++; 253 } 254 } else { 255 for (i = start ; i < finish ; ) { 256 int j = i + 1; 257 float max = indices[i].data[axis] + fudge; 258 while (j < finish && max >= indices[j].data[axis]) j++; 259 if (j == i+1) { 260 float *dest = VEC_ELT(out, vec_stride, uniq); 261 int k; 262 263 indices[i].uniq_idx = uniq; 264 265 for (k = 0 ; k < vec_size ; k++) 266 dest[k] = indices[i].data[k]; 267 268 uniq++; 269 } else { 270 uniq = sort_axis( axis+1, vec_size, vec_stride, 271 indices, i, j, out, uniq, fudge ); 272 } 273 i = j; 274 } 275 } 276 277 return uniq; 278} 279 280 281static void extract_indices1( const struct data_idx *in, unsigned int *out, 282 int n ) 283{ 284 int i; 285 for ( i = 0 ; i < n ; i++ ) { 286 out[in[i].idx] = in[i].uniq_idx; 287 } 288} 289 290 291static void compactify_arrays(void) 292{ 293 int i; 294 struct data_idx *ind; 295 296 ind = (struct data_idx *) malloc( sizeof(struct data_idx) * numverts ); 297 298 for (i = 0 ; i < numverts ; i++) { 299 ind[i].idx = i; 300 ind[i].data = data[i]; 301 } 302 303 numuniq = sort_axis(0, 304 sizeof(compressed_data[0])/sizeof(float), 305 sizeof(compressed_data[0]), 306 ind, 307 0, 308 numverts, 309 (float *)compressed_data, 310 0, 311 1e-6); 312 313 printf("Nr unique vertex/normal pairs: %d\n", numuniq); 314 315 extract_indices1( ind, indices, numverts ); 316 free( ind ); 317} 318 319static void expand_arrays(void) 320{ 321 int i; 322 int parity = 0; 323 for (i = 2 ; i < numverts ; i++, parity ^= 1) { 324 int v0 = i-2+parity; 325 int v1 = i-1-parity; 326 int v2 = i; 327 memcpy( expanded_data[(i-2)*3+0], data[v0], sizeof(data[0]) ); 328 memcpy( expanded_data[(i-2)*3+1], data[v1], sizeof(data[0]) ); 329 memcpy( expanded_data[(i-2)*3+2], data[v2], sizeof(data[0]) ); 330 } 331} 332 333static float myrand( float max ) 334{ 335 return max*rand()/(RAND_MAX+1.0); 336} 337 338 339static void make_tri_indices( void ) 340{ 341 unsigned int *v = tri_indices; 342 unsigned int parity = 0; 343 int i, j; 344 345 for (j=2;j<numverts;j++,parity^=1) { 346 if (parity) { 347 *v++ = indices[j-1]; 348 *v++ = indices[j-2]; 349 *v++ = indices[j]; 350 } else { 351 *v++ = indices[j-2]; 352 *v++ = indices[j-1]; 353 *v++ = indices[j]; 354 } 355 } 356 357 num_tri_verts = v - tri_indices; 358 printf("num_tri_verts: %d\n", num_tri_verts); 359 360 for (i = j = 0 ; i < num_tri_verts ; i += 600, j++) { 361 col[j][3] = 1; 362 col[j][2] = myrand(1); 363 col[j][1] = myrand(1); 364 col[j][0] = myrand(1); 365 } 366 367 for (i = 0; i < numverts ; i++) 368 strip_indices[i] = i; 369} 370 371#define MIN(x,y) (x < y) ? x : y 372 373static void draw_surface( unsigned int with_state ) 374{ 375 GLint i, j; 376 377 if (with_state & DISPLAYLIST) { 378 if ((with_state & (RENDER_STYLE_MASK|PRIMITIVE_MASK|MATERIAL_MASK)) != 379 dlist_state) { 380 /* 381 */ 382 fprintf(stderr, "rebuilding displaylist\n"); 383 384 if (dlist_state) 385 glDeleteLists( surf1, 1 ); 386 387 dlist_state = with_state & (RENDER_STYLE_MASK|PRIMITIVE_MASK| 388 MATERIAL_MASK); 389 surf1 = glGenLists(1); 390 glNewList(surf1, GL_COMPILE); 391 draw_surface( dlist_state ); 392 glEndList(); 393 } 394 395 glCallList( surf1 ); 396 return; 397 } 398 399 switch (with_state & (RENDER_STYLE_MASK|PRIMITIVE_MASK)) { 400 401 case (DRAW_ELTS|TRIANGLES): 402 if (with_state & MATERIALS) { 403 for (j = i = 0 ; i < num_tri_verts ; i += 600, j++) { 404 GLuint nr = MIN(num_tri_verts-i, 600); 405 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]); 406 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]); 407 glDrawElements( GL_TRIANGLES, nr, GL_UNSIGNED_INT, tri_indices+i ); 408 } 409 } else { 410 glDrawElements( GL_TRIANGLES, num_tri_verts, GL_UNSIGNED_INT, 411 tri_indices ); 412 } 413 break; 414 415 case (DRAW_ARRAYS|TRIANGLES): 416 glDrawArrays( GL_TRIANGLES, 0, (numverts-2)*3 ); 417 break; 418 419 case (ARRAY_ELT|TRIANGLES): 420 if (with_state & MATERIALS) { 421 for (j = i = 0 ; i < num_tri_verts ; i += 600, j++) { 422 GLuint nr = MIN(num_tri_verts-i, 600); 423 GLuint k; 424 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]); 425 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]); 426 glBegin( GL_TRIANGLES ); 427 for (k = 0 ; k < nr ; k++) 428 glArrayElement( tri_indices[i+k] ); 429 glEnd(); 430 } 431 } else { 432 glBegin( GL_TRIANGLES ); 433 for (i = 0 ; i < num_tri_verts ; i++) 434 glArrayElement( tri_indices[i] ); 435 436 glEnd(); 437 } 438 break; 439 440 441 /* Uses the original arrays (including duplicate elements): 442 */ 443 case (DRAW_ARRAYS|STRIPS): 444 glDrawArrays( GL_TRIANGLE_STRIP, 0, numverts ); 445 break; 446 case (DRAW_ELTS|STRIPS): 447 glDrawElements( GL_TRIANGLE_STRIP, numverts, 448 GL_UNSIGNED_INT, strip_indices ); 449 break; 450 451 /* Uses the original arrays (including duplicate elements): 452 */ 453 case (ARRAY_ELT|STRIPS): 454 glBegin( GL_TRIANGLE_STRIP ); 455 for (i = 0 ; i < numverts ; i++) 456 glArrayElement( i ); 457 glEnd(); 458 break; 459 460 case (DRAW_ARRAYS|POINTS): 461 glDrawArrays( GL_POINTS, 0, numuniq ); 462 break; 463 case (DRAW_ELTS|POINTS): 464 /* can use numuniq with strip_indices as strip_indices[i] == i. 465 */ 466 glDrawElements( GL_POINTS, numuniq, 467 GL_UNSIGNED_INT, strip_indices ); 468 break; 469 case (ARRAY_ELT|POINTS): 470 /* just emit each unique element once: 471 */ 472 glBegin( GL_POINTS ); 473 for (i = 0 ; i < numuniq ; i++) 474 glArrayElement( i ); 475 glEnd(); 476 break; 477 478 case (GLVERTEX|TRIANGLES): 479 if (with_state & MATERIALS) { 480 for (j = i = 0 ; i < num_tri_verts ; i += 600, j++) { 481 GLuint nr = MIN(num_tri_verts-i, 600); 482 GLuint k; 483 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]); 484 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]); 485 glBegin( GL_TRIANGLES ); 486 for (k = 0 ; k < nr ; k++) { 487 glNormal3fv( &compressed_data[tri_indices[i+k]][3] ); 488 glVertex3fv( &compressed_data[tri_indices[i+k]][0] ); 489 } 490 glEnd(); 491 } 492 } else { 493 glBegin( GL_TRIANGLES ); 494 for (i = 0 ; i < num_tri_verts ; i++) { 495 glNormal3fv( &compressed_data[tri_indices[i]][3] ); 496 glVertex3fv( &compressed_data[tri_indices[i]][0] ); 497 } 498 glEnd(); 499 } 500 break; 501 502 case (GLVERTEX|POINTS): 503 /* Renders all points, but not in strip order... Shouldn't be a 504 * problem, but people may be confused as to why points are so 505 * much faster in this demo... And why cva doesn't help them... 506 */ 507 glBegin( GL_POINTS ); 508 for ( i = 0 ; i < numuniq ; i++ ) { 509 glNormal3fv( &compressed_data[i][3] ); 510 glVertex3fv( &compressed_data[i][0] ); 511 } 512 glEnd(); 513 break; 514 515 case (GLVERTEX|STRIPS): 516 if (with_state & MATERIALS) { 517 glBegin( GL_TRIANGLE_STRIP ); 518 for (i=0;i<numverts;i++) { 519 if (i % 600 == 0 && i != 0) { 520 unsigned j = i / 600; 521 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]); 522 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]); 523 } 524 glNormal3fv( &data[i][3] ); 525 glVertex3fv( &data[i][0] ); 526 } 527 glEnd(); 528 } 529 else { 530 glBegin( GL_TRIANGLE_STRIP ); 531 for (i=0;i<numverts;i++) { 532 glNormal3fv( &data[i][3] ); 533 glVertex3fv( &data[i][0] ); 534 } 535 glEnd(); 536 } 537 break; 538 539 default: 540 fprintf(stderr, "unimplemented mode %x...\n", 541 (with_state & (RENDER_STYLE_MASK|PRIMITIVE_MASK))); 542 break; 543 } 544} 545 546 547 548static void Display(void) 549{ 550 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 551 draw_surface( state ); 552 glFlush(); 553 if (doubleBuffer) glutSwapBuffers(); 554} 555 556 557/* KW: only do this when necessary, so CVA can re-use results. 558 */ 559static void set_matrix( void ) 560{ 561 glMatrixMode(GL_MODELVIEW); 562 glLoadIdentity(); 563 glTranslatef( 0.0, 0.0, dist ); 564 glRotatef( yrot, 0.0, 1.0, 0.0 ); 565 glRotatef( xrot, 1.0, 0.0, 0.0 ); 566} 567 568static void Benchmark( float xdiff, float ydiff ) 569{ 570 int startTime, endTime; 571 int draws; 572 double seconds, fps, triPerSecond; 573 574 printf("Benchmarking...\n"); 575 576 draws = 0; 577 startTime = glutGet(GLUT_ELAPSED_TIME); 578 xrot = 0.0; 579 do { 580 xrot += xdiff; 581 yrot += ydiff; 582 set_matrix(); 583 Display(); 584 draws++; 585 endTime = glutGet(GLUT_ELAPSED_TIME); 586 } while (endTime - startTime < 5000); /* 5 seconds */ 587 588 /* Results */ 589 seconds = (double) (endTime - startTime) / 1000.0; 590 triPerSecond = (numverts - 2) * draws / seconds; 591 fps = draws / seconds; 592 printf("Result: triangles/sec: %g fps: %g\n", triPerSecond, fps); 593} 594 595 596static void InitMaterials(void) 597{ 598 static float ambient[] = {0.1, 0.1, 0.1, 1.0}; 599 static float diffuse[] = {0.5, 1.0, 1.0, 1.0}; 600 static float position0[] = {0.0, 0.0, 20.0, 0.0}; 601 static float position1[] = {0.0, 0.0, -20.0, 0.0}; 602 static float front_mat_shininess[] = {60.0}; 603 static float front_mat_specular[] = {0.2, 0.2, 0.2, 1.0}; 604 static float front_mat_diffuse[] = {0.5, 0.28, 0.38, 1.0}; 605 /* 606 static float back_mat_shininess[] = {60.0}; 607 static float back_mat_specular[] = {0.5, 0.5, 0.2, 1.0}; 608 static float back_mat_diffuse[] = {1.0, 1.0, 0.2, 1.0}; 609 */ 610 static float lmodel_ambient[] = {1.0, 1.0, 1.0, 1.0}; 611 static float lmodel_twoside[] = {GL_FALSE}; 612 613 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); 614 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); 615 glLightfv(GL_LIGHT0, GL_POSITION, position0); 616 glEnable(GL_LIGHT0); 617 618 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); 619 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); 620 glLightfv(GL_LIGHT1, GL_POSITION, position1); 621 glEnable(GL_LIGHT1); 622 623 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); 624 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside); 625 626 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_mat_shininess); 627 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_mat_specular); 628 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, front_mat_diffuse); 629 630 glPolygonStipple (halftone); 631} 632 633 634 635#define UPDATE(o,n,mask) (o&=~mask, o|=n&mask) 636#define CHANGED(o,n,mask) ((n&mask) && (n&mask) != (o&mask) ) 637 638static void ModeMenu(int m) 639{ 640 m &= allowed; 641 642 if (!m) return; 643 644 if (m==QUIT) 645 exit(0); 646 647 if (m==GLINFO) { 648 printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION)); 649 printf("GL_EXTENSIONS: %s\n", (char *) glGetString(GL_EXTENSIONS)); 650 printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER)); 651 return; 652 } 653 654 if (CHANGED(state, m, FILTER_MASK)) { 655 UPDATE(state, m, FILTER_MASK); 656 if (m & LINEAR_FILTER) { 657 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 658 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 659 } else { 660 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 661 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 662 } 663 } 664 665 if (CHANGED(state, m, LIGHT_MASK)) { 666 UPDATE(state, m, LIGHT_MASK); 667 if (m & LIT) { 668 glEnable(GL_LIGHTING); 669 glDisable(GL_TEXTURE_GEN_S); 670 glDisable(GL_TEXTURE_GEN_T); 671 glDisable(GL_TEXTURE_2D); 672 } 673 else if (m & UNLIT) { 674 glDisable(GL_LIGHTING); 675 glDisable(GL_TEXTURE_GEN_S); 676 glDisable(GL_TEXTURE_GEN_T); 677 glDisable(GL_TEXTURE_2D); 678 } 679 else if (m & REFLECT) { 680 glDisable(GL_LIGHTING); 681 glEnable(GL_TEXTURE_GEN_S); 682 glEnable(GL_TEXTURE_GEN_T); 683 glEnable(GL_TEXTURE_2D); 684 } 685 } 686 687 if (CHANGED(state, m, SHADE_MASK)) { 688 UPDATE(state, m, SHADE_MASK); 689 if (m & SHADE_SMOOTH) 690 glShadeModel(GL_SMOOTH); 691 else 692 glShadeModel(GL_FLAT); 693 } 694 695 696 if (CHANGED(state, m, CLIP_MASK)) { 697 UPDATE(state, m, CLIP_MASK); 698 if (m & USER_CLIP) { 699 glEnable(GL_CLIP_PLANE0); 700 } else { 701 glDisable(GL_CLIP_PLANE0); 702 } 703 } 704 705 if (CHANGED(state, m, FOG_MASK)) { 706 UPDATE(state, m, FOG_MASK); 707 if (m & FOG) { 708 glEnable(GL_FOG); 709 } 710 else { 711 glDisable(GL_FOG); 712 } 713 } 714 715 if (CHANGED(state, m, STIPPLE_MASK)) { 716 UPDATE(state, m, STIPPLE_MASK); 717 if (m & STIPPLE) { 718 glEnable(GL_POLYGON_STIPPLE); 719 } 720 else { 721 glDisable(GL_POLYGON_STIPPLE); 722 } 723 } 724 725 if (CHANGED(state, m, POLYGON_MASK)) { 726 UPDATE(state, m, POLYGON_MASK); 727 if (m & POLYGON_FILL) { 728 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 729 } 730 else if (m & POLYGON_LINE) { 731 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 732 } 733 else { 734 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); 735 } 736 } 737 738 if (CHANGED(state, m, (LOCK_MASK|RENDER_STYLE_MASK|PRIMITIVE_MASK))) 739 { 740 if (m & (PRIMITIVE_MASK)) { 741 UPDATE(state, m, (PRIMITIVE_MASK)); 742 } 743 744 if (m & (RENDER_STYLE_MASK)) { 745 UPDATE(state, m, (RENDER_STYLE_MASK)); 746 } 747 748 if (m & LOCK_MASK) { 749 UPDATE(state, m, (LOCK_MASK)); 750 } 751 752 753 print_flags("primitive", state & PRIMITIVE_MASK); 754 print_flags("render style", state & RENDER_STYLE_MASK); 755 756 if ((state & PRIMITIVE_MASK) != STRIPS && 757 ((state & RENDER_STYLE_MASK) == DRAW_ELTS || 758 (state & RENDER_STYLE_MASK) == ARRAY_ELT || 759 (state & PRIMITIVE_MASK) == POINTS)) 760 { 761 fprintf(stderr, "enabling small arrays\n"); 762 /* Rendering any primitive with draw-element/array-element 763 * --> Can't do strips here as ordering has been lost in 764 * compaction process... 765 */ 766 glVertexPointer( 3, GL_FLOAT, sizeof(data[0]), compressed_data ); 767 glNormalPointer( GL_FLOAT, sizeof(data[0]), &compressed_data[0][3] ); 768#ifdef GL_EXT_compiled_vertex_array 769 if (allowed & LOCKED) { 770 if (state & LOCKED) { 771 glLockArraysEXT( 0, numuniq ); 772 } else { 773 glUnlockArraysEXT(); 774 } 775 } 776#endif 777 } 778 else if ((state & PRIMITIVE_MASK) == TRIANGLES && 779 (state & RENDER_STYLE_MASK) == DRAW_ARRAYS) { 780 fprintf(stderr, "enabling big arrays\n"); 781 /* Only get here for TRIANGLES and drawarrays 782 */ 783 glVertexPointer( 3, GL_FLOAT, sizeof(data[0]), expanded_data ); 784 glNormalPointer( GL_FLOAT, sizeof(data[0]), &expanded_data[0][3] ); 785 786#ifdef GL_EXT_compiled_vertex_array 787 if (allowed & LOCKED) { 788 if (state & LOCKED) { 789 glLockArraysEXT( 0, (numverts-2)*3 ); 790 } else { 791 glUnlockArraysEXT(); 792 } 793 } 794#endif 795 } 796 else { 797 fprintf(stderr, "enabling normal arrays\n"); 798 glVertexPointer( 3, GL_FLOAT, sizeof(data[0]), data ); 799 glNormalPointer( GL_FLOAT, sizeof(data[0]), &data[0][3] ); 800#ifdef GL_EXT_compiled_vertex_array 801 if (allowed & LOCKED) { 802 if (state & LOCKED) { 803 glLockArraysEXT( 0, numverts ); 804 } else { 805 glUnlockArraysEXT(); 806 } 807 } 808#endif 809 } 810 811 } 812 813 814 if (m & DLIST_MASK) { 815 UPDATE(state, m, DLIST_MASK); 816 } 817 818 if (m & MATERIAL_MASK) { 819 UPDATE(state, m, MATERIAL_MASK); 820 } 821 822 print_flags("new flags", state); 823 824 glutPostRedisplay(); 825} 826 827 828 829static void Init(int argc, char *argv[]) 830{ 831 GLfloat fogColor[4] = {0.5,1.0,0.5,1.0}; 832 833 xrot = 0; 834 yrot = 0; 835 dist = -6; 836 plane[0] = 1.0; 837 plane[1] = 0.0; 838 plane[2] = -1.0; 839 plane[3] = 0.0; 840 841 glClearColor(0.0, 0.0, 1.0, 0.0); 842 glEnable( GL_DEPTH_TEST ); 843 glEnableClientState( GL_VERTEX_ARRAY ); 844 glEnableClientState( GL_NORMAL_ARRAY ); 845 846 glMatrixMode(GL_PROJECTION); 847 glLoadIdentity(); 848 glFrustum( -1.0, 1.0, -1.0, 1.0, 5, 25 ); 849 850 glMatrixMode(GL_MODELVIEW); 851 glLoadIdentity(); 852 glClipPlane(GL_CLIP_PLANE0, plane); 853 854 InitMaterials(); 855 856 set_matrix(); 857 858 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 859 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); 860 861 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); 862 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); 863 864 865 /* Green fog is easy to see */ 866 glFogi(GL_FOG_MODE,GL_EXP2); 867 glFogfv(GL_FOG_COLOR,fogColor); 868 glFogf(GL_FOG_DENSITY,0.15); 869 glHint(GL_FOG_HINT,GL_DONT_CARE); 870 871 { 872 static int firsttime = 1; 873 if (firsttime) { 874 firsttime = 0; 875 compactify_arrays(); 876 expand_arrays(); 877 make_tri_indices(); 878 879 if (!LoadRGBMipmaps(TEXTURE_FILE, GL_RGB)) { 880 printf("Error: couldn't load texture image\n"); 881 exit(1); 882 } 883 } 884 } 885 886 ModeMenu(SHADE_SMOOTH| 887 LIT| 888 POINT_FILTER| 889 NO_USER_CLIP| 890 NO_MATERIALS| 891 NO_FOG| 892 NO_STIPPLE| 893 IMMEDIATE| 894 STRIPS| 895 UNLOCKED| 896 GLVERTEX); 897 898 if (PrintInfo) { 899 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); 900 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); 901 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); 902 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); 903 } 904} 905 906 907 908static void Reshape(int width, int height) 909{ 910 glViewport(0, 0, (GLint)width, (GLint)height); 911} 912 913 914 915static void Key( unsigned char key, int x, int y ) 916{ 917 (void) x; 918 (void) y; 919 switch (key) { 920 case 27: 921 exit(0); 922 case 'f': 923 ModeMenu((state ^ FOG_MASK) & FOG_MASK); 924 break; 925 case 's': 926 ModeMenu((state ^ SHADE_MASK) & SHADE_MASK); 927 break; 928 case 't': 929 ModeMenu((state ^ STIPPLE_MASK) & STIPPLE_MASK); 930 break; 931 case 'l': 932 ModeMenu((state ^ LIGHT_MASK) & (LIT|UNLIT)); 933 break; 934 case 'm': 935 ModeMenu((state ^ MATERIAL_MASK) & MATERIAL_MASK); 936 break; 937 case 'c': 938 ModeMenu((state ^ CLIP_MASK) & CLIP_MASK); 939 break; 940 case 'v': 941 ModeMenu((LOCKED|IMMEDIATE|DRAW_ELTS|TRIANGLES) & allowed); 942 break; 943 case 'V': 944 ModeMenu(UNLOCKED|IMMEDIATE|GLVERTEX|STRIPS); 945 break; 946 case 'b': 947 Benchmark(5.0, 0); 948 break; 949 case 'B': 950 Benchmark(0, 5.0); 951 break; 952 case 'i': 953 dist += .25; 954 set_matrix(); 955 glutPostRedisplay(); 956 break; 957 case 'I': 958 dist -= .25; 959 set_matrix(); 960 glutPostRedisplay(); 961 break; 962 case '-': 963 case '_': 964 plane[3] += 0.5; 965 glMatrixMode(GL_MODELVIEW); 966 glLoadIdentity(); 967 glClipPlane(GL_CLIP_PLANE0, plane); 968 set_matrix(); 969 glutPostRedisplay(); 970 break; 971 case '+': 972 case '=': 973 plane[3] -= 0.5; 974 glMatrixMode(GL_MODELVIEW); 975 glLoadIdentity(); 976 glClipPlane(GL_CLIP_PLANE0, plane); 977 set_matrix(); 978 glutPostRedisplay(); 979 break; 980 case ' ': 981 Init(0,0); 982 break; 983 } 984} 985 986 987static void SpecialKey( int key, int x, int y ) 988{ 989 (void) x; 990 (void) y; 991 switch (key) { 992 case GLUT_KEY_LEFT: 993 yrot -= 15.0; 994 break; 995 case GLUT_KEY_RIGHT: 996 yrot += 15.0; 997 break; 998 case GLUT_KEY_UP: 999 xrot += 15.0; 1000 break; 1001 case GLUT_KEY_DOWN: 1002 xrot -= 15.0; 1003 break; 1004 default: 1005 return; 1006 } 1007 set_matrix(); 1008 glutPostRedisplay(); 1009} 1010 1011 1012 1013static GLint Args(int argc, char **argv) 1014{ 1015 GLint i; 1016 GLint mode = 0; 1017 1018 for (i = 1; i < argc; i++) { 1019 if (strcmp(argv[i], "-sb") == 0) { 1020 doubleBuffer = GL_FALSE; 1021 } 1022 else if (strcmp(argv[i], "-db") == 0) { 1023 doubleBuffer = GL_TRUE; 1024 } 1025 else if (strcmp(argv[i], "-info") == 0) { 1026 PrintInfo = GL_TRUE; 1027 } 1028 else if (strcmp(argv[i], "-10") == 0) { 1029 maxverts = 10; 1030 } 1031 else if (strcmp(argv[i], "-100") == 0) { 1032 maxverts = 100; 1033 } 1034 else if (strcmp(argv[i], "-1000") == 0) { 1035 maxverts = 1000; 1036 } 1037 else { 1038 printf("%s (Bad option).\n", argv[i]); 1039 return QUIT; 1040 } 1041 } 1042 1043 return mode; 1044} 1045 1046int main(int argc, char **argv) 1047{ 1048 GLenum type; 1049 1050 GLuint arg_mode = Args(argc, argv); 1051 1052 if (arg_mode & QUIT) 1053 exit(0); 1054 1055 read_surface(DEMOS_DATA_DIR "isosurf.dat"); 1056 1057 glutInitWindowSize(400, 400); 1058 glutInit( &argc, argv); 1059 1060 type = GLUT_DEPTH; 1061 type |= GLUT_RGB; 1062 type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE; 1063 glutInitDisplayMode(type); 1064 1065 if (glutCreateWindow("Isosurface") <= 0) { 1066 exit(0); 1067 } 1068 1069 glewInit(); 1070 1071 /* Make sure server supports vertex arrays */ 1072 if (!GLEW_VERSION_1_1) 1073 { 1074 printf("Vertex arrays not supported by this renderer\n"); 1075 allowed &= ~(LOCKED|DRAW_ARRAYS|DRAW_ELTS|ARRAY_ELT); 1076 } 1077 else if (!GLEW_EXT_compiled_vertex_array) 1078 { 1079 printf("Compiled vertex arrays not supported by this renderer\n"); 1080 allowed &= ~LOCKED; 1081 } 1082 1083 Init(argc, argv); 1084 ModeMenu(arg_mode); 1085 1086 glutCreateMenu(ModeMenu); 1087 glutAddMenuEntry("GL info", GLINFO); 1088 glutAddMenuEntry("", 0); 1089 glutAddMenuEntry("Lit", LIT); 1090 glutAddMenuEntry("Unlit", UNLIT); 1091 glutAddMenuEntry("Reflect", REFLECT); 1092 glutAddMenuEntry("", 0); 1093 glutAddMenuEntry("Smooth", SHADE_SMOOTH); 1094 glutAddMenuEntry("Flat", SHADE_FLAT); 1095 glutAddMenuEntry("", 0); 1096 glutAddMenuEntry("Fog", FOG); 1097 glutAddMenuEntry("No Fog", NO_FOG); 1098 glutAddMenuEntry("", 0); 1099 glutAddMenuEntry("Stipple", STIPPLE); 1100 glutAddMenuEntry("No Stipple", NO_STIPPLE); 1101 glutAddMenuEntry("", 0); 1102 glutAddMenuEntry("Polygon Mode Fill", POLYGON_FILL); 1103 glutAddMenuEntry("Polygon Mode Line", POLYGON_LINE); 1104 glutAddMenuEntry("Polygon Mode Points", POLYGON_POINT); 1105 glutAddMenuEntry("", 0); 1106 glutAddMenuEntry("Point Filtered", POINT_FILTER); 1107 glutAddMenuEntry("Linear Filtered", LINEAR_FILTER); 1108 glutAddMenuEntry("", 0); 1109 glutAddMenuEntry("GL_TRIANGLES", TRIANGLES); 1110 glutAddMenuEntry("GL_TRIANGLE_STRIPS", STRIPS); 1111 glutAddMenuEntry("GL_POINTS", POINTS); 1112 glutAddMenuEntry("", 0); 1113 glutAddMenuEntry("Displaylist", DISPLAYLIST); 1114 glutAddMenuEntry("Immediate", IMMEDIATE); 1115 glutAddMenuEntry("", 0); 1116 if (allowed & LOCKED) { 1117 glutAddMenuEntry("Locked Arrays (CVA)", LOCKED); 1118 glutAddMenuEntry("Unlocked Arrays", UNLOCKED); 1119 glutAddMenuEntry("", 0); 1120 } 1121 glutAddMenuEntry("glVertex", GLVERTEX); 1122 if (allowed & DRAW_ARRAYS) { 1123 glutAddMenuEntry("glDrawElements", DRAW_ELTS); 1124 glutAddMenuEntry("glDrawArrays", DRAW_ARRAYS); 1125 glutAddMenuEntry("glArrayElement", ARRAY_ELT); 1126 } 1127 glutAddMenuEntry("", 0); 1128 glutAddMenuEntry("Quit", QUIT); 1129 glutAttachMenu(GLUT_RIGHT_BUTTON); 1130 1131 glutReshapeFunc(Reshape); 1132 glutKeyboardFunc(Key); 1133 glutSpecialFunc(SpecialKey); 1134 glutDisplayFunc(Display); 1135 1136 glutMainLoop(); 1137 return 0; 1138} 1139