LoginSignup
12
13

More than 5 years have passed since last update.

逆射影変換でマウス位置を3D空間に表示してみる

Last updated at Posted at 2013-09-19

いわゆるRayCast的なことを自前でやってみるテスト。
気づいたことや分かったことを徒然とまとめていきます。

実際に作ってみたjsdo.itのデモはこちら

手順

  1. 手順はまず、マウス座標をビューポートの逆変換をする(これは-1〜1の間に収まるようにするだけ。ただし、Y座標の扱いに注意)
  2. 次に、ProjectionMatrixの逆行列を生成する
  3. さらにViewMatrixの逆行列を生成する
  4. 求めた行列を使ってプロジェクションを適用する関数を通して変換する(逆射影変換も結局は射影変換ってこと?)
// スクリーン上のマウス位置3D空間内の座標系に変換(ビューポート行列の逆を行う)
mouseX =  (mouseX/SCREEN_WIDTH) * 2 - 1;
mouseY = -(mouseY/SCREEN_HEIGHT) * 2 + 1;

とりあえず、Three.jsの中を覗いて見たものをメモ。
↓まずはProjector.js内で行われているunprojectVectorの処理。

Projector.js
this.unprojectVector = function ( vector, camera ) {
    camera.projectionMatrixInverse.getInverse( camera.projectionMatrix );

    _viewProjectionMatrix.multiplyMatrices( camera.matrixWorld, camera.projectionMatrixInverse );

    return vector.applyProjection( _viewProjectionMatrix );

};

getInverseメソッドで、カメラのprojectionMatrixの逆行列をprojectioMatrixInverseに保存。
この逆行列とカメラ位置をかけたものを_viewProjectionMatrixに保存

これらを用いて、渡されたvectorapplyProjectionを適用している。

最終的に出来た部分

//プロジェクション変換マトリクスの生成
var projMatrix = mat4.perspective(60, w / h, 1, 100, mat4());

//ビュー座標変換マトリクスの生成
var viewMatrix = mat4.lookAt(vec3(0, 0, z), vec3(0, 0, 0), vec3(0, 1, 0));

//モデル変換マトリクスを生成
var modelMatrix = mat4();

//最終的に使用されるMVP合算マトリクスを生成
var mvpMatrix   = mat4();

//...中略

//他で取得したマウスの位置を元に3次ベクトルを生成(この時点でmouse.x, mouse.yともに-1〜1の間になるよう補正済)
var pos = vec3(mouse.x, mouse.y, 0);

//プロジェクションの逆行列を生成
var invProjMatrix = mat4.inverse(projMatrix);

//ビューの逆行列を生成
var invViewMatrix = mat4.inverse(viewMatrix);

//上記の計算結果用
var res = mat4();

//生成した逆行列を掛ける
mat4.multiply(invViewMatrix, invProjMatrix, res);

//できあがった行列をマウス座標に適用する
pos = vec3.applyProjection(pos, res);

参考記事

12
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
13