我想在鼠标移动时将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
};
}
答案 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元素的大小和位置(使用透视相机也可以使用相同的方法,只需要更多的三角测量即可)。