title: How do I make opengl objects appear on mouse click?
body: <p>What I need to do is click somewhere on my OpenGL viewport and have an object render in that spot. I already know the basic stuff, i.e. creating the window, detecting mouse clicks, getting the click coordinates and draw objects. The missing link I have is getting the coordinates right. I need to determine what the (X,Y) point I click on the screen means openGL world coordinates. I am aware of a GLUT function called gluUnProject, but due to technical reasons I can't use GLUT. I've checked many algorithms to make my own unproject function by hand:</p>
  
  <p><a href="http://schabby.de/picking-opengl-ray-tracing/" rel="nofollow noreferrer">http://schabby.de/picking-opengl-ray-tracing/</a>
  <a href="http://collagefactory.blogspot.mx/2010/03/gluunproject-source-code.html" rel="nofollow noreferrer">http://collagefactory.blogspot.mx/2010/03/gluunproject-source-code.html</a>
  <a href="https://stackoverflow.com/questions/7692988/opengl-math-projecting-screen-space-to-world-space-coords-solved">OpenGL Math - Projecting Screen space to World space coords</a></p>
  
  <p>And others, but none worked, when I clicked on the screen the object was drawn in weird places. I'm not even sure what I'm looking for here, I don't know if what I'm trying to implement is Picking, or Raycasting or Raypicking or something else.  Does anyone know the algorithm I'm looking for?</p>
  
  <p>EDIT:
  I'm adding a screen capture, I marked the spot where I clicked and, as you can see, the sphere is drawing in a different place.
  <a href="http://img23.imageshack.us/img23/4738/proofxd.jpg" rel="nofollow noreferrer">http://img23.imageshack.us/img23/4738/proofxd.jpg</a>
  I'm also adding my opengl source code:</p>
  
  <pre><code>    /**OPENGL**/
      private void GLC_display_Load(object sender, EventArgs e)
      {
          //CONTEXT
          GL.ClearColor(Color.LightGray);
          GL.Enable(EnableCap.Texture2D);
          GL.Enable(EnableCap.Blend);
          GL.Enable(EnableCap.DepthTest);
          GL.Enable(EnableCap.CullFace);
          GL.CullFace(CullFaceMode.Back);
          GL.Enable(EnableCap.Blend);
          GL.DepthFunc(DepthFunction.Always);     
          GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
          GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest); 
          SetupViewport();
      }
  
  
      private void SetupViewport()
      {
          GL.Clear(ClearBufferMask.ColorBufferBit);
          GL.ShadeModel(ShadingModel.Smooth);
          float aspectRatio = (float)GLC_display.Width / (float)GLC_display.Height;
          GL.Viewport(0, 0, GLC_display.Width, GLC_display.Height);
          GL.MatrixMode(MatrixMode.Projection);
          GL.LoadIdentity();
          OpenTK.Matrix4 perspective = OpenTK.Matrix4.CreatePerspectiveFieldOfView((float)(System.Math.PI / 4f), aspectRatio, 0.1f, 2000f);
          GL.MultMatrix(ref perspective);
          GL.MatrixMode(MatrixMode.Modelview);
          GL.LoadIdentity();
      }
  
      private void GLC_display_Resize(object sender, EventArgs e)
      {
          SetupViewport();
          GLC_display.Invalidate();
      }
  
      private void GLC_display_Paint(object sender, EventArgs e)
      {
  
          GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
          Matrix4 lookat = Matrix4.LookAt(posVector, eyeVector, Vector3.UnitY);
          GL.MatrixMode(MatrixMode.Modelview);
          GL.LoadMatrix(ref lookat);
          GL.Color3(Color.Red);
          //GL.PushMatrix();
          //GL.Translate(new Vector3(10f,3f,5f));
          //Geometry.drawSphere(5, 20);
          //GL.PopMatrix();
  
          foreach (Vector3 coord in clicks)
          {
              Console.WriteLine("List: "+coord.ToString());
              //GL.Color3(0f, 1f, 0f);
              GL.PushMatrix();
              GL.Translate(coord);
              Geometry.drawSphere(5, 20);
              GL.PopMatrix();
          }
          GLC_display.SwapBuffers();
      }
  
      public Vector3 unProjectInput(Vector2 mouse)
      {
          Vector4 result;
          int[] view = new int[4];
          GL.GetInteger(GetPName.Viewport, view);
  
          mouse.Y = view[3] - mouse.Y;
          result.X = (2f*((float)(mouse.X - view[0])/view[2])) - 1f;
          result.Y = (2f*((float)(mouse.Y - view[1]) / view[3])) - 1f;
          result.Z = 0f;
          result.W = 1f;
  
          double[] projection = new double[16];
          GL.GetDouble(GetPName.ProjectionMatrix, projection);
          Matrix4 Projection = new Matrix4((float)projection[0], (float)projection[1], (float)projection[2], (float)projection[3],
                                                     (float)projection[4], (float)projection[5], (float)projection[6], (float)projection[7],
                                                     (float)projection[8], (float)projection[9], (float)projection[10], (float)projection[11],
                                                     (float)projection[12], (float)projection[13], (float)projection[14], (float)projection[15]);
          double[] modelViewMatrix = new double[16];
          GL.GetDouble(GetPName.ModelviewMatrix, modelViewMatrix);
          Matrix4 MV = new Matrix4((float)modelViewMatrix[0], (float)modelViewMatrix[1], (float)modelViewMatrix[2], (float)modelViewMatrix[3],
                                                     (float)modelViewMatrix[4], (float)modelViewMatrix[5], (float)modelViewMatrix[6], (float)modelViewMatrix[7],
                                                     (float)modelViewMatrix[8], (float)modelViewMatrix[9], (float)modelViewMatrix[10], (float)modelViewMatrix[11],
                                                     (float)modelViewMatrix[12], (float)modelViewMatrix[13], (float)modelViewMatrix[14], (float)modelViewMatrix[15]);
  
          Matrix4 iMVP = Matrix4.Invert(Matrix4.Mult(MV, Projection));
          result = Vector4.Transform(result, iMVP);
  
          if (result.W &gt; float.Epsilon || result.W &lt; float.Epsilon)
          {
              result.X /= result.W;
              result.Y /= result.W;
              result.Z = 0f;
              //result.Z /= result.W;
          }
  
          return result.Xyz;
      }
  </code></pre>