I use a Vertex buffer object (VBO) to render a large object of about 400K vertices. Rendering performance is amazing.
However, I need to be able to pick vertices from such an object. Is it possible to use the VBO for selection??
Right now I have to render all 400K vertices using the following:
// For all vertices
for (pVertex = v_begin(); v_end(); pVertex++)
{
Point p = pVertex->point();
glPushName(pVertex->id());
glBegin(GL_POINTS);
glVertex3f(p[0], p[1], p[2]);
glEnd();
glPopName();
}
You may or may not be able to use the same data structure that you draw from to draw either using Arrays from the client side, or even by mapping the VBO to client space for intersection checks. More likely (and I would recommend initially) you’ll need to duplicate the data so you have a collision structure on the client side that works separately from the VBO on the GPU.
Start simple with a slow recursive check on the data for collisions, and then get more technical later by feeding the data into something like an Octree, so you can discard large chunks of data to speed up collisions.
In any case this will be faster than picking and direct drawing, as you are doing now.
Ultimately you should be able to merge the two structures in some way, perhaps “fence” the area it’s stored in so that it’s shared between the GPU and CPU, and then save some memory.
This is sort of what I ended up doing. I basically did a Ray-sphere intersection between a ray coming from the camera with the direction of the mouse click and a small sphere around the vertex (I used average smallest edge length / 2 for the radius).
I think my solution is not the most elegant or efficient but selecting vertices now works in real time. Which is way better than the 3 seconds I had to wait for
Here is the pseudo code for my quick, dirty way:
// For all vertices
for (pVertex = v_begin(); v_end(); pVertex++)
{
Point p = pVertex->point();
sphere_o = Vec(p[0], p[1], p[2]); // vertex position
dst = ray_o - sphere_o; // ray_o = ray origin from camera
B = (dst * ray_dir); // ray_dir = ray direction from camera towards the world
C = (dst * dst) - r2;
D = (B*B) - C;
// Do we have an intersection
if (D >= 0)
{
// Make sure we choose the closest to the ray's origin
if(dst.norm() < smallest_distance)
{
vertex_index = pVertex->id();
smallest_distance = dst.norm();
}
}
}