簡體   English   中英

THREE.JS:從3D透視場景轉換為2D正交平視場景

[英]THREE.JS: Conversion from 3D Perspective scene to 2D Orthographic hud scene

使用透視相機和使用正交相機設置的2D HUD,我在3D場景中有物體(很遠):

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),你可以做到以下幾點,我從修改這篇文章

  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是您要在平顯器中查找位置的對象。

vector.project(this.camera); 通過對象的near平面從對象到this.camera的位置繪制矢量。

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

坐標雖然在three.js的世界坐標系中,所以我們必須快速轉換為像素坐標,以放大到畫布的大小。

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

上面的轉換是針對HUD坐標系在屏幕中心具有原點(0,0),並且最大值是畫布分辨率的一半的設置。 例如,如果您的畫布是1024 x 768像素,則右上角的位置將是(512,384)。

對於典型的屏幕坐標系,右下角為(1024,768),屏幕中間為(512,384)。 有此設置,您可以使用下面的轉換,在看到這個帖子

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

注意,因為我們處於2D狀態,所以z坐標現在不再重要。

您要做的最后一件事是確保您要在2D中顯示的對象實際上對透視相機可見。 這就像檢查對象是否落在this.camera視錐中一樣this.camera 以下代碼的來源

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的矩陣和矩陣世界也是一個好習慣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM