-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OpenGL mouse picking with ray casting #222
Conversation
Nicely done. Looking forward to the suggested enhancements. |
Just chiming in to say thank you for write-ups such as this. They serve as great learning material and high level insight into how these tests / features work. Much appreciate the effort, love reading these. |
`get-bounds-world` is applicable for any `shape`, not just `point-cloud`.
vector3*matrix added revently was actually not needed.
Original C code authored by Tomas Moller: https://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/raytri/raytri.c
src/kernel/polyhedron.lisp
Outdated
(defmethod triangles-list ((polyh polyhedron) &key (matrix nil)) | ||
(let ((triangles '()) | ||
(tri-polyh (if (is-triangulated-polyhedron? polyh) | ||
polyh | ||
(triangulate-polyhedron polyh)))) | ||
(flet ((transform-if (xs) (if matrix (transform-points xs matrix) xs))) | ||
(do-array (_ face (faces tri-polyh)) | ||
(push (transform-if (face-points-array tri-polyh face)) triangles))) | ||
triangles)) | ||
|
||
(defmethod triangles-array ((polyh polyhedron) &key (matrix nil)) | ||
(coerce (triangles-list polyh :matrix matrix) 'vector)) | ||
|
||
(defmethod triangles-world-array ((polyh polyhedron)) | ||
(triangles-array polyh :matrix (transform-matrix (transform polyh)))) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please review if these added functions are reasonable, the triangulation is based on existing code in the same file. Regarding naming of the added functions: since there was a face-points-array
function which gets the face points, a similar nomenclature was used to name this function triangles-array
which gets an array of triangles representing the polyhedron. Please suggest better names if any.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks reasonable. Just FYI the current triangulation expects convex polygons only. I don't currently handle concave polygons.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking a look. Have added a todo in the PR description above regarding the convex polygons precondition. Will address this, maybe in a subsequent PR once the basic object picking is done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just FYI the current triangulation expects convex polygons only. I don't currently handle concave polygons.
@kaveh808 I don't have much of a math background but after searching about triangulating concave polyhedrons, it seems non trivial, at least for me:) However if this could be useful to kons-9 roadmap, I can dig deeper into it. btw I came across CGAL which might do the triangulation we need. Could CGAL be useful? As you rightly mentioned elsewhere its also important to keep very few dependencies and in which case it might be better to postpone the use of such a library until we really need it at a later stage?
Updates have been commited to branch opengl-mouse-picking-with-ray-casting: Try the updates by getting the latest of the branch and as before, after What to look out for in this update:Hover the mouse over shapes to begin picking them - You will observe that the shape now gets selected only when the mouse hovers its Update summary for commits made until now:
Questions:
Observations:Near the center of the viewport, picking seems reasonably precise. As we moving towards the periphery of the viewport a small but noticeable offset begins to grow between the mouse position and the shape which gets selected. I wonder if this unwanted behaviour could be related to perspective of the perpective camera 🤔 update: this unwanted behaviour is now fixed, which was due to a wrong function being used to instantiate a ray. see #234 |
(this got left out in the previous commit)
The picking raw which was being drawn until this commit did not actually represent the picking ray because it started from the scene origin instead of from the camera position. It doesn't serve any purpose anymore.
Object pick only on mouse left click, ignore click due to drag.
At this stage we can pick a single object at a time. We can also add to the existing selection using the shift key and make mulitple selections.
Update: You can now select a shape using |
@kaveh808 would be great to get your feedback on the object picking - It is ready for review. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approving. Thank you for such a useful enhancement.
I enjoyed working on it :) I plan to do more random stuff with kons-9. If you have any specific tasks in mind, let me know. |
Great, @kayomarz :) It would be helpful to implement OpenGL texture mapping. Currently we do basic OpenGL rendering and viewing, without explicit camera objects or materials. Implementing simple texture mapping will allow us to enhance both our 3D display and support 2D GUI icons. I have been holding off implementing materials, lights, and cameras until we figure out our rendering backend. |
This commit fixes ray creation which fixes a bit of unexpected behaviour of object picking. See the `observation` note towards the end of this comment: #222 The origin library provides a couple of functions to create a ray. Prior to this, we used a helper function which expected the ray `origin` and `direction` as parameters while what was actually being passed were the `from` and `to` coordinates. In this commit we use the more appropriate function which expects the `from` and `to` coordinates.
This commit fixes some unexpected behaviour of object picking. See the note (`observation`) note towards the end of this comment: #222 The problem was with the function being used for ray creation. The origin library provides a couple of functions to create a ray. Prior to this, we used a helper function which expected the ray `origin` and `direction` as parameters while what was actually being passed were the `from` and `to` coordinates. In this commit we use the more appropriate function which expects the `from` and `to` coordinates.
Branch opengl-mouse-picking-with-ray-casting has some code to experiement with with OpenGL mouse picking using ray casting.
How to test it out
Left click to select a single shape. In the case when multiple shapes lie in the path of the ray, then subsequent clicks select each shape in turn. This allows cycling amongst many closely overlapping objects. @kaveh this behaviour was arbitrarily done using blender as a reference - we can discuss and change it to suit to whatever works best for kons-9.
Left click while pressing the
shift
key to add an item to the selection.To write custom selection behaviour, see test/demo-object-picking.lisp
TODOs:
triangles-list
in filepolyhedron.lisp
will only work for convex polyhedrons but we need to be able to intersect for all cases.How it tries to pick shapes
glu:un-project
to determine the far point under the mouse(gl:get-double :modelview-matrix)
ray
from the camera to the far plane under the mouseorigin
library'sorigin.geometry.ray
which gives us a ray objectorigin
library'sorigin.geometry.aabb
origin
library functionorigin.geometry:raycast-aabb
to intesect the aboveray
andaabb
objectsxs-miss
and move on to the next shape.xs-hit
containing a list of shapes sorted by distance from the camera. Anoter listxs-miss
contains all shapes which did not intersect.xs-hit
,xs-hit
along with another listxs-current
to decide which shapes should be selected in the scene. See test/demo-object-picking.lisp for moreWill look forward to comments and suggestions.
(Below is older stuff, not relevant anymore)
This demo picks objects whenever the mouse hovers over them which is done as follows:1. Use a flag (*do-mouse-pick*
) to detect mouse move2. Immediately after each draw scene the object picker described above kicks in if the flag*do-mouse-pick*
was set### Picking resolution/accuracySince the ray is intersected with the aabb (axis aligned bounding box) an objects gets picked whenever it intersects the bounding box of a shape. As you will observe, this is not very accurate.### Next stepsThis was more like an fun experiment. If this type of picking might be of use to kons-9 (at-least until vulkan comes in), we can:1. Improve the picking accuracy: If an object's aabb does get picked, attempt further intersections of the ray with the actual shape and not just the aabb2. Design an api to enable/disable picking with useful options such as on mouse clicks / double clicks / hover, etc...### Notes1. For this demo, all objects that are in the path of the ray get picked, not only the closest one. This behaviour is easy to change and pick only the object closest to the camera. This can be done using the number returned by intersect funtion (origin.geometry:raycast-aabb
) which indicates the distance from the camera.Since this was an experiment, this is just a draft pull request to view code diffs and get feedback (rather than a normal pull request)