home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / sphigs / sph_dos.lha / dos / sphsrc.v08 / sph_input.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-26  |  9.6 KB  |  428 lines

  1. #include "HEADERS.h"
  2. #include  "sphigslocal.h"
  3.  
  4.  
  5. static void ConvertLocatorMeasure 
  6.    (locator_measure *lm, srgp__locator_measure *slm)
  7. {
  8.    register i;
  9.  
  10.    /* SIMPLY COPY THE PORTIONS THAT NEED NO CONVERSION */
  11.    bcopy (slm->button_chord, lm->button_chord, sizeof(slm->button_chord));
  12.    slm->button_of_last_transition = lm->button_of_last_transition;
  13.  
  14.    /* TRANSLATE srgp/pdc TO npc */
  15.    lm->position[X] = (double)(slm->position.x) / SPH_ndcSpaceSizeInPixels;
  16.    lm->position[Y] = (double)(slm->position.y) / SPH_ndcSpaceSizeInPixels;
  17.    lm->position[Z] = 0.0;
  18.  
  19.    /* FIND THE RELEVANT VIEW INDEX:
  20.       I will give higher-indexed views first priority, but ignore any
  21.       views that have nothing posted to them.
  22.       But, 0 will be returned if nothing else fits the bill. */
  23.    for (i=MAX_VIEW_INDEX; i>=0; i--)
  24.       if (GEOM_ptInRect(slm->position, SPH_viewTable[i].pdc_viewport))
  25.      if (SPH_viewTable[i].highestOverlapNetwork)
  26.         break;
  27.    lm->view_index = i;
  28. }
  29.  
  30.  
  31.  
  32. void SPH_getLocator (locator_measure* lm)
  33. {
  34.    srgp__locator_measure slm;
  35.  
  36.    SRGP_getLocator (&slm);
  37.    ConvertLocatorMeasure (lm, &slm);
  38. }
  39.  
  40.  
  41.  
  42. void SPH_sampleLocator (locator_measure* lm)
  43. {
  44.    srgp__locator_measure slm;
  45.  
  46.    SRGP_sampleLocator (&slm);
  47.    ConvertLocatorMeasure (lm, &slm);
  48. }
  49.  
  50. void SPH_setLocatorMeasure (point position)
  51. {
  52.    srgp__point spt;
  53.    register i;
  54.  
  55.    /* TRANSLATE npc TO srgp/pdc */
  56.    spt.x = position[X] * SPH_ndcSpaceSizeInPixels;
  57.    spt.y = position[Y] * SPH_ndcSpaceSizeInPixels;
  58.  
  59.    SRGP_setLocatorMeasure (spt);
  60. }
  61.  
  62.  
  63. void SPH_setKeyboardEchoOrigin (point position)
  64. {
  65.    srgp__point spt;
  66.    register i;
  67.  
  68.    /* TRANSLATE npc TO srgp/pdc */
  69.    spt.x = position[X] * SPH_ndcSpaceSizeInPixels;
  70.    spt.y = position[Y] * SPH_ndcSpaceSizeInPixels;
  71.  
  72.    SRGP_setKeyboardEchoOrigin (spt);
  73. }
  74.  
  75.  
  76. /** CORRELATION ROUTINES
  77. **/
  78.  
  79. static srgp__rectangle epsilonSquare;
  80.  
  81.  
  82. static int Outcode (srgp__point pt)
  83. {
  84.    int outcode;
  85.  
  86.    if (pt.x > epsilonSquare.top_right.x)
  87.       outcode = 2;
  88.    else if (pt.x < epsilonSquare.bottom_left.x)
  89.       outcode = 1;
  90.    else
  91.       outcode = 0;
  92.  
  93.    if (pt.y > epsilonSquare.top_right.y)
  94.       outcode += 8;
  95.    else if (pt.y < epsilonSquare.bottom_left.y)
  96.       outcode += 4;
  97.  
  98.    return outcode;
  99. }
  100.  
  101.  
  102. static boolean IsPowerOfTwo[] = {
  103.    FALSE,        /*  0 */
  104.    TRUE,        /*  1 */
  105.    TRUE,        /*  2 */
  106.    FALSE,        /*  3 */
  107.    TRUE,        /*  4 */
  108.    FALSE,        /*  5 */
  109.    FALSE,        /*  6 */
  110.    FALSE,        /*  7 */
  111.    TRUE,        /*  8 */
  112.    FALSE,        /*  9 */
  113.    FALSE,        /* 10 */
  114.    FALSE,        /* 11 */
  115.    FALSE,        /* 12 */
  116.    FALSE,        /* 13 */
  117.    FALSE,        /* 15 */
  118.    TRUE            /* 16 */
  119. };
  120.  
  121.  
  122.  
  123.  
  124. static boolean
  125. LineCrossesEpsilonSquare (srgp__point pt1, srgp__point pt2)
  126. {
  127.    enum {UNKNOWN, YES, NO} doesCross = UNKNOWN;
  128.    int outcode1, outcode2;
  129.  
  130.  
  131.    do {
  132.       outcode1 = Outcode (pt1);
  133.       outcode2 = Outcode (pt2);
  134.  
  135.       if ((outcode1 & outcode2) > 0) 
  136.      doesCross = NO;
  137.       else if ((outcode1==0) || (outcode2==0)) 
  138.      doesCross = YES;
  139.       else if ((IsPowerOfTwo[outcode1]) && (IsPowerOfTwo[outcode2])) {
  140.      if ((outcode1 ^ outcode2) == 3)
  141.         doesCross = YES;
  142.      else if ((outcode1 ^ outcode2) == 12)
  143.         doesCross = YES;
  144.       }
  145.  
  146.       if (doesCross == UNKNOWN) {
  147.      if ((outcode1 & 8) != 0) {
  148.         pt1.x += ((pt2.x-pt1.x)*(epsilonSquare.top_right.y-pt1.y))/
  149.            (pt2.y-pt1.y);
  150.         pt1.y = epsilonSquare.top_right.y;
  151.      }
  152.      else if ((outcode1 & 4) != 0) {
  153.         pt1.x += ((pt2.x-pt1.x)*(epsilonSquare.bottom_left.y-pt1.y))/
  154.            (pt2.y-pt1.y);
  155.         pt1.y = epsilonSquare.bottom_left.y;
  156.      }
  157.      else if ((outcode1 & 2) != 0) {
  158.         pt1.y += ((pt2.y-pt1.y)*(epsilonSquare.top_right.x-pt1.x))/
  159.            (pt2.x-pt1.x);
  160.         pt1.x = epsilonSquare.top_right.x;
  161.      }
  162.      else if ((outcode1 & 1) != 0) {
  163.         pt1.y += ((pt2.y-pt1.y)*(epsilonSquare.bottom_left.x-pt1.x))/
  164.            (pt2.x-pt1.x);
  165.         pt1.x = epsilonSquare.bottom_left.x;
  166.      }
  167.       }
  168.    }
  169.    while (doesCross == UNKNOWN);
  170.  
  171.    return (doesCross == YES);
  172. }
  173.       
  174.  
  175.  
  176. static boolean 
  177. PtInPolygon (int vertcount, vertex_index *vertindexlist, srgp__point *verts)
  178. {
  179.    int hitcount = 0;
  180.    int codecur, codeprev, codeLOOK;
  181.    int jcur, jprev;
  182.    double m, b;
  183.    srgp__point ptcur, ptprev;
  184.    register i;
  185.  
  186.  
  187.    jcur = 0;
  188.    ptcur = verts[vertindexlist[jcur]];
  189.    codecur = Outcode (ptcur);
  190.  
  191.    for (i=1; i<=vertcount; i++) {
  192.       jprev = jcur;
  193.       codeprev = codecur;
  194.       ptprev = ptcur;
  195.       
  196.       if (i==vertcount)
  197.      jcur = 0;
  198.       else
  199.      jcur = i;
  200.       
  201.       ptcur = verts[vertindexlist[jcur]];
  202.       codecur = Outcode (ptcur);
  203.  
  204.       /* FIRST, CHECK FOR SPECIAL CASE OF A VERTEX ON THE RAY ITSELF. */
  205.       if ((codecur == 2) || (codeprev == 2)) {     /* if  *on* the ray! */
  206.      if (ptcur.y < ptprev.y)
  207.         codeLOOK = codecur;
  208.      else
  209.         codeLOOK = codeprev;
  210.      if ((codeLOOK == 2) && (codecur != codeprev))
  211.         hitcount++;
  212.  
  213.      continue;   /* don't go into the switch statement */
  214.       }
  215.       
  216.       switch (codecur & codeprev) {
  217.        case 1:
  218.        case 4:
  219.        case 5:
  220.        case 6:
  221.        case 8:
  222.        case 9:
  223.        case 10:
  224.      /* TRIVIAL REJECT */
  225.      break;
  226.        case 2:
  227.      /* TRIVIAL ACCEPT */
  228.      hitcount++;
  229.      break;
  230.        default:
  231.      if (((codecur | codeprev) & 3) == 0) {
  232.         /* THE prev->cur LINE ACTUALLY PASSES THROUGH THE pdcpt !!! */
  233.         /* IGNORE IT!!! */
  234.      }
  235.      else {
  236. #           define pdcpt   (epsilonSquare.bottom_left)
  237.         m = ((double)ptprev.y-ptcur.y) / ((double)ptprev.x-ptcur.x);
  238.         b = (double)ptprev.y - (m*ptprev.x);
  239.         if ( (((double)pdcpt.y - b) / m ) >= (double)pdcpt.x)
  240.            hitcount++;
  241. #           undef pdcpt
  242.      }
  243.       }
  244.    }
  245.    
  246.    return ((hitcount % 2) == 1);
  247. }
  248.  
  249.  
  250.  
  251.       
  252.  
  253.  
  254. static boolean 
  255. PtOnPolygon (int vertcount, vertex_index *vertindexlist, srgp__point *verts)
  256. {
  257.    int jcur, jprev;
  258.    srgp__point ptcur, ptprev;
  259.    register i;
  260.  
  261.  
  262.    jcur = 0;
  263.    ptcur = verts[vertindexlist[jcur]];
  264.  
  265.    for (i=1; i<=vertcount; i++) {
  266.       jprev = jcur;
  267.       ptprev = ptcur;
  268.       
  269.       if (i==vertcount)
  270.      jcur = 0;
  271.       else
  272.      jcur = i;
  273.       
  274.       ptcur = verts[vertindexlist[jcur]];
  275.  
  276.       if (LineCrossesEpsilonSquare (ptcur, ptprev))
  277.      return TRUE;
  278.    }
  279.  
  280.    return FALSE;
  281. }
  282.  
  283.  
  284.  
  285.  
  286.  
  287.  
  288. static boolean hit_was_made;
  289. static unsigned short cur_traversal_index, hit_traversal_index;
  290. static pickInformation *INFO;
  291.  
  292.  
  293.  
  294.  
  295. static boolean TraverseStruct (int structID)
  296. {
  297.    register element *curel;
  298.  
  299.    pickPathItem *curpitem = &(INFO->path[INFO->pickLevel++]);
  300.  
  301.    curpitem->structureID = structID;
  302.    curpitem->elementIndex = 0;
  303.    curpitem->pickID = 0;
  304.  
  305.    for /* FOR EACH ELEMENT IN THE STRUCTURE, IN ORDER: */
  306.       (curel = SPH__structureTable[structID].first_element;
  307.        curel;
  308.        curel = curel->next) {
  309.      curpitem->elementIndex++;
  310.      switch (curel->type) {
  311.       case ELTYP__PICK_ID:
  312.         curpitem->pickID = curel->data.value;
  313.         break;
  314.       case ELTYP__POLYHEDRON:
  315.       case ELTYP__FILL_AREA:
  316.         if (cur_traversal_index++ == hit_traversal_index) {
  317.            /******* !!!!!!!!!!!! C O R R E L A T I O N !!!!!!!!!!!! ******/
  318.            SRGP_beep();
  319.            curpitem->elementType = curel->type;
  320.            return TRUE;
  321.         }
  322.         break;
  323.       case ELTYP__EXECUTE_STRUCTURE:
  324.         if (TraverseStruct (curel->data.value)) {
  325.            curpitem->elementType = curel->type;
  326.            return TRUE;
  327.         }
  328.      }
  329.       }
  330.  
  331.    /* Well, we didn't make a correlate happen in this structure! */
  332.    INFO->pickLevel--;
  333.    return FALSE;
  334. }
  335.  
  336.  
  337.  
  338.  
  339.  
  340. void SPH_pickCorrelate (point npc_position, int viewindex, 
  341.             pickInformation *pickinfo)
  342. {
  343.    srgp__point pdcpoint;
  344.    register obj *curobj;
  345.    root_header *root;
  346.    view_spec *vs = &(SPH_viewTable[viewindex]);
  347.    boolean (*correlator)();
  348.  
  349.  
  350.    /* IF THE POINT IS OUTSIDE ALL KNOWN VIEWPORTS */
  351.    if (viewindex < 0) {
  352.       pickinfo->pickLevel = 0;
  353.       return;
  354.    }
  355.       
  356.    
  357.    if (vs->obsolete_object_list || vs->obsolete_pdc_vertices)
  358.       SPH__error (ERR_PICK_CORR_WITH_UNSYNCH_DISPLAY);
  359.  
  360.    if (vs->rendermode == WIREFRAME_RAW)
  361.       SPH__error (ERR_PICK_CORR_WITH_WIRE_RAW);
  362.  
  363.  
  364.    /********* CONVERT NPC PICK POINT TO srgp COORDS. */
  365.    pdcpoint.x = npc_position[X] * SPH_ndcSpaceSizeInPixels;
  366.    pdcpoint.y = npc_position[Y] * SPH_ndcSpaceSizeInPixels;
  367.  
  368.    /********* SET THE EPSILON SQUARE STATIC
  369.     The way it is set depends upon the type of correlation that will be done:
  370.     for PtInPolygon, it should be a square of 0 area. */
  371.    epsilonSquare.bottom_left = pdcpoint;
  372.    epsilonSquare.top_right = pdcpoint;
  373.    correlator = PtInPolygon;
  374.    if (vs->rendermode == WIREFRAME) {
  375.       epsilonSquare.bottom_left.x--;
  376.       epsilonSquare.bottom_left.y--;
  377.       epsilonSquare.top_right.x++;
  378.       epsilonSquare.top_right.y++;
  379.       correlator = PtOnPolygon;
  380.    }
  381.  
  382.  
  383.    /********** FIRST, SCAN BACKWARDS THROUGH THE OBJECT LIST. 
  384.      Optimization bug!  We can't scan backwards, because the object
  385.      list currently is singly linked.  All I can do is scan forwards
  386.      and I have to examine EVERYTHING in the list unconditionally!
  387.      */
  388.    hit_was_made = FALSE;   /* ...until proven guilty */
  389.  
  390.    for (curobj = vs->objects;
  391.     curobj != NULL;
  392.     curobj = curobj->next) {
  393.       if (correlator
  394.           (curobj->data.face.numPoints,
  395.           curobj->data.face.points,
  396.           vs->pdcVertices)) {
  397.      /********** !!!!!!!!!!!  H I T !!!!!!!!!!!!! ************/
  398.      hit_was_made = TRUE;
  399.      hit_traversal_index = curobj->traversal_index;
  400.       }
  401.    }
  402.  
  403.  
  404.    if (FALSE == hit_was_made) {
  405.       pickinfo->pickLevel = 0;
  406.       return;
  407.    }
  408.  
  409.  
  410.    /***** NOW, WE KNOW THE UNIQUE TRAVERSAL INDEX OF THE PRIMITIVE SELECTED.
  411.      We must traverse the network speedily (honoring only the
  412.      execution elements) looking for the primitive having that index, keeping
  413.      a stack with the pick information in it.
  414.      */
  415.  
  416.    cur_traversal_index = 0;
  417.    INFO = pickinfo;
  418.  
  419.    for
  420.       (root = vs->lowestOverlapNetwork;
  421.        root != NULL;
  422.        root = root->nextHigherOverlapRoot) {
  423.      INFO->pickLevel  = 0;
  424.      if (TraverseStruct (root->root_structID))
  425.         break;
  426.       }
  427. }
  428.