Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tessdemo.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. /* $Id: tessdemo.c,v 1.3 1999/11/04 04:00:42 gareth Exp $ */
  2. /*
  3. * A demo of the GLU polygon tesselation functions written by Bogdan Sikorski.
  4. * This demo isn't built by the Makefile because it needs GLUT. After you've
  5. * installed GLUT you can try this demo.
  6. * Here's the command for IRIX, for example:
  7. cc -g -ansi -prototypes -fullwarn -float -I../include -DSHM tess_demo.c -L../lib -lglut -lMesaGLU -lMesaGL -lm -lX11 -lXext -lXmu -lfpe -lXext -o tess_demo
  8. */
  9. /*
  10. * Updated for GLU 1.3 tessellation by Gareth Hughes <garethh@bell-labs.com>
  11. */
  12. /*
  13. * $Log: tessdemo.c,v $
  14. * Revision 1.3 1999/11/04 04:00:42 gareth
  15. * Updated demo for new GLU 1.3 tessellation. Added optimized rendering
  16. * by saving the output of the tessellation into display lists.
  17. *
  18. * Revision 1.2 1999/09/19 20:09:00 tanner
  19. *
  20. * lots of autoconf updates
  21. *
  22. * Revision 1.1.1.1 1999/08/19 00:55:40 jtg
  23. * Imported sources
  24. *
  25. * Revision 3.5 1999/03/28 18:24:37 brianp
  26. * minor clean-up
  27. *
  28. * Revision 3.4 1999/02/14 03:37:07 brianp
  29. * fixed callback problem
  30. *
  31. * Revision 3.3 1998/07/26 01:25:26 brianp
  32. * removed include of gl.h and glu.h
  33. *
  34. * Revision 3.2 1998/06/29 02:37:30 brianp
  35. * minor changes for Windows (Ted Jump)
  36. *
  37. * Revision 3.1 1998/06/09 01:53:49 brianp
  38. * main() should return an int
  39. *
  40. * Revision 3.0 1998/02/14 18:42:29 brianp
  41. * initial rev
  42. *
  43. */
  44. #include <GL/glut.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #define MAX_POINTS 256
  49. #define MAX_CONTOURS 32
  50. #define MAX_TRIANGLES 256
  51. #ifndef GLCALLBACK
  52. #ifdef CALLBACK
  53. #define GLCALLBACK CALLBACK
  54. #else
  55. #define GLCALLBACK
  56. #endif
  57. #endif
  58. typedef enum{ QUIT, TESSELATE, CLEAR } menu_entries;
  59. typedef enum{ DEFINE, TESSELATED } mode_type;
  60. static GLsizei width, height;
  61. static GLuint contour_cnt;
  62. static GLuint triangle_cnt;
  63. static mode_type mode;
  64. static int menu;
  65. static GLuint list_start;
  66. static GLfloat edge_color[3];
  67. static struct
  68. {
  69. GLint p[MAX_POINTS][2];
  70. GLuint point_cnt;
  71. } contours[MAX_CONTOURS];
  72. static struct
  73. {
  74. GLsizei no;
  75. GLint p[3][2];
  76. GLclampf color[3][3];
  77. } triangles[MAX_TRIANGLES];
  78. void GLCALLBACK my_error( GLenum err )
  79. {
  80. int len, i;
  81. char const *str;
  82. glColor3f( 0.9, 0.9, 0.9 );
  83. glRasterPos2i( 5, 5 );
  84. str = (const char *) gluErrorString( err );
  85. len = strlen( str );
  86. for ( i = 0 ; i < len ; i++ ) {
  87. glutBitmapCharacter( GLUT_BITMAP_9_BY_15, str[i] );
  88. }
  89. }
  90. void GLCALLBACK begin_callback( GLenum mode )
  91. {
  92. /* Allow multiple triangles to be output inside the begin/end pair. */
  93. triangle_cnt = 0;
  94. triangles[triangle_cnt].no = 0;
  95. }
  96. void GLCALLBACK edge_callback( GLenum flag )
  97. {
  98. /* Persist the edge flag across triangles. */
  99. if ( flag == GL_TRUE )
  100. {
  101. edge_color[0] = 1.0;
  102. edge_color[1] = 1.0;
  103. edge_color[2] = 0.5;
  104. }
  105. else
  106. {
  107. edge_color[0] = 1.0;
  108. edge_color[1] = 0.0;
  109. edge_color[2] = 0.0;
  110. }
  111. }
  112. void GLCALLBACK end_callback()
  113. {
  114. GLint i;
  115. glBegin( GL_LINES );
  116. /* Output the three edges of each triangle as lines colored
  117. according to their edge flag. */
  118. for ( i = 0 ; i < triangle_cnt ; i++ )
  119. {
  120. glColor3f( triangles[i].color[0][0],
  121. triangles[i].color[0][1],
  122. triangles[i].color[0][2] );
  123. glVertex2i( triangles[i].p[0][0], triangles[i].p[0][1] );
  124. glVertex2i( triangles[i].p[1][0], triangles[i].p[1][1] );
  125. glColor3f( triangles[i].color[1][0],
  126. triangles[i].color[1][1],
  127. triangles[i].color[1][2] );
  128. glVertex2i( triangles[i].p[1][0], triangles[i].p[1][1] );
  129. glVertex2i( triangles[i].p[2][0], triangles[i].p[2][1] );
  130. glColor3f( triangles[i].color[2][0],
  131. triangles[i].color[2][1],
  132. triangles[i].color[2][2] );
  133. glVertex2i( triangles[i].p[2][0], triangles[i].p[2][1] );
  134. glVertex2i( triangles[i].p[0][0], triangles[i].p[0][1] );
  135. }
  136. glEnd();
  137. }
  138. void GLCALLBACK vertex_callback( void *data )
  139. {
  140. GLsizei no;
  141. GLint *p;
  142. p = (GLint *) data;
  143. no = triangles[triangle_cnt].no;
  144. triangles[triangle_cnt].p[no][0] = p[0];
  145. triangles[triangle_cnt].p[no][1] = p[1];
  146. triangles[triangle_cnt].color[no][0] = edge_color[0];
  147. triangles[triangle_cnt].color[no][1] = edge_color[1];
  148. triangles[triangle_cnt].color[no][2] = edge_color[2];
  149. /* After every three vertices, initialize the next triangle. */
  150. if ( ++(triangles[triangle_cnt].no) == 3 )
  151. {
  152. triangle_cnt++;
  153. triangles[triangle_cnt].no = 0;
  154. }
  155. }
  156. void set_screen_wh( GLsizei w, GLsizei h )
  157. {
  158. width = w;
  159. height = h;
  160. }
  161. void tesse( void )
  162. {
  163. GLUtesselator *tobj;
  164. GLdouble data[3];
  165. GLuint i, j, point_cnt;
  166. list_start = glGenLists( 2 );
  167. tobj = gluNewTess();
  168. if ( tobj != NULL )
  169. {
  170. gluTessCallback( tobj, GLU_BEGIN, glBegin );
  171. gluTessCallback( tobj, GLU_VERTEX, glVertex2iv );
  172. gluTessCallback( tobj, GLU_END, glEnd );
  173. gluTessCallback( tobj, GLU_ERROR, my_error );
  174. glNewList( list_start, GL_COMPILE );
  175. gluBeginPolygon( tobj );
  176. for ( j = 0 ; j <= contour_cnt ; j++ )
  177. {
  178. point_cnt = contours[j].point_cnt;
  179. gluNextContour( tobj, GLU_UNKNOWN );
  180. for ( i = 0 ; i < point_cnt ; i++ )
  181. {
  182. data[0] = (GLdouble)( contours[j].p[i][0] );
  183. data[1] = (GLdouble)( contours[j].p[i][1] );
  184. data[2] = 0.0;
  185. gluTessVertex( tobj, data, contours[j].p[i] );
  186. }
  187. }
  188. gluEndPolygon( tobj );
  189. glEndList();
  190. gluTessCallback( tobj, GLU_BEGIN, begin_callback );
  191. gluTessCallback( tobj, GLU_VERTEX, vertex_callback );
  192. gluTessCallback( tobj, GLU_END, end_callback );
  193. gluTessCallback( tobj, GLU_EDGE_FLAG, edge_callback );
  194. glNewList( list_start + 1, GL_COMPILE );
  195. gluBeginPolygon( tobj );
  196. for ( j = 0 ; j <= contour_cnt ; j++ )
  197. {
  198. point_cnt = contours[j].point_cnt;
  199. gluNextContour( tobj, GLU_UNKNOWN );
  200. for ( i = 0 ; i < point_cnt ; i++ )
  201. {
  202. data[0] = (GLdouble)( contours[j].p[i][0] );
  203. data[1] = (GLdouble)( contours[j].p[i][1] );
  204. data[2] = 0.0;
  205. gluTessVertex( tobj, data, contours[j].p[i] );
  206. }
  207. }
  208. gluEndPolygon( tobj );
  209. glEndList();
  210. gluDeleteTess( tobj );
  211. glutMouseFunc( NULL );
  212. mode = TESSELATED;
  213. }
  214. }
  215. void left_down( int x1, int y1 )
  216. {
  217. GLint P[2];
  218. GLuint point_cnt;
  219. /* translate GLUT into GL coordinates */
  220. P[0] = x1;
  221. P[1] = height - y1;
  222. point_cnt = contours[contour_cnt].point_cnt;
  223. contours[contour_cnt].p[point_cnt][0] = P[0];
  224. contours[contour_cnt].p[point_cnt][1] = P[1];
  225. glBegin( GL_LINES );
  226. if ( point_cnt )
  227. {
  228. glVertex2iv( contours[contour_cnt].p[point_cnt-1] );
  229. glVertex2iv( P );
  230. }
  231. else
  232. {
  233. glVertex2iv( P );
  234. glVertex2iv( P );
  235. }
  236. glEnd();
  237. glFinish();
  238. contours[contour_cnt].point_cnt++;
  239. }
  240. void middle_down( int x1, int y1 )
  241. {
  242. GLuint point_cnt;
  243. (void) x1;
  244. (void) y1;
  245. point_cnt = contours[contour_cnt].point_cnt;
  246. if ( point_cnt > 2 )
  247. {
  248. glBegin( GL_LINES );
  249. glVertex2iv( contours[contour_cnt].p[0] );
  250. glVertex2iv( contours[contour_cnt].p[point_cnt-1] );
  251. contours[contour_cnt].p[point_cnt][0] = -1;
  252. glEnd();
  253. glFinish();
  254. contour_cnt++;
  255. contours[contour_cnt].point_cnt = 0;
  256. }
  257. }
  258. void mouse_clicked( int button, int state, int x, int y )
  259. {
  260. x -= x%10;
  261. y -= y%10;
  262. switch ( button )
  263. {
  264. case GLUT_LEFT_BUTTON:
  265. if ( state == GLUT_DOWN ) {
  266. left_down( x, y );
  267. }
  268. break;
  269. case GLUT_MIDDLE_BUTTON:
  270. if ( state == GLUT_DOWN ) {
  271. middle_down( x, y );
  272. }
  273. break;
  274. }
  275. }
  276. void display( void )
  277. {
  278. GLuint i,j;
  279. GLuint point_cnt;
  280. glClear( GL_COLOR_BUFFER_BIT );
  281. switch ( mode )
  282. {
  283. case DEFINE:
  284. /* draw grid */
  285. glColor3f( 0.6, 0.5, 0.5 );
  286. glBegin( GL_LINES );
  287. for ( i = 0 ; i < width ; i += 10 )
  288. {
  289. for ( j = 0 ; j < height ; j += 10 )
  290. {
  291. glVertex2i( 0, j );
  292. glVertex2i( width, j );
  293. glVertex2i( i, height );
  294. glVertex2i( i, 0 );
  295. }
  296. }
  297. glColor3f( 1.0, 1.0, 0.0 );
  298. for ( i = 0 ; i <= contour_cnt ; i++ )
  299. {
  300. point_cnt = contours[i].point_cnt;
  301. glBegin( GL_LINES );
  302. switch ( point_cnt )
  303. {
  304. case 0:
  305. break;
  306. case 1:
  307. glVertex2iv( contours[i].p[0] );
  308. glVertex2iv( contours[i].p[0] );
  309. break;
  310. case 2:
  311. glVertex2iv( contours[i].p[0] );
  312. glVertex2iv( contours[i].p[1] );
  313. break;
  314. default:
  315. --point_cnt;
  316. for ( j = 0 ; j < point_cnt ; j++ )
  317. {
  318. glVertex2iv( contours[i].p[j] );
  319. glVertex2iv( contours[i].p[j+1] );
  320. }
  321. if ( contours[i].p[j+1][0] == -1 )
  322. {
  323. glVertex2iv( contours[i].p[0] );
  324. glVertex2iv( contours[i].p[j] );
  325. }
  326. break;
  327. }
  328. glEnd();
  329. }
  330. glFinish();
  331. break;
  332. case TESSELATED:
  333. /* draw triangles */
  334. glColor3f( 0.7, 0.7, 0.0 );
  335. glCallList( list_start );
  336. glLineWidth( 2.0 );
  337. glCallList( list_start + 1 );
  338. glLineWidth( 1.0 );
  339. glFlush();
  340. break;
  341. }
  342. glColor3f( 1.0, 1.0, 0.0 );
  343. }
  344. void clear( void )
  345. {
  346. contour_cnt = 0;
  347. contours[0].point_cnt = 0;
  348. triangle_cnt = 0;
  349. glutMouseFunc( mouse_clicked );
  350. mode = DEFINE;
  351. glDeleteLists( list_start, 2 );
  352. list_start = 0;
  353. }
  354. void quit( void )
  355. {
  356. exit( 0 );
  357. }
  358. void menu_selected( int entry )
  359. {
  360. switch ( entry )
  361. {
  362. case CLEAR:
  363. clear();
  364. break;
  365. case TESSELATE:
  366. tesse();
  367. break;
  368. case QUIT:
  369. quit();
  370. break;
  371. }
  372. glutPostRedisplay();
  373. }
  374. void key_pressed( unsigned char key, int x, int y )
  375. {
  376. (void) x;
  377. (void) y;
  378. switch ( key )
  379. {
  380. case 'c':
  381. case 'C':
  382. clear();
  383. break;
  384. case 't':
  385. case 'T':
  386. tesse();
  387. break;
  388. case 'q':
  389. case 'Q':
  390. quit();
  391. break;
  392. }
  393. glutPostRedisplay();
  394. }
  395. void myinit( void )
  396. {
  397. /* clear background to gray */
  398. glClearColor( 0.4, 0.4, 0.4, 0.0 );
  399. glShadeModel( GL_FLAT );
  400. glPolygonMode( GL_FRONT, GL_FILL );
  401. menu = glutCreateMenu( menu_selected );
  402. glutAddMenuEntry( "clear", CLEAR );
  403. glutAddMenuEntry( "tesselate", TESSELATE );
  404. glutAddMenuEntry( "quit", QUIT );
  405. glutAttachMenu( GLUT_RIGHT_BUTTON );
  406. glutMouseFunc( mouse_clicked );
  407. glutKeyboardFunc( key_pressed );
  408. contour_cnt = 0;
  409. mode = DEFINE;
  410. }
  411. static void reshape( GLsizei w, GLsizei h )
  412. {
  413. glViewport( 0, 0, w, h );
  414. glMatrixMode( GL_PROJECTION );
  415. glLoadIdentity();
  416. glOrtho( 0.0, (GLdouble)w, 0.0, (GLdouble)h, -1.0, 1.0 );
  417. glMatrixMode( GL_MODELVIEW );
  418. glLoadIdentity();
  419. set_screen_wh( w, h );
  420. }
  421. static void usage( void )
  422. {
  423. printf( "Use left mouse button to place vertices.\n" );
  424. printf( "Press middle mouse button when done.\n" );
  425. printf( "Select tesselate from the pop-up menu.\n" );
  426. }
  427. /*
  428. * Main Loop
  429. * Open window with initial window size, title bar,
  430. * RGBA display mode, and handle input events.
  431. */
  432. int main( int argc, char **argv )
  433. {
  434. usage();
  435. glutInit( &argc, argv );
  436. glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB );
  437. glutInitWindowSize( 400, 400 );
  438. glutCreateWindow( argv[0] );
  439. myinit();
  440. glutDisplayFunc( display );
  441. glutReshapeFunc( reshape );
  442. glutMainLoop();
  443. return 0;
  444. }