ピッキング(ポリゴン選択)のサンプル

ネットに落ちていたものをPythonに移植したサンプルを一応貼っておく。

# coding: cp932
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
  
WIDTH   = 300
HEIGHT  = 300
BUFSIZE = 64

def DrawObjects():
	glLoadName(1)
	glBegin(GL_QUADS)
	glColor3f(0.0, 1.0, 1.0)
	glVertex3i(3, 2, -1)
	glVertex3i(3, 8, -1)
	glVertex3i(8, 8, -1)
	glVertex3i(8, 2, -1)
	glEnd()
	
	glLoadName(2)
	glBegin(GL_QUADS)
	glColor3f(1.0, 1.0, 0.0)
	glVertex3f(2, 0,-0.1)
	glVertex3f(2, 6,-0.1)
	glVertex3f(6, 6,-0.1)
	glVertex3f(6, 0,-0.1)
	glEnd()
	
	glBegin(GL_QUADS)
	glColor3f(1.0, 0.0, 0.0)
	glVertex3f(2, 0, -0.05)
	glVertex3f(2, 1, -0.05)
	glVertex3f(8, 1, -0.05)
	glVertex3f(8, 0, -0.05)
	glEnd()
	
	glBegin(GL_QUADS)
	glColor3f(1.0, 1.0, 1.0)
	glVertex3i( 1, 0, 0)
	glVertex3i( 1, 1, 0)
	glVertex3i(-1, 1, 0)
	glVertex3i(-1, 0, 0)
	glEnd()
	
	glLoadName(3)
	glBegin(GL_QUADS)
	glColor3f(1.0, 0.0, 1.0)
	glVertex3i(0, 2, -2)
	glVertex3i(0, 7, -2)
	glVertex3i(5, 7, -2)
	glVertex3i(5, 2, -2)
	glEnd()

def SelectHits(hits, buf):
	if hits:
		glutSetWindowTitle("You clicked object.")
	else:
		glutSetWindowTitle("Nothing.")
	print '------'
	for record in hits:
		min_depth, max_depth, names = record
		print min_depth, max_depth, names

def pick(x, y):
	selectBuf = glSelectBuffer(BUFSIZE)
	glRenderMode(GL_SELECT)
	
	glInitNames()
	glPushName(0)
	
	glMatrixMode(GL_PROJECTION)
	glPushMatrix()
	glLoadIdentity()
	viewport = glGetIntegerv(GL_VIEWPORT)
	gluPickMatrix(x,viewport[3]-y, 2.0, 2.0, viewport)
	current_aspect = viewport[2]/float(viewport[3])
	gluPerspective(60.0, current_aspect, 1.0, 100.0)
	
	glMatrixMode( GL_MODELVIEW )
	DrawObjects()
	
	glMatrixMode(GL_PROJECTION)
	glPopMatrix()
	glMatrixMode( GL_MODELVIEW )
	
	hits = glRenderMode(GL_RENDER)
	SelectHits(hits, selectBuf)

def display():
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
	glLoadIdentity()
	gluLookAt( 
		4,4,12, 
		4,4,0, 
		0.0, 1.0, 0.0)
  
	DrawObjects()
	glFlush()
	glutSwapBuffers()

def init(): 
	glEnable(GL_DEPTH_TEST)
	glClearColor( 0.0, 0.0, 0.0, 1.0 )
	glClearDepth( 1.0 )

def mouse(button, state, x, y):
	if button == GLUT_LEFT_BUTTON:
		if(state == GLUT_DOWN):
			pick(x,y)

def resize(w, h):
	aspect = 0.0;  
	glViewport(0, 0, w, h)
	aspect = w/float(h)
	glMatrixMode( GL_PROJECTION )
	glLoadIdentity()
	gluPerspective( 60.0, aspect, 1.0,100.0 )
	glMatrixMode( GL_MODELVIEW )

def main():
	glutInit(sys.argv)
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB)
	glutInitWindowSize (WIDTH,HEIGHT)
	glutInitWindowPosition (100, 100)
	glutCreateWindow ("Simple GLUT")
	init()
	glutDisplayFunc(display)
	glutReshapeFunc(resize)
	glutMouseFunc(mouse)
	glutMainLoop()

main()