Changeset 8458:7ca26fdff6fc in orange


Ignore:
Timestamp:
07/26/11 00:53:39 (3 years ago)
Author:
matejd <matejd@…>
Branch:
default
Convert:
72876b334243c215770083c5dad0a9bcdbf800e9
Message:

owplot3d: much faster selections using stencil buffer

File:
1 edited

Legend:

Unmodified
Added
Removed
  • orange/OrangeWidgets/plot/owplot3d.py

    r8457 r8458  
    6464import struct 
    6565import numpy 
     66#numpy.seterr(all='raise') # Raises exceptions on invalid numerical operations. 
    6667 
    6768try: 
     
    228229        draw_line(v2[0], v2[1], v2[0], v1[1]) 
    229230        draw_line(v2[0], v1[1], v1[0], v1[1]) 
     231 
     232    def draw_mask(self): 
     233        v1, v2 = self.first_vertex, self.current_vertex 
     234        glBegin(GL_QUADS) 
     235        glVertex2f(v1[0], v1[1]) 
     236        glVertex2f(v1[0], v2[1]) 
     237        glVertex2f(v2[0], v2[1]) 
     238        glVertex2f(v2[0], v1[1]) 
     239        glEnd() 
    230240 
    231241    def valid(self): 
     
    299309        v1, v2 = last_vertex, self.current_vertex 
    300310        draw_line(v1[0], v1[1], v2[0], v2[1]) 
     311 
     312    def draw_mask(self): 
     313        if len(self.vertices) < 3: 
     314            return 
     315        v0 = self.vertices[0] 
     316        for i in range(1, len(self.vertices)-1): 
     317            vi = self.vertices[i] 
     318            vj = self.vertices[i+1] 
     319            draw_triangle(v0[0], v0[1], 
     320                          vi[0], vi[1], 
     321                          vj[0], vj[1]) 
    301322 
    302323class OWPlot3D(QtOpenGL.QGLWidget): 
     
    495516 
    496517        # TODO: map mouse coordinates properly (instead of using larger FBO) 
    497         self.tooltip_fbo = QtOpenGL.QGLFramebufferObject(1024, 1024) 
     518        format = QtOpenGL.QGLFramebufferObjectFormat() 
     519        format.setAttachment(QtOpenGL.QGLFramebufferObject.CombinedDepthStencil) 
     520        self.tooltip_fbo = QtOpenGL.QGLFramebufferObject(1024, 1024, format) 
    498521        if self.tooltip_fbo.isValid(): 
    499522            print('Tooltip FBO created.') 
     
    581604            if cmd == 'scatter': 
    582605                vao_id, outline_vao_id, (X, Y, Z), labels = params 
    583                 # Draw into color-picking buffer. 
     606                # Draw into color-picking buffer. Each example gets its own 
     607                # unique color, carrying example's index. We also draw stencil mask 
     608                # of selections, so we can quickly determine whether or not pixel 
     609                # is selected (and therefore corresponding example). See 
     610                # get_selection_indices for the other part of the algorithm (reading 
     611                # and interpreting the FBO). 
    584612                self.tooltip_fbo.bind() 
     613                glClearColor(1, 1, 1, 1) 
     614                glClearStencil(0) 
     615                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) 
     616                glDisable(GL_BLEND) 
     617                glEnable(GL_DEPTH_TEST) 
     618 
    585619                self.symbol_shader.bind() 
    586620                # Most uniforms retain their values. 
    587621                self.symbol_shader.setUniformValue(self.symbol_shader_tooltip_mode, True) 
    588                 glClearColor(1, 1, 1, 1) 
    589                 glClear(GL_COLOR_BUFFER_BIT) 
    590                 glDisable(GL_BLEND) 
    591622                glBindVertexArray(vao_id) 
    592623                glDrawArrays(GL_TRIANGLES, 0, vao_id.num_vertices) 
    593624                glBindVertexArray(0) 
    594625                self.symbol_shader.release() 
     626 
     627                if len(self.selections) > 0: 
     628                    glMatrixMode(GL_PROJECTION) 
     629                    glLoadIdentity() 
     630                    glOrtho(0, self.width(), self.height(), 0, -1, 1) 
     631                    glMatrixMode(GL_MODELVIEW) 
     632                    glLoadIdentity() 
     633 
     634                    glDisable(GL_DEPTH_TEST) 
     635                    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE) 
     636                    glDepthMask(GL_FALSE) 
     637                    glStencilMask(0x01) 
     638                    glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT) 
     639                    glStencilFunc(GL_ALWAYS, 0, ~0) 
     640                    glEnable(GL_STENCIL_TEST) 
     641                    for selection in self.selections: 
     642                        selection.draw_mask() 
     643                    glDisable(GL_STENCIL_TEST) 
     644                    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) 
     645                    glDepthMask(GL_TRUE) 
     646                    glEnable(GL_DEPTH_TEST) 
    595647                self.tooltip_fbo.release() 
    596648 
     649        glDisable(GL_DEPTH_TEST) 
    597650        glDisable(GL_BLEND) 
    598651        if self.show_legend: 
     
    10491102 
    10501103    def transform_plot_to_data(self, vertex): 
    1051         vertex /= numpy.maximum([0., 0., 0.], self.scale + self.additional_scale) 
     1104        denominator = numpy.maximum([0., 0., 0.], self.scale + self.additional_scale) 
     1105        denominator = numpy.array(map(lambda v: v+0.00001 if v == 0. else v, denominator)) 
     1106        vertex /= denominator 
    10521107        vertex -= self.translation 
    10531108        vertex /= self.data_scale 
     
    10601115 
    10611116        width, height = self.width(), self.height() 
     1117        # TODO: check width < fbo.width 
     1118        self.tooltip_fbo.bind() 
     1119        color_pixels = glReadPixels(0, 0, 
     1120                                    width, height, 
     1121                                    GL_RGBA, 
     1122                                    GL_UNSIGNED_BYTE) 
     1123        stencil_pixels = glReadPixels(0, 0, 
     1124                                      width, height, 
     1125                                      GL_STENCIL_INDEX, 
     1126                                      GL_FLOAT) 
     1127        self.tooltip_fbo.release() 
     1128        stencils = struct.unpack('f'*width*height, stencil_pixels) 
     1129        colors = struct.unpack('I'*width*height, color_pixels) 
     1130        indices = set([]) 
     1131        for stencil, color in zip(stencils, colors): 
     1132            if stencil > 0. and color < 4294967295: 
     1133                indices.add(color) 
     1134 
     1135        # TODO: figure out what' causing incorrect values, filter them out 
     1136        # for now 
     1137        indices = [i for i in indices if i < len(self.commands[0][1][2][0])] 
     1138        return indices 
     1139 
    10621140 
    10631141        projection = QMatrix4x4() 
     
    11591237        if self.state == PlotState.IDLE: 
    11601238            if any(sel.contains(pos.x(), pos.y()) for sel in self.selections) or\ 
    1161                self.legend.contains(pos.x(), pos.y()): 
     1239               (self.show_legend and self.legend.contains(pos.x(), pos.y())): 
    11621240                self.setCursor(Qt.OpenHandCursor) 
    11631241            else: 
     
    12181296                if self.new_selection.valid(): 
    12191297                    self.selections.append(self.new_selection) 
     1298                    self.updateGL() 
    12201299                    self.selection_changed_callback() if self.selection_changed_callback else None 
    12211300        elif self.state == PlotState.ROTATING: 
Note: See TracChangeset for help on using the changeset viewer.