Closed mshoe closed 4 years ago
Good question ! (We'll cover this in detail in class but I'll put an explanation here)
You find nearest vertices via raycasting.
The window coordinate (win in the code) is the point clicked by the user on the screen. Notice this is 3D. The screen itself lies at the z=0 in this 3D screen space. The camera is at (win_x, win_y, 1).
You can use ligigl::unprotect to convert these coordinates from window space to world space.
Then we can cast a ray through these two points and see what it hits (use igl::ray_mesh_intersect).
This method will return a hit triangle and the barycentric coordinates of the ray-triangle intersection. You can now compute the distance, in the world space, between all vertices and this hit point. Selected vertices are ones that are within the user defined radius (r).
Actually this is already enough detail to implement the method (I think). If you have questions don't hesitate to ask though.
So the radius passed into the function pick_nearest_vertices is supposed to be used to compute the distance between the hit point and the face vertices in world space? I tried that but since the radius passed into the function is 0.1 (in visualization.cpp line 403), it seems like I would need to scale it up by quite a bit. Or does that selection radius need to get scaled by the amount the ray traveled? Or is there supposed to be an imgui option to modify the selection radius?
Also, if the ray misses the mesh, but is very close to one of the vertices (within selection radius in world space, does that vertex need to be added to the picked vertices?
I've hand tuned the radius so it doesn't need to be scaled up. It's the radius around the hit point (0.1 = 10cm) so it's quite a big sphere.
If the ray misses the mesh you can count it as no selection.
I might be doing something wrong here but the bunny is really quite big then. For an arbitrary face: (V.row(face(1)) - V.row(face(0))).norm() gives me 7.7. So should we assume that the vertices are in units of centimeters and that the radius is in meters (i.e. x100 conversion factor)?
You shouldn’t have to do any conversion to get vertex picking to work.
The bunny is very big relative to its mass and stiffness. We will talk about why that is in Wednesday’s lecture.
Correction: the one thing I do in the solution is snap the hit point to the nearest vertex. You can do this by finding the maximum barycentric coordinate of the hit point.
Is there some documentation for these libigl functions somewhere? I'm having a hard time finding any and progress is slow trying to decipher the source code (what is the difference between igl::Hit.id
and igl::Hit.gid
? The barycentric coords sum to 1? Which triangle vertices does each correspond to?)
Thanks!
I am wondering are we supposed to pick vertices that are close enough around the mouse cursor in screen space after shooting the ray? If we do it this way, it is possible no vertices are close enough to the mouse in screen space, despite being attached to the face that was hit. Then you can't control the bunny even if you are clicking on one of the bunny's faces. It seems like just picking all three of the vertices that are in the face that the ray hit would be more robust, and works pretty well in practice.