import sys, time, math from OpenGL.GL import * from OpenGL.GLU import * from OpenGL.GLUT import * from dmsgl import * import Image from random import * camera = PerspCamera() camera.pitch(-30) camera.moveBackward(30) balls = [] class displayList: def __init__(self, func): self.func = func self.dlist = 0 self.__call__ = self.define def define(self): self.dlist = glGenLists(1) glNewList(self.dlist, GL_COMPILE) self.func() glEndList() self.__call__ = self.call self.call() def call(self): glCallList(self.dlist) class heightfield: def __init__(self, heightfile, xrange, yrange, zrange, texturefile): self.img = Image.open(heightfile).convert('L') self.xrange = xrange self.yrange = yrange self.zrange = zrange self.texture = Texture2D(texturefile) self.ystep = self.yrange / 255.0 def draw(self): xstep = 2*self.xrange / (self.img.size[0] - 1.0) zstep = 2*self.zrange / (self.img.size[1] - 1.0) self.texture.apply() z = -self.zrange for row in range(0, self.img.size[1]-1): x = -self.xrange glBegin(GL_TRIANGLE_STRIP) for col in range(0, self.img.size[0]): glTexCoord2f(row / (self.img.size[1]-1.0), 1.0 - col / (self.img.size[0]-1.0)) glVertex3f(x, self.img.getpixel((row,col))*self.ystep, z) glTexCoord2f((row+1) / (self.img.size[1]-1.0), 1.0 - col / (self.img.size[0]-1.0)) glVertex3f(x, self.img.getpixel((row+1,col))*self.ystep, z+zstep) x = x + xstep glEnd() z = z + zstep self.texture.disable() def elevation(self,x,z): col = (x + self.xrange) / (2.0 * self.xrange) * (self.img.size[1]-2) row = (z + self.zrange) / (2.0 * self.zrange) * (self.img.size[0]-2) icol = int(col) irow = int(row) fcol = col - icol frow = row - irow p00 = self.img.getpixel( (irow, icol) ) * self.ystep p01 = self.img.getpixel( (irow, icol+1) ) * self.ystep p10 = self.img.getpixel( (irow+1, icol) ) * self.ystep p11 = self.img.getpixel( (irow+1, icol+1) ) * self.ystep interp0 = (1.0 - fcol) * p00 + fcol * p01 interp1 = (1.0 - fcol) * p10 + fcol * p11 return (1.0 - frow) * interp0 + frow * interp1 terrain = heightfield('andes-topo.jpg', 10, 10, 10, 'andes-color.jpg') drawTerrain = displayList(terrain.draw) angle = 0 def draw(): Color.Black.clear() camera.apply() glRotatef(angle, 0, 1, 0) # glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) drawTerrain() # glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) for t in balls: glPushMatrix() glTranslatef(t[0], t[1], t[2]) glutSolidSphere(0.25, 8, 4) glPopMatrix() glutSwapBuffers() def addTeapot(): global balls x = uniform(-terrain.xrange, terrain.xrange) z = uniform(-terrain.zrange, terrain.zrange) balls.append( (x, terrain.elevation(x,z)+0.25, z) ) def keyboard(key, x, y): global viewDistance if key == chr(27): sys.exit(0) if key == ' ': addTeapot() prevTime = time.time() def update(): global prevTime, angle t = time.time() dt = t - prevTime prevTime = t angle += 45*dt glutPostRedisplay() glutInit([]) glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH) glutInitWindowSize(400,400) glutCreateWindow(sys.argv[0]) glutDisplayFunc(draw) glutKeyboardFunc(keyboard) glutIdleFunc(update) glEnable(GL_DEPTH_TEST) quadric = gluNewQuadric() glutMainLoop()