Exemplo n.º 1
0
Arquivo: graph.py Projeto: reims/wesen
 def Draw(self):
     """draw a curve of all previous data,
     up to a certain point (self.resolution)"""
     self.vbo.bind()
     self.vbo.copy_data()
     glEnableClientState(GL_VERTEX_ARRAY)
     glVertexPointer(2, GL_FLOAT, 0, self.vbo)
     if self.buffer_full:
         if self.previous_index != self.size - 1:
             glPushMatrix()
             glTranslatef(-1 * (self.previous_index + 1), 0.0, 0.0)
             glDrawArrays(GL_LINE_STRIP,
                          (self.previous_index + 1),
                          (self.size - self.previous_index - 1))
             glPopMatrix()
         glPushMatrix()
         glTranslatef(self.size - self.previous_index - 1, 0.0, 0.0)
         glDrawArrays(GL_LINE_STRIP, 0,
                      (self.previous_index + 1))
         glPopMatrix()
     else:
         glDrawArrays(GL_LINE_STRIP, 0,
                      (self.previous_index + 1))
     glDisableClientState(GL_VERTEX_ARRAY)
     self.vbo.unbind()
Exemplo n.º 2
0
def draw_circle_memoized(p, n, r, sides=64):
    """Draw circle given point, normal vector, radius, and # sides.
    Uses the function compute_circle to generate points.
    """
    vertices, count = compute_circle(*p, *n, r, sides)

    # draw vertices
    glEnableClientState(GL_VERTEX_ARRAY)
    glVertexPointer(3, GL_FLOAT, 0, vertices)
    glDrawArrays(GL_LINE_STRIP, 0, count)
    glDisableClientState(GL_VERTEX_ARRAY)
Exemplo n.º 3
0
def draw_helix_memoized(p, n, r, pitch=1, turns=1.0, sides=64):
    """Draw helix given point, normal vector, radius, pitch, # turns, and # sides.
    Uses the function compute_helix to generate points.
    """
    vertices, count = compute_helix(*p, *n, r, pitch, turns, sides)

    # draw vertices
    glEnableClientState(GL_VERTEX_ARRAY)
    glVertexPointer(3, GL_FLOAT, 0, vertices)
    glDrawArrays(GL_LINE_STRIP, 0, count)
    glDisableClientState(GL_VERTEX_ARRAY)
Exemplo n.º 4
0
 def draw_detector(self):
     glUseProgram(self.shader)
     try:
         self.dom_positions_vbo.bind()
         try:
             glEnableClientState(GL_VERTEX_ARRAY)
             glVertexPointerf(self.dom_positions_vbo)
             glPointSize(2)
             glDrawArrays(GL_POINTS, 0, len(self.dom_positions)*3)
         finally:
             self.dom_positions_vbo.unbind()
             glDisableClientState(GL_VERTEX_ARRAY)
     finally:
         glUseProgram(0)
Exemplo n.º 5
0
    def Render(self, mode):
        """Render the geometry for the scene."""

        shaders.glUseProgram(self.shader)
        try:
            self.vbo.bind()
            try:
                glEnableClientState(GL_VERTEX_ARRAY)
                GLVertexPointer(self.vbo)
                glDrawArrays(GL_TRIANGLES, 0, 9)
            finally:
                self.vbo.unbind()
                glDisableClientState(GL_VERTEX_ARRAY)
        finally:
            shaders.glUseProgram(0)
Exemplo n.º 6
0
    def draw(self):
        glDisable(GL_LIGHTING)

        glLineWidth(self._width)
        glColor(*self._color)

        glEnableClientState(GL_VERTEX_ARRAY)

        if self._vbo:
            with self._vbo:
                glVertexPointerf(self._vbo)
                glDrawArrays(GL_LINE_STRIP, 0, len(self._vbo))

        glDisableClientState(GL_VERTEX_ARRAY)

        glEnable(GL_LIGHTING)
Exemplo n.º 7
0
    def display(self):
        self.world.drawGL()

        glDisable(GL_LIGHTING)
        glLineWidth(2.0)

        glEnableClientState(GL_VERTEX_ARRAY)

        for (color, vbo) in self.trace_vbos:
            glColor(*color)
            with vbo:
                glVertexPointerf(vbo)
                glDrawArrays(GL_LINE_STRIP, 0, len(vbo))

        glDisableClientState(GL_VERTEX_ARRAY)

        glEnable(GL_LIGHTING)
Exemplo n.º 8
0
    def draw_lines(ls):
        glDisableClientState(GL_NORMAL_ARRAY)
        glEnableClientState(GL_VERTEX_ARRAY)
        glLineWidth(3.0)
        allpts = ls.v[ls.e.flatten()].astype(np.float32)
        glVertexPointerf(allpts)
        if hasattr(ls, 'vc') or hasattr(ls, 'ec'):
            glEnableClientState(GL_COLOR_ARRAY)
            if hasattr(ls, 'vc'):
                glColorPointerf(ls.vc[ls.e.flatten()].astype(np.float32))
            else:
                clrs = np.ones(
                    (ls.e.shape[0] * 2, 3)) * np.repeat(ls.ec, 2, axis=0)
                glColorPointerf(clrs)
        else:
            glDisableClientState(GL_COLOR_ARRAY)

        glDisable(GL_LIGHTING)
        glDrawElementsui(GL_LINES, np.arange(len(allpts), dtype=np.uint32))
Exemplo n.º 9
0
def draw_circle_trig(p, n, r, sides=36):
    """Draw circle given point, normal vector, radius, and # sides."""
    a, b, n = rotate_basis(*n)
    tau = 6.28318530717958647692

    count = sides + 1
    vertices = np.empty(count * 3)
    for i in range(count):
        vertices[i * 3] = p[0] + r * (a[0] * math.cos(i * tau / sides) +
                                      b[0] * math.sin(i * tau / sides))
        vertices[i * 3 + 1] = p[1] + r * (a[1] * math.cos(i * tau / sides) +
                                          b[1] * math.sin(i * tau / sides))
        vertices[i * 3 + 2] = p[2] + r * (a[2] * math.cos(i * tau / sides) +
                                          b[2] * math.sin(i * tau / sides))

    # draw vertices
    glEnableClientState(GL_VERTEX_ARRAY)
    glVertexPointer(3, GL_FLOAT, 0, vertices)
    glDrawArrays(GL_LINE_STRIP, 0, count)
    glDisableClientState(GL_VERTEX_ARRAY)
Exemplo n.º 10
0
    def paint(self):
        """
        For all of the known terrain, render whatever faces are exposed.
        """
        if self._texture is None:
            self._texture = self._createTexture()

        glBindTexture(GL_TEXTURE_2D, self._texture)
        glEnableClientState(GL_VERTEX_ARRAY)
        glEnableClientState(GL_TEXTURE_COORD_ARRAY)
        for surface in self._vbos:
            vbo = surface.update
            length = surface.important
            vbo.bind()
            glVertexPointer(3, GL_FLOAT, 4 * 5, vbo)
            glTexCoordPointer(2, GL_FLOAT, 4 * 5, vbo + (4 * 3))
            glDrawArrays(GL_TRIANGLES, 0, length)
            vbo.unbind()
        glDisableClientState(GL_VERTEX_ARRAY)
        glDisableClientState(GL_TEXTURE_COORD_ARRAY)
        glBindTexture(GL_TEXTURE_2D, 0)
Exemplo n.º 11
0
Arquivo: map.py Projeto: reims/wesen
 def Draw(self, descriptor=[]):
     """Draws a map with all objects in the world,
     according to the descriptor."""
     GuiObject.Draw(self)
     # TODO get rid of any frame mechanism parts here
     frame = self._getFrameData()["frame"]
     glTranslatef(frame, 2 * frame, 0.0)
     # moving away from the frame
     blockSize = (1 - 2 * frame) / self.worldLength
     scaleFactor = blockSize
     # data = narray(reduce(lambda a,b: a + b,
     # 		     map(self.__descToArray,
     # 			 descriptor)),
     # 	      "f");
     if len(descriptor) > 0:
         #valuesPerObject = len(self.__descToArray(descriptor[0]))
         if self._vbo is None:
             self._BuildData(descriptor)
         for _id, obj in self._dirty_objects.items():
             self._UpdateObject(_id, obj)
         self._dirty_objects = {}
         glTranslatef(frame, 2 * frame, 0.0)
         # moving away from the frame
         glScale(scaleFactor, scaleFactor, 1.0)
         self._vbo.bind()
         self._vbo.copy_data()
         try:
             glEnableClientState(GL_VERTEX_ARRAY)
             glEnableClientState(GL_COLOR_ARRAY)
             # 2 coordinates with 4 color values with 4 bytes each in
             # between
             glVertexPointer(2, GL_FLOAT, 24, self._vbo)
             # 4 color values with 2 coordinates with 4 bytes each in
             # between
             glColorPointer(4, GL_FLOAT, 24, self._vbo + 8)
             glDrawArrays(GL_TRIANGLES, 0, 3 * 2 * (self._max_index + 1))
         finally:
             self._vbo.unbind()
             glDisableClientState(GL_VERTEX_ARRAY)
             glDisableClientState(GL_COLOR_ARRAY)
Exemplo n.º 12
0
Arquivo: map.py Projeto: reims/wesen
 def Draw(self, descriptor=[]):
     """Draws a map with all objects in the world,
     according to the descriptor."""
     GuiObject.Draw(self)
     # TODO get rid of any frame mechanism parts here
     frame = self._getFrameData()["frame"]
     glTranslatef(frame, 2 * frame, 0.0)
     # moving away from the frame
     blockSize = (1 - 2 * frame) / self.worldLength
     scaleFactor = blockSize
     # data = narray(reduce(lambda a,b: a + b,
     # 		     map(self.__descToArray,
     # 			 descriptor)),
     # 	      "f");
     if len(descriptor) > 0:
         # valuesPerObject = len(self.__descToArray(descriptor[0]))
         if self._vbo is None:
             self._BuildData(descriptor)
         for _id, obj in self._dirty_objects.items():
             self._UpdateObject(_id, obj)
         self._dirty_objects = {}
         glTranslatef(frame, 2 * frame, 0.0)
         # moving away from the frame
         glScale(scaleFactor, scaleFactor, 1.0)
         self._vbo.bind()
         self._vbo.copy_data()
         try:
             glEnableClientState(GL_VERTEX_ARRAY)
             glEnableClientState(GL_COLOR_ARRAY)
             # 2 coordinates with 4 color values with 4 bytes each in
             # between
             glVertexPointer(2, GL_FLOAT, 24, self._vbo)
             # 4 color values with 2 coordinates with 4 bytes each in
             # between
             glColorPointer(4, GL_FLOAT, 24, self._vbo + 8)
             glDrawArrays(GL_TRIANGLES, 0, 3 * 2 * (self._max_index + 1))
         finally:
             self._vbo.unbind()
             glDisableClientState(GL_VERTEX_ARRAY)
             glDisableClientState(GL_COLOR_ARRAY)
Exemplo n.º 13
0
    def draw(self):
        '''
        Draw the point cloud.
        '''
        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()
        glMultMatrixf(self._pose.T)

        glDisable(GL_LIGHTING)
        glPointSize(2)

        if self._xyz_vbo:
            # ref: http://stackoverflow.com/questions/16558819/vertex-buffer-objects-in-pyopengl-vertex-index-and-colour
            with self._xyz_vbo:
                glEnableClientState(GL_VERTEX_ARRAY)
                glVertexPointerf(self._xyz_vbo)

                if self._rgb_vbo:
                    # check for dimension match to avoid segmentation faults
                    if len(self._rgb_vbo) != len(self._xyz_vbo):
                        raise RuntimeError(
                            'point cloud XYZ and RGB length mismatch: {} vs {}'
                            .format(len(self._xyz_vbo), len(self._rgb_vbo)))

                    with self._rgb_vbo:
                        # add color
                        glEnableClientState(GL_COLOR_ARRAY)
                        glColorPointerf(self._rgb_vbo)
                        glDrawArrays(GL_POINTS, 0, len(self._xyz_vbo))
                else:
                    # draw without color
                    glDrawArrays(GL_POINTS, 0, len(self._xyz_vbo))

        glDisableClientState(GL_COLOR_ARRAY)
        glDisableClientState(GL_VERTEX_ARRAY)

        glEnable(GL_LIGHTING)

        glPopMatrix()
Exemplo n.º 14
0
 def Draw(self):
     """draw a curve of all previous data,
     up to a certain point (self.resolution)"""
     self.vbo.bind()
     self.vbo.copy_data()
     glEnableClientState(GL_VERTEX_ARRAY)
     glVertexPointer(2, GL_FLOAT, 0, self.vbo)
     if self.buffer_full:
         if self.previous_index != self.size - 1:
             glPushMatrix()
             glTranslatef(-1 * (self.previous_index + 1), 0.0, 0.0)
             glDrawArrays(GL_LINE_STRIP, (self.previous_index + 1),
                          (self.size - self.previous_index - 1))
             glPopMatrix()
         glPushMatrix()
         glTranslatef(self.size - self.previous_index - 1, 0.0, 0.0)
         glDrawArrays(GL_LINE_STRIP, 0, (self.previous_index + 1))
         glPopMatrix()
     else:
         glDrawArrays(GL_LINE_STRIP, 0, (self.previous_index + 1))
     glDisableClientState(GL_VERTEX_ARRAY)
     self.vbo.unbind()
Exemplo n.º 15
0
def drawLineCube(color, pos, radius):
    vtIndices = [0,1,2,3, 0,4,5,1, 5,4,7,6, 6,7,3,2]
    glEnableClientState(GL_VERTEX_ARRAY)
    #bruce 051117 revised this
    glVertexPointer(3, GL_FLOAT, 0, drawing_globals.flatCubeVertices)
        #grantham 20051213 observations, reported/paraphrased by bruce 051215:
        # - should verify PyOpenGL turns Python float (i.e. C double) into C
        #     float for OpenGL's GL_FLOAT array element type.
        # - note that GPUs are optimized for DrawElements types GL_UNSIGNED_INT
        #     and GL_UNSIGNED_SHORT.
    glDisable(GL_LIGHTING)
    glColor3fv(color)
    glPushMatrix()
    glTranslatef(pos[0], pos[1], pos[2])
    glScale(radius,radius,radius)
    glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices)
    #glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices[4])
    #glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices[8])
    #glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices[12])
    glPopMatrix()
    glEnable(GL_LIGHTING)
    glDisableClientState(GL_VERTEX_ARRAY)
    return    
Exemplo n.º 16
0
def drawLineCube(color, pos, radius):
    vtIndices = [0, 1, 2, 3, 0, 4, 5, 1, 5, 4, 7, 6, 6, 7, 3, 2]
    glEnableClientState(GL_VERTEX_ARRAY)
    #bruce 051117 revised this
    glVertexPointer(3, GL_FLOAT, 0, drawing_globals.flatCubeVertices)
    #grantham 20051213 observations, reported/paraphrased by bruce 051215:
    # - should verify PyOpenGL turns Python float (i.e. C double) into C
    #     float for OpenGL's GL_FLOAT array element type.
    # - note that GPUs are optimized for DrawElements types GL_UNSIGNED_INT
    #     and GL_UNSIGNED_SHORT.
    glDisable(GL_LIGHTING)
    glColor3fv(color)
    glPushMatrix()
    glTranslatef(pos[0], pos[1], pos[2])
    glScale(radius, radius, radius)
    glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices)
    #glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices[4])
    #glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices[8])
    #glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices[12])
    glPopMatrix()
    glEnable(GL_LIGHTING)
    glDisableClientState(GL_VERTEX_ARRAY)
    return
Exemplo n.º 17
0
    def draw_mesh(m, lighting_on):

        # Supply vertices
        glEnableClientState(GL_VERTEX_ARRAY)
        m.vbo['v'].bind()
        glVertexPointer(3, GL_FLOAT, 0, m.vbo['v'])
        m.vbo['v'].unbind()

        # Supply normals
        if 'vn' in m.vbo.keys():
            glEnableClientState(GL_NORMAL_ARRAY)
            m.vbo['vn'].bind()
            glNormalPointer(GL_FLOAT, 0, m.vbo['vn'])
            m.vbo['vn'].unbind()
        else:
            glDisableClientState(GL_NORMAL_ARRAY)

        # Supply colors
        if 'vc' in m.vbo.keys():
            glEnableClientState(GL_COLOR_ARRAY)
            m.vbo['vc'].bind()
            glColorPointer(3, GL_FLOAT, 0, m.vbo['vc'])
            m.vbo['vc'].unbind()
        else:
            glDisableClientState(GL_COLOR_ARRAY)

        if ('vt' in m.vbo.keys()) and hasattr(m, 'textureID'):
            glEnable(GL_TEXTURE_2D)
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)
            glBindTexture(GL_TEXTURE_2D, m.textureID)

            glEnableClientState(GL_TEXTURE_COORD_ARRAY)
            m.vbo['vt'].bind()
            glTexCoordPointer(2, GL_FLOAT, 0, m.vbo['vt'])
            m.vbo['vt'].unbind()
        else:
            glDisable(GL_TEXTURE_2D)
            glDisableClientState(GL_TEXTURE_COORD_ARRAY)

        # Draw
        if len(m.f) > 0:
            # ie if it is triangulated
            if lighting_on:
                glEnable(GL_LIGHTING)
            else:
                glDisable(GL_LIGHTING)
            glDrawElementsui(GL_TRIANGLES, np.arange(m.f.size,
                                                     dtype=np.uint32))
        else:
            # not triangulated, so disable lighting
            glDisable(GL_LIGHTING)
            glPointSize(2)
            glDrawElementsui(GL_POINTS, np.arange(len(m.v), dtype=np.uint32))
        if hasattr(m, 'v_to_text'):

            glEnable(GL_TEXTURE_2D)
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                            GL_LINEAR_MIPMAP_LINEAR)
            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)

            # glEnable(GL_TEXTURE_GEN_S)
            # glEnable(GL_TEXTURE_GEN_T)
            # glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR)
            # glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR)

            bgcolor = np.array(glGetDoublev(GL_COLOR_CLEAR_VALUE))
            fgcolor = 1. - bgcolor

            from .lines import Lines
            sc = float(np.max(np.max(m.v, axis=0) - np.min(m.v, axis=0))) / 10.

            cur_mtx = np.linalg.pinv(glGetFloatv(GL_MODELVIEW_MATRIX).T)
            xdir = cur_mtx[:3, 0]
            ydir = cur_mtx[:3, 1]

            glEnable(GL_LINE_SMOOTH)
            glEnable(GL_BLEND)
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

            for vidx, text in m.v_to_text.items():
                pos0 = m.v[vidx].copy()
                pos1 = m.v[vidx].copy()
                if hasattr(m, 'vn'):
                    pos1 += m.vn[vidx] * sc
                glLineWidth(5.0)
                ln = Lines(v=np.vstack((pos0, pos1)), e=np.array([[0, 1]]))
                glEnable(GL_LIGHTING)
                glColor3f(1. - 0.8, 1. - 0.8, 1. - 1.00)
                MeshViewerSingle.draw_lines(ln)

                glDisable(GL_LIGHTING)

                texture_id = get_textureid_with_text(text, bgcolor, fgcolor)
                glBindTexture(GL_TEXTURE_2D, texture_id)

                glPushMatrix()
                glTranslatef(pos1[0], pos1[1], pos1[2])

                dx = xdir * .10
                dy = ydir * .10
                if False:
                    glBegin(GL_QUADS)

                    glTexCoord2f(1., 0.)
                    glVertex3f(*(+dx + dy))

                    glTexCoord2f(1., 1.)
                    glVertex3f(*(+dx - dy))

                    glTexCoord2f(0., 1.)
                    glVertex3f(*(-dx - dy))

                    glTexCoord2f(0., 0.)
                    glVertex3f(*(-dx + dy))

                    # gluSphere(quadratic,0.05,32,32)
                    glEnd()
                else:
                    glBegin(GL_POLYGON)

                    for r in np.arange(0, np.pi * 2., .01):
                        glTexCoord2f(np.cos(r) / 2. + .5, np.sin(r) / 2. + .5)
                        glVertex3f(*(dx * np.cos(r) + -dy * np.sin(r)))

                    glEnd()
                glPopMatrix()
Exemplo n.º 18
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
Exemplo n.º 19
0
def drawHeightfield(color,
                    w,
                    h,
                    textureReady,
                    opacity,
                    SOLID=False,
                    pickCheckOnly=False,
                    hf=None):
    """
    Draw a heighfield using vertex and normal arrays. Optionally, it could be
    texuture mapped.

    @pickCheckOnly This is used to draw the geometry only, used for OpenGL pick
      selection purpose.
    """

    from OpenGL.GL import glTexEnvf
    from OpenGL.GL import GL_TEXTURE_ENV
    from OpenGL.GL import GL_TEXTURE_ENV_MODE
    from OpenGL.GL import GL_MODULATE
    from OpenGL.GL import glVertexPointer
    from OpenGL.GL import glNormalPointer
    from OpenGL.GL import glTexCoordPointer
    from OpenGL.GL import glDrawArrays
    from OpenGL.GL import glEnableClientState
    from OpenGL.GL import GL_VERTEX_ARRAY
    from OpenGL.GL import GL_NORMAL_ARRAY
    from OpenGL.GL import GL_TEXTURE_COORD_ARRAY

    glEnable(GL_COLOR_MATERIAL)
    glEnable(GL_LIGHTING)

    ### glColor4fv(list(color) + [opacity])
    ### glColor3fv(list(color))
    glColor3f(1.0, 1.0, 1.0)

    glPushMatrix()
    glScalef(w, h, 1.0)

    if SOLID:
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
    else:
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)

    glDisable(GL_CULL_FACE)

    if not pickCheckOnly:
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

        if textureReady:
            glEnable(GL_TEXTURE_2D)
            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)

    glEnableClientState(GL_VERTEX_ARRAY)
    glEnableClientState(GL_NORMAL_ARRAY)
    glEnableClientState(GL_TEXTURE_COORD_ARRAY)

    for tstrip_vert, tstrip_norm, tstrip_tex in hf:
        glVertexPointer(3, GL_FLOAT, 0, tstrip_vert)
        glNormalPointer(GL_FLOAT, 0, tstrip_norm)
        glTexCoordPointer(2, GL_FLOAT, 0, tstrip_tex)
        glDrawArrays(GL_TRIANGLE_STRIP, 0, len(tstrip_vert))

    glDisableClientState(GL_VERTEX_ARRAY)
    glDisableClientState(GL_NORMAL_ARRAY)
    glDisableClientState(GL_TEXTURE_COORD_ARRAY)

    glDisable(GL_COLOR_MATERIAL)

    if not pickCheckOnly:
        if textureReady:
            glDisable(GL_TEXTURE_2D)

        glDepthMask(GL_TRUE)

    glEnable(GL_CULL_FACE)
    if not SOLID:
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)

    glPopMatrix()
    glEnable(GL_LIGHTING)

    return
Exemplo n.º 20
0
def drawsphere_worker(params):
    """
    Draw a sphere.  Receive parameters through a sequence so that this function
    and its parameters can be passed to another function for deferment.  Right
    now this is only ColorSorter.schedule (see below)
    """

    (pos, radius, detailLevel) = params

    vboLevel = drawing_globals.use_drawing_variant

    glPushMatrix()
    glTranslatef(pos[0], pos[1], pos[2])
    glScale(radius,radius,radius)

    if vboLevel == 0:
        glCallList(drawing_globals.sphereList[detailLevel])
    else:                               # Array variants.
        glEnableClientState(GL_VERTEX_ARRAY)
        glEnableClientState(GL_NORMAL_ARRAY)

        size = len(drawing_globals.sphereArrays[detailLevel])
        GLIndexType = drawing_globals.sphereGLIndexTypes[detailLevel]

        if vboLevel == 1:               # DrawArrays from CPU RAM.
            verts = drawing_globals.sphereCArrays[detailLevel]
            glVertexPointer(3, GL_FLOAT, 0, verts)
            glNormalPointer(GL_FLOAT, 0, verts)
            glDrawArrays(GL_TRIANGLE_STRIP, 0, size)

        elif vboLevel == 2:             # DrawElements from CPU RAM.
            verts = drawing_globals.sphereCElements[detailLevel][1]
            glVertexPointer(3, GL_FLOAT, 0, verts)
            glNormalPointer(GL_FLOAT, 0, verts)
            # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug.
            index = drawing_globals.sphereElements[detailLevel][0]
            glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index)

        elif vboLevel == 3:             # DrawArrays from graphics RAM VBO.
            vbo = drawing_globals.sphereArrayVBOs[detailLevel]
            vbo.bind()
            glVertexPointer(3, GL_FLOAT, 0, None)
            glNormalPointer(GL_FLOAT, 0, None)
            glDrawArrays(GL_TRIANGLE_STRIP, 0, vbo.size)
            vbo.unbind()

        elif vboLevel == 4: # DrawElements from index in CPU RAM, verts in VBO.
            vbo = drawing_globals.sphereElementVBOs[detailLevel][1]
            vbo.bind()              # Vertex and normal data comes from the vbo.
            glVertexPointer(3, GL_FLOAT, 0, None)
            glNormalPointer(GL_FLOAT, 0, None)
            # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug.
            index = drawing_globals.sphereElements[detailLevel][0]
            glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index)
            vbo.unbind()

        elif vboLevel == 5: # VBO/IBO buffered DrawElements from graphics RAM.
            (ibo, vbo) = drawing_globals.sphereElementVBOs[detailLevel]
            vbo.bind()              # Vertex and normal data comes from the vbo.
            glVertexPointer(3, GL_FLOAT, 0, None)
            glNormalPointer(GL_FLOAT, 0, None)
            ibo.bind()              # Index data comes from the ibo.
            glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, None)
            vbo.unbind()
            ibo.unbind()
            pass

        glDisableClientState(GL_VERTEX_ARRAY)
        glDisableClientState(GL_NORMAL_ARRAY)
        pass

    glPopMatrix()
    return
Exemplo n.º 21
0
def drawHeightfield(color,
                    w,
                    h,
                    textureReady,
                    opacity,
                    SOLID=False,
                    pickCheckOnly=False,
                    hf=None):
    """
    Draw a heighfield using vertex and normal arrays. Optionally, it could be
    texture mapped.

    @pickCheckOnly This is used to draw the geometry only, used for OpenGL pick
      selection purpose.
    """

    if not hf:
        # Return if heightfield is not provided
        return

    glEnable(GL_COLOR_MATERIAL)
    glEnable(GL_LIGHTING)

    # Don't use opacity, otherwise the heighfield polygons should be sorted
    # - something to implement later...
    ## glColor3v(list(color))

    if textureReady:
        # For texturing, use white color (to be modulated by the texture)
        glColor3f(1, 1, 1)
    else:
        glColor3fv(list(color))

    glPushMatrix()
    glScalef(w, h, 1.0)

    if SOLID:
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
    else:
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)

    glDisable(GL_CULL_FACE)

    if not pickCheckOnly:
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

        if textureReady:
            glEnable(GL_TEXTURE_2D)
            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)

    glEnableClientState(GL_VERTEX_ARRAY)
    glEnableClientState(GL_NORMAL_ARRAY)
    glEnableClientState(GL_TEXTURE_COORD_ARRAY)

    for tstrip_vert, tstrip_norm, tstrip_tex in hf:
        glVertexPointer(3, GL_FLOAT, 0, tstrip_vert)
        glNormalPointer(GL_FLOAT, 0, tstrip_norm)
        glTexCoordPointer(2, GL_FLOAT, 0, tstrip_tex)
        glDrawArrays(GL_TRIANGLE_STRIP, 0, len(tstrip_vert))

    glDisableClientState(GL_VERTEX_ARRAY)
    glDisableClientState(GL_NORMAL_ARRAY)
    glDisableClientState(GL_TEXTURE_COORD_ARRAY)

    glDisable(GL_COLOR_MATERIAL)

    if not pickCheckOnly:
        if textureReady:
            glDisable(GL_TEXTURE_2D)

        glDepthMask(GL_TRUE)

    glEnable(GL_CULL_FACE)
    if not SOLID:
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)

    glPopMatrix()
    glEnable(GL_LIGHTING)

    return
Exemplo n.º 22
0
def drawsphere_worker(params):
    """
    Draw a sphere.  Receive parameters through a sequence so that this function
    and its parameters can be passed to another function for deferment.  Right
    now this is only ColorSorter.schedule (see below)
    """

    (pos, radius, detailLevel, n) = params
    del n

    # KLUGE: the detailLevel can be a tuple, (vboLevel, detailLevel).
    # The only for reason for this is that drawsphere_worker is used
    # in ProteinChunks (I added a comment there saying why that's bad)
    # and I don't have time to clean that up now. Ideally, vboLevel
    # would just be another parameter, or we'd combine it with detailLevel
    # in some other way not constrained by backward compatibility of
    # this internal worker function's API. [bruce 090304]
    if type(detailLevel) == type(()):
        (vboLevel, detailLevel) = detailLevel

    ## vboLevel = drawing_globals.use_drawing_variant

    glPushMatrix()
    glTranslatef(pos[0], pos[1], pos[2])
    glScale(radius, radius, radius)

    if vboLevel == 0:  # OpenGL 1.0 - glBegin/glEnd tri-strips vertex-by-vertex.
        glCallList(drawing_globals.sphereList[detailLevel])

    else:  # OpenGL 1.1/1.5 - Array/VBO/IBO variants.
        glEnableClientState(GL_VERTEX_ARRAY)
        glEnableClientState(GL_NORMAL_ARRAY)

        size = len(drawing_globals.sphereArrays[detailLevel])
        GLIndexType = drawing_globals.sphereGLIndexTypes[detailLevel]

        if vboLevel == 1:  # DrawArrays from CPU RAM.
            verts = drawing_globals.sphereCArrays[detailLevel]
            glVertexPointer(3, GL_FLOAT, 0, verts)
            glNormalPointer(GL_FLOAT, 0, verts)
            glDrawArrays(GL_TRIANGLE_STRIP, 0, size)

        elif vboLevel == 2:  # DrawElements from CPU RAM.
            verts = drawing_globals.sphereCElements[detailLevel][1]
            glVertexPointer(3, GL_FLOAT, 0, verts)
            glNormalPointer(GL_FLOAT, 0, verts)
            # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug.
            index = drawing_globals.sphereElements[detailLevel][0]
            glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index)

        elif vboLevel == 3:  # DrawArrays from graphics RAM VBO.
            vbo = drawing_globals.sphereArrayVBOs[detailLevel]
            vbo.bind()
            glVertexPointer(3, GL_FLOAT, 0, None)
            glNormalPointer(GL_FLOAT, 0, None)
            glDrawArrays(GL_TRIANGLE_STRIP, 0, vbo.size)
            vbo.unbind()

        elif vboLevel == 4:  # DrawElements from index in CPU RAM, verts in VBO.
            vbo = drawing_globals.sphereElementVBOs[detailLevel][1]
            vbo.bind()  # Vertex and normal data comes from the vbo.
            glVertexPointer(3, GL_FLOAT, 0, None)
            glNormalPointer(GL_FLOAT, 0, None)
            # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug.
            index = drawing_globals.sphereElements[detailLevel][0]
            glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index)
            vbo.unbind()

        elif vboLevel == 5:  # VBO/IBO buffered DrawElements from graphics RAM.
            (ibo, vbo) = drawing_globals.sphereElementVBOs[detailLevel]
            vbo.bind()  # Vertex and normal data comes from the vbo.
            glVertexPointer(3, GL_FLOAT, 0, None)
            glNormalPointer(GL_FLOAT, 0, None)
            ibo.bind()  # Index data comes from the ibo.
            glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, None)
            vbo.unbind()
            ibo.unbind()
            pass

        glDisableClientState(GL_VERTEX_ARRAY)
        glDisableClientState(GL_NORMAL_ARRAY)
        pass

    glPopMatrix()
    return
Exemplo n.º 23
0
def drawsphere_worker(params):
    """
    Draw a sphere.  Receive parameters through a sequence so that this function
    and its parameters can be passed to another function for deferment.  Right
    now this is only ColorSorter.schedule (see below)
    """

    (pos, radius, detailLevel) = params

    vboLevel = drawing_globals.use_drawing_variant

    glPushMatrix()
    glTranslatef(pos[0], pos[1], pos[2])
    glScale(radius, radius, radius)

    if vboLevel == 0:
        glCallList(drawing_globals.sphereList[detailLevel])
    else:  # Array variants.
        glEnableClientState(GL_VERTEX_ARRAY)
        glEnableClientState(GL_NORMAL_ARRAY)

        size = len(drawing_globals.sphereArrays[detailLevel])
        GLIndexType = drawing_globals.sphereGLIndexTypes[detailLevel]

        if vboLevel == 1:  # DrawArrays from CPU RAM.
            verts = drawing_globals.sphereCArrays[detailLevel]
            glVertexPointer(3, GL_FLOAT, 0, verts)
            glNormalPointer(GL_FLOAT, 0, verts)
            glDrawArrays(GL_TRIANGLE_STRIP, 0, size)

        elif vboLevel == 2:  # DrawElements from CPU RAM.
            verts = drawing_globals.sphereCElements[detailLevel][1]
            glVertexPointer(3, GL_FLOAT, 0, verts)
            glNormalPointer(GL_FLOAT, 0, verts)
            # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug.
            index = drawing_globals.sphereElements[detailLevel][0]
            glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index)

        elif vboLevel == 3:  # DrawArrays from graphics RAM VBO.
            vbo = drawing_globals.sphereArrayVBOs[detailLevel]
            vbo.bind()
            glVertexPointer(3, GL_FLOAT, 0, None)
            glNormalPointer(GL_FLOAT, 0, None)
            glDrawArrays(GL_TRIANGLE_STRIP, 0, vbo.size)
            vbo.unbind()

        elif vboLevel == 4:  # DrawElements from index in CPU RAM, verts in VBO.
            vbo = drawing_globals.sphereElementVBOs[detailLevel][1]
            vbo.bind()  # Vertex and normal data comes from the vbo.
            glVertexPointer(3, GL_FLOAT, 0, None)
            glNormalPointer(GL_FLOAT, 0, None)
            # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug.
            index = drawing_globals.sphereElements[detailLevel][0]
            glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index)
            vbo.unbind()

        elif vboLevel == 5:  # VBO/IBO buffered DrawElements from graphics RAM.
            (ibo, vbo) = drawing_globals.sphereElementVBOs[detailLevel]
            vbo.bind()  # Vertex and normal data comes from the vbo.
            glVertexPointer(3, GL_FLOAT, 0, None)
            glNormalPointer(GL_FLOAT, 0, None)
            ibo.bind()  # Index data comes from the ibo.
            glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, None)
            vbo.unbind()
            ibo.unbind()
            pass

        glDisableClientState(GL_VERTEX_ARRAY)
        glDisableClientState(GL_NORMAL_ARRAY)
        pass

    glPopMatrix()
    return
Exemplo n.º 24
0
def drawHeightfield(color, w, h, textureReady, opacity,
                    SOLID=False, pickCheckOnly=False, hf=None):
    """
    Draw a heighfield using vertex and normal arrays. Optionally, it could be
    texuture mapped.

    @pickCheckOnly This is used to draw the geometry only, used for OpenGL pick
      selection purpose.
    """        

    from OpenGL.GL import glTexEnvf
    from OpenGL.GL import GL_TEXTURE_ENV
    from OpenGL.GL import GL_TEXTURE_ENV_MODE
    from OpenGL.GL import GL_MODULATE
    from OpenGL.GL import glVertexPointer
    from OpenGL.GL import glNormalPointer
    from OpenGL.GL import glTexCoordPointer
    from OpenGL.GL import glDrawArrays
    from OpenGL.GL import glEnableClientState
    from OpenGL.GL import GL_VERTEX_ARRAY
    from OpenGL.GL import GL_NORMAL_ARRAY
    from OpenGL.GL import GL_TEXTURE_COORD_ARRAY
        
    glEnable(GL_COLOR_MATERIAL)
    glEnable(GL_LIGHTING)

    ### glColor4fv(list(color) + [opacity])
    ### glColor3fv(list(color))
    glColor3f(1.0, 1.0, 1.0)
    
    glPushMatrix()
    glScalef(w, h, 1.0)

    if SOLID:
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
    else:
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
    
    glDisable(GL_CULL_FACE) 
    
    if not pickCheckOnly:
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

        if textureReady:
            glEnable(GL_TEXTURE_2D)  
            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)

    glEnableClientState(GL_VERTEX_ARRAY)
    glEnableClientState(GL_NORMAL_ARRAY)
    glEnableClientState(GL_TEXTURE_COORD_ARRAY)

    for tstrip_vert, tstrip_norm, tstrip_tex in hf:
        glVertexPointer(3, GL_FLOAT, 0, tstrip_vert)
        glNormalPointer(GL_FLOAT, 0, tstrip_norm)
        glTexCoordPointer(2, GL_FLOAT, 0, tstrip_tex)
        glDrawArrays(GL_TRIANGLE_STRIP, 0, len(tstrip_vert))
        
    glDisableClientState(GL_VERTEX_ARRAY)
    glDisableClientState(GL_NORMAL_ARRAY)
    glDisableClientState(GL_TEXTURE_COORD_ARRAY)

    glDisable(GL_COLOR_MATERIAL)
    
    if not pickCheckOnly:
        if textureReady:
            glDisable(GL_TEXTURE_2D)

        glDepthMask(GL_TRUE) 

    glEnable(GL_CULL_FACE)
    if not SOLID:
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)

    glPopMatrix()
    glEnable(GL_LIGHTING)
    
    return
Exemplo n.º 25
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
Exemplo n.º 26
0
def drawHeightfield(color, w, h, textureReady, opacity,
                    SOLID = False, pickCheckOnly = False, hf = None):
    """
    Draw a heighfield using vertex and normal arrays. Optionally, it could be
    texture mapped.

    @pickCheckOnly This is used to draw the geometry only, used for OpenGL pick
      selection purpose.
    """        

    if not hf:
        # Return if heightfield is not provided
        return
    
    glEnable(GL_COLOR_MATERIAL)
    glEnable(GL_LIGHTING)

    # Don't use opacity, otherwise the heighfield polygons should be sorted
    # - something to implement later...
    ## glColor3v(list(color))
    
    if textureReady:
        # For texturing, use white color (to be modulated by the texture)
        glColor3f(1,1,1)
    else:
        glColor3fv(list(color))
        
    glPushMatrix()
    glScalef(w, h, 1.0)

    if SOLID:
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
    else:
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
    
    glDisable(GL_CULL_FACE) 
    
    if not pickCheckOnly:
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

        if textureReady:
            glEnable(GL_TEXTURE_2D)  
            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)

    glEnableClientState(GL_VERTEX_ARRAY)
    glEnableClientState(GL_NORMAL_ARRAY)
    glEnableClientState(GL_TEXTURE_COORD_ARRAY)

    for tstrip_vert, tstrip_norm, tstrip_tex in hf:
        glVertexPointer(3, GL_FLOAT, 0, tstrip_vert)
        glNormalPointer(GL_FLOAT, 0, tstrip_norm)
        glTexCoordPointer(2, GL_FLOAT, 0, tstrip_tex)
        glDrawArrays(GL_TRIANGLE_STRIP, 0, len(tstrip_vert))
        
    glDisableClientState(GL_VERTEX_ARRAY)
    glDisableClientState(GL_NORMAL_ARRAY)
    glDisableClientState(GL_TEXTURE_COORD_ARRAY)

    glDisable(GL_COLOR_MATERIAL)
    
    if not pickCheckOnly:
        if textureReady:
            glDisable(GL_TEXTURE_2D)

        glDepthMask(GL_TRUE) 

    glEnable(GL_CULL_FACE)
    if not SOLID:
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)

    glPopMatrix()
    glEnable(GL_LIGHTING)
    
    return
Exemplo n.º 27
0
    def draw(self, drawIndex = None, highlighted = False, selected = False,
             patterning = True, highlight_color = None, opacity = 1.0):
        """
        Draw the buffered geometry, binding vertex attribute values for the
        shaders.

        If no drawIndex is given, the whole array is drawn.
        """
        self.shader.setActive(True)                # Turn on the chosen shader.

        glEnableClientState(GL_VERTEX_ARRAY)

        self.shader.setupDraw(highlighted, selected, patterning,
                              highlight_color, opacity)

        # XXX No transform data until that is more implemented.
        ###self.shader.setupTransforms(self.transforms)
        # (note: the reason TransformControls work in their test case
        #  is due to a manual call of shader.setupTransforms. [bruce 090306 guess])
        if self.shader.get_TEXTURE_XFORMS():
            # Activate a texture unit for transforms.
            ## XXX Not necessary for custom shader programs.
            ##glEnable(GL_TEXTURE_2D)
            glBindTexture(GL_TEXTURE_2D, self.transform_memory)
                ### BUG: pylint warning:
                # Instance of 'GLPrimitiveBuffer' has no 'transform_memory' member
                #### REVIEW: should this be the attr of that name in GLShaderObject,
                # i.e. self.shader? I didn't fix it myself as a guess, in case other
                # uses of self also need fixing in the same way. [bruce 090304 comment]

            # Set the sampler to the handle for the active texture image (0).
            ## XXX Not needed if only one texture is being used?
            ##glActiveTexture(GL_TEXTURE0)
            ##glUniform1iARB(self.shader._uniform("transforms"), 0)
            pass

        glDisable(GL_CULL_FACE)

        # Draw the hunks.
        for hunkNumber in range(self.nHunks):
            # Bind the per-vertex generic attribute arrays for one hunk.
            for buffer in self.hunkBuffers:
                buffer.flush()      # Sync graphics card copies of the VBO data.
                buffer.bindHunk(hunkNumber)
                continue

            # Shared vertex coordinate data VBO: GL_ARRAY_BUFFER_ARB.
            self.hunkVertVBO.bind()
            glVertexPointer(3, GL_FLOAT, 0, None)

            # Shared vertex index data IBO: GL_ELEMENT_ARRAY_BUFFER_ARB
            self.hunkIndexIBO.bind()

            if drawIndex is not None:
                # Draw the selected primitives for this Hunk.
                index = drawIndex[hunkNumber]
                primcount = len(index)
                glMultiDrawElementsVBO(
                    self.drawingMode, self.C_indexBlockLengths,
                    GL_UNSIGNED_INT, index, primcount)
            else:
                # For initial testing, draw all primitives in the Hunk.
                if hunkNumber < self.nHunks-1:
                    nToDraw = HUNK_SIZE # Hunks before the last.
                else:
                    nToDraw = self.nPrims - (self.nHunks-1) * HUNK_SIZE
                    pass
                glDrawElements(self.drawingMode, self.nIndices * nToDraw,
                               GL_UNSIGNED_INT, None)
                pass
            continue

        self.shader.setActive(False)            # Turn off the chosen shader.
        glEnable(GL_CULL_FACE)

        self.hunkIndexIBO.unbind()   # Deactivate the ibo.
        self.hunkVertVBO.unbind()    # Deactivate all vbo's.

        glDisableClientState(GL_VERTEX_ARRAY)
        for buffer in self.hunkBuffers:
            buffer.unbindHunk()      # glDisableVertexAttribArrayARB.
            continue
        return
    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()
Exemplo n.º 29
0
def drawsphere_worker(params):
    """
    Draw a sphere.  Receive parameters through a sequence so that this function
    and its parameters can be passed to another function for deferment.  Right
    now this is only ColorSorter.schedule (see below)
    """

    (pos, radius, detailLevel, n) = params
    del n

    # KLUGE: the detailLevel can be a tuple, (vboLevel, detailLevel).
    # The only for reason for this is that drawsphere_worker is used
    # in ProteinChunks (I added a comment there saying why that's bad)
    # and I don't have time to clean that up now. Ideally, vboLevel
    # would just be another parameter, or we'd combine it with detailLevel
    # in some other way not constrained by backward compatibility of
    # this internal worker function's API. [bruce 090304]
    if type(detailLevel) == type(()):
        (vboLevel, detailLevel) = detailLevel

    ## vboLevel = drawing_globals.use_drawing_variant

    glPushMatrix()
    glTranslatef(pos[0], pos[1], pos[2])
    glScale(radius,radius,radius)

    if vboLevel == 0:  # OpenGL 1.0 - glBegin/glEnd tri-strips vertex-by-vertex.
        glCallList(drawing_globals.sphereList[detailLevel])

    else:                             # OpenGL 1.1/1.5 - Array/VBO/IBO variants.
        glEnableClientState(GL_VERTEX_ARRAY)
        glEnableClientState(GL_NORMAL_ARRAY)

        size = len(drawing_globals.sphereArrays[detailLevel])
        GLIndexType = drawing_globals.sphereGLIndexTypes[detailLevel]

        if vboLevel == 1:               # DrawArrays from CPU RAM.
            verts = drawing_globals.sphereCArrays[detailLevel]
            glVertexPointer(3, GL_FLOAT, 0, verts)
            glNormalPointer(GL_FLOAT, 0, verts)
            glDrawArrays(GL_TRIANGLE_STRIP, 0, size)

        elif vboLevel == 2:             # DrawElements from CPU RAM.
            verts = drawing_globals.sphereCElements[detailLevel][1]
            glVertexPointer(3, GL_FLOAT, 0, verts)
            glNormalPointer(GL_FLOAT, 0, verts)
            # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug.
            index = drawing_globals.sphereElements[detailLevel][0]
            glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index)

        elif vboLevel == 3:             # DrawArrays from graphics RAM VBO.
            vbo = drawing_globals.sphereArrayVBOs[detailLevel]
            vbo.bind()
            glVertexPointer(3, GL_FLOAT, 0, None)
            glNormalPointer(GL_FLOAT, 0, None)
            glDrawArrays(GL_TRIANGLE_STRIP, 0, vbo.size)
            vbo.unbind()

        elif vboLevel == 4: # DrawElements from index in CPU RAM, verts in VBO.
            vbo = drawing_globals.sphereElementVBOs[detailLevel][1]
            vbo.bind()              # Vertex and normal data comes from the vbo.
            glVertexPointer(3, GL_FLOAT, 0, None)
            glNormalPointer(GL_FLOAT, 0, None)
            # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug.
            index = drawing_globals.sphereElements[detailLevel][0]
            glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index)
            vbo.unbind()

        elif vboLevel == 5: # VBO/IBO buffered DrawElements from graphics RAM.
            (ibo, vbo) = drawing_globals.sphereElementVBOs[detailLevel]
            vbo.bind()              # Vertex and normal data comes from the vbo.
            glVertexPointer(3, GL_FLOAT, 0, None)
            glNormalPointer(GL_FLOAT, 0, None)
            ibo.bind()              # Index data comes from the ibo.
            glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, None)
            vbo.unbind()
            ibo.unbind()
            pass

        glDisableClientState(GL_VERTEX_ARRAY)
        glDisableClientState(GL_NORMAL_ARRAY)
        pass

    glPopMatrix()
    return
Exemplo n.º 30
0
    def draw(self,
             drawIndex=None,
             highlighted=False,
             selected=False,
             patterning=True,
             highlight_color=None,
             opacity=1.0):
        """
        Draw the buffered geometry, binding vertex attribute values for the
        shaders.

        If no drawIndex is given, the whole array is drawn.
        """
        self.shader.setActive(True)  # Turn on the chosen shader.

        glEnableClientState(GL_VERTEX_ARRAY)

        self.shader.setupDraw(highlighted, selected, patterning,
                              highlight_color, opacity)

        # XXX No transform data until that is more implemented.
        ###self.shader.setupTransforms(self.transforms)
        # (note: the reason TransformControls work in their test case
        #  is due to a manual call of shader.setupTransforms. [bruce 090306 guess])
        if self.shader.get_TEXTURE_XFORMS():
            # Activate a texture unit for transforms.
            ## XXX Not necessary for custom shader programs.
            ##glEnable(GL_TEXTURE_2D)
            glBindTexture(GL_TEXTURE_2D, self.transform_memory)
            ### BUG: pylint warning:
            # Instance of 'GLPrimitiveBuffer' has no 'transform_memory' member
            #### REVIEW: should this be the attr of that name in GLShaderObject,
            # i.e. self.shader? I didn't fix it myself as a guess, in case other
            # uses of self also need fixing in the same way. [bruce 090304 comment]

            # Set the sampler to the handle for the active texture image (0).
            ## XXX Not needed if only one texture is being used?
            ##glActiveTexture(GL_TEXTURE0)
            ##glUniform1iARB(self.shader._uniform("transforms"), 0)
            pass

        glDisable(GL_CULL_FACE)

        # Draw the hunks.
        for hunkNumber in range(self.nHunks):
            # Bind the per-vertex generic attribute arrays for one hunk.
            for buffer in self.hunkBuffers:
                buffer.flush()  # Sync graphics card copies of the VBO data.
                buffer.bindHunk(hunkNumber)
                continue

            # Shared vertex coordinate data VBO: GL_ARRAY_BUFFER_ARB.
            self.hunkVertVBO.bind()
            glVertexPointer(3, GL_FLOAT, 0, None)

            # Shared vertex index data IBO: GL_ELEMENT_ARRAY_BUFFER_ARB
            self.hunkIndexIBO.bind()

            if drawIndex is not None:
                # Draw the selected primitives for this Hunk.
                index = drawIndex[hunkNumber]
                primcount = len(index)
                glMultiDrawElementsVBO(self.drawingMode,
                                       self.C_indexBlockLengths,
                                       GL_UNSIGNED_INT, index, primcount)
            else:
                # For initial testing, draw all primitives in the Hunk.
                if hunkNumber < self.nHunks - 1:
                    nToDraw = HUNK_SIZE  # Hunks before the last.
                else:
                    nToDraw = self.nPrims - (self.nHunks - 1) * HUNK_SIZE
                    pass
                glDrawElements(self.drawingMode, self.nIndices * nToDraw,
                               GL_UNSIGNED_INT, None)
                pass
            continue

        self.shader.setActive(False)  # Turn off the chosen shader.
        glEnable(GL_CULL_FACE)

        self.hunkIndexIBO.unbind()  # Deactivate the ibo.
        self.hunkVertVBO.unbind()  # Deactivate all vbo's.

        glDisableClientState(GL_VERTEX_ARRAY)
        for buffer in self.hunkBuffers:
            buffer.unbindHunk()  # glDisableVertexAttribArrayARB.
            continue
        return
Exemplo n.º 31
0
    def paint(self):
        self._applyGLOptions()

        if self.__antialiasing:
            glEnable(GL_LINE_SMOOTH)
            glEnable(GL_BLEND)
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
            glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
            glLineWidth(1.5)

        if self.draw_faces:
            # need face
            with self.shader_program:
                glEnableClientState(GL_VERTEX_ARRAY)

                glVertexPointerf(self.mesh.face_vertices)
                glColor4f(*self.face_color)

                glEnableClientState(GL_NORMAL_ARRAY)
                glNormalPointerf(self.mesh.face_normal_vectors)

                glDrawArrays(GL_TRIANGLES, 0,
                             np.product(self.mesh.face_vertices.shape[:-1]))

                glDisableClientState(GL_NORMAL_ARRAY)
                glDisableClientState(GL_VERTEX_ARRAY)
                glDisableClientState(GL_COLOR_ARRAY)

        if self.debug_face_normals:
            # Visualize the face normal vectors
            glEnableClientState(GL_VERTEX_ARRAY)

            N = self.mesh.face_vertices.shape[0] * 3
            v = np.concatenate([
                self.mesh.face_vertices,
                self.mesh.face_vertices + self.mesh.face_normal_vectors,
            ])
            e = np.array([np.arange(N), np.arange(N) + N]).T.flatten()

            glColor4f(1.0, 1.0, 0.0, 1.0)
            glVertexPointerf(v)
            glDrawElements(GL_LINES, e.shape[0], GL_UNSIGNED_INT, e)

            glDisableClientState(GL_VERTEX_ARRAY)
            glDisableClientState(GL_COLOR_ARRAY)

        if self.debug_face_edges:
            # visualize all face edges
            glEnableClientState(GL_VERTEX_ARRAY)
            glVertexPointerf(self.mesh.wireframe_vertices)

            glColor4f(1.0, 1.0, 0.0, 1.0)
            edges = self.mesh.face_edges.flatten()
            glDrawElements(GL_LINES, edges.shape[0], GL_UNSIGNED_INT, edges)

            glDisableClientState(GL_VERTEX_ARRAY)
            glDisableClientState(GL_COLOR_ARRAY)

        if self.draw_wireframe and self.mesh.has_wireframe:
            # draw a mesh wireframe which may or may not be identical to the face edges, depending on the mesh
            glEnableClientState(GL_VERTEX_ARRAY)
            glVertexPointerf(self.mesh.wireframe_vertices)
            glColor4f(0, 1, 0, 1)
            edges = self.mesh.wireframe_edges.flatten()
            glDrawElements(GL_LINES, edges.shape[0], GL_UNSIGNED_INT, edges)

            glDisableClientState(GL_VERTEX_ARRAY)
            glDisableClientState(GL_COLOR_ARRAY)