2010-04-08 14 views
1

Je travaille avec opengl en utilisant C# (en utilisant le travail TaoFrame), la chose est que je veux dessiner 2 objets sur l'écran (rectangle par exemple), l'objectif principal de ma Question est , comment appuyer sur le bouton de la souris pour que je puisse sélectionner un objet pour le faire bouger.Cueillir des objets dans OpenGl, en utilisant C#

Fondamentalement, je veux juste savoir comment sélectionner un objet qui est tout:

infos sur mon projet:

J'utilise les bibliothèques de travail de taoframe, le port de vue opengl est juste un petit panneau dans un fenêtre de contrôle principale, ce n'est pas en plein écran.

cette fonction est la fonction principale de tirage 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(); 

}

cette fonction est le gestionnaire de la souris:

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

    } 

La sélection actuelle Vodo est fait ici:

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

Cette fonction ProcessHits pour que je puisse obtenir le nom de l'objet

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-La valeur de résultat en fonction ProcessHits est toujours 1 qui préfère Object1 si je presse dans l'espace que j'ai l'objet 1 même si Je n'ai rien à sélectionner, alors je manque un peu de code? .

2-la valeur de frappe dans la fonction select est toujours 2? je ne sais pas pourquoi?

Répondre

2

C'est simple, vous appelez glOrtho() après gluPickMatrix(), effaçant ainsi efficacement la matrice de sélection et dessinant la trame entière à la place. C'est pourquoi votre contrôle est toujours choisi. Oh oui, n'utilisez pas le mode sélection, c'est déprécié et c'est quand même un travail terrible. Utilisez picking par rayon en utilisant gluUnProject() ou utilisez la sélection de couleur à la place.