How to draw a geographical object on the globe using direct OpenGL plug-in


Summary
OpenGL drawing can be used in two places—GlobeDisplay’s BeforeDraw or AfterDraw event handlers and in CustomGlobeLayers' DrawImmediate method implementations. This topic shows how to draw a geographical object on the globe’s surface using OpenGL in the context of a user-defined command.


Drawing a geographic object on the globe

Do the following steps to draw geographic objects on the globe.
  1. Start Visual Studio. In the Solution Explorer, add a new ArcGIS command. Use the Visual Studio .NET integration development environment (IDE) integration framework to implement a BaseCommand for ArcGlobe and GlobeControl.
  2. Add references to your OpenGL wrapper library, and the ESRI GlobeCore and Analyst 3D assemblies. For more information, see How to get and install an OpenGL wrapper for .NET.
  3. If possible, use the IGlobeHookHelper interface to allow your command to work in the ArcGIS Engine and ArcGlobe applications.
  4. In your class, set a member variable for the IGlobeDisplay, IGlobeViewUtil, and ISceneViewer interfaces. Set an array list to store the input coordinates information. See the following code example:
[C#]
private IGlobeViewUtil m_globeViewUtil = null;
private IGlobeDisplay m_globeDisplay = null;
private ISceneViewer m_sceneViwer = null;
private ArrayList m_array = null;
  1. Declare a structure to store the input coordinate information. See the following code example:
[C#]
private struct GLPoint
{
    public string Name;
    public double geoX;
    public double geoY;
    public double geoZ;
    public double glX;
    public double glY;
    public double glZ;
}
You can use any other data structure, such as ADO.NET DataTable or a HashTable (dependent on the specific requirements).
  1. In the OnCreate method, initialize the ArrayList. See the following code example:
[C#]
m_array = new ArrayList(100);
  1. In the command's OnCreate() method, cache GlobeDisplay, SceneViewer, and GlobeViewUtil, then start listening to Globe’s AfterDraw event. See the following code example:
[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);
The code example in the following steps is implemented inside the OnClick() method.
  1. In the OnClick event handler, open a dialog box and request the input coordinate from the user. The following code example assumes that you have a Windows forms dialog box, InputCoordinateDlg, that allows you to get an input coordinate from the user (longitude, latitude, and altitude):
[C#]
// Open an input dialog box for the user to set the geographic point.       
InputCoordinateDlg dlg = new InputCoordinateDlg();
if (DialogResult.OK != dlg.ShowDialog())
    return ;
  1. Get the geographic point from the dialog box and convert it into a geocentric coordinate (OpenGl’s coordinate system). See the following code example:
[C#]
// Get the geo coordinate from the form.
GLPoint glPnt = new GLPoint();
glPnt.geoX = dlg.Longitude;
glPnt.geoY = dlg.Latitude;
glPnt.geoZ = dlg.Altitude;

// Convert the geopgraphic coordinate into a geocentric (OpenGL) coordinate system.
m_globeViewUtil.GeographicToGeocentric(glPnt.geoX, glPnt.geoY, glPnt.geoZ, out
    glPnt.glX, out glPnt.glY, out glPnt.glY);
  1. Add the new element to the coordinates list. See the following code example:
[C#]
m_array.Add(glPnt);
  1. Refresh the display. See the following code example:
[C#]
// Refresh the display so that the AfterDraw gets called.
m_sceneViwer.Redraw(false);

Implementing the OnAfterDraw event handler

The drawing occurs in the OnAfterDraw event handler. 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).
Do the following steps to implement the OnAfterDraw event handler:
  1. Iterate through the list items.
  2. Draw the list items directly on the globe. See the following code example:
[C#]
public void OnAfterDraw(ISceneViewer pViewer)
{
    foreach (GLPoint p in m_array)
    {
        GL.glPointSize(10.0f);
        GL.glColor3ub(0, 255, 0);
        GL.glBegin(GL.GL_POINTS);
        GL.glVertex3f((float)p.glX, (float)p.glY, (float)p.glZ);
        GL.glEnd();
    }
}


See Also:

How to draw mouse feedback on the globe using direct OpenGL plug-in
Sample: RSS weather 3D layer
How to get and install an OpenGL wrapper for .NET
Implementing custom globe layers with dynamic feed




Additional Requirements
  • It is assumed that you have an OpenGL wrapper library (such as CsGL) that allows you to make the OpenGL calls.
  • This topic assumes that you are familiar with the C# programming language, have basic OpenGL programming knowledge, and knowledge of creating commands and tools for ArcGIS Engine and ArcGIS for Desktop.

Development licensing Deployment licensing
Engine Developer Kit Engine: 3D Analyst
ArcGIS for Desktop Basic: 3D Analyst ArcGIS for Desktop Basic: 3D Analyst
ArcGIS for Desktop Standard: 3D Analyst ArcGIS for Desktop Standard: 3D Analyst
ArcGIS for Desktop Advanced: 3D Analyst ArcGIS for Desktop Advanced: 3D Analyst