def __init__(self, servIP="127.0.0.1", ownIP="127.0.0.1", port="21560"): self.oldScreenValues = None self.view = 0 self.worldRadius = 400 # Start of mousepointer self.lastx = 0 self.lasty = 15 self.lastz = 300 self.zDis = 1 # Start of cube self.cube = [0.0, 0.0, 0.0] self.bmpCount = 0 self.actCount = 0 self.calcPhysics = 0 self.newPic = 1 self.picCount = 0 self.target = array([80.0, 0.0, 0.0]) self.centerOfGrav = array([0.0, -2.0, 0.0]) self.points = ones((8, 3), float) self.savePics = False self.drawCounter = 0 self.fps = 25 self.dt = 1.0 / float(self.fps) self.client = UDPClient(servIP, ownIP, port)
def __init__(self, servIP="127.0.0.1", ownIP="127.0.0.1", port="21590", buf="16384"): # initialize the viewport size self.width = 800 self.height = 600 # initialize object which the camera follows self.centerObj = None self.mouseView = True self.viewDistance = 30 self.lastx = -0.5 self.lasty = 1 self.lastz = -1 self.dt = 1 self.fps = 50 self.lasttime = time.time() self.starttime = time.time() self.captureScreen = False self.isCapturing = False self.isFloorGreen = True self.message = None self.keyboardCallback = None # capture only every frameT. frame self.counter = 0 self.frameT = 1 self.init_GL() # set own callback functions glutMotionFunc(self._motionfunc) glutPassiveMotionFunc(self._passivemotionfunc) glutDisplayFunc(self._drawfunc) glutIdleFunc(self._idlefunc) glutKeyboardFunc(self._keyfunc) self.dt = 1.0 / self.fps self.lasttime = time.time() self.starttime = self.lasttime # initialize udp client self.client = UDPClient(servIP, ownIP, port, buf)
def __init__(self, servIP="127.0.0.1", ownIP="127.0.0.1", port="21590", buf="16384"): # initialize the viewport size self.width = 800 self.height = 600 # initialize object which the camera follows self.centerObj = None self.mouseView = True self.viewDistance = 30 self.lastx = -0.5 self.lasty = 1 self.lastz = -1 self.dt = 1 self.fps = 50 self.lasttime = time.time() self.starttime = time.time() self.captureScreen = False self.isCapturing = False self.isFloorGreen = True self.message = None self.keyboardCallback = None # capture only every frameT. frame self.counter = 0 self.frameT = 1 self.init_GL() # set own callback functions glutMotionFunc (self._motionfunc) glutPassiveMotionFunc(self._passivemotionfunc) glutDisplayFunc (self._drawfunc) glutIdleFunc (self._idlefunc) glutKeyboardFunc (self._keyfunc) self.dt = 1.0 / self.fps self.lasttime = time.time() self.starttime = self.lasttime # initialize udp client self.client = UDPClient(servIP, ownIP, port, buf)
class FlexCubeRenderer(object): #Options: ServerIP(default:localhost), OwnIP(default:localhost), Port(default:21560) def __init__(self, servIP="127.0.0.1", ownIP="127.0.0.1", port="21560"): self.oldScreenValues = None self.view = 0 self.worldRadius = 400 # Start of mousepointer self.lastx = 0 self.lasty = 15 self.lastz = 300 self.zDis = 1 # Start of cube self.cube = [0.0, 0.0, 0.0] self.bmpCount = 0 self.actCount = 0 self.calcPhysics = 0 self.newPic = 1 self.picCount = 0 self.target = array([80.0, 0.0, 0.0]) self.centerOfGrav = array([0.0, -2.0, 0.0]) self.points = ones((8, 3), float) self.savePics = False self.drawCounter = 0 self.fps = 25 self.dt = 1.0 / float(self.fps) self.client = UDPClient(servIP, ownIP, port) # If self.savePics=True this method saves the produced images def saveTo(self, filename, format="JPEG"): import Image # get PIL's functionality... @UnresolvedImport width, height = 800, 600 glPixelStorei(GL_PACK_ALIGNMENT, 1) data = glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE) image = Image.fromstring("RGB", (width, height), data) image = image.transpose(Image.FLIP_TOP_BOTTOM) image.save(filename, format) print('Saved image to ', filename) return image # the render method containing the Glut mainloop def _render(self): # Call init: Parameter(Window Position -> x, y, height, width) self.init_GL(self, 300, 300, 800, 600) self.object = objects3d.Objects3D() self.quad = gluNewQuadric() glutMainLoop() # The Glut idle function def drawIdleScene(self): #recive data from server and update the points of the cube try: self.points, self.centerOfGrav = eval( self.client.listen([self.points, self.centerOfGrav])) except: pass if self.points == "r": self.target = array([80.0, 0.0, 0.0]) self.centerOfGrav = array([0.0, -2.0, 0.0]) self.points = ones((8, 3), float) self.drawScene() if self.savePics: self.saveTo("./screenshots/image_jump" + repr(10000 + self.picCount) + ".jpg") self.picCount += 1 else: sleep(self.dt) def drawScene(self): ''' This methode describes the complete scene.''' # clear the buffer if self.zDis < 10: self.zDis += 0.25 if self.lastz > 200: self.lastz -= self.zDis glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() # Point of view glRotatef(self.lastx, 0.0, 1.0, 0.0) glRotatef(self.lasty, 1.0, 0.0, 0.0) #glRotatef(15, 0.0, 0.0, 1.0) # direction of view is aimed to the center of gravity of the cube glTranslatef(-self.centerOfGrav[0], -self.centerOfGrav[1] - 50.0, -self.centerOfGrav[2] - self.lastz) #Objects #Target Ball glColor3f(1, 0.25, 0.25) glPushMatrix() glTranslate(self.target[0], 0.0, self.target[2]) glutSolidSphere(1.5, 8, 8) glPopMatrix() #Massstab for lk in range(41): if float(lk - 20) / 10.0 == (lk - 20) / 10: glColor3f(0.75, 0.75, 0.75) glPushMatrix() glRotatef(90, 1, 0, 0) glTranslate( self.worldRadius / 40.0 * float(lk) - self.worldRadius / 2.0, -40.0, -30) quad = gluNewQuadric() gluCylinder(quad, 2, 2, 60, 4, 1) glPopMatrix() else: if float(lk - 20) / 5.0 == (lk - 20) / 5: glColor3f(0.75, 0.75, 0.75) glPushMatrix() glRotatef(90, 1, 0, 0) glTranslate( self.worldRadius / 40.0 * float(lk) - self.worldRadius / 2.0, -40.0, -15.0) quad = gluNewQuadric() gluCylinder(quad, 1, 1, 30, 4, 1) glPopMatrix() else: glColor3f(0.75, 0.75, 0.75) glPushMatrix() glRotatef(90, 1, 0, 0) glTranslate( self.worldRadius / 40.0 * float(lk) - self.worldRadius / 2.0, -40.0, -7.5) quad = gluNewQuadric() gluCylinder(quad, 0.5, 0.5, 15, 4, 1) glPopMatrix() #Mirror Center Ball glColor3f(1, 1, 1) glPushMatrix() glTranslate(self.centerOfGrav[0], -self.centerOfGrav[1], self.centerOfGrav[2]) glutSolidSphere(1.5, 8, 8) glPopMatrix() #Mirror Cube glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glColor4f(0.5, 0.75, 0.5, 0.75) glPushMatrix() glTranslatef(0, -0.05, 0) self.object.drawMirCreat(self.points, self.centerOfGrav) glPopMatrix() # Floor tile = self.worldRadius / 40.0 glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) for xF in range(40): for yF in range(40): if float(xF + yF) / 2.0 == (xF + yF) / 2: glColor3f(0.8, 0.8, 0.7) else: glColor4f(0.8, 0.8, 0.8, 0.7) glPushMatrix() glTranslatef(0.0, -0.03, 0.0) glBegin(GL_QUADS) glNormal(0.0, 1.0, 0.0) for i in range(2): for k in range(2): glVertex3f((i + xF - 20) * tile, 0.0, ((k ^ i) + yF - 20) * tile) glEnd() glPopMatrix() #Center Ball glColor3f(1, 1, 1) glPushMatrix() glTranslate(self.centerOfGrav[0], self.centerOfGrav[1], self.centerOfGrav[2]) glutSolidSphere(1.5, 8, 8) glPopMatrix() # Cube glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glColor4f(0.5, 0.75, 0.5, 0.75) glPushMatrix() self.object.drawCreature(self.points, self.centerOfGrav) glPopMatrix() glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) # Cubes shadow glColor4f(0, 0, 0, 0.5) glPushMatrix() self.object.drawShadow(self.points, self.centerOfGrav) glPopMatrix() # swap the buffer glutSwapBuffers() def resizeScene(self, width, height): '''Needed if window size changes.''' if height == 0: # Prevent A Divide By Zero If The Window Is Too Small height = 1 glViewport( 0, 0, width, height ) # Reset The Current Viewport And Perspective Transformation glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(45.0, float(width) / float(height), 0.1, 700.0) glMatrixMode(GL_MODELVIEW) def activeMouse(self, x, y): #Returns mouse coordinates while any mouse button is pressed. # store the mouse coordinate if self.mouseButton == GLUT_LEFT_BUTTON: self.lastx = x - self.xOffset self.lasty = y - self.yOffset if self.mouseButton == GLUT_RIGHT_BUTTON: self.lastz = y - self.zOffset # redisplay glutPostRedisplay() def passiveMouse(self, x, y): '''Returns mouse coordinates while no mouse button is pressed.''' pass def completeMouse(self, button, state, x, y): #Returns mouse coordinates and which button was pressed resp. released. self.mouseButton = button if state == GLUT_DOWN: self.xOffset = x - self.lastx self.yOffset = y - self.lasty self.zOffset = y - self.lastz # redisplay glutPostRedisplay() #Initialise an OpenGL windows with the origin at x, y and size of height, width. def init_GL(self, pyWorld, x, y, height, width): # initialize GLUT glutInit([]) glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH) glutInitWindowSize(height, width) glutInitWindowPosition(x, y) glutCreateWindow("The Curious Cube") glClearDepth(1.0) glEnable(GL_DEPTH_TEST) glClearColor(0.0, 0.0, 0.0, 0.0) glShadeModel(GL_SMOOTH) glMatrixMode(GL_MODELVIEW) # initialize lighting */ glLightfv(GL_LIGHT0, GL_DIFFUSE, [1, 1, 1, 1.0]) glLightModelfv(GL_LIGHT_MODEL_AMBIENT, [1.0, 1.0, 1.0, 1.0]) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) # glColorMaterial(GL_FRONT, GL_DIFFUSE) glEnable(GL_COLOR_MATERIAL) # Automatic vector normalise glEnable(GL_NORMALIZE) ### Instantiate the virtual world ### glutDisplayFunc(pyWorld.drawScene) glutMotionFunc(pyWorld.activeMouse) glutMouseFunc(pyWorld.completeMouse) glutReshapeFunc(pyWorld.resizeScene) glutIdleFunc(pyWorld.drawIdleScene)
def __init__(self, servIP='127.0.0.1', ownIP='127.0.0.1', port='21590', buf='16384', verbose=False, window_name='ODE Viewer'): """Initialize Initializes all viewer attributes and starts the OpenGL engine. The UDP server is also started. """ self.verbose = verbose self.window_name = window_name # Determine if the viewport will display in stereoscopic mode self.is_stereoscopic = True # Figure out the spacing between cameras for stereoscopic projection # NOTE: Pupillary distance for 95% of men in the USA is 7cm # Source: (Wikipedia: Pupillary Distance) self.stereoscopic_offset = 0.07 / 2.0 # [m] # initialize viewport starting size self.width = 800 self.height = 600 # Determine if fullscreen is active or not self.is_fullscreen = False # Calculate the initial aspect ratio of the window self.aspect_ratio = float(self.width) / float(self.height) self.aspect_ratio_changed = False # initialize object which the camera follows self.mouseView = True # Toggles to determine if the view should zoom or rotate self.motion_rotate_mode = False self.motion_zoom_mode = False # Stores the location of the mouse the last time it was clicked self.motion_last_mouse_down_pos = [0.0, 0.0] self.centerObj = None # Define the initial spherical camera positions self.cam_r_init = 1.0 self.cam_theta_init = pi / 4.0 self.cam_phi_init = 0.0 # Define the camera spherical coodrinate attributes self.cam_r = self.cam_r_init self.cam_theta = self.cam_theta_init self.cam_phi = self.cam_phi_init # Define attributes to maintain frame rate self.fps = 60 self.dt = 1.0 / self.fps self.last_time = time.time() self.capture_screen = False # Define attributes to store geometries to display self.message = None self.prev_message = None # Capture screen only every 'frameT'-th frame self.counter = 0 self.frameT = 2 # Initialize the OpenGL viewer window self.init_gl() # Set OpenGL callback functions glutKeyboardFunc(self._keyboard_callback) glutMouseFunc(self._mouse_callback) glutMotionFunc(self._motion_callback) glutPassiveMotionFunc(self._passive_motion_callback) glutDisplayFunc(self._display_callback) glutIdleFunc(self._idle_callback) # Initialize UDP client connection to the ODE simulation self.client = UDPClient(servIP, ownIP, port, buf, verbose=self.verbose) return
class ODEViewer(object): def __init__(self, servIP='127.0.0.1', ownIP='127.0.0.1', port='21590', buf='16384', verbose=False, window_name='ODE Viewer'): """Initialize Initializes all viewer attributes and starts the OpenGL engine. The UDP server is also started. """ self.verbose = verbose self.window_name = window_name # Determine if the viewport will display in stereoscopic mode self.is_stereoscopic = True # Figure out the spacing between cameras for stereoscopic projection # NOTE: Pupillary distance for 95% of men in the USA is 7cm # Source: (Wikipedia: Pupillary Distance) self.stereoscopic_offset = 0.07 / 2.0 # [m] # initialize viewport starting size self.width = 800 self.height = 600 # Determine if fullscreen is active or not self.is_fullscreen = False # Calculate the initial aspect ratio of the window self.aspect_ratio = float(self.width) / float(self.height) self.aspect_ratio_changed = False # initialize object which the camera follows self.mouseView = True # Toggles to determine if the view should zoom or rotate self.motion_rotate_mode = False self.motion_zoom_mode = False # Stores the location of the mouse the last time it was clicked self.motion_last_mouse_down_pos = [0.0, 0.0] self.centerObj = None # Define the initial spherical camera positions self.cam_r_init = 1.0 self.cam_theta_init = pi / 4.0 self.cam_phi_init = 0.0 # Define the camera spherical coodrinate attributes self.cam_r = self.cam_r_init self.cam_theta = self.cam_theta_init self.cam_phi = self.cam_phi_init # Define attributes to maintain frame rate self.fps = 60 self.dt = 1.0 / self.fps self.last_time = time.time() self.capture_screen = False # Define attributes to store geometries to display self.message = None self.prev_message = None # Capture screen only every 'frameT'-th frame self.counter = 0 self.frameT = 2 # Initialize the OpenGL viewer window self.init_gl() # Set OpenGL callback functions glutKeyboardFunc(self._keyboard_callback) glutMouseFunc(self._mouse_callback) glutMotionFunc(self._motion_callback) glutPassiveMotionFunc(self._passive_motion_callback) glutDisplayFunc(self._display_callback) glutIdleFunc(self._idle_callback) # Initialize UDP client connection to the ODE simulation self.client = UDPClient(servIP, ownIP, port, buf, verbose=self.verbose) return def start(self): # start the OpenGL main loop glutMainLoop() return def set_dt(self, dt): self.dt = dt self.fps = 1.0 / self.dt return def set_fps(self, fps): self.fps = fps self.dt = 1.0 / self.fps return def init_gl(self): """ initialize OpenGL. This function has to be called only once before drawing. """ glutInit([]) # Set up the new window glutInitWindowPosition(0, 0) glutInitWindowSize(self.width, self.height) glutCreateWindow(self.window_name) # Determine if stereoscopic is supported if it is desired if self.is_stereoscopic and not glGetBooleanv(GL_STEREO): print '>>> OpenGL stereoscopic is not supported' print '>>> Reverting to monoscopic viewer' self.is_stereoscopic = False # Initialize the display for either stereo or monoscopic if self.is_stereoscopic: glutInitDisplayMode(GLUT_STEREO | GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH) else: glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH) # Initialize Viewport and Shading glViewport(0, 0, self.width, self.height) glShadeModel(GL_SMOOTH) glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) #glClearColor(1.0, 1.0, 1.0, 0.0) glClearColor(0.52, 0.80, 0.98, 1.0) # Initialize Depth Buffer glClearDepth(1.0) glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) # Initialize Lighting glEnable(GL_LIGHTING) glLightfv(GL_LIGHT1, GL_AMBIENT, [0.7, 0.7, 0.7, 1.0]) glLightfv(GL_LIGHT1, GL_DIFFUSE, [1.0, 1.0, 1.0, 1.0]) glLightfv(GL_LIGHT1, GL_POSITION, [0.0, 5.0, 5.0, 1.0]) glEnable(GL_LIGHT1) # enable material coloring glEnable(GL_COLOR_MATERIAL) glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE) glEnable(GL_NORMALIZE) return def calc_aspect_ratio(self): """Calculate Aspect Ratio Recalculates the value of the aspect ratio of the viewport using the width and height of the viewport. Returns: The current aspect ratio as a floating point value. """ # Calculate the current aspect ratio so we have an accurate model (_, _, x, y) = glGetIntegerv(GL_VIEWPORT) # Protect against divide by zero exceptions if y == 0: y = 1 # Aspect Ratio = Width / Height ratio = float(x) / float(y) return ratio def prepare_gl(self): """Prepare drawing. This function is called in every step. It clears the screen and sets the new camera position""" # Do prep to determine the center of focus and general camera position # Center the camera on a given object or (0, 0, 0) if not specified center = [0.0, 0.0, 0.0] if self.centerObj is not None: center[0], center[1], center[2] = self.centerObj.getPosition() # Convert spherical to cartesian coordinates cam = [0.0, 0.0, 0.0] cam[0] = self.cam_r * sin(self.cam_theta) * sin(self.cam_phi) cam[1] = self.cam_r * cos(self.cam_theta) cam[2] = self.cam_r * sin(self.cam_theta) * cos(self.cam_phi) # If the aspect ratio changed due to fullscreen, recalculate the value if self.aspect_ratio_changed: self.aspect_ratio = self.calc_aspect_ratio() # Begin drawing into OpenGL buffers depending on mono or stereoscopic if self.is_stereoscopic: self.prepare_stereoscopic(cam, center, self.stereoscopic_offset) else: self.prepare_monoscopic(cam, center) return def prepare_stereoscopic(self, cam, center, eye_offset): """Prepare Stereoscopic View Draws the buffers required for stereoscopic support. Note that if this function is called without verifying that stereoscopic support exists, OpenGL exceptions will be thrown. NOTE: The stereoscopic support code was modified from the tutorial for Stereo Geometry in OpenGL. The website can be found here: http://www.orthostereo.com/geometryopengl.html Arguments: cam: A 3-element list of [x, y, z] float positions of the camera. center: A 3-element list of [x, y, z] float positions of the object to center the camera on. eye_offset: The distance of each eye to the left and right of the given cam position. """ # Calculate the distance of each eye from the center perspective # Draw into both back color buffers glDrawBuffer(GL_BACK) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Draw the left eye perspective glDrawBuffer(GL_BACK_LEFT) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glMatrixMode(GL_PROJECTION) glLoadIdentity() # Define the perspective based on current aspect ratio gluPerspective(45, self.aspect_ratio, 0.1, 50.0) # Draw the world as seen through the left eye glMatrixMode(GL_MODELVIEW) glLoadIdentity() # TODO: At the moment, the eye_offset is just given to the x offset. # this is not correct as the z position should also change with # the sperical rotation. y position is not affected. # Place the left eye and set the camera's target object gluLookAt(cam[0]-eye_offset, cam[1], cam[2], center[0]-eye_offset, center[1], center[2], 0, 1, 0) # Draw the right eye perspective glDrawBuffer(GL_BACK_RIGHT) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glMatrixMode(GL_PROJECTION) glLoadIdentity() # Define the perspective based on current aspect ratio gluPerspective(45, self.aspect_ratio, 0.1, 50.0) # Draw the world as seen through the right eye glMatrixMode(GL_MODELVIEW) glLoadIdentity() # Place the left eye and set the camera's target object gluLookAt(cam[0]+eye_offset, cam[1], cam[2], center[0]+eye_offset, center[1], center[2], 0, 1, 0) return def prepare_monoscopic(self, cam, center): """Prepare Monoscopic View Draws the buffer required for single-camera (monoscopic) viewer. Arguments: cam: A 3-element list of [x, y, z] float positions of the camera. center: A 3-element list of [x, y, z] float positions of the object to center the camera on. """ # Clear the screen glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Load the Projection matrix glMatrixMode(GL_PROJECTION) glLoadIdentity() # Define the perspective based on current aspect ratio gluPerspective(45, self.aspect_ratio, 0.1, 50.0) # Initialize ModelView matrix glMatrixMode(GL_MODELVIEW) glLoadIdentity() # Place the camera and set the camera's target object gluLookAt(cam[0], cam[1], cam[2], center[0], center[1], center[2], 0, 1, 0) return def draw_item(self, item): """Draw Item Draws an object from the ODE specifications. Arguments: item: A dictionary containing keys relating to an ODE geometry. """ glDisable(GL_TEXTURE_2D) # Create a matrix for the new geometry calculations glPushMatrix() # Determine which geometric object we are dealing with. Draw it if item['type'] in ['box', 'sphere', 'cylinder', 'ccylinder']: # set color of object (currently dark gray) if item.has_key('color'): glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glColor4f(*(item['color'])) else: glColor3f(0.1, 0.1, 0.1) # transform (rotate, translate) body accordingly (x, y, z) = item['position'] R = item['rotation'] # Create rotation matrix rot = [R[0], R[3], R[6], 0.0, R[1], R[4], R[7], 0.0, R[2], R[5], R[8], 0.0, x, y, z, 1.0] # Apply rotation matrix to any shape created glMultMatrixd(rot) if item['type'] == 'box': # Draw a cube scaled to size (sx, sy, sz) = item['scale'] glScaled(float(sx), float(sy), float(sz)) glutSolidCube(1.0) elif item['type'] == 'sphere': # sphere glutSolidSphere(item['radius'], 20, 20) elif item['type'] == 'ccylinder': quad = gluNewQuadric() # draw cylinder and two spheres, one at each end glTranslate(0.0, 0.0, -item['length']/2.0) # Draw the cylinder object gluCylinder(quad, item['radius'], item['radius'], item['length'], 32, 32) # Draw the first cylinder end sphere glutSolidSphere(item['radius'], 20, 20) # Draw the second cylinder end sphere glTranslate(0.0, 0.0, item['length']) glutSolidSphere(item['radius'], 20, 20) elif item['type'] == 'cylinder': glTranslate(0.0, 0.0, -item['length']/2.0) # Draw the first cylinder end disk quad = gluNewQuadric() # Modify the orientation. This quad normal is inward gluQuadricOrientation(quad, GLU_INSIDE) gluDisk(quad, 0, item['radius'], 32, 1) # Draw the cylinder quad = gluNewQuadric() gluCylinder(quad, item['radius'], item['radius'], item['length'], 32, 32) # Draw the second cylinder end disk glTranslate(0.0, 0.0, item['length']) quad = gluNewQuadric() gluDisk(quad, 0.0, item['radius'], 32, 1) elif item['type'] == 'plane': # set color of plane (currently green) glColor3f(0.0, 0.2, 0.0) # for planes, we need a Quadric object quad = gluNewQuadric() gluQuadricTexture(quad, GL_TRUE) p = item['normal'] # the normal vector to the plane d = item['distance'] # the distance to the origin q = (0.0, 0.0, 1.0) # the normal vector of default gluDisks (z=0 plane) # calculate the cross product to get the rotation axis c = crossproduct(p, q) # calculate the angle between default normal q and plane normal p theta = acos(dotproduct(p, q) / (norm(p) * norm(q))) / pi * 180 # rotate the plane glTranslate(d * p[0], d * p[1], d * p[2]) glRotate(-theta, c[0], c[1], c[2]) # Create the disk with "infinite" (very large) radius gluDisk(quad, 0, 200, 20, 1) glPopMatrix() return @staticmethod def _loadTexture(textureFile): image = open(textureFile) ix = image.size[0] iy = image.size[1] image = image.tostring("raw", "RGBX", 0, -1) # Create Texture textures = glGenTextures(3) glBindTexture(GL_TEXTURE_2D, textures[0]) # 2d texture (x and y size) glPixelStorei(GL_UNPACK_ALIGNMENT, 1) glTexImage2D(GL_TEXTURE_2D, 0, 3, ix, iy, 0, GL_RGBA, GL_BYTE, image) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL) # Create Linear Filtered Texture glBindTexture(GL_TEXTURE_2D, textures[1]) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexImage2D(GL_TEXTURE_2D, 0, 3, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image) # Create MipMapped Texture glBindTexture(GL_TEXTURE_2D, textures[2]) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST) gluBuild2DMipmaps(GL_TEXTURE_2D, 3, ix, iy, GL_RGBA, GL_UNSIGNED_BYTE, image) return textures def _display_callback (self): """ draw callback function """ # Draw the scene self.prepare_gl() if self.message is not None: for item_name, item in self.message.iteritems(): try: # Attempt to draw in item from the message self.draw_item(item) except: # If something goes wrong in draw_item, we need to # pop the matrix to prevent stack overflow glPopMatrix() glutSwapBuffers() if self.capture_screen: self._screenshot() return def _idle_callback(self): # Listen for the latest data try: self.message = self.client.listen() except: pass if self.message is None: # If the message wasn't properly received, use the old message self.message = self.prev_message else: # Message received in full. Fill in any unsent items from the # previous message. These have not been modified if self.prev_message is not None: for item_name, item in self.prev_message.iteritems(): if item_name not in self.message: self.message[item_name] = item #Store it for future use self.prev_message = self.message # Display the latest data directly after receiving glutPostRedisplay() # Maintain the frame rate at the desired fps t = self.dt - (time.time() - self.last_time) if (t > 0.0): time.sleep(t) self.last_time = time.time() return def _keyboard_callback(self, key, x, y): """ keyboard call-back function. """ if key == 's': self.capture_screen = not self.capture_screen print "Screen Capture: " + (self.capture_screen and "on" or "off") elif key == 'f': self.aspect_ratio_changed = True if self.is_fullscreen: # Toggle out of fullscreen mode glutReshapeWindow(self.width, self.height) glutPositionWindow(0, 0) glutSetCursor(GLUT_CURSOR_INHERIT) self.is_fullscreen = False else: # Toggle into fullscreen mode glutFullScreen() glutSetCursor(GLUT_CURSOR_NONE) self.is_fullscreen = True elif key in ['x', 'q']: sys.exit() elif key == 'c': print 'Reset Camera' self.cam_r = self.cam_r_init self.cam_theta = self.cam_theta_init self.cam_phi = self.cam_phi_init return def _mouse_callback(self, button, state, x, y): if state == GLUT_DOWN: self.motion_last_mouse_down_pos = (x, y) if button == GLUT_LEFT_BUTTON: # If the left button is down, activate rotation mode if state == GLUT_DOWN: self.motion_rotate_mode = True elif state == GLUT_UP: self.motion_rotate_mode = False elif button == GLUT_RIGHT_BUTTON: # If the right button is down, activate zoom mode if state == GLUT_DOWN: self.motion_zoom_mode = True elif state == GLUT_UP: self.motion_zoom_mode = False return def _motion_callback(self, x, y): x_down, y_down = self.motion_last_mouse_down_pos # Note that if a mouse has two buttons (left/right) pressed at the # same time, rotate mode will always override zoom mode if self.motion_rotate_mode: # Modify the polar and azimuthal angles via y, x mouse direction d_phi = 0.2 * (float(x) - float(x_down)) / self.height d_theta = 0.2 * (float(y) - float(y_down)) / self.width # Set camera angle constraints if 0.0 <= self.cam_theta + d_theta <= pi / 2.0: self.cam_theta += d_theta if -pi / 2.0 <= self.cam_phi + d_phi <= pi / 2.0: self.cam_phi += d_phi elif self.motion_zoom_mode: # Change radius from target based on the relative 'y' position of # the mouse from the last click dr = 0.2 * (float(y) - float(y_down)) / self.height # Limit the zoom range between 0.2 and 10 meters if 0.2 < self.cam_r + dr < 10: self.cam_r += dr return def _passive_motion_callback(self, x, z): pass def _screenshot(self, path_prefix='.', format='PNG'): """Saves a screenshot of the current frame buffer. The save path is <path_prefix>/.screenshots/shot<num>.png The path is automatically created if it does not exist. Shots are automatically numerated based on how many files are already in the directory.""" if self.counter == self.frameT: self.counter = 1 dir = os.path.join(path_prefix, 'screenshots') if not os.path.exists(dir): os.makedirs(dir) num_present = len(os.listdir(dir)) num_digits = len(str(num_present)) index = '0' * (5 - num_digits) + str(num_present) path = os.path.join(dir, 'shot' + index + '.' + format.lower()) glPixelStorei(GL_PACK_ALIGNMENT, 1) data = glReadPixels(0, 0, self.width, self.height, GL_RGB, GL_UNSIGNED_BYTE) image = Image.fromstring("RGB", (self.width, self.height), data) image = image.transpose(Image.FLIP_TOP_BOTTOM) image.save(path, format) print 'Image saved to %s' % (os.path.basename(path)) else: self.counter += 1 return
class FlexCubeRenderer(object): #Options: ServerIP(default:localhost), OwnIP(default:localhost), Port(default:21560) def __init__(self, servIP="127.0.0.1", ownIP="127.0.0.1", port="21560"): self.oldScreenValues = None self.view = 0 self.worldRadius = 400 # Start of mousepointer self.lastx = 0 self.lasty = 15 self.lastz = 300 self.zDis = 1 # Start of cube self.cube = [0.0, 0.0, 0.0] self.bmpCount = 0 self.actCount = 0 self.calcPhysics = 0 self.newPic = 1 self.picCount = 0 self.target = array([80.0, 0.0, 0.0]) self.centerOfGrav = array([0.0, -2.0, 0.0]) self.points = ones((8, 3), float) self.savePics = False self.drawCounter = 0 self.fps = 25 self.dt = 1.0 / float(self.fps) self.client = UDPClient(servIP, ownIP, port) # If self.savePics=True this method saves the produced images def saveTo(self, filename, format="JPEG"): import Image # get PIL's functionality... @UnresolvedImport width, height = 800, 600 glPixelStorei(GL_PACK_ALIGNMENT, 1) data = glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE) image = Image.fromstring("RGB", (width, height), data) image = image.transpose(Image.FLIP_TOP_BOTTOM) image.save(filename, format) print('Saved image to ', filename) return image # the render method containing the Glut mainloop def _render(self): # Call init: Parameter(Window Position -> x, y, height, width) self.init_GL(self, 300, 300, 800, 600) self.object = objects3d.Objects3D() self.quad = gluNewQuadric() glutMainLoop() # The Glut idle function def drawIdleScene(self): #recive data from server and update the points of the cube try: self.points, self.centerOfGrav = eval(self.client.listen([self.points, self.centerOfGrav])) except: pass if self.points == "r": self.target = array([80.0, 0.0, 0.0]) self.centerOfGrav = array([0.0, -2.0, 0.0]) self.points = ones((8, 3), float) self.drawScene() if self.savePics: self.saveTo("./screenshots/image_jump" + repr(10000 + self.picCount) + ".jpg") self.picCount += 1 else: sleep(self.dt) def drawScene(self): ''' This methode describes the complete scene.''' # clear the buffer if self.zDis < 10: self.zDis += 0.25 if self.lastz > 200: self.lastz -= self.zDis glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() # Point of view glRotatef(self.lastx, 0.0, 1.0, 0.0) glRotatef(self.lasty, 1.0, 0.0, 0.0) #glRotatef(15, 0.0, 0.0, 1.0) # direction of view is aimed to the center of gravity of the cube glTranslatef(-self.centerOfGrav[0], -self.centerOfGrav[1] - 50.0, -self.centerOfGrav[2] - self.lastz) #Objects #Target Ball glColor3f(1, 0.25, 0.25) glPushMatrix() glTranslate(self.target[0], 0.0, self.target[2]) glutSolidSphere(1.5, 8, 8) glPopMatrix() #Massstab for lk in range(41): if float(lk - 20) / 10.0 == (lk - 20) / 10: glColor3f(0.75, 0.75, 0.75) glPushMatrix() glRotatef(90, 1, 0, 0) glTranslate(self.worldRadius / 40.0 * float(lk) - self.worldRadius / 2.0, -40.0, -30) quad = gluNewQuadric() gluCylinder(quad, 2, 2, 60, 4, 1); glPopMatrix() else: if float(lk - 20) / 5.0 == (lk - 20) / 5: glColor3f(0.75, 0.75, 0.75) glPushMatrix() glRotatef(90, 1, 0, 0) glTranslate(self.worldRadius / 40.0 * float(lk) - self.worldRadius / 2.0, -40.0, -15.0) quad = gluNewQuadric() gluCylinder(quad, 1, 1, 30, 4, 1); glPopMatrix() else: glColor3f(0.75, 0.75, 0.75) glPushMatrix() glRotatef(90, 1, 0, 0) glTranslate(self.worldRadius / 40.0 * float(lk) - self.worldRadius / 2.0, -40.0, -7.5) quad = gluNewQuadric() gluCylinder(quad, 0.5, 0.5, 15, 4, 1); glPopMatrix() #Mirror Center Ball glColor3f(1, 1, 1) glPushMatrix() glTranslate(self.centerOfGrav[0], -self.centerOfGrav[1], self.centerOfGrav[2]) glutSolidSphere(1.5, 8, 8) glPopMatrix() #Mirror Cube glEnable (GL_BLEND) glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glColor4f(0.5, 0.75, 0.5, 0.75) glPushMatrix() glTranslatef(0, -0.05, 0) self.object.drawMirCreat(self.points, self.centerOfGrav) glPopMatrix() # Floor tile = self.worldRadius / 40.0 glEnable (GL_BLEND) glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) for xF in range(40): for yF in range(40): if float(xF + yF) / 2.0 == (xF + yF) / 2: glColor3f(0.8, 0.8, 0.7) else: glColor4f(0.8, 0.8, 0.8, 0.7) glPushMatrix() glTranslatef(0.0, -0.03, 0.0) glBegin(GL_QUADS) glNormal(0.0, 1.0, 0.0) for i in range(2): for k in range(2): glVertex3f((i + xF - 20) * tile, 0.0, ((k ^ i) + yF - 20) * tile); glEnd() glPopMatrix() #Center Ball glColor3f(1, 1, 1) glPushMatrix() glTranslate(self.centerOfGrav[0], self.centerOfGrav[1], self.centerOfGrav[2]) glutSolidSphere(1.5, 8, 8) glPopMatrix() # Cube glEnable (GL_BLEND) glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glColor4f(0.5, 0.75, 0.5, 0.75) glPushMatrix() self.object.drawCreature(self.points, self.centerOfGrav) glPopMatrix() glEnable (GL_BLEND) glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) # Cubes shadow glColor4f(0, 0, 0, 0.5) glPushMatrix() self.object.drawShadow(self.points, self.centerOfGrav) glPopMatrix() # swap the buffer glutSwapBuffers() def resizeScene(self, width, height): '''Needed if window size changes.''' if height == 0: # Prevent A Divide By Zero If The Window Is Too Small height = 1 glViewport(0, 0, width, height) # Reset The Current Viewport And Perspective Transformation glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(45.0, float(width) / float(height), 0.1, 700.0) glMatrixMode(GL_MODELVIEW) def activeMouse(self, x, y): #Returns mouse coordinates while any mouse button is pressed. # store the mouse coordinate if self.mouseButton == GLUT_LEFT_BUTTON: self.lastx = x - self.xOffset self.lasty = y - self.yOffset if self.mouseButton == GLUT_RIGHT_BUTTON: self.lastz = y - self.zOffset # redisplay glutPostRedisplay() def passiveMouse(self, x, y): '''Returns mouse coordinates while no mouse button is pressed.''' pass def completeMouse(self, button, state, x, y): #Returns mouse coordinates and which button was pressed resp. released. self.mouseButton = button if state == GLUT_DOWN: self.xOffset = x - self.lastx self.yOffset = y - self.lasty self.zOffset = y - self.lastz # redisplay glutPostRedisplay() #Initialise an OpenGL windows with the origin at x, y and size of height, width. def init_GL(self, pyWorld, x, y, height, width): # initialize GLUT glutInit([]) glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH) glutInitWindowSize(height, width) glutInitWindowPosition(x, y) glutCreateWindow("The Curious Cube") glClearDepth(1.0) glEnable(GL_DEPTH_TEST) glClearColor(0.0, 0.0, 0.0, 0.0) glShadeModel(GL_SMOOTH) glMatrixMode(GL_MODELVIEW) # initialize lighting */ glLightfv(GL_LIGHT0, GL_DIFFUSE, [1, 1, 1, 1.0]) glLightModelfv(GL_LIGHT_MODEL_AMBIENT, [1.0, 1.0, 1.0, 1.0]) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) # glColorMaterial(GL_FRONT, GL_DIFFUSE) glEnable(GL_COLOR_MATERIAL) # Automatic vector normalise glEnable(GL_NORMALIZE) ### Instantiate the virtual world ### glutDisplayFunc(pyWorld.drawScene) glutMotionFunc(pyWorld.activeMouse) glutMouseFunc(pyWorld.completeMouse) glutReshapeFunc(pyWorld.resizeScene) glutIdleFunc(pyWorld.drawIdleScene)
class ODEViewer(object): def __init__(self, servIP="127.0.0.1", ownIP="127.0.0.1", port="21590", buf="16384"): # initialize the viewport size self.width = 800 self.height = 600 # initialize object which the camera follows self.centerObj = None self.mouseView = True self.viewDistance = 30 self.lastx = -0.5 self.lasty = 1 self.lastz = -1 self.dt = 1 self.fps = 50 self.lasttime = time.time() self.starttime = time.time() self.captureScreen = False self.isCapturing = False self.isFloorGreen = True self.message = None self.keyboardCallback = None # capture only every frameT. frame self.counter = 0 self.frameT = 1 self.init_GL() # set own callback functions glutMotionFunc(self._motionfunc) glutPassiveMotionFunc(self._passivemotionfunc) glutDisplayFunc(self._drawfunc) glutIdleFunc(self._idlefunc) glutKeyboardFunc(self._keyfunc) self.dt = 1.0 / self.fps self.lasttime = time.time() self.starttime = self.lasttime # initialize udp client self.client = UDPClient(servIP, ownIP, port, buf) def start(self): # start the OpenGL main loop while True: glutMainLoop() def setFrameRate(self, fps): self.fps = fps self.dt = 1.0 / self.fps def setCaptureScreen(self, capture): self.captureScreen = capture def getCaptureScreen(self): return self.captureScreen def waitScreenCapturing(self): self.isCapturing = True def isScreenCapturing(self): return self.isCapturing def setCenterObj(self, obj): self.centerObj = obj def updateData(self): try: self.message = self.client.listen() except: pass def init_GL(self, width=800, height=600): """ initialize OpenGL. This function has to be called only once before drawing. """ glutInit([]) # Open a window glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH) self.width = width self.height = height glutInitWindowPosition(500, 0) glutInitWindowSize(self.width, self.height) self._myWindow = glutCreateWindow("ODE Viewer") # Initialize Viewport and Shading glViewport(0, 0, self.width, self.height) glShadeModel(GL_SMOOTH) glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) glClearColor(1.0, 1.0, 1.0, 0.0) # Initialize Depth Buffer glClearDepth(1.0) glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) # Initialize Lighting glEnable(GL_LIGHTING) glLightfv(GL_LIGHT1, GL_AMBIENT, [0.5, 0.5, 0.5, 1.0]) glLightfv(GL_LIGHT1, GL_DIFFUSE, [1.0, 1.0, 1.0, 1.0]) glLightfv(GL_LIGHT1, GL_POSITION, [0.0, 5.0, 5.0, 1.0]) glEnable(GL_LIGHT1) # enable material coloring glEnable(GL_COLOR_MATERIAL) glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE) glEnable(GL_NORMALIZE) def prepare_GL(self): """Prepare drawing. This function is called in every step. It clears the screen and sets the new camera position""" # Clear the screen glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Projection mode glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(45, 1.3333, 0.2, 500) # Initialize ModelView matrix glMatrixMode(GL_MODELVIEW) glLoadIdentity() # View transformation (if "centerOn(...)" is set, keep camera to specific object) if self.centerObj is not None: (centerX, centerY, centerZ) = self.centerObj.getPosition() else: centerX = centerY = centerZ = 0 # use the mouse to shift eye sensor on a hemisphere eyeX = self.viewDistance * self.lastx eyeY = self.viewDistance * self.lasty + centerY eyeZ = self.viewDistance * self.lastz gluLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, 0, 1, 0) def draw_item(self, item): """ draws an object (spere, cube, plane, ...) """ glDisable(GL_TEXTURE_2D) glPushMatrix() if item['type'] in [ 'GeomBox', 'GeomSphere', 'GeomCylinder', 'GeomCCylinder' ]: # set color of object (currently dark gray) if item.has_key('color'): glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glColor4f(*(item['color'])) else: glColor3f(0.1, 0.1, 0.1) # transform (rotate, translate) body accordingly (x, y, z) = item['position'] R = item['rotation'] rot = [ R[0], R[3], R[6], 0.0, R[1], R[4], R[7], 0.0, R[2], R[5], R[8], 0.0, x, y, z, 1.0 ] glMultMatrixd(rot) # switch different geom objects if item['type'] == 'GeomBox': # cube (sx, sy, sz) = item['scale'] glScaled(sx, sy, sz) glutSolidCube(1) elif item['type'] == 'GeomSphere': # sphere glutSolidSphere(item['radius'], 20, 20) elif item['type'] == 'GeomCCylinder': quad = gluNewQuadric() # draw cylinder and two spheres, one at each end glTranslate(0.0, 0.0, -item['length'] / 2) gluCylinder(quad, item['radius'], item['radius'], item['length'], 32, 32) glutSolidSphere(item['radius'], 20, 20) glTranslate(0.0, 0.0, item['length']) glutSolidSphere(item['radius'], 20, 20) elif item['type'] == 'GeomCylinder': glTranslate(0.0, 0.0, -item['length'] / 2) quad = gluNewQuadric() gluDisk(quad, 0, item['radius'], 32, 1) quad = gluNewQuadric() gluCylinder(quad, item['radius'], item['radius'], item['length'], 32, 32) glTranslate(0.0, 0.0, item['length']) quad = gluNewQuadric() gluDisk(quad, 0, item['radius'], 32, 1) else: # TODO: add other geoms here pass elif item['type'] == 'GeomPlane': # set color of plane (currently green) if self.isFloorGreen: glColor3f(0.2, 0.6, 0.3) else: glColor3f(0.2, 0.3, 0.8) # for planes, we need a Quadric object quad = gluNewQuadric() gluQuadricTexture(quad, GL_TRUE) p = item['normal'] # the normal vector to the plane d = item['distance'] # the distance to the origin q = (0.0, 0.0, 1.0 ) # the normal vector of default gluDisks (z=0 plane) # calculate the cross product to get the rotation axis c = crossproduct(p, q) # calculate the angle between default normal q and plane normal p theta = acos(dotproduct(p, q) / (norm(p) * norm(q))) / pi * 180 # rotate the plane glPushMatrix() glTranslate(d * p[0], d * p[1], d * p[2]) glRotate(-theta, c[0], c[1], c[2]) gluDisk(quad, 0, 20, 20, 1) glPopMatrix() glPopMatrix() @staticmethod def _loadTexture(textureFile): image = open(textureFile) ix = image.size[0] iy = image.size[1] image = image.tostring("raw", "RGBX", 0, -1) # Create Texture textures = glGenTextures(3) glBindTexture(GL_TEXTURE_2D, textures[0]) # 2d texture (x and y size) glPixelStorei(GL_UNPACK_ALIGNMENT, 1) glTexImage2D(GL_TEXTURE_2D, 0, 3, ix, iy, 0, GL_RGBA, GL_BYTE, image) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL) # Create Linear Filtered Texture glBindTexture(GL_TEXTURE_2D, textures[1]) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexImage2D(GL_TEXTURE_2D, 0, 3, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image) # Create MipMapped Texture glBindTexture(GL_TEXTURE_2D, textures[2]) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST) gluBuild2DMipmaps(GL_TEXTURE_2D, 3, ix, iy, GL_RGBA, GL_UNSIGNED_BYTE, image) return textures def _drawfunc(self): """ draw callback function """ # Draw the scene self.prepare_GL() if self.message: for item in self.message: self.draw_item(item) glutSwapBuffers() if self.captureScreen: self._screenshot() def _idlefunc(self): self.updateData() t = self.dt - (time.time() - self.lasttime) if (t > 0): time.sleep(t) self.lasttime = time.time() glutPostRedisplay() def _keyfunc(self, c, x, y): """ keyboard call-back function. """ if c == 's': self.setCaptureScreen(not self.getCaptureScreen()) print("Screen Capture: " + (self.getCaptureScreen() and "on" or "off")) if c in ['x', 'q']: sys.exit() if c == 'v': self.mouseView = not self.mouseView def _motionfunc(self, x, z): """Control the zoom factor""" if not self.mouseView: return zn = 2.75 * float(z) / self.height + 0.25 # [0.25,3] self.viewDistance = 3.0 * zn * zn self._passivemotionfunc(x, z) def _passivemotionfunc(self, x, z): """ Store the mouse coordinates (relative to center and normalized) the eye does not exactly move on a unit hemisphere; we fudge the projection a little by shifting the hemisphere into the ground by 0.1 units, such that approaching the perimeter dows not cause a huge change in the viewing direction. The limit for l is thus cos(arcsin(0.1)).""" if not self.mouseView: return x1 = 3 * float(x) / self.width - 1.5 z1 = -3 * float(z) / self.height + 1.5 lsq = x1 * x1 + z1 * z1 l = sqrt(lsq) if l > 0.994987: # for mouse outside window, project onto the unit circle x1 = x1 / l z1 = z1 / l y1 = 0 else: y1 = max(0.0, sqrt(1.0 - x1 * x1 - z1 * z1) - 0.1) self.lasty = y1 self.lastx = x1 self.lastz = z1 def _screenshot(self, path_prefix='.', format='PNG'): """Saves a screenshot of the current frame buffer. The save path is <path_prefix>/.screenshots/shot<num>.png The path is automatically created if it does not exist. Shots are automatically numerated based on how many files are already in the directory.""" if self.counter == self.frameT: self.counter = 1 dir = os.path.join(path_prefix, 'screenshots') if not os.path.exists(dir): os.makedirs(dir) num_present = len(os.listdir(dir)) num_digits = len(str(num_present)) index = '0' * (5 - num_digits) + str(num_present) path = os.path.join(dir, 'shot' + index + '.' + format.lower()) glPixelStorei(GL_PACK_ALIGNMENT, 1) data = glReadPixels(0, 0, self.width, self.height, GL_RGB, GL_UNSIGNED_BYTE) image = Image.fromstring("RGB", (self.width, self.height), data) image = image.transpose(Image.FLIP_TOP_BOTTOM) image.save(path, format) print('Image saved to %s' % (os.path.basename(path))) else: self.counter += 1 self.isCapturing = False
class FlexCubeRenderer(object): #Options: ServerIP(default:localhost), OwnIP(default:localhost), Port(default:21560) def __init__(self, servIP="127.0.0.1", ownIP="127.0.0.1", port="21580"): self.oldScreenValues = None self.view = 0 self.worldRadius = 400 # Start of mousepointer self.lastx = 0 self.lasty = 15 self.lastz = 300 self.zDis = 1 # Start of cube self.cube = [0.0, 0.0, 0.0] self.bmpCount = 0 self.actCount = 0 self.calcPhysics = 0 self.newPic = 1 self.picCount = 0 self.sensors = [0.0, 0.0, 0.0] self.centerOfGrav = array([0.0, 5.0, 0.0]) self.savePics = False self.drawCounter = 0 self.fps = 50 self.dt = 1.0 / float(self.fps) self.step = 0 self.client = UDPClient(servIP, ownIP, port) # If self.savePics=True this method saves the produced images def saveTo(self, filename, format="JPEG"): import Image # get PIL's functionality... width, height = 800, 600 glPixelStorei(GL_PACK_ALIGNMENT, 1) data = glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE) image = Image.fromstring("RGB", (width, height), data) image = image.transpose(Image.FLIP_TOP_BOTTOM) image.save(filename, format) print('Saved image to ', filename) return image # the render method containing the Glut mainloop def _render(self): # Call init: Parameter(Window Position -> x, y, height, width) self.init_GL(self, 300, 300, 800, 600) self.quad = gluNewQuadric() glutMainLoop() # The Glut idle function def drawIdleScene(self): #recive data from server and update the points of the cube try: self.sensors = self.client.listen(self.sensors) except: pass if self.sensors == ["r", "r", "r"]: self.centerOfGrav = array([0.0, 5.0, 0.0]) else: self.step += 1 a = self.sensors[0] / 360.0 * 3.1428 dir = array([cos(a), 0.0, -sin(a)]) self.centerOfGrav += self.sensors[2] * dir * 0.02 self.drawScene() if self.savePics: self.saveTo("./screenshots/image_jump" + repr(10000 + self.picCount) + ".jpg") self.picCount += 1 else: sleep(self.dt) def drawScene(self): ''' This methode describes the complete scene.''' # clear the buffer if self.zDis < 10: self.zDis += 0.25 if self.lastz > 100: self.lastz -= self.zDis glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() # Point of view glRotatef(self.lastx, 0.0, 1.0, 0.0) glRotatef(self.lasty, 1.0, 0.0, 0.0) #glRotatef(15, 0.0, 0.0, 1.0) # direction of view is aimed to the center of gravity of the cube glTranslatef(-self.centerOfGrav[0], -self.centerOfGrav[1] - 50.0, -self.centerOfGrav[2] - self.lastz) #Objects #Massstab for lk in range(41): if float(lk - 20) / 10.0 == (lk - 20) / 10: glColor3f(0.75, 0.75, 0.75) glPushMatrix() glRotatef(90, 1, 0, 0) glTranslate( self.worldRadius / 40.0 * float(lk) - self.worldRadius / 2.0, -40.0, -30) quad = gluNewQuadric() gluCylinder(quad, 2, 2, 60, 4, 1) glPopMatrix() else: if float(lk - 20) / 5.0 == (lk - 20) / 5: glColor3f(0.75, 0.75, 0.75) glPushMatrix() glRotatef(90, 1, 0, 0) glTranslate( self.worldRadius / 40.0 * float(lk) - self.worldRadius / 2.0, -40.0, -15.0) quad = gluNewQuadric() gluCylinder(quad, 1, 1, 30, 4, 1) glPopMatrix() else: glColor3f(0.75, 0.75, 0.75) glPushMatrix() glRotatef(90, 1, 0, 0) glTranslate( self.worldRadius / 40.0 * float(lk) - self.worldRadius / 2.0, -40.0, -7.5) quad = gluNewQuadric() gluCylinder(quad, 0.5, 0.5, 15, 4, 1) glPopMatrix() # Floor tile = self.worldRadius / 40.0 glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glColor3f(0.8, 0.8, 0.5) glPushMatrix() glTranslatef(0.0, -3.0, 0.0) glBegin(GL_QUADS) glNormal(0.0, 1.0, 0.0) glVertex3f(-self.worldRadius, 0.0, -self.worldRadius) glVertex3f(-self.worldRadius, 0.0, self.worldRadius) glVertex3f(self.worldRadius, 0.0, self.worldRadius) glVertex3f(self.worldRadius, 0.0, -self.worldRadius) glEnd() glPopMatrix() #Water for xF in range(40): for yF in range(40): if float(xF + yF) / 2.0 == (xF + yF) / 2: glColor4f(0.7, 0.7, 1.0, 0.5) else: glColor4f(0.9, 0.9, 1.0, 0.5) glPushMatrix() glTranslatef(0.0, -0.03, 0.0) glBegin(GL_QUADS) glNormal(0.5 + sin(float(xF) + float(self.step) / 4.0) * 0.5, 0.5 + cos(float(xF) + float(self.step) / 4.0) * 0.5, 0.0) for i in range(2): for k in range(2): glVertex3f( (i + xF - 20) * tile, sin(float(xF + i) + float(self.step) / 4.0) * 3.0, ((k ^ i) + yF - 20) * tile) glEnd() glPopMatrix() self.ship() # swap the buffer glutSwapBuffers() def ship(self): glColor3f(0.4, 0.1, 0.2) glPushMatrix() glTranslate(self.centerOfGrav[0] + 14, self.centerOfGrav[1], self.centerOfGrav[2]) glRotatef(180 - self.sensors[0], 0.0, 1.0, 0.0) self.cuboid(0, 0, 0, 20, 5, 5) #bow of ship glBegin(GL_TRIANGLES) glNormal3fv( self.calcNormal(self.points2Vector([-5, 6, 2.5], [0, 5, 5]), self.points2Vector([-5, 6, 2.5], [0, 5, 0]))) glVertex3f(-5, 6, 2.5), glVertex3f(0, 5, 0), glVertex3f(0, 5, 5) glNormal3fv( self.calcNormal(self.points2Vector([-5, 6, 2.5], [0, 0, 5]), self.points2Vector([-5, 6, 2.5], [0, 5, 5]))) glVertex3f(-5, 6, 2.5), glVertex3f(0, 0, 5), glVertex3f(0, 5, 5) glNormal3fv( self.calcNormal(self.points2Vector([-5, 6, 2.5], [0, 0, 0]), self.points2Vector([-5, 6, 2.5], [0, 0, 5]))) glVertex3f(-5, 6, 2.5), glVertex3f(0, 0, 5), glVertex3f(0, 0, 0) glNormal3fv( self.calcNormal(self.points2Vector([-5, 6, 2.5], [0, 5, 0]), self.points2Vector([-5, 6, 2.5], [0, 0, 0]))) glVertex3f(-5, 6, 2.5), glVertex3f(0, 0, 0), glVertex3f(0, 5, 0) glEnd() # stern glPushMatrix() glRotatef(-90, 1.0, 0.0, 0.0) glTranslatef(15, -2.5, 0) gluCylinder(self.quad, 2.5, 2.5, 5, 10, 1) glTranslatef(0, 0, 5) gluDisk(self.quad, 0, 2.5, 10, 1) glPopMatrix() # deck if abs(self.sensors[0]) < 5.0: reward = (self.sensors[2] + 10.0) / 50.0 else: reward = 0.2 glColor3f(1.0 - reward, reward, 0) self.cuboid(5, 5, 1, 10, 8, 4) glPushMatrix() glRotatef(-90, 1.0, 0.0, 0.0) glTranslatef(13, -2.5, 5) glColor3f(1, 1, 1) gluCylinder(self.quad, 1, 0.8, 5, 20, 1) glPopMatrix() glPopMatrix() def cuboid(self, x0, y0, z0, x1, y1, z1): glBegin(GL_QUADS) glNormal(0, 0, 1) glVertex3f(x0, y0, z1) glVertex3f(x0, y1, z1) glVertex3f(x1, y1, z1) glVertex3f(x1, y0, z1) #front glNormal(-1, 0, 0) glVertex3f(x0, y0, z0) glVertex3f(x0, y0, z1) glVertex3f(x0, y1, z1) glVertex3f(x0, y1, z0) # left glNormal(0, -1, 0) glVertex3f(x0, y0, z0) glVertex3f(x0, y0, z1) glVertex3f(x1, y0, z1) glVertex3f(x1, y0, z0) # bottom glNormal(0, 0, -1) glVertex3f(x0, y0, z0) glVertex3f(x1, y0, z0) glVertex3f(x1, y1, z0) glVertex3f(x0, y1, z0) # back glNormal(0, 1, 0) glVertex3f(x0, y1, z0) glVertex3f(x1, y1, z0) glVertex3f(x1, y1, z1) glVertex3f(x0, y1, z1) # top glNormal(1, 0, 0) glVertex3f(x1, y0, z0) glVertex3f(x1, y0, z1) glVertex3f(x1, y1, z1) glVertex3f(x1, y1, z0) # right glEnd() def calcNormal(self, xVector, yVector): result = [0, 0, 0] result[0] = xVector[1] * yVector[2] - yVector[1] * xVector[2] result[1] = -xVector[0] * yVector[2] + yVector[0] * xVector[2] result[2] = xVector[0] * yVector[1] - yVector[0] * xVector[1] return [result[0], result[1], result[2]] def points2Vector(self, startPoint, endPoint): result = [0, 0, 0] result[0] = endPoint[0] - startPoint[0] result[1] = endPoint[1] - startPoint[1] result[2] = endPoint[2] - startPoint[2] return [result[0], result[1], result[2]] def resizeScene(self, width, height): '''Needed if window size changes.''' if height == 0: # Prevent A Divide By Zero If The Window Is Too Small height = 1 glViewport( 0, 0, width, height ) # Reset The Current Viewport And Perspective Transformation glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(45.0, float(width) / float(height), 0.1, 700.0) glMatrixMode(GL_MODELVIEW) def activeMouse(self, x, y): #Returns mouse coordinates while any mouse button is pressed. # store the mouse coordinate if self.mouseButton == GLUT_LEFT_BUTTON: self.lastx = x - self.xOffset self.lasty = y - self.yOffset if self.mouseButton == GLUT_RIGHT_BUTTON: self.lastz = y - self.zOffset # redisplay glutPostRedisplay() def passiveMouse(self, x, y): '''Returns mouse coordinates while no mouse button is pressed.''' pass def completeMouse(self, button, state, x, y): #Returns mouse coordinates and which button was pressed resp. released. self.mouseButton = button if state == GLUT_DOWN: self.xOffset = x - self.lastx self.yOffset = y - self.lasty self.zOffset = y - self.lastz # redisplay glutPostRedisplay() #Initialise an OpenGL windows with the origin at x, y and size of height, width. def init_GL(self, pyWorld, x, y, height, width): # initialize GLUT glutInit([]) glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH) glutInitWindowSize(height, width) glutInitWindowPosition(x, y) glutCreateWindow("The Curious Cube") glClearDepth(1.0) glEnable(GL_DEPTH_TEST) glClearColor(0.0, 0.0, 0.0, 0.0) glShadeModel(GL_SMOOTH) glMatrixMode(GL_MODELVIEW) # initialize lighting */ glLightfv(GL_LIGHT0, GL_DIFFUSE, [1, 1, 1, 1.0]) glLightModelfv(GL_LIGHT_MODEL_AMBIENT, [1.0, 1.0, 1.0, 1.0]) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) # glColorMaterial(GL_FRONT, GL_DIFFUSE) glEnable(GL_COLOR_MATERIAL) # Automatic vector normalise glEnable(GL_NORMALIZE) ### Instantiate the virtual world ### glutDisplayFunc(pyWorld.drawScene) glutMotionFunc(pyWorld.activeMouse) glutMouseFunc(pyWorld.completeMouse) glutReshapeFunc(pyWorld.resizeScene) glutIdleFunc(pyWorld.drawIdleScene)
class ODEViewer(object): def __init__(self, servIP="127.0.0.1", ownIP="127.0.0.1", port="21590", buf="16384"): # initialize the viewport size self.width = 800 self.height = 600 # initialize object which the camera follows self.centerObj = None self.mouseView = True self.viewDistance = 30 self.lastx = -0.5 self.lasty = 1 self.lastz = -1 self.dt = 1 self.fps = 50 self.lasttime = time.time() self.starttime = time.time() self.captureScreen = False self.isCapturing = False self.isFloorGreen = True self.message = None self.keyboardCallback = None # capture only every frameT. frame self.counter = 0 self.frameT = 1 self.init_GL() # set own callback functions glutMotionFunc (self._motionfunc) glutPassiveMotionFunc(self._passivemotionfunc) glutDisplayFunc (self._drawfunc) glutIdleFunc (self._idlefunc) glutKeyboardFunc (self._keyfunc) self.dt = 1.0 / self.fps self.lasttime = time.time() self.starttime = self.lasttime # initialize udp client self.client = UDPClient(servIP, ownIP, port, buf) def start(self): # start the OpenGL main loop while True: glutMainLoop() def setFrameRate(self, fps): self.fps = fps self.dt = 1.0 / self.fps def setCaptureScreen(self, capture): self.captureScreen = capture def getCaptureScreen(self): return self.captureScreen def waitScreenCapturing(self): self.isCapturing = True def isScreenCapturing(self): return self.isCapturing def setCenterObj(self, obj): self.centerObj = obj def updateData(self): try: self.message = self.client.listen() except: pass def init_GL(self, width=800, height=600): """ initialize OpenGL. This function has to be called only once before drawing. """ glutInit([]) # Open a window glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH) self.width = width self.height = height glutInitWindowPosition (500, 0) glutInitWindowSize (self.width, self.height) self._myWindow = glutCreateWindow ("ODE Viewer") # Initialize Viewport and Shading glViewport(0, 0, self.width, self.height) glShadeModel(GL_SMOOTH) glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) glClearColor(1.0, 1.0, 1.0, 0.0) # Initialize Depth Buffer glClearDepth(1.0) glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) # Initialize Lighting glEnable(GL_LIGHTING) glLightfv(GL_LIGHT1, GL_AMBIENT, [0.5, 0.5, 0.5, 1.0]) glLightfv(GL_LIGHT1, GL_DIFFUSE, [1.0, 1.0, 1.0, 1.0]) glLightfv(GL_LIGHT1, GL_POSITION, [0.0, 5.0, 5.0, 1.0]) glEnable(GL_LIGHT1) # enable material coloring glEnable(GL_COLOR_MATERIAL) glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE) glEnable(GL_NORMALIZE) def prepare_GL(self): """Prepare drawing. This function is called in every step. It clears the screen and sets the new camera position""" # Clear the screen glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Projection mode glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective (45, 1.3333, 0.2, 500) # Initialize ModelView matrix glMatrixMode(GL_MODELVIEW) glLoadIdentity() # View transformation (if "centerOn(...)" is set, keep camera to specific object) if self.centerObj is not None: (centerX, centerY, centerZ) = self.centerObj.getPosition() else: centerX = centerY = centerZ = 0 # use the mouse to shift eye sensor on a hemisphere eyeX = self.viewDistance * self.lastx eyeY = self.viewDistance * self.lasty + centerY eyeZ = self.viewDistance * self.lastz gluLookAt (eyeX, eyeY, eyeZ, centerX, centerY, centerZ, 0, 1, 0) def draw_item(self, item): """ draws an object (spere, cube, plane, ...) """ glDisable(GL_TEXTURE_2D) glPushMatrix() if item['type'] in ['GeomBox', 'GeomSphere', 'GeomCylinder', 'GeomCCylinder']: # set color of object (currently dark gray) if item.has_key('color'): glEnable (GL_BLEND) glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glColor4f(*(item['color'])) else: glColor3f(0.1, 0.1, 0.1) # transform (rotate, translate) body accordingly (x, y, z) = item['position'] R = item['rotation'] rot = [R[0], R[3], R[6], 0.0, R[1], R[4], R[7], 0.0, R[2], R[5], R[8], 0.0, x, y, z, 1.0] glMultMatrixd(rot) # switch different geom objects if item['type'] == 'GeomBox': # cube (sx, sy, sz) = item['scale'] glScaled(sx, sy, sz) glutSolidCube(1) elif item['type'] == 'GeomSphere': # sphere glutSolidSphere(item['radius'], 20, 20) elif item['type'] == 'GeomCCylinder': quad = gluNewQuadric() # draw cylinder and two spheres, one at each end glTranslate(0.0, 0.0, -item['length'] / 2) gluCylinder(quad, item['radius'], item['radius'], item['length'], 32, 32) glutSolidSphere(item['radius'], 20, 20) glTranslate(0.0, 0.0, item['length']) glutSolidSphere(item['radius'], 20, 20) elif item['type'] == 'GeomCylinder': glTranslate(0.0, 0.0, -item['length'] / 2) quad = gluNewQuadric() gluDisk(quad, 0, item['radius'], 32, 1) quad = gluNewQuadric() gluCylinder(quad, item['radius'], item['radius'], item['length'], 32, 32) glTranslate(0.0, 0.0, item['length']) quad = gluNewQuadric() gluDisk(quad, 0, item['radius'], 32, 1) else: # TODO: add other geoms here pass elif item['type'] == 'GeomPlane': # set color of plane (currently green) if self.isFloorGreen: glColor3f(0.2, 0.6, 0.3) else: glColor3f(0.2, 0.3, 0.8) # for planes, we need a Quadric object quad = gluNewQuadric() gluQuadricTexture(quad, GL_TRUE) p = item['normal'] # the normal vector to the plane d = item['distance'] # the distance to the origin q = (0.0, 0.0, 1.0) # the normal vector of default gluDisks (z=0 plane) # calculate the cross product to get the rotation axis c = crossproduct(p, q) # calculate the angle between default normal q and plane normal p theta = acos(dotproduct(p, q) / (norm(p) * norm(q))) / pi * 180 # rotate the plane glPushMatrix() glTranslate(d * p[0], d * p[1], d * p[2]) glRotate(-theta, c[0], c[1], c[2]) gluDisk(quad, 0, 20, 20, 1) glPopMatrix() glPopMatrix() @staticmethod def _loadTexture(textureFile): image = open(textureFile) ix = image.size[0] iy = image.size[1] image = image.tostring("raw", "RGBX", 0, -1) # Create Texture textures = glGenTextures(3) glBindTexture(GL_TEXTURE_2D, textures[0]) # 2d texture (x and y size) glPixelStorei(GL_UNPACK_ALIGNMENT, 1) glTexImage2D(GL_TEXTURE_2D, 0, 3, ix, iy, 0, GL_RGBA, GL_BYTE, image) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL) # Create Linear Filtered Texture glBindTexture(GL_TEXTURE_2D, textures[1]) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexImage2D(GL_TEXTURE_2D, 0, 3, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image) # Create MipMapped Texture glBindTexture(GL_TEXTURE_2D, textures[2]) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST) gluBuild2DMipmaps(GL_TEXTURE_2D, 3, ix, iy, GL_RGBA, GL_UNSIGNED_BYTE, image) return textures def _drawfunc (self): """ draw callback function """ # Draw the scene self.prepare_GL() if self.message: for item in self.message: self.draw_item(item) glutSwapBuffers() if self.captureScreen: self._screenshot() def _idlefunc(self): self.updateData() t = self.dt - (time.time() - self.lasttime) if (t > 0): time.sleep(t) self.lasttime = time.time() glutPostRedisplay () def _keyfunc (self, c, x, y): """ keyboard call-back function. """ if c == 's': self.setCaptureScreen(not self.getCaptureScreen()) print "Screen Capture: " + (self.getCaptureScreen() and "on" or "off") if c in ['x', 'q']: sys.exit() if c == 'v': self.mouseView = not self.mouseView def _motionfunc(self, x, z): """Control the zoom factor""" if not self.mouseView: return zn = 2.75 * float(z) / self.height + 0.25 # [0.25,3] self.viewDistance = 3.0 * zn * zn self._passivemotionfunc(x, z) def _passivemotionfunc(self, x, z): """ Store the mouse coordinates (relative to center and normalized) the eye does not exactly move on a unit hemisphere; we fudge the projection a little by shifting the hemisphere into the ground by 0.1 units, such that approaching the perimeter dows not cause a huge change in the viewing direction. The limit for l is thus cos(arcsin(0.1)).""" if not self.mouseView: return x1 = 3 * float(x) / self.width - 1.5 z1 = -3 * float(z) / self.height + 1.5 lsq = x1 * x1 + z1 * z1 l = sqrt(lsq) if l > 0.994987: # for mouse outside window, project onto the unit circle x1 = x1 / l z1 = z1 / l y1 = 0 else: y1 = max(0.0, sqrt(1.0 - x1 * x1 - z1 * z1) - 0.1) self.lasty = y1 self.lastx = x1 self.lastz = z1 def _screenshot(self, path_prefix='.', format='PNG'): """Saves a screenshot of the current frame buffer. The save path is <path_prefix>/.screenshots/shot<num>.png The path is automatically created if it does not exist. Shots are automatically numerated based on how many files are already in the directory.""" if self.counter == self.frameT: self.counter = 1 dir = os.path.join(path_prefix, 'screenshots') if not os.path.exists(dir): os.makedirs(dir) num_present = len(os.listdir(dir)) num_digits = len(str(num_present)) index = '0' * (5 - num_digits) + str(num_present) path = os.path.join(dir, 'shot' + index + '.' + format.lower()) glPixelStorei(GL_PACK_ALIGNMENT, 1) data = glReadPixels(0, 0, self.width, self.height, GL_RGB, GL_UNSIGNED_BYTE) image = Image.fromstring("RGB", (self.width, self.height), data) image = image.transpose(Image.FLIP_TOP_BOTTOM) image.save(path, format) print 'Image saved to %s' % (os.path.basename(path)) else: self.counter += 1 self.isCapturing = False
class FlexCubeRenderer(object): #Options: ServerIP(default:localhost), OwnIP(default:localhost), Port(default:21560) def __init__(self, servIP="127.0.0.1", ownIP="127.0.0.1", port="21580"): self.oldScreenValues = None self.view = 0 self.worldRadius = 400 # Start of mousepointer self.lastx = 0 self.lasty = 15 self.lastz = 300 self.zDis = 1 # Start of cube self.cube = [0.0, 0.0, 0.0] self.bmpCount = 0 self.actCount = 0 self.calcPhysics = 0 self.newPic = 1 self.picCount = 0 self.sensors = [0.0, 0.0, 0.0] self.centerOfGrav = array([0.0, 5.0, 0.0]) self.savePics = False self.drawCounter = 0 self.fps = 50 self.dt = 1.0 / float(self.fps) self.step = 0 self.client = UDPClient(servIP, ownIP, port) # If self.savePics=True this method saves the produced images def saveTo(self, filename, format="JPEG"): import Image # get PIL's functionality... width, height = 800, 600 glPixelStorei(GL_PACK_ALIGNMENT, 1) data = glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE) image = Image.fromstring("RGB", (width, height), data) image = image.transpose(Image.FLIP_TOP_BOTTOM) image.save(filename, format) print 'Saved image to ', filename return image # the render method containing the Glut mainloop def _render(self): # Call init: Parameter(Window Position -> x, y, height, width) self.init_GL(self, 300, 300, 800, 600) self.quad = gluNewQuadric() glutMainLoop() # The Glut idle function def drawIdleScene(self): #recive data from server and update the points of the cube try: self.sensors = self.client.listen(self.sensors) except: pass if self.sensors == ["r", "r", "r"]: self.centerOfGrav = array([0.0, 5.0, 0.0]) else: self.step += 1 a = self.sensors[0] / 360.0 * 3.1428 dir = array([cos(a), 0.0, -sin(a)]) self.centerOfGrav += self.sensors[2] * dir * 0.02 self.drawScene() if self.savePics: self.saveTo("./screenshots/image_jump" + repr(10000 + self.picCount) + ".jpg") self.picCount += 1 else: sleep(self.dt) def drawScene(self): ''' This methode describes the complete scene.''' # clear the buffer if self.zDis < 10: self.zDis += 0.25 if self.lastz > 100: self.lastz -= self.zDis glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() # Point of view glRotatef(self.lastx, 0.0, 1.0, 0.0) glRotatef(self.lasty, 1.0, 0.0, 0.0) #glRotatef(15, 0.0, 0.0, 1.0) # direction of view is aimed to the center of gravity of the cube glTranslatef(-self.centerOfGrav[0], -self.centerOfGrav[1] - 50.0, -self.centerOfGrav[2] - self.lastz) #Objects #Massstab for lk in range(41): if float(lk - 20) / 10.0 == (lk - 20) / 10: glColor3f(0.75, 0.75, 0.75) glPushMatrix() glRotatef(90, 1, 0, 0) glTranslate(self.worldRadius / 40.0 * float(lk) - self.worldRadius / 2.0, -40.0, -30) quad = gluNewQuadric() gluCylinder(quad, 2, 2, 60, 4, 1) glPopMatrix() else: if float(lk - 20) / 5.0 == (lk - 20) / 5: glColor3f(0.75, 0.75, 0.75) glPushMatrix() glRotatef(90, 1, 0, 0) glTranslate(self.worldRadius / 40.0 * float(lk) - self.worldRadius / 2.0, -40.0, -15.0) quad = gluNewQuadric() gluCylinder(quad, 1, 1, 30, 4, 1) glPopMatrix() else: glColor3f(0.75, 0.75, 0.75) glPushMatrix() glRotatef(90, 1, 0, 0) glTranslate(self.worldRadius / 40.0 * float(lk) - self.worldRadius / 2.0, -40.0, -7.5) quad = gluNewQuadric() gluCylinder(quad, 0.5, 0.5, 15, 4, 1) glPopMatrix() # Floor tile = self.worldRadius / 40.0 glEnable (GL_BLEND) glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glColor3f(0.8, 0.8, 0.5) glPushMatrix() glTranslatef(0.0, -3.0, 0.0) glBegin(GL_QUADS) glNormal(0.0, 1.0, 0.0) glVertex3f(-self.worldRadius, 0.0, -self.worldRadius) glVertex3f(-self.worldRadius, 0.0, self.worldRadius) glVertex3f(self.worldRadius, 0.0, self.worldRadius) glVertex3f(self.worldRadius, 0.0, -self.worldRadius) glEnd() glPopMatrix() #Water for xF in range(40): for yF in range(40): if float(xF + yF) / 2.0 == (xF + yF) / 2: glColor4f(0.7, 0.7, 1.0, 0.5) else: glColor4f(0.9, 0.9, 1.0, 0.5) glPushMatrix() glTranslatef(0.0, -0.03, 0.0) glBegin(GL_QUADS) glNormal(0.5 + sin(float(xF) + float(self.step) / 4.0) * 0.5, 0.5 + cos(float(xF) + float(self.step) / 4.0) * 0.5, 0.0) for i in range(2): for k in range(2): glVertex3f((i + xF - 20) * tile, sin(float(xF + i) + float(self.step) / 4.0) * 3.0, ((k ^ i) + yF - 20) * tile) glEnd() glPopMatrix() self.ship() # swap the buffer glutSwapBuffers() def ship(self): glColor3f(0.4, 0.1, 0.2) glPushMatrix() glTranslate(self.centerOfGrav[0] + 14, self.centerOfGrav[1], self.centerOfGrav[2]) glRotatef(180 - self.sensors[0], 0.0, 1.0, 0.0) self.cuboid(0, 0, 0, 20, 5, 5) #bow of ship glBegin(GL_TRIANGLES) glNormal3fv(self.calcNormal(self.points2Vector([-5, 6, 2.5], [0, 5, 5]), self.points2Vector([-5, 6, 2.5], [0, 5, 0]))) glVertex3f(-5, 6, 2.5), glVertex3f(0, 5, 0), glVertex3f(0, 5, 5) glNormal3fv(self.calcNormal(self.points2Vector([-5, 6, 2.5], [0, 0, 5]), self.points2Vector([-5, 6, 2.5], [0, 5, 5]))) glVertex3f(-5, 6, 2.5), glVertex3f(0, 0, 5), glVertex3f(0, 5, 5) glNormal3fv(self.calcNormal(self.points2Vector([-5, 6, 2.5], [0, 0, 0]), self.points2Vector([-5, 6, 2.5], [0, 0, 5]))) glVertex3f(-5, 6, 2.5), glVertex3f(0, 0, 5), glVertex3f(0, 0, 0) glNormal3fv(self.calcNormal(self.points2Vector([-5, 6, 2.5], [0, 5, 0]), self.points2Vector([-5, 6, 2.5], [0, 0, 0]))) glVertex3f(-5, 6, 2.5), glVertex3f(0, 0, 0), glVertex3f(0, 5, 0) glEnd() # stern glPushMatrix() glRotatef(-90, 1.0, 0.0, 0.0) glTranslatef(15, -2.5, 0) gluCylinder(self.quad, 2.5, 2.5, 5, 10, 1) glTranslatef(0, 0, 5) gluDisk(self.quad, 0, 2.5, 10, 1) glPopMatrix() # deck if abs(self.sensors[0]) < 5.0: reward = (self.sensors[2] + 10.0) / 50.0 else: reward = 0.2 glColor3f(1.0 - reward, reward, 0) self.cuboid(5, 5, 1, 10, 8, 4) glPushMatrix() glRotatef(-90, 1.0, 0.0, 0.0) glTranslatef(13, -2.5, 5) glColor3f(1, 1, 1) gluCylinder(self.quad, 1, 0.8, 5, 20, 1) glPopMatrix() glPopMatrix() def cuboid(self, x0, y0, z0, x1, y1, z1): glBegin(GL_QUADS) glNormal(0, 0, 1) glVertex3f(x0, y0, z1); glVertex3f(x0, y1, z1); glVertex3f(x1, y1, z1); glVertex3f(x1, y0, z1) #front glNormal(-1, 0, 0) glVertex3f(x0, y0, z0); glVertex3f(x0, y0, z1); glVertex3f(x0, y1, z1); glVertex3f(x0, y1, z0) # left glNormal(0, -1, 0) glVertex3f(x0, y0, z0); glVertex3f(x0, y0, z1); glVertex3f(x1, y0, z1); glVertex3f(x1, y0, z0) # bottom glNormal(0, 0, -1) glVertex3f(x0, y0, z0); glVertex3f(x1, y0, z0); glVertex3f(x1, y1, z0); glVertex3f(x0, y1, z0) # back glNormal(0, 1, 0) glVertex3f(x0, y1, z0); glVertex3f(x1, y1, z0); glVertex3f(x1, y1, z1); glVertex3f(x0, y1, z1) # top glNormal(1, 0, 0) glVertex3f(x1, y0, z0); glVertex3f(x1, y0, z1); glVertex3f(x1, y1, z1); glVertex3f(x1, y1, z0) # right glEnd() def calcNormal(self, xVector, yVector): result = [0, 0, 0] result[0] = xVector[1] * yVector[2] - yVector[1] * xVector[2] result[1] = -xVector[0] * yVector[2] + yVector[0] * xVector[2] result[2] = xVector[0] * yVector[1] - yVector[0] * xVector[1] return [result[0], result[1], result[2]] def points2Vector(self, startPoint, endPoint): result = [0, 0, 0] result[0] = endPoint[0] - startPoint[0] result[1] = endPoint[1] - startPoint[1] result[2] = endPoint[2] - startPoint[2] return [result[0], result[1], result[2]] def resizeScene(self, width, height): '''Needed if window size changes.''' if height == 0: # Prevent A Divide By Zero If The Window Is Too Small height = 1 glViewport(0, 0, width, height) # Reset The Current Viewport And Perspective Transformation glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(45.0, float(width) / float(height), 0.1, 700.0) glMatrixMode(GL_MODELVIEW) def activeMouse(self, x, y): #Returns mouse coordinates while any mouse button is pressed. # store the mouse coordinate if self.mouseButton == GLUT_LEFT_BUTTON: self.lastx = x - self.xOffset self.lasty = y - self.yOffset if self.mouseButton == GLUT_RIGHT_BUTTON: self.lastz = y - self.zOffset # redisplay glutPostRedisplay() def passiveMouse(self, x, y): '''Returns mouse coordinates while no mouse button is pressed.''' pass def completeMouse(self, button, state, x, y): #Returns mouse coordinates and which button was pressed resp. released. self.mouseButton = button if state == GLUT_DOWN: self.xOffset = x - self.lastx self.yOffset = y - self.lasty self.zOffset = y - self.lastz # redisplay glutPostRedisplay() #Initialise an OpenGL windows with the origin at x, y and size of height, width. def init_GL(self, pyWorld, x, y, height, width): # initialize GLUT glutInit([]) glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH) glutInitWindowSize(height, width) glutInitWindowPosition(x, y) glutCreateWindow("The Curious Cube") glClearDepth(1.0) glEnable(GL_DEPTH_TEST) glClearColor(0.0, 0.0, 0.0, 0.0) glShadeModel(GL_SMOOTH) glMatrixMode(GL_MODELVIEW) # initialize lighting */ glLightfv(GL_LIGHT0, GL_DIFFUSE, [1, 1, 1, 1.0]) glLightModelfv(GL_LIGHT_MODEL_AMBIENT, [1.0, 1.0, 1.0, 1.0]) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) # glColorMaterial(GL_FRONT, GL_DIFFUSE) glEnable(GL_COLOR_MATERIAL) # Automatic vector normalise glEnable(GL_NORMALIZE) ### Instantiate the virtual world ### glutDisplayFunc(pyWorld.drawScene) glutMotionFunc(pyWorld.activeMouse) glutMouseFunc(pyWorld.completeMouse) glutReshapeFunc(pyWorld.resizeScene) glutIdleFunc(pyWorld.drawIdleScene)