Using setHitCode and setHitDistance

The GraphicsWindow::setHitCode() and GraphicsWindows::setHitDistance() are methods that make it possible to do hit-testing in some otherwise impossible situations. An example of such a situation arises when hit-testing patch regions that consist of bezier spline-based edges.

Sample Code

The patch object (PatchObject) contains bezier spline-based edges which can consist of up to 102 vertices. Since the GraphicsWindow::polyline() function can only plot lines with up to 32 vertices, it is impossible to plot these in a single call to the function. Multiple calls do not return a proper hit-code when using a "window"-type hit region. By using the GraphicsWindows::setHitCode() method, code can properly handle this situation. The code below shows the function in use from the PatchMesh::renderEdge method:

int steps = GetMeshSteps();
int segNum = steps+2;
float fsegNum = (float) (segNum-1);
 
// If steps are too high for GraphicsWindow's buffer,
// we must draw it manually
if((steps + 2) > GW_MAX_VERTS)
{
   Point3 line[2;
   Point3 prev,current(.0f,.0f,.0f);
   BOOLhitAll = TRUE;
   BOOLhitAny = FALSE;
   DWORDhitDist = 0xffffffff;
   for(int terp = 0; terp < segNum; terp++)
   {
     prev = current;
     current = work.InterpCurve3D((float)terp / fsegNum);
     if (terp != 0)
     {
      line[0 = prev;
      line[1 = current;
      gw->clearHitCode();
      gw->polyline(2, line, NULL, NULL, 0, NULL);
      if(gw->checkHitCode())
       {
         hitAny = TRUE;
         if(gw->getHitDistance() < hitDist)
          hitDist = gw->getHitDistance();
       }
      else hitAll = FALSE;
     } 
   }
 
   if(hr && !hr->crossing && hr->type != POINT_RGN)
     gw->setHitCode(hitAll);
   else
     gw->setHitCode(hitAny);
     gw->setHitDistance(hitDist);
}
else
{
   for(int terp = 0; terp < segNum; terp++)
     fixedBuf[terp = work.InterpCurve3D((float) terp / fsegNum);
 
   gw->polyline(steps+2, fixedBuf, NULL, NULL, 0, NULL);
}
 

Note that the GraphicsWindow::polyline() call is preceded by a call to GraphicsWindows::clearHitCode(), and followed by code which checks the hit code, maintaining hitAny and hitAll flags. When all the segments are drawn, the GraphicsWindow::setHitCode() call is made, setting the hit code depending on the hit region type. When the code which called this function checks the hit code, it will contain the proper value. The sample code also keeps track of the closest hit distance and places that into the GraphicsWindow when all line segments are drawn.