The solution to this question made me recall trigonometry and vector algebra.
Problem statement: when creating, change the object after the mouse movement.
What we have: cursor coordinates in screen coordinates, camera viewing angle, aspect ratio.
It is necessary to determine: how much the scale of the view in world coordinates at a given moment of time differs from the scale of the screen, find the distance from the position of the object in screen coordinates and multiply it by the scale of the view at the current time.
To look at the camera from the side (above), I created a third render and placed it in the second canvas. When you click on canvas, it increases to full screen. Later I will make an orthogonal camera there.
The first thing we will do is determine the position of the object in screen coordinates. To do this, project the position vector of the object onto the screen. Three.js provides a project () function. We clone the position vector of the object, otherwise the function will change the position of the object.
let pos = scope.currentEntity.position.clone().project( sceneCamera.camera ); // t is in the coordinates of the view.
Translation to screen coordinates:
scope.centerOfObjectScreen.x = ( pos.x * window.innerWidth/2 ) + window.innerWidth/2; scope.centerOfObjectScreen.y = - ( pos.y * window.innerHeight/2 ) + window.innerHeight/2;
In the video, the first yellow ball shows the position of the created object.
Now determine the position of the camera in 3D space and write it to a new vector. The function is also provided for this:
let cameraPosition = new THREE.Vector3(); cameraPosition = camera.position.clone();
Similarly, we determine the direction of the camera, expressed by a unit vector:
let cameraDirection = new THREE.Vector3(); camera.getWorldDirection ( cameraDirection );
Define the distance from the camera to the object:
let distance = point.distanceTo( cameraPosition );
Now from the center from the camera we get a point that is at a distance equal to the distance from the camera to the object:
In the video, this is the second yellow ball and the green line, I created them in order to understand whether I am doing the right thing.
We project the point of position of the object on a line passing from the center of the camera along the axis of the camera
let line3 = new THREE.Line3(camera.position, cameraPosition); let pointOnLine = new THREE.Vector3(); line3.closestPointToPoint( point, true, pointOnLine);
This is the second green line from the first yellow ball perpendicular to the camera axis.
We determine the distance from the camera to the intersection point.
distance = pointOnLine.distanceTo( camera.position );
This will be the distance from the camera to the plane perpendicular to the axis of the camera and passing through the object.
Using the trigonometry formulas, we find the screen size in this plane in world coordinates
let angle = camera.fov/2; let sizeOfViewX = distance * Math.tan( angle * Math.PI / 180 ) * 2; let sizeOfViewY = sizeOfViewX * camera.aspect * 2;
let ratio = ( 1000000000 * window.innerHeight)/(1000000000 * worldSizeOfScreen.height );
Determine the distance from the center of the object to the mouse pointer in screen coordinates
let distance = currentCoordsScreen.distanceTo( scope.centerOfObjectScreen );
and divide it by the coefficient obtained
width = distance / ratio; // got the cube size in world coordinates.
PS. At first I wanted to redraw the schematics for this post, but then I changed my mind, it’s so livelier, I can see my mental torment))