import sys, time from math import * from OpenGL.GL import * from OpenGL.GLU import * from OpenGL.GLUT import * SPOT_DIRECTION = 1 SPOT_CUTOFF = 2 SPOT_EXPONENT = 3 viewRotX = 0 viewRotY = 0 lightPos = [ 0, 4, 10, 1 ] spotDirection = [ 0, 0, -1 ] spotCutoff = 30 spotExponent = 0.0 mouseMode = SPOT_DIRECTION def draw(): glClearColor(0.5, 0.8, 1.0, 0.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glEnable(GL_DEPTH_TEST) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(50.0, 1.75, 1.0, 100.0) glMatrixMode(GL_MODELVIEW) glLoadIdentity() glTranslatef(0.0, 0.0, -25.0) glRotatef(viewRotX, 1.0, 0.0, 0.0) glRotatef(viewRotY, 0.0, 1.0, 0.0) defineLight() glEnable(GL_LIGHTING) drawFloorMesh(32,32) drawTeapot() drawPedestal() drawBall() glDisable(GL_LIGHTING) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluOrtho2D(0.0, 1.0, 0.0, 1.0) glMatrixMode(GL_MODELVIEW) glLoadIdentity() glColor3f(1.0, 0.0, 0.5) glRasterPos2f(0.01, 0.01) drawBitmapString("direction = %.2f %.2f %.2f\t cutoff = %.1f\t exponent = %.2f" % (spotDirection[0], spotDirection[1], spotDirection[2], spotCutoff, spotExponent)) glutSwapBuffers() def defineLight(): white = [ 1, 1, 1, 1 ] glEnable(GL_LIGHT0) glLightfv(GL_LIGHT0, GL_DIFFUSE, white) glLightfv(GL_LIGHT0, GL_POSITION, lightPos) glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spotDirection) glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, spotCutoff) glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, spotExponent) drawSpotlight() def drawSpotlight(): glColor3f(1.0, 1.0, 0.0) glPointSize(12.0) glBegin(GL_POINTS) glVertex3fv(lightPos) glEnd() glBegin(GL_LINES) glVertex3fv(lightPos) glVertex3f(spotDirection[0]*100, spotDirection[1]*100, spotDirection[2]*100) glEnd() def drawFloorMesh(columns,rows): green = [ 0, 0.8, 0.1, 1 ] black = [ 0, 0, 0, 1 ] glMaterialfv(GL_FRONT, GL_AMBIENT, green) glMaterialfv(GL_FRONT, GL_DIFFUSE, green) glMaterialfv(GL_FRONT, GL_SPECULAR, black) glNormal3f(0.0, 1.0, 0.0) for j in range(0,rows): glBegin(GL_TRIANGLE_STRIP) for i in range(0,columns): x = ((float(i)) / columns) * 40.0 - 20.0 z = ((float(j)) / rows) * 40.0 - 20.0 glVertex3f(x, -2.0, z) z = ((float(j)+1) / rows) * 40.0 - 20.0 glVertex3f(x, -2.0, z) glEnd() def drawTeapot(): red = [ 0.8, 0, 0, 1 ] white = [ 1, 1, 1, 1 ] glMaterialfv(GL_FRONT, GL_AMBIENT, red) glMaterialfv(GL_FRONT, GL_DIFFUSE, red) glMaterialfv(GL_FRONT, GL_SPECULAR, white) glMaterialf(GL_FRONT, GL_SHININESS, 90.0) glPushMatrix() glTranslatef(2.0, 4.0, -1.0) glRotatef(currentTime() * 30.0, 0.0, 1.0, 0.0) glutSolidTeapot(2.0) glPopMatrix() quadric = None def drawPedestal(): global quadric grey = [ 0.6, 0.6, 0.6, 1 ] white = [ 1, 1, 1, 1 ] if not quadric: quadric = gluNewQuadric() glMaterialfv(GL_FRONT, GL_AMBIENT, grey) glMaterialfv(GL_FRONT, GL_DIFFUSE, grey) glMaterialfv(GL_FRONT, GL_SPECULAR, white) glMaterialf(GL_FRONT, GL_SHININESS, 30.0) glPushMatrix() glTranslatef(2.0, -2.0, -1.0) glRotatef(-90.0, 1.0, 0.0, 0.0) gluCylinder(quadric, 4.0, 4.0, 4.0, 16, 1) glTranslatef(0.0, 0.0, 4.0) gluDisk(quadric, 0.0, 4.0, 16, 1) glPopMatrix() def drawBall(): cyan = [ 0, 1, 1, 1 ] black = [ 0, 0, 0, 1 ] glMaterialfv(GL_FRONT, GL_AMBIENT, cyan) glMaterialfv(GL_FRONT, GL_DIFFUSE, cyan) glMaterialfv(GL_FRONT, GL_SPECULAR, black) glPushMatrix() glTranslatef(-10.0, fabs(sin(currentTime())) * 3.0, -15.0) glutSolidSphere(2.0, 16, 8) glPopMatrix() def drawBitmapString(text, font=GLUT_BITMAP_TIMES_ROMAN_24): for c in text: glutBitmapCharacter(font, ord(c)) startTime = time.time() def currentTime(): return time.time() - startTime def keyboard(key, x, y): if key == chr(27): sys.exit(0) def specialkey(k, x, y): global viewRotX, viewRotY if k == GLUT_KEY_LEFT: viewRotY += 3 elif k == GLUT_KEY_RIGHT: viewRotY -= 3 elif k == GLUT_KEY_UP: viewRotX += 3 elif k == GLUT_KEY_DOWN: viewRotX -= 3 def mousebutton(button, state, x, y): global mouseMode if (button == GLUT_LEFT_BUTTON) and (state == GLUT_DOWN): mouseMode = SPOT_DIRECTION elif (button == GLUT_MIDDLE_BUTTON) and (state == GLUT_DOWN): mouseMode = SPOT_CUTOFF elif (button == GLUT_RIGHT_BUTTON) and (state == GLUT_DOWN): mouseMode = SPOT_EXPONENT def mousemotion(x, y): global spotDirection, spotCutoff, spotExponent if mouseMode == SPOT_DIRECTION: spotDirection[0] = float(x) / glutGet(GLUT_WINDOW_WIDTH) * 2.0 - 1.0 spotDirection[1] = 1.0 - float(y) / glutGet(GLUT_WINDOW_HEIGHT) * 2.0 elif mouseMode == SPOT_CUTOFF: spotCutoff = float(x) / glutGet(GLUT_WINDOW_WIDTH) * 90.0 if spotCutoff < 0: spotCutoff = 0 elif spotCutoff > 90: spotCutoff = 90 elif mouseMode == SPOT_EXPONENT: spotExponent = float(x) / glutGet(GLUT_WINDOW_WIDTH) * 10.0 if spotExponent < 0: spotExponent = 0 glutInit([]) glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH) glutInitWindowSize(700,400) glutCreateWindow(sys.argv[0]) glutDisplayFunc(draw) glutKeyboardFunc(keyboard) glutSpecialFunc(specialkey) glutMouseFunc(mousebutton) glutMotionFunc(mousemotion) glutIdleFunc(glutPostRedisplay) glEnable(GL_DEPTH_TEST) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) glutMainLoop() SPOT_DIRECTION = 1 SPOT_CUTOFF = 2 SPOT_EXPONENT = 3