Question

i'm working with opengl using C#(using TaoFrame work ) ,the thing is that i want to draw 2 objects on screen (rectangle for example ),the main goal of my Question is, how to press the mouse button so i can select one object to make it move .

Basically i just need to know how to select one object that's all :

Info about my project :

i'm using taoframe work libraries , the opengl view port is just a small panel in a main control window ,it's not full screen .

this function is the main opengl draw function :

private void draw()        
    {
        //Gl.glInitNames();  is this function invoked here ?
        Gl.glMatrixMode(Gl.GL_PROJECTION);

        GC.Collect();    
        simpleOpenGlControl1_Resize(new object(), new EventArgs());         
        Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
        Gl.glMatrixMode(Gl.GL_MODELVIEW);
        Gl.glLoadIdentity();      // Reset The Current Modelview M


        //Gl.glPushName(table);
        //Gl.glPushName(room);


        Gl.glPushMatrix();
            Gl.glLoadName(table);
                Gl.glTranslatef(-2, 0,-13);
                Gl.glRects(0, 0, 2, 2);

           Gl.glLoadName(obj1);  // obj1 is a const int =1
                Gl.glTranslatef(-5, 0, -13);
                Gl.glRects(0, 0, 2, 2);
        Gl.glPopMatrix();

        simpleOpenGlControl1.Draw(); 

}

this function is the mouse handler :

private void simpleOpenGlControl1_MouseClick(object sender, MouseEventArgs e)
    {
        //this code here is to supposed  to select object from select Function
        if (e.Button == MouseButtons.Left)
        {
            uint selected = Select(e.X, e.Y);
            if (selected == obj1)
                label1.Text = "object 1";
            else if (selected == obj2) 
                label1.Text = " object 2";
            else label1.Text = "nothing";
        }

    }

The Actual select Vodo is being done here :

    public uint Select(int x, int y)
    {
        int[] viewport = new int[4];    //Current Viewport 
        uint[] selectBuf = new uint[512]; // will hold the id's of selected objects
        //1) Get Current Viewport 

        Gl.glGetIntegerv(Gl.GL_VIEWPORT, viewport);
        // 2 , selection buffer and selection mode
        Gl.glSelectBuffer(512, selectBuf); // Assign a selection buffer 
        Gl.glRenderMode(Gl.GL_SELECT); // switch to selection mode 

        Gl.glInitNames(); // Init Name Stack 

        // go ahead and put a name in
        Gl.glPushName(obj1);
        Gl.glPushName(obj2);
        // 4 matrix mode and initialize
        Gl.glMatrixMode(Gl.GL_PROJECTION); // Change Matrix Mode to projection 
        Gl.glPushMatrix(); // Don't disturb other things 
        Gl.glLoadIdentity(); // Reset the axis 

        // 6 - create pick matrix around current point
        // Main function! Thiss make a virtual clipping region with 
        // center x, y and width and height 1 each w.r.t the current viewport.  
        // Note the "viewport[3]-y" parameter instead of y! 
        Glu.gluPickMatrix(
            (double)x, (double)(viewport[3] - y), 
            //Specify the center of a picking region in window coordinates.
            4.0, 5.0, // delx, dely
            viewport // current viewport
            );

        Gl.glOrtho(0.0f, (double)Size.Width, 0.0f, (double)Size.Height, -0.5f, 2.5f);

        //Call our Render function to load object with names. 
        // Note that since our Render mode is GL_SELECT nothing will be drawn 
         // on the screen due to this function call! 

        simpleOpenGlControl1.Draw();

        Gl.glPopMatrix(); // Don't disturb other things 

        //Switch back to default mode! 
        //This time the "glRenderMode" function returns the no. 
        // of objects that were found to be drawn in the clipping region made by glPickMatrix.  
        int hits = Gl.glRenderMode(Gl.GL_RENDER);
        System.Console.WriteLine("Select, number of hits:" + hits.ToString());
        return ProcessHits(hits, selectBuf);
    }

This function ProcessHits so i can get the name of object

private static uint ProcessHits(int hits, uint[] buffer)
    {
        uint i, j;
        uint names;
        uint[] ptr;
        uint result = 666;                       
        Console.WriteLine("ProcessHits  hits = {0}", hits);
        ptr = buffer;
        for (i = 0; i < hits; i++)
        {             // For Each Hit
            names = ptr[i];
            Console.WriteLine(" number of names for hit = {0}", names);
            i++;
            Console.WriteLine(" z1 is {0}", (float)ptr[i] / 0x7fffffff);
            i++;
            Console.WriteLine(" z2 is {0}", (float)ptr[i] / 0x7fffffff);
            i++;
            Console.Write(" the name is ");
            for (j = 0; j < names; j++)
            {           // For Each Name
                Console.Write("{0} ", ptr[i]);
                result = ptr[i]; // if there are multiple selections, this is an ERROR, but at least for the time being, return something
                i++;
            }
            Console.Write("\n");
        }
        Console.Write("\n");

        return result;
    }

1-The Result value in ProcessHits function is always 1 which prefers to object1 so if i press in the space i've got object 1 even though there aint nothing to select, so am i missing some code ? .

2-the hits value in the select function is always 2? i don't know why ?

Was it helpful?

Solution

It is simple, you are calling glOrtho() after gluPickMatrix(), effectively erasing the pick matrix and drawing the full frame instead. That is why your control is always picked.

Oh yeah, don't use selection mode, it's deprecated and it's a terrible piece of work anyway. Use picking by ray using gluUnProject() or use color picking instead.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top