def __init__(self, focus=[0., 0., 0.], angles=[0., 0., 0.], dist=1.): """Create a new camera. The default camera is positioned at (0.,0.,1.) looking along the -z axis in the direction of the point (0.,0.,0.) and with the upvector in the direction of the y-axis. """ self.locked = False self._modelview = Matrix4() self.focus = focus self.dist = dist self.viewChanged = True self._projection = Matrix4() self._perspective = True self.lensChanged = True self.setModelview(angles=angles) self.setLens(45., 4. / 3.) self.setClip(0.1, 10.) self.area = None self.resetArea() self.keep_aspect = True self.tracking = False self.p = self.v = None
def lookAt(self, focus=None, eye=None, up=None): """Set the Modelview matrix to look at the specified focus point. The Modelview matrix is set with the camera positioned at eye and looking at the focus points, while the camera up vector is in the plane of the camera axis (focus-eye) and the specified up vector. If any of the arguments is left unspecified, the current value will be used. """ if not self.locked: if focus is None: focus = self.focus else: focus = at.checkArray(focus, (3, ), 'f') if eye is None: eye = self.eye else: eye = at.checkArray(eye, (3, ), 'f') if up is None: up = self.upvector else: up = at.normalize(at.checkArray(up, (3, ), 'f')) vector = eye - focus self.focus = focus self.dist = at.length(vector) axis2 = at.normalize(vector) axis0 = at.normalize(np.cross(up, axis2)) axis1 = at.normalize(np.cross(axis2, axis0)) m = Matrix4() m.rotate(np.column_stack([axis0, axis1, axis2])) m.translate(-eye) self.setModelview(m)
def render2D(self, actors): """Render 2D decorations. """ if not actors: return #print("Render %s decorations" % len(actors)) # Set modelview/projection modelview = Matrix4() self.shader.uniformMat4('modelview', modelview.gl()) left = 0. # -0.5 right = float(self.canvas.width()) # -0.5 bottom = 0. # -0.5 top = float(self.canvas.height()) # -0.5 near = -1. far = 1. projection = orthogonal_matrix(left, right, bottom, top, near, far) self.shader.uniformMat4('projection', projection.gl()) GL.glDisable(GL.GL_DEPTH_TEST) GL.glDisable(GL.GL_CULL_FACE) GL.glDepthMask(GL.GL_FALSE) # ALPHABLEND # # We need blending for text rendering! # # 2D actors are by default opak! opaque = [a for a in actors if a.opak is None or a.opak] transp = [a for a in actors if a.opak is False] # First render the opaque objects self.renderObjects(opaque) # Then the transparent ones # Disable writing to the depth buffer # as everything behind the transparent object # also needs to be drawn GL.glEnable(GL.GL_BLEND) GL.glBlendEquation(GL.GL_FUNC_ADD) if pf.cfg['render/textblend'] == 'mult': GL.glBlendFunc(GL.GL_ZERO, GL.GL_SRC_COLOR) elif pf.cfg['render/textblend'] == 'add': GL.glBlendFunc(GL.GL_ONE, GL.GL_ONE) elif pf.cfg['render/textblend'] == 'trad1': GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE) elif pf.cfg['render/textblend'] == 'zero': GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ZERO) else: GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA) self.renderObjects(transp) GL.glDisable(GL.GL_BLEND) GL.glDepthMask(GL.GL_TRUE)
def rotate(self, val, vx, vy, vz): """Rotate the camera around current camera axes.""" if not self.locked: rot = self._modelview.rot m = Matrix4() m.translate([0, 0, -self.dist]) m.rotate(val % 360, [vx, vy, vz]) m.rotate(rot) m.translate(-self.focus) self.setModelview(m)
def pick_matrix(x, y, w, h, viewport): """Create a pick Projection matrix """ m = Matrix4() m[0, 0] = viewport[2] / w m[1, 1] = viewport[3] / h m[3, 0] = (viewport[2] + 2.0 * (viewport[0] - x)) / w m[3, 1] = (viewport[3] + 2.0 * (viewport[1] - y)) / h return m
def orthogonal_matrix(left, right, bottom, top, near, far): """Create an orthogonal Projection matrix. """ m = Matrix4() m[0, 0] = 2 / (right - left) m[1, 1] = 2 / (top - bottom) m[2, 2] = -2 / (far - near) m[3, 0] = -(right + left) / (right - left) m[3, 1] = -(top + bottom) / (top - bottom) m[3, 2] = -(far + near) / (far - near) return m
def setModelview(self, m=None, angles=None): """Set the Modelview matrix. The Modelview matrix can be set from one of the following sources: - if `mat` is specified, it is a 4x4 matrix with a valuable Modelview transformation. It will be set as the current camera Modelview matrix. - else, if `angles` is specified, it is a sequence of the three camera angles (latitude, longitude and twist). The camera Modelview matrix is set from the current camera focus, the current camera distance, and the specified angles. This option is typically used to change the viewing direction of the camera, while keeping the focus point and camera distance. - else, if the viewChanged flags is set, the camera Modelview matrix is set from the current camera focus, the current camera distance, and the current camera rotation matrix. This option is typically used after changing the camera focus point and/or distance, while keeping the current viewing angles. - else, the current Modelview matrix remains unchanged. In all cases, if a modelview callback was set, it is called, and the viewChanged flag is cleared. """ if self.locked: return if m is None and (self.viewChanged or angles is not None): m = Matrix4() m.translate([0, 0, -self.dist]) if angles is None: m.rotate(self._modelview.rot) else: long, lat, twist = angles m.rotate(-twist % 360, [0.0, 0.0, 1.0]) m.rotate(lat % 360, [1.0, 0.0, 0.0]) m.rotate(-long % 360, [0.0, 1.0, 0.0]) m.translate(-self.focus) if m is not None: self.modelview = m try: self.modelview_callback(self) except: pass self.viewChanged = False
def perspective_matrix(left, right, bottom, top, near, far): """Create a perspective Projection matrix. """ m = Matrix4() m[0, 0] = 2 * near / (right - left) m[1, 1] = 2 * near / (top - bottom) m[2, 0] = (right + left) / (right - left) m[2, 1] = (top + bottom) / (top - bottom) m[2, 2] = -(far + near) / (far - near) m[2, 3] = -1. m[3, 2] = -2 * near * far / (far - near) m[3, 3] = 0. return m
def renderBG(self, actors): """Render 2D background actors. """ if not actors: return #print("Render %s backgrounds" % len(actors)) # Set modelview/projection modelview = projection = Matrix4() self.shader.uniformMat4('modelview', modelview.gl()) self.shader.uniformMat4('projection', projection.gl()) self.canvas.zoom_2D() # should be combined with above # in clip space GL.glDisable(GL.GL_DEPTH_TEST) self.renderObjects(actors)
def projection(self, value): """Set the projection matrix to the specified matrix. value should be a proper projection matrix """ self._projection = Matrix4(value)
def modelview(self, value): """Set the modelview matrix to the specified matrix. value should be a proper modelview matrix """ self._modelview = Matrix4(value)
def getGLprojection(self): return Matrix4(GL.glGetDoublev(GL.GL_PROJECTION_MATRIX))
def getGLmodelview(self): return Matrix4(GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX))