Not logged in, Join Here! or Log In Below:  
 
News Articles Search    
 

 Home / General Programming / picking algorithm like silo selection Account Manager
 
Archive Notice: This thread is old and no longer active. It is here for reference purposes. This thread was created on an older version of the flipcode forums, before the site closed in 2005. Please keep that in mind as you view this thread, as many of the topics and opinions may be outdated.
 
fasteez

May 14, 2005, 11:38 AM

hy,
actually studying computer science, ive to develop a curve modelisation tool.
As id like to make it easy to use, im looking for a way to selection control points easily.
for the moment i can do classic picking "like" in maya or max.

i mean , on each mouse click , i get informations from opengl pipeline that helps me to select what under the mouse if i want.. but this is only an "after-click" thing... id like to be able to highlight the nearest point under my mouse pointer to help user to visualize better.

If its not clear, id like to understand how silo do their selection.. i was really knocked out on my feets because it works even for a complex model in the scene.
the main fact is i cant figure how to make this so interactive ... do they call opengl GL_SELECT mode each time the mouse moves or is their a "tricky" algorithm behind this.

if someone knows anything about things that can help , id be really glad that he gave it here.

thanks in advance , steez.

 
Aardbei

May 14, 2005, 06:44 PM

It's actually very easy and not tricky at all.

Here's a quick and dirty test I did before I implemented it in my own modelling program..
(please don't mind the silly comments :)

Stuff this code into a file, compile, link with libgl, libglu, libglut, a few other (Windows or any other OS) common libraries and execute it.

(NOTE: don't resize the window, there's no resize callback so the highlighting code won't do it's work correctly then).

  1.  
  2. #include <windows.h>
  3. #include <GL/gl.h>
  4. #include <GL/glu.h>
  5. #include <GL/glut.h>
  6.  
  7. #include <math.h>
  8. #include <vector>
  9.  
  10. using namespace std;
  11.  
  12.  
  13. /**
  14.  * In a real world program, you would take the center of each component
  15.  * (ie. vertex, edge, face, object), transform this center coord from
  16.  * world or object space to window space (ie. using gluProject) and
  17.  * then use the resulting 2D coord like we're doing in mousemove(..)
  18.  */
  19.  
  20. class Vertex {
  21. public:
  22.     Vertex(float vx, float vy) : x(vx), y(vy), highlighted(false) {};
  23.    
  24.     float x, y;
  25.     bool  highlighted;
  26. };
  27.  
  28. // The Data
  29. vector<Vertex*>   verts;
  30.  
  31.  
  32.  
  33. void initialize() {
  34.      // Fill up the vector with a bunch of random points within the window
  35.      for (int i=0; i<50; i++) {
  36.          verts.push_back(new Vertex(rand()%400, rand()%400));
  37.      }
  38. }
  39.  
  40.  
  41. void display() {
  42.     // Draw them vertices!
  43.     glClear(GL_COLOR_BUFFER_BIT);
  44.     glLoadIdentity();
  45.    
  46.     // Iterate through the vertices
  47.     vector<Vertex*>::iterator  it;
  48.    
  49.     // Render the points
  50.     for (it=verts.begin(); it!=verts.end(); ++it) {
  51.          glBegin(GL_POINTS);
  52.          
  53.          // Set a nice highlight color
  54.          if ((*it)->highlighted) glColor4f(0.933, 0.847, 0.796, 1);
  55.          else                    glColor4f(0.514, 0.471, 0.443, 1);
  56.          
  57.          // Put the thing on the screen
  58.          glVertex2f((*it)->x, (*it)->y);
  59.          
  60.          glEnd();
  61.     }
  62.    
  63.     // You know..
  64.     glutSwapBuffers();
  65. }
  66.  
  67.  
  68. void passivemotion(int mx, int my) {
  69.     /**
  70.      * The area around each vertex is highlightable within a radius of 20 pixels
  71.      *
  72.      * You could also use a large value like 100000 for an 'unlimited'
  73.      * highlighting area around a vertex.
  74.      */
  75.     float                      closestdist = pow(20, 2);
  76.     Vertex*                    closest     = 0l;
  77.     vector<Vertex*>::iterator  it;
  78.    
  79.     // First, turn off the highlights..
  80.     for (it=verts.begin(); it!=verts.end(); ++it) (*it)->highlighted = false;
  81.  
  82.     // Then, find the vertex that's closest to the mouse position...
  83.     for (it=verts.begin(); it!=verts.end(); ++it) {
  84.        
  85.         // Find the distance between the mouse pos and the component center
  86.         float dist = pow(mx - (*it)->x, 2) + pow(my - (*it)->y, 2);
  87.        
  88.         // If it's close enough, keep a pointer to the current vertex and continue
  89.         // until we run out of vertices
  90.         if (dist < closestdist) {
  91.             closestdist   = dist;
  92.             closest       = (*it);
  93.         }
  94.     }
  95.    
  96.     // Did we find any vertex near the mouse position?
  97.     if (closest) {
  98.         // Yes, we did! Turn on the highlight!
  99.         closest->highlighted = true;
  100.     }
  101.    
  102.    
  103.     // Yeah! Now we can update the window and show off to the user! w00t!
  104.     glutPostRedisplay();    
  105. }
  106.  
  107.  
  108.  
  109.  
  110. int main (int argc, char** argv) {
  111.     // 1) Initialize GLUT
  112.     glutInit(&argc, argv);
  113.     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
  114.     glutInitWindowSize(400, 400);
  115.     glutCreateWindow("Shiny Highlights");
  116.    
  117.     // 2) Initialize this program
  118.     glClearColor(0.392, 0.356, 0.334, 1.0);
  119.     glMatrixMode(GL_PROJECTION);
  120.     glLoadIdentity();
  121.     gluOrtho2D(0, 400, 400, 0);
  122.     glMatrixMode(GL_MODELVIEW);
  123.     glPointSize(6);
  124.     glEnable(GL_POINT_SMOOTH);
  125.     initialize();
  126.    
  127.     // 3) Set the GLUT callbacks
  128.     glutDisplayFunc(display);
  129.     glutPassiveMotionFunc(passivemotion);
  130.    
  131.     // 4) Enter the main loop
  132.     glutMainLoop();
  133.    
  134.     // 5) Exit and let the OS clean up the leaked memory ;)
  135.     return 0;
  136. }
  137.  



As you can probably guess by now, it's also very fast!

For fun, try to add 1500 random vertices instead of 50 and set the highlight area to 100.

 
fasteez

May 15, 2005, 04:41 AM

Oh!

i thought it would not be efficient at all to iterate over all the scene elements because the time needed to find the closest element under the mouse will grow at least linearly over the elements number ( and as you said , i ll need to project each control point from 3D to screenspace so it would take some more calculation ).
someone on cgtalk tell me to subdivide the screenspace into uniform grid ( sort of bins ) in order to iterate less points. it cost some setup time a the beginning, and it requires some logic to re"sort" points that have been tweaked into the right bin ...
i will test both youre ideas.
thanks for your answer , long life to internet :D

 
This thread contains 3 messages.
 
 
Hosting by Solid Eight Studios, maker of PhotoTangler Collage Maker.