How to draw mouse feedback on the globe using direct OpenGL plug-in


SummaryOpenGL drawing can be used in GlobeDisplay’s BeforeDraw or AfterDraw event handlers and in CustomGlobeLayers’ DrawImmediate method implementations. This article shows you how to draw mouse feedback on the globe using OpenGL in the context of a user-defined tool.

Development licensing Deployment licensing
Engine Developer Kit Engine Runtime: 3D
ArcView: 3D Analyst ArcView: 3D Analyst
ArcEditor: 3D Analyst ArcEditor: 3D Analyst
ArcInfo: 3D Analyst ArcInfo: 3D Analyst

Additional Requirements
  • OpenGL wrapper library (such as CsGL) that enables you to make the OpenGL calls.
  • ArcGIS Visual Studio IDE Integration Framework installed on your machine. This is installed with a typical install of the ArcGIS .NET SDKs.

Drawing mouse feedback on the globe

This article assumes you are familiar with the following:
 
For a working sample of this document's content, please see Globe digitize tool.
 
  1. In Visual Studio's Solution Explorer, add a new ArcGIS tool. Use the Visual Studio .NET IDE integration framework to implement a BaseTool for ArcGlobe and GlobeControl. 
  2. Add references to your OpenGL wrapper library and to the ESRI GlobeCore and Analyst3D assemblies. For more information, see How to get and install an OpenGL wrapper for .NET.
  3. In your class, set member variables for the IGlobeDisplay, IGlobeViewUtil, and ISceneViewer interfaces. In addition, set member variables to store the mouse coordinates, as well as a Boolean flag that indicates whether the mouse key is pressed down. See the following code:
 

[C#]
private IGlobeViewUtil       m_globeViewUtil       = null;
private IGlobeDisplay        m_globeDisplay         = null;
private ISceneViewer       m_sceneViwer          = null;
private int                      m_srcX;
private int                      m_srcY;
private bool                    m_bDrawPoint          = false;
  1. In the Tool OnClick() event handler method, cache GlobeDisplay, SceneViewer, and GlobeViewUtil, and then start listening to the Globe’s AfterDraw event. See the following code:

[C#]
m_globeViewUtil = m_globeHookHelper.Camera as IGlobeViewUtil;

m_globeDisplay = m_globeHookHelper.GlobeDisplay;
m_sceneViwer = m_globeHookHelper.ActiveViewer;
//Start listening to globe display events.
((IGlobeDisplayEvents_Event)m_globeDisplay).AfterDraw += new IGlobeDisplayEvents_AfterDrawEventHandler(OnAfterDraw);
  1. Get the mouse coordinates and switch into tracking mode in the OnMouseDown event handler.
  2. Call Redraw so that the OnAfterDraw method is called and draws the mouse position on the globe. See the following code:

[C#]
public override void OnMouseDown(int Button, int Shift, int X, int Y)
  {
    m_srcX = X;
    m_srcY = Y;

    //Switch into tracking mode.
    m_bDrawPoint = true;

    //Refresh the display so that the AfterDraw gets called.
    m_sceneViwer.Redraw(false);
}
  1. Repeat the steps for the OnMouseMove event handler, except this time test whether tracking mode is in effect. See the following code:

[C#]
public override void OnMouseMove(int Button, int Shift, int X, int Y)
{
    //If not in tracking mode, just return.
    if (false == m_bDrawPoint)
      return;

    //Cache the coordinates since they are needed for the AfterDraw.
    m_srcX = X;
    m_srcY = Y;

    //Refresh the display so that AfterDraw is called.
    m_sceneViwer.Redraw(false);
} 
  1. In the OnMouseUp event handler, switch off tracking mode to stop drawing the mouse location. See the following code:

[C#]
public override void OnMouseUp(int Button, int Shift, int X, int Y)
{
    //Switch off tracking mode.
    m_bDrawPoint = false;

    //Refresh the display so that AfterDraw is called.
    m_sceneViwer.Redraw(false);
}

Implementing OnAfterDraw event handler

The actual drawing takes place in the OnAfterDraw event handler. In fact, the AfterDraw and BeforeDraw events are the only place where you are guaranteed to safely make OpenGL calls (the OpenGL state is ready for the custom calls).
  
  1. Scroll down to the OnAfterDraw method. See the following code:   

[C#]
public void OnAfterDraw(ISceneViewer pViewer)
{

}
  1. Inside the OnAfterDraw method, use IGlobeViewUtil to convert from window coordinates into geocentric coordinates (used by OpenGL). See the following code:

[C#]
double glX, glY, glZ;
m_globeViewUtil.WindowToGeocentric(m_globeDisplay, 
                                      m_sceneViwer, 
                                      m_srcX, 
                                      m_srcY, 
                                      true,
                                      out glX, 
                                      out glY, 
                                      out glZ);
  1. Once you have converted the geographical coordinate into a geocentric coordinate system, draw the OpenGL point. See the following code:

[C#]
//Draw the converted point on the surface of the globe.
GL.glPointSize(15.0f);
GL.glColor3ub(255, 0, 0);
GL.glBegin(GL.GL_POINTS);
   GL.glVertex3f((float)glX, (float)glY, (float)glZ);
GL.glEnd();


See Also:

How to get and install an OpenGL wrapper for .NET
Globe digitize tool