Выбор объектов в OpenGl, используя C # - PullRequest
1 голос
/ 08 апреля 2010

Я работаю с OpenGL, используя C # (используя работу 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";
        }

    }

Фактический выбор Водо делается здесь:

    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-значение Result в функции ProcessHits всегда равно 1, которое предпочитает object1, поэтому, если я нажимаю в пробеле, у меня есть объект 1, хотя там нечего выбирать, так что мне не хватает некоторого кода? .

2 - значение попаданий в функции выбора всегда равно 2? я не знаю почему?

1 Ответ

2 голосов
/ 08 февраля 2012

Это просто, вы вызываете glOrtho () после gluPickMatrix (), эффективно стирая матрицу выбора и вместо этого рисуя полный кадр. Вот почему ваш контроль всегда выбран.

О да, не используйте режим выбора, он устарел и в любом случае это ужасная работа. Используйте выборку лучом, используя gluUnProject (), или используйте выбор цвета вместо этого.

...