2016-02-21 30 views
0

做了一个简单的jsFiddle example来说明问题。 我试图将对象的边框从不同的相机位置放到屏幕上。在dat.GUI面板中的示例中,您可以更改摄像头位置,然后单击按钮适合屏幕。适合从不同的Orthographic相机位置的屏幕

当改变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) 

;

回答

2

,以适应正视相机,你必须简单地改变它的大小和位置

你可以从

(我用的箱子从几何学的对象的边界框计算变焦,但你必须采取在组对象的核算矩阵;我用他们,因为.setFromObject没有使用这一点,因为你正在使用OrbitControls在拨弄将无法正常工作返回一致的值)

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(); 
}; 

,他们在更新BAS旋转摄像头ED对自己的状态 - 因此无论是更新该国或创建自己的控件

也无论是移动相机后回

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); 

编辑 现在我看到,你不想只适合对象,但整个盒子... 这样做一个简单的方法是投影箱的点,并获得像素的极值的距离,然后你可以直接设置正射相机

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); 

此代码也拉伸视图,从而精确匹配到窗口,以便你将不得不检查纵横比和相应地改变一个大小,但是这应该是微不足道

+0

更新[的jsfiddle](HTTPS: //jsfiddle.net/c12vdwbx/23/)与新的代码和禁用Orbitcontrols。我认为它面临与我的尝试计算顶部/底部/左/右参数相同的问题。在不同的摄像头位置上,边界框角不总是可见的。如果可能的话,我希望将边界框放入屏幕中而不使用0.95因子。我更新的小提琴代码有问题吗?谢谢。 – uhura

+0

从您的代码中借用了一个想法并添加到我的。我没有试图计算旋转,而是照相机旋转。那固定的负位置问题,但仍在偷工减料。 [更新代码](https://jsfiddle.net/c12vdwbx/24/) – uhura

+0

令人惊叹的,谢谢! – uhura