Three.js: unproject-如何获取特定3d对象在“屏幕(左上)”上的真实位置?

创建于 2011-01-04  ·  21评论  ·  资料来源: mrdoob/three.js

通过示例,我知道有一种方法可以将屏幕上的一个点(x,y)投影到“ 3d”点。 但是我不知道如何将其翻译回去。 感谢您提供任何线索。

Question

最有用的评论

如果升级后仍然有人需要它...

function screenXY(obj){

  var vector = obj.clone();
  var windowWidth = window.innerWidth;
  var minWidth = 1280;

  if(windowWidth < minWidth) {
    windowWidth = minWidth;
  }

  var widthHalf = (windowWidth/2);
  var heightHalf = (window.innerHeight/2);

  vector.project(camera);

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

  return vector;

};

所有21条评论

可能使用投影仪,但是MrDoob显然对此有更多了解:)

嗯,也许我们应该有一个object3d.screen ,这将是一个Vector2 ,并在每个渲染器上进行更新?

如果该object3D.screen Vector仅用于将每个object3D的object3D.position转换为2D,那么object3D.screen的价值会不会太小? 我的意思是:我认为能够将x,y,z位置的任何网格的任何点x,y,z转换为2D坐标将更为有用。

这又意味着永远不可能预先计算每个对象的每个3D位置。

例如,有一个函数THREE.3dto2d()接受Vector3(代表场景中的一个点)或一个Vector3和一个对象(其中Vector3代表该对象上的一个点),这将是非常有用的。
然后,该函数计算场景中的3D位置。
最后,它获取摄影机,其位置,旋转,projectionMatrix等,并将点转换回2D。

我想相机也应该是功能的参数...

好吧... Projector.projectScene有点已经做到了;)

瞧,我知道那是投影机... ;-)

有使用它的示例吗?

嗯...尚未...这些功能被设计为与Renderer一起使用...它们返回要与原始对象无关的要渲染的元素列表。 也许我应该给原始对象添加一些链接,那样就可以了...嗯,需要考虑一点。

我目前正在休假,但是一旦回来(下周),我将进行镜头光晕演示(或类似操作)。

当然,祝您假期愉快,我期待新的演示! :-)

嗯,这曾经对我有用(r32),在r35中不再存在。

  toScreenXY: function(position, camera, jqdiv) {
    // converts 3D position to screen coords
    var pos = position.clone();
    projScreenMat = new THREE.Matrix4();
    projScreenMat.multiply( camera.projectionMatrix, camera.matrix);
    projScreenMat.multiplyVector3(pos);
    return { x: (pos.x+1)*jqdiv.width()/2 + jqdiv.offset().left, 
             y:(-pos.y+1)*jqdiv.height()/2 +jqdiv.offset().top }; 
  },

projScreenMat.multiplyVector3(pos);之后的pos以前被限制在-1和1之间(以中心为(0,0)。),但是现在似乎出乎意料地变化了。

是的, camera.matrix现在需要替换为camera.matrixWorldInverse
试试这个:

toScreenXY: function ( position, camera, jqdiv ) {

    var pos = position.clone();
    projScreenMat = new THREE.Matrix4();
    projScreenMat.multiply( camera.projectionMatrix, camera.matrixWorldInverse );
    projScreenMat.multiplyVector3( pos );

    return { x: ( pos.x + 1 ) * jqdiv.width() / 2 + jqdiv.offset().left,
         y: ( - pos.y + 1) * jqdiv.height() / 2 + jqdiv.offset().top };

}

是的,工作正常,不知道矩阵的变化。 希望这个投影函数回答了alivedise的问题。

我认为这是提出有关3D Cube的问题的正确方法。 我在画布上绘制了一个带有可点击面孔的立方体。 立方体在X轴和Y轴上自由旋转。 我想要的是在用户释放鼠标时获得最正面的外观,并通过自动旋转使其完全可见。 在这方面的任何帮助将是高度赞赏的。

谢谢。

@ imrantariq2011 :与这个问题并没有真正的关系,您介意打开一个新的问题吗? 谢谢。

出于纹理映射的目的,我希望能够获得给定面的每个顶点的x,y屏幕坐标。

我可以看到如何使用上面的(toScreenXY:函数)完成此操作-但首先需要给定脸部进行世界变换(缩放,平移和旋转)顶点。 我花了一些时间查看Projector.projectScene,我想知道是否有一种更简单的方法可以实现上述目标,而且看起来object.matrixWorld.getPosition()可能会获得对象的质心,而不是面顶点。

是的,上面的代码是其中之一。 如果您需要投影很多点,则最好从.projectScene()本身中抽取代码的一部分。

到这里来的人可能想了解一下:

https://github.com/zachberry/threejs-tracking-3d-to-2d

我用它,它的工作原理是:

函数toScreenXY(pos3D)
{
var projection = new THREE.Projector();
var v = projection.projectVector(pos3D,camera);
var percX =(vx + 1)/ 2;
var percY =(-vy + 1)/ 2;
var left = percX * window.innerWidth;
var top = percY * window.innerHeight;

返回新的THREE.Vector2(left,top);
}

在2014年8月1日,星期五,上午11:24,Artem Fitiskin [email protected]写道:

当我使用toScreenXY时,我会得到很大的价值。
console.log(pos):// x:-1474.1436403989792,y:-730.829023361206,z:3.0004000663757324
并将其与jqdiv相乘后,函数将返回非常大的x和y。
我做错了什么?
-
直接回复此电子邮件或在GitHub上查看。

@arieljake

指南中所述,帮助请求应定向到stackoverflow 。 该板适用于错误和功能请求。

很好...但是doob先生自己放了代码,那能给什么呢?

@arieljake #1979

如果升级后仍然有人需要它...

function screenXY(obj){

  var vector = obj.clone();
  var windowWidth = window.innerWidth;
  var minWidth = 1280;

  if(windowWidth < minWidth) {
    windowWidth = minWidth;
  }

  var widthHalf = (windowWidth/2);
  var heightHalf = (window.innerHeight/2);

  vector.project(camera);

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

  return vector;

};

好的,很老的问题,但是我有一个嵌套的对象,它与上面的代码不兼容。
我的情况是:渲染后,我想要嵌套对象的真实x和y(和z)位置,因此我改写了上面的示例。
请注意:

  1. 现在,您将整个对象作为参数,而不仅仅是上述示例中的object.position。
  2. 同样,这仅在渲染器完成其工作并调用
  3. 它也适用于非嵌套对象,但是它将进行过多的计算。
  4. 它还为您提供一个屏幕Z,可用于对domElement或zSort标签进行排序。
    屏幕z相对于相机/渲染器的正面和背面修剪平面在0到1之间,对于我的目的(排序)来说,这很好。
  5. 您可以通过renderer.domElement.width和renderer.domElement.height获得渲染器的当前宽度和高度。
scene.updateMatrixWorld(); 

parent.updateMatrixWorld(); 

```js
函数nestedObjecttoScreenXYZ(obj,camera,width,height)
{
var vector = new THREE.Vector3();
vector.setFromMatrixPosition(obj.matrixWorld);
var widthHalf =(width / 2);
var heightHalf =(height / 2);
vector.project(camera);
vector.x =(vector.x * widthHalf)+ widthHalf;
vector.y =-(vector.y * heightHalf)+ heightHalf;
返回向量;
};



typical call:
```js
var screenpos=NestedObjecttoScreenXY(object,camera,renderer.domElement.width,renderer.domElement.height,true);

以防万一有人遇到同样的问题。

此页面是否有帮助?
0 / 5 - 0 等级