制作一个简单的jsFiddle example来说明问题。 我试图让对象的边界框适合从不同的摄像机位置进行屏幕显示。在dat.GUI面板中的示例中,您可以更改摄像机位置,然后单击适合屏幕的按钮。
更改y和z(正)相机位置以查找相机的顶部和底部属性代码时使用
var top = boundingBox.max.y * Math.cos(angleToZAxis) + boundingBox.max.z * Math.sin(angleToZAxis); // line 68
var bottom boundingBox.min.y * Math.cos(angleToZAxis) + boundingBox.min.z * Math.sin(angleToZAxis);
我想知道如何在此计算中包含相机的x位置和负位置,这背后的数学是什么。我应该使用旋转矩阵以及如何使用它?
或者也许可以用一些简单的方法用threejs方法实现,但是不能弄清楚,尝试下面的代码但是出了点问题:
var matrix = new THREE.Matrix4();
matrix.lookAt ( this.camera.position, new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 1, 0) );
var bbMax = boundingBox.max.clone().applyMatrix4(matrix);
var bbMin = boundingBox.min.clone().applyMatrix4(matrix)
答案 0 :(得分:2)
要适合正交相机,您只需更改其缩放和位置
您可以从对象的边界框计算缩放
(我使用几何中的方框,但你必须考虑组中对象的帐户矩阵;我使用它们是因为.setFromObject没有返回一致的值)
Canvas3D.prototype.fitToScreen = function() {
this.group.children[0].geometry.computeBoundingBox();
var boundingBox = this.group.children[0].geometry.boundingBox.clone();
this.group.children[1].geometry.computeBoundingBox();
boundingBox.union(this.group.children[1].geometry.boundingBox);
var rotation = new THREE.Matrix4().extractRotation(this.camera.matrix);
boundingBox.applyMatrix4(rotation);
this.camera.zoom = Math.min(this.winWidth / (boundingBox.max.x - boundingBox.min.x),
this.winHeight / (boundingBox.max.y - boundingBox.min.y)) * 0.95;
this.camera.position.copy(boundingBox.center());
this.camera.updateProjectionMatrix();
this.camera.updateMatrix();
};
使用它将无法在您的小提琴中使用,因为您正在使用OrbitControls并根据自己的状态在更新时旋转相机 - 因此要么更新该状态,要么创建自己的控件
也可以在
后移回相机this.camera.position.copy(boundingBox.center());
或将近平面设置为-1000以避免切割对象
this.camera = new THREE.OrthographicCamera(this.winWidth / -2,
this.winWidth / 2 , this.winHeight / 2, this.winHeight / -2, -10000, 10000);
EDIT 现在我看到你不想只是适合对象而是整个盒子...... 这么做一个简单的方法是投影框的点并获得极端的距离(以像素为单位),然后你可以直接设置正射相机
boundingBox = new THREE.Box3().setFromObject(this.group);
//take all 8 vertices of the box and project them
var p1 = new THREE.Vector3(boundingBox.min.x,boundingBox.min.y,boundingBox.min.z).project(this.camera);
var p2 = new THREE.Vector3(boundingBox.min.x,boundingBox.min.y,boundingBox.max.z).project(this.camera);
var p3 = new THREE.Vector3(boundingBox.min.x,boundingBox.max.y,boundingBox.min.z).project(this.camera);
var p4 = new THREE.Vector3(boundingBox.min.x,boundingBox.max.y,boundingBox.max.z).project(this.camera);
var p5 = new THREE.Vector3(boundingBox.max.x,boundingBox.min.y,boundingBox.min.z).project(this.camera);
var p6 = new THREE.Vector3(boundingBox.max.x,boundingBox.min.y,boundingBox.max.z).project(this.camera);
var p7 = new THREE.Vector3(boundingBox.max.x,boundingBox.max.y,boundingBox.min.z).project(this.camera);
var p8 = new THREE.Vector3(boundingBox.max.x,boundingBox.max.y,boundingBox.max.z).project(this.camera);
//fill a box to get the extremes of the 8 points
var box = new THREE.Box3();
box.expandByPoint(p1);
box.expandByPoint(p2);
box.expandByPoint(p3);
box.expandByPoint(p4);
box.expandByPoint(p5);
box.expandByPoint(p6);
box.expandByPoint(p7);
box.expandByPoint(p8);
//take absolute value because the points already have the correct sign
var top = box.max.y * Math.abs(this.camera.top);
var bottom = box.min.y * Math.abs(this.camera.bottom);
var right = box.max.x * Math.abs(this.camera.right);
var left = box.min.x * Math.abs(this.camera.left);
this.updateCamera(left, right, top, bottom);
此代码还会拉伸视图以完全适合窗口,因此您必须检查宽高比并相应地更改一个尺寸,但这应该是微不足道的