Imaginary Code

from kougaku-navi.net

Processingで視点の位置・姿勢を取得する

3次元のCG空間において、空間に対する視点(カメラ)の位置・姿勢の情報が欲しいときがあります。例えば、監視カメラを表現したいときや、自分中心の移動を行いたいときなど。これに関するTipsを紹介します。

Processingでは、getMatrix()という命令を使うとモデルビュー行列を得ることができます。モデルビュー行列の中には、ローカル座標系からワールド座標系への変換(モデリング変換)と、ワールド座標系からカメラ座標系への変換(ビューイング変換)の2つの変換の情報が含まれています。



視点の位置・姿勢を設定する命令であるcamera()を実行した直後のモデルビュー行列は、モデリング変換の成分が単位行列になっているため、実質的にモデルビュー行列がビューイング変換を示す行列になっています。また、この行列を逆行列にすることで、カメラ座標系からワールド座標系への変換を得ることができます。これを利用することで、ワールド座標系から見た時の視点の位置・姿勢を計算することができます。

視点の前方、右方、下方を示す線を描画するサンプルコードを以下に示します。

void setup() {
  size(400, 300, P3D);
}

void draw() {
  background(200);

  PVector eye = new PVector();   // 視点1の目ん玉の位置
  PVector right = new PVector(); // 視点1の右方向を示す点
  PVector down = new PVector();  // 視点1の下方向を示す点

  pushMatrix(); 
    camera( 170, -100, 100, 0, 0, 0, 0, 1, 0 );  // 視点1
    PMatrix3D mat = (PMatrix3D)getMatrix();      // モデルビュー行列の取得
    mat.invert(); // 逆行列
    mat.mult( new PVector( 0, 0, 0 ), eye );     // カメラ座標系の(0,0,0)をワールド座標系の座標値に変換
    mat.mult( new PVector( 100, 0, 0 ), right ); // カメラ座標系の(100,0,0)をワールド座標系の座標値に変換
    mat.mult( new PVector( 0, 100, 0 ), down );  // カメラ座標系の(0,100,0)をワールド座標系の座標値に変換
  popMatrix();

  // マウスクリックで視点切り替え
  if ( mousePressed ) {
    camera( 170, -100, 100, 0, 0, 0, 0, 1, 0 );  // 視点1
  } else {
    camera( 220, -100, 520, 0, 0, 0, 0, 1, 0 );  // 視点2
  }

  strokeWeight(3);
  noFill();

  // 注視点(0,0,0)に立方体を置く
  stroke(0);
  box(100);

  // 視点1の右方向を示す線(赤)
  stroke(255, 0, 0);
  line( eye.x, eye.y, eye.z, right.x, right.y, right.z );

  // 視点1の下方向を示す線(緑)
  stroke(0, 255, 0);
  line( eye.x, eye.y, eye.z, down.x, down.y, down.z );

  // 視点1の視線方向を示す線(青)
  stroke(0, 0, 255);
  line( eye.x, eye.y, eye.z, 0, 0, 0);
}


視点2から見た様子(視点1の位置・姿勢を表わす線が見える)


視点1から見た時の様子