Changeset 8516:9fb2e5d5b758 in orange


Ignore:
Timestamp:
07/28/11 17:26:16 (3 years ago)
Author:
matejd <matejd@…>
Branch:
default
Convert:
39c7b5861f94492d989088dc1a02d38969dcfd56
Message:

Separated FBOs for tooltips and selections, now updated only when needed -> fluider rotations, no tooltips during rotations

File:
1 edited

Legend:

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

    r8507 r8516  
    461461        self.show_chassis = True 
    462462 
     463        self.tooltip_fbo_dirty = True 
     464        self.selection_fbo_dirty = True 
     465 
    463466    def __del__(self): 
    464467        # TODO: check if anything needs deleting 
     
    483486            attribute vec3 normal; 
    484487 
     488            const int MODE_NORMAL = 0; 
     489            const int MODE_TOOLTIP = 1; 
     490            const int MODE_SELECTION = 2; 
     491 
    485492            uniform bool use_2d_symbols; 
    486             uniform bool tooltip_mode; 
     493            uniform int mode; 
    487494            uniform float symbol_scale; 
    488495            uniform float transparency; 
     
    524531              pos += translation; 
    525532              pos *= scale; 
    526               vec4 off_pos = vec4(pos+offset_rotated, 1); 
     533              vec4 off_pos = vec4(pos, 1.); 
     534              off_pos = vec4(pos+offset_rotated, 1.); 
     535              if (mode != MODE_SELECTION) { 
     536                  // Converge symbols into points by ignoring offsets when 
     537                  // mode == MODE_SELECTION. 
     538                  //off_pos = vec4(pos+offset_rotated, 1.); 
     539              } 
    527540 
    528541              gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * off_pos; 
    529542 
    530               if (tooltip_mode) { 
     543              if (mode != MODE_NORMAL) { 
    531544                // We've packed example index into .w component of this vertex, 
    532545                // to output it to the screen, it has to be broken down into RGBA. 
     
    543556                // Calculate the amount of lighting this triangle receives (diffuse component only). 
    544557                vec3 light_direction = normalize(vec3(1., 1., 0.5)); 
    545                 float diffuse = max(0., dot(normalize((gl_ModelViewMatrix * vec4(normal, 0)).xyz), 
     558                float diffuse = max(0., dot(normalize((gl_ModelViewMatrix * vec4(normal, 0.)).xyz), 
    546559                                    light_direction)); 
    547560                var_color = vec4(color.rgb+diffuse*0.7, a); // Physically wrong, but looks better. 
     
    564577        self.symbol_shader.bindAttributeLocation('offset',   1) 
    565578        self.symbol_shader.bindAttributeLocation('color',    2) 
     579        self.symbol_shader.bindAttributeLocation('normal',   3) 
    566580 
    567581        if not self.symbol_shader.link(): 
     
    575589        self.symbol_shader_scale          = self.symbol_shader.uniformLocation('scale') 
    576590        self.symbol_shader_translation    = self.symbol_shader.uniformLocation('translation') 
    577         self.symbol_shader_tooltip_mode   = self.symbol_shader.uniformLocation('tooltip_mode') 
    578  
    579         # TODO: map mouse coordinates properly (instead of using larger FBO) 
     591        self.symbol_shader_mode           = self.symbol_shader.uniformLocation('mode') 
     592 
     593        # Create two FBOs (framebuffer objects): 
     594        # - one will be used together with stencil mask to find out which 
     595        #   examples have been selected (in an efficient way) 
     596        # - the other one will be used for tooltips (data rendered will have 
     597        #   larger screen coverage so it will be easily pointed at) 
    580598        format = QtOpenGL.QGLFramebufferObjectFormat() 
    581599        format.setAttachment(QtOpenGL.QGLFramebufferObject.CombinedDepthStencil) 
     600        self.selection_fbo = QtOpenGL.QGLFramebufferObject(1024, 1024, format) 
     601        if self.selection_fbo.isValid(): 
     602            print('Selection FBO created.') 
     603        else: 
     604            print('Failed to create selection FBO! Selections may be slow.') 
    582605        self.tooltip_fbo = QtOpenGL.QGLFramebufferObject(1024, 1024, format) 
    583606        if self.tooltip_fbo.isValid(): 
    584607            print('Tooltip FBO created.') 
    585608        else: 
    586             print('Failed to create tooltip FBO!') 
     609            print('Failed to create tooltip FBO! Tooltips disabled.') 
    587610 
    588611    def resizeGL(self, width, height): 
     
    622645        self.draw_grid_and_axes() 
    623646 
    624         glEnable(GL_DEPTH_TEST) 
    625         glEnable(GL_BLEND) 
    626         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 
    627  
    628647        for (cmd, params) in self.commands: 
    629648            if cmd == 'scatter': 
     
    632651 
    633652                self.symbol_shader.bind() 
    634                 self.symbol_shader.setUniformValue(self.symbol_shader_tooltip_mode,   False) 
     653                self.symbol_shader.setUniformValue(self.symbol_shader_mode,           0) 
    635654                self.symbol_shader.setUniformValue(self.symbol_shader_use_2d_symbols, self.use_2d_symbols) 
    636655                self.symbol_shader.setUniformValue(self.symbol_shader_view_edge,      float(self.view_cube_edge)) 
     
    640659                self.symbol_shader.setUniformValue(self.symbol_shader_translation,    *self.translation) 
    641660 
     661                glEnable(GL_DEPTH_TEST) 
     662                glEnable(GL_BLEND) 
     663                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 
    642664                glBindVertexArray(vao_id) 
    643665                glDrawArrays(GL_TRIANGLES, 0, vao_id.num_vertices) 
    644666                glBindVertexArray(0) 
    645                 #if self.use_2d_symbols: 
    646                 #    glLineWidth(1) 
    647                 #    glBindVertexArray(outline_vao_id) 
    648                 #    glDrawElements(GL_LINES, outline_vao_id.num_indices, GL_UNSIGNED_INT, c_void_p(0)) 
    649                 #    glBindVertexArray(0) 
    650667 
    651668                self.symbol_shader.release() 
     
    664681                callback() 
    665682 
     683        if self.selection_fbo_dirty: 
     684            self.selection_fbo.bind() 
     685            glClearColor(1, 1, 1, 1) 
     686            glClearStencil(0) 
     687            glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) 
     688            self.selection_fbo.release() 
     689 
     690        if self.tooltip_fbo_dirty: 
     691            self.tooltip_fbo.bind() 
     692            glClearColor(1, 1, 1, 1) 
     693            glClearDepth(1) 
     694            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 
     695            self.tooltip_fbo.release() 
     696 
    666697        for (cmd, params) in self.commands: 
    667698            if cmd == 'scatter': 
    668                 vao_id, (X, Y, Z), labels = params 
    669                 # Draw into color-picking buffer. Each example gets its own 
    670                 # unique color, carrying example's index. We also draw stencil mask 
    671                 # of selections, so we can quickly determine whether or not pixel 
    672                 # is selected (and therefore corresponding example). See 
    673                 # get_selection_indices for the other part of the algorithm (reading 
    674                 # and interpreting the FBO). 
    675                 self.tooltip_fbo.bind() 
    676                 glClearColor(1, 1, 1, 1) 
    677                 glClearStencil(0) 
    678                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) 
    679                 glDisable(GL_BLEND) 
    680                 glEnable(GL_DEPTH_TEST) 
    681  
    682                 self.symbol_shader.bind() 
    683                 # Most uniforms retain their values. 
    684                 self.symbol_shader.setUniformValue(self.symbol_shader_tooltip_mode, True) 
    685                 glBindVertexArray(vao_id) 
    686                 glDrawArrays(GL_TRIANGLES, 0, vao_id.num_vertices) 
    687                 glBindVertexArray(0) 
    688                 self.symbol_shader.release() 
    689  
    690                 if len(self.selections) > 0: 
     699                # Don't draw auxiliary info when rotating or selecting 
     700                # (but make sure these are drawn the very first frame 
     701                # plot returns to state idle because the user might want to 
     702                # get tooltips or has just selected a bunch of stuff). 
     703                vao_id, _, _ = params 
     704 
     705                if self.tooltip_fbo_dirty: 
     706                    print('tooltip fbo was dirty') 
     707                    # Draw data the same as to the screen, but with 
     708                    # disabled blending and enabled depth testing. 
     709                    self.tooltip_fbo.bind() 
     710                    glDisable(GL_BLEND) 
     711                    glEnable(GL_DEPTH_TEST) 
     712 
     713                    self.symbol_shader.bind() 
     714                    # Most uniforms retain their values. 
     715                    self.symbol_shader.setUniformValue(self.symbol_shader_mode, 1) 
     716                    glBindVertexArray(vao_id) 
     717                    glDrawArrays(GL_TRIANGLES, 0, vao_id.num_vertices) 
     718                    glBindVertexArray(0) 
     719                    self.symbol_shader.release() 
     720                    self.tooltip_fbo.release() 
     721                    self.tooltip_fbo_dirty = False 
     722 
     723                if self.selection_fbo_dirty: 
     724                    print('selection fbo was dirty') 
     725                    # Draw data as points instead, this means that examples farther away 
     726                    # will still have a good chance at being visible. 
     727                    self.selection_fbo.bind() 
     728                    self.symbol_shader.bind() 
     729                    self.symbol_shader.setUniformValue(self.symbol_shader_mode, 2) 
     730                    glDisable(GL_DEPTH_TEST) 
     731                    glDisable(GL_BLEND) 
     732                    glBindVertexArray(vao_id) 
     733                    glDrawArrays(GL_TRIANGLES, 0, vao_id.num_vertices) 
     734                    glBindVertexArray(0) 
     735                    self.symbol_shader.release() 
     736 
     737                    # Also draw stencil masks to the screen. No need to 
     738                    # write color or depth information as well, so we 
     739                    # disable those. 
    691740                    glMatrixMode(GL_PROJECTION) 
    692741                    glLoadIdentity() 
     
    695744                    glLoadIdentity() 
    696745 
    697                     glDisable(GL_DEPTH_TEST) 
    698746                    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE) 
    699747                    glDepthMask(GL_FALSE) 
     
    707755                    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) 
    708756                    glDepthMask(GL_TRUE) 
    709                     glEnable(GL_DEPTH_TEST) 
    710                 self.tooltip_fbo.release() 
     757                    self.selection_fbo.release() 
     758                    self.selection_fbo_dirty = False 
    711759 
    712760        glDisable(GL_DEPTH_TEST) 
     
    824872                if start_value <= key <= end_value: 
    825873                    position = start + (end-start)*((key-start_value) / length) 
     874                    glBegin(GL_LINES) 
     875                    glVertex3f(*(position)) 
     876                    glVertex3f(*(position+normal*0.2)) 
     877                    glEnd() 
    826878                    position += offset 
    827879                    self.renderText(position[0], 
     
    847899                position = start + (end-start)*((value-start_value) / float(end_value-start_value)) 
    848900                glBegin(GL_LINES) 
    849                 glVertex3f(*(position-normal*0.2)) 
     901                glVertex3f(*(position)) 
    850902                glVertex3f(*(position+normal*0.2)) 
    851903                glEnd() 
     
    10461098            triangles = get_symbol_data(symbol) 
    10471099            ss = size*0.08 
     1100            ai += 1 
    10481101            for v0, v1, v2, n0, n1, n2 in triangles: 
    10491102                vertices.extend([x,y,z, ai, ss*v0[0],ss*v0[1],ss*v0[2], r,g,b,a, n0[0],n0[1],n0[2], 
     
    11611214 
    11621215    def get_selection_indices(self): 
     1216        print('get_selection_indices') 
    11631217        if len(self.selections) == 0: 
    11641218            return [] 
    11651219 
     1220        self.selection_fbo_dirty = True 
     1221        self.updateGL() 
     1222 
    11661223        width, height = self.width(), self.height() 
    11671224        # TODO: check width < fbo.width 
    1168         self.tooltip_fbo.bind() 
     1225        self.selection_fbo.bind() 
    11691226        color_pixels = glReadPixels(0, 0, 
    11701227                                    width, height, 
     
    11751232                                      GL_STENCIL_INDEX, 
    11761233                                      GL_FLOAT) 
    1177         self.tooltip_fbo.release() 
     1234        self.selection_fbo.release() 
    11781235        stencils = struct.unpack('f'*width*height, stencil_pixels) 
    11791236        colors = struct.unpack('I'*width*height, color_pixels) 
     
    11831240                indices.add(color) 
    11841241 
     1242        print(indices) 
    11851243        # TODO: figure out what' causing incorrect values, filter them out 
    11861244        # for now 
     
    12701328        pos = event.pos() 
    12711329 
    1272         if self.mouseover_callback != None: 
     1330        if self.mouseover_callback != None and self.state == PlotState.IDLE: 
    12731331            # Use pixel-color-picking to read example index under mouse cursor. 
    12741332            self.tooltip_fbo.bind() 
     
    13551413        if not (self.state == PlotState.SELECTING and self.selection_type == SelectionType.POLYGON): 
    13561414            self.state = PlotState.IDLE 
     1415            self.tooltip_fbo_dirty = True 
    13571416            self.new_selection = None 
    13581417 
     
    13641423            delta = 1 + event.delta() / self.zoom_factor 
    13651424            self.scale *= delta 
     1425            self.tooltip_fbo_dirty = True 
    13661426            self.updateGL() 
    13671427 
     
    13981458        self.x_axis_title = self.y_axis_title = self.z_axis_title = '' 
    13991459        self.x_axis_map = self.y_axis_map = self.z_axis_map = None 
     1460        self.tooltip_fbo_dirty = True 
     1461        self.selection_fbo_dirty = True 
    14001462        self.updateGL() 
    14011463 
Note: See TracChangeset for help on using the changeset viewer.