自行实现相机管制中的旋转性能.
相机管制旋转
对于相机旋转比拟好的是应用球坐标系,绝对于直角坐标系而言,球坐标系用来形容旋转更加适合直观且对于方位角、极角而言属于线性扭转。对于线性函数咱们是十分喜爱的,因为线性代表简略,能用越简略的函数来形容关系的就越适宜。
再想一下如果应用笛卡尔坐标系来解决角度问题,那么肯定是个三角函数,三角函数复杂度大于线性函数,这是咱们不想看到的。
下图所示是球坐标系示意图:
代码解释
// 获取二维坐标 将本来在左上角的原点挪动到屏幕核心,当初取值范畴是[-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();