sgiflag.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:12k
源码类别:

GIS编程

开发平台:

Visual C++

  1. /*
  2.  *    sgiflag.c:
  3.  *
  4.  *  This program displays a waving flag with an SGI logo trimmed out of
  5.  *  it.  The flag is a single nurbs surface (bicubic, bezier). It "waves" 
  6.  *  by making it control point oscillate on a sine wave.
  7.  *
  8.  *  The logo is cut from the flag using a combination of piecewise-linear 
  9.  *  and bezier trim curves.
  10.  *
  11.  *                                    Howard Look - December 1990
  12.  *       David Blythe - June 1995
  13.  */
  14. #include <GL/glut.h>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <math.h>
  18. #include "sgiflag.h"
  19. #include "logopoints.h"
  20. /* Some <math.h> files do not define M_PI... */
  21. #ifndef M_PI
  22. #define M_PI 3.14159265358979323846
  23. #endif
  24. /* Knot sequences for cubic bezier surface and trims */
  25. Knot sknots[S_NUMKNOTS] = {0., 0., 0., 0., 1., 1., 1., 1.};
  26. Knot tknots[T_NUMKNOTS] = {0., 0., 0., 0., 1., 1., 1., 1.};
  27. Knot trimknots[S_NUMKNOTS] = {0., 0., 0., 0., 1., 1., 1., 1.};
  28. /* Control points for the flag. The Z values are modified to make it wave */
  29. Point ctlpoints[S_NUMPOINTS][T_NUMPOINTS] = {
  30.     { {0., 3., 0.}, {1., 3., 0.}, {2., 3., 0}, {3., 3., 0.}},
  31.     { {0., 2., 0.}, {1., 2., 0.}, {2., 2., 0}, {3., 2., 0.}},
  32.     { {0., 1., 0.}, {1., 1., 0.}, {2., 1., 0}, {3., 1., 0.}},
  33.     { {0., 0., 0.}, {1., 0., 0.}, {2., 0., 0}, {3., 0., 0.}}
  34. };
  35. /* Trim the whole exterior of the, counter clockwise. Necessary to do
  36.  * internal trimming
  37.  */
  38. TrimCurve *whole;
  39. TrimCurve ccl_path;
  40. TrimPiece ccl_square[] = {
  41.     {
  42.         PWL,
  43.         11,
  44.         {
  45. {0., 0.}, {.25, 0.}, {.5, 0.}, {.75, 0.}, {1., 0.},
  46. {1., 1.}, {.75, 1.}, {.5, 1.}, {.25, 1.}, {0., 1.}, {0., 0.}
  47. }
  48.     }
  49. };
  50. /* Three paths for three parts of the logo */
  51. TrimCurve *path[3];
  52. /* Initial one-third of the logo, centered at origin */
  53. TrimCurve initial_path;
  54. TrimPiece initial_pieces[] = {
  55.         {
  56.             PWL, /* 0 */
  57.             6,
  58.             {{Ax,Ay},{Bx,By},{Cx,Cy},{Dx,Dy},{Ex,Ey},{0.,0.}}
  59.         },
  60.         {
  61.             CURVE, /* 1 */
  62.             4,
  63.             {{0.,0.},{Fx,Fy},{Fx,Fy},{0.,0.}}
  64.         },
  65.         {
  66.             PWL, /* 2 */
  67.             2,
  68.             {{Gx, Gy},{Gx,Gy}}
  69.         },
  70.         {
  71.             CURVE, /* 3 */
  72.             4,
  73.             {{0.,0.},{Gx,Gy},{Gx,Gy},{0.,0.}}
  74.         },
  75.         {
  76.             PWL, /* 4 */
  77.             3,
  78.             {{0., 0.},{Z,Z},{0.,0.}}
  79.         },
  80.         {
  81.             CURVE, /* 5 */
  82.             4,
  83.             {{0.,0.},{-Gx,Gy},{-Gx,Gy},{0.,0.}}
  84.         },
  85.         {
  86.             PWL, /* 6 */
  87.             2,
  88.             {{-Fx, Fy},{-Fx,Fy}}
  89.         },
  90.         {
  91.             CURVE, /* 7 */
  92.             4,
  93.             {{0.,0.},{-Fx,Fy},{-Fx,Fy},{0.,0.}}
  94.         },
  95.         {
  96.             PWL, /* 8 */
  97.             6,
  98.             {{0.,0.},{-Ex,Ey},{-Dx,Dy},{-Cx,Cy},{-Bx,By},{Ax,Ay}}
  99.         }
  100. };
  101. static GLUnurbsObj *nurbsflag;
  102. static GLboolean trimming = GL_TRUE, filled = GL_TRUE, hull = GL_TRUE;
  103. static int mousex = 248, mousey = 259, mstate;
  104. /* Given endpoints of the line a and b, the distance d from point a,
  105.  * returns a new point (in result) that is on that line.
  106.  */
  107. void interp(TrimPoint a, TrimPoint b, GLfloat d, TrimPoint result) {
  108.     GLfloat l;
  109.     l = sqrt((a[0] - b[0])*(a[0] - b[0]) + (a[1] - b[1])*(a[1] - b[1]));
  110.     result[0] = a[0] + (b[0] - a[0])*d/l; 
  111.     result[1] = a[1] + (b[1] - a[1])*d/l; 
  112.     
  113. }
  114. /* Given two trim pieces, coerces the endpoint of the first and the
  115.  * start point of the second to be indentical.
  116.  *
  117.  * The two trims must be of opposite types, PWL or CURVE.
  118.  */
  119. void join_trims(TrimPiece *trim1, TrimPiece *trim2, GLfloat radius) {
  120.     int last;
  121.     TrimPoint result;
  122.     last = trim1->points - 1;
  123.     
  124.     if (trim1->type == PWL)
  125.         interp(trim2->point[1], trim1->point[last - 1], radius, result);
  126.     else /* trim1 is CURVE */
  127.         interp(trim1->point[last-1], trim2->point[0], radius, result);
  128.     trim1->point[last][0] = trim2->point[0][0] = result[0];
  129.     trim1->point[last][1] = trim2->point[0][1] = result[1];
  130. }    
  131. /* Translates each point in the trim piece by tx and ty */
  132. void translate_trim(TrimPiece *trim, GLfloat tx, GLfloat ty) {
  133.     int i;
  134.     for (i=0; i<trim->points; i++) {
  135.         trim->point[i][0] += tx;
  136.         trim->point[i][1] += ty;
  137.     }
  138. }        
  139. /* Scales each point in the trim piece by sx and sy */
  140. void scale_trim(TrimPiece *trim, GLfloat sx, GLfloat sy) {
  141.     int i;
  142.     for (i=0; i<trim->points; i++) {
  143.         trim->point[i][0] *= sx;
  144.         trim->point[i][1] *= sy;
  145.     }
  146. }        
  147. /* Rotates each point in the trim piece by angle radians about the origin */
  148. void rotate_trim(TrimPiece *trim, GLfloat angle) {
  149.     int i;
  150.     GLfloat s,c;
  151.     TrimPoint t;
  152.     s = sin(angle);
  153.     c = cos(angle);
  154.     for (i=0; i<trim->points; i++) {
  155.         t[0] = trim->point[i][0];
  156.         t[1] = trim->point[i][1];
  157.         
  158.         trim->point[i][0] = c*t[0] - s*t[1];
  159.         trim->point[i][1] = s*t[0] + c*t[1];
  160.     }
  161. }        
  162. /* Creates storage space for dst and copies the contents of src into dst */
  163. void copy_path(TrimCurve *src, TrimCurve **dst) {
  164.     int i,j;
  165.     *dst = (TrimCurve *) malloc(sizeof(TrimCurve));
  166.     (*dst)->pieces = src->pieces;
  167.     (*dst)->trim = (TrimPiece *) malloc((src->pieces)*sizeof(TrimPiece));
  168.     for(i=0; i < src->pieces; i++) {
  169.         (*dst)->trim[i].type = src->trim[i].type;
  170.         (*dst)->trim[i].points = src->trim[i].points;
  171.         for (j=0; j < src->trim[i].points; j++) {
  172.             (*dst)->trim[i].point[j][0] = src->trim[i].point[j][0];
  173.             (*dst)->trim[i].point[j][1] = src->trim[i].point[j][1];
  174.         }
  175.     }
  176. }    
  177. /* Initializes the outer whole trim plus the three trimming paths 
  178.  * required to trim the logo.
  179.  */
  180. void init_trims(void) {
  181.     int i;
  182. /* whole outer path, counter clockwise, so NuRB is not trimmed */
  183.     whole = &ccl_path;
  184.     whole->pieces = 1;
  185.     whole->trim = ccl_square;
  186. /* initial third of logo, centered at origin */
  187.     path[0] = &initial_path;
  188.     path[0]->pieces = ELEMENTS(initial_pieces);
  189.     path[0]->trim = initial_pieces;
  190.     for(i=0; i < path[0]->pieces - 1; i++)
  191.         join_trims(&path[0]->trim[i], &path[0]->trim[i+1], LOGO_RADIUS);
  192. /* copy other to other two thirds */
  193.     copy_path(path[0],&path[1]);
  194.     copy_path(path[0],&path[2]);
  195. /* scale and translate first third */
  196.     for (i=0; i<path[0]->pieces; i++) {
  197.         scale_trim(&path[0]->trim[i],0.5,1.0);
  198.         translate_trim(&path[0]->trim[i],0.5,0.52);
  199.     }
  200. /* rotate, scale and translate second third */
  201.     for (i=0; i<path[1]->pieces; i++) {        
  202.         rotate_trim(&path[1]->trim[i],2.0*M_PI/3.0);
  203.         scale_trim(&path[1]->trim[i],0.5,1.0);
  204.         translate_trim(&path[1]->trim[i],0.49,0.5);
  205.     }
  206. /* rotate, scale and translate last third */
  207.     for (i=0; i<path[2]->pieces; i++) {        
  208.         rotate_trim(&path[2]->trim[i],2.0*2.0*M_PI/3.0);
  209.         scale_trim(&path[2]->trim[i],0.5,1.0);
  210.         translate_trim(&path[2]->trim[i],0.51,0.5);
  211.     }
  212. }
  213.     
  214. /* Opens a square window, and initializes the window, interesting devices,
  215.  * viewing volume, material, and lights.
  216.  */
  217. static void
  218. initialize(void) {
  219.     GLfloat mat_diffuse[] = { .8, .1, .8, 1. };
  220.     GLfloat mat_specular[] = { .6, .6, .6, 1. };
  221.     GLfloat mat_ambient[] = { .1, .1, .1, 1. };
  222.     glClearColor(.58, .58, .58, 0.);
  223.     glClearDepth(1.);
  224.     glEnable(GL_DEPTH_TEST);
  225.     glMatrixMode(GL_PROJECTION);
  226.     gluPerspective(60,1.0,1.0,10.0);
  227.     glMatrixMode(GL_MODELVIEW);
  228.     glTranslatef(0., 0., -6.);
  229.     
  230.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
  231.     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
  232.     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
  233.     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 32.0);
  234.     glEnable(GL_LIGHT0);
  235.     glEnable(GL_LIGHTING);
  236.     glEnable(GL_AUTO_NORMAL);
  237.     glEnable(GL_NORMALIZE);
  238.     nurbsflag = gluNewNurbsRenderer();
  239.     gluNurbsProperty(nurbsflag, GLU_SAMPLING_TOLERANCE, 100.0);
  240.     gluNurbsProperty(nurbsflag, GLU_DISPLAY_MODE, GLU_FILL);
  241.     init_trims();
  242. }
  243. /* Draw the nurb, possibly with trimming */
  244. void draw_nurb(GLboolean trimming) {
  245.     static GLfloat angle = 0.0;
  246.     int i,j;
  247. /* wave the flag by rotating Z coords though a sine wave */
  248.     for (i=1; i<4; i++)
  249.         for (j=0; j<4; j++)
  250.             ctlpoints[i][j][2] = sin((GLfloat)i+angle);
  251.     angle += 0.1;
  252.     
  253.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  254.     glPushMatrix();
  255.         glTranslatef(2.5,-1.0,0.0);
  256.         glScalef(1.5,1.0,1.0);
  257.         glRotatef(90,0.,0.,1.);
  258.         glRotatef(mousey/10.,1.,0.,0.);
  259.         glRotatef(mousex/10.,0.,1.,0.);
  260.         
  261. gluBeginSurface(nurbsflag);
  262.             gluNurbsSurface(nurbsflag,S_NUMKNOTS, sknots, T_NUMKNOTS, tknots,
  263.                           3 * T_NUMPOINTS, 3,
  264.                           &ctlpoints[0][0][0], T_ORDER, S_ORDER, GL_MAP2_VERTEX_3);
  265.             if (trimming) {
  266.                 dotrim(whole);
  267.                 dotrim(path[0]);
  268.                 dotrim(path[1]);
  269.                 dotrim(path[2]);
  270.             }
  271.         gluEndSurface(nurbsflag);
  272.         
  273. if (hull) draw_hull(ctlpoints);
  274.     
  275.     glPopMatrix();
  276.     
  277. }
  278. /* Draw the convex hull of the control points */
  279. void draw_hull(Point cpoints[S_NUMPOINTS][T_NUMPOINTS]) {
  280.     int s,t;
  281.     
  282.     glDisable(GL_LIGHTING);
  283.     glColor3f(0.,1.,0.);
  284.     glBegin(GL_LINES);
  285.     for (s=0; s<S_NUMPOINTS; s++)
  286.         for (t=0; t<T_NUMPOINTS-1; t++) {
  287.                 glVertex3fv(cpoints[s][t]);
  288.                 glVertex3fv(cpoints[s][t+1]);
  289.         }
  290.         
  291.     for (t=0; t<T_NUMPOINTS; t++)
  292.         for (s=0; s<S_NUMPOINTS-1; s++) {
  293.                 glVertex3fv(cpoints[s][t]);
  294.                 glVertex3fv(cpoints[s+1][t]);
  295.         }
  296.     glEnd();
  297.     glEnable(GL_LIGHTING);
  298. }
  299. /* Execute a bgn/endtrim pair for the given trim curve structure. */
  300. void dotrim(TrimCurve *trim_curve) {
  301.     int i;
  302.     gluBeginTrim(nurbsflag);
  303.         for (i=0; i<trim_curve->pieces; i++) {
  304.             if (trim_curve->trim[i].type == PWL) {
  305.                     gluPwlCurve(nurbsflag, trim_curve->trim[i].points,
  306.                               &trim_curve->trim[i].point[0][0],
  307.                               2, GLU_MAP1_TRIM_2);
  308.             } else {
  309.                 gluNurbsCurve(nurbsflag, ELEMENTS(trimknots),trimknots,
  310.                             2,&trim_curve->trim[i].point[0][0],
  311.                             trim_curve->trim[i].points, GLU_MAP1_TRIM_2);
  312.             }
  313.         }
  314.     gluEndTrim(nurbsflag);
  315. }
  316. /* ARGSUSED1 */
  317. static void
  318. Key(unsigned char c, int x, int y)
  319. {
  320.     switch(c) {
  321.     case 27: /* Escape */
  322. exit(0);
  323. break;
  324.     default:
  325. break;
  326.     }
  327. }
  328. static void
  329. Button(int button, int down, int x, int y)
  330. {
  331.     if (down) {
  332. if (button == GLUT_LEFT_BUTTON) {
  333.     mstate = 1;
  334.     mousex = x;
  335.     mousey = y;
  336. }
  337.     } else {
  338. if (button == GLUT_LEFT_BUTTON)
  339.     mstate = 0;
  340.     }
  341.     if (mstate) {
  342. mousex = x;
  343. mousey = y;
  344.     }
  345. }
  346. static void
  347. resize(int width, int height)
  348. {
  349.    glViewport(0, 0, width, height);
  350. }
  351. static void
  352. expose(void)
  353. {
  354.     draw_nurb(trimming);
  355.     glutSwapBuffers();
  356. }
  357. static void
  358. idle(void)
  359. {
  360.   glutPostRedisplay();
  361. }
  362. static void
  363. visibility(int state)
  364. {
  365.   if (state == GLUT_VISIBLE) {
  366.     glutIdleFunc(idle);
  367.   } else {
  368.     glutIdleFunc(NULL);
  369.   }
  370. }
  371. static void
  372. Menu(int value)
  373. {
  374.     switch (value) {
  375.     case 1:
  376. trimming ^= 1; break;
  377.     case 2:
  378. filled ^= 1;
  379. gluNurbsProperty(nurbsflag, GLU_DISPLAY_MODE,
  380.  filled ? GLU_FILL : GLU_OUTLINE_POLYGON);
  381. break;
  382.     case 3:
  383. hull ^= 1; break;
  384.     case 4:
  385. exit(0); break;
  386.     default:
  387. break;
  388.     }
  389. }
  390. int
  391. main(int argc, char *argv[])
  392. {
  393.     glutInit(&argc, argv);
  394.     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  395.     glutInitWindowSize(400, 400);
  396.     glutCreateWindow("NURBS Surface");
  397.     glutDisplayFunc(expose);
  398.     glutReshapeFunc(resize);
  399.     glutKeyboardFunc(Key);
  400.     glutMouseFunc(Button);
  401.     glutCreateMenu(Menu);
  402.     glutAddMenuEntry("Trim", 1);
  403.     glutAddMenuEntry("Fill", 2);
  404.     glutAddMenuEntry("Hull", 3);
  405.     glutAddMenuEntry("Exit", 4);
  406.     glutAttachMenu(GLUT_RIGHT_BUTTON);
  407.     glutVisibilityFunc(visibility);
  408.     initialize();
  409.     glutMainLoop();
  410.     return 0;
  411. }