自行实现相机管制中的旋转性能.
相机管制旋转
对于相机旋转比拟好的是应用球坐标系,绝对于直角坐标系而言,球坐标系用来形容旋转更加适合直观且对于方位角、极角而言属于线性扭转。对于线性函数咱们是十分喜爱的,因为线性代表简略,能用越简略的函数来形容关系的就越适宜。
再想一下如果应用笛卡尔坐标系来解决角度问题,那么肯定是个三角函数,三角函数复杂度大于线性函数,这是咱们不想看到的。
下图所示是球坐标系示意图:
代码解释
// 获取二维坐标 将本来在左上角的原点挪动到屏幕核心,当初取值范畴是 [-1,1]
const offsetX = ((e.offsetX - mouseDownX) / dom.clientWidth) * 2;
const offsetY = ((e.offsetY - mouseDownY) / dom.clientHeight) * 2;
const matrix3 = new THREE.Matrix3();
mouseDownX = e.offsetX;
mouseDownY = e.offsetY;
// 记住本来相机的地位,咱们只挪动视角不挪动地位
cameraPosition.copy(camera.position);
let rotation = new THREE.Vector3(0, 0, -1);
// 获得相机的世界坐标的归一化坐标
rotation.applyNormalMatrix(matrix3.setFromMatrix4(camera.matrixWorld));
let spherical = new THREE.Spherical();
// 从归一化坐标设置球,能够说是将相机坐标映射到了半径为 1 的球坐标系上
// setFromVector3 用于设置 theta 和 phi, 等于是将笛卡尔坐标系换算成球坐标系
spherical.setFromVector3(rotation);
// 上一步将笛卡尔坐标系换算成球坐标系后,theta 和 phi 都是线性扭转的了,对 theta 和 phi 相加减即可
spherical.theta -= offsetX;
spherical.phi += offsetY;
spherical.makeSafe();
rotation.setFromSpherical(spherical);
// 相机挪动到原点 因为球坐标系在原点
camera.position.set(0, 0, 0);
camera.lookAt(rotation.x, rotation.y, rotation.z);
// 视角扭转后挪动到原地位,深藏功与名
camera.position.copy(cameraPosition);
camera.updateMatrixWorld();