2012-04-03 32 views
0

私は、3Dシーンが表示され、画面をクリック/タップして領域を選択できるAndroidアプリケーションを開発中です。場面はかなり異なる平面の(ゲーム)ボードです。
問題は、ボード上のクリックした領域を実際のスクリーンスペース座標からどのように取得するのかです。モデル空間の座標への投影空間の逆投影

(ほとんど)すべての必要なパラメータにアクセスできるので、gluUnProject()を使用する予定です。残念ながら、私はwinZパラメータを紛失しており、タッチイベントがGLスレッドとは異なるスレッドで発生しているため、現在の深さを取得できません。
私の新しい計画では、gluUnProjectを使用していますが、winZが0である場合、結果ポイントをボードに投影します(ボードスペースはから10,0,10まで伸びます)。しかし、これを行う方法?

誰かがこれを行うために必要な数学を助けてくれたら(行列は私の最強の側面ではなかった)、もっと良い解決策を見つけることができたらとてもうれしいです。

明確にする。 image
赤い矩形はデバイスの画面を表し、緑色のxはタッチイベントを表し、黒い四角形はボード(灰色の細分は1単位の正方形を表します)です。私はタッチがどこで起こったのかを把握する必要があります(この場合、正方形である1,1)。

答えて

0

だから、私は、次の手順を実行してこの問題を解決するために管理:

float[] clipPoint = new float[4]; 
int[] viewport = new int[]{0, 0, width, height}; 

//screenY/screenX are the screen-coordinates, y should be flipped: 
screenY = viewport[3] - screenY; 

//Calculate a z-value appropriate for the far clip: 
float dist = 1.0f; 
float z = (1.0f/clip[0] - 1.0f/dist)/(1.0f/clip[0]-1.0f/clip[1]); 

//Use gluUnProject to create a 3d point in the far clip plane: 
GLU.gluUnProject(screenX, screenY, z, vMatrix, 0, pMatrix, 0, viewport, 0, clipPoint, 0); 

//Get a point representing the 'camera': 
float eyeX = lookat[0] + eyeOffset[0]; 
float eyeY = lookat[1] + eyeOffset[1]; 
float eyeZ = lookat[2] + eyeOffset[2]; 

//Do some magic to calculate where the line between clipPoint and eye/camera would intersect the y-plane: 
float dX = eyeX - clipPoint[0]; 
float dY = eyeY - clipPoint[1]; 
float dZ = eyeZ - clipPoint[2]; 

float resX = glu[0] - (dX/dY)*glu[1]; 
float resZ = glu[2] - (dZ/dY)*glu[1]; 
//resX and resZ is the wanted result. 
1

基本的にはすでに2Dで作業しているので(3Dボードが0,0,0から10,10,0(x、y、z)まで伸びていることを意味します)、翻訳/補間/補外gluUnProject()を使用せずに、画面空間の座標から2D/3D空間の座標を調整します。画面の解像度が必要で、変換する3D空間グリッドの解像度を選択する必要があります。画面と3D空間の原点の両方が整列されている(0,0画面空間が0,0,0 3D空間にある)場合、画面の寸法は320x240で、既存の10x10 3Dグリッド、次に320/10 = 32、および240/10 = 24であり、したがって、1x1の単一領域のスクリーンスペースサイズは32x24です。したがって、ユーザが162,40を押すと、ユーザは、3D空間内で、(5,1,0)(162/32> = 5であるが、< 6,40/24> = 1であるが、<)を押す。これ以上の解像度が必要な場合は、より高い3D空間グリッド解像度(10の代わりに20を使用)を選択できます。この要素を使用するには、GL行列を更新する必要はありません。それはいくつかの点でそれを単純化するかもしれませんが、モデリングの観点からすれば、あなたは追加作業が必要になるでしょう。ちょうど20のような要因に気をつけてください、1,3は(.5、1.5、0)になります。画面と3D空間の原点がまだ整列していない場合は、これに先立って画面空間の座標を変換する必要があります。 0,0スクリーンスペースが10,10,0の場合は、スクリーン解像度を取り、そこから現在のポイントを引く必要があります。この例では320,040に0,0を設定し、例ポイント162,40は158(320-158 == 162)、200(240-200 == 40)となります。

投影行列の概要と、それがどのように動作するかを知りたい場合は、スクリーンスペースの寸法を非投影行列に入れる場所を理解するのに役立ちます。この章のOpenGL赤い本を読んでください。 http://www.glprogramming.com/red/chapter03.html

これは役立ちます、そして幸運!

+0

は、あなたの答えをありがとう、残念ながらそれは簡単ではありません、ボードはそう単純で、視線方向に対して垂直ではありませんこのようなソリューションは機能しません。 問題を視覚化するのに役立つ簡単なグラフィックで質問を更新しました。 – Jave

+0

ああ、私は飛行機/ボードが世界ではなくMODEL空間で記述されていることを意味しています(今は編集できません、電話で書く) – Jave

関連する問題