def display(self): """ Callback function, handler for window re-paint """ # Set background color (clear background) glClearColor( self.background_color[0], self.background_color[1], self.background_color[2], 1.0, ) glClear(GL_COLOR_BUFFER_BIT) # Display background for shape in self.background.shapes: self.draw_geometric2d(shape) # Display objects if len(self.data) > 0: idx = self.time_count % len(self.data) for shape in self.data[idx].shapes: self.draw_geometric2d(shape) self.time_count += 1 glFlush()
def leftDrag(self, event): """ Compute the changing rubber band window ending point. Erase the previous window, draw the new window. """ # bugs 1190, 1818 wware 4/05/2006 - sometimes Qt neglects to call leftDown # before this if not hasattr(self, "pWxy") or not hasattr(self, "firstDraw"): return cWxy = (event.pos().x(), self.glpane.height - event.pos().y()) rbwcolor = self.command.rbwcolor if not self.firstDraw: #Erase the previous rubberband window drawrectangle(self.pStart, self.pPrev, self.glpane.up, self.glpane.right, rbwcolor) self.firstDraw = False self.pPrev = A(gluUnProject(cWxy[0], cWxy[1], 0.005)) # draw the new rubberband window drawrectangle(self.pStart, self.pPrev, self.glpane.up, self.glpane.right, rbwcolor) glFlush() self.glpane.swapBuffers() # Update display # Based on a suggestion in bug 2961, I added this second call to # swapBuffers(). It definitely helps, but the rectangle disappears # once the zoom cursor stops moving. I suspect this is due to # a gl_update() elsewhere. I'll ask Bruce about his thoughts on # this. --Mark 2008-12-22. self.glpane.swapBuffers() return
def leftDrag(self, event): """ Compute the changing rubber band window ending point. Erase the previous window, draw the new window. """ # bugs 1190, 1818 wware 4/05/2006 - sometimes Qt neglects to call leftDown # before this if not hasattr(self, "pWxy") or not hasattr(self, "firstDraw"): return cWxy = (event.pos().x(), self.glpane.height - event.pos().y()) rbwcolor = self.command.rbwcolor if not self.firstDraw: #Erase the previous rubber window drawrectangle(self.pStart, self.pPrev, self.glpane.up, self.glpane.right, rbwcolor) self.firstDraw = False self.pPrev = A(gluUnProject(cWxy[0], cWxy[1], 0.005)) # draw the new rubber band drawrectangle(self.pStart, self.pPrev, self.glpane.up, self.glpane.right, rbwcolor) glFlush() self.glpane.swapBuffers() # Update display return
def render(self): """ The render pass for the scene """ self.init_view() # Enable lighting and color glEnable(GL_LIGHTING) glClearColor(0.4, 0.4, 0.4, 0.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Load the modelview matrix from the current state of the trackball glMatrixMode(GL_MODELVIEW) glPushMatrix() glLoadIdentity() loc = self.interaction.translation glTranslated(-loc[0], -loc[1], -loc[2]) glMultMatrixf(self.interaction.trackball.matrix) # store the inverse of the current modelview. currentModelView = numpy.array(glGetFloatv(GL_MODELVIEW_MATRIX)) self.modelView = numpy.transpose(currentModelView) self.inverseModelView = inv(numpy.transpose(currentModelView)) # render the scene. This will call the render function for each object in the scene self.scene.render() # draw the grid glDisable(GL_LIGHTING) glCallList(G_OBJ_PLANE) glPopMatrix() # flush the buffers so that the scene can be drawn glFlush()
def draw(self): t1 = time.time() glClearColor(0.0, 0.0, 0.0, 0.0) glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) glLoadIdentity() horizonY = 1 * 2.2 - .6 + .5 GLU.gluLookAt(self.eyeX.x, horizonY, 8.0, self.lookX.x, horizonY, 0.0, 0.0, 1.0, 0.0) glEnable(GL.GL_TEXTURE_2D) if 0: with pushMatrix(): glColor3f(1, 0, 0) glTranslatef(*self.ball) glScalef(.2, .2, 1) imageCard("sample.jpg") with pushMatrix(): with mode(disable=[GL.GL_LIGHTING]): for card in self.cards: card.draw(self.eyeX.x, horizonY, self.cardList) glFlush() pygame.display.flip()
def render(self): #初始化投影矩阵 self.init_view() #启动光照 glEnable(GL_LIGHTING) #清空颜色缓存与深度缓存 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) #设置模型视图矩阵,这节课先用单位矩阵就行了。 glMatrixMode(GL_MODELVIEW) glPushMatrix() glLoadIdentity() glMultMatrixf(self.interaction.trackball.matrix) # 存储ModelView矩阵与其逆矩阵之后做坐标系转换用 currentModelView = numpy.array(glGetFloatv(GL_MODELVIEW_MATRIX)) self.modelView = numpy.transpose(currentModelView) self.inverseModelView = inv(numpy.transpose(currentModelView)) #渲染场景 self.scene.render() #每次渲染后复位光照状态 glDisable(GL_LIGHTING) glCallList(G_OBJ_PLANE) glPopMatrix() #把数据刷新到显存上 glFlush()
def render(self): #init shadow matrix self.init_view() #open light glEnable(GL_LIGHTING) #clear color and depth caches glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) #set model view matrix(danwei matrix is ok) #set trackball's rotate matrix as Modelview glMatrixMode(GL_MODELVIEW) glPushMatrix() #replace now-matrix with hengdeng matrix glLoadIdentity() glMultMatrixf(self.interaction.trackball.matrix) #save Modelview matrix, later change system with anti-matrix currentModelView = numpy.array(glGetFloatv(GL_MODELVIEW_MATRIX)) self.modelView = numpy.transpose(currentModelView) self.inverseModelView = inv(numpy.transpose(currentModelView)) #rend the scene self.scene.render() #after each shadow , huifu light state glDisable(GL_LIGHTING) glPopMatrix() glFlush()
def _capture_saved_bg_image(self): """ """ # TODO: investigate better ways to do this, which don't involve the CPU. # For example, frame buffer objects, or "render to texture": # - by glCopyTexImage2D, # http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=36 # (which can do color -- I don't know about depth), # - or by more platform-specific ways, e.g. pbuffer. # [bruce 081002] print "_capture_saved_bg_image", self._print_data() sys.stdout.flush() if 1: from OpenGL.GL import glFlush, glFinish glFlush( ) # might well be needed, based on other code in NE1; not enough by itself glFinish() # try this too if needed w = _trim(self.width) h = _trim(self.height) # grab the color image part image = glReadPixels(0, 0, w, h, _GL_FORMAT_FOR_COLOR, GL_UNSIGNED_BYTE) self._cached_bg_color_image = image # grab the depth part ## image = glReadPixels( 0, 0, w, h, GL_DEPTH_COMPONENT, _GL_TYPE_FOR_DEPTH ) image = glReadPixelsf(0, 0, w, h, GL_DEPTH_COMPONENT) ##### self._cached_bg_depth_image = image print "grabbed depth at 0,0:", image[0][0] ###### return
def draw(self): t1 = time.time() glClearColor(0.0, 0.0, 0.0, 0.0) glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) glLoadIdentity () horizonY = 1 * 2.2 - .6 + .5 GLU.gluLookAt(self.eyeX.x, horizonY, 8.0, self.lookX.x, horizonY, 0.0, 0.0, 1.0, 0.0) glEnable(GL.GL_TEXTURE_2D) if 0: with pushMatrix(): glColor3f(1,0,0) glTranslatef(*self.ball) glScalef(.2, .2, 1) imageCard("sample.jpg") with pushMatrix(): with mode(disable=[GL.GL_LIGHTING]): for card in self.cards: card.draw(self.eyeX.x, horizonY, self.cardList) glFlush() pygame.display.flip()
def _capture_saved_bg_image(self): """ """ # TODO: investigate better ways to do this, which don't involve the CPU. # For example, frame buffer objects, or "render to texture": # - by glCopyTexImage2D, # http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=36 # (which can do color -- I don't know about depth), # - or by more platform-specific ways, e.g. pbuffer. # [bruce 081002] print "_capture_saved_bg_image", self._print_data() sys.stdout.flush() if 1: from OpenGL.GL import glFlush, glFinish glFlush() # might well be needed, based on other code in NE1; not enough by itself glFinish() # try this too if needed w = _trim(self.width) h = _trim(self.height) # grab the color image part image = glReadPixels( 0, 0, w, h, _GL_FORMAT_FOR_COLOR, GL_UNSIGNED_BYTE ) self._cached_bg_color_image = image # grab the depth part ## image = glReadPixels( 0, 0, w, h, GL_DEPTH_COMPONENT, _GL_TYPE_FOR_DEPTH ) image = glReadPixelsf(0, 0, w, h, GL_DEPTH_COMPONENT) ##### self._cached_bg_depth_image = image print "grabbed depth at 0,0:", image[0][0]###### return
def render_figure(self): glClear(GL_COLOR_BUFFER_BIT) for figure in self.list_of_figures_to_draw: figure.draw_me() glFlush()
def render_scene(self): "render scene one time" self.init_gl() # should be a no-op after the first frame is rendered SDL_GL_MakeCurrent(self.window, self.context) self.renderer.render_scene() # Done rendering # SDL_GL_SwapWindow(self.window) glFlush()
def render_scene(self): "render scene one time" self.init_gl() # should be a no-op after the first frame is rendered SDL_GL_MakeCurrent ( self.window, self.context ) self.renderer.render_scene() # Done rendering # SDL_GL_SwapWindow(self.window) glFlush()
def on_expose_event(self, widget, _event=None): with GLContext(widget) as gldrawable: self.paint_blocks() if gldrawable.is_double_buffered(): gldrawable.swap_buffers() else: glFlush() return True
def draw(self) -> None: ''' each frame''' glClearColor(0.0, 0.0, 1.0, 0.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self.renderer.draw(self.scene, self.projection.matrix, self.view.matrix) glFlush()
def on_expose_event(self, widget, event): if not self.get_gl_drawable().gl_begin(self.get_gl_context()): return vb = context.application.vis_backend vb.draw(self.allocation.width, self.allocation.height) if self.get_gl_drawable().is_double_buffered(): self.get_gl_drawable().swap_buffers() else: glFlush() self.get_gl_drawable().gl_end()
def render_scene(self): "render scene one time" self.init_gl() # should be a no-op after the first frame is rendered glfw.make_context_current(self.window) self.renderer.render_scene() # Done rendering # glfw.swap_buffers(self.window) # avoid double buffering to avoid stalling glFlush() # single buffering glfw.poll_events()
def gl_show(self): if self.glconfig.is_double_buffered(): # Show the backbuffer on screen log("%s.gl_show() swapping buffers now", self) gldrawable = self.get_gl_drawable() gldrawable.swap_buffers() else: #just ensure stuff gets painted: log("%s.gl_show() flushing", self) glFlush()
def gl_show(self): start = time.time() if self.glconfig.is_double_buffered(): # Show the backbuffer on screen log("%s.gl_show() swapping buffers now", self) gldrawable = self.get_gl_drawable() gldrawable.swap_buffers() else: #just ensure stuff gets painted: log("%s.gl_show() flushing", self) glFlush() end = time.time() fpslog("gl_show took %ims", (end-start)*1000)
def display(self): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glPushMatrix() glTranslatef(0.0, 0.0, -1.0) glRotatef(self.rot_x, 1.0, 0.0, 0.0) glRotatef(self.rot_z, 0.0, 1.0, 0.0) self.render() glPopMatrix() glFlush() glutSwapBuffers()
def present_fbo(self, drawable): self.gl_marker("Presenting FBO on screen for drawable %s" % drawable) assert drawable # Change state to target screen instead of our FBO glBindFramebuffer(GL_FRAMEBUFFER, 0) if self._has_alpha: # transparent background: glClearColor(0.0, 0.0, 0.0, 0.0) else: # plain white no alpha: glClearColor(1.0, 1.0, 1.0, 1.0) # Draw FBO texture on screen self.set_rgb_paint_state() glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) if self._has_alpha: # support alpha channel if present: glEnable(GL_BLEND) glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD) glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO) w, h = self.size glBegin(GL_QUADS) glTexCoord2i(0, h) glVertex2i(0, 0) glTexCoord2i(0, 0) glVertex2i(0, h) glTexCoord2i(w, 0) glVertex2i(w, h) glTexCoord2i(w, h) glVertex2i(w, 0) glEnd() # Show the backbuffer on screen if drawable.is_double_buffered(): debug("%s.present_fbo() swapping buffers now", self) drawable.swap_buffers() # Clear the new backbuffer to illustrate that its contents are undefined glClear(GL_COLOR_BUFFER_BIT) else: glFlush() if self._has_alpha: glDisable(GL_BLEND) self.gl_frame_terminator() self.unset_rgb_paint_state() glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) debug("%s.present_fbo() done", self)
def update_texture_yuv(self, img_data, x, y, width, height, rowstrides, pixel_format): window_width, window_height = self.size assert self.textures is not None, "no OpenGL textures!" if self.pixel_format is None or self.pixel_format!=pixel_format: self.pixel_format = pixel_format divs = self.get_subsampling_divs(pixel_format) log("GL creating new YUV textures for pixel format %s using divs=%s", pixel_format, divs) # Create textures of the same size as the window's glEnable(GL_TEXTURE_RECTANGLE_ARB) for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): div = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glEnable(GL_TEXTURE_RECTANGLE_ARB) mag_filter = GL_NEAREST if div>1: mag_filter = GL_LINEAR glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, mag_filter) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, window_width/div, window_height/div, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0) log("Assigning fragment program") glEnable(GL_FRAGMENT_PROGRAM_ARB) if not self.yuv_shader: self.yuv_shader = [ 1 ] glGenProgramsARB(1, self.yuv_shader) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv_shader[0]) prog = GL_COLORSPACE_CONVERSIONS glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, len(prog), prog) err = glGetString(GL_PROGRAM_ERROR_STRING_ARB) if err: #FIXME: maybe we should do something else here? log.error(err) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv_shader[0]) # Clamp width and height to the actual texture size if x + width > window_width: width = window_width - x if y + height > window_height: height = window_height - y divs = self.get_subsampling_divs(pixel_format) for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): div = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[index]) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width/div, height/div, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[index]) glFlush()
def _ns_flush(self): glFlush() width, height = self.size pixels = glReadPixels(0, 0, int(width), int(height), GL_RGBA, GL_UNSIGNED_BYTE) bytes_per_row = int(width) * 4 ns_new_bitmap = NSBitmapImageRep.alloc().\ initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bytesPerRow_bitsPerPixel_( (pixels, "", "", "", ""), int(width), int(height), 8, 4, True, False, AppKit.NSDeviceRGBColorSpace, bytes_per_row, 0) ns_image = NSImage.alloc().initWithSize_(NSSize(width, height)) ns_image.addRepresentation_(ns_new_bitmap) ns_image.lockFocus() ns_image.unlockFocus() self._ns_image = ns_image self._ns_bitmap_image_rep = ns_new_bitmap
def on_draw(self, want_cameras=False): # sys.stderr.write('fps: %.2e\n' % (1. / (time.time() - self.tm_for_fps))) self.tm_for_fps = time.time() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) cameras = [] for mvl in self.mesh_viewers: cameras.append([]) for mv in mvl: cameras[-1].append(mv.on_draw(self.transform, want_cameras)) glFlush() # Flush The GL Rendering Pipeline glutSwapBuffers() self.need_redraw = False if want_cameras: return cameras
def render_image(self, rx, ry, rw, rh): log("render_image %sx%s at %sx%s pixel_format=%s", rw, rh, rx, ry, self.pixel_format) if self.pixel_format not in (YUV420P, YUV422P, YUV444P): #not ready to render yet return divs = self.get_subsampling_divs(self.pixel_format) glEnable(GL_FRAGMENT_PROGRAM_ARB) glBegin(GL_QUADS) for x,y in ((rx, ry), (rx, ry+rh), (rx+rw, ry+rh), (rx+rw, ry)): for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): div = divs[index] glMultiTexCoord2i(texture, x/div, y/div) glVertex2i(x, y) glEnd() glFlush()
def plot(): glClear(GL_COLOR_BUFFER_BIT) glPointSize(3.0) glColor3f(1.0, 0.0, 0.0) glBegin(GL_POINTS) x_lst, y_lst = circle(0, 0, 1, 100) for x, y in zip(x_lst, y_lst): glVertex2f(x, y) glEnd() glFlush()
def on_render(self, area, *args): area.attach_buffers() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glUseProgram(self.shaderContent.shader_prog) self.timer() glUniform1f(self.time_l, self.time) glBindVertexArray(self.vertex_array_object) glDrawArrays(GL_TRIANGLES, 0, 6) glBindVertexArray(0) glUseProgram(0) glFlush() self.shaderContent.queue_render() return True
def gl_show(self, rect_count): start = time.time() if self.glconfig.is_double_buffered(): # Show the backbuffer on screen log("%s.gl_show() swapping buffers now", self) gldrawable = self.get_gl_drawable() gldrawable.swap_buffers() else: #just ensure stuff gets painted: log("%s.gl_show() flushing", self) glFlush() end = time.time() flush_elapsed = end-self.last_flush self.last_flush = end fpslog("gl_show after %3ims took %2ims, %2i updates", flush_elapsed*1000, (end-start)*1000, rect_count)
def _with_context(self, proc, flush): drawable = self._gl_drawable if drawable: if not drawable.gl_begin(self._gl_context): raise ValueError( "Unable to make %s the current OpenGL context (gl_begin failed)" % self) try: self._with_share_group(proc) if flush: if drawable.is_double_buffered(): #print "GLContext.with_context: swapping buffers" ### drawable.swap_buffers() else: #print "GLContext.with_context: flushing" ### glFlush() finally: drawable.gl_end()
def paintGL(self): """ Drawing routing """ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() #Draw spiral in 'immediate mode' #WARNING: You should not be doing the spiral calculation inside the loop #even if you are using glBegin/glEnd, sin/cos are fairly expensive functions #For now left here to make code simpler radius = 1.0 x = radius * math.sin(0) y = radius * math.cos(0) glColor(0.0, 1.0, 0.0) glBegin(GL_LINE_STRIP) for deg in range(1000): glVertex(x, y, 0.0) rad = math.radians(deg) radius -= 0.001 x = radius * math.sin(rad) y = radius * math.cos(rad) glEnd() glEnableClientState(GL_VERTEX_ARRAY) #TODO: Use list comprehension spiral_array = [] #Second spiral using "array immediate mode" (i.e vertex arrays) radius = 0.8 x = radius * math.sin(0) y = radius * math.cos(0) glColor(1.0, 0.0, 0.0) for deg in range(820): spiral_array.append([x, y]) rad = math.radians(deg) radius -= 0.001 x = radius * math.sin(rad) y = radius * math.cos(rad) glVertexPointerf(spiral_array) glDrawArrays(GL_LINE_STRIP, 0, len(spiral_array)) glFlush()
def render(self): # 每次循环调用的渲染函数 self.init_view() # 初始化投影矩阵 glEnable(GL_LIGHTING) # 启动光照 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # 清空颜色缓存和深度缓存 # 设置模型视图矩阵,此处使用单位矩阵 glMatrixMode(GL_MODELVIEW) glPushMatrix() glLoadIdentity() # 渲染场景 self.scene.render() # 每次渲染后恢复光照状态 glDisable(GL_LIGHTING) glPopMatrix() # 把数据刷新到显存上 glFlush()
def render_image(self, rx, ry, rw, rh): log("render_image %sx%s at %sx%s pixel_format=%s", rw, rh, rx, ry, self.pixel_format) if self.pixel_format not in (YUV420P, YUV422P, YUV444P): #not ready to render yet return divs = self.get_subsampling_divs(self.pixel_format) glEnable(GL_FRAGMENT_PROGRAM_ARB) glBegin(GL_QUADS) for x, y in ((rx, ry), (rx, ry + rh), (rx + rw, ry + rh), (rx + rw, ry)): for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): div = divs[index] glMultiTexCoord2i(texture, x / div, y / div) glVertex2i(x, y) glEnd() glFlush()
def execute(self): if self.PreExecute: self.PreExecute() if self.gl_objects: cl.enqueue_acquire_gl_objects(self.queue, self.gl_objects) #self.program.part2(self.queue, self.pos.shape, None, # *(self.kernelargs)) if self.gl_objects: cl.enqueue_release_gl_objects(self.queue, self.gl_objects) self.queue.finish() glFlush() if self.PostExecute: self.PostExecute()
def blit_buffer(self, buffer, size=None, mode='RGB', format=None, pos=(0, 0), buffertype=GL_UNSIGNED_BYTE): '''Blit a buffer into a texture. :Parameters: `buffer` : str Image data `size` : tuple, default to texture size Size of the image (width, height) `mode` : str, default to 'RGB' Image mode, can be one of RGB, RGBA, BGR, BGRA `format` : glconst, default to None if format is passed, it will be used instead of mode `pos` : tuple, default to (0, 0) Position to blit in the texture `buffertype` : glglconst, default to GL_UNSIGNED_BYTE Type of the data buffer ''' if size is None: size = self.size if format is None: format = self.mode_to_gl_format(mode) target = self.target glBindTexture(target, self.id) glEnable(target) # activate 1 alignement, of window failed on updating weird size glPixelStorei(GL_UNPACK_ALIGNMENT, 1) # need conversion ? pdata, format = self._convert_buffer(buffer, format) # transfer the new part of texture glTexSubImage2D(target, 0, pos[0], pos[1], size[0], size[1], format, buffertype, pdata) glFlush() glDisable(target)
def __draw(self, widget, event): x = self.__distance * sin(self.__angle) z = self.__distance * cos(self.__angle) gldrawable = widget.get_gl_drawable() glcontext = widget.get_gl_context() # OpenGL begin. if not gldrawable.gl_begin(glcontext): return glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity () gluLookAt(x, 0.0, z, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) #========================== glPushMatrix() glLineWidth(3) glRotatef(self.__arm_angles[0], 1., 0., 0.) glRotatef(self.__arm_angles[1], 0., 1., 0.) glRotatef(self.__arm_angles[2], 0., 0., 1.) glTranslatef(self.__upper_arm, 0., 0.) #========================== glPushMatrix() glColor3f(30./255., 126./255., 30./255.) glScalef(self.__upper_arm, 0.4, 1.0) self.__draw_cube() # shoulder glPopMatrix() #========================== glTranslatef(self.__upper_arm, 0., 0.) glRotatef(self.__arm_angles[3] , 0., 0., 1.) glTranslatef(self.__forearm, 0., 0.) glPushMatrix() #========================== glScalef(self.__forearm, 0.3, 0.75) glColor3f(126./255., 30./255., 30./255.) self.__draw_cube() # elbow glPopMatrix() glPopMatrix() #========================== if gldrawable.is_double_buffered(): gldrawable.swap_buffers() else: glFlush() gldrawable.gl_end() # OpenGL end return
def render(self): """ The render pass for the scene """ self.init_view() glEnable(GL_LIGHTING) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Load the modelview matrix from the current state of the trackball glMatrixMode(GL_MODELVIEW) glPushMatrix() glLoadIdentity() tar = self.interaction.LookAttarget; self.Camera.target = (tar[0],tar[1],tar[2]) if self.Camera.CameraMode == 'Trackball': loc = self.Camera.position; #Camera.position glTranslated(-loc[0], -loc[1], -loc[2]) glMultMatrixf(self.interaction.trackball.matrix) elif self.Camera.CameraMode == 'LookAt': # embed() self.Camera.point() elif self.Camera.CameraMode == 'LookAtFollow': self.Camera.follow() self.Camera.point() else: glMultMatrixf(self.interaction.trackball.matrix) # by default revert to trackball if mode is set incorrectly # store the inverse of the current modelview. currentModelView = numpy.array(glGetFloatv(GL_MODELVIEW_MATRIX)) self.modelView = numpy.transpose(currentModelView) self.inverseModelView = inv(numpy.transpose(currentModelView)) # render the scene. This will call the render function for each object in the scene self.scene.render() # draw the grid glDisable(GL_LIGHTING) glCallList(G_OBJ_PLANE) glPopMatrix() # flush the buffers so that the scene can be drawn glFlush()
def highlightSelected(self, obj): # TODO: merge with GLPane (from which this was copied and modified) """ Highlight the selected object <obj>. In the mean time, we do stencil test to update stencil buffer, so it can be used to quickly test if pick is still on the same <obj> as last test. """ if not obj: return if not isinstance(obj, Atom) or (obj.element is not Singlet): return self._preHighlight() self._drawSelected_using_DrawingSets(obj) self._endHighlight() glFlush() self.swapBuffers() return
def present_fbo(self): drawable = self.gl_init() debug("present_fbo() drawable=%s", drawable) self.gl_marker("Presenting FBO on screen") if not drawable: return # Change state to target screen instead of our FBO glBindFramebuffer(GL_FRAMEBUFFER, 0) # Draw FBO texture on screen self.set_rgb24_paint_state() glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) w, h = self.size glBegin(GL_QUADS) glTexCoord2i(0, h) glVertex2i(0, 0) glTexCoord2i(0, 0) glVertex2i(0, h) glTexCoord2i(w, 0) glVertex2i(w, h) glTexCoord2i(w, h) glVertex2i(w, 0) glEnd() # Show the backbuffer on screen if drawable.is_double_buffered(): debug("SWAPPING BUFFERS NOW") drawable.swap_buffers() # Clear the new backbuffer to illustrate that its contents are undefined glClear(GL_COLOR_BUFFER_BIT) else: glFlush() self.gl_frame_terminator() self.unset_rgb24_paint_state() glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) drawable.gl_end()
def execute(self): if self.PreExecute: self.PreExecute() if self.gl_objects: cl.enqueue_acquire_gl_objects(self.queue, self.gl_objects) #really we should use a python trick to get the name of the kernel function to call #self.program.calibrate(self.queue, self.pos.shape, None, # *(self.kernelargs)) #here we assume we only have one kernel in the program and we call that one... self.program.all_kernels()[0](self.queue, self.pos.shape, None, *(self.kernelargs)) if self.gl_objects: cl.enqueue_release_gl_objects(self.queue, self.gl_objects) self.queue.finish() glFlush() if self.PostExecute: self.PostExecute()
def _on_expose_event(self, *args): """ Called on every frame rendering of the drawing area. Calls self.draw() and swaps the buffers. """ print("_on_expose_event(%s)" % str(args)) gldrawable = self.get_gl_drawable() glcontext = self.get_gl_context() if gldrawable is None: return False if not gldrawable.gl_begin(glcontext): return False glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() self.draw() if gldrawable.is_double_buffered(): gldrawable.swap_buffers() else: glFlush() gldrawable.gl_end() return False
def _gldraw(self): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) buf = np.asarray(self._screenbuffer)[::-1, :] glDrawPixels(COLS, ROWS, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, buf) glFlush()
def present_fbo(self, drawable): if not self.paint_screen: return self.gl_marker("Presenting FBO on screen for drawable %s" % drawable) assert drawable # Change state to target screen instead of our FBO glBindFramebuffer(GL_FRAMEBUFFER, 0) if self._alpha_enabled: # transparent background: glClearColor(0.0, 0.0, 0.0, 0.0) else: # plain white no alpha: glClearColor(1.0, 1.0, 1.0, 1.0) # Draw FBO texture on screen self.set_rgb_paint_state() w, h = self.size glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) if self._alpha_enabled: # support alpha channel if present: glEnablei(GL_BLEND, self.textures[TEX_FBO]) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glBegin(GL_QUADS) glTexCoord2i(0, h) glVertex2i(0, 0) glTexCoord2i(0, 0) glVertex2i(0, h) glTexCoord2i(w, 0) glVertex2i(w, h) glTexCoord2i(w, h) glVertex2i(w, 0) glEnd() #if desired, paint window border if self.border and self.border.shown: glDisable(GL_TEXTURE_RECTANGLE_ARB) #double size since half the line will be off-screen glLineWidth(self.border.size*2) glColor4f(self.border.red, self.border.green, self.border.blue, self.border.alpha) glBegin(GL_LINE_LOOP) for x,y in ((0, 0), (w, 0), (w, h), (0, h)): glVertex2i(x, y) glEnd() #reset color to default glColor4f(1.0, 1.0, 1.0, 1.0) # Show the backbuffer on screen if drawable.is_double_buffered(): log("%s.present_fbo() swapping buffers now", self) drawable.swap_buffers() # Clear the new backbuffer to illustrate that its contents are undefined glClear(GL_COLOR_BUFFER_BIT) else: glFlush() self.gl_frame_terminator() self.unset_rgb_paint_state() glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) log("%s.present_fbo() done", self)
def test_drawing(glpane, initOnly = False): """ When TEST_DRAWING is enabled at the start of graphics/widgets/GLPane_rendering_methods.py, and when TestGraphics_Command is run (see its documentation for various ways to do that), this file is loaded and GLPane.paintGL() calls the test_drawing() function instead of the usual body of paintGL(). """ # WARNING: this duplicates some code with test_Draw_model(). # Load the sphere shaders if needed. global _USE_SHADERS if _USE_SHADERS: if not drawing_globals.test_sphereShader: print "test_drawing: Loading sphere shaders." try: from graphics.drawing.gl_shaders import GLSphereShaderObject drawing_globals.test_sphereShader = GLSphereShaderObject() ##### REVIEW: is this compatible with my refactoring in drawing_globals? # If not, use of Test Graphics Performance command might cause subsequent # bugs in other code. Ideally we'd call the new methods that encapsulate # this, to setup shaders. [bruce 090304 comment] print "test_drawing: Sphere-shader initialization is complete.\n" except: _USE_SHADERS = False print "test_drawing: Exception while loading sphere shaders, will reraise and not try again" raise pass global start_pos, first_time if first_time: # Set up the viewing scale, but then let interactive zooming work. glpane.scale = nSpheres * .6 pass # This same function gets called to set up for drawing, and to draw. if not initOnly: glpane._setup_modelview() glpane._setup_projection() ##glpane._compute_frustum_planes() glClearColor(64.0, 64.0, 64.0, 1.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ) ##glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) glMatrixMode(GL_MODELVIEW) pass global test_csdl, test_dl, test_dls, test_ibo, test_vbo, test_spheres global test_DrawingSet, test_endpoints, test_Object # See below for test case descriptions and timings on a MacBook Pro. # The Qt event toploop in NE1 tops out at about 60 frames-per-second. # NE1 with test toploop, single CSDL per draw (test case 1) # . 17,424 spheres (132x132, through the color sorter) 4.8 FPS # Russ 080919: More recently, 12.2 FPS. # . Level 2 spheres have 9 triangles x 20 faces, 162 distinct vertices, # visited on the average 2.3 times, giving 384 tri-strip vertices. # . 17,424 spheres is 6.7 million tri-strip vertices. (6,690,816) if testCase == 1: if test_csdl is None: print ("Test case 1, %d^2 spheres\n %s." % (nSpheres, "ColorSorter")) test_csdl = ColorSortedDisplayList() ColorSorter.start(None, test_csdl) drawsphere([0.5, 0.5, 0.5], # color [0.0, 0.0, 0.0], # pos .5, # radius DRAWSPHERE_DETAIL_LEVEL, testloop = nSpheres ) ColorSorter.finish(draw_now = True) pass else: test_csdl.draw() pass # NE1 with test toploop, single display list per draw (test case 2) # . 10,000 spheres (all drawing modes) 17.5 FPS # . 17,424 spheres (132x132, manual display list) 11.1 FPS # . 40,000 spheres (mode 5 - VBO/IBO spheres from DL's) 2.2 FPS # . 40,000 spheres (mode 6 - Sphere shaders from DL's) 2.5 FPS # . 90,000 spheres (all drawing modes) 1.1 FPS elif testCase == 2: if test_dl is None: print ("Test case 2, %d^2 spheres\n %s." % (nSpheres, "One display list calling primitive dl's")) test_dl = glGenLists(1) glNewList(test_dl, GL_COMPILE_AND_EXECUTE) drawsphere_worker_loop(([0.0, 0.0, 0.0], # pos .5, # radius DRAWSPHERE_DETAIL_LEVEL, nSpheres )) glEndList() pass else: glColor3i(127, 127, 127) glCallList(test_dl) pass # NE1 with test toploop, one big chunk VBO/IBO of box quads (test case 3) # . 17,424 spheres (1 box/shader draw call) 43.7 FPS # . 17,424 spheres (1 box/shader draw call w/ rad/ctrpt attrs) 57.7 FPS # . 40,000 spheres (1 box/shader draw call w/ rad/ctrpt attrs) 56.7 FPS # . 90,000 spheres (1 box/shader draw call w/ rad/ctrpt attrs) 52.7 FPS # . 160,000 spheres (1 box/shader draw call w/ rad/ctrpt attrs) 41.4 FPS # . 250,000 spheres (1 box/shader draw call w/ rad/ctrpt attrs) 27.0 FPS elif int(testCase) == 3: doTransforms = False if test_spheres is None: print ("Test case 3, %d^2 spheres\n %s." % (nSpheres, "One big VBO/IBO chunk buffer")) if testCase == 3.1: print ("Sub-test 3.1, animate partial updates.") elif testCase == 3.2: print ("Sub-test 3.2, animate partial updates" + " w/ C per-chunk array buffering.") elif testCase == 3.3: print ("Sub-test 3.3, animate partial updates" + " w/ Python array buffering.") # . 3.4 - Big batch draw, with transforms indexed by IDs added. # (Second FPS number with debug colors in the vertex shader off.) # - 90,000 (300x300) spheres, TEXTURE_XFORMS = True, 26(29) FPS # - 90,000 (300x300) spheres, N_CONST_XFORMS = 250, 26(29) FPS # - 90,000 (300x300) spheres, N_CONST_XFORMS = 275, 0.3(0.6) FPS # (What happens after 250? CPU usage goes from 40% to 94%.) # -160,000 (400x400) spheres, TEXTURE_XFORMS = True, 26 FPS # -250,000 (500x500) spheres, TEXTURE_XFORMS = True, 26 FPS elif testCase == 3.4: print ("Sub-test 3.4, add transforms indexed by IDs.") from graphics.drawing.gl_shaders import TEXTURE_XFORMS from graphics.drawing.gl_shaders import N_CONST_XFORMS from graphics.drawing.gl_shaders import UNIFORM_XFORMS if TEXTURE_XFORMS: print "Transforms in texture memory." elif UNIFORM_XFORMS: print "%d transforms in uniform memory." % N_CONST_XFORMS pass else: print "transforms not supported, error is likely" doTransforms = True pass centers = [] radius = .5 radii = [] colors = [] if not doTransforms: transformIDs = None else: transformIDs = [] transformChunkID = -1 # Allocate IDs sequentially from 0. # For this test, allow arbitrarily chunking the primitives. primCounter = transformChunkLength transforms = [] # Accumulate transforms as a list of lists. # Initialize transforms with an identity matrix. # Transforms here are lists (or Numpy arrays) of 16 numbers. identity = ([1.0] + 4*[0.0]) * 3 + [1.0] pass for x in range(nSpheres): for y in range(nSpheres): centers += [sphereLoc(x, y)] # Sphere radii progress from 3/4 to full size. t = float(x+y)/(nSpheres+nSpheres) # 0 to 1 fraction. thisRad = radius * (.75 + t*.25) radii += [thisRad] # Colors progress from red to blue. colors += [rainbow(t)] # Transforms go into a texture memory image if needed. # Per-primitive Transform IDs go into an attribute VBO. if doTransforms: primCounter = primCounter + 1 if primCounter >= transformChunkLength: # Start a new chunk, allocating a transform matrix. primCounter = 0 transformChunkID += 1 if 0: # 1 # Debug hack: Label mat[0,0] with the chunk ID. # Vertex shader debug code shows these in blue. # If viewed as geometry, it will be a slight # stretch of the array in the X direction. transforms += [ [1.0+transformChunkID/100.0] + identity[1:]] elif 0: # 1 # Debug hack: Fill mat with mat.element pattern. transforms += [ [transformChunkID + i/100.0 for i in range(16)]] else: transforms += [identity] pass pass # All of the primitives in a chunk have the same ID. transformIDs += [transformChunkID] pass continue continue test_spheres = GLSphereBuffer() test_spheres.addSpheres(centers, radii, colors, transformIDs, None) if doTransforms: print ("%d primitives in %d transform chunks of size <= %d" % (nSpheres * nSpheres, len(transforms), transformChunkLength)) shader = drawing_globals.test_sphereShader shader.setupTransforms(transforms) pass else: shader = drawing_globals.test_sphereShader shader.configShader(glpane) # Update portions for animation. pulse = time.time() pulse -= floor(pulse) # 0 to 1 in each second # Test animating updates on 80% of the radii in 45% of the columns. # . 3.1 - Update radii Python array per-column, send to graphics RAM. # - 2,500 (50x50) spheres 55 FPS # - 10,000 (100x100) spheres 35 FPS # - 17,424 (132x132) spheres 22.2 FPS # - 40,000 (200x200) spheres 12.4 FPS # - 90,000 (300x300) spheres 6.0 FPS if testCase == 3.1: # Not buffered, send each column change. radius = .5 margin = nSpheres/10 for x in range(margin, nSpheres, 2): radii = [] for y in range(margin, nSpheres-margin): t = float(x+y)/(nSpheres+nSpheres) # 0 to 1 fraction. # Sphere radii progress from 3/4 to full size. thisRad = radius * (.75 + t*.25) phase = pulse + float(x+y)/nSpheres radii += 8 * [thisRad-.1 + .1*sin(phase * 2*pi)] continue C_radii = numpy.array(radii, dtype=numpy.float32) offset = x*nSpheres + margin test_spheres.radii_vbo.update(offset * 8, C_radii) continue pass # . 3.2 - Numpy buffered in C array, subscript assignments to C. # - 2,500 (50x50) spheres 48 FPS # - 10,000 (100x100) spheres 17.4 FPS # - 17,424 (132x132) spheres 11.2 FPS # - 40,000 (200x200) spheres 5.5 FPS # - 90,000 (300x300) spheres 2.5 FPS elif testCase == 3.2: # Buffered per-chunk at the C array level. radius = .5 margin = nSpheres/10 global C_array if C_array is None: # Replicate. C_array = numpy.zeros((8 * (nSpheres-(2*margin)),), dtype=numpy.float32) pass for x in range(margin, nSpheres, 2): count = 0 for y in range(margin, nSpheres-margin): t = float(x+y)/(nSpheres+nSpheres) # 0 to 1 fraction. # Sphere radii progress from 3/4 to full size. thisRad = radius * (.75 + t*.25) phase = pulse + float(x+y)/nSpheres C_array[count*8:(count+1)*8] = \ thisRad-.1 + .1*sin(phase * 2*pi) count += 1 continue offset = x*nSpheres + margin test_spheres.radii_vbo.update(offset * 8, C_array) continue pass # . 3.3 - updateRadii in Python array, copy via C to graphics RAM. # - 2,500 (50x50) spheres 57 FPS # - 10,000 (100x100) spheres 32 FPS # - 17,424 (132x132) spheres 20 FPS # - 40,000 (200x200) spheres 10.6 FPS # - 90,000 (300x300) spheres 4.9 FPS elif testCase == 3.3: # Buffered at the Python level, batch the whole-array update. radius = .5 margin = nSpheres/10 for x in range(margin, nSpheres, 2): radii = [] for y in range(margin, nSpheres-margin): t = float(x+y)/(nSpheres+nSpheres) # 0 to 1 fraction. # Sphere radii progress from 3/4 to full size. thisRad = radius * (.75 + t*.25) phase = pulse + float(x+y)/nSpheres radii += [thisRad-.1 + .1*sin(phase * 2*pi)] continue test_spheres.updateRadii( # Update, but don't send yet. x*nSpheres + margin, radii, send = False) continue test_spheres.sendRadii() pass # Options: color = [0.0, 1.0, 0.0], transform_id = 1, radius = 1.0 test_spheres.draw() pass # NE1 with test toploop, separate sphere VBO/IBO box/shader draws (test case 4) # . 17,424 spheres (132x132 box/shader draw quads calls) 0.7 FPS elif testCase == 4: if test_ibo is None: print ("Test case 4, %d^2 spheres\n %s." % (nSpheres, "Separate VBO/IBO shader/box buffer sphere calls, no DL")) # Collect transformed bounding box vertices and offset indices. # Start at the lower-left corner, offset so the whole pattern comes # up centered on the origin. cubeVerts = drawing_globals.shaderCubeVerts cubeIndices = drawing_globals.shaderCubeIndices C_indices = numpy.array(cubeIndices, dtype=numpy.uint32) test_ibo = GLBufferObject( GL_ELEMENT_ARRAY_BUFFER_ARB, C_indices, GL_STATIC_DRAW) test_ibo.unbind() C_verts = numpy.array(cubeVerts, dtype=numpy.float32) test_vbo = GLBufferObject( GL_ARRAY_BUFFER_ARB, C_verts, GL_STATIC_DRAW) test_vbo.unbind() pass else: drawing_globals.test_sphereShader.configShader(glpane) glEnableClientState(GL_VERTEX_ARRAY) test_vbo.bind() # Vertex data comes from the vbo. glVertexPointer(3, GL_FLOAT, 0, None) drawing_globals.test_sphereShader.setActive(True) glDisable(GL_CULL_FACE) glColor3i(127, 127, 127) test_ibo.bind() # Index data comes from the ibo. for x in range(nSpheres): for y in range(nSpheres): # From drawsphere_worker_loop(). pos = start_pos + (x+x/10+x/100) * V(1, 0, 0) + \ (y+y/10+y/100) * V(0, 1, 0) radius = .5 glPushMatrix() glTranslatef(pos[0], pos[1], pos[2]) glScale(radius,radius,radius) glDrawElements(GL_QUADS, 6 * 4, GL_UNSIGNED_INT, None) glPopMatrix() continue continue drawing_globals.test_sphereShader.setActive(False) glEnable(GL_CULL_FACE) test_ibo.unbind() test_vbo.unbind() glDisableClientState(GL_VERTEX_ARRAY) pass # NE1 with test toploop, # One DL around separate VBO/IBO shader/box buffer sphere calls (test case 5) # . 17,424 spheres (1 box/shader DL draw call) 9.2 FPS elif testCase == 5: if test_dl is None: print ("Test case 5, %d^2 spheres\n %s." % (nSpheres, "One DL around separate VBO/IBO shader/box buffer sphere calls")) # Collect transformed bounding box vertices and offset indices. # Start at the lower-left corner, offset so the whole pattern comes # up centered on the origin. cubeVerts = drawing_globals.shaderCubeVerts cubeIndices = drawing_globals.shaderCubeIndices C_indices = numpy.array(cubeIndices, dtype=numpy.uint32) test_ibo = GLBufferObject( GL_ELEMENT_ARRAY_BUFFER_ARB, C_indices, GL_STATIC_DRAW) test_ibo.unbind() C_verts = numpy.array(cubeVerts, dtype=numpy.float32) test_vbo = GLBufferObject( GL_ARRAY_BUFFER_ARB, C_verts, GL_STATIC_DRAW) test_vbo.unbind() # Wrap a display list around the draws. test_dl = glGenLists(1) glNewList(test_dl, GL_COMPILE_AND_EXECUTE) glEnableClientState(GL_VERTEX_ARRAY) test_vbo.bind() # Vertex data comes from the vbo. glVertexPointer(3, GL_FLOAT, 0, None) drawing_globals.test_sphereShader.setActive(True) glDisable(GL_CULL_FACE) glColor3i(127, 127, 127) test_ibo.bind() # Index data comes from the ibo. for x in range(nSpheres): for y in range(nSpheres): # From drawsphere_worker_loop(). pos = start_pos + (x+x/10+x/100) * V(1, 0, 0) + \ (y+y/10+y/100) * V(0, 1, 0) radius = .5 glPushMatrix() glTranslatef(pos[0], pos[1], pos[2]) glScale(radius,radius,radius) glDrawElements(GL_QUADS, 6 * 4, GL_UNSIGNED_INT, None) glPopMatrix() continue continue drawing_globals.test_sphereShader.setActive(False) glEnable(GL_CULL_FACE) test_ibo.unbind() test_vbo.unbind() glDisableClientState(GL_VERTEX_ARRAY) glEndList() else: glColor3i(127, 127, 127) glCallList(test_dl) pass pass # NE1 with test toploop, # N column DL's around VBO/IBO shader/box buffer sphere calls (test case 6) # . 2,500 (50x50) spheres 58 FPS # . 10,000 (100x100) spheres 57 FPS # . 17,424 (132x132) spheres 56 FPS # . 40,000 (200x200) spheres 50 FPS # . 90,000 (300x300) spheres 28 FPS # . 160,000 (400x400) spheres 16.5 FPS # . 250,000 (500x500) spheres 3.2 FPS elif testCase == 6: if test_dls is None: print ("Test case 6, %d^2 spheres\n %s." % (nSpheres, "N col DL's around VBO/IBO shader/box buffer sphere calls")) # Wrap n display lists around the draws (one per column.) test_dls = glGenLists(nSpheres) # Returns ID of first DL in the set. test_spheres = [] for x in range(nSpheres): centers = [] radius = .5 radii = [] colors = [] # Each column is relative to its bottom sphere location. Start # at the lower-left corner, offset so the whole pattern comes up # centered on the origin. start_pos = V(0, 0, 0) # So it doesn't get subtracted twice. pos = sphereLoc(x, 0) - V(nSpheres/2.0, nSpheres/2.0, 0) for y in range(nSpheres): centers += [sphereLoc(0, y)] # Sphere radii progress from 3/4 to full size. t = float(x+y)/(nSpheres+nSpheres) # 0 to 1 fraction. thisRad = radius * (.75 + t*.25) radii += [thisRad] # Colors progress from red to blue. colors += [rainbow(t)] continue test_sphere = GLSphereBuffer() test_sphere.addSpheres(centers, radii, colors, None, None) test_spheres += [test_sphere] glNewList(test_dls + x, GL_COMPILE_AND_EXECUTE) glPushMatrix() glTranslatef(pos[0], pos[1], pos[2]) test_sphere.draw() glPopMatrix() glEndList() continue pass else: shader = drawing_globals.test_sphereShader shader.configShader(glpane) # Turn the lights on. for x in range(nSpheres): glCallList(test_dls + x) continue pass pass # NE1 with test toploop, # N column VBO sets of shader/box buffer sphere calls (test case 7) # . 2,500 (50x50) spheres 50 FPS # . 10,000 (100x100) spheres 30.5 FPS # . 17,424 (132x132) spheres 23.5 FPS # . 40,000 (200x200) spheres 16.8 FPS # . 90,000 (300x300) spheres 10.8 FPS # . 160,000 (400x400) spheres 9.1 FPS # . 250,000 (500x500) spheres 7.3 FPS elif testCase == 7: if test_spheres is None: print ("Test case 7, %d^2 spheres\n %s." % (nSpheres, "Per-column VBO/IBO chunk buffers")) test_spheres = [] for x in range(nSpheres): centers = [] radius = .5 radii = [] colors = [] for y in range(nSpheres): centers += [sphereLoc(x, y)] # Sphere radii progress from 3/4 to full size. t = float(x+y)/(nSpheres+nSpheres) # 0 to 1 fraction. thisRad = radius * (.75 + t*.25) radii += [thisRad] # Colors progress from red to blue. colors += [rainbow(t)] continue _spheres1 = GLSphereBuffer() _spheres1.addSpheres(centers, radii, colors, None, None) test_spheres += [_spheres1] continue pass else: shader = drawing_globals.test_sphereShader shader.configShader(glpane) for chunk in test_spheres: chunk.draw() pass # NE1 with test toploop, # Short chunk VBO sets of shader/box buffer sphere calls (test case 8) # . 625 (25x25) spheres 30 FPS, 79 chunk buffers of length 8. # . 2,500 (50x50) spheres 13.6 FPS, 313 chunk buffers of length 8. # . 10,000 (100x100) spheres 6.4 FPS, 704 chunk buffers of length 8. # . 10,000 (100x100) spheres 3.3 FPS, 1250 chunk buffers of length 8. # . 17,424 (132x132) spheres 2.1 FPS, 2178 chunk buffers of length 8. # . 2,500 (50x50) spheres 33.5 FPS, 105 chunk buffers of length 24. # . 17,424 (132x132) spheres 5.5 FPS, 726 chunk buffers of length 24. # # Subcase 8.1: CSDLs in a DrawingSet. (Initial pass-through version.) # . 2,500 (50x50) spheres 36.5 FPS, 105 chunk buffers of length 24. # . 5,625 (75x75) spheres 16.1 FPS, 235 chunk buffers of length 24. # . 10,000 (100x100) spheres 0.5 FPS?!, 414 chunk buffers of length 24. # Has to be <= 250 chunks for constant memory transforms? # . 10,000 (100x100) spheres 11.8 FPS, 50 chunk buffers of length 200. # After a minute of startup. # . 10,000 (100x100) spheres 9.3 FPS, 200 chunk buffers of length 50. # After a few minutes of startup. # Subcase 8.2: CSDLs in a DrawingSet with transforms. (Pass-through.) # . 10,000 (100x100) spheres 11.5 FPS, 50 chunk buffers of length 200. # # Subcase 8.1: CSDLs in a DrawingSet. (First HunkBuffer version.) # Measured with auto-rotate on, ignoring startup and occasional outliers. # As before, on a 2 core, 2.4 GHz Intel MacBook Pro with GeForce 8600M GT. # HUNK_SIZE = 10000 # . 2,500 (50x50) spheres 140-200 FPS, 105 chunks of length 24. # . 5,625 (75x75) spheres 155-175 FPS, 235 chunks of length 24. # . 10,000 (100x100) spheres 134-145 FPS, 50 chunks of length 200. # . 10,000 (100x100) spheres 130-143 FPS, 200 chunks of length 50. # . 10,000 (100x100) spheres 131-140 FPS, 1,250 chunks of length 8. # Chunks are gathered into hunk buffers, so no chunk size speed diff. # . 17,424 (132x132) spheres 134-140 FPS, 88 chunks of length 200. # . 17,424 (132x132) spheres 131-140 FPS, 2,178 chunks of length 8. # HUNK_SIZE = 20000 # . 17,424 (132x132) spheres 131-140 FPS, 88 chunks of length 200. # . 17,424 (132x132) spheres 130-141 FPS, 2,178 chunks of length 8. # HUNK_SIZE = 10000 # . 40,000 (200x200) spheres 77.5-82.8 FPS, 5,000 chunks of length 8. # . 90,000 (300x300) spheres 34.9-42.6 FPS, 11,2500 chunks of length 8. # Spheres are getting down to pixel size, causing moire patterns. # Rotate the sphere-array off-axis 45 degrees to minimize. # (Try adding multi-sampled anti-aliasing, to the drawing test...) # . 160,000 (400x400) spheres 26.4-27.1 FPS, 20,000 chunks of length 8. # . 250,000 (500x500) spheres 16.8-17.1 FPS, 31,250 chunks of length 8. # The pattern is getting too large, far-clipping is setting in. # . 360,000 (600x600) spheres 11.6-11.8 FPS, 45,000 chunks of length 8. # Extreme far-clipping in the drawing test pattern. # HUNK_SIZE = 20000; no significant speed-up. # . 40,000 (200x200) spheres 75.9-81.5 FPS, 5,000 chunks of length 8. # . 90,000 (300x300) spheres 41.2-42.4 FPS, 11,250 chunks of length 8. # Spheres are getting down to pixel size, causing moire patterns. # . 160,000 (400x400) spheres 26.5-26.9 FPS, 20,000 chunks of length 8. # . 250,000 (500x500) spheres 16.5-17.1 FPS, 31,250 chunks of length 8. # . 360,000 (600x600) spheres 11.8-12.1 FPS, 45,000 chunks of length 8. # HUNK_SIZE = 5000; no significant slowdown or CPU load difference. # . 40,000 (200x200) spheres 81.0-83.8 FPS, 5,000 chunks of length 8. # . 160,000 (400x400) spheres 27.3-29.4 FPS, 20,000 chunks of length 8. # . 360,000 (600x600) spheres 11.7-12.1 FPS, 45,000 chunks of length 8. # # Retest after updating MacOS to 10.5.5, with TestGraphics, HUNK_SIZE = 5000 # . 40,000 (200x200) spheres 68.7-74.4 FPS, 5,000 chunks of length 8. # . 90,000 (300x300) spheres 39.4-42.0 FPS, 11,250 chunks of length 8. # . 160,000 (400x400) spheres 24.4-25.2 FPS, 20,000 chunks of length 8. # Retest with glMultiDrawElements drawing indexes in use, HUNK_SIZE = 5000 # . 40,000 (200x200) spheres 52.8-54.4 FPS, 5,000 chunks of length 8. # . 90,000 (300x300) spheres 22.8-23.3 FPS, 11,250 chunks of length 8. # . 160,000 (400x400) spheres 13.5-15.2 FPS, 20,000 chunks of length 8. # # Retest with reworked halo/sphere shader, HUNK_SIZE = 5000 [setup time] # . 17,424 (132x132) spheres 52.8-53.7 FPS, 2,178 chunks of length 8. [60] # . 40,000 (200x200) spheres 29.3-30.4 FPS, 5,000 chunks of length 8.[156] # . 90,000 (300x300) spheres 18.2-19.2 FPS, 11,250 chunks of length 8.[381] # . 160,000 (400x400) spheres 10.2-11.6 FPS, 20,000 chunks of length 8.[747] # Billboard drawing patterns instead of cubes, HUNK_SIZE = 5000 [setup time] # . 17,424 (132x132) spheres 49.7-55.7 FPS, 2,178 chunks of length 8. [35] # . 40,000 (200x200) spheres 39.6-40.8 FPS, 5,000 chunks of length 8. [88] # . 90,000 (300x300) spheres 18.9-19.5 FPS, 11,250 chunks of length 8.[225] # . 160,000 (400x400) spheres 11.2-11.7 FPS, 20,000 chunks of length 8.[476] # elif int(testCase) == 8: doTransforms = False doCylinders = False if test_spheres is None: # Setup. print ("Test case 8, %d^2 primitives\n %s, length %d." % (nSpheres, "Short VBO/IBO chunk buffers", chunkLength)) if testCase == 8.1: print ("Sub-test 8.1, sphere chunks are in CSDL's in a DrawingSet.") test_DrawingSet = DrawingSet() elif testCase == 8.2: print ("Sub-test 8.2, spheres, rotate with TransformControls.") test_DrawingSet = DrawingSet() doTransforms = True elif testCase == 8.3: print ("Sub-test 8.3, cylinder chunks are in CSDL's in a DrawingSet.") test_DrawingSet = DrawingSet() doCylinders = True pass if test_DrawingSet: # note: doesn't happen in test 8.0, which causes a bug then. [bruce 090223 comment] print "constructed test_DrawingSet =", test_DrawingSet if USE_GRAPHICSMODE_DRAW: print ("Use graphicsMode.Draw_model for DrawingSet in paintGL.") pass t1 = time.time() if doTransforms: # Provide several TransformControls to test separate action. global numTCs, TCs numTCs = 3 TCs = [TransformControl() for i in range(numTCs)] pass def primCSDL(centers, radii, colors): if not doTransforms: csdl = ColorSortedDisplayList() # Transformless. else: # Test pattern for TransformControl usage - vertical columns # of TC domains, separated by X coord of first center point. # Chunking will be visible when transforms are changed. xCoord = centers[0][0] - start_pos[0] # Negate centering X. xPercent = (xCoord / (nSpheres + nSpheres/10 + nSpheres/100 - 1 + (nSpheres <= 1))) xTenth = int(xPercent * 10 + .5) csdl = ColorSortedDisplayList(TCs[xTenth % numTCs]) pass # Test selection using the CSDL glname. ColorSorter.pushName(csdl.glname) ColorSorter.start(glpane, csdl) for (color, center, radius) in zip(colors, centers, radii): if not doCylinders: # Through ColorSorter to the sphere primitive buffer... drawsphere(color, center, radius, DRAWSPHERE_DETAIL_LEVEL) else: # Through ColorSorter to cylinder primitive buffer... if not drawing_globals.cylinderShader_available(): print "warning: not cylinderShader_available(), error is likely:" if (True and # Whether to do tapered shader-cylinders. # Display List cylinders don't support taper. glpane.glprefs.cylinderShader_desired()): ###cylRad = (radius/2.0, (.75-radius)/2.0) cylRad = (radius/1.5 - .167, .3 - radius/1.5) else: cylRad = radius/2.0 pass endPt2 = center + V(0.5, 0.0, 0.0) # 0.5, -0.5) drawcylinder(color, center, endPt2, cylRad) global test_endpoints test_endpoints += [(center, endPt2)] pass continue ColorSorter.popName() ColorSorter.finish(draw_now = True) test_DrawingSet.addCSDL(csdl) return csdl if testCase == 8: #bruce 090223 revised to try to avoid traceback def chunkFn(centers, radii, colors): res = GLSphereBuffer() res.addSpheres(centers, radii, colors, None, None) return res pass else: chunkFn = primCSDL pass test_spheres = [] radius = .5 centers = [] radii = [] colors = [] global test_endpoints test_endpoints = [] for x in range(nSpheres): for y in range(nSpheres): centers += [sphereLoc(x, y)] # Sphere radii progress from 3/4 to full size. t = float(x+y)/(nSpheres+nSpheres) # 0 to 1 fraction. thisRad = radius * (.5 + t*.5) radii += [thisRad] # Colors progress from red to blue. colors += [rainbow(t)] # Put out short chunk buffers. if len(centers) >= chunkLength: test_spheres += [ chunkFn(centers, radii, colors) ] centers = [] radii = [] colors = [] continue continue # Remainder fraction buffer. if len(centers): test_spheres += [chunkFn(centers, radii, colors)] pass print "Setup time", time.time() - t1, "seconds." print "%d chunk buffers" % len(test_spheres) pass elif not initOnly: # Run. test_Draw_8x(glpane) pass elif testCase == 100: #bruce 090102 # before making more of these, modularize it somehow from commands.TestGraphics.test_selection_redraw import test_selection_redraw test_class = test_selection_redraw params = ( nSpheres, ) # note: test size is not directly comparable to other tests with same value of nSpheres if test_Object is None \ or not isinstance(test_Object, test_class) \ or test_Object.current_params() != params: # review: same_vals? # Setup. if test_Object: test_Object.destroy() test_Object = test_class(*params) test_Object.activate() print test_Object pass # review: safe to change elif to if? not sure, GL state is only initialized below elif not initOnly: # Run. test_Object.draw_complete() pass pass if not initOnly: glMatrixMode(GL_MODELVIEW) glFlush() pass first_time = False return
def gl_end(self, drawable): if drawable.is_double_buffered(): drawable.swap_buffers() else: glFlush() drawable.gl_end()
def OnPaint(self, event): # startTime = time.time() if not self.init: self.context = GLContext(self) self.SetCurrent(self.context) glEnable(GL_DEPTH_TEST); self.init = True if self._refreshAll: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() # prepareTime = time.time() - startTime if self.dataNum == 0: self.SwapBuffers() return eyePos = self.eyeDistance ex = 0.0 ey = 0.0 ez = 0.0 dx = 0.0 dy = 0.0 dz = 0.0 ux = 0.0 uy = 0.0 uz = 0.0 xLen = max(abs(self.xMax), abs(self.xMin)) * 2 yLen = max(abs(self.yMax), abs(self.yMin)) * 2 zLen = max(abs(self.zMax), abs(self.zMin)) * 2 # print 'transX, transY:', self.transX, self.transY if self.is3D: r2s = max(xLen, yLen, zLen) / self.size.width tX = self.transX * r2s tY = self.transY * r2s if not zLen == 0: z = zLen / 2 if yLen / zLen > self.size.width / self.size.height: z = yLen * self.size.height / self.size.width / 2 z *= 1.5 usedAngle = pi / 2 - viewPosAngle cfovy1 = (eyePos - z * cos(usedAngle)) / sqrt(eyePos * eyePos + z * z - 2 * eyePos * z * cos(usedAngle)) cfovy2 = (eyePos - z * cos(pi - usedAngle)) / sqrt(eyePos * eyePos + z * z - 2 * eyePos * z * cos(pi - usedAngle)) fovy1 = degrees(acos(cfovy1)) fovy2 = degrees(acos(cfovy2)) self.fovy = 3 * max(fovy1, fovy2) angleX = viewPosAngle + radians(self.angleHorizontal) angleZ = viewPosAngle + radians(self.angleVertical) ex = eyePos * cos(angleZ) * cos(angleX) ey = eyePos * cos(angleZ) * sin(angleX) ez = eyePos * sin(angleZ) ux = 0.0 uy = cos(pi / 2 - radians(self.angleFlat)) uz = sin(pi / 2 - radians(self.angleFlat)) flatAngle = radians(self.angleFlat) dx = -tX * cos(flatAngle) * sin(angleX) - tX * sin(flatAngle) * sin(angleZ) * sin(angleX) dx += tY * sin(flatAngle) * sin(angleX) - tY * cos(flatAngle) * sin(angleZ) * cos(angleX) dy = tX * cos(flatAngle) * cos(angleX) - tX * sin(flatAngle) * sin(angleZ) * cos(angleX) dy += -tY * sin(flatAngle) * cos(angleX) - tY * cos(flatAngle) * sin(angleZ) * sin(angleX) dz = tX * sin(flatAngle) * cos(angleZ) dz += tY * cos(flatAngle) * cos(angleZ) else: r2s = xLen / self.size.width dx = self.transX * r2s dy = self.transY * r2s dz = 0.0 y = yLen / 2 if xLen / yLen > self.size.width / self.size.height: y = xLen * self.size.height / self.size.width / 2 y += yLen / 10 self.fovy = 2 * degrees(atan(y / eyePos)) ez = eyePos ux = sin(radians(self.angleFlat)) uy = cos(radians(self.angleFlat)) uz = 0.0 scale = 1 if self.size != None: scale = float(self.size.width) / self.size.height # userCalculationTime = time.time() - startTime - prepareTime glMatrixMode(GL_PROJECTION) glLoadIdentity() if self.is3D: gluPerspective(self.fovy * self.scaleFactor, scale, 0.1, self.eyeDistance * 2) else: gluPerspective(self.fovy * self.scaleFactor, scale, self.eyeDistance - self.zMax - 10, self.eyeDistance - self.zMin + 10) glMatrixMode(GL_MODELVIEW) glLoadIdentity() gluLookAt(ex, ey, ez, -dx, -dy, -dz, ux, uy, uz) self._startPointIdx = 0 if self.isDragging: # draw the frame instead of all data glLineWidth(1.0) glColor3f(0.0, 0.5, 0.0) glBegin(GL_LINES) glVertex3f(self.xMin, self.yMin, self.zMin) # 1 glVertex3f(self.xMax, self.yMin, self.zMin) # 2 glVertex3f(self.xMax, self.yMin, self.zMin) # 2 glVertex3f(self.xMax, self.yMax, self.zMin) # 3 glVertex3f(self.xMax, self.yMax, self.zMin) # 3 glVertex3f(self.xMin, self.yMax, self.zMin) # 4 glVertex3f(self.xMin, self.yMax, self.zMin) # 4 glVertex3f(self.xMin, self.yMin, self.zMin) # 1 glVertex3f(self.xMin, self.yMin, self.zMin) # 1 glVertex3f(self.xMin, self.yMin, self.zMax) # 5 glVertex3f(self.xMin, self.yMin, self.zMax) # 5 glVertex3f(self.xMax, self.yMin, self.zMax) # 6 glVertex3f(self.xMax, self.yMin, self.zMax) # 6 glVertex3f(self.xMax, self.yMax, self.zMax) # 7 glVertex3f(self.xMax, self.yMax, self.zMax) # 7 glVertex3f(self.xMin, self.yMax, self.zMax) # 8 glVertex3f(self.xMin, self.yMax, self.zMax) # 8 glVertex3f(self.xMin, self.yMin, self.zMax) # 5 glVertex3f(self.xMax, self.yMin, self.zMin) # 2 glVertex3f(self.xMax, self.yMin, self.zMax) # 6 glVertex3f(self.xMax, self.yMax, self.zMin) # 3 glVertex3f(self.xMax, self.yMax, self.zMax) # 7 glVertex3f(self.xMin, self.yMax, self.zMin) # 4 glVertex3f(self.xMin, self.yMax, self.zMax) # 8 glEnd() glFlush() self.SwapBuffers() return glEnableClientState(GL_VERTEX_ARRAY) if self.colorsNum >= self.dataNum: glEnableClientState(GL_COLOR_ARRAY) glDrawBuffer(GL_FRONT_AND_BACK) if self._startPointIdx + self._drawnPointsNum >= self.dataNum: glDrawArrays(GL_POINTS, self._startPointIdx, self.dataNum - self._startPointIdx) if self.displaySelected: selNum = len(self.displayedSelPoints) if selNum >= 2: glLineWidth(2.0) glColor3f(0.0, 1.0, 0.0) glBegin(GL_LINES) for i in xrange(1, selNum): glVertex3f(self.displayedSelPoints[i - 1][0], self.displayedSelPoints[i - 1][1], self.displayedSelPoints[i - 1][2]) glVertex3f(self.displayedSelPoints[i][0], self.displayedSelPoints[i][1], self.displayedSelPoints[i][2]) glVertex3f(self.displayedSelPoints[selNum - 1][0], self.displayedSelPoints[selNum - 1][1], self.displayedSelPoints[selNum - 1][2]) glVertex3f(self.displayedSelPoints[0][0], self.displayedSelPoints[0][1], self.displayedSelPoints[0][2]) glEnd() self._refreshAll = True else: glDrawArrays(GL_POINTS, self._startPointIdx, self._drawnPointsNum) self._refreshAll = False self._isFront = not self._isFront self._startPointIdx += self._drawnPointsNum if self._isFront else 0 glDisableClientState(GL_VERTEX_ARRAY) if self.colorsNum >= self.dataNum: glDisableClientState(GL_COLOR_ARRAY) glFlush() self.SwapBuffers() # drawingTime = time.time() - startTime - prepareTime - userCalculationTime # print "preparation time:", str(prepareTime), "user calculation time:",\ # str(userCalculationTime), "drawing time:", str(drawingTime) if not self._refreshAll: PostEvent(self, PaintEvent()) event.Skip()
def select(self, wX, wY): """ Use the OpenGL picking/selection to select any object. Return the selected object, otherwise, return None. Restore projection and modelview matrices before returning. """ ### NOTE: this code is similar to (and was copied and modified from) # GLPane_highlighting_methods.do_glselect_if_wanted, but also differs # in significant ways (too much to make it worth merging, unless we # decide to merge the differing algorithms as well). It's one of # several instances of hit-test code that calls glRenderMode. # [bruce 060721/080917 comment] wZ = glReadPixelsf(wX, wY, 1, 1, GL_DEPTH_COMPONENT) gz = wZ[0][0] if gz >= GL_FAR_Z: # Empty space was clicked return None pxyz = A(gluUnProject(wX, wY, gz)) pn = self.out pxyz -= 0.0002 * pn # Note: if this runs before the model is drawn, this can have an # exception "OverflowError: math range error", presumably because # appropriate state for gluUnProject was not set up. That doesn't # normally happen but can happen due to bugs (no known open bugs # of that kind). # Sometimes our drawing area can become "stuck at gray", # and when that happens, the same exception can occur from this line. # Could it be that too many accidental mousewheel scrolls occurred # and made the scale unreasonable? (To mitigate, we should prevent # those from doing anything unless we have a valid model, and also # reset that scale when loading a new model (latter is probably # already done, but I didn't check). See also the comments # in def wheelEvent.) [bruce 080220 comment] dp = - dot(pxyz, pn) # Save projection matrix before it's changed. glMatrixMode(GL_PROJECTION) glPushMatrix() current_glselect = (wX, wY, 1, 1) self._setup_projection(glselect = current_glselect) glSelectBuffer(self.SIZE_FOR_glSelectBuffer) glRenderMode(GL_SELECT) glInitNames() glMatrixMode(GL_MODELVIEW) # Save model view matrix before it's changed. glPushMatrix() # Draw model using glRenderMode(GL_SELECT) as set up above try: glClipPlane(GL_CLIP_PLANE0, (pn[0], pn[1], pn[2], dp)) glEnable(GL_CLIP_PLANE0) self._drawModel_using_DrawingSets() except: #bruce 080917 fixed predicted bugs in this except clause (untested) print_compact_traceback("exception in ThumbView._drawModel_using_DrawingSets() during GL_SELECT; ignored; restoring matrices: ") glDisable(GL_CLIP_PLANE0) glMatrixMode(GL_PROJECTION) glPopMatrix() glMatrixMode(GL_MODELVIEW) glPopMatrix() glRenderMode(GL_RENDER) return None else: glDisable(GL_CLIP_PLANE0) # Restore model/view matrix glPopMatrix() # Restore projection matrix and set matrix mode to Model/View glMatrixMode(GL_PROJECTION) glPopMatrix() glMatrixMode(GL_MODELVIEW) glFlush() hit_records = list(glRenderMode(GL_RENDER)) ## print "%d hits" % len(hit_records) for (near, far, names) in hit_records: ## print "hit record: near, far, names:", near, far, names # note from testing: near/far are too far apart to give actual depth, # in spite of the 1-pixel drawing window (presumably they're vertices # taken from unclipped primitives, not clipped ones). ### REVIEW: this just returns the first candidate object found. # The clip plane may restrict the set of candidates well enough to # make sure that's the right one, but this is untested and unreviewed. # (And it's just my guess that that was Huaicai's intention in # setting up clipping, since it's not documented. I'm guessing that # the plane is just behind the hitpoint, but haven't confirmed this.) # [bruce 080917 comment] if names: name = names[-1] assy = self.assy obj = assy and assy.object_for_glselect_name(name) #k should always return an obj return obj return None # from ThumbView.select
def leftUp(self, event): """ Erase the final rubber band window and do zoom if user indeed draws a rubber band window. """ # bugs 1190, 1818 wware 4/05/2006 - sometimes Qt neglects to call # leftDown before this if not hasattr(self, "pWxy") or not hasattr(self, "firstDraw"): return cWxy = (event.pos().x(), self.glpane.height - event.pos().y()) zoomX = (abs(cWxy[0] - self.pWxy[0]) + 0.0) / (self.glpane.width + 0.0) zoomY = (abs(cWxy[1] - self.pWxy[1]) + 0.0) / (self.glpane.height + 0.0) # The rubber band window size can be larger than that of glpane. # Limit the zoomFactor to 1.0 zoomFactor = min(max(zoomX, zoomY), 1.0) # Huaicai: when rubber band window is too small, # like a double click, a single line rubber band, skip zoom DELTA = 1.0E-5 if self.pWxy[0] == cWxy[0] or self.pWxy[1] == cWxy[1] \ or zoomFactor < DELTA: self.command.command_Done() return # Erase the last rubber-band window rbwcolor = self.command.rbwcolor drawrectangle(self.pStart, self.pPrev, self.glpane.up, self.glpane.right, rbwcolor) glFlush() self.glpane.swapBuffers() winCenterX = (cWxy[0] + self.pWxy[0]) / 2.0 winCenterY = (cWxy[1] + self.pWxy[1]) / 2.0 winCenterZ = \ glReadPixelsf(int(winCenterX), int(winCenterY), 1, 1, GL_DEPTH_COMPONENT) assert winCenterZ[0][0] >= 0.0 and winCenterZ[0][0] <= 1.0 if winCenterZ[0][0] >= GL_FAR_Z: # window center touches nothing p1 = A(gluUnProject(winCenterX, winCenterY, 0.005)) p2 = A(gluUnProject(winCenterX, winCenterY, 1.0)) los = self.glpane.lineOfSight k = dot(los, -self.glpane.pov - p1) / dot(los, p2 - p1) zoomCenter = p1 + k*(p2-p1) else: zoomCenter = \ A(gluUnProject(winCenterX, winCenterY, winCenterZ[0][0])) self.glpane.pov = V(-zoomCenter[0], -zoomCenter[1], -zoomCenter[2]) # The following are 2 ways to do the zoom, the first one # changes view angles, the 2nd one change viewing distance # The advantage for the 1st one is model will not be clipped by # near or back clipping planes, and the rubber band can be # always shown. The disadvantage: when the view field is too # small, a selection window may be actually act as a single pick. # rubber band window will not look as rectangular any more. #zf = self.glpane.getZoomFactor() # [note: method does not exist] #zoomFactor = pow(zoomFactor, 0.25) #zoomFactor *= zf #self.glpane.setZoomFactor(zoomFactor) # [note: method does not exist] # Change viewing distance to do zoom. This works better with # mouse wheel, since both are changing viewing distance, and # it's not too bad of model being clipped, since the near/far clip # plane change as scale too. self.glpane.scale *= zoomFactor self.command.command_Done() return