demos: add missing binaries to .gitignore
[mesa-demos.git] / src / tests / debugger.c
blob707e7700385ee3b3fd5db9b8a87725218fa3da4b
1 /*
2 * Test the GL_MESA_program_debug extension
3 */
6 #include <assert.h>
7 #include <ctype.h>
8 #include <string.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <math.h>
12 #include <GL/glew.h>
13 #include "glut_wrap.h"
17 * Print the string with line numbers
19 static void list_program(const GLubyte *string, GLsizei len)
21 const char *c = (const char *) string;
22 int i, line = 1, printNumber = 1;
24 for (i = 0; i < len; i++) {
25 if (printNumber) {
26 printf("%3d ", line);
27 printNumber = 0;
29 if (*c == '\n') {
30 line++;
31 printNumber = 1;
33 putchar(*c);
34 c++;
36 putchar('\n');
41 * Return the line number and column number that corresponds to the
42 * given program position. Also return a null-terminated copy of that
43 * line of the program string.
45 static const GLubyte *
46 find_line_column(const GLubyte *string, const GLubyte *pos,
47 GLint *line, GLint *col)
49 const GLubyte *lineStart = string;
50 const GLubyte *p = string;
51 GLubyte *s;
52 int len;
54 *line = 1;
56 while (p != pos) {
57 if (*p == (GLubyte) '\n') {
58 (*line)++;
59 lineStart = p + 1;
61 p++;
64 *col = (pos - lineStart) + 1;
66 /* return copy of this line */
67 while (*p != 0 && *p != '\n')
68 p++;
69 len = p - lineStart;
70 s = (GLubyte *) malloc(len + 1);
71 memcpy(s, lineStart, len);
72 s[len] = 0;
74 return s;
78 #define ARB_VERTEX_PROGRAM 1
79 #define ARB_FRAGMENT_PROGRAM 2
80 #define NV_VERTEX_PROGRAM 3
81 #define NV_FRAGMENT_PROGRAM 4
85 struct breakpoint {
86 enum {PIXEL, LINE} type;
87 int x, y;
88 int line;
89 GLboolean enabled;
92 #define MAX_BREAKPOINTS 100
93 static struct breakpoint Breakpoints[MAX_BREAKPOINTS];
94 static int NumBreakpoints = 0;
99 * Interactive debugger
101 static void Debugger2(GLenum target, GLvoid *data)
103 static GLuint skipCount = 0;
104 const GLubyte *ln;
105 GLint pos = 0, line, column;
106 GLint id;
107 int progType;
108 GLint len;
109 GLubyte *program;
110 GLboolean stop;
111 int i;
113 /* Sigh, GL_VERTEX_PROGRAM_ARB == GL_VERTEX_PROGRAM_NV so it's a bit
114 * hard to distinguish between them.
116 if (target == GL_FRAGMENT_PROGRAM_ARB)
117 progType = ARB_FRAGMENT_PROGRAM;
118 else if (target == GL_FRAGMENT_PROGRAM_NV)
119 progType = NV_FRAGMENT_PROGRAM;
120 else
121 progType = NV_VERTEX_PROGRAM;
123 /* Until we hit zero, continue rendering */
124 if (skipCount > 0) {
125 skipCount--;
126 return;
129 /* Get id of the program and current position */
130 switch (progType) {
131 case ARB_FRAGMENT_PROGRAM:
132 glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_BINDING_ARB, &id);
133 glGetIntegerv(GL_FRAGMENT_PROGRAM_POSITION_MESA, &pos);
134 break;
135 case NV_FRAGMENT_PROGRAM:
136 glGetIntegerv(GL_FRAGMENT_PROGRAM_BINDING_NV, &id);
137 glGetIntegerv(GL_FRAGMENT_PROGRAM_POSITION_MESA, &pos);
138 break;
139 case ARB_VERTEX_PROGRAM:
140 glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_BINDING_ARB, &id);
141 glGetIntegerv(GL_VERTEX_PROGRAM_POSITION_MESA, &pos);
142 break;
143 case NV_VERTEX_PROGRAM:
144 glGetIntegerv(GL_VERTEX_PROGRAM_BINDING_NV, &id);
145 glGetIntegerv(GL_VERTEX_PROGRAM_POSITION_MESA, &pos);
146 break;
147 default:
148 abort();
151 /* get program string */
152 if (progType == ARB_VERTEX_PROGRAM ||
153 progType == ARB_FRAGMENT_PROGRAM)
154 glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &len);
155 else
156 glGetProgramivNV(id, GL_PROGRAM_LENGTH_NV, &len);
157 program = malloc(len + 1);
158 if (progType == ARB_VERTEX_PROGRAM ||
159 progType == ARB_FRAGMENT_PROGRAM)
160 glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, program);
161 else
162 glGetProgramStringNV(id, GL_PROGRAM_STRING_NV, program);
165 /* Get current line number, column, line string */
166 ln = find_line_column(program, program + pos, &line, &column);
168 /* test breakpoints */
169 if (NumBreakpoints > 0)
170 stop = GL_FALSE;
171 else
172 stop = GL_TRUE;
173 for (i = 0; i < NumBreakpoints; i++) {
174 if (Breakpoints[i].enabled) {
175 switch (Breakpoints[i].type) {
176 case PIXEL:
177 if (progType == ARB_FRAGMENT_PROGRAM) {
180 else if (progType == NV_FRAGMENT_PROGRAM) {
181 GLfloat pos[4];
182 int px, py;
183 glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
184 6, (GLubyte *) "f[WPOS]", pos);
185 px = (int) pos[0];
186 py = (int) pos[1];
187 printf("%d, %d\n", px, py);
188 if (px == Breakpoints[i].x &&
189 py == Breakpoints[i].y) {
190 printf("Break at pixel (%d, %d)\n", px, py);
191 stop = GL_TRUE;
194 break;
195 case LINE:
196 if (line == Breakpoints[i].line) {
197 /* hit a breakpoint! */
198 printf("Break at line %d\n", line);
199 stop = GL_TRUE;
201 break;
205 if (!stop) {
206 free(program);
207 return;
210 printf("%d: %s\n", line, ln);
212 /* get commands from stdin */
213 while (1) {
214 char command[1000], *cmd;
216 /* print prompt and get command */
217 printf("(%s %d) ", (target == GL_VERTEX_PROGRAM_ARB ? "vert" : "frag"),
218 line);
219 fgets(command, 999, stdin);
221 /* skip leading whitespace */
222 for (cmd = command; cmd[0] == ' '; cmd++)
225 if (!cmd[0])
226 /* nothing (repeat the previous cmd?) */
227 continue;
229 switch (cmd[0]) {
230 case 's':
231 /* skip N instructions */
232 i = atoi(cmd + 2);
233 skipCount = i;
234 printf("Skipping %d instructions\n", i);
235 return;
236 case 'n':
237 /* next */
238 return;
239 case 'c':
240 return;
241 case 'd':
242 /* dump machine state */
243 if (progType == NV_FRAGMENT_PROGRAM) {
244 static const char *inRegs[] = {
245 "f[WPOS]", "f[COL0]", "f[COL1]", "f[FOGC]",
246 "f[TEX0]", "f[TEX1]", "f[TEX2]", "f[TEX3]",
247 NULL
249 static const char *outRegs[] = {
250 "o[COLR]", "o[COLH]", "o[DEPR]", NULL
252 GLfloat v[4];
253 int i;
254 printf("Fragment input attributes:\n");
255 for (i = 0; inRegs[i]; i++) {
256 glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
257 strlen(inRegs[i]),
258 (const GLubyte *) inRegs[i], v);
259 printf(" %s: %g, %g, %g, %g\n", inRegs[i],
260 v[0], v[1], v[2], v[3]);
262 printf("Fragment output attributes:\n");
263 for (i = 0; outRegs[i]; i++) {
264 glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
265 strlen(outRegs[i]),
266 (const GLubyte *) outRegs[i], v);
267 printf(" %s: %g, %g, %g, %g\n", outRegs[i],
268 v[0], v[1], v[2], v[3]);
270 printf("Temporaries:\n");
271 for (i = 0; i < 4; i++) {
272 char temp[100];
273 GLfloat v[4];
274 sprintf(temp, "R%d", i);
275 glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
276 strlen(temp),
277 (const GLubyte *) temp, v);
278 printf(" %s: %g, %g, %g, %g\n", temp, v[0],v[1],v[2],v[3]);
281 else if (progType == NV_VERTEX_PROGRAM) {
282 GLfloat v[4];
283 int i;
284 static const char *inRegs[] = {
285 "v[OPOS]", "v[WGHT]", "v[NRML]", "v[COL0]",
286 "v[COL1]", "v[FOGC]", "v[6]", "v[7]",
287 "v[TEX0]", "v[TEX1]", "v[TEX2]", "v[TEX3]",
288 "v[TEX4]", "v[TEX5]", "v[TEX6]", "v[TEX7]",
289 NULL
291 static const char *outRegs[] = {
292 "o[HPOS]", "o[COL0]", "o[COL1]", "o[BFC0]",
293 "o[BFC1]", "o[FOGC]", "o[PSIZ]",
294 "o[TEX0]", "o[TEX1]", "o[TEX2]", "o[TEX3]",
295 "o[TEX4]", "o[TEX5]", "o[TEX6]", "o[TEX7]",
296 NULL
298 printf("Vertex input attributes:\n");
299 for (i = 0; inRegs[i]; i++) {
300 glGetProgramRegisterfvMESA(GL_VERTEX_PROGRAM_NV,
301 strlen(inRegs[i]),
302 (const GLubyte *) inRegs[i], v);
303 printf(" %s: %g, %g, %g, %g\n", inRegs[i],
304 v[0], v[1], v[2], v[3]);
306 printf("Vertex output attributes:\n");
307 for (i = 0; outRegs[i]; i++) {
308 glGetProgramRegisterfvMESA(GL_VERTEX_PROGRAM_NV,
309 strlen(outRegs[i]),
310 (const GLubyte *) outRegs[i], v);
311 printf(" %s: %g, %g, %g, %g\n", outRegs[i],
312 v[0], v[1], v[2], v[3]);
314 printf("Temporaries:\n");
315 for (i = 0; i < 4; i++) {
316 char temp[100];
317 GLfloat v[4];
318 sprintf(temp, "R%d", i);
319 glGetProgramRegisterfvMESA(GL_VERTEX_PROGRAM_NV,
320 strlen(temp),
321 (const GLubyte *) temp, v);
322 printf(" %s: %g, %g, %g, %g\n", temp, v[0],v[1],v[2],v[3]);
325 break;
326 case 'l':
327 /* list */
328 list_program(program, len);
329 break;
330 case 'p':
331 /* print */
333 GLfloat v[4];
334 char *c;
335 cmd++;
336 while (*cmd == ' ')
337 cmd++;
338 c = cmd;
339 while (*c) {
340 if (*c == '\n' || *c == '\r')
341 *c = 0;
342 else
343 c++;
345 glGetProgramRegisterfvMESA(target, strlen(cmd),
346 (const GLubyte *) cmd, v);
347 if (glGetError() == GL_NO_ERROR)
348 printf("%s = %g, %g, %g, %g\n", cmd, v[0], v[1], v[2], v[3]);
349 else
350 printf("Invalid expression\n");
352 break;
353 case 'b':
354 if (cmd[1] == ' ' && isdigit(cmd[2])) {
355 char *comma = strchr(cmd, ',');
356 if (comma) {
357 /* break at pixel */
358 int x = atoi(cmd + 2);
359 int y = atoi(comma + 1);
360 if (NumBreakpoints < MAX_BREAKPOINTS) {
361 Breakpoints[NumBreakpoints].type = PIXEL;
362 Breakpoints[NumBreakpoints].x = x;
363 Breakpoints[NumBreakpoints].y = y;
364 Breakpoints[NumBreakpoints].enabled = GL_TRUE;
365 NumBreakpoints++;
366 printf("Breakpoint %d: break at pixel (%d, %d)\n",
367 NumBreakpoints, x, y);
370 else {
371 /* break at line */
372 int l = atoi(cmd + 2);
373 if (l && NumBreakpoints < MAX_BREAKPOINTS) {
374 Breakpoints[NumBreakpoints].type = LINE;
375 Breakpoints[NumBreakpoints].line = l;
376 Breakpoints[NumBreakpoints].enabled = GL_TRUE;
377 NumBreakpoints++;
378 printf("Breakpoint %d: break at line %d\n",
379 NumBreakpoints, l);
383 else {
384 /* list breakpoints */
385 printf("Breakpoints:\n");
386 for (i = 0; i < NumBreakpoints; i++) {
387 switch (Breakpoints[i].type) {
388 case LINE:
389 printf(" %d: break at line %d\n",
390 i + 1, Breakpoints[i].line);
391 break;
392 case PIXEL:
393 printf(" %d: break at pixel (%d, %d)\n",
394 i + 1, Breakpoints[i].x, Breakpoints[i].y);
395 break;
399 break;
400 case 'h':
401 /* help */
402 printf("Debugger commands:\n");
403 printf(" b list breakpoints\n");
404 printf(" b N break at line N\n");
405 printf(" b x,y break at pixel x,y\n");
406 printf(" c continue execution\n");
407 printf(" d display register values\n");
408 printf(" h help\n");
409 printf(" l list program\n");
410 printf(" n next instruction\n");
411 printf(" p V print value V\n");
412 printf(" s N skip N instructions\n");
413 break;
414 default:
415 printf("Unknown command: %c\n", cmd[0]);
422 * Print current line, some registers, and continue.
424 static void Debugger(GLenum target, GLvoid *data)
426 GLint pos;
427 const GLubyte *ln;
428 GLint line, column;
429 GLfloat v[4];
431 assert(target == GL_FRAGMENT_PROGRAM_NV);
433 glGetIntegerv(GL_FRAGMENT_PROGRAM_POSITION_MESA, &pos);
435 ln = find_line_column((const GLubyte *) data, (const GLubyte *) data + pos,
436 &line, &column);
437 printf("%d:%d: %s\n", line, column, (char *) ln);
439 glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
440 2, (const GLubyte *) "R0", v);
441 printf(" R0 = %g, %g, %g, %g\n", v[0], v[1], v[2], v[3]);
442 glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
443 7, (const GLubyte *) "f[WPOS]", v);
444 printf(" o[WPOS] = %g, %g, %g, %g\n", v[0], v[1], v[2], v[3]);
445 glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
446 7, (const GLubyte *) "o[COLR]", v);
447 printf(" o[COLR] = %g, %g, %g, %g\n", v[0], v[1], v[2], v[3]);
449 free((void *) ln);
455 /**********************************************************************/
457 static GLfloat Diffuse[4] = { 0.5, 0.5, 1.0, 1.0 };
458 static GLfloat Specular[4] = { 0.8, 0.8, 0.8, 1.0 };
459 static GLfloat LightPos[4] = { 0.0, 10.0, 20.0, 1.0 };
460 static GLfloat Delta = 1.0;
462 static GLuint FragProg;
463 static GLuint VertProg;
464 static GLboolean Anim = GL_TRUE;
465 static GLboolean Wire = GL_FALSE;
466 static GLboolean PixelLight = GL_TRUE;
468 static GLfloat Xrot = 0, Yrot = 0;
471 #define NAMED_PARAMETER4FV(prog, name, v) \
472 glProgramNamedParameter4fvNV(prog, strlen(name), (const GLubyte *) name, v)
475 static void Display( void )
477 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
479 if (PixelLight) {
480 NAMED_PARAMETER4FV(FragProg, "LightPos", LightPos);
481 glEnable(GL_FRAGMENT_PROGRAM_NV);
482 glEnable(GL_VERTEX_PROGRAM_NV);
483 glDisable(GL_LIGHTING);
485 else {
486 glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
487 glDisable(GL_FRAGMENT_PROGRAM_NV);
488 glDisable(GL_VERTEX_PROGRAM_NV);
489 glEnable(GL_LIGHTING);
492 glPushMatrix();
493 glRotatef(Xrot, 1, 0, 0);
494 glRotatef(Yrot, 0, 1, 0);
496 #if 1
497 glutSolidSphere(2.0, 10, 5);
498 #else
500 GLUquadricObj *q = gluNewQuadric();
501 gluQuadricNormals(q, GL_SMOOTH);
502 gluQuadricTexture(q, GL_TRUE);
503 glRotatef(90, 1, 0, 0);
504 glTranslatef(0, 0, -1);
505 gluCylinder(q, 1.0, 1.0, 2.0, 24, 1);
506 gluDeleteQuadric(q);
508 #endif
510 glPopMatrix();
512 glutSwapBuffers();
516 static void Idle(void)
518 LightPos[0] += Delta;
519 if (LightPos[0] > 25.0)
520 Delta = -1.0;
521 else if (LightPos[0] <- 25.0)
522 Delta = 1.0;
523 glutPostRedisplay();
527 static void Reshape( int width, int height )
529 glViewport( 0, 0, width, height );
530 glMatrixMode( GL_PROJECTION );
531 glLoadIdentity();
532 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 );
533 /*glOrtho( -2.0, 2.0, -2.0, 2.0, 5.0, 25.0 );*/
534 glMatrixMode( GL_MODELVIEW );
535 glLoadIdentity();
536 glTranslatef( 0.0, 0.0, -15.0 );
540 static void Key( unsigned char key, int x, int y )
542 (void) x;
543 (void) y;
544 switch (key) {
545 case ' ':
546 Anim = !Anim;
547 if (Anim)
548 glutIdleFunc(Idle);
549 else
550 glutIdleFunc(NULL);
551 break;
552 case 'x':
553 LightPos[0] -= 1.0;
554 break;
555 case 'X':
556 LightPos[0] += 1.0;
557 break;
558 case 'w':
559 Wire = !Wire;
560 if (Wire)
561 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
562 else
563 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
564 break;
565 case 'p':
566 PixelLight = !PixelLight;
567 if (PixelLight) {
568 printf("Per-pixel lighting\n");
570 else {
571 printf("Conventional lighting\n");
573 break;
574 case 27:
575 exit(0);
576 break;
578 glutPostRedisplay();
581 static void SpecialKey( int key, int x, int y )
583 const GLfloat step = 3.0;
584 (void) x;
585 (void) y;
586 switch (key) {
587 case GLUT_KEY_UP:
588 Xrot -= step;
589 break;
590 case GLUT_KEY_DOWN:
591 Xrot += step;
592 break;
593 case GLUT_KEY_LEFT:
594 Yrot -= step;
595 break;
596 case GLUT_KEY_RIGHT:
597 Yrot += step;
598 break;
600 glutPostRedisplay();
604 static void Init( int argc, char *argv[] )
606 static const char *fragProgramText =
607 "!!FP1.0\n"
608 "DECLARE Diffuse; \n"
609 "DECLARE Specular; \n"
610 "DECLARE LightPos; \n"
612 "# Compute normalized LightPos, put it in R0\n"
613 "DP3 R0.x, LightPos, LightPos;\n"
614 "RSQ R0.y, R0.x;\n"
615 "MUL R0, LightPos, R0.y;\n"
617 "# Compute normalized normal, put it in R1\n"
618 "DP3 R1, f[TEX0], f[TEX0]; \n"
619 "RSQ R1.y, R1.x;\n"
620 "MUL R1, f[TEX0], R1.y;\n"
622 "# Compute dot product of light direction and normal vector\n"
623 "DP3 R2, R0, R1;\n"
625 "MUL R3, Diffuse, R2; # diffuse attenuation\n"
627 "POW R4, R2.x, {20.0}.x; # specular exponent\n"
629 "MUL R5, Specular, R4; # specular attenuation\n"
631 "ADD o[COLR], R3, R5; # add diffuse and specular colors\n"
632 "END \n"
635 static const char *vertProgramText =
636 "!!VP1.0\n"
637 "# typical modelview/projection transform\n"
638 "DP4 o[HPOS].x, c[0], v[OPOS] ;\n"
639 "DP4 o[HPOS].y, c[1], v[OPOS] ;\n"
640 "DP4 o[HPOS].z, c[2], v[OPOS] ;\n"
641 "DP4 o[HPOS].w, c[3], v[OPOS] ;\n"
642 "# transform normal by inv transpose of modelview, put in tex0\n"
643 "DP4 o[TEX0].x, c[4], v[NRML] ;\n"
644 "DP4 o[TEX0].y, c[5], v[NRML] ;\n"
645 "DP4 o[TEX0].z, c[6], v[NRML] ;\n"
646 "DP4 o[TEX0].w, c[7], v[NRML] ;\n"
647 "END\n";
650 if (!glutExtensionSupported("GL_NV_vertex_program")) {
651 printf("Sorry, this demo requires GL_NV_vertex_program\n");
652 exit(1);
654 if (!glutExtensionSupported("GL_NV_fragment_program")) {
655 printf("Sorry, this demo requires GL_NV_fragment_program\n");
656 exit(1);
659 glGenProgramsNV(1, &FragProg);
660 assert(FragProg > 0);
661 glGenProgramsNV(1, &VertProg);
662 assert(VertProg > 0);
665 * Fragment program
667 glLoadProgramNV(GL_FRAGMENT_PROGRAM_NV, FragProg,
668 strlen(fragProgramText),
669 (const GLubyte *) fragProgramText);
670 assert(glIsProgramNV(FragProg));
671 glBindProgramNV(GL_FRAGMENT_PROGRAM_NV, FragProg);
673 NAMED_PARAMETER4FV(FragProg, "Diffuse", Diffuse);
674 NAMED_PARAMETER4FV(FragProg, "Specular", Specular);
677 * Vertex program
679 glLoadProgramNV(GL_VERTEX_PROGRAM_NV, VertProg,
680 strlen(vertProgramText),
681 (const GLubyte *) vertProgramText);
682 assert(glIsProgramNV(VertProg));
683 glBindProgramNV(GL_VERTEX_PROGRAM_NV, VertProg);
684 glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 0, GL_MODELVIEW_PROJECTION_NV, GL_IDENTITY_NV);
685 glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 4, GL_MODELVIEW, GL_INVERSE_TRANSPOSE_NV);
688 * Misc init
690 glClearColor(0.3, 0.3, 0.3, 0.0);
691 glEnable(GL_DEPTH_TEST);
692 glEnable(GL_LIGHT0);
693 glEnable(GL_LIGHTING);
694 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Diffuse);
695 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Specular);
696 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.0);
698 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
699 printf("Press p to toggle between per-pixel and per-vertex lighting\n");
701 #ifdef GL_MESA_program_debug
702 if (argc > 1 && strcmp(argv[1], "fragment") == 0) {
703 printf(">> Debugging fragment program\n");
704 glProgramCallbackMESA(GL_FRAGMENT_PROGRAM_ARB, Debugger2,
705 (GLvoid *) fragProgramText);
706 glEnable(GL_FRAGMENT_PROGRAM_CALLBACK_MESA);
708 else {
709 printf(">> Debugging vertex program\n");
710 glProgramCallbackMESA(GL_VERTEX_PROGRAM_ARB, Debugger2,
711 (GLvoid *) fragProgramText);
712 glEnable(GL_VERTEX_PROGRAM_CALLBACK_MESA);
714 #endif
718 int main( int argc, char *argv[] )
720 glutInit( &argc, argv );
721 glutInitWindowPosition( 0, 0 );
722 glutInitWindowSize( 200, 200 );
723 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
724 glutCreateWindow(argv[0]);
725 glewInit();
726 glutReshapeFunc( Reshape );
727 glutKeyboardFunc( Key );
728 glutSpecialFunc( SpecialKey );
729 glutDisplayFunc( Display );
730 if (Anim)
731 glutIdleFunc(Idle);
732 Init(argc, argv);
733 glutMainLoop();
734 return 0;