18

这可能是一个非常基本的问题,但我还没有找到解决方案,它一直困扰着我。我想在相机的右下角显示指示世界坐标方向(x,y,z)的箭头,就像在 Maya 中所做的那样,以便在围绕对象旋转相机或在场景中移动时,您仍然可以识别世界坐标的方向。我尝试使用两种不同的方法来实现这一点,但到目前为止都没有奏效。

我有一个带有三个箭头的对象作为使用THREE.ArrowHelper该类的子对象,我们XYZ暂时将其称为。第一种方法是创建XYZ场景的一个子节点,并为其提供一个根据相机当前位置计算的位置加上相机指向的方向的偏移量并进行调整,使其出现在我想要的角落而不是中心的屏幕。我几乎已经完成了这项工作,因为箭头保持正确的旋转,但位置有点有趣,我停止沿着这条路线走,因为在移动相机时真的很“紧张”。我不确定这是性能问题还是其他问题。

第二种方法是XYZ使用局部位置偏移制作相机的子级,然后反转相机的旋转并应用反向旋转,XYZ使其与世界坐标相匹配。我似乎使用这种方法很接近,但我可以得到正确的位置,或者正确的旋转,而不是两者。

我目前正在使用代码XYZ.matrix.extractRotation( camera.matrixWorldInverse );为我提供正确的方向XYZ,但它的定位已关闭。如果我使用XYZ.matrixWorld.extractRotation( camera.matrixWorldInverse );,则位置保持正常(连接到相机),但方向不会改变。

如果有人有一个快速的技巧来让它工作,那将不胜感激。如果您有比我正在追求的更好的方法,那也会有所帮助。

4

4 回答 4

21

使用新three.js版本,您可以使用:

var axesHelper = new THREE.AxesHelper( 5 );
scene.add( axesHelper );

参考:AxesHelper

于 2016-04-16T18:12:34.903 回答
20

这在此之前已经出现过。

诀窍是使用第二个摄像机添加第二个场景,该摄像机与原始摄像机具有相同的方向,但与原点保持指定距离。

camera2.position.copy( camera.position );
camera2.position.sub( controls.target );
camera2.position.setLength( CAM_DISTANCE );
camera2.lookAt( scene2.position );

编辑:更新小提琴:http: //jsfiddle.net/aqnL1mx9/

三.js r.69

于 2013-04-26T02:18:03.837 回答
7

var camera, scene, renderer, geometry, material, mesh, axisHelper, localToCameraAxesPlacement;

init();
animate();

function init() {

    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
    camera.position.z = 500;
    camera.up = new THREE.Vector3(0,0,1);
    scene.add(camera);
    
    axisHelper = new THREE.AxisHelper( 0.1 )
    localToCameraAxesPlacement = new THREE.Vector3(0.45 * camera.aspect,-0.45, -2); // make sure to update this on window resize
		scene.add(axisHelper)

    geometry = new THREE.CubeGeometry(200, 200, 200);
    material = new THREE.MeshNormalMaterial();

    mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);

    renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);

    document.body.appendChild(renderer.domElement);

}

function animate() {

    requestAnimationFrame(animate);
    render();

}

var t = 0
function render() {
    t++
    
    camera.position.x = Math.cos(t/80) * 500
    camera.position.y = Math.sin(t/80) * 500
    camera.lookAt(mesh.position)
    
    camera.updateMatrixWorld()
    var axesPlacement = camera.localToWorld(localToCameraAxesPlacement.clone())
		axisHelper.position.copy(axesPlacement);

    renderer.render(scene, camera);

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>

这是在不创建额外场景的情况下添加 AxisHelper 的“快速而肮脏”的方式。它通过在每次渲染时将轴助手移动到相机前面来工作。

// Initialize
var scene = getScene();
axisHelper = new THREE.AxisHelper( 0.1 );
var localToCameraAxesPlacement = new THREE.Vector3(0.45 * camera.aspect,-0.45,-2); // make sure to update this on window resize
scene.add(axisHelper);

// On every render
var camera = getCamera();
camera.updateMatrixWorld();
var axesPlacement = camera.localToWorld(localToCameraAxesPlacement.clone());
axisHelper.position.copy(axesPlacement);
于 2017-05-13T19:19:53.460 回答
2

我知道这有点晚了,但这是我的代码沙箱,它带有一个渲染多个场景的解决方案https://codesandbox.io/s/eager-glade-46ung

它可能有点笨拙,对 JS 来说是新的,等等。这是基于threejsfundamentals的教程。它使用这些renderer.setScissor函数来正确渲染碎石的不同部分。这也意味着您可以使用此设置来创建各种调试窗口......也许是一个用于轴助手的窗口,同时您可以跟踪您的主场景。

脚本的重要部分是定义将发生绘图的区域。这是通过将测量保持在 0-1 空间中来完成的,然后使用画布大小适当地缩放它们。

var nleft = Math.floor(canvas.width * left);
var nbottom = Math.floor(canvas.height * bottom);
var nwidth = Math.floor(canvas.width * width);
var nheight = Math.floor(canvas.height * height);
于 2019-11-24T22:34:27.697 回答