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 10KB

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