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