6

カメラが見ている CubeGeometry があり、カメラをズームして、立方体が完全に見えるようにしますが、大きくはなりません。

私の最初の試みは、立方体の頂点をカメラ座標系に変換することでした。

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は実際には私の目的では一定です)。

4

2 に答える 2

4

パースペクティブカメラ。カメラが中央に配置され、立方体を正面から見ている場合は、次のように定義します。

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

立方体の高さは、表示される高さと一致します。

いずれの場合も、カメラが中央に配置されていない場合、または立方体を斜めに見ている場合、問題はより複雑になります。

また、ウィンドウが高いよりも狭い場合、幅が制約要因となり、問題はより複雑になります。

于 2012-07-01T01:27:24.920 に答える
3

camera.matrixWorldInverse を乗算すると、カメラの座標にベクトルが得られますが、重要なことに、遠近法は適用されません。

function toCameraCoords(position) {
  return camera.matrixWorldInverse.multiplyVector3(position.clone());
}

次に、シーン内のすべてのボックス コーナーに適合する最小の角度を見つけることができます。arctan(Dx / Dz) は角度 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();
}
于 2012-08-02T04:51:39.273 に答える