5

I have a 3D model consisting of point vertices (XYZ) and eventually triangular faces. Using OpenGL or camera-view-matrix-projection I can project the 3D model to a 2D plane, i.e. a view window or an image with m*n resolution.

The question is how can I determine the correspondence between a pixel from the 2D projection plan and its corresponding vertex (or face) from the original 3D model.

Namely,
What is the closest vertices in 3D model for a given pixel from 2D projection?
It sounds like picking in openGL or raytracing problem. Is there however any easy solution?

With the idea of ray tracing it is actually about finding the first vertex/face intersected with the ray from a view point. Can someone show me some tutorial or examples? I would like to find an algorithm independent from using OpenGL.

Phrogz
  • 296,393
  • 112
  • 651
  • 745
rnd_nr_gen
  • 2,203
  • 3
  • 36
  • 55

3 Answers3

2

Hit testing in OpenGL usually is done without raytracing. Instead, as each primitive is rendered, a plane in the output is used to store the unique ID of the primitive. Hit testing is then as simple as reading the ID plane at the cursor location.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • Hi. Could you please elaborate on this? I have a 3D point cloud and each point has XYZRGB. After the projection of point cloud on the image, can I get their original (x,y,z) from the pixel coordinates? I require the original location of all the pixels. – Ankitp Feb 21 '17 at 12:16
1

My (possibly-naive) thought would be to create an array of the vertices and then sort them by their distance (or distance-squared, for speed) once projected to your screen point. The first item in the list will be closest. It will be O(n) for n vertices, but no worse.

Edit: Better for speed and memory: simply loop through all vertices and keep track of the vertex whose projection is closest (distance squared) to your viewport pixel. This assumes that you are able to perform the projection yourself, without relying on OpenGL.

For example, in pseudo-code:

function findPointFromViewPortXY( pointOnViewport )
  closestPoint = false
  bestDistance = false
  for (each point in points)
    projectedXY     = projectOntoViewport(point)
    distanceSquared = distanceBetween(projectedXY, pointOnViewport)
    if bestDistance==false or distanceSquared<bestDistance
      closestPoint = point
      bestDistance = distanceSquared
  return closestPoint
Phrogz
  • 296,393
  • 112
  • 651
  • 745
  • The closest point in the 2D projection may be very far away in 3D space. – Mike Daniels Apr 05 '11 at 01:05
  • @MikeDaniels I'm not sure what you mean. Yes, it may be very far in 3D space from the projection on the plane, but I don't believe that matters. As I understand it, the OP has a 3D point cloud being rendered to the screen, the user is clicking on the screen to select a point, and the OP is trying to find which point is closest (on screen) to the picked point. – Phrogz Apr 05 '11 at 01:26
  • sorry I cannot get your idea. What kind of the distance should I calculate and sort? – rnd_nr_gen Apr 05 '11 at 07:14
  • @elgcom I've updated my answer with pseudo-code for what I am suggesting. – Phrogz Apr 05 '11 at 12:53
1

In addition to Ben Voigt's answer:

  1. If you do a separate pass over pickable objects, then you can set the viewport to contain only a single pixel that you will read.

  2. You can also encode triangle ID by using geometry shader (gl_PrimitiveID).

kvark
  • 5,291
  • 2
  • 24
  • 33