2012-01-08 4 views
1

Я пытался реализовать выбор цвета, и это просто не работает. проблема в том, что если сначала нарисовать мою модель в разных цветах, которые используются для выбора (я имею в виду, я даю каждому треугольнику другой цвет, который является его цветом), он отлично работает (без текстуры или чего-то еще), но если я положил текстуру модели, и что при щелчке мыши я окрасить модель, давая каждый треугольник в другой цвет, он не работает .. вот код:Выбор цвета в 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); 

     } 
    } 
} 

частная пустота drawTriangle (GL_Triangle т, INT 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(); 
} 

, как вы можете видеть, у меня есть функция выбора, которая вызывается каждый раз щелкнуть мышью, затем отключить подсветку и текстуру, а затем снова визуализировать сцену в уникальных цветах, а затем прочитать буфер пикселов и вызвать: GL11.glReadPixels (x, y, 1, 1 , GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, pixelbuff); дает мне неправильные значения .. и его вождение меня nutz! btw, основная функция рендеринга визуализируется (mesh m, boolean inPickingMode), как вы можете видеть, вы также можете увидеть, что текстура на модели перед щелчком мыши.

ответ

1

есть несколько проблем с примером.

Во-первых, вы не очищаете цвет и буфер глубины при нажатии мыши (что приводит к смещению сцены с цветными полигонами в сцену с текстурированными многоугольниками, а затем она не работает). вам необходимо позвонить:

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

Во-вторых, это, вероятно, плохая идея использовать материалы при выборе цвета. Я не знаком с классом 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 бит на канал), поэтому вам нужно использовать цвета, которые не имеют этих битов. Это может быть плохой идеей сделать это на мобильном устройстве.

Если ваши объекты достаточно просты (могут быть представлены, например, сферой, для выбора), может быть хорошей идеей использовать raytracing для выбора объектов. Это довольно просто, идея состоит в том, что вы берете обратную матрицу проекции-проекции и преобразуете точки (mouse_x, mouse_y, -1) и (mouse_x, mouse_y, +1) им, что даст вам положение мыши на рядом и в дальнем плане зрения, в пространстве объектов. Все, что вам нужно сделать, это вычесть их, чтобы получить направление луча (происхождение находится на ближней плоскости), и вы можете выбрать свои объекты с помощью этого луча (пересечение лучей google-сферы).

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 установлен верно, так что вы можете увидеть, что это такое, что вы на самом деле рисования на экране.Если вы видите текстуру или освещение, то что-то пошло не так.

+0

Прежде всего, спасибо за ответ, я действительно его утвержу. – gal

Смежные вопросы