views:

106

answers:

7

Greetings all,

As seen in the image

http://oi56.tinypic.com/ifu33k.jpg

I draw set of contours (polygons) as GL_LINE_STRIP. Now I want to select curve(polygon) under the mouse to delete,move..etc in 3D .

I am wondering which method to use:

1.use OpenGL picking and selection. ( glRenderMode(GL_SELECT) )

2.use manual collision detection , by using a pick-ray and check whether the ray is inside each polygon.

Any suggestions,

Thanks in advance.

+1  A: 

The first is easy to implement and widely used.

Hieu Phan
A: 

In the past I've used GL_SELECT to determine which object(s) contributed the pixel(s) of interest and then used computational geometry to get an accurate intersection with the object(s) if required.

Daniel Paull
+1  A: 

Do you expect to select by clicking the contour (on the edge) or the interior of the polygon? Your second approach sounds like you want clicks in the interior to select the tightest containing polygon. I don't think that GL_SELECT after rendering GL_LINE_STRIP is going to make the interior responsive to clicks.

If this was a true contour plot (from the image I don't think it is, edges appear to intersect) then a much simpler algorithm would be available.

Ben Voigt
+4  A: 

I strongly recommend against GL_SELECT. This method is very old and absent in new GL versions, and you're likely to get problems with modern graphics cards. Don't expect it to be supported by hardware - probably you'd encounter a software (driver) fallback for this mode on many GPUs, provided it would work at all. Use at your own risk :)

Let me provide you with an alternative.

For solid, big objects, there's an old, good approach of selection by:

  • setting the viewport to a 1x1 window at the curor position
  • drawing the screen with no lighting and no texturing, assigning an unique solid colour for every "important" entity - this colour will become the object ID for picking
  • calling glReadPixels and retrieving the colour, which would then serve to identify the picked object
  • clearing the buffers, resetting the viewport to the normal size and drawing the scene normally.

This gives you a very reliable "per-object" picking method. Also, drawing and clearing only 1 pixel with minimal per-pixel operation won't really hurt your performance, unless you are short on vertex processing power (unlikely, I think) or have really a lot of objects and are likely to get CPU-bound on the number of draw calls (but then again, I believe it's possible to optimize this away to a single draw call if you could pass the colour as per-pixel data).

The colour in RGB is 3 unsigned bytes, but it should be possible to additionally use the alpha channel of the framebuffer for the last byte, so you'd get 4 bytes in total - enough to store any 32-bit pointer to the object as the colour.

The above is a nice and quick alternative (both in terms of reliability and in implementation time) for the strict geometric approach.

Kos
+2  A: 

I found that on new GPUs, the GL_SELECT mode is extremely slow. I played with a few different ways of fixing the problem.

The first was to do a CPU collision test, which worked, but wasn't as fast as I would have liked. It definitely slows down when you are casting rays into the screen (using gluUnproject) and then trying to find which object the mouse is colliding with. The only way I got satisfactory speeds was to use an octree to reduce the number of collision tests down and then do a bounding box collision test - however, this resulted in a method that was not pixel perfect.

The method I settled on was to first find all the objects under the mouse (using gluUnproject and bounding box collision tests) which is usually very fast. I then rendered each of the objects that have potentially collided with the mouse in the backbuffer as a different color. I then used glReadPixel to get the color under the mouse, and map that back to the object. glReadPixel is a slow call, since it has to read from the frame buffer. However, it is done once per frame, which ends up taking a negligible amount of time. You can speed it up by rendering to a PBO if you'd like.

Giawa

Giawa
+1  A: 

You cant use select if you stay with the lines because you would have to click on the line pixels rendered not the space inside the lines bounding them which I read as what you wish to do.

You can use Kos's answer but in order to render the space you need to solid fill it which would involve converting all of your contours to convex types which is painful. So I think that would work sometimes and give the wrong answer in some cases unless you did that.

What you need to do is use the CPU. You have the view extents from the viewport and the perspective matrix. With the mouse coord, generate the view to mouse pointer vector. You also have all the coords of the contours.

Take the first coord of the first contour and make a vector to the second coord. Make a vector out of them. Take 3rd coord and make a vector from 2 to 3 and repeat all the way around your contour and finally make the last one from coord n back to 0 again. For each pair in sequence find the cross product and sum up all the results. When you have that final summation vector keep hold of that and do a dot product with the mouse pointer direction vector. If its +ve then the mouse is inside the contour, if its -ve then its not and if 0 then I guess the plane of the contour and the mouse direction are parallel.

Do that for each contour and then you will know which of them are spiked by your mouse. Its up to you which one you want to pick from that set. Highest Z ?

It sounds like a lot of work but its not too bad and will give the right answer. You might like to additionally keep bounding boxes of all your contours then you can early out the ones off of the mouse vector by doing the same math as for the full vector but only on the 4 sides and if its not inside then the contour cannot be either.

Redrobes