0

I am trying to orient a 3d object at the world origin such that it doesn't change its position wrt camera when I move the camera OR change its field of view. I tried doing this

Object Transform = Inverse(CameraProjectionMatrix)

How do I undo the perspective divide because when I change the fov, the object is affected by it

In detail it looks like

origin(0.0, 0.0, 0.0, 1.0f);
projViewInverse = Camera.projViewMatrix().inverse();
projectionMatrix = Camera.projViewMatrix();
projectedOrigin = projectionMatrix * origin;
topRight(0.5f, 0.5f, 0.f);
scaleFactor = 1.0/projectedOrigin.z();
scale(scaleFactor,scaleFactor,scaleFactor);
finalMatrix = projViewInverse * Scaling(w) * Translation(topRight);
YuNo
  • 131
  • 1
  • 2
  • 12
  • please include enough code to help debug, include how you use those matrix. – apple apple Apr 13 '21 at 17:18
  • you should not use projection-view matrix, you only need to multiply `view.inverse()` to the model (or, simply ignore the view matrix in shader) – apple apple Apr 13 '21 at 17:26
  • Let me try. How to cancel the perspective divide? – YuNo Apr 13 '21 at 17:28
  • the view matrix would not contain perspective divide? (which is done in projection matrix iirc) – apple apple Apr 13 '21 at 17:29
  • so I guess I am dealing with an object that has camera ops applied and I am only trying to undo them, Applying the view inverse only makes it disappear – YuNo Apr 13 '21 at 17:34
  • a vertex it transformed by `proj*view*model`, now you want `proj*model`, it should work to write it as `proj*view*(view^-1*model)` – apple apple Apr 13 '21 at 17:59
  • note: it'd not relate to any position. – apple apple Apr 13 '21 at 18:00
  • note: you need to keep raw `model` to calculate new `view^-1*model` every frame/viewupdate – apple apple Apr 13 '21 at 18:01
  • so proj does contain perspective though? – YuNo Apr 13 '21 at 18:19
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/231078/discussion-between-yuno-and-apple-apple). – YuNo Apr 13 '21 at 18:25
  • If I understand your question, to cancel the motion effect you need the inverse of view-only matrix as was said. While to cancel the fov effect (zoom), you can apply a scale. The factor you need is `sz = tan(fov_last/2) / tan(fov_curr/2)`. So you need the fov parameter, which seems you already have, but you can recover it from projection-only matrix as `fov = 2*atan(1/P11)` – Douglas Oliveira Apr 13 '21 at 18:54
  • Thanks, I will try and get back – YuNo Apr 13 '21 at 19:51
  • what is fov_last and fov_current? – YuNo Apr 13 '21 at 19:52
  • should I multiply it by the above ratio or just fov? – YuNo Apr 13 '21 at 21:30

1 Answers1

0

if you use gfx pipeline where positions (w=1.0) and vectors (w=0.0) are transformed to NDC like this:

(x',y',z',w') = M*(x,y,z,w) // applying transforms
(x'',y'') = (x',y')/w'      // perspective divide

where M are all your 4x4 homogenyuous transform matrices multiplied in their order together. If you want to go back to the original (x,y,z) you need to know w' which can be computed from z. The equation depends on your projection. In such case you can do this:

w' = f(z')             // z' is usually the value encoded in depth buffer and can obtained
(x',y') = (x'',y'')*w' // screen -> camera
(x,y) = Inverse(M)*(x',y',z',w') // camera -> world

However this can be used only if you know the z' and can derive w' from it. So what is usually done (if we can not) is to cast ray from camera focal point through the (x'',y'') and stop at wanted perpendicular distance to camera. For perspective projection you can look at it as triangle similarity:

triangle similarity

So for each vertex you want to transform you need its projected x'',y'' position on the znear plane (screen) and then just scale the x'',y'' by the ratio between distances to camera focal point (*z1/z0). Now all we need is the focal length z0. That one dependss on the kind of projection matrix you use. I usually encounter 2 versions when you are in camera coordinate system then point (0,0,0) is either the focal point or znear plane. However the projection matrix can be any hence also the focal point position can vary ...

Now when you have to deal with aspect ratio then the first method deals with it internally as its inside the M. The second method needs to apply inverse of aspect ratio correction before conversion. So apply it directly on x'',y''

Spektre
  • 49,595
  • 11
  • 110
  • 380
  • So I guess I was trying out method1. I was using the w as `w = tan(0.5 * fov * pi/180);` Is that incorrect or should I just use the camera z? – YuNo Apr 14 '21 at 20:41
  • @YuNo that depends on your projection matrix ... for perspective the `w` must be a function of `z` for some projections `w=z` directly – Spektre Apr 14 '21 at 21:24
  • Is the fov suggestion wrong then? I had no luck with it so far :( – YuNo Apr 14 '21 at 22:25
  • @YuNo the `tan(0.5 * fov * pi/180);` is usually the the ratio between visual size and distance to camera in perspective projections and you can obtain focal length from it ... all depends on what kind of projection you have ... Your example lacks any values and used transform math notation are also unknown ... So I would first try to mimic your direct transformation (take any vertex and obtain its screen position without native gfx aparatus (by using the matrices on your own) and when working then inversing the process should be easy – Spektre Apr 15 '21 at 06:33
  • @YuNo btw if you just want to place object relative to camera then do so ... by using the camera matrix to transform camera local coordinates of position/orientation to world (global) coordinates ... no projection involved ... appart of the relative distances. However you need to have stand alone camera matrix ... not already multiplied MVP ... – Spektre Apr 15 '21 at 06:41
  • yeah I am trying to do it with camera matrix now so the camera always looks at the object. for the fov, I can probably move it in the opposite direction of the zoom – YuNo Apr 15 '21 at 20:51
  • @YuNo I usually scale the relative position by perspective projection focal length ... if you got also zoom then yes you need to scale the position with it too – Spektre Apr 16 '21 at 07:11