0

I am working on an OpenGL project which requires object selection feature. I use OpenTK framework to do this; however OpenTK doesn't support glu.PickMatrix() method to define the picking region. I ended up googling its implementation and here is what i got:

    void GluPickMatrix(double x, double y, double deltax, double deltay, int[] viewport)
    {
        if (deltax <= 0 || deltay <= 0)
        {
            return;
        }

        GL.Translate((viewport[2] - 2 * (x - viewport[0])) / deltax, (viewport[3] - 2 * (y - viewport[1])) / deltay, 0);
        GL.Scale(viewport[2] / deltax, viewport[3] / deltay, 1.0);
    }

I totally fail to understand this piece of code. Moreover, this doesn't work with my following code sample:

    //selectbuffer
    private int[] _selectBuffer = new int[512];

    private void Init()
    {
        float[] triangleVertices = new float[] { 0.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f };
        float[] _triangleColors = new float[] { 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f };

        GL.GenBuffers(2, _vBO);
        GL.BindBuffer(BufferTarget.ArrayBuffer, _vBO[0]);
        GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(sizeof(float) * _triangleVertices.Length), _triangleVertices, BufferUsageHint.StaticDraw);
        GL.VertexPointer(3, VertexPointerType.Float, 0, 0);
        GL.BindBuffer(BufferTarget.ArrayBuffer, _vBO[1]);
        GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(sizeof(float) * _triangleColors.Length), _triangleColors, BufferUsageHint.StaticDraw);
        GL.ColorPointer(3, ColorPointerType.Float, 0, 0);
        GL.EnableClientState(ArrayCap.VertexArray);
        GL.EnableClientState(ArrayCap.ColorArray);

        //Selectbuffer set up
        GL.SelectBuffer(512, _selectBuffer);
    }

    private void glControlWindow_Paint(object sender, PaintEventArgs e)
    {

        GL.Clear(ClearBufferMask.ColorBufferBit);
        GL.Clear(ClearBufferMask.DepthBufferBit);

        float[] eyes = { 0.0f, 0.0f, -10.0f };
        float[] target = { 0.0f, 0.0f, 0.0f };
        Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView(0.785398163f, 4.0f / 3.0f, 0.1f, 100f);  //45 degree = 0.785398163 rads
        Matrix4 view = Matrix4.LookAt(eyes[0], eyes[1], eyes[2], target[0], target[1], target[2], 0, 1, 0);
        Matrix4 model = Matrix4.Identity;
        Matrix4 MV = view * model;

        //First Clear Buffers
        GL.Clear(ClearBufferMask.ColorBufferBit);
        GL.Clear(ClearBufferMask.DepthBufferBit);

        GL.MatrixMode(MatrixMode.Projection);
        GL.LoadIdentity();
        GL.LoadMatrix(ref projection);

        GL.MatrixMode(MatrixMode.Modelview);
        GL.LoadIdentity();
        GL.LoadMatrix(ref MV);


        GL.Viewport(0, 0, glControlWindow.Width, glControlWindow.Height);
        GL.Enable(EnableCap.DepthTest); //Enable correct Z Drawings
        GL.DepthFunc(DepthFunction.Less); //Enable correct Z Drawings
        GL.MatrixMode(MatrixMode.Modelview);

        GL.PushMatrix();
        GL.Translate(3.0f, 0.0f, 0.0f);
        DrawTriangle();
        GL.PopMatrix();

        GL.PushMatrix();
        GL.Translate(-3.0f, 0.0f, 0.0f);
        DrawTriangle();
        GL.PopMatrix();

        //Finally...
        GraphicsContext.CurrentContext.VSync = true; //Caps frame rate as to not over run GPU
        glControlWindow.SwapBuffers(); //Takes from the 'GL' and puts into control
    }

    private void DrawTriangle()
    {
        GL.BindBuffer(BufferTarget.ArrayBuffer, _vBO[0]);
        GL.VertexPointer(3, VertexPointerType.Float, 0, 0);
        GL.EnableClientState(ArrayCap.VertexArray);
        GL.DrawArrays(BeginMode.Triangles, 0, 3);
        GL.DisableClientState(ArrayCap.VertexArray);
    }

    //mouse click event implementation
    private void glControlWindow_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
    {

        //Enter Select mode. Pretend drawing.
        GL.RenderMode(RenderingMode.Select);

        int[] viewport = new int[4];
        GL.GetInteger(GetPName.Viewport, viewport);
        GL.PushMatrix();
        GL.MatrixMode(MatrixMode.Projection);

        GL.LoadIdentity();

        GluPickMatrix(e.X, e.Y, 5, 5, viewport);

        Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView(0.785398163f, 4.0f / 3.0f, 0.1f, 100f);  // this projection matrix is the same as one in glControlWindow_Paint method.

        GL.LoadMatrix(ref projection);
        GL.MatrixMode(MatrixMode.Modelview);

        int i = 0;
        int hits;

        GL.InitNames();

        GL.PushMatrix();
        GL.Translate(3.0f, 0.0f, 0.0f); 
        GL.PushName(i);
        DrawTriangle();
        GL.PopName();
        GL.PopMatrix();

        i++;

        GL.PushMatrix();
        GL.Translate(-3.0f, 0.0f, 0.0f);
        GL.PushName(i);
        DrawTriangle();
        GL.PopName();
        GL.PopMatrix();

        hits = GL.RenderMode(RenderingMode.Render);

        .....hits processing code goes here...

        GL.PopMatrix();

        glControlWindow.Invalidate();
    }

I expect to get only one hit everytime i click inside a triangle, but i always get 2 no matter where i click. I suspect there is something wrong with the implementation of the GluPickMatrix, I haven't figured out yet.

stoney78us
  • 195
  • 2
  • 5
  • 17
  • You might get more than one hit if you click an area with more than one object under that picking matrix. It's then upto you to choose which object to pick or toggle between all the objects with successive clicks. – Ani Oct 29 '13 at 19:01
  • i get that but i specified the picking region that is a 5 pixels square. It should be small enough to avoid picking more than one at the same time. – stoney78us Oct 29 '13 at 19:15
  • I also don't see a call to glInitNames in your code. Are you clearing the stack before rendering all the objects per frame? – Ani Oct 29 '13 at 19:20
  • Good call but it doesn't help much with my situation :(. I read the _selectBuffer content, see the min and max depth values are both -38695660 which is weird. I think they should be both 0.0 since my 2 triangles z values are 0.0 – stoney78us Oct 29 '13 at 19:26

0 Answers0