1

I have severals pairs of points in world space each pair have a different depth. I want to project those points on the near plane of the view frustrum, then recompute their new world position.

note: I want to keep the perspective effect

To do so, I convert the point's location in NDC space. I think that each pair of points on NDC space with the same z value lie on the same plane, parallel to the view direction. So if I set their z value to -1, they should lie on the near plane.

Now that I have thoose new NDC locations I need their world position, I lost the w component by changing the depth, I need to recompute it.

I found this link: unproject ndc

which said that:

wclip * inverse(mvp) * vec4(ndc.xyz, 1.0f) = 1.0f
wclip = 1.0f / (inverse(mvp) * vec4(ndc.xyz, 1.0f))

my full code:

glm::vec4 homogeneousClipSpaceLeft  = mvp * leftAnchor;
glm::vec4 homogeneousClipSpaceRight = mvp * rightAnchor;

glm::vec3 ndc_left  = homogeneousClipSpaceLeft.xyz() / homogeneousClipSpaceLeft.w;
glm::vec3 ndc_right = homogeneousClipSpaceRight.xyz() / homogeneousClipSpaceRight.w;

ndc_left.z  = -1.0f;
ndc_right.z = -1.0f;

float clipWLeft  = (1.0f / (inverseMVP * glm::vec4(ndc_left, 1.0f)).w);
float clipWRight = (1.0f / (inverseMVP * glm::vec4(ndc_right, 1.0f)).w);

glm::vec3 worldPositionLeft  = clipWLeft * inverseMVP * (glm::vec4(ndc_left, 1.0f));
glm::vec3 worldPositionRight = clipWRight * inverseMVP * (glm::vec4(ndc_right, 1.0f));

It should work in practice but i get weird result, I start with 2 points in world space:

left world position:  -116.463 15.6386 -167.327
right world position: 271.014 15.6386 -167.327
left NDC position: -0.59719 0.0790622 -1
right NDC position: 0.722784 0.0790622 -1
final left position:  31.4092 -9.22973 1251.16
final right position: 31.6823 -9.22981 1251.17
mvp
4.83644 0 0 0
0 4.51071 0 0
0 0 -1.0002 -1
-284.584 41.706 1250.66 1252.41

Am I doing something wrong ?

Would you recommend this way to project pair of points to the near plane, with perspective ?

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Paltoquet
  • 1,184
  • 1
  • 10
  • 18

1 Answers1

1

If glm::vec3 ndc_left and glm::vec3 ndc_right are normalized device coordiantes, then the following projects the coordinates to the near plane in normaized device space:

ndc_left.z  = -1.0f;
ndc_right.z = -1.0f;

If you want to get the model positon of a point in normalized device space in Cartesian coordinates, then you have to transform the point by the invers model view projection matrix and to devide the x, y and z component by the w component of the result. Not the transfomation by inverseMVP gives a Homogeneous coordinate:

glm::vec4 wlh = inverseMVP * glm::vec4(ndc_left, 1.0f);
glm::vec4 wrh = inverseMVP * glm::vec4(ndc_right, 1.0f);

glm::vec3 worldPositionLeft  = glm::vec3( wlh.x, wlh.y, wlh.z ) / wlh.w;
glm::vec3 worldPositionRight = glm::vec3( wrh.x, wrh.y, wrh.z ) / wrh.w;


Note, that the OpenGL Mathematics (GLM) library provides operations vor "unproject". See glm::unProject.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • I don't understand why you do the division by w in world space is it not supposed to be something like ```world = inverseMVP * (ndc * wlh.w)``` – Paltoquet Jun 07 '18 at 07:02
  • I figure it now, I don't know why it's is not not working. Both our code do the same thing, the w division is perform by ```clipWLeft```in mine. I think i have an issue with the linearisation of the depth. Your answer is right. At the ned i draw a line between the 2 new points, the line is too big according to the distance to the camera. – Paltoquet Jun 07 '18 at 07:50
  • It's working, i have one last question. I try this solution to draw lines in world coordonates on a plane which remove the final perspective effect obtain via the projection matrix. This way the projected points will be on the same location on the screen with their previous values. if i am right no matter z i specify in ```ndc.z = myvalue``` i will still be on the same position in screen space ? – Paltoquet Jun 07 '18 at 08:15
  • @DraykoonD Yes you ar right. At Perspective Projection the projection matrix describes the mapping from 3D points in the world as they are seen from of a pinhole camera, to 2D points of the viewport. All the points which have the same xy-coordiante in normalized device space are projected to the same point on the viewport. – Rabbid76 Jun 07 '18 at 08:33
  • See also [How to render depth linearly in modern OpenGL with gl_FragCoord.z in fragment shader?](https://stackoverflow.com/questions/7777913/how-to-render-depth-linearly-in-modern-opengl-with-gl-fragcoord-z-in-fragment-sh/45710371#45710371), [3 Solutions to recover view space position in perspective projection](https://stackoverflow.com/questions/11277501/how-to-recover-view-space-position-given-view-space-depth-value-and-ndc-xy/46118945#46118945) or [Perspective Projection](https://github.com/Rabbid76/graphics-snippets/blob/master/documentation/projection_and_depth.md#perspective-projection). – Rabbid76 Jun 07 '18 at 08:33