代码之家  ›  专栏  ›  技术社区  ›  wackozacko

Three.js:在场景的一角显示世界坐标轴

  •  22
  • wackozacko  · 技术社区  · 12 年前

    我想在相机的右下角显示指示世界坐标方向(x,y,z)的箭头,就像在Maya中一样,这样当围绕对象旋转相机或在场景中移动时,仍然可以识别世界坐标的方向。


    我试着用两种不同的方法来实现这一点,但到目前为止都没有成功。

    我小时候用 THREE.ArrowHelper 同学们,我们称之为 XYZ 暂时。第一种方法是 XYZ公司 一个场景的子对象,并为其提供一个根据相机当前位置计算的位置,再加上相机指向的方向上的偏移,然后进行调整,使其向下显示在我想要的角落,而不是屏幕的中心。我几乎做到了,因为箭头保持了正确的旋转,但这个位置有点有趣,我停止了沿着这条路线走,因为在移动相机时真的很“紧张”。我不确定是性能问题还是其他问题。

    第二种方法是 XYZ公司 具有局部位置偏移的摄影机的子对象,然后反转摄影机的旋转并将反转的旋转应用于 XYZ公司 所以它与世界坐标相匹配。使用这种方法我似乎很接近,但我可以得到正确的位置或旋转,而不是两者都正确。

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

    如果有人能快速破解,那将不胜感激。如果你有一个比我追求的更好的方法,那也会很有帮助。

    4 回复  |  直到 2 年前
        1
  •  24
  •   xXx    7 年前

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

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

    参考文献: AxesHelper

        2
  •  21
  •   WestLangley    3 年前

    注意:这个答案适用于three.js的遗留版本。


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

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

    三个.js r.69

        3
  •  9
  •   seveibar    8 年前

    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);
    
        4
  •  3
  •   9301293    5 年前

    我知道现在有点晚了,但这是我的代码沙盒,它有一个渲染多个场景的解决方案 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);