Changeset 8345:23f889b4e9b8 in orange


Ignore:
Timestamp:
07/03/11 00:39:57 (3 years ago)
Author:
matejd <matejd@…>
Branch:
default
Convert:
def791a6d3630a5b9cdb33d8fd212548d77c8851
Message:

Drawing now uses vertex buffers, work on axes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • orange/OrangeWidgets/OWGraph3D.py

    r8344 r8345  
    1010from OpenGL.GL import * 
    1111from OpenGL.GLU import * 
     12from OpenGL.arrays import ArrayDatatype 
    1213from ctypes import byref, c_char_p, c_int, create_string_buffer 
    1314import sys 
     
    1516from math import sin, cos 
    1617 
    17 # Import undefined functions. 
     18# Import undefined functions, override some wrappers. 
    1819try: 
    1920  from OpenGL import platform 
     
    3334glGetShaderiv = gl.glGetShaderiv 
    3435glDeleteShader = gl.glDeleteShader 
     36glDeleteProgram = gl.glDeleteProgram 
     37glGetShaderInfoLog = gl.glGetShaderInfoLog 
     38glGenVertexArrays = gl.glGenVertexArrays 
     39glBindVertexArray = gl.glBindVertexArray 
     40glGenBuffers = gl.glGenBuffers 
     41glDeleteBuffers = gl.glDeleteBuffers 
     42glVertexAttribPointer = gl.glVertexAttribPointer 
     43glEnableVertexAttribArray = gl.glEnableVertexAttribArray 
     44glVertexAttribPointer = gl.glVertexAttribPointer 
     45glEnableVertexAttribArray = gl.glEnableVertexAttribArray 
     46#glBegin = gl.glBegin 
     47#glEnd = gl.glEnd 
     48#glColor4f = gl.glColor4f 
     49#glColor3f = gl.glColor3f 
    3550 
    3651 
     
    4257    def __init__(self, parent=None): 
    4358        QtOpenGL.QGLWidget.__init__(self, QtOpenGL.QGLFormat(QtOpenGL.QGL.SampleBuffers), parent) 
     59 
    4460        self.commands = [] 
    4561        self.minx = self.miny = self.minz = 0 
     
    5773        self.move_factor = 100. 
    5874        self.mouse_pos = [100, 100] # TODO: get real mouse position, calculate camera, fix the initial jump 
    59         self.update_axes() 
     75        #self.update_axes() 
    6076 
    6177        self.axis_title_font = QFont('Helvetica', 10, QFont.Bold) 
     
    6581        self.z_axis_title = '' 
    6682 
     83        self.vertex_buffers = [] 
     84        self.vaos = [] 
     85 
     86    def __del__(self): 
     87      #for shader in self.shaders: 
     88      #  glDeleteShader(shader) 
     89 
     90      glDeleteProgram(self.color_shader) 
     91 
     92      #for vertex_buffer in self.vertex_buffers: 
     93      #  glDeleteBuffers(1, byref(vertex_buffer)) 
     94 
     95    def initializeGL(self): 
     96        self.update_axes() 
     97        glClearColor(1.0, 1.0, 1.0, 1.0) 
     98        glClearDepth(1.0) 
     99        glDepthFunc(GL_LESS) 
     100        glEnable(GL_DEPTH_TEST) 
     101        glShadeModel(GL_SMOOTH) 
     102        #glEnable(GL_BLEND) 
     103        #glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 
     104 
    67105        self.color_shader = glCreateProgram() 
    68106        vertex_shader = glCreateShader(GL_VERTEX_SHADER) 
    69107        fragment_shader = glCreateShader(GL_FRAGMENT_SHADER) 
     108        self.shaders = [vertex_shader, fragment_shader] 
    70109 
    71110        vertex_shader_source = ''' 
    72             attribute vec4 position; 
     111            attribute vec3 position; 
     112            attribute vec3 offset; 
    73113            attribute vec4 color; 
    74114 
     
    79119 
    80120            void main(void) { 
    81               gl_Position = projection * modelview * position; 
     121              //gl_Position = projection * modelview * position; 
     122 
     123              // Calculate inverse of rotations (in this case, inverse 
     124              // is actually just transpose), so that polygons face 
     125              // camera all the time. 
     126              mat3 invs; 
     127 
     128              invs[0][0] = gl_ModelViewMatrix[0][0]; 
     129              invs[0][1] = gl_ModelViewMatrix[1][0]; 
     130              invs[0][2] = gl_ModelViewMatrix[2][0]; 
     131 
     132              invs[1][0] = gl_ModelViewMatrix[0][1]; 
     133              invs[1][1] = gl_ModelViewMatrix[1][1]; 
     134              invs[1][2] = gl_ModelViewMatrix[2][1]; 
     135 
     136              invs[2][0] = gl_ModelViewMatrix[0][2]; 
     137              invs[2][1] = gl_ModelViewMatrix[1][2]; 
     138              invs[2][2] = gl_ModelViewMatrix[2][2]; 
     139 
     140              vec3 offset_rotated = invs * offset; 
     141              gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * vec4(position+offset_rotated, 1); 
    82142              var_color = color; 
    83143            } 
     
    105165 
    106166        length = c_int(-1) 
    107         for shader, source in zip([vertex_shader, fragment_shader], [vertex_shader_source, fragment_shader_source]): 
    108           glShaderSource(shader, 1, byref(source), byref(length)); 
     167        for shader, source in zip([vertex_shader, fragment_shader], 
     168                                  [vertex_shader_source, fragment_shader_source]): 
     169          glShaderSource(shader, 1, byref(source), byref(length)) 
    109170          glCompileShader(shader) 
    110171          status = c_int() 
    111172          glGetShaderiv(shader, GL_COMPILE_STATUS, byref(status)) 
    112173          if not status.value: 
    113             print('Failed to compile shader:') 
    114174            print_log(shader) 
    115175            glDeleteShader(shader) 
    116  
    117         print('Shaders compiled!') 
    118  
    119  
    120     def initializeGL(self): 
    121         glClearColor(1.0, 1.0, 1.0, 1.0) 
    122         glClearDepth(1.0) 
    123         glDepthFunc(GL_LESS) 
    124         glShadeModel(GL_SMOOTH) 
    125         glEnable(GL_BLEND) 
    126         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 
    127         glMatrixMode(GL_PROJECTION) 
    128         glLoadIdentity() 
    129         gluPerspective(30.0, float(self.width())/float(self.height()), 0.1, 100.0) 
    130         glMatrixMode(GL_MODELVIEW) 
    131         glLoadIdentity() 
    132   
     176            return 
     177          else: 
     178            glAttachShader(self.color_shader, shader) 
     179 
     180        glBindAttribLocation(self.color_shader, 0, 'position') 
     181        glBindAttribLocation(self.color_shader, 1, 'offset') 
     182        glBindAttribLocation(self.color_shader, 2, 'color') 
     183        glLinkProgram(self.color_shader) 
     184        # TODO: link status 
     185        print('Shaders compiled and linked!') 
    133186 
    134187    def resizeGL(self, width, height): 
    135188        glViewport(0, 0, width, height) 
    136189        glMatrixMode(GL_PROJECTION) 
     190 
     191    def paintGL(self): 
     192        glClearColor(1,1,1,1) 
     193        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 
     194        glMatrixMode(GL_PROJECTION) 
    137195        glLoadIdentity() 
    138         if height == 0: 
    139             aspect = 1 
    140         else: 
    141             aspect = float(width) / height 
     196        aspect = float(self.width()) / self.height() if self.height() != 0 else 1 
    142197        gluPerspective(30.0, aspect, 0.1, 100) 
    143198        glMatrixMode(GL_MODELVIEW) 
    144199        glLoadIdentity() 
    145  
    146  
    147     def paintGL(self): 
    148         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 
    149200        glMatrixMode(GL_MODELVIEW) 
    150201        glLoadIdentity() 
     
    159210        self.paint_axes() 
    160211 
    161         glEnable(GL_CULL_FACE) 
    162         glCullFace(GL_BACK) 
    163  
    164         for cmd, vertex_buffer in self.commands: 
    165           self.color_shader.bind() 
    166           self.color_shader.setAttributeBuffer(0, GL_FLOAT, 0,   4, 8*4) 
    167           self.color_shader.setAttributeBuffer(1, GL_FLOAT, 4*4, 4, 8*4) 
    168           self.color_shader.enableAttributeArray(0) 
    169           self.color_shader.enableAttributeArray(1) 
    170  
    171           glDrawArrays(GL_TRIANGLES, 0, vertex_buffer.num_vertices); 
    172  
    173           self.color_shader.disableAttributeArray(0) 
    174           self.color_shader.disableAttributeArray(1) 
    175           glUseProgram(0) 
    176  
    177212        glDisable(GL_CULL_FACE) 
     213 
     214        for cmd, vao in self.commands: 
     215          if cmd == 'scatter': 
     216            glUseProgram(self.color_shader) 
     217            glBindVertexArray(vao.value) 
     218            glDrawArrays(GL_TRIANGLES, 0, vao.num_vertices) 
     219            glBindVertexArray(0) 
     220            glUseProgram(0) 
    178221 
    179222    def set_x_axis_title(self, title): 
     
    206249        self.renderText(ac[0], ac[1]-0.2, ac[2]-0.2, self.x_axis_title, font=self.axis_title_font) 
    207250 
    208         glPushMatrix(); 
     251        glPushMatrix() 
    209252        ac = (self.y_axis[0] + self.y_axis[1]) / 2. 
    210253        glTranslatef(ac[0], ac[1]-0.2, ac[2]-0.2) 
    211         glRotatef(90, 1,0,0); 
     254        glRotatef(90, 1,0,0) 
    212255        #self.renderText(ac[0], ac[1]-0.2, ac[2]-0.2, self.YaxisTitle, font=self.axisTitleFont) 
    213256        self.renderText(0,0,0, self.y_axis_title, font=self.axis_title_font) 
    214         glPopMatrix(); 
     257        glPopMatrix() 
    215258 
    216259        ac = (self.z_axis[0] + self.z_axis[1]) / 2. 
    217260        self.renderText(ac[0], ac[1]-0.2, ac[2]-0.2, self.z_axis_title, font=self.axis_title_font) 
    218261 
    219         outwards = normalize(self.x_axis[0] - bb_center) 
    220         pos = self.x_axis[0] + outwards * 0.2 
    221         self.renderText(pos[0], pos[1], pos[2], '{0:.2}'.format(pos[0])) 
     262        glEnable(GL_TEXTURE_2D) 
     263        glBindTexture(GL_TEXTURE_2D, self.x_axis_frame.texture()) 
     264 
     265        glBegin(GL_QUADS) 
     266        glTexCoord2f(0,1) 
     267        glVertex3f(*self.x_axis[0]) 
     268        glTexCoord2f(1,1) 
     269        glVertex3f(*self.x_axis[1]) 
     270        glTexCoord2f(1,0) 
     271        glVertex3f(*(self.x_axis[1] + [0,0,-0.5])) 
     272        glTexCoord2f(0,0) 
     273        glVertex3f(*(self.x_axis[0] + [0,0,-0.5])) 
     274        glEnd() 
     275        glDisable(GL_TEXTURE_2D) 
    222276 
    223277        glColor4f(1,1,1,1) 
     
    256310 
    257311        def paint_plane(plane_quad): 
    258             #glColor4f(*colorPlane) 
    259             #paintQuad(planeQuad) 
    260312            glColor4f(*color_grid) 
    261313            paint_grid(plane_quad) 
    262314 
    263         def normal_from_points(P1, P2, P3): 
    264             V1 = P2 - P1 
    265             V2 = P3 - P1 
    266             return normalize(numpy.cross(V1, V2)) 
     315        def normal_from_points(p1, p2, p3): 
     316            v1 = p2 - p1 
     317            v2 = p3 - p1 
     318            return normalize(numpy.cross(v1, v2)) 
    267319  
    268320        def draw_grid_visible(plane_quad, ccw=False): 
     
    320372        self.axis_plane_xz_top = [E, F, B, A] 
    321373 
    322     def scatter(self, X, Y, Z, c="b", s=20, **kwargs): 
     374        if hasattr(self, 'x_axis_frame'): 
     375          return 
     376        self.x_axis_frame = QtOpenGL.QGLFramebufferObject(256, 64) 
     377        print(self.x_axis_frame.isBound()) 
     378        self.x_axis_frame.bind() 
     379        print(self.x_axis_frame.isValid()) 
     380        glMatrixMode(GL_PROJECTION) 
     381        glLoadIdentity() 
     382        glOrtho(0,1, 0,1, -1,1) 
     383        glMatrixMode(GL_MODELVIEW) 
     384        glLoadIdentity() 
     385        glClearColor(1,0,0,1) 
     386        glClear(GL_COLOR_BUFFER_BIT) 
     387        direction = self.x_axis[1] - self.x_axis[0] 
     388        glColor3f(1,1,1) 
     389        glBegin(GL_TRIANGLES) 
     390        glVertex3f(0,0,0) 
     391        glVertex3f(1,0,0) 
     392        glVertex3f(0,1,0) 
     393        glEnd() 
     394        #for i in range(10): 
     395        #  pos = self.x_axis[0] + direction * (i / 10.) 
     396        #  self.renderText(pos[0], 10, '{0:.2}'.format(pos[0])) 
     397        self.x_axis_frame.release() 
     398 
     399    def scatter(self, X, Y, Z, c="b", s=5, **kwargs): 
    323400        array = [[x, y, z] for x,y,z in zip(X, Y, Z)] 
    324401        if isinstance(c, str): 
     
    341418        self.normal_size = numpy.max(self.center - self.b_box[1]) / 100. 
    342419 
    343         vertex_buffer = QtOpenGL.QGLBuffer(QtOpenGL.QGLBuffer.VertexBuffer) 
    344         if vertex_buffer.create() == False: 
    345           print('Warning: vertex buffers not supported') 
    346           return 
    347  
    348         vertex_buffer.bind() 
    349         vertex_buffer.setUsagePattern(QtOpenGL.QGLBuffer.StaticDraw) 
     420        vao = c_int() 
     421        glGenVertexArrays(1, byref(vao)) 
     422        glBindVertexArray(vao.value) 
     423 
     424        vertex_buffer = c_int() 
     425        glGenBuffers(1, byref(vertex_buffer)) 
     426        glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer.value) 
     427 
     428        vertex_size = (3+3+4)*4 
     429        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertex_size, 0) 
     430        glEnableVertexAttribArray(0) 
     431        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertex_size, 3*4) 
     432        glEnableVertexAttribArray(1) 
     433        glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, vertex_size, 6*4) 
     434        glEnableVertexAttribArray(2) 
    350435 
    351436        vertices = [] 
    352437        for (x,y,z), (r,g,b,a), size in zip(array, colors, s): 
    353           vertices.extend([x-size*self.normal_size,y,z, r,g,b,a]) 
    354           vertices.extend([x+size*self.normal_size,y,z, r,g,b,a]) 
    355           vertices.extend([x,y+size*self.normal_size,z, r,g,b,a]) 
    356  
    357         vertex_buffer.allocate((GLfloat * len(vertices))(vertices), len(vertices)*4) 
    358  
    359         self.commands.append(("scatter", (vertex_buffer))) 
     438          vertices.extend([x,y,z, -size*self.normal_size,0,0, r,g,b,a]) 
     439          vertices.extend([x,y,z, +size*self.normal_size,0,0, r,g,b,a]) 
     440          vertices.extend([x,y,z, 0,+size*self.normal_size,0, r,g,b,a]) 
     441 
     442        # It's important to keep reference to vertices around, 
     443        # data uploaded to GPU seem to get corrupted without. 
     444        vertex_buffer.vertices = numpy.array(vertices, 'f') 
     445        glBufferData(GL_ARRAY_BUFFER, len(vertices)*4, 
     446          ArrayDatatype.voidDataPointer(vertex_buffer.vertices), GL_STATIC_DRAW) 
     447 
     448        glBindVertexArray(0) 
     449        glBindBuffer(GL_ARRAY_BUFFER, 0) 
     450 
     451        vao.num_vertices = len(vertices) / (vertex_size / 4) 
     452        self.vertex_buffers.append(vertex_buffer) 
     453        self.vaos.append(vao) 
     454        self.commands.append(("scatter", vao)) 
    360455        self.update_axes() 
    361456        self.updateGL() 
    362   
     457 
    363458    def mousePressEvent(self, event): 
    364459      self.mouse_pos = event.pos() 
     
    394489        self.commands = [] 
    395490 
     491 
    396492if __name__ == "__main__": 
    397493    app = QApplication(sys.argv) 
     
    412508    colors = [[c.red()/255., c.green()/255., c.blue()/255., 0.8] for c in colors] 
    413509 
    414 #    x = [rand()*2 for i in range(N)] 
    415 #    y = [rand()*2 for i in range(N)] 
    416 #    z = [-3 + rand() for i in range(N)] 
    417 #    colors = "b" 
    418510    w.scatter(x, y, z, c=colors) 
    419511    app.exec_() 
Note: See TracChangeset for help on using the changeset viewer.