Note that there are some explanatory texts on larger screens.

plurals
  1. POopengl select sphere with mouse
    text
    copied!<p>I have a number of spheres in 3d space which the user should be able to select with a mouse click. Now I've seen some examples around using gluUnProject so I gave it a shot. So I have (please correct me every step of the way if I'm wrong because I'm not 100% sure of any part of it):</p> <pre><code>def compute_pos(x, y, z): ''' Compute the 3d opengl coordinates for 3 coordinates. @param x,y: coordinates from canvas taken with mouse position @param z: coordinate for z-axis @return; (gl_x, gl_y, gl_z) tuple corresponding to coordinates in OpenGL context ''' modelview = numpy.matrix(glGetDoublev(GL_MODELVIEW_MATRIX)) projection = numpy.matrix(glGetDoublev(GL_PROJECTION_MATRIX)) viewport = glGetIntegerv(GL_VIEWPORT) winX = float(x) winY = float(viewport[3] - float(y)) winZ = z return gluUnProject(winX, winY, winZ, modelview, projection, viewport) </code></pre> <p>Then, having the x and y of a mouse click and the position of the center of the sphere:</p> <pre><code>def is_picking(x, y, point): ray_start = compute_pos(x, y, -1) ray_end = compute_pos(x, y, 1) d = _compute_2d_distance( (ray_start[0], ray_start[1]), (ray_end[0], ray_end[1]), (point[0], point[1])) if d &gt; CUBE_SIZE: return False d = _compute_2d_distance( (ray_start[0], ray_start[2]), (ray_end[0], ray_end[2]), (point[0], point[2])) if d &gt; CUBE_SIZE: return False d = _compute_2d_distance( (ray_start[1], ray_start[2]), (ray_end[1], ray_end[2]), (point[1], point[2])) if d &gt; CUBE_SIZE: return False return True </code></pre> <p>So because my 3d geometry is not good at all, I compute two points as a ray start and end point, the go into 2d 3 times eliminating one dimension at a time and compute the distance there between my line and the center of the sphere. If any of those distances are bigger than my sphere ray the it's not clicked. I think the formula for the distance is correct but just in case:</p> <pre><code>def _compute_2d_distance(p1, p2, target): ''' Compute the distance between the line defined by two points and a target point. @param p1: first point that defines the line @param p2: second point that defines the line @param target: the point to which distance needs to be computed @return: distance from point to line ''' if p2[0] != p1[0]: if p2[1] == p1[1]: return abs(p2[0] - p1[0]) a = (p2[1] - p1[1])/(p2[0] - p1[0]) b = -1 c = p1[1] + p1[0] * (p2[1] - p1[1]) / (p2[0] - p1[0]) d = abs(a * target[0] + b * target[1] + c) / math.sqrt(a * a + b * b) return d if p2[0] == p1[0]: d = abs(p2[1] - p1[1]) return d return None </code></pre> <p>Now the code seems to work fine in the start position. But after you use to mouse and rotate the screen even for a little bit, nothing works as expected anymore.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload