OpenGLでの選択処理は、GL_SELECTモードでポリゴンを描画することによって行われます。
指定された領域にポリゴンが描画されたかどうかで、選択範囲に入っているかを判断します。
ただし、GL_SELECTモードでは実際の描画は行われません。
PyOpenGLで、選択されたポリゴンを調べる手順は以下のようになります。
sel = glSelectBuffer(バッファの個数)
glRenderMode(GL_SELECT)
glInitNames()
glPushName(0)
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glLoadIdentity()
gluPickMatrix(選択範囲中心X座標, 選択範囲中心Y座標, 選択範囲横幅, 選択範囲縦幅, ビュー情報)
glLoadName(番号)
glMatrixMode(GL_PROJECTION)
glPopMatrix()
hits = glRenderMode(GL_RENDER)
マウスの左ボタンでクリックされたポリゴンの色を変えてみます。
#!env python from OpenGL.GL import * from OpenGL.GLU import * from OpenGL.GLUT import * vertex = [ [ -1.0, -1.0, 1.0 ], [ 1.0, -1.0, 1.0 ], [ -1.0, 1.0, 1.0 ], [ 1.0, 1.0, 1.0 ], [ -1.0, 1.0, -1.0 ], [ 1.0, 1.0, -1.0 ], [ -1.0, -1.0, -1.0 ], [ 1.0, -1.0, -1.0 ]] face = [ [ 0, 1, 3, 2 ], [ 2, 3, 5, 4 ], [ 4, 5, 7, 6 ], [ 6, 7, 1, 0 ], [ 1, 7, 5, 3 ], [ 6, 0, 2, 4 ]] color = [ [ 0.3, 0.3, 0.3 ], [ 0.4, 0.4, 0.4 ], [ 0.5, 0.5, 0.5 ], [ 0.6, 0.6, 0.6 ], [ 0.7, 0.7, 0.7 ], [ 0.8, 0.8, 0.8 ]] angleX = 0.0 angleY = 0.0 def resize(w, h): glViewport(0, 0, w, h) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(30.0, w/h, 1.0, 100.0) glMatrixMode(GL_MODELVIEW) def drawObjs(name=False): global angleX, angleY glLoadIdentity() gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) glRotated(angleX, 1.0, 0.0, 0.0); glRotated(angleY, 0.0, 1.0, 0.0); for j in range(0, len(face)): if name: glLoadName(j) glBegin(GL_QUADS) glColor3dv(color[j]) for i in range(0, 4): glVertex(vertex[face[j][i]]) glEnd() def draw(): glClearColor(0.0, 0.0, 1.0, 0.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) drawObjs() glFlush() glutSwapBuffers() def mouse(button, state, x, y): if state == GLUT_DOWN: if button == GLUT_LEFT_BUTTON: sel = glSelectBuffer(8) glRenderMode(GL_SELECT) glInitNames() glPushName(0) glMatrixMode(GL_PROJECTION) glPushMatrix() glLoadIdentity() vp = glGetIntegerv(GL_VIEWPORT) gluPickMatrix(x, vp[3] - y -1, 1, 1, vp) gluPerspective(30.0, vp[2]/vp[3], 1.0, 100.0) glMatrixMode(GL_MODELVIEW) drawObjs(name=True) glMatrixMode(GL_PROJECTION) glPopMatrix() hits = glRenderMode(GL_RENDER) for n in hits: h = n.names[0] color[h] = [1.0, 0, 0] glMatrixMode(GL_MODELVIEW) glutPostRedisplay() def keyboard(key, x, y): global angleX, angleY if key=='q': sys.exit() elif key=='h': angleY += 1.0 glutPostRedisplay() elif key=='j': angleX += 1.0 glutPostRedisplay() glutInit(sys.argv) glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH) glutInitWindowSize(320, 320) glutCreateWindow("PyOpenGL 18") glutDisplayFunc(draw) glutReshapeFunc(resize) glutKeyboardFunc(keyboard) glutMouseFunc(mouse) glClearColor(0.0, 0.0, 1.0, 0.0) glEnable(GL_DEPTH_TEST) glEnable(GL_CULL_FACE) glCullFace(GL_BACK) glutMainLoop()
def drawObjs(name=False):
if name:
glLoadName(j)
sel = glSelectBuffer(8)
glRenderMode(GL_SELECT)
glInitNames()
glPushName(0)
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glLoadIdentity()
vp = glGetIntegerv(GL_VIEWPORT)
gluPickMatrix(x, vp[3] - y -1, 1, 1, vp)
gluPerspective(30.0, vp[2]/vp[3], 1.0, 100.0)
glMatrixMode(GL_MODELVIEW)
drawObjs(name=True)
glMatrixMode(GL_PROJECTION)
glPopMatrix()
hits = glRenderMode(GL_RENDER)
for n in hits:
h = n.names[0]
color[h] = [1.0, 0, 0]
glMatrixMode(GL_MODELVIEW)
GL_SELECTモードで、名前に階層構造を与えたいときにはglPushName(), glPopName()を使用します。
glPushName(1)
glPushName(1)
glPushName(0)
glLoadName(0)
# ポリゴンA1を描画
glLoadName(1)
# ポリゴンA2を描画
glPopName()
glPopName()
glPushName(2)
glPushName(0)
glLoadName(0)
# ポリゴンB1を描画
glLoadName(1)
# ポリゴンB2を描画
glPopName()
glPopName()
glPopName()
glPushName(2)
glPushName(1)
glPushName(0)
glLoadName(0)
# ポリゴンC1を描画
glLoadName(1)
# ポリゴンC2を描画
glPopName()
glPopName()
glPopName()
上のコードで、選択されたオブジェクトの名前は以下のようになります。
マウスの選択スクリプトでは、n.namesに入っている値です。