three.js实现一个方向控制盒子

1,247 阅读2分钟

在大型的三维模型里面,对模型进行旋转平移等操作,有时候能把头弄得晕头转向,找不着东南西北。所以今天我们自己实现一个方向控制盒子功能(自己定义的名字),实现过程不难,主要是一些以前学过的数学公式,实现的效果如下:

       当我们旋转模型时,需要同步旋转左上角的方向控制盒,我们用到了两个场景,一个是处理方向控制器的小场景,一个是模型所在的大场景。假设在我们大场景里,设相机视点为p1,相机的位置设为p2,我们只需要将p2到p1的向量单位化,所谓的单位化,就是方向保持不变,将其长度化为1。求出来的坐标位置就是小场景中相机的位置。

公式如下:

v = (p2 - p1)  /  |p2 - p1|

将坐标代入到公式中,算出来的 v 就是小场景的相机位置了,视点始终设为原点。

controls.addEventListener( 'change', function() {   
    var cameraPostion = camera.position; // 大场景相机位置   
    var vector = cameraPostion.clone().sub( controls.target ); //    
    var mu = Math.sqrt( Math.pow( vector.x, 2 ) + Math.pow( vector.y, 2 ) + Math.pow( vector.z, 2 ) ) / 2; // 求模,除以2是因为z轴上的值不够,相机的位置处于盒子里边   
    var smallCameraPostion = new THREE.Vector3( vector.x / mu, vector.y / mu, vector.z / mu ); // 单位化​   
    smallCamera.position.set( smallCameraPostion.x, smallCameraPostion.y, smallCameraPostion.z );   
    smallCamera.lookAt( smallScene.position );   
    smallCamera.updateProjectionMatrix(); 
})

change 事件是three.js OrbitControls控制中的一个事件,可以监听模型的旋转、平移、放大缩小的操作。这里需要注意的是,向量单位化之后,z轴的值可能不够,相机位置在盒子里面,所以这里我们除了个2。

这个只是旋转大场景的时候,小场景跟着联动,下面我们要对小场景的盒子进行操作,大场景也一起联动。

公式如下:

p2' = p1 + |p2-p1| * p3

同样监听 change 事件,对数据进行处理

smallControls.addEventListener( 'change', function(render) {    
    var cameraPostion = camera.position;    
    var smallCameraPostion = smallCamera.position;    
    var target = controls.target;    
    var vec1 = cameraPostion.clone().sub( target );    
    var mu = Math.sqrt( Math.pow( vec1.x, 2 ) + Math.pow( vec1.y, 2 ) + Math.pow( vec1.z, 2 ) ) / 2;    
    var newCameraPosition = target.clone().add( new THREE.Vector3( smallCameraPostion.x * mu, smallCameraPostion.y * mu, smallCameraPostion.z * mu ) );    
    camera.position.set( newCameraPosition.x, newCameraPosition.y, newCameraPosition.z );    
    camera.updateProjectionMatrix();
})