2012-01-13 110 views
2

我有需要跨平臺的wxPython + pyOpenGL應用程序。現在供選擇我實現了一個顏色選擇方案,主要如下:pyOpenGL在windows上採摘

if len(self.pick_color_array) == 0: 
    self.init_color_buffers(len(self.points)) 
glUseProgram(0) 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 
glMatrixMode(GL_MODELVIEW) 
glLoadIdentity() 
glDisable(GL_BLEND) 
glDisable(GL_DITHER) 
glDisable(GL_FOG) 
glDisable(GL_LIGHTING) 
glDisable(GL_TEXTURE_1D) 
glDisable(GL_TEXTURE_2D) 
glDisable(GL_TEXTURE_3D) 
glShadeModel(GL_FLAT) 
glPushMatrix()   
glTranslate(self.x_translation_step,self.y_translation_step, 
         Z_DISTANCE + z_translation) 

glRotate(alpha_rotation, 0.0, 0.0, 1.0) 
glRotate(beta_rotation, 0.0, 1.0, 0.0) 
self.apply_connectivity_nose_correction() 
for i in range(len(self.points)): 
    glColor3ub(self.pick_color_array[i][0], self.pick_color_array[i][1], self.pick_color_array[i][2]) 
    glEnableClientState(GL_VERTEX_ARRAY) 
    glBindBuffer(GL_ARRAY_BUFFER, self.positions_buffers[i][0]) 
    glVertexPointer(3, GL_FLOAT, 0, None) 
    glBindBuffer(GL_ARRAY_BUFFER, self.positions_buffers[i][2]) 

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.positions_buffers[i][2]) 
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, None) 
glPopMatrix() 
viewport = glGetIntegerv(GL_VIEWPORT) 
pixel = glReadPixels(self.control.mouse_x(), float(viewport[3] - float(self.control.mouse_y())), 1, 1, 
        GL_RGB, GL_UNSIGNED_BYTE) 
glUseProgram(self.shader.shader) 
glEnable(GL_BLEND) 
glEnable(GL_DITHER) 
glEnable(GL_FOG) 
glEnable(GL_LIGHTING) 
glEnable(GL_TEXTURE_1D) 
glEnable(GL_TEXTURE_2D) 
glEnable(GL_TEXTURE_3D) 
glShadeModel(GL_SMOOTH)  

現在的init_color_buffers:

glMatrixMode(GL_MODELVIEW) 
    glLoadIdentity() 
    self.pick_color_dict = {} 
    self.pick_color_array = [] 
    vertices = numpy.array([ 
     0.0, 1000.0, 0.0, 
     -1000.0, -1000.0, 1000.0, 
     1000.0, -1000.0, 1000.0, 
     0.0, 1000.0, 0.0, 
     1000.0, -1000.0, 1000.0, 
     1000.0, -1000.0, -1000.0, 
     0.0, 100.0, 0.0, 
     1000.0, -1000.0, -1000.0, 
     -1000.0, -1000.0, -1000.0, 
     0.0, 1000.0, 0.0, 
     -1000.0, -1000.0, -1000.0, 
     -1000.0, -1000.0, 1000.0 
    ], dtype=numpy.float32) 
    buffer_cube = glGenBuffers(1) 
    glBindBuffer(GL_ARRAY_BUFFER, buffer_cube) 
    glBufferData(GL_ARRAY_BUFFER, ADT.arrayByteCount(vertices), 
        ADT.voidDataPointer(vertices), GL_STATIC_DRAW) 
    glUseProgram(0) 
    glDisable(GL_BLEND) 
    glDisable(GL_DITHER) 
    glDisable(GL_FOG) 
    glDisable(GL_LIGHTING) 
    glDisable(GL_TEXTURE_1D) 
    glDisable(GL_TEXTURE_2D) 
    glDisable(GL_TEXTURE_3D) 
    glMatrixMode(GL_MODELVIEW) 
    glLoadIdentity()  
    glShadeModel(GL_FLAT) 
    for i in range(nr_points): 
     self.pick_color_array.append((numpy.uint8(255.0/nr_points*i), 
             numpy.uint8(255 - 255.0/nr_points*i), 
             numpy.uint8(255.0/nr_points*i))) 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 
     glColor3ub(self.pick_color_array[i][0], self.pick_color_array[i][1], self.pick_color_array[i][2]) 
     glEnableClientState(GL_VERTEX_ARRAY) 
     glBindBuffer(GL_ARRAY_BUFFER, buffer_cube) 
     glVertexPointer(3, GL_FLOAT, 0, None) 
     glDrawArrays(GL_TRIANGLES, 0, 12) 
     pixel = glReadPixels(10, 10, 1, 1, 
        GL_RGB, GL_UNSIGNED_BYTE) 
     from binascii import hexlify 
     bit_repr = bin(int(b"1" + hexlify(pixel), 16))[3:]  
     color_0 = 0 
     for bit in bit_repr[:8]: 
      color_0 = color_0 * 2 + numpy.uint8(bit) 
     color_1 = 0 
     for bit in bit_repr[8:16]: 
      color_1 = color_1 * 2 + numpy.uint8(bit) 
     color_2 = 0 
     for bit in bit_repr[16:]: 
      color_2 = color_2 * 2 + numpy.uint8(bit)    
     self.pick_color_dict[(color_0, color_1, color_2)] = i 

現在,這是書面和在MacOS完美。但現在,當我在Windows上嘗試它時,它根本無法工作。創建的顏色字典只是一個{(0,0,0):last_index},任何點擊我的項目也會返回(0,0,0)。現在我非常難以理解我在這裏做錯了什麼,特別是因爲在MacOS上一切正常。我唯一的猜測就是glReadPixels不知何故在Windows上無法正常工作,或者Windows上的wxPython會以某種方式搞砸它?

任何幫助將不勝感激。

問候, 波格丹

回答

1

你不設置在init_color_buffers任意視口中,這可能是原因glReadPixels()調用返回的黑色像素。此外,投影矩陣未被設置。也許在Mac和Windows上調用順序有點不同(如果沒有完整的源代碼,很難說)。

在窗口上,glViewport()通常在初始化OpenGL後首次顯示窗口時調用。這可能會在調用init_color_buffers之後很好。通常,窗口應該可見,以便glReadPixels()返回某些內容。

嘗試使用延遲初始化(在調用init_color_buffers之前確保窗口可見)。你也可以在GL_RED_BITS,GL_GREEN_BITS和GL_BLUE_BITS中使用glGetIntegerv()函數來計算正確的顏色而不需要回讀(同樣,你的代碼並沒有使用所有可能的顏色,它最多隻能顯示256不同的顏色,但與8位RGB可以顯示2^24色)。

+0

感謝您的建議,我會試一試。我知道我沒有使用所有的顏色,但因爲我只需要最多120種顏色,所以我不想讓任何進一步複雜化。 – Bogdan 2012-01-13 15:47:34

+0

此外,投影矩陣在initGl中被設置一次,在gluPerspective(45.0,比率,0.1,800.0)之前被調用,之後它根本不會改變。我還應該在init_color_buffers中再次調用它嗎? – Bogdan 2012-01-13 15:51:07

+0

那不是那麼必要。它應該在Windows上工作,以防萬一它在Mac上工作。我也注意到你的頂點數據有一個小錯誤,第6個頂點的y座標是100,它可能應該是1000.但是這不應該影響任何東西。 – 2012-01-14 11:28:32