Actually, I’m thinking about making an example (gizmo’s + picking), but that could take some time.
Meanwhile, I will give you some pointers on how to set things up for the picking.
Well I’m not using shaders at all (not really my cup of tea, sorry Craig ); instead, I’m applying the picking color to the vertices (since all of the models in my project are created procedurally).
For loaded models that could be a bit problematic, but as your main concern seems to be to allow users to select proxies for different kinds of objects, setting the vertex colors for those shouldn’t be a problem, right?
Anyway, this is how I use picking colors:
- generate a unique picking color and assign it to the vertices using a GeomVertexWriter;
- set the regular color (to be rendered by the main camera) using NodePath.setColor();
- call setColorOff(), setLightOff() and setRenderModeThickness() for the NodePath whose state you’ll use for picking_camera.setInitialState().
Now about the picking camera itself.
The lens of this camera needs a very small field of view, since it would otherwise be far too imprecise (the picking color of a point relatively far from the cursor would be rendered to the one-pixel buffer, as if that point were directly under the mouse); a value of 0.1 seems to work very well(*). (Smaller values might cause problems due to rounding errors, so be careful.)
Since GeomPoints or GeomLines would only be detected when the picking camera is pointed straight at them (they are culled when outside the frustum, regardless of their render thickness), it would require pixel-perfect clicking to select them, and that is not very user-friendly. To remedy this, bigger culling bounds need to be set (depending on the desired render thickness). A good value for the field of view corresponding to the culling frustum is 1.0, which accommodates a render thickness of about 10 pixels(*).
You can set the FoV and the culling bounds like this:
node = picking_cam.node()
lens = node.getLens()
lens.setFov(1.0) # this defines the size of the culling frustum
cull_bounds = lens.makeBounds()
lens.setFov(0.1) # this defines the size of the viewing frustum
node.setCullBounds(cull_bounds)
(*)Please note that the given values work well with the default FoV of the main camera (40 degrees) and a window size of 800 x 600; other settings might require different values.
Rendering done by the picking camera + texture lookup seems to be fast enough to let it run in a task - useful for highlighting objects and changing cursors on mouseover.
Now I’m off to make that example - wish me luck!