Data loss in Vector3.project(this.camera) function

Hi, with due respect. I have two points named A, B. These points have float values for ther x,y,z axis of upto 15 digits. Now when I find the difference between the two points, A.distnaceTo(B) I get their distance in World Space. But When I project these two vectors, A.project(camera); B.project(camera) and after that i try to find out the distance A.distanceTo(B) i get values in the NDC space. I understand that NDC space has values ranging from +1 to -1. But the problem is the distance of the point is almost always same in the world space, but in NDC space the distance changes. Why is that?

I am referencing some sample data to understand.

If you look at these data, you will see the distance between A and B in world space in all t1-t4 time is almost same. But the distance of A and B in NDC space has some serious change, at t2 the distance is 0.23 but at t3 it is 0.4. Why it may happen?

How much the values in NDC space changes depends on your camera settings. Do you mind sharing how you are setting the camera up?

Sidenote: You can improve your post by sharing the above computations as a live example instead of a screenshot.

Hi, my camera is always updating inside the animation frame, based on point B and some other calculation, My data source is a bit complex to create a live fiddle. But I will make one and post here asap. Thank you.

vokoscreenNG-2023-01-06_15-48-41.mkv (4.3 MB)
Hi, my data source is from a private repo, so it is hard to replicate a js fiddle with the data, besides the dataset is too large to embed as json object in js fiddle. So I attached a video here. Yellow point is B, red point is A. both the points are updating continuously, and my camera is also updating with respect to the yellow point. You can see the distance from yellow point and the camera is always almost constant(upto 5 decimal places). However if we look at the distance between red and yellow point it seems, their distance in world space is constant(changes but very slightly) but their distance in NDC space*referred as display) changes too frequent and the change is also big by margin. In real scenario the point A and B are always at constant distance, there is now way at all that there is change in the distance. So when I render this line joining these two points, the line sometimes seems squeezing, sometimes getting larger. I can’t find any probable issue. I tried best to my capacity. Thought it is of perspective distortion, but couldn’t identify any specific problem for that. Any idea?

@mahadi –

A shot in the dark. Projection converts the camera frustum into a cube. See the image, both segments are almost the same in NDC, but are quite different in the camera frustum, which near and far planes are too close.

Untitled Diagram

– Pavel

Hi, pavel thanks for your reply. I understand that, but why it is not constant, that’s my question. I mean my camera frustrum is always constant right? So whatever be the frustrum, the distance between two points should be constant, right? Coz my near, far everything is always constant. The distance of the points from the camera is also constant. So I want to see the exact distance between these two points in the scene and akways want them to maintain a constant distance. In real life it is constant, their euclidean distance is also constant but visually it is not constant in the screen. Now I underatnd it may be for camera frustrum/NDC, or may be due to perspective distortion. But how can I fix it? I don’t have any idea.

@mahadi –

This type of projection does not preserve distances except in extreme cases of orthographic projection and cubic frustum. Even if the distance between two points is constant, if they rotate in space (or if the camera rotates), their NDC distance could and will change.

This image shows that even if the frustum shape is constant and the red segment is constant, when the camera is rotated, the projected segment will have a different length.

Untitled Diagram

I hope that someone else will give a more helpful advice or a more understandable explanation.

– Pavel

Hi, I understand your point. Lets forget about NDC, projection for now. Lets just say I have two points A, B. If I calculate their euclidean distance I always get a constant result. But in the screen it seems that the distance between these two points visibly are not always constant, it changes when points are moving. I want them always in the same distance wherever they go. My camers is looking at point B, so it is always at the center of the screen. Other point, A is like miving around B. Both A, and B is continuously updating their position in the render loop, the camera position is also updating based on point B.( At a constant distance and angle from B)
Now the screen distance between A, B is not always constant, but I want them to be always constant coz their actual euclidean distance is constant.

Reason: Actually I want to put a sprite(a png image as texture) between these two points, so that the size of the sprite is always constant to the distance between A, B. But as distance between A, B seems nit constant in the screen, my image size is not also constant. Image looks squeezed, sometimes enlarged. Thank you. I am sorry, I think I am making a simple thing complex.

@mahadi You are experiencing a perspective camera distortion, the distortion effect greatly depends on the FOV of the camera (Large FOV = large distortion, small Fov = reduced distortion) and the horizontal position of the object relative to the camera (The nearest to the edge the more distorted).

You have two options, either you reduce the perspective camera FOV or use an OrthographicCamera, in your case I would suggest the latter option since you want to project a 2D image the Orthographic camera is made for this kind of scenario.

Hi, I am not well versed with orthographic camera settings. My points are 47000<x<47500, 80<y<85, 94000<z<95000 in this range. I don’t understand, how to set left, right, top, bottom for the camera. My camera position is also in this range. Points are very near to camera. However I have seen that the values for orthographic camera are in world space. I want to know the relation between these values and the div(where my scene is drawn in html) size.

@mahadi Check this example (code)

This is the relevant code snipet:

const frustumSize = 1000;
const aspect = window.innerWidth / window.innerHeight;
camera = new THREE.OrthographicCamera( frustumSize * aspect / - 2, frustumSize * aspect / 2, frustumSize / 2, frustumSize / - 2, 0.01, 1000 );

Reset the furstum variable till you get the desired view (increase = Zoom out, decrease = Zoom in).

Don’t forget about the near and far properties and the camera position as well

Hi, i have implemented this already with my desired frustrum size. It didnt solve my problem. My two points are still seems changing their distance in the screen. I have two points A, B. They are updating their position in render loop. My camera is also updating itz position in render loop. Camera position = Position of B + Some offset. Camera is always looking at position B. Distance from camera to point A, B is almost constant ( upto 5 decimal precision). Distance between point A, B is 1.44-1.46 range always (in real life 0.01 difference = 1cm difference is kind of constant, given the actual distance is 1.45m, it is not visible, right?). However their (A,B) distance on the screen do not seem constant. Their change is visible in eyes. I have used frustrum size as 6.

Help me understand, what happens when i update the position of camera. As it is continuously updating, what happens to the rectangle viewbox we are creating initially(with left, right, top, bottom), and how the axes are also impacted. How I am seeing the points through this camera after updating their position. I think i am not getting the scenario visually, that’s why it seems complex to me. A article with image or drawings would be better.

If it’s not a camera distortion then there must be some transformation applied to the points (position/rotation/scale) or the camera position relative to the points (the points position will change depending on how you move/position your camera, like in real life), sorry I can’t help without looking at the code, at this point the problem can be anything.

1 Like

There is only one transformation applied for all the points and camera, that is I update their position in render loop. I found that the distance between my points A, B changes with time, but the change is very tiny like 0.03-0.05 like that. Which means 3-5cm if I am not wrong. Now given to the actual distance of these two points in real life (which is 1.45m), this 3-5cm is negligible, right? But in the screen it is not negligiblr, it is clearly visible that the distance is changing. I want to know why such a small change in distance is visible on the screen, and how can I avoid this? https://jsfiddle.net/fsgv4j1q/4/ added some code here. Sorry the data set is too high. https://jsfiddle.net/0ejqo2st/19/ this fiddle has working example. You can clearly see the weird behaviour of the red point.

There is nothing weird about your code, it is perfectly reflecting the data you’re given it, if the movement is visible and bothering you then it’s not negligible.

You could transform the data itself, add some iteration with a threshold and a clamping condition, check the distance between the current point and the last valid point if the distance is negligible clamp/remove it.

Hi @Fennec thanks a lot. After lots of experiement and trial i found out that there was issue with the data. It wasn’t reliable as it was meant to be. Thank you so much for helping out.

2 Likes