Javascript 使用投影将 Three.js 中的世界坐标转换为屏幕坐标

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11586527/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 06:25:16  来源:igfitidea点击:

Converting World coordinates to Screen coordinates in Three.js using Projection

javascript3dthree.js

提问by BishopZ

There are several excellent stack questions (1, 2) about unprojecting in Three.js, that is how to convert (x,y) mouse coordinates in the browser to the (x,y,z) coordinates in Three.js canvas space. Mostly they follow this pattern:

有几个关于 Three.js 中取消投影的优秀堆栈问题 ( 1, 2),即如何将浏览器中的 (x,y) 鼠标坐标转换为 Three.js 画布空间中的 (x,y,z) 坐标。大多数情况下,他们遵循以下模式:

    var elem = renderer.domElement, 
        boundingRect = elem.getBoundingClientRect(),
        x = (event.clientX - boundingRect.left) * (elem.width / boundingRect.width),
        y = (event.clientY - boundingRect.top) * (elem.height / boundingRect.height);

    var vector = new THREE.Vector3( 
        ( x / WIDTH ) * 2 - 1, 
        - ( y / HEIGHT ) * 2 + 1, 
        0.5 
    );

    projector.unprojectVector( vector, camera );
    var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() );
    var intersects = ray.intersectObjects( scene.children );

I have been attempting to do the reverse - instead of going from "screen to world" space, to go from "world to screen" space. If I know the position of the object in Three.js, how do I determine its position on the screen?

我一直试图做相反的事情 - 而不是从“屏幕到世界”空间,而是从“世界到屏幕”空间。如果我知道 Three.js 中对象的位置,我如何确定它在屏幕上的位置?

There does not seem to be any published solution to this problem. Another question about this just showed up on Stack, but the author claims to have solved the problem with a function that is not working for me. Their solution does not use a projected Ray, and I am pretty sure that since 2D to 3D uses unprojectVector(), that the 3D to 2D solution will require projectVector().

这个问题似乎没有任何已发布的解决方案。关于这个的另一个问题刚刚出现在 Stack 上,但作者声称已经用一个对我不起作用的函数解决了这个问题。他们的解决方案不使用投影射线,我很确定由于 2D 到 3D 使用 unprojectVector(),因此 3D 到 2D 解决方案将需要 projectVector()。

There is also this issueopened on Github.

Github上也有这个问题

Any help is appreciated.

任何帮助表示赞赏。

回答by mrdoob

Try with this:

试试这个:

var width = 640, height = 480;
var widthHalf = width / 2, heightHalf = height / 2;

var vector = new THREE.Vector3();
var projector = new THREE.Projector();
projector.projectVector( vector.setFromMatrixPosition( object.matrixWorld ), camera );

vector.x = ( vector.x * widthHalf ) + widthHalf;
vector.y = - ( vector.y * heightHalf ) + heightHalf;

回答by dkobozev

For modern Three.js (r75), a vector can be projected onto the screen with:

对于现代 Three.js (r75),可以使用以下命令将向量投影到屏幕上:

var width = window.innerWidth, height = window.innerHeight;
var widthHalf = width / 2, heightHalf = height / 2;

var pos = object.position.clone();
pos.project(camera);
pos.x = ( pos.x * widthHalf ) + widthHalf;
pos.y = - ( pos.y * heightHalf ) + heightHalf;

回答by martin

For everyone getting deprecatedor warningslogs, the accepted answer is for older Three.js versions. Now it's even easier with:

对于获取deprecatedwarnings记录的每个人,接受的答案是旧的 Three.js 版本。现在它更容易:

let pos = new THREE.Vector3();
pos = pos.setFromMatrixPosition(object.matrixWorld);
pos.project(camera);

let widthHalf = canvasWidth / 2;
let heightHalf = canvasHeight / 2;

pos.x = (pos.x * widthHalf) + widthHalf;
pos.y = - (pos.y * heightHalf) + heightHalf;
pos.z = 0;

console.log(pos);

回答by ninjagecko

You cannotconvert (x,y) coordinates to (x,y,z) coordinates because you lose information. What you have quoted is how to find all points on all objects in the scene which intersect the ray generated by (x,y).

无法将 (x,y) 坐标转换为 (x,y,z) 坐标,因为您会丢失信息。您所引用的是如何找到场景中与 (x,y) 生成的光线相交的所有对象上的所有点。

The going from "world to screen" as you request is what projection is all about, and is equivalent to rendering a single point (x,y,z). What you do is you apply the projection matrix to your point (x,y,z). It is presumably the Projector.projectVector(vector, camera)function at http://mrdoob.github.com/three.js/docs/49/#Projector, but due to the fact that it outputs a 3d vector, I can only assume that one of the dimensions is 0 and you can ignore it.

根据您的要求从“世界到屏幕”是投影的全部内容,相当于渲染单个点 (x,y,z)。您所做的是将投影矩阵应用于您的点 (x,y,z)。它大概是http://mrdoob.github.com/three.js/docs/49/#Projector 上Projector.projectVector(vector, camera)函数,但由于它输出一个 3d 矢量,我只能假设其中一个维度是 0你可以忽略它。