home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / graphicgems4.lha / GemsIV / arcball / Ball.c next >
Encoding:
C/C++ Source or Header  |  1995-02-06  |  5.1 KB  |  200 lines

  1. /***** Ball.c *****/
  2. /* Ken Shoemake, 1993 */
  3. #include <gl/gl.h>
  4. #include "Ball.h"
  5. #include "BallMath.h"
  6.  
  7. #define LG_NSEGS 4
  8. #define NSEGS (1<<LG_NSEGS)
  9. #define RIMCOLOR()    RGBcolor(255, 255, 255)
  10. #define FARCOLOR()    RGBcolor(195, 127, 31)
  11. #define NEARCOLOR()   RGBcolor(255, 255, 63)
  12. #define DRAGCOLOR()   RGBcolor(127, 255, 255)
  13. #define RESCOLOR()    RGBcolor(195, 31, 31)
  14.  
  15. HMatrix mId = {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
  16. float otherAxis[][4] = {{-0.48, 0.80, 0.36, 1}};
  17.  
  18. /* Establish reasonable initial values for controller. */
  19. void Ball_Init(BallData *ball)
  20. {
  21.     int i;
  22.     ball->center = qOne;
  23.     ball->radius = 1.0;
  24.     ball->vDown = ball->vNow = qOne;
  25.     ball->qDown = ball->qNow = qOne;
  26.     for (i=15; i>=0; i--)
  27.     ((float *)ball->mNow)[i] = ((float *)ball->mDown)[i] = ((float *)mId)[i];
  28.     ball->showResult = ball->dragging = FALSE;
  29.     ball->axisSet = NoAxes;
  30.     ball->sets[CameraAxes] = mId[X]; ball->setSizes[CameraAxes] = 3;
  31.     ball->sets[BodyAxes] = ball->mDown[X]; ball->setSizes[BodyAxes] = 3;
  32.     ball->sets[OtherAxes] = otherAxis[X]; ball->setSizes[OtherAxes] = 1;
  33. }
  34.  
  35. /* Set the center and size of the controller. */
  36. void Ball_Place(BallData *ball, HVect center, double radius)
  37. {
  38.     ball->center = center;
  39.     ball->radius = radius;
  40. }
  41.  
  42. /* Incorporate new mouse position. */
  43. void Ball_Mouse(BallData *ball, HVect vNow)
  44. {
  45.     ball->vNow = vNow;
  46. }
  47.  
  48. /* Choose a constraint set, or none. */
  49. void Ball_UseSet(BallData *ball, AxisSet axisSet)
  50. {
  51.     if (!ball->dragging) ball->axisSet = axisSet;
  52. }
  53.  
  54. /* Begin drawing arc for all drags combined. */
  55. void Ball_ShowResult(BallData *ball)
  56. {
  57.     ball->showResult = TRUE;
  58. }
  59.  
  60. /* Stop drawing arc for all drags combined. */
  61. void Ball_HideResult(BallData *ball)
  62. {
  63.     ball->showResult = FALSE;
  64. }
  65.  
  66. /* Using vDown, vNow, dragging, and axisSet, compute rotation etc. */
  67. void Ball_Update(BallData *ball)
  68. {
  69.     int i, setSize = ball->setSizes[ball->axisSet];
  70.     HVect *set = (HVect *)(ball->sets[ball->axisSet]);
  71.     ball->vFrom = MouseOnSphere(ball->vDown, ball->center, ball->radius);
  72.     ball->vTo = MouseOnSphere(ball->vNow, ball->center, ball->radius);
  73.     if (ball->dragging) {
  74.     if (ball->axisSet!=NoAxes) {
  75.         ball->vFrom = ConstrainToAxis(ball->vFrom, set[ball->axisIndex]);
  76.         ball->vTo = ConstrainToAxis(ball->vTo, set[ball->axisIndex]);
  77.     }
  78.     ball->qDrag = Qt_FromBallPoints(ball->vFrom, ball->vTo);
  79.     ball->qNow = Qt_Mul(ball->qDrag, ball->qDown);
  80.     } else {
  81.     if (ball->axisSet!=NoAxes) {
  82.         ball->axisIndex = NearestConstraintAxis(ball->vTo, set, setSize);
  83.     }
  84.     }
  85.     Qt_ToBallPoints(ball->qDown, &ball->vrFrom, &ball->vrTo);
  86.     Qt_ToMatrix(Qt_Conj(ball->qNow), ball->mNow); /* Gives transpose for GL. */
  87. }
  88.  
  89. /* Return rotation matrix defined by controller use. */
  90. void Ball_Value(BallData *ball, HMatrix mNow)
  91. {
  92.     int i;
  93.     for (i=15; i>=0; i--) ((float *)mNow)[i] = ((float *)ball->mNow)[i];
  94. }
  95.  
  96.  
  97. /* Begin drag sequence. */
  98. void Ball_BeginDrag(BallData *ball)
  99. {
  100.     ball->dragging = TRUE;
  101.     ball->vDown = ball->vNow;
  102. }
  103.  
  104. /* Stop drag sequence. */
  105. void Ball_EndDrag(BallData *ball)
  106. {
  107.     int i;
  108.     ball->dragging = FALSE;
  109.     ball->qDown = ball->qNow;
  110.     for (i=15; i>=0; i--)
  111.     ((float *)ball->mDown)[i] = ((float *)ball->mNow)[i];
  112. }
  113.  
  114. /* Draw the controller with all its arcs. */
  115. void Ball_Draw(BallData *ball)
  116. {
  117.     float r = ball->radius;
  118.     pushmatrix();
  119.     loadmatrix(mId);
  120.     ortho2(-1.0, 1.0, -1.0, 1.0);
  121.     RIMCOLOR();
  122.     scale(r, r, r);
  123.     circ(0.0, 0.0, 1.0);
  124.     Ball_DrawResultArc(ball);
  125.     Ball_DrawConstraints(ball);
  126.     Ball_DrawDragArc(ball);
  127.     popmatrix();
  128. }
  129.  
  130. /* Draw an arc defined by its ends. */
  131. void DrawAnyArc(HVect vFrom, HVect vTo)
  132. {
  133.     int i;
  134.     HVect pts[NSEGS+1];
  135.     double dot;
  136.     pts[0] = vFrom;
  137.     pts[1] = pts[NSEGS] = vTo;
  138.     for (i=0; i<LG_NSEGS; i++) pts[1] = V3_Bisect(pts[0], pts[1]);
  139.     dot = 2.0*V3_Dot(pts[0], pts[1]);
  140.     for (i=2; i<NSEGS; i++) {
  141.     pts[i] = V3_Sub(V3_Scale(pts[i-1], dot), pts[i-2]);
  142.     }
  143.     bgnline();
  144.     for (i=0; i<=NSEGS; i++)
  145.     v3f((float *)&pts[i]);
  146.     endline();
  147. }
  148.  
  149. /* Draw the arc of a semi-circle defined by its axis. */
  150. void DrawHalfArc(HVect n)
  151. {
  152.     HVect p, m;
  153.     p.z = 0;
  154.     if (n.z != 1.0) {
  155.     p.x = n.y; p.y = -n.x;
  156.     p = V3_Unit(p);
  157.     } else {
  158.     p.x = 0; p.y = 1;
  159.     }
  160.     m = V3_Cross(p, n);
  161.     DrawAnyArc(p, m);
  162.     DrawAnyArc(m, V3_Negate(p));
  163. }
  164.  
  165. /* Draw all constraint arcs. */
  166. void Ball_DrawConstraints(BallData *ball)
  167. {
  168.     ConstraintSet set;
  169.     HVect axis;
  170.     int j, axisI, setSize = ball->setSizes[ball->axisSet];
  171.     if (ball->axisSet==NoAxes) return;
  172.     set = ball->sets[ball->axisSet];
  173.     for (axisI=0; axisI<setSize; axisI++) {
  174.     if (ball->axisIndex!=axisI) {
  175.         if (ball->dragging) continue;
  176.         FARCOLOR();
  177.     } else NEARCOLOR();
  178.     axis = *(HVect *)&set[4*axisI];
  179.     if (axis.z==1.0) {
  180.         circ(0.0, 0.0, 1.0);
  181.     } else {
  182.         DrawHalfArc(axis);
  183.     }
  184.     }
  185. }
  186.  
  187. /* Draw "rubber band" arc during dragging. */
  188. void Ball_DrawDragArc(BallData *ball)
  189. {
  190.     DRAGCOLOR();
  191.     if (ball->dragging) DrawAnyArc(ball->vFrom, ball->vTo);
  192. }
  193.  
  194. /* Draw arc for result of all drags. */
  195. void Ball_DrawResultArc(BallData *ball)
  196. {
  197.     RESCOLOR();
  198.     if (ball->showResult) DrawAnyArc(ball->vrFrom, ball->vrTo);
  199. }
  200.