/// <summary>
 /// For custom OpenGL layers, perform immediate drawing.
 /// </summary>
 /// <param name="pGlobeViewer"></param>
 /// <remarks>This is where you should add your drawings on the Globe. This method must be overridden in 
 /// your inheriting class. DrawImmediate together with IGlobeDisplayEvents::BeforeDraw and  IGlobeDisplayEvents::AfterDraw
 /// is the only safe place where the OpenGL state is ready for custom actions.</remarks>
 public abstract void DrawImmediate(IGlobeViewer pGlobeViewer);
    /// <summary>
    /// This is where the actual drawing takes place.
    /// </summary>
    /// <param name="pGlobeViewer"></param>
    public override void DrawImmediate(IGlobeViewer pGlobeViewer)
    {
      //make sure that the layer is valid, visible and that the main table exists 
      if (!m_bVisible || !m_bValid | null == m_table)
        return;

      
      //get the OpenGL rendering mode
      uint mode;
      unsafe
      {
        int m;
        GL.glGetIntegerv(GL.GL_RENDER_MODE, &m);
        mode = (uint)m;
          //GL.glGetIntegerv(GL.GL_RENDER_MODE, out mode);
        
      }

      //get the OpenGL matrices (required for the viewport filtering and the billboard orientation)
      GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX, m_modelViewMatrix);
      GL.glGetIntegerv(GL.GL_VIEWPORT, m_viewport);
      GL.glGetDoublev(GL.GL_PROJECTION_MATRIX, m_projMatrix);

      //populate the billboard matrix
      m_billboardMatrix[0] = m_modelViewMatrix[0];
      m_billboardMatrix[1] = m_modelViewMatrix[4];
      m_billboardMatrix[2] = m_modelViewMatrix[8];
      m_billboardMatrix[3] = 0;

      m_billboardMatrix[4] = m_modelViewMatrix[1];
      m_billboardMatrix[5] = m_modelViewMatrix[5];
      m_billboardMatrix[6] = m_modelViewMatrix[9];
      m_billboardMatrix[7] = 0;

      m_billboardMatrix[8] = m_modelViewMatrix[2];
      m_billboardMatrix[9] = m_modelViewMatrix[6];
      m_billboardMatrix[10] = m_modelViewMatrix[10];
      m_billboardMatrix[11] = 0;

      m_billboardMatrix[12] = 0;
      m_billboardMatrix[13] = 0;
      m_billboardMatrix[14] = 0;
      m_billboardMatrix[15] = 1;

      ISceneViewer sceneViewer = pGlobeViewer.GlobeDisplay.ActiveViewer;

      //only once, create display lists and do initializations
      if (!m_bDisplayListCreated)
      {
        CreateDisplayLists();
        m_globeDisplay = pGlobeViewer.GlobeDisplay;
      }

      //get the globeViewUtil which allow to convert between the different globe coordinate systems
      m_globeViewUtil = sceneViewer.Camera as IGlobeViewUtil;
      IGlobeViewUtil globeViewUtil = sceneViewer.Camera as IGlobeViewUtil;
      IGlobeAdvancedOptions advOpt = m_globeDisplay.AdvancedOptions;

      //the ClipNear value is required for the viewport filtering (since we don't
      //want to draw an item which is beyond the clipping planes).
      double clipNear = advOpt.ClipNear;

      double dblObsX, dblObsY, dblObsZ, dMagnitude;
      ICamera camera = pGlobeViewer.GlobeDisplay.ActiveViewer.Camera;
      
      //query the camera location in geocentric coordinate (OpenGL coord system)
      camera.Observer.QueryCoords(out dblObsX, out dblObsY);
      dblObsZ = camera.Observer.Z;

      double lat, lon, X = 0.0, Y = 0.0, Z = 0.0;

      //iterate through all the records of the layer, test whether the item is within the 
      //viewport are and draw it onto the globe.
      foreach (DataRow rec in m_table.Rows)
      {

        lat = Convert.ToDouble(rec[3]);
        lon = Convert.ToDouble(rec[4]);
        X = Convert.ToDouble(rec[5]);
        Y = Convert.ToDouble(rec[6]);
        Z = Convert.ToDouble(rec[7]);

        #region get the OGL geocentric coordinates X,Y,Z
        if (X == 0.0 && Y == 0.0 && Z == 0.0)
        {
          //calculate the geocentric coordinates
          globeViewUtil.GeographicToGeocentric(lon, lat, 1000.0, out X, out Y, out Z);

          //write the calculated geocentric coordinate to the table
          lock (m_table)
          {
            rec[5] = X;
            rec[6] = Y;
            rec[7] = Z;
            rec.AcceptChanges();
          }
        }
        #endregion

        //make sure that the item is inside the viewport, otherwise no need to draw it
        if (!InsideViewport(X, Y, Z, clipNear, mode))
          continue;

        //get the distance from the camera to the drawn item.
        //This distance will determine whether to draw the item as a dot or as
        //a full icon.
        m_vector3D.SetComponents(dblObsX - X, dblObsY - Y, dblObsZ - Z);
        dMagnitude = m_vector3D.Magnitude;

        //call the drawing method
        DrawItem(rec, dMagnitude);
      }
    }