javascript - THREE.JS:从 3D 透视场景到 2D 正交 hud 场景的转换

标签 javascript graphics 3d three.js 2d

我在 3D 场景中有物体(非常远),使用透视相机和使用正交相机设置的 2D HUD:

this.scene = new THREE.Scene();
this.hud = new THREE.Scene();

this.camera = new THREE.PerspectiveCamera( 30, aspect, front, back );
this.camera.position.set(0,0,0);

this.hudCamera = new THREE.OrthographicCamera (-this.windowHalfX,this.windowHalfX, this.windowHalfY, -this.windowHalfY, 1, 10);
this.hudCamera.position.set(0,0,10);

这是我的渲染循环:

  updateFrame : function () {
    this.renderer.clear();
    this.renderer.render( this.scene, this.camera );
    this.renderer.clearDepth();
    this.renderer.render( this.hud, this.hudCamera );
  },

如何利用对象在 3D 场景中的位置找到 HUD 中对象的位置?

最佳答案

为了找到 3D 对象的 2D HUD 位置(使用 Three.js 版本 r71),您可以执行以下操作,这是我从 this post 修改的:

  findHUDPosition : function (obj) {
      var vector = new THREE.Vector3();

      obj.updateMatrixWorld();
      vector.setFromMatrixPosition(obj.matrixWorld);
      vector.project(this.camera);

      vector.x = ( vector.x * this.windowHalfX );
      vector.y = ( vector.y * this.windowHalfY );

      return {
          x: vector.x,
          y: vector.y,
          z: vector.z
      }
  }

参数obj是您试图在HUD中查找位置的对象。

vector.project(this.camera);绘制一个从物体到this.camera位置的向量,通过near相机的平面。

向量分量的新值是投影向量与this.camera近平面的交集。

虽然坐标是在 Three.js 的世界坐标系中,所以我们必须快速转换为像素坐标,以放大到 Canvas 的大小。

  vector.x = ( vector.x * this.windowHalfX );
  vector.y = ( vector.y * this.windowHalfY );

上述转换适用于 HUD 坐标系的原点 (0,0) 位于屏幕中心且最大值为 Canvas 分辨率一半的设置。例如,如果您的 Canvas 为 1024 x 768 像素,则右上角的位置将为 (512, 384)。

对于典型的屏幕坐标系,右下角为 (1024, 768),屏幕中间为 (512, 384)。要进行此设置,您可以使用以下转换,如 this post 中所示。 .

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

注意,z 坐标现在并不重要,因为我们处于二维状态。

您要做的最后一件事是确保您以 2D 形式显示的对象实际上对透视相机可见。这就像检查对象是否落在 this.camera 的视锥体内一样简单。 source for following code

checkFrustrum : function (obj) {
    var frustum = new THREE.Frustum();
    var projScreenMatrix = new THREE.Matrix4();

    this.camera.updateMatrix();
    this.camera.updateMatrixWorld();

    projScreenMatrix.multiplyMatrices( this.camera.projectionMatrix, this.camera.matrixWorldInverse );

    frustum.setFromMatrix( new THREE.Matrix4().multiplyMatrices( this.camera.projectionMatrix,
                                                     this.camera.matrixWorldInverse ) );
    return frustum.containsPoint ( obj.position );
}

如果不这样做,您可以将相机后面的对象注册为在 2D 场景中可见(这会给对象跟踪带来问题)。更新 obj 的矩阵和矩阵世界也是一个很好的做法。

关于javascript - THREE.JS:从 3D 透视场景到 2D 正交 hud 场景的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29992594/

相关文章:

javascript - CoffeeScript + node.js : Unexpected token > (function arrow)

java - 我可以在 Rhino 中将 Javascript 数组作为通用集合传递吗?

graphics - 同时支持 DirectX 9 和 10 的应用程序

c# - 将 System.Drawing.Bitmap 缩放到给定大小,同时保持纵横比

java - 从 java 代码启动 javaFX 应用程序

python - 来自带有 matplotlib 的数组的 3D 曲线的线条颜色

javascript - Regex - 正则表达式完全匹配字符串

javascript - Three.js - 使用 scale.set() 缩放模型或增加模型大小?

c++ - 在 OpenGL 中向 3D 对象添加光源

javascript - 使用 JavaScript 的视差效果问题