Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm making a windows forms application with opengl view. I need to get the mouse coords converted to the opengl world coords. Well, my Y coord gets converted wrong. It's hard to explain, so here is the video: http://tinypic.com/r/23sal8k/6. I'm constantly pressing left mouse button and the red dot should be where the mouse is(but it isn't). Here is the code:

    private void glview_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            Point worldCoords = convertScreenToWorldCoords(e.X, e.Y);
            shitx = worldCoords.X;
            shity = worldCoords.Y;
        }
    }


    // functions:
    public static Point convertScreenToWorldCoords(int x, int y)
    {
        int[] viewport = new int[4];
        Matrix4 modelViewMatrix, projectionMatrix;
        GL.GetFloat(GetPName.ModelviewMatrix, out modelViewMatrix);
        GL.GetFloat(GetPName.ProjectionMatrix, out projectionMatrix);
        GL.GetInteger(GetPName.Viewport, viewport);
        Vector2 mouse;
        mouse.X = x;
        mouse.Y = viewport[3] - y;
        Vector4 vector = UnProject(ref projectionMatrix, modelViewMatrix, new Size(viewport[2], viewport[3]), mouse);
        Point coords = new Point((int)vector.X, (int)vector.Y);
        return coords;
    }
    public static Vector4 UnProject(ref Matrix4 projection, Matrix4 view, Size viewport, Vector2 mouse)
    {
        Vector4 vec;

        vec.X = 2.0f * mouse.X / (float)viewport.Width - 1;
        vec.Y = -(2.0f * mouse.Y / (float)viewport.Height - 1);
        vec.Z = 0;
        vec.W = 1.0f;

        Matrix4 viewInv = Matrix4.Invert(view);
        Matrix4 projInv = Matrix4.Invert(projection);

        Vector4.Transform(ref vec, ref projInv, out vec);
        Vector4.Transform(ref vec, ref viewInv, out vec);

        if (vec.W > float.Epsilon || vec.W < float.Epsilon)
        {
            vec.X /= vec.W;
            vec.Y /= vec.W;
            vec.Z /= vec.W;
        }

        return vec;
    }
share|improve this question
add comment

3 Answers

I changed

-(vec.Y = 2.0f * mouse.Y / (float)viewport.Height) - 1;

to

-(vec.Y = 2.0f * mouse.Y / (float)viewport.Height) + 1;

and it works.

share|improve this answer
add comment

I have exactly the same problem and have used your code. I think I fixed it fully now.

in ConvertScreenToWorld()
change 
mouse.Y = viewport[3] - y;
to
mouse.Y = y;

in UnProject()
change
vec.Y = -(2.0f * mouse.Y / (float)viewport.Height - 1);
to
vec.Y = 2.0f * mouse.Y / (float)viewport.Height - 1;

then call it like convertScreenToWorldCoords(e.X,ClientRectangle.Height - e.Y);

it's very precise too bye!

share|improve this answer
add comment
up vote 1 down vote accepted

Finally, I got this fixed. I just changed

mouse.Y = viewport[3] - y;

to

mouse.Y = y + (ClientRectangle.Height - glview.Size.Height);

still not very accurate but not very bad.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.