def __init__(self, vtype, utype): # Convert vtype to a list (in case it was already a dtype) such that we # can append new fields vtype = eval(str(np.dtype(vtype))) # Convert utype to a list (in case it was already a dtype) such that we # can append new fields utype = eval(str(np.dtype(utype))) # We add a uniform index to access uniform data from texture vtype.append(('index', 'f4')) VertexBuffer.__init__(self, vtype) # Check if given utype is made of float32 only rutype = dtype_reduce(utype) if type(rutype[0]) is not str or rutype[2] != 'float32': print "Uniform type cannot de reduced to float32 only" else: count = rutype[1] size = count // 4 if count % 4: size += 1 utype.append(('unnused', 'f4', size * 4 - count)) self.uniforms_data = np.zeros((1, 1), dtype=utype) self.uniforms_size = 0 self.uniforms_capacity = 1 self.uniforms_shape = None self._uniforms_id = 0
def append(self, vertices, indices, uniforms): vertices = vertices.astype(self.vertices_data.dtype) indices = indices.astype(self.indices_data.dtype) uniforms = uniforms.astype(self.uniforms_data.dtype) VertexBuffer.append(self, vertices, indices) # Test if current uniforms capacity is big enough to hold new data if self.uniforms_size + 1 >= self.uniforms_capacity: capacity = int(2**np.ceil(np.log2(self.uniforms_size + 1))) self.uniforms_data = np.resize(self.uniforms_data, (capacity, 1)) self.uniforms_capacity = len(self.uniforms_data) # Add uniforms data ustart, uend = self.uniforms_size, self.uniforms_size + 1 self.uniforms_data[ustart] = uniforms # Keep track of new object vstart, vend, istart, iend = self.objects[-1] self.objects[-1] = self, vstart, vend, istart, iend, ustart, uend # Update uniforms size self.uniforms_size += 1 self.dirty = True """
def __init__(self, vtype, utype): self.dash_atlas = None # Convert types to lists (in case they were already dtypes) such that # we can append new fields vtype = eval(str(np.dtype(vtype))) utype = eval(str(np.dtype(utype))) # We add a uniform index to access uniform data from texture vtype.append(('a_index', 'f4')) # Check if given utype is made of float32 only rutype = dtype_reduce(utype) if type(rutype[0]) is not str or rutype[2] != 'float32': raise CollectionError( "Uniform type cannot de reduced to float32 only") else: count = rutype[1] size = count // 4 if count % 4: size += 1 utype.append(('unnused', 'f4', size * 4 - count)) count = size * 4 self.utype = utype self._vbuffer = VertexBuffer(vtype) self._ubuffer = DynamicBuffer(utype) self._ubuffer_id = 0 self._ubuffer_shape = [0, count] self._dirty = True
def upload(self): # Update uniform index for all objects # TODO: vectorize for i in range(len(self.objects)): _,vstart,vend,_,_,_,_ = self.objects[i] self.vertices_data[vstart:vend]['index'] = i/float(len(self.uniforms_data)) VertexBuffer.upload(self) if not self._uniforms_id: self._uniforms_id = gl.glGenTextures(1) gl.glActiveTexture( gl.GL_TEXTURE0 ) gl.glPixelStorei( gl.GL_UNPACK_ALIGNMENT, 1 ) gl.glPixelStorei( gl.GL_PACK_ALIGNMENT, 1 ) gl.glBindTexture( gl.GL_TEXTURE_2D, self._uniforms_id ) gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST ) gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST ) gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE ) gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE ) data = self.uniforms_data.view(np.float32) self.uniforms_shape = data.shape[1]//4, data.shape[0] gl.glTexImage2D( gl.GL_TEXTURE_2D, 0, gl.GL_RGBA32F_ARB, data.shape[1]//4, data.shape[0], 0, gl.GL_RGBA, gl.GL_FLOAT, data )
def __init__(self, vtype, utype): # Convert types to lists (in case they were already dtypes) such that # we can append new fields vtype = eval(str(np.dtype(vtype))) utype = eval(str(np.dtype(utype))) # We add a uniform index to access uniform data from texture vtype.append( ('a_index', 'f4') ) # Check if given utype is made of float32 only rutype = dtype_reduce(utype) if type(rutype[0]) is not str or rutype[2] != 'float32': raise CollectionError("Uniform type cannot de reduced to float32 only") else: count = rutype[1] count2 = int(math.pow(2, math.ceil(math.log(count, 2)))) if (count2 - count) > 0: utype.append(('unused', 'f4', count2-count)) self._count = count2 self.utype = utype self._vbuffer = VertexBuffer(vtype) self._ubuffer = DynamicBuffer( utype ) self._ubuffer_id = 0 self._max_texture_size = gl.glGetInteger(gl.GL_MAX_TEXTURE_SIZE) self._compute_ushape(1) self._ubuffer.reserve( self._ushape[1] / (count/4) ) self._dirty = True
def __init__(self, vtype, utype): # Convert vtype to a list (in case it was already a dtype) such that we # can append new fields vtype = eval(str(np.dtype(vtype))) # Convert utype to a list (in case it was already a dtype) such that we # can append new fields utype = eval(str(np.dtype(utype))) # We add a uniform index to access uniform data from texture vtype.append( ('index', 'f4') ) VertexBuffer.__init__(self, vtype) # Check if given utype is made of float32 only rutype = dtype_reduce(utype) if type(rutype[0]) is not str or rutype[2] != 'float32': print "Uniform type cannot de reduced to float32 only" else: count = rutype[1] size = count//4 if count % 4: size += 1 utype.append(('unnused', 'f4', size*4-count)) self.uniforms_data = np.zeros((1,1), dtype=utype) self.uniforms_size = 0 self.uniforms_capacity = 1 self.uniforms_shape = None self._uniforms_id = 0
def append(self, vertices, indices, uniforms): vertices = vertices.astype(self.vertices_data.dtype) indices = indices.astype(self.indices_data.dtype) uniforms = uniforms.astype(self.uniforms_data.dtype) VertexBuffer.append(self, vertices, indices) # Test if current uniforms capacity is big enough to hold new data if self.uniforms_size + 1 >= self.uniforms_capacity: capacity = int(2**np.ceil(np.log2(self.uniforms_size + 1))) self.uniforms_data = np.resize( self.uniforms_data, (capacity,1) ) self.uniforms_capacity = len(self.uniforms_data) # Add uniforms data ustart, uend = self.uniforms_size, self.uniforms_size+1 self.uniforms_data[ustart] = uniforms # Keep track of new object vstart,vend,istart,iend = self.objects[-1] self.objects[-1] = self,vstart,vend,istart,iend,ustart,uend # Update uniforms size self.uniforms_size += 1 self.dirty = True """
def upload(self): # Update uniform index for all objects # TODO: vectorize for i in range(len(self.objects)): _, vstart, vend, _, _, _, _ = self.objects[i] self.vertices_data[vstart:vend]['index'] = i / float( len(self.uniforms_data)) VertexBuffer.upload(self) if not self._uniforms_id: self._uniforms_id = gl.glGenTextures(1) gl.glActiveTexture(gl.GL_TEXTURE0) gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1) gl.glPixelStorei(gl.GL_PACK_ALIGNMENT, 1) gl.glBindTexture(gl.GL_TEXTURE_2D, self._uniforms_id) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE) data = self.uniforms_data.view(np.float32) self.uniforms_shape = data.shape[1] // 4, data.shape[0] gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA32F_ARB, data.shape[1] // 4, data.shape[0], 0, gl.GL_RGBA, gl.GL_FLOAT, data)
def build(self): self.vertices = np.zeros(len(self._text) * 4, dtype=[('position', 'f4', 3), ('tex_coord', 'f4', 2), ('color', 'f4', 4)]) self.indices = np.zeros((len(self._text) * 6, ), dtype=np.uint32) prev = None x, y = 0, 0 for i, charcode in enumerate(self._text): glyph = self._font[charcode] kerning = glyph.get_kerning(prev) / 64.0 x0 = int(x + glyph.offset[0] + kerning) y0 = int(y + glyph.offset[1]) x1 = x0 + glyph.size[0] y1 = y0 - glyph.size[1] u0 = glyph.texcoords[0] v0 = glyph.texcoords[1] u1 = glyph.texcoords[2] v1 = glyph.texcoords[3] index = i * 4 indices = [ index, index + 1, index + 2, index, index + 2, index + 3 ] vertices = [[x0, y0, 0], [x0, y1, 0], [x1, y1, 0], [x1, y0, 0]] texcoords = [[u0, v0], [u0, v1], [u1, v1], [u1, v0]] colors = [ self._color, ] * 4 self.indices[i * 6:i * 6 + 6] = indices self.vertices['position'][i * 4:i * 4 + 4] = vertices self.vertices['tex_coord'][i * 4:i * 4 + 4] = texcoords self.vertices['color'][i * 4:i * 4 + 4] = colors x += glyph.advance[0] / 64.0 + kerning y += glyph.advance[1] / 64.0 prev = charcode width = x + glyph.advance[0] / 64.0 + glyph.size[0] if self._anchor_y == 'top': dy = -round(self._font.ascender) elif self._anchor_y == 'center': dy = +round(-self._font.height / 2 - self._font.descender) elif self._anchor_y == 'bottom': dy = -round(self._font.descender) else: dy = 0 if self._anchor_x == 'right': dx = -width / 1.0 elif self._anchor_x == 'center': dx = -width / 2.0 else: dx = 0 self.vertices['position'] += self._x + round(dx), self._y + round( dy), self._z self.buffer = VertexBuffer(self.vertices, self.indices)
def __init__(self, major_lines = (1.00, 1.00, 0.75), major_lines_color = (0.75, 0.75, 0.75, 1.00), major_ticks = (5.00, 5.00, 1.50), major_ticks_color = (0.00, 0.00, 0.00, 1.00), minor_lines = (0.10, 0.10, 0.25), minor_lines_color = (0.75, 0.75, 0.75, 1.00), minor_ticks = (2.50, 2.50, 1.00), minor_ticks_color = (0.00, 0.00, 0.00, 1.00) ): self._major_lines = np.array(major_lines) self._major_lines_color = np.array(major_lines_color) self._major_ticks = np.array(major_ticks) self._major_ticks_color = np.array(major_ticks_color) self._minor_lines = np.array(minor_lines) self._minor_lines_color = np.array(minor_lines_color) self._minor_ticks = np.array(minor_ticks) self._minor_ticks_color = np.array(minor_ticks_color) vert = open('./grid.vert').read() frag = open('./grid.frag').read() self._shader = Shader(vert,frag) self._transform = 0.0,0.0,100.0,0.0 w,h = 512,512 vertices = np.array( [ ((0, 0), (0,0)), ((w, 0), (w,0)), ((w, h), (w,h)), ((0, h), (0,h)) ], dtype = [('position','f4',2), ('tex_coord','f4',2)] ) vertices['position'] += .315,.315 indices = np.array( [0,1,2, 0,2,3 ], dtype=np.uint32 ) self._buffer = VertexBuffer(vertices,indices)
def __init__(self, vtype, utype): self.dash_atlas = None # Convert types to lists (in case they were already dtypes) such that # we can append new fields vtype = eval(str(np.dtype(vtype))) utype = eval(str(np.dtype(utype))) # We add a uniform index to access uniform data from texture vtype.append( ('a_index', 'f4') ) # Check if given utype is made of float32 only rutype = dtype_reduce(utype) if type(rutype[0]) is not str or rutype[2] != 'float32': raise CollectionError("Uniform type cannot de reduced to float32 only") else: count = rutype[1] size = count//4 if count % 4: size += 1 utype.append(('unnused', 'f4', size*4-count)) count = size*4 self.utype = utype self._vbuffer = VertexBuffer(vtype) self._ubuffer = DynamicBuffer( utype ) self._ubuffer_id = 0 self._ubuffer_shape = [0,count] self._dirty = True
def __delitem__(self, key): _,vstart,vend,istart,iend,ustart,uend = self.objects[key] vsize = self.vertices_size-vend usize = self.uniforms_size-tend isize = self.indices_size-iend VertexBuffer.__delitem__(self,key) # Remove uniforms self.uniforms_data[ustart:ustart+usize] = self.uniforms_data[tend:tend+usize] self.uniforms_size -= 1 # Update all subsequent objects for i in range(key, len(self.objects)): _, _vstart,_vend,_istart,_iend,_ustart,_uend = self.objects[i] self.objects[i] = [self, \ _vstart-vsize, _vend-vsize, \ _istart-isize, _iend-isize, \ _ustart-usize, _uend-usize]
def __delitem__(self, key): _, vstart, vend, istart, iend, ustart, uend = self.objects[key] vsize = self.vertices_size - vend usize = self.uniforms_size - tend isize = self.indices_size - iend VertexBuffer.__delitem__(self, key) # Remove uniforms self.uniforms_data[ustart:ustart + usize] = self.uniforms_data[tend:tend + usize] self.uniforms_size -= 1 # Update all subsequent objects for i in range(key, len(self.objects)): _, _vstart, _vend, _istart, _iend, _ustart, _uend = self.objects[i] self.objects[i] = [self, \ _vstart-vsize, _vend-vsize, \ _istart-isize, _iend-isize, \ _ustart-usize, _uend-usize]
def __init__ (self, centers, radii, linewidths = 1.0, edgecolors = (0,0,0,1), facecolors = (0,0,0,1), transforms = (0,0,1,0), antialiased = 0.75): """ """ Collection.__init__(self) self.dtype = np.dtype( [('position', 'f4', 3), ('tex_coord', 'f4', 2), ('color', 'f4', 4), ('facecolor', 'f4', 4), ('transform', 'f4', 4), ('radius', 'f4', 2), ('thickness', 'f4', 1), ('support', 'f4', 1)] ) vertices = np.zeros(0, dtype = self.dtype) self._buffer = VertexBuffer(vertices) self.append(centers, radii, linewidths, edgecolors, facecolors, transforms, antialiased) vert = open('./ellipse.vert').read() frag = open('./ellipse.frag').read() self._shader = Shader(vert,frag)
def __init__ (self, segments, linewidths = 1.0, colors = (0,0,0,1), caps = (1,1), transforms = (0,0,1,0), antialiased = 0.75): """ """ Collection.__init__(self) self.dtype = np.dtype( [('position', 'f4', 3), ('tex_coord', 'f4', 2), ('color', 'f4', 4), ('transform', 'f4', 4), ('tangent', 'f4', 2), ('cap', 'f4', 2), ('length', 'f4', 1), ('thickness', 'f4', 1), ('support', 'f4', 1)] ) vertices = np.zeros(0, dtype = self.dtype) self._buffer = VertexBuffer(vertices) self.append(segments, linewidths, colors, caps, transforms, antialiased) vert = open('./line.vert').read() frag = open('./line.frag').read() self._shader = Shader(vert,frag)
def build(self): self.vertices = np.zeros( len(self._text)*4, dtype = [('position', 'f4',3), ('tex_coord', 'f4',2), ('color', 'f4',4)] ) self.indices = np.zeros( (len(self._text)*6, ), dtype=np.uint32 ) prev = None x,y = 0, 0 for i,charcode in enumerate(self._text): glyph = self._font[charcode] kerning = glyph.get_kerning(prev)/64.0 x0 = int(x + glyph.offset[0] + kerning) y0 = int(y + glyph.offset[1]) x1 = x0 + glyph.size[0] y1 = y0 - glyph.size[1] u0 = glyph.texcoords[0] v0 = glyph.texcoords[1] u1 = glyph.texcoords[2] v1 = glyph.texcoords[3] index = i*4 indices = [index, index+1, index+2, index, index+2, index+3] vertices = [[x0,y0,0],[x0,y1,0],[x1,y1,0], [x1,y0,0]] texcoords = [[u0,v0],[u0,v1],[u1,v1], [u1,v0]] colors = [self._color,]*4 self.indices[i*6:i*6+6] = indices self.vertices['position'][i*4:i*4+4] = vertices self.vertices['tex_coord'][i*4:i*4+4] = texcoords self.vertices['color'][i*4:i*4+4] = colors x += glyph.advance[0]/64.0 + kerning y += glyph.advance[1]/64.0 prev = charcode width = x+glyph.advance[0]/64.0+glyph.size[0] if self._anchor_y == 'top': dy = -round(self._font.ascender) elif self._anchor_y == 'center': dy = +round(-self._font.height/2-self._font.descender) elif self._anchor_y == 'bottom': dy = -round(self._font.descender) else: dy = 0 if self._anchor_x == 'right': dx = -width/1.0 elif self._anchor_x == 'center': dx = -width/2.0 else: dx = 0 self.vertices['position'] += self._x+round(dx), self._y+round(dy), self._z self.buffer = VertexBuffer(self.vertices, self.indices)
class Label(object): ''' ''' def __init__(self, text, family='Sans', size=16, bold=False, italic=False, color=(1.0, 1.0, 1.0, 1.0), x=0, y=0, z=0, anchor_x='left', anchor_y='baseline', filename='./Arial.ttf'): self._text = text self._font = get_font(filename, size) self._color = color self._x = x self._y = y self._z = z self._anchor_x = anchor_x self._anchor_y = anchor_y self.build() def build(self): self.vertices = np.zeros(len(self._text) * 4, dtype=[('position', 'f4', 3), ('tex_coord', 'f4', 2), ('color', 'f4', 4)]) self.indices = np.zeros((len(self._text) * 6, ), dtype=np.uint32) prev = None x, y = 0, 0 for i, charcode in enumerate(self._text): glyph = self._font[charcode] kerning = glyph.get_kerning(prev) / 64.0 x0 = int(x + glyph.offset[0] + kerning) y0 = int(y + glyph.offset[1]) x1 = x0 + glyph.size[0] y1 = y0 - glyph.size[1] u0 = glyph.texcoords[0] v0 = glyph.texcoords[1] u1 = glyph.texcoords[2] v1 = glyph.texcoords[3] index = i * 4 indices = [ index, index + 1, index + 2, index, index + 2, index + 3 ] vertices = [[x0, y0, 0], [x0, y1, 0], [x1, y1, 0], [x1, y0, 0]] texcoords = [[u0, v0], [u0, v1], [u1, v1], [u1, v0]] colors = [ self._color, ] * 4 self.indices[i * 6:i * 6 + 6] = indices self.vertices['position'][i * 4:i * 4 + 4] = vertices self.vertices['tex_coord'][i * 4:i * 4 + 4] = texcoords self.vertices['color'][i * 4:i * 4 + 4] = colors x += glyph.advance[0] / 64.0 + kerning y += glyph.advance[1] / 64.0 prev = charcode width = x + glyph.advance[0] / 64.0 + glyph.size[0] if self._anchor_y == 'top': dy = -round(self._font.ascender) elif self._anchor_y == 'center': dy = +round(-self._font.height / 2 - self._font.descender) elif self._anchor_y == 'bottom': dy = -round(self._font.descender) else: dy = 0 if self._anchor_x == 'right': dx = -width / 1.0 elif self._anchor_x == 'center': dx = -width / 2.0 else: dx = 0 self.vertices['position'] += self._x + round(dx), self._y + round( dy), self._z self.buffer = VertexBuffer(self.vertices, self.indices) def draw(self): gl.glDisable(gl.GL_TEXTURE_1D) gl.glEnable(gl.GL_TEXTURE_2D) gl.glDisable(gl.GL_DEPTH_TEST) gl.glBindTexture(gl.GL_TEXTURE_2D, self._font.texid) gl.glEnable(gl.GL_BLEND) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glColor(1, 1, 1, 1) self.buffer.draw(gl.GL_TRIANGLES) def _get_position(self): return self._x, self.y, self._z def _set_position(self, position): x, y = position self.vertices['position'] -= self._x, self._y, 0 self._x, self._y = x, y self.vertices['position'] += x, y, 0 self.vbo.upload() position = property(_get_position, _set_position)
class LineCollection(Collection): def __init__ (self, segments, linewidths = 1.0, colors = (0,0,0,1), caps = (1,1), transforms = (0,0,1,0), antialiased = 0.75): """ """ Collection.__init__(self) self.dtype = np.dtype( [('position', 'f4', 3), ('tex_coord', 'f4', 2), ('color', 'f4', 4), ('transform', 'f4', 4), ('tangent', 'f4', 2), ('cap', 'f4', 2), ('length', 'f4', 1), ('thickness', 'f4', 1), ('support', 'f4', 1)] ) vertices = np.zeros(0, dtype = self.dtype) self._buffer = VertexBuffer(vertices) self.append(segments, linewidths, colors, caps, transforms, antialiased) vert = open('./line.vert').read() frag = open('./line.frag').read() self._shader = Shader(vert,frag) def append(self, segments, linewidths = 1.0, colors = (0,0,0,1), caps = (1,1), transforms = (0,0,1,0), antialiased = 0.75): """ """ linewidths = np.atleast_1d(linewidths) colors = np.atleast_2d(colors) caps = np.atleast_2d(caps) transforms = np.atleast_2d(transforms) antialiased = np.atleast_1d(antialiased) for i,segment in enumerate(segments): thickness = linewidths[ i % len(linewidths)] color = colors[ i % len(colors)] cap = caps[ i % len(caps)] transform = transforms[ i % len(transforms)] support = antialiased[ i % len(antialiased)] # Points as array P = np.array(segment).reshape(len(segment),3).astype(float) # Tangent vectors T = np.zeros_like(P) T[:-1] = P[1:] - P[:-1] T[-1] = T[-2] T = T[:,0:2] L = np.sqrt(T[:,0]**2 + T[:,1]**2) T /= L.reshape(len(P),1) # Lengths L = np.cumsum(L) L[1:] = L[:-1] L[0] = 0 length = L[-1] # Special case for start and end caps L[0],L[-1] = -1, length+1 n = len(P) vertices = np.zeros(n, dtype = self.dtype) vertices['position'] = P vertices['tangent'] = T vertices['thickness'] = thickness vertices['color'] = color vertices['cap'] = cap vertices['length'] = length vertices['support'] = support vertices['transform'] = transform vertices['tex_coord'][:,0] = L vertices = np.repeat(vertices, 2) vertices['tex_coord'][0::2,1] = -1 vertices['tex_coord'][1::2,1] = +1 indices = np.resize( np.array([0,1,2,1,2,3], dtype=np.uint32), (n-1)*(2*3)) indices += np.repeat( 2*np.arange(n-1), 6) self._buffer.append( vertices, indices ) self._dirty = True
gl.glPolygonOffset(1, 1) gl.glClearColor(.3, .3, .35, 1) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glEnable(gl.GL_LINE_SMOOTH) projection = np.eye(4, dtype=np.float32) view = np.eye(4, dtype=np.float32) theta, phi = 0, 0 vtype = [('position', np.float32, 3), ('normal', np.float32, 3), ('color', np.float32, 4)] vertices, normals, faces = load_obj('./bunny.obj') V = np.zeros(len(vertices), dtype=vtype) V['position'] = vertices V['color'] = 1, 1, 1, 1 V['normal'] = normals obj = VertexBuffer(vtype) obj.append(V, faces) outline = VertexBuffer(vtype) I = [] for f in faces: I.extend([f[0], f[1], f[1], f[2], f[2], f[0]]) outline.append(V, I) shader = Shader(open("./cube.vert").read(), open("./cube.frag").read()) glut.glutMainLoop()
gl.glBlendFunc( gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA ) gl.glEnable( gl.GL_LINE_SMOOTH ) projection = np.eye(4,dtype=np.float32) view = np.eye(4,dtype=np.float32) theta, phi = 0,0 vtype = [('position', np.float32, 3), ('normal' , np.float32, 3), ('color', np.float32, 4)] vertices, normals, faces = load_obj('./bunny.obj') V = np.zeros(len(vertices), dtype=vtype) V['position'] = vertices V['color'] = 1,1,1,1 V['normal'] = normals obj = VertexBuffer(vtype) obj.append(V, faces) outline = VertexBuffer(vtype) I = [] for f in faces: I.extend([f[0],f[1],f[1],f[2],f[2],f[0]]) outline.append(V, I) shader = Shader(open("./cube.vert").read(), open("./cube.frag").read()) glut.glutMainLoop()
glut.glutInitDisplayMode(glut.GLUT_DOUBLE | glut.GLUT_RGB | glut.GLUT_DEPTH) glut.glutCreateWindow("Thick lines") glut.glutReshapeWindow(800, 800) glut.glutDisplayFunc(on_display) glut.glutReshapeFunc(on_reshape) glut.glutKeyboardFunc(on_keyboard) glut.glutIdleFunc(on_idle) shader = Shader(open("line-uniform.vert").read(), open("line-uniform.frag").read()) S = star() vtype = np.dtype( [ ("prev2", "f4", 2), ("prev", "f4", 2), ("curr", "f4", 2), ("next", "f4", 2), ("next2", "f4", 2), ("vid", "f4", 1), ] ) line = VertexBuffer(vtype) np.random.seed(1) for i in range(1000): s = np.random.uniform(0.025, 0.100) x, y = np.random.uniform(0, 800, 2) V, I = bake(S * s + (x, y), closed=True) line.append(V, I) glut.glutMainLoop()
t0 = glut.glutGet(glut.GLUT_ELAPSED_TIME) glut.glutInit(sys.argv) glut.glutInitDisplayMode(glut.GLUT_DOUBLE | glut.GLUT_RGB | glut.GLUT_DEPTH) glut.glutCreateWindow("Thick lines") glut.glutReshapeWindow(800, 800) glut.glutDisplayFunc(on_display) glut.glutReshapeFunc(on_reshape) glut.glutKeyboardFunc(on_keyboard) glut.glutIdleFunc(on_idle) shader = Shader( open('line-uniform.vert').read(), open('line-uniform.frag').read() ) S = star() vtype = np.dtype([('prev2', 'f4', 2), ('prev', 'f4', 2), ('curr', 'f4', 2), ('next', 'f4', 2), ('next2', 'f4', 2), ('vid', 'f4', 1) ] ) line = VertexBuffer(vtype) np.random.seed(1) for i in range(1000): s = np.random.uniform(0.025,0.100) x,y = np.random.uniform(0,800,2) V,I = bake( S*s + (x,y), closed=True) line.append(V,I) glut.glutMainLoop()
class Collection(object): join = {'miter': 0, 'round': 1, 'bevel': 2} caps = { '': 0, 'none': 0, '.': 0, 'round': 1, ')': 1, '(': 1, 'o': 1, 'triangle in': 2, '<': 2, 'triangle out': 3, '>': 3, 'square': 4, '=': 4, 'butt': 4, '|': 5 } # --------------------------------- def __init__(self, vtype, utype): self.dash_atlas = None # Convert types to lists (in case they were already dtypes) such that # we can append new fields vtype = eval(str(np.dtype(vtype))) utype = eval(str(np.dtype(utype))) # We add a uniform index to access uniform data from texture vtype.append(('a_index', 'f4')) # Check if given utype is made of float32 only rutype = dtype_reduce(utype) if type(rutype[0]) is not str or rutype[2] != 'float32': raise CollectionError( "Uniform type cannot de reduced to float32 only") else: count = rutype[1] size = count // 4 if count % 4: size += 1 utype.append(('unnused', 'f4', size * 4 - count)) count = size * 4 self.utype = utype self._vbuffer = VertexBuffer(vtype) self._ubuffer = DynamicBuffer(utype) self._ubuffer_id = 0 self._ubuffer_shape = [0, count] self._dirty = True # --------------------------------- def __len__(self): return len(self._vbuffer) # --------------------------------- def __getitem__(self, key): V = self._vbuffer.vertices[key] I = self._vbuffer.indices[key] U = self._ubuffer[key] return Item(self, key, V, I, U) # --------------------------------- def __delitem__(self, key): start, end = self._vbuffer.vertices.range(key) del self._vbuffer[key] del self._ubuffer[key] self._vbuffer.vertices.data['a_index'][start:] -= 1 self._vbuffer._dirty = True self._dirty = True # --------------------------------- def get_vertices(self): return self._vbuffer.vertices vertices = property(get_vertices) # --------------------------------- def get_indices(self): return self._vbuffer.indices indices = property(get_indices) # --------------------------------- def get_uniforms(self): return self._ubuffer uniforms = property(get_uniforms) # --------------------------------- def __getattr__(self, name): if hasattr(self, '_ubuffer'): buffer = object.__getattribute__(self, '_ubuffer') if name in buffer.dtype.names: return buffer.data[name] return object.__getattribute__(self, name) # --------------------------------- def __setattr__(self, name, value): object.__setattr__(self, name, value) if hasattr(self, '_ubuffer'): buffer = object.__getattribute__(self, '_ubuffer') if name in buffer.dtype.names: buffer.data[name] = value # buffer._dirty = True object.__setattr__(self, '_dirty', True) object.__setattr__(self, name, value) # --------------------------------- def clear(self): self._vbuffer.clear() self._ubuffer.clear() self._dirty = True # --------------------------------- def append(self, vertices, indices, uniforms): vertices = np.array(vertices).astype(self._vbuffer.vertices.dtype) indices = np.array(indices).astype(self._vbuffer.indices.dtype) uniforms = np.array(uniforms).astype(self._ubuffer.dtype) vertices['a_index'] = len(self) self._vbuffer.append(vertices, indices) self._ubuffer.append(uniforms) self._ubuffer_shape[0] = len(self) self._dirty = True # --------------------------------- def upload(self): if not self._dirty: return self._vbuffer.upload() gl.glActiveTexture(gl.GL_TEXTURE0) data = self._ubuffer.data.view(np.float32) shape = self._ubuffer_shape if not self._ubuffer_id: self._ubuffer_id = gl.glGenTextures(1) gl.glBindTexture(gl.GL_TEXTURE_2D, self._ubuffer_id) gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1) gl.glPixelStorei(gl.GL_PACK_ALIGNMENT, 1) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_BASE_LEVEL, 0) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAX_LEVEL, 0) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA32F, shape[1] // 4, shape[0], 0, gl.GL_RGBA, gl.GL_FLOAT, data) gl.glActiveTexture(gl.GL_TEXTURE0) gl.glBindTexture(gl.GL_TEXTURE_2D, self._ubuffer_id) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA32F, shape[1] // 4, shape[0], 0, gl.GL_RGBA, gl.GL_FLOAT, data) #gl.glTexSubImage2D( gl.GL_TEXTURE_2D,0, 0, 0, shape[1]//4, shape[0], # gl.GL_RGBA, gl.GL_FLOAT, data); self._dirty = False # --------------------------------- def bake(self, vertices): raise NotImplemented # --------------------------------- def draw(self): if self._dirty: self.upload() gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glEnable(gl.GL_BLEND) _, _, width, height = gl.glGetIntegerv(gl.GL_VIEWPORT) P = orthographic(0, width, 0, height, -1, +1) V = np.eye(4).astype(np.float32) M = np.eye(4).astype(np.float32) shader = self.shader shader.bind() gl.glActiveTexture(gl.GL_TEXTURE0) shader.uniformi('u_uniforms', 0) gl.glBindTexture(gl.GL_TEXTURE_2D, self._ubuffer_id) if self.dash_atlas: gl.glActiveTexture(gl.GL_TEXTURE1) shader.uniformi('u_dash_atlas', 1) gl.glBindTexture(gl.GL_TEXTURE_2D, self.dash_atlas.texture_id) shader.uniform_matrixf('u_M', M) shader.uniform_matrixf('u_V', V) shader.uniform_matrixf('u_P', P) shape = self._ubuffer_shape shader.uniformf('u_uniforms_shape', shape[1] // 4, shape[0]) self._vbuffer.draw() shader.unbind()
class Collection(object): # --------------------------------- def __init__(self, vtype, utype): # Convert types to lists (in case they were already dtypes) such that # we can append new fields vtype = eval(str(np.dtype(vtype))) utype = eval(str(np.dtype(utype))) # We add a uniform index to access uniform data from texture vtype.append( ('a_index', 'f4') ) # Check if given utype is made of float32 only rutype = dtype_reduce(utype) if type(rutype[0]) is not str or rutype[2] != 'float32': raise CollectionError("Uniform type cannot de reduced to float32 only") else: count = rutype[1] count2 = int(math.pow(2, math.ceil(math.log(count, 2)))) if (count2 - count) > 0: utype.append(('unused', 'f4', count2-count)) self._count = count2 self.utype = utype self._vbuffer = VertexBuffer(vtype) self._ubuffer = DynamicBuffer( utype ) self._ubuffer_id = 0 self._max_texture_size = gl.glGetInteger(gl.GL_MAX_TEXTURE_SIZE) self._compute_ushape(1) self._ubuffer.reserve( self._ushape[1] / (count/4) ) self._dirty = True # --------------------------------- def _compute_ushape(self, size=1): max_texsize = self._max_texture_size cols = max_texsize//(self._count/4) rows = (size // cols)+1 self._ushape = rows, cols*(self._count/4), self._count # --------------------------------- def __len__(self): return len(self._vbuffer) # --------------------------------- def __getitem__(self, key): V = self._vbuffer.vertices[key] I = self._vbuffer.indices[key] U = self._ubuffer[key] return Item(self, key, V, I, U) # --------------------------------- def __delitem__(self, key): start,end = self._vbuffer.vertices.range(key) del self._vbuffer[key] del self._ubuffer[key] self._vbuffer.vertices.data['a_index'][start:] -= 1 self._vbuffer._dirty = True self._dirty = True # --------------------------------- def get_vbuffer(self): return self._vbuffer vbuffer = property(get_vbuffer) # --------------------------------- def get_vertices(self): return self._vbuffer.vertices vertices = property(get_vertices) # --------------------------------- def get_indices(self): return self._vbuffer.indices indices = property(get_indices) # --------------------------------- def get_uniforms(self): return self._ubuffer uniforms = property(get_uniforms) # --------------------------------- def get_attributes(self): return self._vbuffer._attributes attributes = property(get_attributes) # --------------------------------- def __getattr__(self, name): if hasattr(self, '_ubuffer'): buffer = object.__getattribute__(self,'_ubuffer') if name in buffer.dtype.names: return buffer.data[name] return object.__getattribute__(self,name) # --------------------------------- def __setattr__(self, name, value): object.__setattr__(self, name, value) if hasattr(self, '_ubuffer'): buffer = object.__getattribute__(self,'_ubuffer') if name in buffer.dtype.names: buffer.data[name] = value # buffer._dirty = True object.__setattr__(self, '_dirty', True) object.__setattr__(self, name, value) # --------------------------------- def clear(self): self._vbuffer.clear() self._ubuffer.clear() self._dirty = True # --------------------------------- def append(self, vertices, indices, uniforms, splits=None): vertices = np.array(vertices).astype(self._vbuffer.vertices.dtype) indices = np.array(indices).astype(self._vbuffer.indices.dtype) uniforms = np.array(uniforms).astype(self._ubuffer.dtype) if splits is None: vertices['a_index'] = len(self) self._vbuffer.append( vertices, indices ) self._ubuffer.append( uniforms ) self._compute_ushape(len(self)) elif len(splits) == 2: vsize,isize = splits[0], splits[1] if (vertices.size % vsize) != 0: raise( RuntimeError, "Cannot split vertices data into %d pieces" % vsize) if (indices.size % isize) != 0: raise( RuntimeError, "Cannot split indices data into %d pieces" % vsize) vcount = vertices.size//vsize icount = indices.size//isize ucount = uniforms.size n = ucount if vcount != icount or vcount != ucount: raise( RuntimeError, "Vertices/indices/uniforms cannot be split") vertices['a_index'] = len(self)+np.repeat(np.arange(n),vsize) self._vbuffer.append( vertices, indices, (vsize,isize)) self._ubuffer.append( uniforms ) self._compute_ushape(len(self)) else: raise(RuntimeError, "Splits argument not understood") self._dirty = True # --------------------------------- def upload(self): if not self._dirty: return self._vbuffer.upload() self.upload_uniforms() self._dirty = False # --------------------------------- def upload_uniforms(self): gl.glActiveTexture( gl.GL_TEXTURE0 ) data = self._ubuffer.data.view(np.float32) shape = self._ushape if not self._ubuffer_id: self._ubuffer_id = gl.glGenTextures(1) gl.glBindTexture( gl.GL_TEXTURE_2D, self._ubuffer_id ) gl.glPixelStorei( gl.GL_UNPACK_ALIGNMENT, 1 ) gl.glPixelStorei( gl.GL_PACK_ALIGNMENT, 1 ) gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST ) gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST ) gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE ) gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE ) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_BASE_LEVEL, 0) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAX_LEVEL, 0) gl.glTexImage2D( gl.GL_TEXTURE_2D, 0, gl.GL_RGBA32F, shape[1], shape[0], 0, gl.GL_RGBA, gl.GL_FLOAT, data ) gl.glActiveTexture( gl.GL_TEXTURE0 ) gl.glBindTexture( gl.GL_TEXTURE_2D, self._ubuffer_id ) gl.glTexImage2D( gl.GL_TEXTURE_2D, 0, gl.GL_RGBA32F, shape[1], shape[0], 0, gl.GL_RGBA, gl.GL_FLOAT, data ) # --------------------------------- def draw(self, mode=gl.GL_TRIANGLES, uniforms = {}): if self._dirty: self.upload() shader = self.shader shader.bind() gl.glActiveTexture( gl.GL_TEXTURE0 ) shader.uniformi( 'u_uniforms', 0 ) gl.glBindTexture( gl.GL_TEXTURE_2D, self._ubuffer_id ) for name,value in uniforms.items(): shader.uniform(name, value) shader.uniformf('u_uniforms_shape', *self._ushape) self._vbuffer.draw(mode) shader.unbind()
class EllipseCollection(Collection): def __init__ (self, centers, radii, linewidths = 1.0, edgecolors = (0,0,0,1), facecolors = (0,0,0,1), transforms = (0,0,1,0), antialiased = 0.75): """ """ Collection.__init__(self) self.dtype = np.dtype( [('position', 'f4', 3), ('tex_coord', 'f4', 2), ('color', 'f4', 4), ('facecolor', 'f4', 4), ('transform', 'f4', 4), ('radius', 'f4', 2), ('thickness', 'f4', 1), ('support', 'f4', 1)] ) vertices = np.zeros(0, dtype = self.dtype) self._buffer = VertexBuffer(vertices) self.append(centers, radii, linewidths, edgecolors, facecolors, transforms, antialiased) vert = open('./ellipse.vert').read() frag = open('./ellipse.frag').read() self._shader = Shader(vert,frag) def append (self, centers, radii, linewidths = 1.0, edgecolors = (0,0,0,1), facecolors = (0,0,0,1), transforms = (0,0,1,0), antialiased = 0.75): """ """ linewidths = np.atleast_1d(linewidths) radii = np.atleast_2d(radii) edgecolors = np.atleast_2d(edgecolors) facecolors = np.atleast_2d(facecolors) transforms = np.atleast_2d(transforms) antialiased = np.atleast_1d(antialiased) for i,center in enumerate(centers): thickness = linewidths[ i % len(linewidths)] edgecolor = edgecolors[ i % len(edgecolors)] facecolor = facecolors[ i % len(facecolors)] radius = radii[ i % len(radii)] transform = transforms[ i % len(transforms)] support = antialiased[ i % len(antialiased)] # Points as array P = np.array(center).reshape(1,3).astype(float) vertices = np.zeros(1, dtype = self.dtype) vertices['position'] = P vertices['thickness'] = thickness vertices['color'] = edgecolor vertices['facecolor'] = facecolor vertices['radius'] = radius vertices['support'] = support vertices['transform'] = transform vertices = np.repeat(vertices, 4) vertices['tex_coord'][0::4] = -1,-1 vertices['tex_coord'][1::4] = +1,-1 vertices['tex_coord'][2::4] = +1,+1 vertices['tex_coord'][3::4] = -1,+1 indices = np.array([0,1,2,0,2,3], dtype=np.uint32) self._buffer.append( vertices, indices ) self._dirty = True
class Label(object): ''' ''' def __init__( self, text, family='Sans', size=16, bold=False, italic=False, color=(1.0, 1.0, 1.0, 1.0), x=0, y=0, z=0, anchor_x='left', anchor_y='baseline', filename='./Arial.ttf'): self._text = text self._font = get_font(filename, size) self._color = color self._x = x self._y = y self._z = z self._anchor_x = anchor_x self._anchor_y = anchor_y self.build() def build(self): self.vertices = np.zeros( len(self._text)*4, dtype = [('position', 'f4',3), ('tex_coord', 'f4',2), ('color', 'f4',4)] ) self.indices = np.zeros( (len(self._text)*6, ), dtype=np.uint32 ) prev = None x,y = 0, 0 for i,charcode in enumerate(self._text): glyph = self._font[charcode] kerning = glyph.get_kerning(prev)/64.0 x0 = int(x + glyph.offset[0] + kerning) y0 = int(y + glyph.offset[1]) x1 = x0 + glyph.size[0] y1 = y0 - glyph.size[1] u0 = glyph.texcoords[0] v0 = glyph.texcoords[1] u1 = glyph.texcoords[2] v1 = glyph.texcoords[3] index = i*4 indices = [index, index+1, index+2, index, index+2, index+3] vertices = [[x0,y0,0],[x0,y1,0],[x1,y1,0], [x1,y0,0]] texcoords = [[u0,v0],[u0,v1],[u1,v1], [u1,v0]] colors = [self._color,]*4 self.indices[i*6:i*6+6] = indices self.vertices['position'][i*4:i*4+4] = vertices self.vertices['tex_coord'][i*4:i*4+4] = texcoords self.vertices['color'][i*4:i*4+4] = colors x += glyph.advance[0]/64.0 + kerning y += glyph.advance[1]/64.0 prev = charcode width = x+glyph.advance[0]/64.0+glyph.size[0] if self._anchor_y == 'top': dy = -round(self._font.ascender) elif self._anchor_y == 'center': dy = +round(-self._font.height/2-self._font.descender) elif self._anchor_y == 'bottom': dy = -round(self._font.descender) else: dy = 0 if self._anchor_x == 'right': dx = -width/1.0 elif self._anchor_x == 'center': dx = -width/2.0 else: dx = 0 self.vertices['position'] += self._x+round(dx), self._y+round(dy), self._z self.buffer = VertexBuffer(self.vertices, self.indices) def draw(self): gl.glDisable (gl.GL_TEXTURE_1D) gl.glEnable( gl.GL_TEXTURE_2D ) gl.glDisable( gl.GL_DEPTH_TEST ) gl.glBindTexture( gl.GL_TEXTURE_2D, self._font.texid ) gl.glEnable( gl.GL_BLEND ) gl.glBlendFunc( gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA ) gl.glColor(1,1,1,1) self.buffer.draw(gl.GL_TRIANGLES) def _get_position(self): return self._x, self.y, self._z def _set_position(self, position): x,y = position self.vertices['position'] -= self._x, self._y, 0 self._x, self._y = x,y self.vertices['position'] += x, y, 0 self.vbo.upload() position = property(_get_position, _set_position)
class Grid(object): def __init__(self, major_lines = (1.00, 1.00, 0.75), major_lines_color = (0.75, 0.75, 0.75, 1.00), major_ticks = (5.00, 5.00, 1.50), major_ticks_color = (0.00, 0.00, 0.00, 1.00), minor_lines = (0.10, 0.10, 0.25), minor_lines_color = (0.75, 0.75, 0.75, 1.00), minor_ticks = (2.50, 2.50, 1.00), minor_ticks_color = (0.00, 0.00, 0.00, 1.00) ): self._major_lines = np.array(major_lines) self._major_lines_color = np.array(major_lines_color) self._major_ticks = np.array(major_ticks) self._major_ticks_color = np.array(major_ticks_color) self._minor_lines = np.array(minor_lines) self._minor_lines_color = np.array(minor_lines_color) self._minor_ticks = np.array(minor_ticks) self._minor_ticks_color = np.array(minor_ticks_color) vert = open('./grid.vert').read() frag = open('./grid.frag').read() self._shader = Shader(vert,frag) self._transform = 0.0,0.0,100.0,0.0 w,h = 512,512 vertices = np.array( [ ((0, 0), (0,0)), ((w, 0), (w,0)), ((w, h), (w,h)), ((0, h), (0,h)) ], dtype = [('position','f4',2), ('tex_coord','f4',2)] ) vertices['position'] += .315,.315 indices = np.array( [0,1,2, 0,2,3 ], dtype=np.uint32 ) self._buffer = VertexBuffer(vertices,indices) def set_transforms(self, transforms): """ """ self._transform = transforms def update(self): """ """ _,_,w,h = gl.glGetIntegerv(gl.GL_VIEWPORT) self._buffer.vertices['position'][0] = 0, 0 self._buffer.vertices['position'][1] = w, 0 self._buffer.vertices['position'][2] = w, h self._buffer.vertices['position'][3] = 0, h self._buffer.vertices['position'] += .315, .315 self._buffer.vertices['tex_coord'][0] = 0, 0 self._buffer.vertices['tex_coord'][1] = w, 0 self._buffer.vertices['tex_coord'][2] = w, h self._buffer.vertices['tex_coord'][3] = 0, h self._buffer.upload() def draw(self): x,y,scale,rotation = self._transform _,_,w,h = gl.glGetIntegerv(gl.GL_VIEWPORT) shader = self._shader shader.bind() shader.uniformf( 'size', w,h) shader.uniformf( 'offset', x,y) x,y,t = self._major_lines r,g,b,a = self._major_lines_color shader.uniformf( 'major_lines', x*scale, y*scale, max(t,1.0) ) shader.uniformf( 'major_lines_color', r,g,b,a*min(t,1.0) ) x,y,t = self._major_ticks r,g,b,a = self._major_ticks_color shader.uniformf( 'major_ticks', x,y,max(t,1.0) ) shader.uniformf( 'major_ticks_color', r,g,b,a*min(t,1.0) ) x,y,t = self._minor_lines r,g,b,a = self._minor_lines_color shader.uniformf( 'minor_lines', x*scale, y*scale, max(t,1.0) ) shader.uniformf( 'minor_lines_color', r,g,b,a*min(t,1.0) ) x,y,t = self._minor_ticks r,g,b,a = self._minor_ticks_color shader.uniformf( 'minor_ticks', x,y,max(t,1.0) ) shader.uniformf( 'minor_ticks_color', r,g,b,a*min(t,1.0) ) self._buffer.draw( gl.GL_TRIANGLES ) shader.unbind()
class Collection(object): join = { 'miter' : 0, 'round' : 1, 'bevel' : 2 } caps = { '' : 0, 'none' : 0, '.' : 0, 'round' : 1, ')' : 1, '(' : 1, 'o' : 1, 'triangle in' : 2, '<' : 2, 'triangle out' : 3, '>' : 3, 'square' : 4, '=' : 4, 'butt' : 4, '|' : 5 } # --------------------------------- def __init__(self, vtype, utype): self.dash_atlas = None # Convert types to lists (in case they were already dtypes) such that # we can append new fields vtype = eval(str(np.dtype(vtype))) utype = eval(str(np.dtype(utype))) # We add a uniform index to access uniform data from texture vtype.append( ('a_index', 'f4') ) # Check if given utype is made of float32 only rutype = dtype_reduce(utype) if type(rutype[0]) is not str or rutype[2] != 'float32': raise CollectionError("Uniform type cannot de reduced to float32 only") else: count = rutype[1] size = count//4 if count % 4: size += 1 utype.append(('unnused', 'f4', size*4-count)) count = size*4 self.utype = utype self._vbuffer = VertexBuffer(vtype) self._ubuffer = DynamicBuffer( utype ) self._ubuffer_id = 0 self._ubuffer_shape = [0,count] self._dirty = True # --------------------------------- def __len__(self): return len(self._vbuffer) # --------------------------------- def __getitem__(self, key): V = self._vbuffer.vertices[key] I = self._vbuffer.indices[key] U = self._ubuffer[key] return Item(self, key, V, I, U) # --------------------------------- def __delitem__(self, key): start,end = self._vbuffer.vertices.range(key) del self._vbuffer[key] del self._ubuffer[key] self._vbuffer.vertices.data['a_index'][start:] -= 1 self._vbuffer._dirty = True self._dirty = True # --------------------------------- def get_vertices(self): return self._vbuffer.vertices vertices = property(get_vertices) # --------------------------------- def get_indices(self): return self._vbuffer.indices indices = property(get_indices) # --------------------------------- def get_uniforms(self): return self._ubuffer uniforms = property(get_uniforms) # --------------------------------- def __getattr__(self, name): if hasattr(self, '_ubuffer'): buffer = object.__getattribute__(self,'_ubuffer') if name in buffer.dtype.names: return buffer.data[name] return object.__getattribute__(self,name) # --------------------------------- def __setattr__(self, name, value): object.__setattr__(self, name, value) if hasattr(self, '_ubuffer'): buffer = object.__getattribute__(self,'_ubuffer') if name in buffer.dtype.names: buffer.data[name] = value # buffer._dirty = True object.__setattr__(self, '_dirty', True) object.__setattr__(self, name, value) # --------------------------------- def clear(self): self._vbuffer.clear() self._ubuffer.clear() self._dirty = True # --------------------------------- def append(self, vertices, indices, uniforms): vertices = np.array(vertices).astype(self._vbuffer.vertices.dtype) indices = np.array(indices).astype(self._vbuffer.indices.dtype) uniforms = np.array(uniforms).astype(self._ubuffer.dtype) vertices['a_index'] = len(self) self._vbuffer.append( vertices, indices) self._ubuffer.append( uniforms ) self._ubuffer_shape[0] = len(self) self._dirty = True # --------------------------------- def upload(self): if not self._dirty: return self._vbuffer.upload() gl.glActiveTexture( gl.GL_TEXTURE0 ) data = self._ubuffer.data.view(np.float32) shape = self._ubuffer_shape if not self._ubuffer_id: self._ubuffer_id = gl.glGenTextures(1) gl.glBindTexture( gl.GL_TEXTURE_2D, self._ubuffer_id ) gl.glPixelStorei( gl.GL_UNPACK_ALIGNMENT, 1 ) gl.glPixelStorei( gl.GL_PACK_ALIGNMENT, 1 ) gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST ) gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST ) gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE ) gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE ) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_BASE_LEVEL, 0) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAX_LEVEL, 0) gl.glTexImage2D( gl.GL_TEXTURE_2D, 0, gl.GL_RGBA32F, shape[1]//4, shape[0], 0, gl.GL_RGBA, gl.GL_FLOAT, data ) gl.glActiveTexture( gl.GL_TEXTURE0 ) gl.glBindTexture( gl.GL_TEXTURE_2D, self._ubuffer_id ) gl.glTexImage2D( gl.GL_TEXTURE_2D, 0, gl.GL_RGBA32F, shape[1]//4, shape[0], 0, gl.GL_RGBA, gl.GL_FLOAT, data ) #gl.glTexSubImage2D( gl.GL_TEXTURE_2D,0, 0, 0, shape[1]//4, shape[0], # gl.GL_RGBA, gl.GL_FLOAT, data); self._dirty = False # --------------------------------- def bake(self, vertices): raise NotImplemented # --------------------------------- def draw(self): if self._dirty: self.upload() gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glEnable(gl.GL_BLEND) _,_,width,height = gl.glGetIntegerv( gl.GL_VIEWPORT ) P = orthographic( 0, width, 0, height, -1, +1 ) V = np.eye(4).astype( np.float32 ) M = np.eye(4).astype( np.float32 ) shader = self.shader shader.bind() gl.glActiveTexture( gl.GL_TEXTURE0 ) shader.uniformi( 'u_uniforms', 0 ) gl.glBindTexture( gl.GL_TEXTURE_2D, self._ubuffer_id ) if self.dash_atlas: gl.glActiveTexture( gl.GL_TEXTURE1 ) shader.uniformi('u_dash_atlas', 1) gl.glBindTexture( gl.GL_TEXTURE_2D, self.dash_atlas.texture_id ) shader.uniform_matrixf( 'u_M', M ) shader.uniform_matrixf( 'u_V', V ) shader.uniform_matrixf( 'u_P', P ) shape = self._ubuffer_shape shader.uniformf( 'u_uniforms_shape', shape[1]//4, shape[0]) self._vbuffer.draw( ) shader.unbind()
# vertices v = [ [ 1, 1, 1], [-1, 1, 1], [-1,-1, 1], [ 1,-1, 1], [ 1,-1,-1], [ 1, 1,-1], [-1, 1,-1], [-1,-1,-1] ] # normals n = [ [ 0, 0, 1], [ 1, 0, 0], [ 0, 1, 0] , [-1, 0, 1], [ 0,-1, 0], [ 0, 0,-1] ] # colors c = [ [0, 1, 1, 1], [0, 0, 1, 1], [0, 0, 0, 1], [0, 1, 0, 1], [1, 1, 0, 1], [1, 1, 1, 1], [1, 0, 1, 1], [1, 0, 0, 1] ]; V = np.array([(v[0],n[0],c[0]), (v[1],n[0],c[1]), (v[2],n[0],c[2]), (v[3],n[0],c[3]), (v[0],n[1],c[0]), (v[3],n[1],c[3]), (v[4],n[1],c[4]), (v[5],n[1],c[5]), (v[0],n[2],c[0]), (v[5],n[2],c[5]), (v[6],n[2],c[6]), (v[1],n[2],c[1]), (v[1],n[3],c[1]), (v[6],n[3],c[6]), (v[7],n[3],c[7]), (v[2],n[3],c[2]), (v[7],n[4],c[7]), (v[4],n[4],c[4]), (v[3],n[4],c[3]), (v[2],n[4],c[2]), (v[4],n[5],c[4]), (v[7],n[5],c[7]), (v[6],n[5],c[6]), (v[5],n[5],c[5]) ], dtype = vtype) I = np.resize( np.array([0,1,2,0,2,3], dtype=np.uint32), 6*(2*3)) I += np.repeat( 4*np.arange(2*3), 6) cube = VertexBuffer(vtype) cube.append(V,I) I = np.resize( np.array([0,1,1,2,2,3,3,0], dtype=np.uint32), 6*(2*4)) I += np.repeat( 4*np.arange(6), 8) outline = VertexBuffer(vtype) outline.append(V,I) shader = Shader(open("./cube.vert").read(), open("./cube.frag").read()) glut.glutMainLoop()
u_projection = np.eye(4, dtype=np.float32) u_view = np.eye(4, dtype=np.float32) theta, phi = 0, 0 vtype = [('position', np.float32, 3), ('normal', np.float32, 3), ('color', np.float32, 4)] vertices, normals, faces = load_obj('obj/icosahedron.obj') V = np.zeros(len(vertices), dtype=vtype) V['position'] = vertices * .99 V['color'] = 1, 1, 1, 1 V['normal'] = normals obj = VertexBuffer(vtype) obj.append(V, faces) outline = DashLines() F = np.roll(faces.repeat(2, axis=1), -1, axis=1) F = F.reshape(len(F) * 3, 2) F = np.sort(F, axis=1) G = F.view(dtype=[('p0', F.dtype), ('p1', F.dtype)]) G = np.unique(G) for face in G: p0 = vertices[face['p0']] p1 = vertices[face['p1']] outline.append([p0, p1], fg_color=(0, 0, 0, 1), linewidth=0.01, dash_pattern="dashed",