2012-01-05 6 views
1

私は、マウスのクリックで選択できるはずの3次元空間にいくつかの球を持っています。今私はgluUnProjectを使用していくつかの例を見てきましたので、私はそれを与えました。だから私は(私はそれのいずれかの部分の100%わからないので、私が間違っている場合は、私に方法のあらゆるステップを修正してください)があります。マウスで球を選択する

def compute_pos(x, y, z): 
    ''' 
    Compute the 3d opengl coordinates for 3 coordinates. 
    @param x,y: coordinates from canvas taken with mouse position 
    @param z: coordinate for z-axis 
    @return; (gl_x, gl_y, gl_z) tuple corresponding to coordinates in OpenGL context 
    ''' 
    modelview = numpy.matrix(glGetDoublev(GL_MODELVIEW_MATRIX)) 
    projection = numpy.matrix(glGetDoublev(GL_PROJECTION_MATRIX)) 
    viewport = glGetIntegerv(GL_VIEWPORT) 

    winX = float(x) 
    winY = float(viewport[3] - float(y)) 
    winZ = z 
    return gluUnProject(winX, winY, winZ, modelview, projection, viewport) 

次に、マウスクリックのxとyを持ちますそして、球の中心の位置:

だから、
def is_picking(x, y, point): 
    ray_start = compute_pos(x, y, -1) 
    ray_end = compute_pos(x, y, 1) 
    d = _compute_2d_distance((ray_start[0], ray_start[1]), 
          (ray_end[0], ray_end[1]), 
          (point[0], point[1])) 
    if d > CUBE_SIZE: 
     return False 

    d = _compute_2d_distance((ray_start[0], ray_start[2]), 
          (ray_end[0], ray_end[2]), 
          (point[0], point[2])) 
    if d > CUBE_SIZE: 
     return False 

    d = _compute_2d_distance((ray_start[1], ray_start[2]), 
          (ray_end[1], ray_end[2]), 
          (point[1], point[2])) 
    if d > CUBE_SIZE: 
     return False 
    return True 

私の3Dジオメトリは、私は線の開始と終了点として2点を計算し、全然良くないので、3回に1次元を排除する2Dに入ります時間と私の線と球の中心との間の距離を計算する。それらの距離のいずれかが私の球よりも大きい場合、それはクリックされません。私は、距離の式は正しいが、念のためだと思う:

def _compute_2d_distance(p1, p2, target): 
''' 
Compute the distance between the line defined by two points and a target point. 
@param p1: first point that defines the line 
@param p2: second point that defines the line 
@param target: the point to which distance needs to be computed 
@return: distance from point to line 
''' 
    if p2[0] != p1[0]: 
     if p2[1] == p1[1]: 
      return abs(p2[0] - p1[0]) 
     a = (p2[1] - p1[1])/(p2[0] - p1[0]) 
     b = -1 
     c = p1[1] + p1[0] * (p2[1] - p1[1])/(p2[0] - p1[0]) 
     d = abs(a * target[0] + b * target[1] + c)/math.sqrt(a * a + b * b) 
     return d 
    if p2[0] == p1[0]: 
     d = abs(p2[1] - p1[1]) 
     return d 
    return None 

は今のコードでは、スタート位置で正常に動作するようです。しかし、マウスを使って画面を少し回転させても、もう何も期待どおりに機能しません。

答えて

3

こんにちは、この種の問題の解決策はたくさんあります。

レイキャスティングは最高ですが、多くのジオメトリ知識が必要なため、まったく簡単ではありません。

さらに、gluUnProjectは、モバイルデバイス用のESなどの他のOpenGL実装では使用できません(ただし、行列操作関数に書き込むことはできます)。

私は個人的には非常に柔軟性があり、非常に高速な計算を行うカラーピッキングソリューションを好んでいます。

アイデアは、オフスクリーンバッファ上の特定の色で選択可能(パフォーマンスの向上のための選択肢のみ)をレンダリングすることです。

次に、ユーザーがクリックした座標でピクセルの色を取得し、対応する3Dオブジェクトを選択します。

乾杯 マウリツィオ・ベネデッティ入力用

+0

おかげで、しかし、私は本当に私は私の解決策にこれを適用することができるかどうか/分かりません。すべての選択可能な球体は同じ色でなければなりません。 – Bogdan

+0

もちろん、これを簡単に達成することができます。 これを実現するには、標準のレンダリングフレームに独自の色で球をレンダリングします。選択が完了すると、事前に割り当てられた色で平滑なシェーディングの方法でレンダリングを行いますライトはありません。説明するよりもはるかに実装が簡単です。 –

+0

"Maurizio Benedetti"が最適です。カラーピッカーが最適です。また、オブジェクトのポインタを色の値として使用することもできます。もちろん、64ビットのアプリケーションを作成する場合は、64ビットのテクスチャを使用するか、2つの32ビットテクスチャ間でポインタを分割する必要があります。 – zezba9000

関連する問題