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

GIS编程

开发平台:

Visual C++

  1. #include <GL/glut.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <math.h>
  5. #include <string.h>
  6. #ifdef _WIN32
  7. #include "win32_dirent.h"
  8. /* Have to #undef LoadMenu or else Microsoft VC++ won't allow us to
  9.    redefine it. */
  10. #undef LoadMenu
  11. #else
  12. #include <dirent.h>
  13. #endif
  14. #include <assert.h>
  15. #include "walker.h"
  16. #define MAX(x,y) ((x) > (y) ? (x) : (y))
  17. #define MIN(x,y) ((x) < (y) ? (x) : (y))
  18. #define CYCLE_SIZE 100
  19. #define CYCLE_STEP 1.0/CYCLE_SIZE
  20. #define OVERSAMPLE 10
  21. #define MAX_CPOINTS 34   /* 2 end point ones and 10 in the middle */
  22. #define MAX_CSETNAMELEN 25
  23. #define NUM_JOINTS 5
  24. #define CSET_EXT ".cset"
  25. #define CSET_EXTLEN 5
  26. #include "walkviewer.h"
  27. typedef enum { CMENU_QUIT, CMENU_CURVE, CMENU_HORIZ, CMENU_RESET,
  28.                CMENU_WALK, CMENU_DONEEDIT, CMENU_SAVE, CMENU_LOAD,
  29.        CMENU_MIRROR
  30.               } CurveMenuChoices;
  31. typedef enum { WIRECUBE, SOLIDCUBE, CYLINDER1, CYLINDER2 } ModelTypes;
  32. int GuyModel = SOLIDCUBE;
  33. /***************************************************************/
  34. /*************************** GLOBALS ***************************/
  35. /***************************************************************/
  36. GLuint HorizontalList, AxesList,     /* Display lists */
  37.        CurveLists, ControlPtsLists;  /* Firsts of groups of display lists */
  38. int CurveAsPoints   =  0,    /* Display curve as points? */
  39.     DrawHorizontals =  0,    /* Draw horizontal lines?   */
  40.     EditingCurve    = -1;    /* Editing what curve, -1 means none */
  41. int CurveWindow,   /* Glut window id's to two top level windows */
  42.     GuyWindow;
  43. int MirrorLegs = 0;
  44. int CurveMenu     = -1,
  45.     CurveEditMenu = -1,
  46.     StepSizeMenu  = -1,
  47.     LoadMenu      = -1,
  48.     SaveMenu      = -1;
  49. char *CSetNames[MAX_CSETNAMELEN];
  50. int CurrentCurve = -1;  /* Curve loaded, index to CSetNames */
  51. GLfloat Walk_cycle[2][NUM_JOINTS][CYCLE_SIZE];  /* array of computed angles */
  52. int Step = CYCLE_SIZE/2;  /* Position in cycle, start in middle */
  53. float fStep = CYCLE_SIZE/2;   /* floating point for non-integer steping */
  54. float IncStep = 1.0;
  55. typedef struct ControlPts {
  56.   int numpoints;
  57.   float xcoords[MAX_CPOINTS];
  58.   float angles[MAX_CPOINTS];
  59. } tControlPts;
  60. tControlPts RotCurve[NUM_JOINTS];   /* series of cntrl points for ea joint */
  61. int Walking         = 0,     /* Guy is walking? */
  62.     ViewPerspective = 1,     /* Perspective or orthographic views */
  63.     DrawAxes        = 0;     /* Draw axes for alignment */
  64. int CurveWWidth,             /* Dimensions of curve window */
  65.     CurveWHeight;  
  66. int CurveDownBtn = -1,               /* mouse stuff, for editing curves */
  67.     WasWalking,
  68.     CurvePickedPoint = -1,
  69.     CurveLastX,
  70.     CurveLastY;
  71. int CurveWindowVisible = 1;
  72.   /* prototypes */
  73. void RedisplayBoth(void);
  74. void IncrementStep(void);
  75. void CurveCPointDrag(void);
  76. void CurveHandleMenu(int value);
  77. void StopWalking(void);
  78. void CurveHandleEditMenu(int curve);
  79. void ComputeCSetAndMakeLists(void);
  80. int MakeLoadAndSaveMenus(void);
  81. void CurveMenuInit(void);
  82. void SetWindowTitles(char *csetname);
  83. /***************************************************************/
  84. /**************************** BEZIER ***************************/
  85. /***************************************************************/
  86.   /* Matrix times a vector  dest = m*v */
  87. void MultMV(float m[3][4], float v[4], float dest[3])
  88. {
  89.   int i, j;
  90.   for (i = 0; i < 3; i++) {
  91.     dest[i] = 0;
  92.     for (j = 0; j < 4; j++)
  93.       dest[i] += m[i][j] * v[j];
  94.   }
  95. }
  96.   /* Matrix multiplication, dest = m1*m2 */
  97. void MultM(float m1[3][4], float m2[4][4], float dest[3][4])
  98. {
  99.   int i, j, k;
  100.   for (i = 0; i < 3; i++)
  101.     for (j = 0; j < 4; j++) {
  102.       dest[i][j] = 0;
  103.       for (k = 0; k < 4; k++)
  104.   dest[i][j] += (m1[i][k] * m2[k][j]);
  105.     }
  106. }
  107. void ComputeCurve(int joint)
  108. {
  109.   float prod[3][4], tm[4], pos[3];
  110.   float t = 0, tinc = (float)CYCLE_STEP/OVERSAMPLE;
  111.   int ctlpoint, i;
  112.   float BBasis[4][4] = {{-1, 3, -3, 1}, {3, -6, 3, 0},
  113.                         {-3, 3,  0, 0}, {1,  0, 0, 0}};
  114.   int lastindex, newindex;
  115.   float pointset[3][4];
  116.   for (i = 0; i < 4; i++)   /* z's are always zero, only 2-d */
  117.     pointset[2][i] = 0; 
  118.   lastindex = -1;
  119.   for(ctlpoint = 0; ctlpoint < RotCurve[joint].numpoints; ctlpoint += 3) {
  120.     t = 0;
  121.     for (i = 0; i < 4; i++)
  122.       pointset[0][i] = RotCurve[joint].xcoords[ctlpoint + i];
  123.     for (i = 0; i < 4; i++)
  124.       pointset[1][i] = RotCurve[joint].angles[ctlpoint + i];
  125.     MultM(pointset, BBasis, prod);
  126.     while (t <= 1) {
  127.       tm[0] = t*t*t;
  128.       tm[1] = t*t;
  129.       tm[2] = t;
  130.       tm[3] = 1;
  131.       MultMV(prod, tm, pos);
  132.       newindex = (int)(pos[0]*(CYCLE_SIZE-1));
  133.       if ((int)(newindex > lastindex))  {  /* go at least one */
  134. Walk_cycle[0][joint][newindex] = pos[1];
  135. lastindex++;
  136.       } 
  137.       t += tinc;
  138.     }
  139.   }
  140.   for (i = 0; i < CYCLE_SIZE; i++) {      /* copy to other leg, out-o-phase */
  141.     if (MirrorLegs)
  142.       Walk_cycle[1][joint][i] =
  143.         Walk_cycle[0][joint][i];
  144.     else
  145.       Walk_cycle[1][joint][i] =
  146.         Walk_cycle[0][joint][(i+(CYCLE_SIZE/2))%CYCLE_SIZE];
  147.   }
  148. }
  149. /***************************************************************/
  150. /************************* CURVE I/O ***************************/
  151. /***************************************************************/
  152. void FlatCSet(void)
  153. {
  154.   int joint;
  155.   for (joint = 0; joint < NUM_JOINTS; joint++) {
  156.     RotCurve[joint].numpoints = 4;
  157.     RotCurve[joint].xcoords[0] = 0.0;
  158.     RotCurve[joint].angles[0]  = 0.0;
  159.     RotCurve[joint].xcoords[1] = 0.2;
  160.     RotCurve[joint].angles[1]  = 0.0;
  161.     RotCurve[joint].xcoords[2] = 0.8;
  162.     RotCurve[joint].angles[2]  = 0.0;
  163.     RotCurve[joint].xcoords[3] = 1.0;
  164.     RotCurve[joint].angles[3]  = 0.0;
  165.   }
  166. }
  167. int ReadCSetFromFile(char *filename)
  168. {
  169.   FILE *infile = fopen(filename, "r");
  170.   int numjoints, numpoints, joint, point, mirrorlegs;
  171.   float value;
  172.   if (infile == NULL)
  173.     goto abort;
  174.   
  175.   if (!fscanf(infile, " %d", &numjoints) || numjoints != NUM_JOINTS)
  176.     goto abort;
  177.   if (!fscanf(infile, " %d", &mirrorlegs) || (mirrorlegs != 0 &&
  178.                                               mirrorlegs != 1))
  179.     goto abort;
  180.   MirrorLegs = mirrorlegs;
  181.   for (joint = 0; joint < NUM_JOINTS; joint++) {
  182.     if (!fscanf(infile, " %d", &numpoints) || numpoints < 4 || 
  183.                                               numpoints > MAX_CPOINTS)
  184.       goto abort;
  185.     RotCurve[joint].numpoints = numpoints;
  186.     for (point = 0; point < numpoints; point++) {
  187.       if (!fscanf(infile, " %f", &value))
  188. goto abort;
  189.       RotCurve[joint].xcoords[point] = value;
  190.     }
  191.     for (point = 0; point < numpoints; point++) {
  192.       if (!fscanf(infile, " %f", &value))
  193. goto abort;
  194.       RotCurve[joint].angles[point] = value;
  195.     }
  196.   }
  197.   fclose(infile);
  198.   return 0;
  199.   abort:
  200.     fclose(infile);
  201.     fprintf(stderr, "Something went wrong while reading file %sn", filename);
  202.     FlatCSet();
  203.     return -1;
  204. }
  205. void WriteCSetToFile(char *filename)
  206. {
  207.   FILE *outfile = fopen(filename, "w+");
  208.   int joint, point;
  209.   if (outfile == NULL) {
  210.     fprintf(stderr, "Error: could not create file %sn", filename);
  211.     return;
  212.   }
  213.   fprintf(outfile, "%dn", NUM_JOINTS);
  214.   fprintf(outfile, "%dn", MirrorLegs);
  215.   for (joint = 0; joint < NUM_JOINTS; joint++) {
  216.     fprintf(outfile, "%dn", RotCurve[joint].numpoints);
  217.     for (point = 0; point < RotCurve[joint].numpoints; point++) {
  218.       fprintf(outfile, "%f ", RotCurve[joint].xcoords[point]);
  219.     }
  220.     fprintf(outfile, "n");
  221.     for (point = 0; point < RotCurve[joint].numpoints; point++) {
  222.       fprintf(outfile, "%f ", RotCurve[joint].angles[point]);
  223.     }
  224.     fprintf(outfile, "n");
  225.   }
  226.   fclose(outfile);
  227. }
  228. void HandleLoadMenu(int cset)
  229. {
  230.   char filename[MAX_CSETNAMELEN + CSET_EXTLEN + 1];
  231.   if (cset == -1) {
  232.     MakeLoadAndSaveMenus();
  233.     CurveMenuInit();
  234.   } else {
  235.     (void)strcpy(filename, CSetNames[cset]);
  236.     (void)strcat(filename, CSET_EXT);
  237.     if (ReadCSetFromFile(filename) == 0) {
  238.       glutSetMenu(SaveMenu);
  239.       glutChangeToMenuEntry(1, CSetNames[cset], cset);
  240.       ComputeCSetAndMakeLists();
  241.       SetWindowTitles(CSetNames[cset]);
  242.       RedisplayBoth();
  243.     }
  244.   }
  245. }
  246. void HandleSaveMenu(int cset)
  247. {
  248.   char filename[MAX_CSETNAMELEN + CSET_EXTLEN + 1];
  249.   (void)strcpy(filename, CSetNames[cset]);
  250.   (void)strcat(filename, CSET_EXT);
  251.   WriteCSetToFile(filename);
  252.   ComputeCSetAndMakeLists();
  253.   RedisplayBoth();
  254. }
  255. int MakeLoadAndSaveMenus(void)
  256. {
  257.   DIR *dirp = opendir(".");
  258.   struct dirent *direntp;
  259.   int csetnum = 0;
  260.   char *newcsetname;
  261.   if (LoadMenu != -1)
  262.     glutDestroyMenu(LoadMenu);
  263.   if (SaveMenu != -1)
  264.     glutDestroyMenu(SaveMenu);
  265.   SaveMenu = glutCreateMenu(HandleSaveMenu);
  266.   LoadMenu = glutCreateMenu(HandleLoadMenu);
  267.   if (dirp == NULL) {
  268.     fprintf(stderr, "Error opening current dir in MakeLoadAndSaveMenusn");
  269.     return(0);
  270.   }
  271.   while ((direntp = readdir(dirp)) != NULL) {
  272.     char *ext = direntp->d_name + (strlen(direntp->d_name) - CSET_EXTLEN);
  273.     if (!strcmp(ext, CSET_EXT)) {
  274.       newcsetname = malloc(strlen(direntp->d_name) - CSET_EXTLEN + 1);
  275.       strncpy(newcsetname, direntp->d_name,
  276.       strlen(direntp->d_name) - CSET_EXTLEN);
  277.       newcsetname[strlen(direntp->d_name) - CSET_EXTLEN] = 0;
  278.       CSetNames[csetnum] = newcsetname;
  279.       glutAddMenuEntry(newcsetname, csetnum++);
  280.     }
  281.   }
  282.   closedir(dirp);
  283.   glutSetMenu(LoadMenu);
  284.   glutAddMenuEntry("-> Rescan Directory <-", -1);
  285.   glutSetMenu(SaveMenu);
  286.   CSetNames[csetnum] = "NewCurve0";
  287.   glutAddMenuEntry("NewCurve0", csetnum++);
  288.   CSetNames[csetnum] = "NewCurve1";
  289.   glutAddMenuEntry("NewCurve1", csetnum++);
  290.   CSetNames[csetnum] = "NewCurve2";
  291.   glutAddMenuEntry("NewCurve2", csetnum++);
  292.   return (csetnum - 2);  /* just indicate curves in Load menu */
  293. }
  294. /***************************************************************/
  295. /********************* DISPLAY LISTS ***************************/
  296. /***************************************************************/
  297. void MakeCurveList(int joint)
  298. {
  299.   int i;
  300.   glNewList(CurveLists+joint, GL_COMPILE);
  301.   glColor3f(1, 1, 1);
  302.   for (i = 0; i < CYCLE_SIZE; i++) {
  303.     glVertex3f((GLfloat)i/CYCLE_SIZE, Walk_cycle[0][joint][i]/180, 0);
  304.   }
  305.   glEndList();
  306. }
  307. void MakeCPointList(int joint)
  308. {
  309.   int point;
  310.  
  311.   glNewList(ControlPtsLists+joint, GL_COMPILE);
  312.     glColor3f(0, 0.4, 0);
  313.     glBegin(GL_LINE_STRIP);
  314.     for (point = 0; point < RotCurve[joint].numpoints; point++) {
  315.       if (!((point-2) % 3)) {
  316.         glEnd();
  317.         glBegin(GL_LINE_STRIP);
  318.       }
  319.       glVertex3f(RotCurve[joint].xcoords[point],
  320.          (RotCurve[joint].angles[point])/180.0, 0.0);
  321.     }
  322.     glEnd();
  323.     glBegin(GL_POINTS);
  324.     for (point = 0; point < RotCurve[joint].numpoints; point++) {
  325.       if (point % 3)
  326.         glColor3f(0, 0.7, 0);
  327.       else
  328.         glColor3f(0.7, 0.0, 0);
  329.       glVertex3f(RotCurve[joint].xcoords[point],
  330.          (RotCurve[joint].angles[point])/180, 0);
  331.     }
  332.     glEnd();
  333.   glEndList();
  334. }
  335. void MakeJointLists(int joint)
  336. {
  337.   MakeCurveList(joint);
  338.   MakeCPointList(joint);
  339. }
  340. void ComputeCSetAndMakeLists(void)
  341. {
  342.   int joint;
  343.   for(joint = 0; joint < NUM_JOINTS; joint++) {
  344.     ComputeCurve(joint);
  345.     MakeJointLists(joint);
  346.   }
  347. }
  348. void MakeLists(void)
  349. {
  350.   HorizontalList = glGenLists(1);
  351.   glNewList(HorizontalList, GL_COMPILE);
  352.   {
  353.     float line1 = 25.0/180,
  354.           line2 = 35.0/180,
  355.           line3 = 45.0/180;
  356.     glColor3f(0, 0, 0.7);
  357.     glPushAttrib(GL_ENABLE_BIT);
  358.     glEnable(GL_LINE_STIPPLE);
  359.     glBegin(GL_LINES);
  360.       glVertex3f(0, 0, 0.5);
  361.       glVertex3f(1, 0, 0.5);
  362.       glVertex3f(0, line1, 0.5);  glVertex3f(1, line1, 0.5);
  363.       glVertex3f(0, -line1, 0.5); glVertex3f(1, -line1, 0.5);
  364.       glVertex3f(0, line2, 0.5);  glVertex3f(1, line2, 0.5);
  365.       glVertex3f(0, -line2, 0.5); glVertex3f(1, -line2, 0.5);
  366.       glVertex3f(0, line3, 0.5);  glVertex3f(1, line3, 0.5);
  367.       glVertex3f(0, -line3, 0.5); glVertex3f(1, -line3, 0.5);
  368.     glEnd();
  369.     glPopAttrib();
  370.   }
  371.   glEndList();
  372.   CurveLists = glGenLists(NUM_JOINTS);
  373.   assert(CurveLists != 0);
  374.   ControlPtsLists = glGenLists(NUM_JOINTS);
  375.   assert(ControlPtsLists != 0);
  376.   ComputeCSetAndMakeLists();
  377. }
  378. /***************************************************************/
  379. /********************* curve WINDOW ****************************/
  380. /***************************************************************/
  381. void CurveReshape(int w, int h)
  382. {
  383.   glViewport(0,0,w,h);
  384.   CurveWWidth = w; 
  385.   CurveWHeight = h;
  386.   glFlush();
  387. }
  388. void CurveDisplay(void)
  389. {
  390.   int joint, otherlegstep;
  391.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  392.   glPushMatrix();
  393.   glTranslatef(0, 0.5, 0);
  394.   for (joint = NUM_JOINTS-1; joint >= 0; joint--) {
  395.     if (DrawHorizontals) 
  396.       glCallList(HorizontalList);
  397.     (CurveAsPoints) ?
  398.     glBegin(GL_POINTS) :
  399.     glBegin(GL_LINE_STRIP);
  400.       glCallList(CurveLists+joint);
  401.     glEnd();
  402.     if (joint == EditingCurve) { 
  403.       glPointSize(5.0);
  404.       glCallList(ControlPtsLists+EditingCurve);
  405.       glPointSize(1.0);
  406.     }
  407.   glTranslatef(0, 1, 0);
  408.   }
  409.   glPopMatrix();
  410.   otherlegstep = (Step+50) % CYCLE_SIZE;
  411.     /* draw vertical line */
  412.   glColor3f(1, 1, 1);
  413.   glBegin(GL_LINES);
  414.     glVertex3f((GLfloat)Step/CYCLE_SIZE, 0, 0);
  415.     glVertex3f((GLfloat)Step/CYCLE_SIZE, NUM_JOINTS, 0);
  416.     if (!MirrorLegs) {
  417.       glVertex3f((GLfloat)otherlegstep/CYCLE_SIZE, 0, 0);
  418.       glVertex3f((GLfloat)otherlegstep/CYCLE_SIZE, NUM_JOINTS, 0);
  419.     }
  420.   glEnd();
  421.   glFlush();
  422.   glutSwapBuffers();
  423. }
  424. void CurveGLInit(void)
  425. {
  426.   glMatrixMode(GL_PROJECTION);
  427.   glLoadIdentity();
  428.   glOrtho(0,1,0,NUM_JOINTS,1,-1);
  429.   glMatrixMode(GL_MODELVIEW);
  430.   glLoadIdentity();
  431.   glLineStipple(1, 0x00FF);
  432.   glEnable(GL_DEPTH_TEST);
  433.   glDepthFunc(GL_LEQUAL);
  434.   glFlush();
  435. /* ARGSUSED2 */
  436. void CurveHandleButton(int button, int state, int x, int y)
  437. {
  438.   if (button == GLUT_RIGHT_BUTTON )
  439.     return;
  440.   if (state == GLUT_DOWN && CurveDownBtn == -1) {
  441.     if (button == GLUT_MIDDLE_BUTTON)
  442.       CurveHandleMenu(CMENU_WALK);
  443.     else
  444.       fStep = Step = (int)((float)x/glutGet(GLUT_WINDOW_WIDTH) * CYCLE_SIZE);
  445.       
  446.     CurveDownBtn = button;
  447.     WasWalking = Walking;
  448.     StopWalking();
  449.     RedisplayBoth();
  450.   } else if (button == CurveDownBtn) {
  451.     CurveDownBtn = -1;
  452.     if (WasWalking) {
  453.       Walking = 1;
  454.       agvSetAllowIdle(0);
  455.       glutIdleFunc(IncrementStep);
  456.     }
  457.   }
  458. }
  459. float CurveEditConstrain(float fx)
  460. {
  461.   if (CurvePickedPoint == 0)
  462.     fx = 0;
  463.   else if (CurvePickedPoint == RotCurve[EditingCurve].numpoints-1)
  464.     fx = 1;
  465.   else if (!(CurvePickedPoint % 3)) {  /* is a pivot */
  466.     fx = MAX(fx, RotCurve[EditingCurve].xcoords[CurvePickedPoint-1]);
  467.     fx = MIN(fx, RotCurve[EditingCurve].xcoords[CurvePickedPoint+1]);   
  468.     fx = MAX(fx, RotCurve[EditingCurve].xcoords[CurvePickedPoint-3]);
  469.     fx = MIN(fx, RotCurve[EditingCurve].xcoords[CurvePickedPoint+3]);       
  470.   } else if (!((CurvePickedPoint - 1) % 3)) {   /* is right slope */
  471.     fx = MAX(fx, RotCurve[EditingCurve].xcoords[CurvePickedPoint-1]);
  472.   } else {
  473.     fx = MIN(fx, RotCurve[EditingCurve].xcoords[CurvePickedPoint+1]);
  474.   } 
  475.   return fx;
  476. }
  477. void RemovePoint(int pt)
  478. {
  479.   int i;
  480.   for (i = pt - 1; i < RotCurve[EditingCurve].numpoints; i++) {
  481.     RotCurve[EditingCurve].xcoords[i] = RotCurve[EditingCurve].xcoords[i+3];
  482.     RotCurve[EditingCurve].angles[i]  = RotCurve[EditingCurve].angles[i+3];
  483.   }
  484.   RotCurve[EditingCurve].numpoints -= 3;
  485. }
  486. void AddPoint(float fx)
  487. {
  488.   int i, j;
  489.   if (fx < 0.05 || fx > 0.95 || RotCurve[EditingCurve].numpoints + 3 >=
  490.                                 MAX_CPOINTS)
  491.     return;
  492.   for (i = 3; i < RotCurve[EditingCurve].numpoints; i += 3) {
  493.     if (fx < RotCurve[EditingCurve].xcoords[i]) {
  494.       for (j = RotCurve[EditingCurve].numpoints + 2; j > i + 1; j--) { 
  495.         RotCurve[EditingCurve].xcoords[j] =
  496.                 RotCurve[EditingCurve].xcoords[j-3];
  497.         RotCurve[EditingCurve].angles[j] =
  498.                 RotCurve[EditingCurve].angles[j-3];
  499.       }
  500.     RotCurve[EditingCurve].xcoords[i]   = fx;
  501.     RotCurve[EditingCurve].angles[i]    =
  502.       Walk_cycle[0][EditingCurve][(int)(fx*CYCLE_SIZE)];
  503.     RotCurve[EditingCurve].xcoords[i-1] = fx - 0.05;
  504.     RotCurve[EditingCurve].angles[i-1]  =
  505.       Walk_cycle[0][EditingCurve][(int)((fx-0.05)*CYCLE_SIZE)];
  506.     RotCurve[EditingCurve].xcoords[i+1] = fx + 0.05;
  507.     RotCurve[EditingCurve].angles[i+1]  = 
  508.       Walk_cycle[0][EditingCurve][(int)((fx+0.05)*CYCLE_SIZE)];
  509.     RotCurve[EditingCurve].numpoints += 3;
  510.     break;
  511.     }
  512.   }  
  513. }
  514. void CurveEditHandleButton(int button, int state, int x, int y)
  515. {
  516.   float fx, fy;
  517.   int point;
  518.   fy = -(((float)y - ((float)CurveWHeight/NUM_JOINTS * EditingCurve)) /
  519.        ((float)CurveWHeight/NUM_JOINTS) - 0.5) * 180.0,
  520.   fx = (float)x/CurveWWidth;
  521.   
  522.   if (state == GLUT_DOWN && button == GLUT_LEFT_BUTTON &&
  523.                             CurveDownBtn == -1) {
  524.     CurvePickedPoint = -1;
  525.     
  526.     for (point = 0; point < RotCurve[EditingCurve].numpoints; point++) {
  527.       if (fabs(RotCurve[EditingCurve].xcoords[point] - fx) < 0.01 &&
  528.   fabs(RotCurve[EditingCurve].angles[point] - fy) < 4) {
  529. CurvePickedPoint = point;
  530. CurveLastX = x;
  531. CurveLastY = y;
  532. glutIdleFunc(CurveCPointDrag);
  533. break;
  534.       }
  535.     }
  536.    if (CurvePickedPoint == -1)
  537.      CurveHandleButton(button, state, x, y);
  538.     CurveDownBtn = button;
  539.   } else if (state == GLUT_DOWN && button == GLUT_MIDDLE_BUTTON &&
  540.                                    CurveDownBtn == -1) {
  541.     for (point = 3; point < RotCurve[EditingCurve].numpoints - 1; point += 3) {
  542.       if (fabs(RotCurve[EditingCurve].xcoords[point] - fx) < 0.01 &&
  543.   fabs(RotCurve[EditingCurve].angles[point] - fy) < 4) {
  544. break;
  545.       }
  546.     }
  547.     if (point >= 3 && point < RotCurve[EditingCurve].numpoints - 1)
  548.       RemovePoint(point);
  549.     else if (fabs(Walk_cycle[0][EditingCurve][(int)(fx*CYCLE_SIZE)] - fy) < 4)
  550.       AddPoint(fx);
  551.     ComputeCurve(EditingCurve);
  552.     MakeJointLists(EditingCurve);    
  553.     RedisplayBoth();
  554.   } else if (button == GLUT_LEFT_BUTTON && button == CurveDownBtn) {
  555.     y = MAX(y, 0); y = MIN(y, CurveWHeight);
  556.     x = MAX(x, 0); x = MIN(x, CurveWWidth);
  557.     fy = -(((float)y - ((float)CurveWHeight/NUM_JOINTS * EditingCurve)) /
  558.          ((float)CurveWHeight/NUM_JOINTS) - 0.5) * 180.0,
  559.     fx = (float)x/CurveWWidth;
  560.     CurveDownBtn = -1;
  561.     if (CurvePickedPoint != -1) {
  562.       fx = CurveEditConstrain(fx);
  563.       RotCurve[EditingCurve].xcoords[CurvePickedPoint] = fx;
  564.       RotCurve[EditingCurve].angles[CurvePickedPoint] = fy;        
  565.       ComputeCurve(EditingCurve);
  566.       MakeJointLists(EditingCurve);
  567.       glutIdleFunc(NULL);
  568.       RedisplayBoth();
  569.     }
  570.   }
  571. }  
  572. void CurveHandleMotion(int x, int y)
  573. {
  574.   if (CurvePickedPoint == -1) { 
  575.     
  576.     if (CurveDownBtn == GLUT_LEFT_BUTTON || CurveDownBtn ==
  577.                                             GLUT_MIDDLE_BUTTON) {
  578.       Step = (int)((float)x/glutGet(GLUT_WINDOW_WIDTH) * CYCLE_SIZE)
  579. % CYCLE_SIZE;
  580.       if (Step < 0)
  581. Step = CYCLE_SIZE + Step;
  582.       fStep = Step;
  583.     RedisplayBoth();
  584.     }
  585.   } else {
  586.     y = MAX(y, 0); y = MIN(y, CurveWHeight);
  587.     x = MAX(x, 0); x = MIN(x, CurveWWidth);
  588.     CurveLastX = x;
  589.     CurveLastY = y;
  590.   }
  591. }
  592. void CurveCPointDrag(void)
  593. {
  594.   float fx, fy;
  595.   if (CurveDownBtn == GLUT_LEFT_BUTTON && CurvePickedPoint != -1) {
  596.     fy = -(((float)CurveLastY -
  597.            ((float)CurveWHeight/NUM_JOINTS * EditingCurve)) /
  598.           ((float)CurveWHeight/NUM_JOINTS) - 0.5) * 180.0,
  599.     fx = (float)CurveLastX/CurveWWidth;
  600.     fx = CurveEditConstrain(fx);
  601.     RotCurve[EditingCurve].xcoords[CurvePickedPoint] = fx;
  602.     RotCurve[EditingCurve].angles[CurvePickedPoint] = fy;        
  603.     ComputeCurve(EditingCurve);
  604.     MakeJointLists(EditingCurve);
  605.     RedisplayBoth();
  606.   }
  607. }
  608. /* ARGSUSED1 */
  609. void CurveHandleKeys(unsigned char key, int x, int y)
  610. {
  611.   if (key > '0' && key < '9')
  612.     CurveHandleEditMenu((key-'0')-1);
  613.   else if (key == 'd')
  614.     CurveHandleMenu(CMENU_DONEEDIT);
  615.   else {
  616.     switch(key) {
  617.       case 'f':
  618.       case ' ': Step++;
  619.                 StopWalking(); break;
  620.       case 'F': Step += 5;
  621.                 StopWalking(); break;
  622.       case 'b': Step--;
  623.                 StopWalking(); break;
  624.       case 'B': Step -= 5; 
  625.                 StopWalking(); break;
  626.     }
  627.     Step %= CYCLE_SIZE;
  628.     if (Step < 0)
  629.       Step = CYCLE_SIZE + Step;
  630.     fStep = Step;
  631.     RedisplayBoth();
  632.   }
  633. }
  634. void CurveHandleEditMenu(int curve)
  635. {
  636.   if (curve >= NUM_JOINTS)
  637.     return;
  638.   if (EditingCurve == -1) {
  639.     WasWalking = Walking;
  640.     Walking = 0;
  641.     agvSetAllowIdle(0);   /* don't allow spinning, just slows us down */
  642.     glutIdleFunc(NULL);
  643.     glutMouseFunc(CurveEditHandleButton);
  644.   }
  645.   EditingCurve = curve;
  646.   glutPostRedisplay();
  647. }
  648. void CurveHandleSZMenu(int size)
  649. {
  650.   IncStep = (float)size/100;
  651. }
  652. void CurveHandleMenu(int value)
  653. {
  654.   switch (value) {
  655.     case CMENU_QUIT:
  656.       exit(0);
  657.       break;
  658.     case CMENU_CURVE:
  659.       CurveAsPoints = !CurveAsPoints;
  660.       glutPostRedisplay();
  661.       break;
  662.     case CMENU_HORIZ:
  663.       DrawHorizontals = !DrawHorizontals;
  664.       glutPostRedisplay();
  665.       break;
  666.     case CMENU_WALK:
  667.       if (EditingCurve != -1)
  668. break;
  669.       Walking = !Walking;
  670.       if (Walking) {
  671.         agvSetAllowIdle(0);
  672. glutIdleFunc(IncrementStep);
  673.       } else {
  674.         agvSetAllowIdle(1);
  675.       }
  676.       break;
  677.     case CMENU_DONEEDIT:
  678.       glutMouseFunc(CurveHandleButton);
  679.       EditingCurve = -1;
  680.       CurvePickedPoint = -1;
  681.       Walking = WasWalking;
  682.       if (Walking)
  683. glutIdleFunc(IncrementStep);
  684.       else
  685.         agvSetAllowIdle(1);
  686.       glutPostRedisplay();
  687.       break;
  688.     case CMENU_RESET:
  689.       FlatCSet();
  690.       ComputeCSetAndMakeLists();
  691.       glutPostRedisplay();
  692.       break;
  693.     case CMENU_MIRROR:
  694.       MirrorLegs = !MirrorLegs;
  695.       ComputeCSetAndMakeLists();
  696.       glutPostRedisplay();      
  697.     }
  698. }
  699. void CurveMenuInit(void)
  700. {
  701.   int i;
  702.   char label[3];
  703.   if (CurveEditMenu != -1) {
  704.     glutDestroyMenu(CurveEditMenu);
  705.     glutDestroyMenu(CurveMenu);
  706.     glutDestroyMenu(StepSizeMenu);
  707.   }
  708.   CurveEditMenu = glutCreateMenu(CurveHandleEditMenu);
  709.   for (i = 0; i < NUM_JOINTS; i++) {
  710.     sprintf(label, " %d ", i+1);
  711.     glutAddMenuEntry(label, i);
  712.   }
  713.   StepSizeMenu = glutCreateMenu(CurveHandleSZMenu);
  714.   glutAddMenuEntry("0.25", 25);
  715.   glutAddMenuEntry("0.5",  50);
  716.   glutAddMenuEntry("1.0", 100);
  717.   glutAddMenuEntry("2.0", 200);
  718.   glutAddMenuEntry("3.0", 300);
  719.   glutAddMenuEntry("5.0", 500);
  720.   CurveMenu = glutCreateMenu(CurveHandleMenu);
  721.   glutAddSubMenu("Load Curve Set", LoadMenu);
  722.   glutAddSubMenu("Save As Curve Set", SaveMenu);
  723.   glutAddSubMenu("Edit Curve", CurveEditMenu);
  724.   glutAddMenuEntry("Done Editing", CMENU_DONEEDIT);
  725.   glutAddMenuEntry("Flatten Curve Set", CMENU_RESET);
  726.   glutAddMenuEntry("Toggle mirrored", CMENU_MIRROR);
  727.   glutAddSubMenu("Step size", StepSizeMenu);
  728.   glutAddMenuEntry("Toggle dotted", CMENU_CURVE);
  729.   glutAddMenuEntry("Toggle horizontals", CMENU_HORIZ);
  730.   glutAddMenuEntry("Toggle walking", CMENU_WALK);
  731.   glutAddMenuEntry("Quit", CMENU_QUIT);
  732.   glutSetWindow(CurveWindow);
  733.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  734. }
  735. void CurveVisible(int v)
  736. {
  737.   if (v == GLUT_VISIBLE)
  738.     CurveWindowVisible = 1;
  739.   else 
  740.     CurveWindowVisible = 0;
  741. }
  742. /***************************************************************/
  743. /*********************** GUY WINDOW ****************************/
  744. /***************************************************************/
  745. void GuyDisplay(void)
  746. {
  747.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  748.   glFlush();
  749.   glLoadIdentity();
  750.   agvViewTransform();
  751.   if (DrawAxes)
  752.     glCallList(AxesList);
  753.   switch(GuyModel) {
  754.     case WIRECUBE:   DrawTheGuy_WC();  break;
  755.     case SOLIDCUBE:  DrawTheGuy_SC();  break;
  756.     case CYLINDER1:  DrawTheGuy_SL();  break;
  757.     case CYLINDER2:  DrawTheGuy_SL2(); break;
  758.   }
  759.   glutSwapBuffers();
  760.   glFlush();
  761. }
  762. void GuyReshape(int w, int h)
  763. {
  764.   glViewport(0,0,w,h);
  765.   glMatrixMode(GL_PROJECTION);
  766.   glLoadIdentity();
  767.   if (ViewPerspective)
  768.     gluPerspective(60.0, (GLdouble)w/h, 0.01, 100);
  769.   else
  770.     glOrtho(-1.2, 1.2, -1.2, 1.2, 0.1, 100);
  771.   glMatrixMode(GL_MODELVIEW);
  772.   glFlush();
  773. }
  774. void GuyGLInit(void)
  775. {
  776.   GLfloat mat_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
  777.   GLfloat light_position[] = { 0.3, 0.5, 0.8, 0.0 };
  778.   GLfloat lm_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
  779.   
  780.   glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
  781.   glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  782.   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lm_ambient);
  783.   
  784.   glEnable(GL_LIGHTING);
  785.   glEnable(GL_LIGHT0);
  786.   glDepthFunc(GL_LESS);
  787.   glEnable(GL_DEPTH_TEST);
  788.   glEnable(GL_NORMALIZE);
  789.   glShadeModel(GL_SMOOTH);
  790.   /* Cylinder stuff */
  791.   StoreTheGuy_SL();
  792.   StoreTheGuy_SL2();
  793. }
  794. void GuyHandleKeys(unsigned char key, int x, int y)
  795. {
  796.   switch(key) {
  797.     case 'f':
  798.     case ' ': Step++;
  799.               StopWalking(); break;
  800.     case 'F': Step += 5;
  801.               StopWalking(); break;
  802.     case 'b': Step--;
  803.               StopWalking(); break;
  804.     case 'B': Step -= 5; 
  805.               StopWalking(); break;
  806.   }
  807.   Step %= CYCLE_SIZE;
  808.   if (Step < 0)
  809.     Step = CYCLE_SIZE + Step;
  810.   agvHandleKeys(key, x, y);
  811.   RedisplayBoth();
  812. }
  813. typedef enum { GMENU_QUIT, GMENU_CURVE, GMENU_HORIZ,
  814.                GMENU_AXES, GMENU_PERSP } GuyMenuChoices;
  815. void GuyModelHandleMenu(int model)
  816. {
  817.   GuyModel = model;
  818.   if (model == WIRECUBE)
  819.     glDisable(GL_LIGHTING);
  820.   else
  821.     glEnable(GL_LIGHTING);
  822.   glutPostRedisplay();
  823. }
  824. void GuyHandleMenu(int value)
  825. {
  826.   switch (value) {
  827.     case GMENU_QUIT:
  828.       exit(0);
  829.       break;
  830.     case GMENU_AXES:
  831.       DrawAxes = !DrawAxes;
  832.       glutPostRedisplay();
  833.       break;
  834.     case GMENU_PERSP:
  835.       ViewPerspective = !ViewPerspective;
  836.       GuyReshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
  837.       glutPostRedisplay();
  838.       break;
  839.   }
  840. }
  841. void GuyMenuInit(void)
  842. {
  843.   int sub2, sub1 = glutCreateMenu(agvSwitchMoveMode);
  844.   glutAddMenuEntry("Flying move",  FLYING);
  845.   glutAddMenuEntry("Polar move",   POLAR);
  846.   sub2 = glutCreateMenu(GuyModelHandleMenu);
  847.   glutAddMenuEntry("Wire cubes",  WIRECUBE);
  848.   glutAddMenuEntry("Solid cubes", SOLIDCUBE);
  849.   glutAddMenuEntry("Cylinder 1",  CYLINDER1);
  850.   glutAddMenuEntry("Cylinder 2",  CYLINDER2);
  851.   glutCreateMenu(GuyHandleMenu);
  852.   glutAddSubMenu("Viewing", sub1);
  853.   glutAddSubMenu("Model", sub2);
  854.   glutAddMenuEntry("Toggle Axes",    GMENU_AXES);
  855.   glutAddMenuEntry("Toggle Perspective View", GMENU_PERSP);
  856.   glutAddMenuEntry("Quit",           GMENU_QUIT);
  857.   glutSetWindow(GuyWindow);
  858.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  859. }
  860. /***************************************************************/
  861. /********************* BOTH WINDOWS ****************************/
  862. /***************************************************************/
  863. void RedisplayBoth(void)
  864. {
  865.   glutPostWindowRedisplay(GuyWindow);
  866.   if (CurveWindowVisible) {
  867.     glutPostWindowRedisplay(CurveWindow);
  868.   }
  869. }
  870. void IncrementStep(void)
  871. {
  872.   fStep = fmod(fStep + IncStep, CYCLE_SIZE);
  873.   Step = (int)fStep;
  874.   if (agvMoving)
  875.     agvMove();
  876.   RedisplayBoth();
  877. }
  878. void StopWalking(void)
  879. {
  880.   if (Walking) {
  881.     Walking = 0;
  882.     agvSetAllowIdle(1);
  883.   }
  884. }
  885. void SetWindowTitles(char *csetname)
  886. {
  887.   char windowtitle[MAX_CSETNAMELEN + 20];
  888.   strcpy(windowtitle, "Rotation Curves: ");
  889.   strcat(windowtitle, csetname);
  890.   glutSetWindow(CurveWindow);
  891.   glutSetWindowTitle(windowtitle);
  892.   strcpy(windowtitle, "The Guy: ");
  893.   strcat(windowtitle, csetname);
  894.   glutSetWindow(GuyWindow);
  895.   glutSetWindowTitle(windowtitle);
  896. }
  897. /***************************************************************/
  898. /***************************** MAIN ****************************/
  899. /***************************************************************/
  900. int main(int argc, char** argv)
  901. {
  902.   glutInit(&argc, argv);
  903.   glutInitWindowSize(512, 512);
  904.   glutInitWindowPosition(700, 250);
  905.   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  906.   GuyWindow = glutCreateWindow("The Guy:");
  907.   agvInit(!Walking);
  908.   AxesList = glGenLists(1);
  909.   agvMakeAxesList(AxesList);
  910.   GuyGLInit();
  911.   GuyMenuInit();
  912.   glutDisplayFunc(GuyDisplay);
  913.   glutReshapeFunc(GuyReshape);
  914.   glutKeyboardFunc(GuyHandleKeys);
  915.   glutInitWindowSize(512, 1024);
  916.   glutInitWindowPosition(100, 0);
  917.   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  918.   CurveWindow = glutCreateWindow("Rotation Curves:");
  919.   CurveGLInit();
  920.   glutDisplayFunc(CurveDisplay);
  921.   glutReshapeFunc(CurveReshape);
  922.   glutMouseFunc(CurveHandleButton);
  923.   glutMotionFunc(CurveHandleMotion);
  924.   glutKeyboardFunc(CurveHandleKeys);
  925.   glutVisibilityFunc(CurveVisible);
  926.   FlatCSet();
  927.   MakeLists();
  928.   if (MakeLoadAndSaveMenus() > 0)  /* read first curve if there was one */
  929.     HandleLoadMenu(0);
  930.   CurveMenuInit();
  931.   glutMainLoop();
  932.   return 0;             /* ANSI C requires main to return int. */
  933. }