使用C#在OpenGl中挑选对象

时间:2010-04-08 14:05:39

标签: c# opengl picking

我正在使用C#使用opengl(使用TaoFrame工作),问题是我想画画 屏幕上有2个对象(例如矩形),我的问题的主要目标是,如何按下鼠标按钮以便我可以选择一个对象使其移动。

基本上我只需要知道如何选择一个对象:

关于我的项目的信息:

我正在使用taoframe工作库,opengl视图端口只是主控制窗口中的一个小面板,它不是全屏。

这个函数是主要的opengl绘制函数:

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(); 

}

这个函数是鼠标处理程序:

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";
        }

    }

实际选择Vodo正在这里完成:

    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);
    }

这个函数ProcessHits所以我可以得到对象的名称

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 - ProcessHits函数中的Result值总是1,它更喜欢object1所以如果我按下空间我有对象1,即使没有什么可以选择,所以我错过了一些代码?

2 - select函数中的命中值总是2?我不知道为什么?

1 个答案:

答案 0 :(得分:2)

很简单,你在gluPickMatrix()之后调用glOrtho(),有效地擦除了拾取矩阵并绘制了全帧。这就是为什么总是选择你的控件。

哦,是的,不要使用选择模式,它已被弃用,无论如何这都是一项糟糕的工作。使用gluUnProject()使用光线拾取或使用颜色拾取。