如何在从3d到屏幕(hud)更新混乱位置时加速计算

时间:2017-05-25 02:37:33

标签: three.js projection

我想在鼠标移动时将hud positon形式的3d位置更新为2d。由于可能有大量的3d对象投射到屏幕位置,因此我遇到了性能问题。

有没有办法加速计算?以下是我在2d屏幕上计算3d对象位置的方法。

function toScreenPosition(obj) {
    var vector = new THREE.Vector3();
    //calculate screen half size
    var widthHalf = 0.5 * renderer.context.canvas.width;
    var heightHalf = 0.5 * renderer.context.canvas.height;
    //get 3d object position
    obj.updateMatrixWorld();
    vector.setFromMatrixPosition(obj.matrixWorld); 
    vector.project(this.camera);
    //get 2d position on screen
    vector.x = (vector.x * widthHalf) + widthHalf;
    vector.y = -(vector.y * heightHalf) + heightHalf;

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

2 个答案:

答案 0 :(得分:1)

每次相机移动时,不要将HUD重新定位在世界空间中,而是将HUD对象添加到相机对象中,并仅将它们放置一次。然后,当你的相机移动时,你的HUD会随之移动,因为相机的转换会与它的孩子级联。

yourCamera.add(yourHUD);
yourHUD.position.z = 10;

请注意,这样做(或者甚至按照您的方式定位)可能会允许场景对象剪切您的HUD几何体,甚至出现在HUD和相机之间,从而遮挡HUD。如果这就是你想要的,太棒了!如果没有,你可以将你的HUD移动到第二个渲染过程,使其保持“在顶部。”

答案 1 :(得分:1)

首先,这里是你的函数重写的一个例子,如上面的评论中所写的那样(几乎)最佳性能,renderloop显然只是一个例子来说明在哪里进行调用:

var width = renderer.context.canvas.width;
var height = renderer.context.canvas.height;

// has to be called whenever the canvas-size changes
function onCanvasResize() {
  width = renderer.context.canvas.width;
  height = renderer.context.canvas.height;
});

var projMatrix = new THREE.Matrix4();

// renderloop-function, called per animation-frame
function render() {    
  // just needed once per frame (even better would be 
  // once per camera-movement)
  projMatrix.multiplyMatrices( 
    camera.projectionMatrix, 
    projMatrix.getInverse(camera.matrixWorld)
  );

  hudObjects.forEach(function(obj) {
    toScreenPosition(obj, projMatrix);
  });
}

// wrapped in IIFE to store the local vector-variable (this pattern 
// is used everywhere in three.js)
var toScreenPosition = (function() {
  var vector = new THREE.Vector3();

  return function __toScreenPosition(obj, projectionMatrix) {
    // this could potentially be left away, but isn't too
    // expensive as there are 'needsUpdate'-checks in place
    obj.updateMatrixWorld();
    vector.setFromMatrixPosition(obj.matrixWorld);
    vector.applyMatrix4(projectionMatrix);

    vector.x = (vector.x + 1) * width / 2;
    vector.y = (1 - vector.y) * height / 2;

    // might want to consider returning a Vector3-instance 
    // instead, depends on how the result is used
    return {x: vector.x, y: vector.y};
  }
}) ();

但是,考虑到你想要渲染一个HUD,最好独立于主场景这样做,使上述所有计算都过时,并允许你选择一个不同的坐标系统来调整和定位HUD元素。

我在这里有一个例子:https://codepen.io/usefulthink/pen/ZKPvPB。在那里,我使用了一个正交相机和一个单独的场景来渲染三维场景之上的HUD元素。无需额外计算。另外,我可以方便地以像素为单位指定HUD元素的大小和位置(使用透视相机也可以使用相同的方法,只需要更多的三角测量即可)。