マウスクリック座標からWebGL 3Dスペースでオブジェクトを取得する方法

StackOverflow https://stackoverflow.com/questions/7364693

質問

WebGLでボードゲームを構築しています。ボードを回転/ズームすることができます。 Canvas要素(x、y)のクリックを3D空間(x、y、z)の関連ポイントに変換する方法が必要です。最終的な結果は、ユーザーに最も近いオブジェクトに触れるポイントを含む(x、y、z)座標を知りたいということです。たとえば、ユーザーはピースをクリックし、ピースとゲームボードの両方を通過する3Dスペースを移動するレイを想像しますが、ピースの(x、y、z)座標が必要な時点で、触れた。

これは非常に一般的な問題であるに違いないと思いますが、グーグルに解決策を見つけることができないようです。 3Dスペースの現在のビューを2Dに投影するには、2Dスペースの各ポイントを3Dスペースの関連ポイントにマッピングできるようにする方法が必要です。ボード上のスペースの上にネズミをマウスし、スポットを変更できるようにしたいと考えています。

役に立ちましたか?

解決

画面座標をカメラの位置から3Dワールドにレイキャストに変換する不定関数を探しています。次に、光線と三角形の交差点テストを実行して、カメラに最も近い三角形を見つける必要があります。

で利用可能な未処理の例があります jax/camera.js#l568 - ただし、レイ/トライアングルの交差点を実装する必要があります。私はそれを実装しています jax/triangle.js#l113.

ただし、「ピッキング」と呼ばれるよりシンプルで(通常)より高速な代替品があります。オブジェクト全体(たとえば、チェスピース)を選択する場合、およびマウスが実際にクリックした場所を気にしない場合は、これを使用してください。これを行うWebGlの方法は、シーン全体をさまざまな青の色合い(青はキーであり、赤と緑がシーン内のオブジェクトの一意のIDに使用されます)でテクスチャにレンダリングし、からのピクセルを読み返します。そのテクスチャー。 RGBをオブジェクトのIDにデコードすると、クリックされたオブジェクトが表示されます。繰り返しますが、私はこれを実装しました、そしてそれはで利用可能です jax/world.js#l82. 。 (146、162、175という行も参照してください。)

どちらのアプローチにも長所と短所があります(議論されています ここ そして、その後のいくつかのコメントで)そして、あなたはあなたのニーズに最適なアプローチを把握する必要があります。ピッキングは巨大なシーンで遅くなりますが、純粋なJSでの紹介は非常に遅いです(JS自体がそれほど速くないため)。私の最善の推奨事項は両方を試すことです。

参考までに、GLUプロジェクトと不定コードを見ることもできます。 http://www.opengl.org/wiki/gluproject_and_gluunproject_code

他のヒント

私は現在この問題に取り組んでいます - 私が取っているアプローチは

  1. オブジェクトをレンダリングして、それぞれを一意の色で選択します
  2. バッファピクセルを読み取り、選択したオブジェクトに戻ります
  3. 各ピクセル色でバッファーに選択したオブジェクトをz-depthの関数でバッファーします
  4. バッファピクセルを読み取り、Z-Depthに戻ります
  5. ピック座標のオブジェクトと近似Zを選択しました

これが機能するデモです

function onMouseUp(event) {

    event.preventDefault();        
    x_pos = (event.clientX / window.innerWidth) * 2 - 1;
    y_pos = -(event.clientY / window.innerHeight) * 2 + 1;
    z_pos = 0.5;

    var vector = new THREE.Vector3( x_pos , y_pos , z_pos );

    var projector = new THREE.Projector();
    projector.unprojectVector(vector, camera);
    var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
    var intersects = raycaster.intersectObjects(intersectObjects);

    if (intersects.length > 0) {

        xp = intersects[0].point.x.toFixed(2);
        yp = intersects[0].point.y.toFixed(2);
        zp = intersects[0].point.z.toFixed(2);  
        destination = new THREE.Vector3( xp , yp , zp );

        radians =  Math.atan2( ( driller.position.x - xp) , (driller.position.z - zp));
        radians += 90 * (Math.PI / 180);
        console.log(radians);

        var tween = new TWEEN.Tween(driller.rotation).to({ y : radians },200).easing(TWEEN.Easing.Linear.None).start();

    }

weissner-doors.de/drone/

スレッドの1つから栽培されています。 (x、y、z)についてはわかりませんが、 canvas(x,y) 使用

getBoundingClientRect()

function getCanvasCoord(){
  var mx = event.clientX;
  var my = event.clientY;
  var canvas = document.getElementById('canvasId');
  var rect = canvas.getBoundingClientRect();// check if your browser supports this
  mx = mx - rect.left;
  my = my - rect.top;
  return {x: mx , y: my};
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top