Ejemplo n.º 1
0
    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()
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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()
Ejemplo n.º 5
0
    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()
Ejemplo n.º 6
0
    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()
Ejemplo n.º 7
0
    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()
Ejemplo n.º 8
0
    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
Ejemplo n.º 9
0
    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
Ejemplo n.º 10
0
    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()
Ejemplo n.º 11
0
    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()
Ejemplo n.º 12
0
    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
Ejemplo n.º 13
0
    def render_figure(self):
        glClear(GL_COLOR_BUFFER_BIT)

        for figure in self.list_of_figures_to_draw:
            figure.draw_me()

        glFlush()
Ejemplo n.º 14
0
    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
Ejemplo n.º 15
0
 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()
Ejemplo n.º 16
0
	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()
Ejemplo n.º 17
0
    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
Ejemplo n.º 18
0
    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()
Ejemplo n.º 19
0
 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()
Ejemplo n.º 20
0
 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()
Ejemplo n.º 21
0
 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()
Ejemplo n.º 22
0
 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()
Ejemplo n.º 23
0
 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)
Ejemplo n.º 24
0
    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()
Ejemplo n.º 25
0
 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)
Ejemplo n.º 26
0
    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)
Ejemplo n.º 27
0
    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()
Ejemplo n.º 28
0
 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
Ejemplo n.º 29
0
    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)
Ejemplo n.º 30
0
 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
Ejemplo n.º 31
0
 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()
Ejemplo n.º 32
0
 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
Ejemplo n.º 33
0
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()
Ejemplo n.º 34
0
    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
Ejemplo n.º 35
0
 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)
Ejemplo n.º 36
0
 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)
Ejemplo n.º 37
0
	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()
Ejemplo n.º 38
0
 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()
Ejemplo n.º 39
0
    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()
Ejemplo n.º 40
0
    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()
Ejemplo n.º 41
0
 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()
Ejemplo n.º 42
0
    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()
Ejemplo n.º 43
0
    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()        
Ejemplo n.º 44
0
    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)
Ejemplo n.º 45
0
 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
Ejemplo n.º 46
0
    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()
Ejemplo n.º 47
0
 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
Ejemplo n.º 48
0
    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)
Ejemplo n.º 49
0
    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()        
Ejemplo n.º 51
0
    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
Ejemplo n.º 52
0
 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()
Ejemplo n.º 53
0
    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)
Ejemplo n.º 54
0
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
Ejemplo n.º 55
0
 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()
Ejemplo n.º 57
0
    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
Ejemplo n.º 58
0
    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