在大型的三维模型里面,对模型进行旋转平移等操作,有时候能把头弄得晕头转向,找不着东南西北。所以今天我们自己实现一个方向控制盒子功能(自己定义的名字),实现过程不难,主要是一些以前学过的数学公式,实现的效果如下:
当我们旋转模型时,需要同步旋转左上角的方向控制盒,我们用到了两个场景,一个是处理方向控制器的小场景,一个是模型所在的大场景。假设在我们大场景里,设相机视点为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();
})