VTK abstract picker for multiple actors of different opacity value - c++

I am new to VTK. I would like to know how VTK abstract picker behaves for multiple actors of different opacity values. Let's consider two actors, with one
inside another. When I set the opacity of the outer surface to 0.3, while
keeping the opacity of the inner one 1.0.Since the outer one is semi-transparent, I can see the inner actor in the overlap region of the two actors. When I perform picking in that region,the resulting coordinates is from the inner surface itself, and when I pick some point other than the overlap region,I am getting outer surface coordinates. How can I perform picking operation based on opacity values? Such that i want to pick one actor at a time. Anybody please help..

vtkAbstractPicker is, as the name suggest, just as an abstract class that defines interface for picking, but nothing more. When choosing actual pickers, you basically have a choice between picking based on ray casting or "color picking" using graphical hardware (see the linked documentation for actual vtk classes that implement those).
Now to the actual problem, if I understood what you wrote correctly, you are facing a rather simple sorting problem. The opacity can be seen as kind of a priority - the actors with higher opacity should be picked even if they are inside others with lower opacity, right? Then all you need to do is get all the actors that are underneath your mouse cursor and then choose the one with highest opacity, or the closest one for cases when they have the same opacity.
I think the easiest way to implement this is using the vtkPropPicker (vtkProp is a parent class for actor so this is a good picker for picking actors). It is one of the "hardware" pickers, using the color picking algorithm. The basic algorithm is that each pickable object is rendered using a different color into a hidden buffer (texture). This color (which after all is a 32-bit number like any other) serves as an ID of that object: when the user clicks on a screen, you read the color of the pixel from the picking texture on the clicked coordinates and then you simply look into the map of objects under the ID that is equal to that color and you have the object. Obviously, it cannot use any transparency - the individual colors are IDs of the objects, blending them would make them impossible to identify.
However, the vtkPropPicker provides a method:
// Perform a pick from the user-provided list of vtkProps
// and not from the list of vtkProps that the render maintains.
// If something is picked, a 1 is returned, otherwise 0 is returned.
// Use the GetViewProp() method to get the instance of vtkProp that was picked.
int PickProp (double selectionX, double selectionY,
vtkRenderer *renderer, vtkPropCollection *pickfrom);
What you can do with this is simply first call PickProp(mouseClickX, mouseClickY, renderer of your render window, pickfrom) providing only the highest-priority actors in the pickfrom collection i.e. the actors with the highest opacity. Underneath, this will do a render of all the provided actors using the color-coding algorithm and tell you which actor is underneath the specified coordinates. If it picks something (return value is 1, you call GetViewProp on it and it gives you the pointer to your picked actor), you keep it, if it does not (return value is 0), you call it again, this time providing actors with lower opacity and so on until you pick something or you test all the actors.
You can do the same with the ray-casting pickers like vtkPicker as well - it cast a ray underneath your mouse and gives you all intersections with everything in the scene. But the vtkPicker's API is optimized for finding the closest intersection, it might be a bit of work to get all of them and then sorting them and in the end, I believe the solution using vtkPropPicker will be faster anyway.
If this solution is good, you might want to look at vtkHardwareSelector, which uses the same algorithm, but unlike the vtkPropPicker allows you to access the underlying picking texture many times, so that you don't need to re-render for every picking query. Depending on how your rendering pipeline is set up, this might be a more efficient solution (= if you make a lot of picking without updating the scene).

Related

How to handle mouse hovering for object [Allegro5/C++]

I want to be able to register/de-register Objects to a list and check if the mouse is hovering over them to display tool-tips. However I'm stumbling at the beginning.
I'm going to use: al_get_pixel & al_unmap_rgba to retrieve the alpha of each pixel and decide if it's visible enough to count as a hit when hovering over it with the mouse.
The major problem I'm having is working out how best to store this individual "hitmap" & the reference to the object that generated it; As many different types objects (as struct's) of different sizes may need hitmaps generated. I was hoping I could do something similar to checking if the complex object 'extends' the base object but I don't see how I can achieve this in c++.
Ps; I know I could create an array the size of the screen for each object, but I'm doing this mainly with the purpose of maximizing efficiency. I'd make dynamic sized arrays but...
al_get_pixel will work, but it will be terribly slow, even if you lock all your bitmaps, unless you use something like a picking buffer. The basic idea is to render every interactive area on each object with a different color id. This means you need to draw your scene twice, once normally, and once with picking colors. Then when you need to read back a mouse position, you can use the picking buffer to read a single pixel and get its color id.
You might also want to try different methods of collision detection, such as bounding boxes, bounding circles, or other easily collision detectable shapes.
There is a third option, which is pixel perfect collision. It involves making 1bpp masks out of all your objects and then checking for collision between those.

Best way to detect the window coordinates of a drawn line in c++ Builder

Using moveto and lineto to draw various lines on a window canvas...
What is the simplest way to determine at run-time if an object, like a bit map or a picture control is in "contact" (same x,y coordinates) with a line(s) that had been drawn with lineto on a window canvas?
A simple example would be a ball (bitmap or picture) "contacting" a drawn border and rebounding... What is the easiest way to know if "contact" occurs between the object, picture or bitmap and any line that exists on the window?
If I get it right you want collision detection/avoidance between circular object and line(s) while moving. There are more option to do this I know of...
Vector approach
you need to remember all the rendered stuff in vector form too so you need list of all rendered lines, objects etc ... Then for particular object loop through all the other ones and check for collision algebraically with vector math. Like detecting intersection between bounding boxes and then with particular line/polyline/polygon or what ever.
Raster approach
This is simpler to mplement and sometimes even faster but less acurate (only pixel precision). The idea is to clear object last position with background color. Then check all the pixels that would be rendered at new position and if no other than background color present then no colision occurs so you can render the pixels. If any non background color present then render the object on the original position again as collision occur.
You can also check between old and new position and place the object on first non collision position so you are closer to the edge...
This approach need fast pixel access otherwise it woul dbe too slow. Standard Canvas does not allow this without using BitBlt from GDI. Luckily VCL GRaphics::TBitmap has ScanLine[] property allowing direct pixel access without any performance hit if used right. See example of it in your other question I answered:
bitmap rotate using direct pixel access
accessing ScanLine[y][x] is as slow as Pixels[x][y] but you can store all the pointers to each line of bitmap once and then just use that instead which is the same as accessing your own 2D array. So you really need just bitmap->Height calls of ScanLine[y] for entire image rendering after any resize or assigment of bitmap...
If you got tile based scene you can use this approach on tiles instead of pixels something like this:
What is the best way to move an object on the screen? but it is in asm ...
Field approach
This one is also considered to be a vector approach but does not require collision checks. Instead each object creates repulsive force the bigger the closer you are to it which is added to the Newton/D'Alembert physics driving force. When coefficients set properly it will avoid collisions on its own. This is used also for automatic placement of items etc... for more info see:
How to implement a constraint solver for 2-D geometry?
Hybrid approach
You can combine any of the above approaches together to better suite your needs. For example see:
Path generation for non-intersecting disc movement on a plane

How to project/unproject when in an openGL display list

I have openGL code that renders some objects and displays text labels for some of them. Displaying a label is done by projecting the appropriate vertex to the screen using gluProject, and then adding a small offset so the label is beside the vertex. This way each label is the same distance from its vertex on the screen.
I didn't originally use a display list for this (apart from the display lists for the glyphs), and it worked correctly (if somewhat slowly). Now I build a display list for the entire scene, and find that the labels are placed incorrectly.
It took me a while, but I think I have basically found the problem: gluProject takes as parameters the projection matrix, model-view matrix, and the viewport. I see no way to provide them other than calling glGetDoublev(GL_MODELVIEW_MATRIX, ...), etc. But glGet functions are "not allowed" in a display list, which - empirically - seems to mean that they don't cause an error, but rather execute immediately. So the matrix data being compiled into the display list is from list compilation time instead of list execution time (which is a problem because I need to precompile the list, not execute it immediately). At least this is my current theory.
Can anyone confirm or deny that this would cause the problem?
How does one solve this? I just want to do what gluProject does, but using the list's current matrices.
Note: I'm aware that various functions/approaches are deprecated in recent versions of openGL; please spare me answers along the lines of "you shouldn't be doing that" ;-)
Think about it: glGet… places some data in your process memory, possibly on the stack. There is absolutely no way, how a display list could even reproduce the calculations performed on data, that is not even in its reach. Add to this, that GLU (note the U) functions are not part of OpenGL, hence don't make it to the display list. GLU functions also are not GPU accelerated, all the calculations happen on the CPU and due to the API design data transfer is rather inefficient.
Scrunities like those, which as you find out, make display lists rather impractical are among the reasons, why they have been stripped from later versions of OpenGL. Or in other words: Don't use them.
Instead use Vertex Buffer Object and Index Buffers. A labeling system like yours can be implemented using instancing, fed by a list of the target positions. If instancing is not available you need to supply redundant position attributes to the label's vertex attribute vector.
Anyway: In your case making proper use of shaders and VBOs will easily outperform any display list based solution (because you can't display list everything).
Rather odd, but working would be calls to glRasterPos, glBitmap (hence glutBitmap text calls) put in a display list, and the offset applied in the projection matrix before the actual projection mapping, i.e.
glMatrixMode(GL_PROJECITON);
glLoadIdentity();
scene_projection();
draw_scene();
glMatrixMode(GL_PROJECITON);
glLoadIdentity();
glTranslatef(...); /* for the offset */
scene_projection();
draw_labels();
Though this is how I'd have done it 12 years ago. Definitely not today.

An efficient way to draw many OpenGL points in individual Begin-End blocks?

If you begin to render points, render a ton of vertices, and then end, you get noticeably better performance than if you begin points, render a vertex, end, and repeat a ton of times (e.g., redraws during pan and zoom actions for, say, 200,000 points are MUCH smoother).
I guess this might make sense, but it's disappointing. Is there a way to get back the performance while still rendering each point in its own begin-end block?
BACKGROUND:
I wanted to design a control that could contain a ton (upwards of a million in an extreme case) of "objects" that each do its own rendering. Many of these objects will represent themselves as points.
If I let a hundred-thousand points individually render themselves in their own begin-end blocks, I get a major performance hit (as opposed to rendering them all in a single begin-end block). It thus seems I might have to make the container aware of the way the objects render themselves (for example, beginning points, telling everything that needs to render a point to do so, and then ending).
This messes up the independent nature of the display-object relationship I wanted. It also messes up hit testing by selection because I don't think you can add a name to a vertex inside a begin-end block of points, right?
FYI (in case this helps) my project will be displaying a 2D scene (using an ortho projection) and requires hit testing to determine which related object a user might click. In general, the objects will represent "tracks" containing individual points connected with lines. The position data is generally static, but point and track colors and display representations may change due to user settings and selection information. One exception--a "playback" mode may allow the user to see only one track point at a time (the "current" point in the playback) and step through time from one point to the next. However, even in that case I assumed I would simply change which point on each track is actually displayed (at its "static" location) depending on the current time in the playback. If any of that brings to mind further suggestions for an OpenGL newbie, then much thanks!
To solve this issue, I started by using VBOs (which did speed things up). I then allowed my "track" objects to each draw their own set of points as well as the lines connecting the points (each track using two DrawArrays: one for the line strip and one for the points). Each point does not have to draw itself independent of the other points--this was the major performance improvement.
BUT, I still needed hit-testing against the points, so..
Finally, I needed allowed each displayed object (in this case, the tracks) to do its own selection routine so each object can do what it needs for efficient selection. For tracks, they took a two-step process. First, a track names its entire line strip with one name (0) and performs the select. IF that results in a hit, then the track does a second render pass, naming each individual point and line segment to hit-test against each part of the track. This makes hit-testing against each point quite fast.
As an aside, I'm using .Net (C#) for my programming. With it, I created a class (SelectEventArgs) derived from EventArgs to describe selection criteria to objects being displayed. My SelectEventArgs class includes a list meant to be filled with selected objects. The display class then has an EventHandler<SelectEventArgs> event. When an object is added to a display, it subscribes to that event. When the event fires, each object determines whether it's been selected and fills the list of selected objects (in the SelectEventArgs passed in the event) with its information. After the event fires, I can access the list of objects returned in the SelectEventArgs instance to handle the user interaction. I find this to be a nice pattern for creating flexible display objects and selection tools.

OpenGL GL_SELECT or manual collision detection?

As seen in the image
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.
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:
enabling and setting the scissor test to a 1x1 window at the cursor position
drawing the screen with no lighting, texturing and multisampling, 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 scissor 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.
Alternatively, you can create a dedicated framebuffer object with a specific pixel format (like GL_R32UI, or even GL_RG32UI if you need 64 bits) for that.
The above is a nice and quick alternative (both in terms of reliability and in implementation time) for the strict geometric approach.
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
umanga, Cant see how to reply inline... maybe I should sign up :)
First of all I must apologize for giving you the wrong algo - i did the back face culling one. But the one you need is very similar which is why I got confused... d'oh.
Get the camera position to mouse vector as said before.
For each contour, loop through all the coords in pairs (0-1, 1-2, 2-3, ... n-0) in it and make a vec out of them as before. I.e. walk the contour.
Now do the cross prod of those two (contour edge to mouse vec) instead of between pairs like I said before, do that for all the pairs and vector add them all up.
At the end find the magnitude of the resulting vector. If the result is zero (taking into account rounding errors) then your outside the shape - regardless of facing. If your interested in facing then instead of the mag you can do that dot prod with the mouse vector to find the facing and test the sign +/-.
It works because the algo finds the amount of distance from the vector line to each point in turn. As you sum them up and you are outside then they all cancel out because the contour is closed. If your inside then they all sum up. Its actually Gauss's Law of electromagnetic fields in physics...
See:http://en.wikipedia.org/wiki/Gauss%27s_law and note "the right-hand side of the equation is the total charge enclosed by S divided by the electric constant" noting the word "enclosed" - i.e. zero means not enclosed.
You can still do that optimization with the bounding boxes for speed.
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.
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.
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.
The first is easy to implement and widely used.