javascript - 调整摄像机以显示 Three.js 形状
我有一个立方体几何体,摄像机正对着它看,我希望摄像机缩放,使立方体完全可见,但不更大。
我最初的尝试是将立方体顶点转换到相机坐标系中,
function toScreenXY(position, camera) {
var pos = position.clone();
var projScreenMat = new THREE.Matrix4();
projScreenMat.multiply(camera.projectionMatrix, camera.matrixWorldInverse);
projScreenMat.multiplyVector3( pos );
return pos;
}
function ScaleInView() {
camera.fov = 0.0;
for (var i=0; i<8; i++) {
proj2d = toScreenXY(cube.geometry.vertices[i],camera);
angle = 57.296 * Math.max(Math.atan(proj2d.x/proj2d.z), Math.atan(proj2d.y/proj2d.z));
camera.fov = Math.max(camera.fov,angle);
}
camera.updateProjectionMatrix();
}
我以为这会有效,但有时它太小,有时又太大(取决于相机的位置)。
我也需要为正交相机做这个。
编辑:我知道当立方体面向相机时如何做这件事,我正在寻找一种方法,当相机移动到某个任意的 (r, theta, phi) 位置(球面坐标;对于我的目的,r 实际上是恒定的)时也能做到这一点。
答案#1
透视相机。如果相机居中并正面观察立方体,定义
dist=相机到立方体正面的距离(重要!)
和
height=立方体的高度。
如果你按如下方式设置相机的视野
fov = 2 * Math.atan( height / ( 2 * dist ) ) * ( 180 / Math.PI );
那么立方体的高度将与可见高度相匹配。
正交相机。如果相机居中并正对立方体观看,请定义
aspect=你窗口的宽高比(即宽度/高度)
和
height=立方体的高度。
然后这样构建你的相机:
camera = new THREE.OrthographicCamera( -aspect * height/2, aspect * height/2, height/2, -height/2, near, far );
立方体的高度将与可见高度相匹配。
无论哪种情况,如果相机没有居中,或者以某种角度观看立方体,那么问题就会更复杂。
此外,如果窗户的宽度比高度窄,那么宽度就是限制因素,问题就会更复杂。
答案#2
乘以 camera.matrixWorldInverse 会得到相机坐标系下的向量,但重要的是不会应用透视。
function toCameraCoords(position) {
return camera.matrixWorldInverse.multiplyVector3(position.clone());
}
然后,我们可以找到能够容纳场景中所有盒子角落的最小角度。arctan(D.x/D.z) 给出了角 BCD,其中 B 是相机所看的位置,C 是相机的位置,D 是你希望在相机坐标中可见的物体的位置。
在我的情况下,以下确保立方体边界框完全可见。
function ScaleInView() {
var tmp_fov = 0.0;
for (var i=0; i<8; i++) {
proj2d = toCameraCoords(boundbox.geometry.vertices[i]);
angle = 114.59 * Math.max( // 2 * (Pi / 180)
Math.abs(Math.atan(proj2d.x/proj2d.z) / camera.aspect),
Math.abs(Math.atan(proj2d.y/proj2d.z))
);
tmp_fov = Math.max(tmp_fov, angle);
}
camera.fov = tmp_fov + 5; // An extra 5 degrees keeps all lines visible
camera.updateProjectionMatrix();
}
