2013-08-08 50 views
5

私のアプリケーションではに3Dオブジェクトを作成しました。オブジェクトは人体のようなもので、タッチで回転させることができます。この3Dオブジェクトのタッチの位置をどのように検出できますか?ユーザーが頭に触れたら、頭であることを検出する必要があります。タッチが手の上にある場合、それは特定されなければならない。オブジェクトが別の方向に回転しても動作するはずです。私は、3Dオブジェクトのタッチ座標が必要だと思います。
これは私がビューのタッチの位置を取得しているメソッドです。OpenGLでの3Dオブジェクトのタッチ位置の検出

- (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event 
{ 
    UITouch* touch = [touches anyObject]; 
    CGPoint location = [touch locationInView: self]; 
    m_applicationEngine->OnFingerDown(ivec2(location.x, location.y)); 
} 

誰でも手助けできますか?前もって感謝します!

答えて

5

RayTracingと他のトップノッチアルゴリズムについては忘れてしまいます。私たちは、App Store上の私たちのアプリケーション(Iyan 3D)のための簡単なトリックを使いました。しかし、このテクニックでは、シーンを新しい角度に回転させるたびに、追加のレンダリングパスが1つ必要です。異なるオブジェクト(頭、手、足など)を異なる色(実際の色ではなく、固有のもの)でレンダリングします。スクリーン位置に対応するレンダリングされたイメージの色を読み取ります。その色に基づいてオブジェクトを見つけることができます。

この方法では、レンダリングされたイメージの解像度を使用して、精度とパフォーマンスのバランスをとることができます。

+0

+1 - 技術を実装するのは非常に簡単で簡単です。ここではProcessing(Javaのようなもの)にもっと多くの情報とソースコードがあります - http://wiki.processing.org/w/Picking_with_a_color_buffer – cyriel

+0

このトピックにはどのサンプルコードもありますか? –

+0

レンダリングのためにテクスチャにレンダリングを検索します。そうすれば、色を見つけるのは簡単です。 http://stackoverflow.com/questions/8439697/opengl-es-2-0-render-to-texture – codetiger

4

オブジェクトの3D位置を特定するには、レイトレーシングをお勧めします。

モデルがワールドスペース座標であると仮定すると、アイ・ロケーションのワールド空間座標とイメージ・プレーンのワールド空間座標も知る必要があります。これら2つの点を使って、モデルと交差するために使う線を計算することができます。線は三角形で構成されています。

次に、レイ・トライアングル・テストを使用して、イメージ・プレーンに最も近い交差点を持つ三角形を見つけることによって、タッチの3D位置を決定することができます。どの三角形をタッチするかを知りたい場合は、交差テストを行うときにその情報を保存することもできます。

このページでは、光線三角形の交差テストを行う方法の例を示します:http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-9-ray-triangle-intersection/ray-triangle-intersection-geometric-solution/

編集:いくつかのサンプルコードを持つように更新

。ちょっと前に私が行ったC++レイトレーシングプロジェクトから少し修正したコードをいくつか修正して、iOS用に少し修正する必要があります。また、現行の形式のコードは、実際の交点を返さず、光線が三角形と交差するかどうかにかかわらず有用ではありません。あなたが興味がある

// d is the direction the ray is heading in 
// o is the origin of the ray 
// verts is the 3 vertices of the triangle 
// faceNorm is the normal of the triangle surface 
bool 
Triangle::intersect(Vector3 d, Vector3 o, Vector3* verts, Vector3 faceNorm) 
{ 
    // Check for line parallel to plane 
    float r_dot_n = (dot(d, faceNorm)); 

    // If r_dot_n == 0, then the line and plane are parallel, but we need to 
    // do the range check due to floating point precision 
    if (r_dot_n > -0.001f && r_dot_n < 0.001f) 
     return false; 

    // Then we calculate the distance of the ray origin to the triangle plane 
    float t = (dot(faceNorm, (verts[0] - o))/r_dot_n); 
    if (t < 0.0) 
     return false; 

    // We can now calculate the barycentric coords of the intersection 
    Vector3 ba_ca = cross(verts[1]-verts[0], verts[2]-verts[0]); 
    float denom = dot(-d, ba_ca); 

    dist_out = dot(o-verts[0], ba_ca)/denom; 
    float b = dot(-d, cross(r.o-verts[0], verts[2]-verts[0]))/denom; 
    float c = dot(-d, cross(verts[1]-verts[0], o-verts[0]))/denom; 

    // Check if in tri or if b & c have NaN values 
    if ( b < 0 || c < 0 || b+c > 1 || b != b || c != c) 
     return false; 

    // Use barycentric coordinates to calculate the intersection point 
    Vector3 P = (1.f-b-c)*verts[0] + b*verts[1] + c*verts[2]; 

    return true; 
} 

実際の交点がP.

+0

iOSでこの線三角形の交差点を使用してサンプルコードを取得できますか? –

+0

私はいくつかのサンプルコードを追加しました。これは何を計算する必要があるかを示しています。 C++の私の古いプロジェクトの1つからそれを取り出したので、簡単に理解できるはずです。また、関数の戻り値はあなたが探しているものではありませんが、交差点が計算される関数の終わりはあなた自身のために有用な形式に変換できるはずです。 – illeyezur

+0

ありがとうございました!これを試してみましょう。 –

2

レイトレーシングはオプションですと(ピッキング)ちょうどそれを行うための多くのアプリケーションで使用されています。レイトレーシングの問題は、このソリューションは非常に簡単な基本機能を動作させるための多くの作業であるということです。また、レイ・トレーシングは遅くなることがありますが、トレースするレイが1つしかない場合(指の位置がわかります)、大丈夫です。

OpenGLのAPIはオブジェクトを選択するテクニックも提供します。 http://www.lighthouse3d.com/opengl/picking/

最後に、最後のオプションは、画面空間にオブジェクトの頂点を投影し、単純な2次元技法を使用して、オブジェクトのどの面が重なっているかを調べることです。

+0

ESはピッキングAPIを提供していませんが、独自の色でレンダリングされた各ポリゴンでレンダリングを実行し、タッチ位置で色をつかむために 'glReadPixels'を使用するか、非常に近い表面を穴で塗りつぶし、分割されたジオメトリとオクルージョンクエリー(メモリが使用されている場合はiOS 5でiOS上で提供されています)を続けることに基づいて、より精巧ですがおそらくより効率的なシステムです。セグメントが閉じている場合は、カバーをバックグラウンドに置き、深度テストを反転することによって描画する際に、オクルージョンを行うことができます。 – Tommy

関連する問題