Commit 44e66fbb by blanch

working on core profile

parent 9cfe42d0
 # -*- coding: utf-8 -*- """ Basic matrix operations emulating OpenGL 3D transforms. Copyright (c) 2010, Renaud Blanch Licence: GPLv3 or higher """ # imports #################################################################### from math import (cos as _cos, sin as _sin, radians as _radians, sqrt as _sqrt) _sum = sum # matrix construction ######################################################## def identity(): return [[1., 0., 0., 0.], [0., 1., 0., 0.], [0., 0., 1., 0.], [0., 0., 0., 1.]] def scale(sx=1., sy=1., sz=1.): return [[sx, 0., 0., 0.], [0., sy, 0., 0.], [0., 0., sz, 0.], [0., 0., 0., 1.]] def translate(tx=0., ty=0., tz=0.): return [[1., 0., 0., tx], [0., 1., 0., ty], [0., 0., 1., tz], [0., 0., 0., 1.]] def rotate(a=0., x=0., y=0., z=1.): a = _radians(a) s, c = _sin(a), _cos(a) h = _sqrt(x*x + y*y + z*z) x, y, z = x/h, y/h, z/h sx, sy, sz = s*x, s*y, s*z oc = 1.-c return [[oc*x*x+c, oc*x*y-sz, oc*x*z+sy, 0.], [oc*x*y+sz, oc*y*y+c, oc*y*z-sx, 0.], [oc*x*z-sy, oc*y*z+sx, oc*z*z+c, 0.], [0., 0., 0., 1.]] def ortho(l, r, b, t, n, f): w, h, d = r-l, t-b, f-n return [[2./w, 0., 0., -(r+l)/w], [0., 2./h, 0., -(t+b)/h], [0., 0., -2./d, -(f+n)/d], [0., 0., 0., 1. ]] def frustum(l, r, b, t, n, f): w, h, d = r-l, t-b, f-n return [[2.*n/w, 0., (r+l)/w, 0. ], [0., 2.*n/h, (t+b)/h, 0. ], [0., 0., -(f+n)/d, -2.*f*n/d], [0., 0., -1., 0. ]] # manipulation ############################################################### def matrix(n, m, f=lambda i, j: 0.): I, J = range(n), range(m) return [[f(i, j) for j in J] for i in I] def size(A): return len(A), len(A[0]) def transpose(A): n, m = size(A) return matrix(m, n, lambda i, j: A[j][i]) def column_major(A): return [float(a) for line in transpose(A) for a in line] def exclude(A, i, j): return [R[:j]+R[j+1:] for R in A[:i]+A[i+1:]] def top_left(A): n, m = size(A) return exclude(A, n-1, m-1) # sum ######################################################################## def add(A, B): n, p = size(A) q, m = size(B) assert (n, p) == (q, m) return matrix(n, m, lambda i, j: A[i][j]+B[i][j]) def sub(A, B): n, p = size(A) q, m = size(B) assert (n, p) == (q, m) return matrix(n, m, lambda i, j: A[i][j]-B[i][j]) # product #################################################################### def scalar(s, A): n, m = size(A) return matrix(n, m, lambda i, j: s*A[i][j]) def mul(A, B): n, p = size(A) q, m = size(B) assert p == q K = range(p) return matrix(n, m, lambda i, j: _sum(A[i][k]*B[k][j] for k in K)) def product(A, *Bs): for B in Bs: A = mul(A, B) return A # inverse #################################################################### def det(A): n, m = size(A) assert n == m if n == 1: return A[0][0] else: return sum(A[i][0]*cofactor(A, i, 0) for i in range(n)) def minor(A, i, j): return det(exclude(A, i, j)) def cofactor(A, i, j): return (-1)**(i+j)*minor(A, i, j) def inverse(A): n, m = size(A) assert n == m C = matrix(n, m, lambda i, j: cofactor(A, i, j)) I = range(n) d = sum(A[i][0]*C[i][0] for i in I) return scalar(1./d, transpose(C))
 # -*- coding: utf-8 -*- """ Quaternion to have nice rotations in 3D. Copyright (c) 2010, Renaud Blanch Licence: GPLv3 or higher """ # imports #################################################################### from math import (cos as _cos, sin as _sin, atan2 as _atan2, asin as _asin, sqrt as _sqrt) from . import vector as _v # quaternion ################################################################# def quaternion(theta=0, u=(1., 0., 0.)): w = _cos(theta/2.) x, y, z = (ui*_sin(theta/2.) for ui in u) return w, (x, y, z) def arcball(x, y): h2 = x*x+y*y if h2 > 1.: h = _sqrt(h2) v = x/h, y/h, 0. else: v = x, y, _sqrt(1.-h2) return 0., v def mul(P, Q): w1, v1 = P w2, v2 = Q return (w1*w2 - _v.dot(v1, v2), _v.sum(_v.mul(w1, v2), _v.mul(w2, v1), _v.cross(v1, v2))) def product(P=quaternion(), *Qs): for Q in Qs: P = mul(P, Q) return P def matrix(Q): w, (x, y, z) = Q return [[1.-2.*(y*y+z*z), 2.*(x*y+w*z), 2.*(x*z-w*y), 0.], [2.*(x*y-w*z), 1.-2.*(x*x+z*z), 2.*(y*z+w*x), 0.], [2.*(x*z+w*y), 2.*(y*z-w*x), 1.-2.*(x*x+y*y), 0.], [0., 0., 0., 1.]] def euler_angles(Q): w, (x, y, z) = Q phi = _atan2(2.*(w*x+y*z), 1.-2.*(x*x+y*y)) theta = _asin(2*(w*y-x*z)) psi = _atan2(2.*(w*z+x*y), 1.-2.*(y*y+z*z)) return phi, theta, psi def antipod(Q): w, v = Q return -w, _v.mul(-1., v) def inverse(Q): w, v = Q return w, _v.mul(-1., v) def rotate(Q, v): _, v = product(Q, (0, v), inverse(Q)) return v def theta_u(Q): w, v = Q norm = _v.norm(v) theta = 2.*_atan2(norm, w) u = _v.mul(1./norm, v) return theta, u def power(Q, a): theta, u = theta_u(Q) return quaternion(a*theta, u) def slerp(Q0, Q1, a): return mul(power(mul(Q1, inverse(Q0)), a), Q0)
 # -*- coding: utf-8 -*- """ Basic 3D vector operations. Copyright (c) 2010, Renaud Blanch Licence: GPLv3 or higher """ # imports #################################################################### from math import sqrt as _sqrt _sum = sum # globals #################################################################### def _zip_zero_pad(*ps): len_max = max(len(p) for p in ps) ps = [tuple(p) + (0.,)*(len_max-len(p)) for p in ps] for t in zip(*ps): yield t _O = tuple() _3D = 3 _X, _Y, _Z = range(_3D) # vector ##################################################################### def vector(p1=_O, p0=_O): return tuple(p1i-p0i for (p1i, p0i) in _zip_zero_pad(p1, p0)) def mul(a, v): return tuple(a*vi for vi in v) def add(u, v): return tuple(ui+vi for (ui, vi) in _zip_zero_pad(u, v)) def sum(u=vector(), *vs): for v in vs: u = add(u, v) return u def sub(u, v): return tuple(ui-vi for (ui, vi) in _zip_zero_pad(u, v)) def dot(u, v): return _sum(ui*vi for (ui, vi) in _zip_zero_pad(u, v)) def cross(u, v): assert len(u) == len(v) == _3D return (u[_Y]*v[_Z]-u[_Z]*v[_Y], u[_Z]*v[_X]-u[_X]*v[_Z], u[_X]*v[_Y]-u[_Y]*v[_X]) def norm(v): return _sqrt(dot(v, v)) def matrix(v): return [[vi] for vi in v]
 ... ... @@ -30,6 +30,13 @@ from OpenGL.GL import ( glGenTextures, glTexParameter, glGenBuffers, glBindBuffer, glBufferData, glTexImage1D, glDeleteBuffers, glDrawArrays, GL_ARRAY_BUFFER, GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER, GL_STREAM_DRAW, glDrawElements, GL_UNSIGNED_INT, glBindAttribLocation, glBindVertexArray, glGenVertexArrays, glEnableVertexAttribArray, glGetAttribLocation, glVertexAttribPointer, GL_FLOAT, glUseProgram, ) from PyQt5.QtCore import ( ... ... @@ -94,10 +101,12 @@ class AbstractMapView(QOpenGLWidget): glActiveTexture(GL_TEXTURE0+DATA_UNIT) set_uniform(self.program, 'values', DATA_UNIT) glActiveTexture(GL_TEXTURE0+PALETTE_UNIT) set_uniform(self.program, b'palette', PALETTE_UNIT) set_uniform(self.program, 'palette', PALETTE_UNIT) set_uniform(self.program, 'v_0', 0.) set_uniform(self.program, 'v_1', 1.) self.set_colormap() self.va = None def update_vs(self): """update min and max to keep program in sync with model""" ... ...
 ... ... @@ -3,11 +3,16 @@ # imports ################################################################### from .AbstractMapView import * import ctypes from PyQt5.QtCore import QSize from ..Interaction import * from ..linalg import matrix as m from .AbstractMapView import * # map ####################################################################### ... ... @@ -79,6 +84,7 @@ class MapView(AbstractMapView): # selection texture glActiveTexture(GL_TEXTURE0+SEL_UNIT) set_uniform(program, 'selection', SEL_UNIT) return program def sizeHint(self): ... ... @@ -103,16 +109,21 @@ class MapView(AbstractMapView): glViewport(0, 0, width, height) tw, th = self.model.tex_width, self.model.tex_height glMatrixMode(GL_TEXTURE) glLoadIdentity() glScale(1./tw, 1./th, 1.) glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(0, width, 0, height, -1, 1) glMatrixMode(GL_MODELVIEW) glLoadIdentity() # glMatrixMode(GL_TEXTURE) # glLoadIdentity() # glScale(1./tw, 1./th, 1.) self.texture = m.scale(1./tw, 1./th) # glMatrixMode(GL_PROJECTION) # glLoadIdentity() # glOrtho(0, width, 0, height, -1, 1) projection = m.ortho(0, width, 0, height, -1, 1) set_uniform(self.program, 'projection_matrix', m.column_major(projection)) # glMatrixMode(GL_MODELVIEW) # glLoadIdentity() modelview = m.identity() set_uniform(self.program, 'modelview_matrix', m.column_major(modelview)) self.repaint() ... ... @@ -127,7 +138,7 @@ class MapView(AbstractMapView): """ # band using OpenGL texturing glClear(GL_COLOR_BUFFER_BIT) glEnable(GL_TEXTURE_2D) # glEnable(GL_TEXTURE_2D) glUseProgram(self.program) # selection texture ... ... @@ -142,21 +153,66 @@ class MapView(AbstractMapView): z = self.model.z w, h = self.width(), self.height() glMatrixMode(GL_TEXTURE) glPushMatrix() glTranslate(cx, cy, 0.) glScale(1./z, 1./z, 1.) glTranslate(-w//2, -h//2, 0.) # glMatrixMode(GL_TEXTURE) # glPushMatrix() # glTranslate(cx, cy, 0.) # glScale(1./z, 1./z, 1.) # glTranslate(-w//2, -h//2, 0.) texture = m.product( self.texture, m.translate(cx, cy), m.scale(1./z, 1./z), m.translate(-w//2, -h//2) ) set_uniform(self.program, 'texture_matrix', m.column_major(texture)) """ glBegin(GL_TRIANGLE_STRIP) for x in [0, w]: for y in [0, h]: glTexCoord(x, y) glVertex(x, y) glEnd() glPopMatrix() """ if self.va == None: self.va = glGenVertexArrays(1) glBindVertexArray(self.va) for attrib in ['vertex', 'tex_coord']: glEnableVertexAttribArray(glGetAttribLocation(self.program, attrib)) data_buffer = np.ravel([ [(x, y, 0.), # vertex (x, y, 0.)] # tex_coord for y in [0., h] for x in [0., w] ]).astype(np.float32) # indicies_buffer = np.array([0, 1, 2, 3], dtype=np.uint) self.array_id = glGenBuffers(1) # self.elements_id = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, self.array_id) glBufferData(GL_ARRAY_BUFFER, data_buffer, GL_STREAM_DRAW) # glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.elements_id) # glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicies_buffer, GL_STATIC_DRAW) del data_buffer # del indicies_buffer float_size = ctypes.sizeof(ctypes.c_float) vertex_offset = ctypes.c_void_p(0 * float_size) tex_coord_offset = ctypes.c_void_p(3 * float_size) record_len = 6 * float_size glBindBuffer(GL_ARRAY_BUFFER, self.array_id) glVertexAttribPointer(glGetAttribLocation(self.program, 'vertex'), 3, GL_FLOAT, False, record_len, vertex_offset) glVertexAttribPointer(glGetAttribLocation(self.program, 'tex_coord'), 3, GL_FLOAT, False, record_len, tex_coord_offset) glDrawArrays(GL_TRIANGLE_STRIP, 0, 4) # glPopMatrix() glUseProgram(0) glDisable(GL_TEXTURE_2D) # glDisable(GL_TEXTURE_2D) # glBindTexture(GL_TEXTURE_2D, 0) ... ...
 ... ... @@ -11,6 +11,8 @@ from PyQt5.QtGui import ( QColor ) import math # mini map ################################################################## ... ...
 ... ... @@ -106,7 +106,7 @@ MINIMAP_SHADER = """ const vec4 color = vec4(1., 1., 1., 1.); in front_color; in vec4 front_color; out vec4 frag_color; ... ...
 ... ... @@ -15,9 +15,11 @@ from OpenGL.GL import ( glGetUniformLocation, glUseProgram, GL_COMPILE_STATUS, GL_LINK_STATUS, glUniform1fv, glUniform2fv, glUniform3fv, glUniform4fv, glUniform1iv, glUniformMatrix3fv, glUniform1iv, glUniformMatrix3fv, glUniformMatrix4fv, ) from ..linalg import matrix as m # utils ##################################################################### ... ... @@ -74,6 +76,8 @@ _Uniforms = { (4, ctypes.c_float): glUniform4fv, (9, ctypes.c_float): lambda location, n, values: glUniformMatrix3fv(location, n, GL_FALSE, values), (16, ctypes.c_float): lambda location, n, values: glUniformMatrix4fv(location, n, GL_FALSE, values), (1, ctypes.c_int): glUniform1iv, } ... ... @@ -84,7 +88,7 @@ def set_uniform(program, uniform, *values): """ v0, n = values[0], len(values) if isinstance(v0, tuple): if isinstance(v0, (tuple, list)): l, t = len(v0), _c_types[type(v0[0])] values = (t * (l*n))(*(u for value in values for u in value)) else: ... ...
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!