2012-01-08 19 views
1

私はカラーピッキングを実装しようとしています。問題は、最初に私のモデルをピッキングに使用される異なる色でペイントすると(私は、それぞれの三角形にid色である異なる色を与えます)、テクスチャなど何もない状態でうまく動作しますが、私はモデルのテクスチャを入れて、マウスがクリックされたときに、私はそれぞれの三角形に異なる色を与えることによって、モデルを描くことならば、それは仕事をdoesntの.. ここのコードです:OpenGLのカラーピックアップ

public int selection(int x, int y) {   
    GL11.glDisable(GL11.GL_LIGHTING); 
    GL11.glDisable(GL11.GL_TEXTURE_2D); 

    IntBuffer viewport = BufferUtils.createIntBuffer(16); 
    ByteBuffer pixelbuff = BufferUtils.createByteBuffer(16); 

    GL11.glGetInteger(GL11.GL_VIEWPORT, viewport);    

    this.render(this.mesh); 

    GL11.glReadPixels(x, y, 1, 1, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, pixelbuff); 

    for (int m = 0; m < 3; m++) 
     System.out.println(pixelbuff.get(m)); 

    GL11.glEnable(GL11.GL_TEXTURE_2D); 
    GL11.glEnable(GL11.GL_LIGHTING); 

    return 0; 
} 


public void render(GL_Mesh m, boolean inPickingMode) 
{ 
    GLMaterial[] materials = m.materials; // loaded from the .mtl file 
    GLMaterial mtl; 
    GL_Triangle t; 
    int currMtl = -1; 
    int i = 0; 

    // draw all triangles in object 
    for (i=0; i < m.triangles.length;) { 
     t = m.triangles[i]; 

     // activate new material and texture 
     currMtl = t.materialID; 
     mtl = (materials != null && materials.length>0 && currMtl >= 0)? materials[currMtl] : defaultMtl; 
     mtl.apply(); 
     GL11.glBindTexture(GL11.GL_TEXTURE_2D, mtl.textureHandle); 

     // draw triangles until material changes 
     for (; i < m.triangles.length && (t=m.triangles[i])!=null && currMtl == t.materialID; i++) { 
       drawTriangle(t, i, inPickingMode); 

     } 
    } 
} 

ます。private void drawTriangle(GL_Triangleは、 tは、あなたが見ることができるように、私は毎回呼ばれています選択機能を持つI、ブールinPickingMode){

if (inPickingMode) { 
     byte[] triColor = this.triangleToColor(i); 

     GL11.glColor3ub((byte)triColor[2], (byte)triColor[1], (byte)triColor[0]); 
    } 

    GL11.glBegin(GL11.GL_TRIANGLES); 

    GL11.glTexCoord2f(t.uvw1.x, t.uvw1.y); 
    GL11.glNormal3f(t.norm1.x, t.norm1.y, t.norm1.z); 
    GL11.glVertex3f((float)t.p1.pos.x, (float)t.p1.pos.y, (float)t.p1.pos.z); 

    GL11.glTexCoord2f(t.uvw2.x, t.uvw2.y); 
    GL11.glNormal3f(t.norm2.x, t.norm2.y, t.norm2.z); 
    GL11.glVertex3f((float)t.p2.pos.x, (float)t.p2.pos.y, (float)t.p2.pos.z); 

    GL11.glTexCoord2f(t.uvw3.x, t.uvw3.y); 
    GL11.glNormal3f(t.norm3.x, t.norm3.y, t.norm3.z); 
    GL11.glVertex3f((float)t.p3.pos.x, (float)t.p3.pos.y, (float)t.p3.pos.z); 

    GL11.glEnd(); 
} 

をint型マウスをクリックして、ライトニングとテクスチャを無効にしてから、シーンを再びユニークな色でレンダリングしてから、ピクセルバッファを読み込み、次の呼び出しを行います。 GL11.glReadPixels(x、y、1、1 、GL11.GL_RGB、GL11.GL_UNSIGNED_BYTE、pixelbuff); は私に間違った値を与えます ..と私を駆動ナッツ! レンダリングところで、主な機能は一例にはいくつかの問題がある

答えて

1

uが見ることができるように、あなたはまた、テクスチャがマウスをクリックする前に、モデルに存在していることがわかります(メッシュM、ブールinPickingModeを)...レンダリングです。

まず、マウスをクリックするとカラーとデプスバッファが消去されません(これにより、カラーポリゴンのシーンがテクスチャ付きポリゴンでシーンに混ざり、動作しなくなります)。

GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); 

第2に、カラーピッキングの際に材料を使用することはおそらく悪い考えです。私はGLMaterialクラスに精通していませんが、GL_COLOR_MATERIALや、照明が無効になっていても最終的な色を変更するその他のものを有効にする可能性があります。これを試してみてください:

if(!inPickingMode) { // === add this line === 
    // activate new material and texture 
    currMtl = t.materialID; 
    mtl = (materials != null && materials.length>0 && currMtl >= 0)? materials[currMtl] : defaultMtl; 
    mtl.apply(); 
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, mtl.textureHandle); 
} // === and this line === 

次に、色の選択には関係しませんが、理由がないためにglBegin()を頻繁に呼び出します。あなたは、三角形がループを描く前に、()レンダリングでそれを呼び出すことができます(それは、結果がどのように見えるか変更しないでください):

GL11.glBegin(GL11.GL_TRIANGLES); 
// draw triangles until material changes 
for (; i < m.triangles.length && (t=m.triangles[i])!=null && currMtl == t.materialID; i++) { 
     drawTriangle(t, i, inPickingMode); 
} 
GL11.glEnd(); 

---今私は少し元の質問に答える超えています - -

カラーピッキングに関することは、レンダラーが色を表すビット数が限られていることです(チャネルあたり5ビットというように)。したがって、これらのビットが設定されていない色を使用する必要があります。モバイルデバイスでこれを行うのは悪い考えかもしれません。

あなたのオブジェクトが十分に単純な場合(球で表現してピッキングすることができます)、オブジェクトをピッキングするにはレイトレーシングを使用することをお勧めします。かなりシンプルですが、モデルビュー投影行列を逆にして、点(mouse_x、mouse_y、-1)と(mouse_x、mouse_y、+1)を変換すると、マウスの位置がオブジェクト空間内の遠景平面の近くおよび遠くの平面にある。あなたがする必要があるのは、線の方向を得るためにそれらを引くことです(原点は近平面にあります)。この線を使ってオブジェクトを選ぶことができます(google ray-sphere intersection)。

float[] mvp = new float[16]; // this is your modelview-projection 
float mouse_x, mouse_y; // those are mouse coordinates (in -1 to +1 range) 
// inputs 

float[] mvp_inverse = new float[16]; 
Matrix.invertM(mvp_inverse, 0, mvp, 0); 
// inverse the matrix 

float nearX = mvp_inverse[0 * 4 + 0] * mouse_x + 
       mvp_inverse[1 * 4 + 0] * mouse_y + 
       mvp_inverse[2 * 4 + 0] * -1 + 
       mvp_inverse[3 * 4 + 0]; 
float nearY = mvp_inverse[0 * 4 + 1] * mouse_x + 
       mvp_inverse[1 * 4 + 1] * mouse_y + 
       mvp_inverse[2 * 4 + 1] * -1 + 
       mvp_inverse[3 * 4 + 1]; 
float nearZ = mvp_inverse[0 * 4 + 2] * mouse_x + 
       mvp_inverse[1 * 4 + 2] * mouse_y + 
       mvp_inverse[2 * 4 + 2] * -1 + 
       mvp_inverse[3 * 4 + 2]; 
float nearW = mvp_inverse[0 * 4 + 3] * mouse_x + 
       mvp_inverse[1 * 4 + 3] * mouse_y + 
       mvp_inverse[2 * 4 + 3] * -1 + 
       mvp_inverse[3 * 4 + 3]; 
// transform the near point 

nearX /= nearW; 
nearY /= nearW; 
nearZ /= nearW; 
// dehomogenize the coordinate 

float farX = mvp_inverse[0 * 4 + 0] * mouse_x + 
      mvp_inverse[1 * 4 + 0] * mouse_y + 
      mvp_inverse[2 * 4 + 0] * +1 + 
      mvp_inverse[3 * 4 + 0]; 
float farY = mvp_inverse[0 * 4 + 1] * mouse_x + 
      mvp_inverse[1 * 4 + 1] * mouse_y + 
      mvp_inverse[2 * 4 + 1] * +1 + 
      mvp_inverse[3 * 4 + 1]; 
float farZ = mvp_inverse[0 * 4 + 2] * mouse_x + 
      mvp_inverse[1 * 4 + 2] * mouse_y + 
      mvp_inverse[2 * 4 + 2] * +1 + 
      mvp_inverse[3 * 4 + 2]; 
float farW = mvp_inverse[0 * 4 + 3] * mouse_x + 
      mvp_inverse[1 * 4 + 3] * mouse_y + 
      mvp_inverse[2 * 4 + 3] * +1 + 
      mvp_inverse[3 * 4 + 3]; 
// transform the far point 

farX /= farW; 
farY /= farW; 
farZ /= farW; 
// dehomogenize the coordinate 

float rayX = farX - nearX, rayY = farY - nearY, rayZ = farZ - nearZ; 
// ray direction 

float orgX = nearX, orgY = nearY, orgZ = nearZ; 
// ray origin 

そして最後に - デバッグの提案:あなたが実際に画面上に描画されていること、それを何であるかを見ることができるようにinPickingModeをtrueに設定してレンダリングしてみてください。テクスチャやライティングが見える場合、何かが間違っていました。

+0

まずはお返事ありがとうございます、本当に申し訳ありません。 – gal