假设您有一个由世界坐标中的位置和观察点(或枢轴点)描述的相机,则缩放(或远离)特定点的核心是非常简单的。
你的表示似乎更简单:只是一个位置/距离对。我没有看到旋转组件,所以我假设你的相机是自上而下的正交相机。
在这种情况下,您的观察点(您不需要)只是(position.x, position.y - distance, position.z)
.
在一般情况下,您所需要做的就是将相机位置和观察点移向变焦点,同时保持相机法线(即方向)。请注意,无论投影类型或相机旋转如何,这都将起作用。编辑(2020/05/01):使用正交投影时,这不是您需要做的全部(请参阅底部的更新)。
如果您仔细想想,这正是您在 3D 中缩放某个点时所发生的情况。你一直看着同一个方向,但你越来越接近(但从未达到)你的目标。
例如,如果您想要缩放 1.1 倍,您可以想象将连接相机位置和缩放点的矢量缩放 1/1.1。
您可以通过简单地插值来做到这一点:
var newPosition = new THREE.Vector3();
newPosition.x = (orgPosition.x - zoomAt.x) / zoomFactor + zoomAt.x;
newPosition.y = (orgPosition.y - zoomAt.y) / zoomFactor + zoomAt.y;
newPosition.z = (orgPosition.z - zoomAt.z) / zoomFactor + zoomAt.z;
正如我上面所说,在您的情况下,您实际上不需要更新观察点,然后计算新距离。您的新距离将是:
var newDistance = newPosition.y
应该可以做到这一点。
如果您想在位置/观察点和位置/缩放点对之间设置最小和最大距离限制,它只会变得更加复杂一点(主要是在一般情况下)。
更新(2020/05/01):
我刚刚意识到,上述内容虽然是正确的(除了缺少一个小但非常重要的步骤),但并不是对OP问题的完整答案。在正交模式下更改相机的位置当然不会改变正在渲染的图形的比例。为此,必须更新相机的投影矩阵(即必须更改正交投影的左、右、上、下参数)。
因此,许多图形库在其正交相机类中包含缩放因子,这正是这样做的。我没有使用 ThreeJS 的经验,但我认为该属性称为“缩放”。
所以,总结一下一切:
var newPosition = new THREE.Vector3();
newPosition.x = (orgPosition.x - zoomAt.x) / zoomFactor + zoomAt.x;
newPosition.y = (orgPosition.y - zoomAt.y) / zoomFactor + zoomAt.y;
newPosition.z = (orgPosition.z - zoomAt.z) / zoomFactor + zoomAt.z;
myCamera.zoom = myCamera.zoom * zoomFactor
myCamera.updateProjectionMatrix()
如果您想使用上面的正交相机类代码,您可能必须更改计算左、右、上和下的部分,并在计算中添加缩放因子。这是一个例子:
var aspect = this.viewportWidth / this.viewportHeight
var dX = (this.right - this.left)
var dY = (this.top - this.bottom) / aspect
var left = -dX / (2 * this.scale)
var right = dX / (2 * this.scale)
var bottom = -dY / (2 * this.scale)
var top = dY / (2 * this.scale)
mat4.ortho(this.mProjection, left, right, bottom, top, this.near, this.far)