Hit detection Example

The following code sets up a very simple hit detection scheme on a rounded box sweep. When you click the mouse on or near the rounded box sweep, the command line displays the text, "Selected," and when you click the mouse anywhere else in the view, the command line displays, "Not selected."

This example uses TBoundsMaker to perform the hit detection. You can also perform hit detection on a 3-D graphic in the following way. See Chapter 19 for more information on scene states, and see Chapter 17 for more information on cameras.

  1. Get the scene state from the drawing port.
  2. Get the camera from the scene state.
  3. Use the camera in the graphic state to project the eight points of the TGBox3D returned by GetGeometricBounds to the 2D plane.
  4. Find the four points out of the eight that form corners of a TGRect that enclose all of the points by testing for minimum and maximum values.
  5. Call the TGRect::Contains function and pass it the TGPoint returned by the MouseDown function to see whether it lies within the TGRect, and therefore, the 3-D graphic.
    1  class THelloWorld : public TDocumentComponentView, public MMouseEventHandler
    2  {
    3      public:
    4      THelloWorld( TGUIBundle* b ) :
    5          TDocumentComponentView( b ),
    6      {
    7          CheckForInitialize();
    8          SetAllocatedArea( TGRect( 0,0, 1000, 1000 ) );
    9  
    10          fGraphic = new TRoundedBox3D( 200, 200, 20 );;
    11      }
    12  
    13      ~THelloWorld()
    14      {
    15  
    16          CheckForFinalize( );
    17          delete fGraphic;
    18      }
    19      void
    20      Initialize()
    21      {
    22          TDocumentComponentView::Initialize();
    23      }
    24      void DrawContents( TGrafPort& thePort ) const
    25      {
    26          TGArea area;
    27          GetAllocatedArea( area );
    28          TFillBundle bundle( new TRGBColor( 1,1,1 ) );
    29          thePort.Draw ( area.GetBounds(), bundle );
    30  
    31          fGraphic->Draw( thePort );
    32      }
    33  
    34      Boolean
    35      MouseDown( TMouseDownEvent& mouseDown )
    36      {
    37          TGPoint selection( mouseDown.GetEventPosition() );
    38          GlobalToLocal( selection  );
    39  
    40          TGrafPort* port = GetGrafPort();
    41  
    42          TBoundsMaker maker;
    43          maker.AccumulateBounds( *fGraphic, port );
    44          TGRect bounds = maker.GetBounds();
    45  
    46          TGArea area( bounds );
    47          GlobalToLocal( area );
    48  
    49          if ( area.Contains( selection ) )
    50              qprintf( "Selected\n" );
    51          else
    52              qprintf( "not selected\n" );
    53  
    54          return( TRUE);
    55      }
    56      VersionDeclarationsMacro( THelloWorld );
    57  
    58      private:
    59          THelloWorld( conts THellowWorld& );
    60          TRoundedBox3D* fGraphic;

Changes to THelloWorld

Line 1: To implement hit detection, you need to mix THelloWorld with
MMouseEventHandler. MMouseEventHandler has a MouseDown function that you implement in lines 40 through 55.

The addition of MMouseEventHandler means that the graphic must be accessible to the MouseDown function.

Lines 10 and 58: The THelloWorld constructor creates the rounded box sweep and stores it in fGraphic. A private field is added to THelloWorld of type TRoundedBox3D.

Line17: A line is added to the destructor to delete fGraphic.

MouseDown function

Lines 34 through 55: The View system calls the MouseDown function when a mouse down event is detected. The mouseDown parameter contains the TGPoint where the mouse down event occurred in global coordinates. The code gets the TGPoint from mouseDown, converts it to local coordinates, gets the bounds of the rounded box sweep, and tests to see whether the TGPoint is contained within the bounds of the rounded box sweep. Since the bounds is a box and the rounded box sweep has rounded corners, there are points close to, but outside of, the rounded box sweep that return True because they are still within the rounded box sweep bounds.

Line 40: Get the drawing port into which the drawing takes place. The port is passed to the TBoundsMaker::AccumulateBounds function.

Lines 42 to 44: Since the TGPoint returned from mouse down is in 2-D coordinates, use TBoundsMaker to return the enclosing TGRect for the graphic, and use the TGRect::Contains function to test whether the TGPoint is contained within the TGRect.

Lines 46 and 47: The bounds returned by TBoundsMaker are in global coordinates (the coordinate system of the CommonPoint application system window). To change the returned bounds to the coordinate system of the view, use the bounds to create an area and pass the area to the TView::GlobalToLocal function.

Line 49: Call the TGArea::Contains functions to test whether the TGPoint is within the bounds.

Line 50: The Invalidate function redraws the view after changes are made. If you adapted this function to change the color of the fill, the Invalidate function redraws the View with the new fill color.

Changes to DrawContents

Lines 24 through 32: To draw the rounded box sweep, you call the Draw function on fGraphic.


[Contents] [Previous] [Next]
Click the icon to mail questions or corrections about this material to Taligent personnel.
Copyright©1995 Taligent,Inc. All rights reserved.

Generated with WebMaker