2016-02-21 53 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