def on_key_press(self, symbol, modifiers): global image_no if symbol in self.bestiary: item = self.bestiary[symbol] if item in self.world: self.world.remove(self.bestiary[symbol]) else: self.world.add(item) elif symbol in (key.PAGEUP, key.PAGEDOWN): zoom = ZOOM_SPEED if symbol == key.PAGEDOWN: zoom = 1 / ZOOM_SPEED if modifiers & key.MOD_SHIFT: self.world.camera.move.desired_variance *= zoom else: self.world.camera.move.desired_mean *= zoom elif symbol == key.BACKSPACE: itemid = max(i for i in self.world.items.keys()) self.world.items.pop(itemid) elif symbol == key.F12: image.get_buffer_manager().get_color_buffer().save( 'screenshot%02d.png' % (image_no, )) image_no += 1
def on_draw(): global screennum scene.setup() spin = Vector([sin(rx) * cos(ry), sin(rx) * sin(ry), cos(rx)]) _ellipsoid.axis = _ellipsoid.length * spin _ellipsoid.render(scene) # The sphere will look the same from all angles, so rotating it doesn't make sense _ball.render(scene) _pyramid.axis = _pyramid.length * spin _pyramid.render(scene) _box.axis = _box.length * spin _box.render(scene) _cylinder.axis = _cylinder.length * spin _cylinder.render(scene) _arrow.axis = _arrow.length * spin _arrow.render(scene) _cone.axis = _cone.length * spin _cone.render(scene) _ring.axis = spin _ring.render(scene) if screennum < 99: path = os.path.dirname(__file__) filename = os.path.join(path, 'screenshot%02d.png' % (screennum, )) get_buffer_manager().get_color_buffer().save(filename) screennum += 1
def screenshot(): ''' save a screenshot to the current directory, named 'screenshotXX.png', where XX is successive integers. ''' number = _get_next() image.get_buffer_manager().get_color_buffer().save(_get_filename(number)) return _get_filename(number)
def _take_screenshot(self): """ Take a screenshot to allow visual verification. """ screenshot_name = self._get_next_screenshot_name() screenshot_file_name = self._get_screenshot_session_file_name(screenshot_name) get_buffer_manager().get_color_buffer().get_image_data().save(screenshot_file_name) self._screenshots.append(screenshot_name)
def on_draw(): global angle global frame_num glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() glTranslatef(0.0, 0.0, -6.0) glRotatef(angle, 1, 1, 0) # Draw Cube (multiple quads) glBegin(GL_QUADS) glColor3f(1.0, 0.0, 0.0) glVertex3f(1.0, 1.0, -1.0) glVertex3f(-1.0, 1.0, -1.0) glVertex3f(-1.0, 1.0, 1.0) glVertex3f(1.0, 1.0, 1.0) glColor3f(1.0, 0.0, 0.0) glVertex3f(1.0, -1.0, 1.0) glVertex3f(-1.0, -1.0, 1.0) glVertex3f(-1.0, -1.0, -1.0) glVertex3f(1.0, -1.0, -1.0) glColor3f(1.0, 0.0, 0.0) glVertex3f(1.0, 1.0, 1.0) glVertex3f(-1.0, 1.0, 1.0) glVertex3f(-1.0, -1.0, 1.0) glVertex3f(1.0, -1.0, 1.0) glColor3f(1.0, 0.0, 0.0) glVertex3f(1.0, -1.0, -1.0) glVertex3f(-1.0, -1.0, -1.0) glVertex3f(-1.0, 1.0, -1.0) glVertex3f(1.0, 1.0, -1.0) glColor3f(1.0, 0.0, 0.0) glVertex3f(-1.0, 1.0, 1.0) glVertex3f(-1.0, 1.0, -1.0) glVertex3f(-1.0, -1.0, -1.0) glVertex3f(-1.0, -1.0, 1.0) glColor3f(1.0, 0.0, 0.0) glVertex3f(1.0, 1.0, -1.0) glVertex3f(1.0, 1.0, 1.0) glVertex3f(1.0, -1.0, 1.0) glVertex3f(1.0, -1.0, -1.0) glEnd() if angle < 180: filename = "b%03d.png" % frame_num image.get_buffer_manager().get_color_buffer().save(filename) frame_num += 1
def _take_screenshot(self, window=None): """ Take a screenshot to allow visual verification. """ screenshot_name = self._get_next_screenshot_name() screenshot_file_name = self._get_screenshot_session_file_name(screenshot_name) if window is not None: window.switch_to() get_buffer_manager().get_color_buffer().get_image_data().save(screenshot_file_name) self.screenshots.append(screenshot_name) self._schedule_commit() return screenshot_name
def capture_regression_image(self): if not self._enable_regression_image: return False self._captured_image = \ get_buffer_manager().get_color_buffer().get_image_data() return not self._enable_interactive
def check(self, img, colors): glClear(GL_COLOR_BUFFER_BIT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) img.blit(img.anchor_x, img.anchor_y) buffer = image.get_buffer_manager().get_color_buffer().get_image_data() bytes = buffer.get_data('RGBA', buffer.width * 4) def sample(x, y): i = y * buffer.pitch + x * len(buffer.format) r, g, b, _ = bytes[i:i + len(buffer.format)] if type(r) is str: r, g, b = map(ord, (r, g, b)) return { (255, 0, 0): 'r', (0, 255, 0): 'g', (0, 0, 255): 'b', (255, 0, 255): 'm' }.get((r, g, b), 'x') samples = ''.join( [sample(3, 3), sample(3, 0), sample(0, 0), sample(0, 3)]) self.assertTrue(samples == colors, samples)
def capture_regression_image(self): if not self._enable_regression_image: return False self._captured_image = \ get_buffer_manager().get_color_buffer().image_data return not self._enable_interactive
def test_defect_pyglet_get_color_buffer_for_resized_windows(self): self.window.set_size(111, 222) self.window.dispatch_events() mgr = get_buffer_manager() col_buf = mgr.get_color_buffer() col_buf_size = col_buf.width, col_buf.height self.assertEquals(col_buf_size, (111, 222), "pyglet bug regression")
def load_texture(self): print('Drawing scene...') self.window.set_visible() self.window.dispatch_events() self.draw() print('Copying colour image...') self.saved_texture = \ image.get_buffer_manager().get_color_buffer().texture print('Done.') self.window.set_visible(False)
def test_resource_image_loading(event_loop, transforms, result): """Test loading an image resource with possible transformations.""" resource.path.append('@' + __name__) resource.reindex() img = resource.image('rgbm.png', **transforms) w = event_loop.create_window(width=10, height=10) @w.event def on_draw(): # XXX For some reason original on_draw is not called w.clear() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) img.blit(img.anchor_x, img.anchor_y) event_loop.interrupt_event_loop() # Need to force multiple draws for platforms that do not support immediate drawing event_loop.run_event_loop() w._legacy_invalid = True event_loop.run_event_loop() w._legacy_invalid = True event_loop.run_event_loop() image_data = image.get_buffer_manager().get_color_buffer().get_image_data() pixels = image_data.get_data('RGBA', image_data.width * 4) def sample(x, y): i = y * image_data.pitch + x * len(image_data.format) r, g, b, _ = pixels[i:i + len(image_data.format)] if type(r) is str: r, g, b = list(map(ord, (r, g, b))) return { (255, 0, 0): 'r', (0, 255, 0): 'g', (0, 0, 255): 'b', (255, 0, 255): 'm' }.get((r, g, b), 'x') samples = ''.join([sample(3, 3), sample(3, 0), sample(0, 0), sample(0, 3)]) if samples == samples[2] * 4: # On retina displays the image buffer is twice the size of the coordinate system samples = ''.join( [sample(6, 6), sample(6, 0), sample(0, 0), sample(0, 6)]) assert samples == result
def on_key_press(self, symbol, modifiers): global image_no if symbol in self.bestiary: item = self.bestiary[symbol] if item in self.world: self.world.remove(self.bestiary[symbol]) else: self.world.add(item) elif symbol in (key.PAGEUP, key.PAGEDOWN): zoom = ZOOM_SPEED if symbol == key.PAGEDOWN: zoom = 1 / ZOOM_SPEED if modifiers & key.MOD_SHIFT: self.world.camera.move.desired_variance *= zoom else: self.world.camera.move.desired_mean *= zoom elif symbol == key.BACKSPACE: itemid = max(i for i in self.world.items.keys()) self.world.items.pop(itemid) elif symbol == key.SPACE: itemid = max(i for i in self.world.items.keys()) item = self.world.items[itemid] if hasattr(item, "old_move"): item.move = item.old_move del item.old_move else: item.old_move = getattr(item, "move", None) item.move = WobblyOrbit(4, 3) elif symbol == key.F12: image.get_buffer_manager().get_color_buffer().save("screenshot%02d.png" % (image_no,)) image_no += 1
def multi_draw(*args, **kwargs): gl.glEnable(gl.GL_BLEND) gl.glBlendFunc(gl.GL_ONE, gl.GL_ONE) gl.glEnable(gl.GL_LINE_SMOOTH) gl.glEnable(gl.GL_POINT_SMOOTH) gl.glClearColor(0, 0, 0, 0) gl.glColor4f(1, 1, 1, 1) gl.glClear(gl.GL_COLOR_BUFFER_BIT) if not buffers: buffers.append(image.get_buffer_manager()) x, y, w, h = buffers[0].get_viewport() #Draw lowres version gl.glViewport(0, 0, 256, 256) func(*args, **kwargs) texes.append(buffers[0].get_color_buffer().texture) if len(texes) > num_texes: texes.pop(0) #Lay down copies of lowres version gl.glViewport(x, y, w, h) gl.glClear(gl.GL_COLOR_BUFFER_BIT) if texes: alphas = range(1, len(texes) + 1) alphas = [float(f) / sum(alphas) for f in alphas] for tex, alpha in zip(texes, alphas): gl.glBindTexture(tex.target, tex.id) gl.glEnable(gl.GL_TEXTURE_2D) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glColor4f(1, 1, 1, alpha) gl.glBegin(gl.GL_QUADS) gl.glTexCoord2f(0, 0) gl.glVertex3f(0, 0, -.5) gl.glTexCoord2f(1, 0) gl.glVertex3f(w, 0, -.5) gl.glTexCoord2f(1, 1) gl.glVertex3f(w, h, -.5) gl.glTexCoord2f(0, 1) gl.glVertex3f(0, h, -.5) gl.glEnd() gl.glDisable(gl.GL_TEXTURE_2D) #Draw real thing gl.glColor4f(1, 1, 1, 1) func(*args, **kwargs)
def multi_draw(*args, **kwargs): gl.glEnable(gl.GL_BLEND) gl.glBlendFunc(gl.GL_ONE, gl.GL_ONE) gl.glEnable(gl.GL_LINE_SMOOTH) gl.glEnable(gl.GL_POINT_SMOOTH) gl.glClearColor(0, 0, 0, 0) gl.glColor4f(1, 1, 1, 1) gl.glClear(gl.GL_COLOR_BUFFER_BIT) if not buffers: buffers.append(image.get_buffer_manager()) x, y, w, h = buffers[0].get_viewport() #Draw lowres version gl.glViewport(0, 0, 256, 256) func(*args, **kwargs) ctex[0] = buffers[0].get_color_buffer().texture #Lay down copies of lowres version gl.glViewport(x, y, w, h) gl.glClear(gl.GL_COLOR_BUFFER_BIT) gl.glBindTexture(ctex[0].target, ctex[0].id) gl.glEnable(gl.GL_TEXTURE_2D) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) if not disp_list: disp_list.append(gl.glGenLists(1)) gl.glNewList(disp_list[0], gl.GL_COMPILE) for u in range(-3, 4, 3): for v in range(-3, 4, 3): gl.glColor4f(1, 1, 1, (20.0 - u**2 - v**2) / 72) gl.glBegin(gl.GL_QUADS) gl.glTexCoord2f(0, 0) gl.glVertex3f(u, v, -.5) gl.glTexCoord2f(1, 0) gl.glVertex3f(u + w, v, -.5) gl.glTexCoord2f(1, 1) gl.glVertex3f(u + w, v + h, -.5) gl.glTexCoord2f(0, 1) gl.glVertex3f(u, v + h, -.5) gl.glEnd() gl.glEndList() gl.glCallList(disp_list[0]) gl.glDisable(gl.GL_TEXTURE_2D) #Draw real thing gl.glColor4f(1, 1, 1, 1) func(*args, **kwargs)
def after_render (self, texture): buffer = image.get_buffer_manager().get_color_buffer() texture.blit_into(buffer, 0, 0, 0) director.window.clear() return self.before.blit(0,0) glEnable(self.before.texture.target) glBindTexture(self.before.texture.target, self.before.texture.id) glPushAttrib(GL_COLOR_BUFFER_BIT) self.vertex_list.draw(pyglet.gl.GL_QUADS) glPopAttrib() glDisable(self.before.texture.target)
def after_render(self, texture): buffer = image.get_buffer_manager().get_color_buffer() texture.blit_into(buffer, 0, 0, 0) director.window.clear() return self.before.blit(0, 0) glEnable(self.before.texture.target) glBindTexture(self.before.texture.target, self.before.texture.id) glPushAttrib(GL_COLOR_BUFFER_BIT) self.vertex_list.draw(pyglet.gl.GL_QUADS) glPopAttrib() glDisable(self.before.texture.target)
def load_texture(self): print "Drawing scene..." self.window.set_visible() self.window.dispatch_events() self.draw() print "Saving colour image..." img = image.get_buffer_manager().get_color_buffer() file = StringIO() img.save("buffer.png", file) print "Loading colour image as texture..." file.seek(0) self.saved_texture = image.load("buffer.png", file) print "Done." self.window.set_visible(False)
def load_texture(self): print('Drawing scene...') self.window.set_visible() self.window.dispatch_events() self.draw() print('Saving depth image...') img = image.get_buffer_manager().get_depth_buffer() file = BytesIO() img.save('buffer.png', file) print('Loading depth image as texture...') file.seek(0) self.saved_texture = image.load('buffer.png', file) print('Done.') self.window.set_visible(False)
def load_texture(self): print 'Drawing scene...' self.window.set_visible() self.window.dispatch_events() self.draw() print 'Saving colour image...' img = image.get_buffer_manager().get_color_buffer() file = StringIO() img.save('buffer.png', file) print 'Loading colour image as texture...' file.seek(0) self.saved_texture = image.load('buffer.png', file) print 'Done.' self.window.set_visible(False)
def test_save(self): self.window = w = self.create_window() w.push_handlers(self) self.screen = image.get_buffer_manager().get_color_buffer() self.checkerboard = image.create(32, 32, image.CheckerImagePattern()) self.load_texture() if self.alpha: glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) w.set_visible() while not (w.has_exit or self.has_exit): w.dispatch_events() w.close()
def check(self, img, colors): glClear(GL_COLOR_BUFFER_BIT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) img.blit(img.anchor_x, img.anchor_y) buffer = image.get_buffer_manager().get_color_buffer().get_image_data() bytes = buffer.get_data("RGBA", buffer.width * 4) def sample(x, y): i = y * buffer.pitch + x * len(buffer.format) r, g, b, _ = bytes[i : i + len(buffer.format)] if type(r) is str: r, g, b = map(ord, (r, g, b)) return {(255, 0, 0): "r", (0, 255, 0): "g", (0, 0, 255): "b", (255, 0, 255): "m"}.get((r, g, b), "x") samples = "".join([sample(3, 3), sample(3, 0), sample(0, 0), sample(0, 3)]) self.assertTrue(samples == colors, samples)
def test_load(self): width, height = 800, 600 self.window = w = Window(width, height, visible=False) w.push_handlers(self) self.screen = image.get_buffer_manager().get_color_buffer() self.checkerboard = image.create(32, 32, image.CheckerImagePattern()) self.load_image() if self.image: self.texture = self.image.texture if self.alpha: glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) w.set_visible() while not (w.has_exit or self.has_exit): w.dispatch_events() w.close()
def end(self): buffer = image.get_buffer_manager().get_color_buffer() self.texture.blit_into(buffer, 0, 0, 0) glViewport(0, 0, self.window.width, self.window.height) self.set_window_projection() aspect_width = self.window.width / float(self.width) aspect_height = self.window.height / float(self.height) if aspect_width > aspect_height: scale_width = aspect_height * self.width scale_height = aspect_height * self.height else: scale_width = aspect_width * self.width scale_height = aspect_width * self.height x = (self.window.width - scale_width) / 2 y = (self.window.height - scale_height) / 2 glClearColor(0, 0, 0, 1) glClear(GL_COLOR_BUFFER_BIT) glLoadIdentity() glColor3f(1, 1, 1) self.texture.blit(x, y, width=scale_width, height=scale_height)
def renderToTexture(w, h, function): import ctypes from pyglet import gl from pyglet import image from pyglet.gl import gl_info global has_fbo if has_fbo is None: has_fbo = gl_info.have_extension('GL_EXT_framebuffer_object') # enforce dimensions are ints w, h = int(w), int(h) # set up viewport gl.glPushAttrib(gl.GL_VIEWPORT_BIT | gl.GL_TRANSFORM_BIT) gl.glViewport(0, 0, w, h) gl.glMatrixMode(gl.GL_PROJECTION) gl.glPushMatrix() gl.glLoadIdentity() gl.glOrtho(0, w, 0, h, -1, 1) gl.glMatrixMode(gl.GL_MODELVIEW) if has_fbo: # render directly to texture # create our frame buffer fbo = gl.GLuint() gl.glGenFramebuffersEXT(1, ctypes.byref(fbo)) gl.glBindFramebufferEXT(gl.GL_FRAMEBUFFER_EXT, fbo) # allocate a texture and add to the frame buffer tex = image.Texture.create_for_size(gl.GL_TEXTURE_2D, w, h, gl.GL_RGBA) gl.glBindTexture(gl.GL_TEXTURE_2D, tex.id) gl.glFramebufferTexture2DEXT(gl.GL_FRAMEBUFFER_EXT, gl.GL_COLOR_ATTACHMENT0_EXT, gl.GL_TEXTURE_2D, tex.id, 0) status = gl.glCheckFramebufferStatusEXT(gl.GL_FRAMEBUFFER_EXT) assert status == gl.GL_FRAMEBUFFER_COMPLETE_EXT # now render gl.glBindFramebufferEXT(gl.GL_FRAMEBUFFER_EXT, fbo) function() gl.glBindFramebufferEXT(gl.GL_FRAMEBUFFER_EXT, 0) # clean up gl.glDeleteFramebuffersEXT(1, ctypes.byref(fbo)) else: # render and copy to texture # render function() # grab the buffer and copy contents to the texture buffer = image.get_buffer_manager().get_color_buffer() tex = image.Texture.create_for_size(gl.GL_TEXTURE_2D, w, h, gl.GL_RGBA) tex.blit_into(buffer.get_region(0, 0, w, h), 0, 0, 0) gl.glMatrixMode(gl.GL_PROJECTION) gl.glPopMatrix() gl.glPopAttrib() # return the region (the whole texture will most likely be larger) return tex.get_region(0, 0, w, h)
def save_screenshot(window): filename = _get_filename("screenshot-", ".png") if filename: image = get_buffer_manager().get_color_buffer() image.save(filename)
def after_render(self, texture): buffer = image.get_buffer_manager().get_color_buffer() texture.blit_into(buffer, 0, 0, 0) director.window.switch_to()
def save_and_load_depth_buffer(self): stream = BytesIO() image.get_buffer_manager().get_depth_buffer().save( 'buffer.png', stream) stream.seek(0) self.right_texture = image.load('buffer.png', stream)
def copy_color_buffer(self): self.right_texture = \ image.get_buffer_manager().get_color_buffer().texture
def renderToTexture(w, h, function): import ctypes from pyglet import gl from pyglet import image from pyglet.gl import gl_info global has_fbo if has_fbo is None: has_fbo = gl_info.have_extension("GL_EXT_framebuffer_object") # enforce dimensions are ints w, h = int(w), int(h) # set up viewport gl.glPushAttrib(gl.GL_VIEWPORT_BIT | gl.GL_TRANSFORM_BIT) gl.glViewport(0, 0, w, h) gl.glMatrixMode(gl.GL_PROJECTION) gl.glPushMatrix() gl.glLoadIdentity() gl.glOrtho(0, w, 0, h, -1, 1) gl.glMatrixMode(gl.GL_MODELVIEW) if has_fbo: # render directly to texture # create our frame buffer fbo = gl.GLuint() gl.glGenFramebuffersEXT(1, ctypes.byref(fbo)) gl.glBindFramebufferEXT(gl.GL_FRAMEBUFFER_EXT, fbo) # allocate a texture and add to the frame buffer tex = image.Texture.create_for_size(gl.GL_TEXTURE_2D, w, h, gl.GL_RGBA) gl.glBindTexture(gl.GL_TEXTURE_2D, tex.id) gl.glFramebufferTexture2DEXT(gl.GL_FRAMEBUFFER_EXT, gl.GL_COLOR_ATTACHMENT0_EXT, gl.GL_TEXTURE_2D, tex.id, 0) status = gl.glCheckFramebufferStatusEXT(gl.GL_FRAMEBUFFER_EXT) assert status == gl.GL_FRAMEBUFFER_COMPLETE_EXT # now render gl.glBindFramebufferEXT(gl.GL_FRAMEBUFFER_EXT, fbo) function() gl.glBindFramebufferEXT(gl.GL_FRAMEBUFFER_EXT, 0) # clean up gl.glDeleteFramebuffersEXT(1, ctypes.byref(fbo)) else: # render and copy to texture # render function() # grab the buffer and copy contents to the texture buffer = image.get_buffer_manager().get_color_buffer() tex = image.Texture.create_for_size(gl.GL_TEXTURE_2D, w, h, gl.GL_RGBA) tex.blit_into(buffer.get_region(0, 0, w, h), 0, 0, 0) gl.glMatrixMode(gl.GL_PROJECTION) gl.glPopMatrix() gl.glPopAttrib() # return the region (the whole texture will most likely be larger) return tex.get_region(0, 0, w, h)
def after_render (self, texture): buffer = image.get_buffer_manager().get_color_buffer() texture.blit_into(buffer, 0, 0, 0)
def after_render (self, texture): buffer = image.get_buffer_manager().get_color_buffer() texture.blit_into (buffer, 0, 0, 0) director.window.switch_to()
def save_screenshot(self, filename): from pyglet.image import get_buffer_manager get_buffer_manager().get_color_buffer().save(filename)
def screenshot(self, name='shots/snapshot.png'): get_buffer_manager().get_color_buffer().save(name)
self.mouse_pressed = True win = my_win( fullscreen=True ) #make a fullscreen window (happily, highest native resolution is captured by default and double buffering is a default behavior) win.x_center = win.width / 2 #store the location of the horizontal center for later reference win.y_center = win.height / 2 #store the location of the vertical center for later reference win.set_exclusive_mouse() #ensures the mouse is invisible glClearColor(0, 0, 0, 0) #set the 'cleared' background to white cursor = win.get_system_mouse_cursor(win.CURSOR_CROSSHAIR) win.set_exclusive_mouse(True) win.set_mouse_cursor(cursor) win.dispatch_events() #always do a dispatch soon after creating a new window image.get_buffer_manager().get_color_buffer( ).get_image_data #necessary (for some reason) to ensure openGL drawing coordinates are in pixels with (0,0) in lower left corner # Perform some calculations to convert stimulus measurements in degrees to pixels screen_width_in_degrees = math.degrees( math.atan((screen_width / 2.0) / viewing_distance) * 2) PPD = win.width / screen_width_in_degrees target_size = target_size_in_degrees * PPD box_offset = box_offset_in_degrees * PPD box_size = box_size_in_degrees * PPD wheel_size = box_size * 5 target_size = target_size_in_degrees * PPD text_width = text_proportion * win.width glLineWidth(target_size * target_thickness_proportion) color_wheel_inner_rim = math.sqrt(((wheel_size / 2.0)**2) + ((wheel_size / 2.0)**2))