def paintGL(self): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self.shaderProgram.bind() p_matrix = QMatrix4x4() p_matrix.perspective(60.0, 1.33, 0.1, 1000) self.shaderProgram.setUniformValue(self.p_matrix_id, p_matrix) self.shaderProgram.setUniformValue(self.main_light_dir, QVector4D(0, 1.0, -1.0, 0.0)) self.shaderProgram.setUniformValue(self.sub_light_dir, QVector4D(0, 1.0, 1.0, 0.0)) self.shaderProgram.setUniformValue(self.back_light_dir, QVector4D(0, -1.0, 0.0, 0.0)) self.shaderProgram.setUniformValue(self.ambient_id, QVector4D(0.15, 0.15, 0.15, 0.0)) self.shaderProgram.setUniformValue(self.diffuse_id, QVector4D(1.0, 1.0, 1.0, 1.0)) mv_matrix = self.camera.getMatrix() self.shaderProgram.setUniformValue(self.mv_matrix_id, mv_matrix) viewport_width = self.width() / self.obj_num for i in range(self.obj_num): glViewport(int(i * viewport_width), 0, int(viewport_width), self.height()) if self.objs[i] is not None: self.objs[i].render() self.shaderProgram.release()
def setUniformBindings(self, wireframe=False): """Sets up uniform shader bindings""" normalMatrix = self._transform.normalMatrix() self._active_shader.setUniformValue("modelMatrix", self._transform) self._active_shader.setUniformValue("viewMatrix", self._scene.camera.viewMatrix) self._active_shader.setUniformValue("projectionMatrix", self._scene.camera.projectionMatrix) self._active_shader.setUniformValue("normalMatrix", normalMatrix) if self.texture() is not None: self._active_shader.setUniformValue("texObject", 0) ## bind active material if self.isSelectable() and self.isSelected(): self._active_shader.setUniformValue("selected", 1.0) else: self._active_shader.setUniformValue("selected", 0.65) ## set highlight color if self.isHighlighted(): self._active_shader.setUniformValue("material.emission", QVector3D(0.25, 0.25, 0.25)) else: self._active_shader.setUniformValue("material.emission", self._active_material.emissionColor) self._active_shader.setUniformValue("material.ambient", self._active_material.ambientColor) ## set the enabled color if self.isEnabled(): self._active_shader.setUniformValue("material.emission", QVector3D(0.25, 0.25, 0.25)) self._active_shader.setUniformValue("material.diffuse", self._active_material.diffuseColor) else: self._active_shader.setUniformValue("material.diffuse", self._active_material.diffuseColor) self._active_shader.setUniformValue("material.specular", self._active_material.specularColor) self._active_shader.setUniformValue("material.shininess", self._active_material.shininess) ## set the error and warning colors if self._errorHighlight: self._active_shader.setUniformValue("material.ambient", self._errorMaterial.ambientColor) self._active_shader.setUniformValue("material.diffuse", self._errorMaterial.diffuseColor) self._active_shader.setUniformValue("material.specular", self._errorMaterial.specularColor) self._active_shader.setUniformValue("material.shininess", self._errorMaterial.shininess) if self._warningHighlight: self._active_shader.setUniformValue("material.ambient", self._warningMaterial.ambientColor) self._active_shader.setUniformValue("material.diffuse", self._warningMaterial.diffuseColor) self._active_shader.setUniformValue("material.specular", self._warningMaterial.specularColor) self._active_shader.setUniformValue("material.shininess", self._warningMaterial.shininess) ## bind lights camera_position = QVector4D(self._scene.camera.position[0], self._scene.camera.position[1], self._scene.camera.position[2], 1.0) if self._scene.light.headlight: if self._scene.light.directional: self._active_shader.setUniformValue("lightPosition", QVector4D(0.0, 0.0, 1.0, 0.0)) else: self._active_shader.setUniformValue("lightPosition", QVector4D(0.0, 0.0, 0.0, 1.0)) else: self._active_shader.setUniformValue("lightPosition", self._scene.camera.viewMatrix * self._scene.light.position) self._active_shader.setUniformValue("light.ambient", self._scene.light.ambientColor) self._active_shader.setUniformValue("light.diffuse", self._scene.light.diffuseColor) self._active_shader.setUniformValue("light.specular", self._scene.light.specularColor) self._active_shader.setUniformValue("lightAttenuation", self._scene.light.attenuation)
def __init__(self, processor, df, parent=None): super().__init__(parent) self.parent = parent self.processor = processor # Data self.df = df # UI self.setupUi(self) self.setupControls() self.keyPressEvent = self.keyPressed self.mouseMoveEvent = self.mouseMoved # Control & Display self.mouse_grabbed = False self.camera_pos = QVector3D(0.5, 0.5, -2) # Start camera position self.center = QVector3D(0.5, 0, 0.5) # Center of object self.rot_center = QVector3D(0.5, 0.5, 0.5) # Center of rotation self.camera_rot = QVector3D(0, 0, 1) # Camera rotation self.scale_vec = QVector3D(1, 1, 1) # Object scale self.real_prop = processor.get_real_scaling() # val to lat self.light_pos = QVector3D(self.xLightSpinBox.value(), self.yLightSpinBox.value(), self.zLightSpinBox.value()) self.ambient = self.ambientSlider.value() / 100 self.diffuse = self.diffuseSlider.value() / 100 self.alpha = self.alphaSlider.value() / 100 # Transparency # Drawing self.normals = [] self.colors = [] self.coords_array = [] # !> len(self.normals) == len(self.colors) == len(self.coords_array) self.update_light = False # Update for light is needed self.update_buffer = False # Update for whole buffer is needed self.show_grid = self.gridCheckBox.isChecked() self.show_contour = self.contourCheckBox.isChecked() self.contour_levels = self.contourLevelSpinBox.value() self.show_light_lines = True self.grid_freq = 10 self.grid_color = QVector4D(1, 1, 1, 1) self.contour_color = QVector4D(1, 1, 1, 1) self.light_line_color = QVector4D(1, 0.6, 0, 1) self.prepareScene() self.updateUi() self.shaders = QOpenGLShaderProgram() self.openGLWidget.initializeGL = self.initializeGL self.openGLWidget.paintGL = self.paintGL
def pos_at(self, t): """ Gets the position of the spline at the given value of the interpolation parameter. t should vary from 0 to 1 Arguments: t: float, the interpolation parameter Returns: a QVector3D representing the position of this spline at the given value """ # if t out of bounds, return the endpoints if t < 0: return self.ctrl_pts[0] if t >= 1: return self.ctrl_pts[-1] # scale t to be from (i_start) to (i_end from the end of the ctrl_pts list) t = util.lerp(t, 0, 1, self.i_start, len(self.ctrl_pts) + self.i_end) # get integer and fractional parts of this i = int(t) t %= 1 # i is now the index of the first ctrl point to be used # t is the interpolation parameter # get control points, depends on spline implementation p1, p2, p3, p4 = self._get_ctrl_pts(i) B = QMatrix4x4(p1.x(), p1.y(), p1.z(), 1, p2.x(), p2.y(), p2.z(), 1, p3.x(), p3.y(), p3.z(), 1, p4.x(), p4.y(), p4.z(), 1) U = QVector4D(t * t * t, t * t, t, 1) # left-multiplying a QVector4D with a QMatrix4x4 uses the QVector4D as a 1x4 row vector. return QVector3D(U * (self.M * B))
def getLightSourceCoords(self): polygons = np.array([((0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0)), ((0, 0, 1), (0, 1, 1), (1, 1, 1), (1, 0, 1)), ((0, 0, 0), (0, 0, 1), (1, 0, 1), (1, 0, 0)), ((0, 1, 0), (0, 1, 1), (1, 1, 1), (1, 1, 0)), ((0, 0, 0), (0, 0, 1), (0, 1, 1), (0, 1, 0)), ((1, 0, 0), (1, 0, 1), (1, 1, 1), (1, 1, 0))]) normals = [(0, 0, -1), (0, 0, 1), (0, -1, 0), (0, 1, 0), (-1, 0, 0), (1, 0, 0)] normals_vec = [] [[ normals_vec.append(QVector3D(*normals[i])) for _ in range(len(polygons[i])) ] for i in range(len(polygons))] center = np.array( (self.light_pos.x(), self.light_pos.y(), self.light_pos.z())) delta = np.array((0.5, 0.5, 0.5)) polygons = [[(p - delta) * 0.05 + center for p in side] for side in polygons] colors = [] [ colors.append(QVector4D(1, 153 / 255, 0, 1) * self.diffuse) for _ in range(len(normals_vec)) ] return polygons, normals_vec, colors
def _setUniformValueDirect(self, uniform, value): if type(value) is Vector: self._shader_program.setUniformValue( uniform, QVector3D(value.x, value.y, value.z)) elif type(value) is Matrix: self._shader_program.setUniformValue( uniform, self._matrixToQMatrix4x4(value)) elif type(value) is Color: self._shader_program.setUniformValue( uniform, QColor(value.r * 255, value.g * 255, value.b * 255, value.a * 255)) elif type(value) is list and type(value[0]) is list and len( value[0]) == 4: self._shader_program.setUniformValue( uniform, self._matrixToQMatrix4x4(Matrix(value))) elif type(value) is list and len(value) == 2: self._shader_program.setUniformValue(uniform, QVector2D(value[0], value[1])) elif type(value) is list and len(value) == 3: self._shader_program.setUniformValue( uniform, QVector3D(value[0], value[1], value[2])) elif type(value) is list and len(value) == 4: self._shader_program.setUniformValue( uniform, QVector4D(value[0], value[1], value[2], value[3])) elif type(value) is list and type(value[0]) is list and len( value[0]) == 2: self._shader_program.setUniformValueArray( uniform, [QVector2D(i[0], i[1]) for i in value]) else: self._shader_program.setUniformValue(uniform, value)
def render(self): ratio = int(self.devicePixelRatio().real) GL.glViewport(0, 0, self.width()*ratio, self.height()*ratio) GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) self.m_offsets = QVector4D(sin(self.m_frame/20)*0.5, cos(self.m_frame/20)*0.5, 0.0, 0.0) self.m_vertices = [(0.25, -0.25, 0, 1.0), (-0.25, -0.25, 0, 1.0), (0.25, 0.25, 0, 1.0)] self.m_colors = [(0.0, 0.0, 1.0, 1.0), (1.0, 0.0, 0.0, 1.0), (0.0, 1.0, 0.0, 1.0)] self.m_program.setAttributeValue(self.m_offset, self.m_offsets) self.m_program.setAttributeArray(self.m_vertex, self.m_vertices) self.m_program.setAttributeArray(self.m_color, self.m_colors) self.m_program.bind() GL.glDrawArrays(GL.GL_TRIANGLES, 0, 3) self.m_program.release() self.m_frame += 1
def getColorByValue(self, value): """Get QVector4D-color from green (value == 0) to red (value == 1) :param value: 0 - 1 """ hue = 120 * (1 - value) / 360 color = QColor.fromHslF(hue, 1, 0.5) color_vec = QVector4D(color.redF(), color.greenF(), color.blueF(), 0.5) return color_vec
def from_numpy(v): if v.size == 3: return QVector3D(v[0], v[1], v[2]) if v.size == 4: return QVector4D(v[0], v[1], v[2], v[3]) if v.shape == (3, 3): return QMatrix3x3(v.flatten().tolist()) if v.shape == (4, 4): return QMatrix4x4(v.flatten().tolist())
def GetUnprojection(winXY: QPoint, winZ: float, winWH: QPoint, vpMat: QMatrix4x4) -> QVector3D: #- from gluUnproject definition, I don't consider glViewport ndcspaceCursorPos = QVector4D( (QVector2D(winXY) / QVector2D(winWH)) * 2 - QVector2D(1, 1), winZ * 2 - 1, 1) invertedVpMat, success = vpMat.inverted() if not success: raise NotImplementedError wspaceCursorPos = invertedVpMat * ndcspaceCursorPos return QVector3D(wspaceCursorPos) / wspaceCursorPos.w()
def ray(self, point): ray_start = QVector4D(point) ray_start.setZ(-1.0) ray_start.setW(1.0) ray_end = QVector4D(point) ray_end.setZ(0.0) ray_end.setW(1.0) inverseProjectionMatrix = self._camera.projectionMatrix.inverted()[0] inverseViewMatrix = self._camera.viewMatrix.inverted()[0] ray_start_camera = inverseProjectionMatrix * ray_start ray_start_camera /= ray_start_camera.w() ray_end_camera = inverseProjectionMatrix * ray_end ray_end_camera /= ray_end_camera.w() ray_start_world = inverseViewMatrix * ray_start_camera ray_start_world /= ray_start_world.w() ray_end_world = inverseViewMatrix * ray_end_camera ray_end_world /= ray_end_world.w() ray = ray_end_world - ray_start_world ray_direction = QVector3D(ray[0], ray[1], ray[2]).normalized() return Ray(self, origin=QVector3D(ray_start_world[0], ray_start_world[1], ray_start_world[2]), direction=QVector3D(ray_direction[0], ray_direction[1], ray_direction[2]))
def render(self): self.m_frame += 1 ratio = int(self.devicePixelRatio().real) GL.glViewport(0, 0, self.width() * ratio, self.height() * ratio) GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) self.m_program.setAttributeArray(self.m_vertex_index, self.m_vertices) self.m_program.setAttributeValue( self.m_offset_index, QVector4D(0.0, 0.0, 0.0, 0.0)) self.m_program.bind() GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE) GL.glPatchParameteri(GL.GL_PATCH_VERTICES, 3) GL.glDrawArrays(GL.GL_PATCHES, 0, 3) self.m_program.release()
def resizeGL(self, width, height): scaleX = 1.0 scaleY = 1.0 scaleZ = 1.0 # Will always be 1.0 since we don't scale depth scaleW = 1.0 # A global scale factor, also always 1.0 if width > height: scaleX = height / width else: scaleY = width / height self.currentScaling = QVector4D(scaleX, scaleY, scaleZ, scaleW) # Redraw since we changed the value of the scaling uniform self.update()
def render(self): self.m_frame += 1 ratio = int(self.devicePixelRatio().real) GL.glViewport(0, 0, self.width() * ratio, self.height() * ratio) GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) self.m_program.setAttributeArray(self.m_vertex_index, self.m_vertices) self.m_program.setAttributeArray(self.m_norm_index, self.m_norms) self.m_program.setAttributeValue(self.m_color_index, QVector4D(1.0, 0.0, 0.0, 0.0)) self.m_program.bind() self.m_program.setUniformValue(self.m_mvp_index, self.m_mvp_matrix) GL.glDrawArrays(GL.GL_TRIANGLES, 0, len(self.m_vertices)) self.m_program.release()
def prepareNormalLines(self, polygons, normals, colors): """Normal lines for each polygon. Debug only """ norm_i = 0 start = len(self.coords_array) for polygon in polygons: point = polygon[0] normal = normals[norm_i] # color = colors[norm_i] color = QVector4D(1, 1, 1, 1) point_2 = QVector3D(*point) + normal * 0.04 point_2 = (point_2.x(), point_2.y(), point_2.z()) self.prepareLine((point, point_2), [color] * 2) norm_i += len(polygon) end = len(self.coords_array) return start, end
def _setUniformValueDirect( self, uniform: int, value: Union[Vector, Matrix, Color, List[float], List[List[float]], float, int] ) -> None: if type(value) is Matrix: cast(QOpenGLShaderProgram, self._shader_program).setUniformValue( uniform, self._matrixToQMatrix4x4(cast(Matrix, value))) elif type(value) is Vector: value = cast(Vector, value) cast(QOpenGLShaderProgram, self._shader_program).setUniformValue( uniform, QVector3D(value.x, value.y, value.z)) elif type(value) is Color: value = cast(Color, value) cast(QOpenGLShaderProgram, self._shader_program).setUniformValue( uniform, QColor(round(value.r * 255), round(value.g * 255), round(value.b * 255), round(value.a * 255))) elif type(value) is list and type(cast( List[List[float]], value)[0]) is list and len( cast(List[List[float]], value)[0]) == 4: value = cast(List[List[float]], value) cast(QOpenGLShaderProgram, self._shader_program).setUniformValue( uniform, self._matrixToQMatrix4x4(Matrix(value))) elif type(value) is list and len(cast(List[float], value)) == 4: value = cast(List[float], value) cast(QOpenGLShaderProgram, self._shader_program).setUniformValue( uniform, QVector4D(value[0], value[1], value[2], value[3])) elif type(value) is list and type(cast( List[List[float]], value)[0]) is list and len( cast(List[List[float]], value)[0]) == 2: value = cast(List[List[float]], value) cast(QOpenGLShaderProgram, self._shader_program).setUniformValueArray( uniform, [QVector2D(i[0], i[1]) for i in value]) elif type(value) is list and len(cast(List[float], value)) == 2: value = cast(List[float], value) cast(QOpenGLShaderProgram, self._shader_program).setUniformValue( uniform, QVector2D(value[0], value[1])) elif type(value) is list and len(cast(List[float], value)) == 3: value = cast(List[float], value) cast(QOpenGLShaderProgram, self._shader_program).setUniformValue( uniform, QVector3D(value[0], value[1], value[2])) else: cast(QOpenGLShaderProgram, self._shader_program).setUniformValue( uniform, cast(Union[float, int], value))
def __init__(self): with open("vertex.glsl","r") as f: self.vertexShaderSource = f.read() with open("fragment.glsl","r") as f: self.fragmentShaderSource = f.read() if self.vertexShaderSource is None: raise Exception("Could not load the source for the vertex shader") if self.fragmentShaderSource is None: raise Exception("Could not load the source for the fragment shader") # Use an initial scale assuming width = height (should always be overwritten # in the resizeGL method below) self.currentScaling = QVector4D(1.0, 1.0, 1.0, 1.0) super(TestCanvas,self).__init__()
def mouseMoveEvent(self, event): """ The Qt event handler when the mouse is dragged. If a slice plane is selected the slice plane is dragged otherwise the scene is rotated. :param QMouseEvent event: the qt mouse event """ if self._slice_planes.has_selection(): x, y = event.x(), event.y() m = self.viewMatrix() dx = x - self._mouse_pos[0] dy = y - self._mouse_pos[1] vec = QVector4D(dx, -dy, 0, 0) * m dx, dy, dz = vec.x(), vec.y(), vec.z() self._mouse_pos = x, y self._slice_planes.drag(dx, dy, dz) self.slice_changed.emit() else: return GLViewWidget.mouseMoveEvent(self, event)
def __init__(self, **kwargs): """Initialize actor.""" super(Light, self).__init__() self._headlight = kwargs.get("headlight", True) self._position = kwargs.get("position", QVector4D(2.0, 2.0, 2.0, 1.0)) self._ambientColor = kwargs.get("ambient", QVector3D(0.5, 0.5, 0.5)) self._diffuseColor = kwargs.get("diffuse", QVector3D(1.0, 1.0, 1.0)) self._specularColor = kwargs.get("specular", QVector3D(1.0, 1.0, 1.0)) self._attenuation = kwargs.get("attenuation", QVector3D(1.0, 0.02, 0.002)) self._directional = kwargs.get("directional", False) self._color = kwargs.get("color", QVector3D(0.5, 0.5, 0.5)) self._lradious = float(kwargs.get("lradious", 0.0)) self._aconst = float(kwargs.get("aconst", 0.06)) self._alinear = float(kwargs.get("alinear", 0.01)) self._aquad = float(kwargs.get("aquad", 0.0)) self._hemispheric = kwargs.get("hemispheric", False) self._csky = kwargs.get("csky", QVector3D(0.0, 0.0, 1.0)) self._cground = kwargs.get("cground", QVector3D(0.0, 1.0, 0.0))
def _setUniformValueDirect(self, uniform, value): if type(value) is Vector: self._shader_program.setUniformValue( uniform, QVector3D(value.x, value.y, value.z)) elif type(value) is Matrix: self._shader_program.setUniformValue( uniform, self._matrixToQMatrix4x4(value)) elif type(value) is Color: self._shader_program.setUniformValue( uniform, QColor(value.r * 255, value.g * 255, value.b * 255, value.a * 255)) elif type(value) is list and len(value) is 2: self._shader_program.setUniformValue(uniform, QVector2D(value[0], value[1])) elif type(value) is list and len(value) is 3: self._shader_program.setUniformValue( uniform, QVector3D(value[0], value[1], value[2])) elif type(value) is list and len(value) is 4: self._shader_program.setUniformValue( uniform, QVector4D(value[0], value[1], value[2], value[3])) else: self._shader_program.setUniformValue(uniform, value)
def position(self): """The position of this light in space""" return QVector4D(self._position[0], self._position[1], self._position[2], 1.0 - float(self._directional))
def _mouseEyeSpace(self, clipCoord): invertedProjectionMatrix = self.projectionMatrix.inverted()[0] eye = invertedProjectionMatrix * clipCoord return QVector4D(eye.x(), eye.y(), -1.0, 0.0)
def _mouseDirection(self, xin, yin, width, height, plane): x, y, z = self.devicePortCoordinates(xin, yin, width, height) clipCoord = QVector4D(x, y, plane, 0.0) eyeCoord = self._mouseEyeSpace(clipCoord) ray = self._mouseWorldCoord(eyeCoord) return ray
def read_Vector4D(self): return QVector4D(self.read_float(), self.read_float(), self.read_float(), self.read_float())
def calculate_model_matrix(self, viewmatrix_inv=None): """ Calculates the Model matrix based upon self.origin and self.scale. If self.billboard == False, the Model matrix will also be rotated determined by self.rotation_angle and self.rotation_axis. If self.billboard == True and self.billboard_axis == None the Model matrix will also be rotated so that the local Z axis will face the camera and the local Y axis will be parallel to the camera up axis at all times. If self.billboard == True and self.billboard_axis is either "X", "Y", or "Z", the local Z axis will always face the camera, but the items rotation will be restricted to self.billboard_axis. @param viewmatrix_inv The inverted View matrix as instance of QMatrix4x4. Mandatory when self.billboard == True, otherwise optional. """ mat_m = QMatrix4x4() mat_m.translate(self.origin) if self.billboard: # Billboard calulation is based on excellent tutorial: # http://nehe.gamedev.net/article/billboarding_how_to/18011/ # extract 2nd column which is camera up vector cam_up = viewmatrix_inv * QVector4D(0,1,0,0) cam_up = QVector3D(cam_up[0], cam_up[1], cam_up[2]) cam_up.normalize() # extract 4th column which is camera position cam_pos = viewmatrix_inv * QVector4D(0,0,0,1) cam_pos = QVector3D(cam_pos[0], cam_pos[1], cam_pos[2]) # calculate self look vector (vector from self.origin to camera) bill_look = cam_pos - self.origin bill_look.normalize() if self.billboard_axis == None: # Fully aligned billboard, rotation not restricted to axes. # Calculate new self right vector based upon self look and camera up bill_right = QVector3D.crossProduct(cam_up, bill_look) # Calculate self up vector based on self look and self right bill_up = QVector3D.crossProduct(bill_look, bill_right) else: axis_words = ["X", "Y", "Z"] axis = axis_words.index(self.billboard_axis) bill_up = [0]*3 for i in range(0,3): bill_up[i] = 1 if i == axis else 0 bill_up = QVector3D(*bill_up) bill_look_zeroed = [0]*3 for i in range(0,3): bill_look_zeroed[i] = 0 if i == axis else bill_look[i] bill_look = QVector3D(*bill_look_zeroed) bill_look.normalize() bill_right = QVector3D.crossProduct(bill_up, bill_look) # View and Model matrices are actually nicely structured! # 1st column: camera right vector # 2nd column: camera up vector # 3rd column: camera look vector # 4th column: camera position # Here we only overwrite right, up and look. # Position is already in the matrix, and we don't have to change it. mat_m[0,0] = bill_right[0] mat_m[1,0] = bill_right[1] mat_m[2,0] = bill_right[2] mat_m[0,1] = bill_up[0] mat_m[1,1] = bill_up[1] mat_m[2,1] = bill_up[2] mat_m[0,2] = bill_look[0] mat_m[1,2] = bill_look[1] mat_m[2,2] = bill_look[2] else: mat_m.rotate(self.rotation_angle, self.rotation_vector) mat_m.scale(self.scale) return mat_m
def setUniformBindings(self, wireframe=False): """Sets up uniform shader bindings""" normalMatrix = self._transform.normalMatrix() self._active_shader.setUniformValue("modelMatrix", self._transform) self._active_shader.setUniformValue("viewMatrix", self._scene.camera.viewMatrix) self._active_shader.setUniformValue( "projectionMatrix", self._scene.camera.projectionMatrix) self._active_shader.setUniformValue("normalMatrix", normalMatrix) ## bind active material if self.isSelectable() and self.isSelected(): self._active_shader.setUniformValue("selected", 1.0) else: self._active_shader.setUniformValue("selected", 0.65) ## set highlight color if self.isHighlighted(): self._active_shader.setUniformValue("material.emission", QVector3D(0.25, 0.25, 0.25)) else: self._active_shader.setUniformValue( "material.emission", self._active_material.emissionColor) self._active_shader.setUniformValue("material.ambient", self._active_material.ambientColor) ## set the enabled color if self.isEnabled(): self._active_shader.setUniformValue("material.emission", QVector3D(0.25, 0.25, 0.25)) self._active_shader.setUniformValue( "material.diffuse", self._active_material.diffuseColor) else: self._active_shader.setUniformValue( "material.diffuse", self._active_material.diffuseColor) self._active_shader.setUniformValue( "material.specular", self._active_material.specularColor) self._active_shader.setUniformValue("material.shininess", self._active_material.shininess) ## set the error and warning colors if self._errorHighlight: self._active_shader.setUniformValue( "material.ambient", self._errorMaterial.ambientColor) self._active_shader.setUniformValue( "material.diffuse", self._errorMaterial.diffuseColor) self._active_shader.setUniformValue( "material.specular", self._errorMaterial.specularColor) self._active_shader.setUniformValue("material.shininess", self._errorMaterial.shininess) if self._warningHighlight: self._active_shader.setUniformValue( "material.ambient", self._warningMaterial.ambientColor) self._active_shader.setUniformValue( "material.diffuse", self._warningMaterial.diffuseColor) self._active_shader.setUniformValue( "material.specular", self._warningMaterial.specularColor) self._active_shader.setUniformValue( "material.shininess", self._warningMaterial.shininess) if self._shader_name == "BRDF": self._active_shader.setUniformValue("material.metallic", self._active_material.metallic) self._active_shader.setUniformValue( "material.roughness", self._active_material.roughness) self._active_shader.setUniformValue("material.cbase", self._active_material.cbase) self._active_shader.setUniformValue("spike", self._active_material._spike) self._active_shader.setUniformValue("h", self._active_material._spike_h) self._active_shader.setUniformValue("w", self._active_material._spike_w) self._active_shader.setUniformValue("portalIteration", self._portalInteration) ## bind lights camera_position = QVector4D(self._scene.camera.position[0], self._scene.camera.position[1], self._scene.camera.position[2], 1.0) lightpos = self._scene.light._position if self._scene.light.headlight: if self._scene.light.directional: self._active_shader.setUniformValue( "lightPosition", QVector4D(lightpos.x(), lightpos.y(), lightpos.z(), 0.0)) elif self._scene.light.hemispheric: self._active_shader.setUniformValue( "lightPosition", QVector4D(lightpos.x(), lightpos.y(), lightpos.z(), 0.2)) else: self._active_shader.setUniformValue( "lightPosition", QVector4D(lightpos.x(), lightpos.y(), lightpos.z(), 1.0)) else: self._active_shader.setUniformValue( "lightPosition", self._scene.camera.viewMatrix * self._scene.light.position) self._active_shader.setUniformValue("light.ambient", self._scene.light.ambientColor) self._active_shader.setUniformValue("light.diffuse", self._scene.light.diffuseColor) self._active_shader.setUniformValue("light.specular", self._scene.light.specularColor) self._active_shader.setUniformValue("lightAttenuation", self._scene.light.attenuation) if self._shader_name == "BRDF": self._active_shader.setUniformValue("light.color", self._scene.light.color) self._active_shader.setUniformValue("light.lradious", self._scene.light.lradious) self._active_shader.setUniformValue("light.aconst", self._scene.light.aconst) self._active_shader.setUniformValue("light.alinear", self._scene.light.alinear) self._active_shader.setUniformValue("light.aquad", self._scene.light.aquad) self._active_shader.setUniformValue("light.csky", self._scene.light.csky) self._active_shader.setUniformValue("light.cground", self._scene.light.cground) if self._isIcosahedron: self._active_shader.setUniformValue("isIcosahedron", 1) else: self._active_shader.setUniformValue("isIcosahedron", 0)
def calc_upper_vertex(upper_vertices, model, head_links, frames, bf): # キー:頂点Y位置小数点第一位まるめ upper_vertex_pos = {} # グローバル行列算出 _, _, matrixs, _ = create_matrix(model, head_links, frames, bf) # 該当ボーンのグローバル行列まで求める upper_matrixes = [QMatrix4x4() for i in range(len(head_links))] for n in range(len(matrixs)): for m in range(n + 1): if n == 0: # 最初は行列そのもの upper_matrixes[n] = copy.deepcopy(matrixs[0]) else: # 2番目以降は行列をかける upper_matrixes[n] *= copy.deepcopy(matrixs[m]) # logger.debug("**u_matrixes[%s]: %s %s -> %s", n, m, matrixs[m], upper_matrixes[n]) # logger.debug("upper_matrixes[%s]: %s", n, upper_matrixes[n]) # 該当リンクボーンのリンクINDEX取得 head_links_indexes = {} for lidx, l in enumerate(reversed(head_links)): head_links_indexes[l.index] = lidx # 上半身の頂点位置 for uv in upper_vertices: # 頂点が乗っているウェイトボーン情報取得 deform_bone = model.bones[model.bone_indexes[uv.deform.index0]] # 頂点初期位置 uv_diff = uv.position - deform_bone.position # 上半身の頂点の位置を算出する upper_pos = upper_matrixes[head_links_indexes[ deform_bone.index]] * QVector4D(uv_diff, 1) # logger.debug("upper_matrixes0 : %s, upper_pos: %s", upper_matrixes[0], upper_pos) # logger.debug("upper_matrixes1 : %s, upper_pos: %s", upper_matrixes[1], upper_pos) # 3Dに変換 uv_pos = upper_pos.toVector3D() uv_round = round(uv_pos.y(), 1) # logger.debug("uv_pos.y: %s -> %s: 0:%s, -1:%s, 1:%s", uv_pos.y(), uv_round, round(uv_pos.y(), 0), round(uv_pos.y(), -1), round(uv_pos.y(), 1)) if uv_round not in upper_vertex_pos.keys(): upper_vertex_pos[uv_round] = {} # 最小値 upper_vertex_pos[uv_round]["min"] = QVector3D(99999, 99999, 99999) # 最大値 upper_vertex_pos[uv_round]["max"] = QVector3D( -99999, -99999, -99999) # 実値 upper_vertex_pos[uv_round]["values"] = [] # if round(uv.position.y(),2) == 8.01: # logger.info("v: %s %s, uv_pos: %s", uv.index, uv.position, uv_pos) if upper_vertex_pos[uv_round]["min"].z() > uv_pos.z(): # 最小値より小さい場合、上書き upper_vertex_pos[uv_round]["min"] = uv_pos if upper_vertex_pos[uv_round]["max"].z() < uv_pos.z(): # 最大値より小さい場合、上書き upper_vertex_pos[uv_round]["max"] = uv_pos # 実値追加 upper_vertex_pos[uv_round]["values"].append(uv_pos) # if bf.frame == 0: # for uvkey in upper_vertex_pos.keys(): # logger.info("upper_vertex_pos key: %s, min: %s, max: %s, len: %s", uvkey, upper_vertex_pos[uv_round]["min"], upper_vertex_pos[uv_round]["max"], len(upper_vertex_pos[uvkey]["values"])) return upper_vertex_pos
def paintGL(self): """ This function is automatially called by the Qt libraries whenever updateGL() has been called. This happens for example when the window is resized or moved or when it is marked as 'dirty' by the window manager. It also fires during mouse interactivity. paintGL() traditionally is structured in the following way, see also OpenGL documentation: 1. Call to glClear() 2. Uploading of per-frame CPU-calculated data if they have changed since the last call. This can include: a. Projection and View matrices b. For each object in the scene: - Model Matrix (translation, scale, rotation of object) 3. For each object in the scene: a. Binding the data buffers of the object b. Drawing of the object """ print("paintGL called") glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # ======= VIEW MATRIX BEGIN ========== # start with an empty matrix self.mat_v = QMatrix4x4() # rotate the world self.mat_v.rotate(self._rotation_quat) # math is done by Qt! # translate the world self.mat_v.translate(self._translation_vec) # math is done by Qt! # calculate inverse view matrix which contains # camera right, up, look directions, and camera position # Items in "billboard" mode will need this to know where the camera is self.mat_v_inverted = self.mat_v.inverted()[0] # the right direction of the camera cam_right = self.mat_v_inverted * QVector4D(1,0,0,0) # extract 1st column self.cam_right = QVector3D(cam_right[0], cam_right[1], cam_right[2]) # the up direction of the camera cam_up = self.mat_v_inverted * QVector4D(0,1,0,0) # extract 2nd column self.cam_up = QVector3D(cam_up[0], cam_up[1], cam_up[2]) # the look direction of the camera cam_look = self.mat_v_inverted * QVector4D(0,0,1,0) # extract 3rd column self.cam_look = QVector3D(cam_look[0], cam_look[1], cam_look[2]) # the postion of the camera cam_pos = self.mat_v_inverted * QVector4D(0,0,0,1) # extract 4th column self.cam_pos = QVector3D(cam_pos[0], cam_pos[1], cam_pos[2]) # upload the View matrix into the GPU, # accessible to the vertex shader under the variable name "mat_v" mat_v_list = PainterWidget.qt_mat_to_list(self.mat_v) # Transform Qt object to Python list # ======= VIEW MATRIX END ========== # ======= PROJECTION MATRIX BEGIN ========== self.mat_p = QMatrix4x4() # start with an empty matrix self.mat_p.perspective(self.fov, self.aspect, 0.1, 100000) # math is done by Qt! mat_p_list = PainterWidget.qt_mat_to_list(self.mat_p) #Transform Qt object to Python list # ======= PROJECTION MATRIX END ========== # loop over all programs/shaders # first switch to that program (expensive operation) # then draw all items belonging to that program for key, prog in self.programs.items(): if len(list(prog.items.keys())) > 0: glUseProgram(prog.id) prog.set_uniform("mat_v", mat_v_list) # set view matrix prog.set_uniform("mat_p", mat_p_list) # set projection matrix prog.items_draw(self.mat_v_inverted)
def create_matrix(model, links, frames, bf): # ローカル位置 trans_vs = [QVector3D() for i in range(len(links))] # 加算用クォータニオン add_qs = [QQuaternion() for i in range(len(links))] for lidx, lbone in enumerate(reversed(links)): # 位置 if lidx == 0: # 一番親は、グローバル座標を考慮 trans_vs[lidx] = lbone.position + calc_bone_by_complement( frames, lbone.name, bf.frame).position else: # 位置:自身から親の位置を引いた値 trans_vs[lidx] = lbone.position + calc_bone_by_complement( frames, lbone.name, bf.frame).position - links[len(links) - lidx].position # 回転 rot = calc_bone_by_complement(frames, lbone.name, bf.frame).rotation if lbone.fixed_axis != QVector3D(): # 軸固定の場合、回転を制限する rot = QQuaternion.fromAxisAndAngle(lbone.fixed_axis, rot.lengthSquared()) add_qs[lidx] = rot # if "ひじ" in lbone.name: # # 右手系→左手系への変換 # # trans_vs[lidx].setX(trans_vs[lidx].x() * -1) # add_qs[lidx].setX(add_qs[lidx].x() * -1) # add_qs[lidx].setY(add_qs[lidx].y() * -1) # # add_qs[lidx].setScalar(add_qs[lidx].scalar() * -1) # # logger.info("%s: fix: %s, vs: %s, qs: %s", lbone.name, lbone.fixed_axis, trans_vs[lidx], add_qs[lidx].toEulerAngles()) # logger.info("trans_vs[%s]: %s", lidx, trans_vs[lidx]) # logger.info("add_qs[%s]: %s", lidx, add_qs[lidx]) # 行列 matrixs = [QMatrix4x4() for i in range(len(links))] for n in range(len(matrixs)): # 行列を生成 matrixs[n] = QMatrix4x4() # 移動 matrixs[n].translate(trans_vs[n]) # 回転 matrixs[n].rotate(add_qs[n]) # logger.info("matrixs n: %s, %s", n, matrixs[n]) # 各関節の位置 global_4ds = [QVector4D() for i in range(len(links))] for n in range(len(global_4ds)): for m in range(n): if m == 0: # 0番目の位置を初期値とする global_4ds[n] = copy.deepcopy(matrixs[0]) else: # 自分より前の行列結果を掛け算する global_4ds[n] *= copy.deepcopy(matrixs[m]) # 自分は、位置だけ掛ける global_4ds[n] *= QVector4D(trans_vs[n], 1) # if bf.frame == 0: # logger.info("global_4ds %s, %s, %s", n, links[len(links) - n - 1].name, global_4ds[n].toVector3D()) return trans_vs, add_qs, matrixs, global_4ds
def calc_boundingbox(model, bone_name, body_links, frames, bf): # グローバル行列算出 _, _, _, matrixs = utils.create_matrix(model, body_links, frames, bf) # 該当ボーンを含む末端までのグローバル行列まで求める upper_matrixes = [QMatrix4x4() for i in range(len(body_links))] target_idx = 0 for i, l in enumerate(reversed(body_links)): if l.name == bone_name: target_idx = i break for n in range(len(matrixs)): for m in range(n + 1): if n == 0: # 最初は行列そのもの upper_matrixes[n] = copy.deepcopy(matrixs[0]) else: # 2番目以降は行列をかける upper_matrixes[n] *= copy.deepcopy(matrixs[m]) # logger.debug("**u_matrixes[%s]: %s %s -> %s", n, m, matrixs[m], upper_matrixes[n]) # logger.debug("upper_matrixes[%s]: %s", n, upper_matrixes[n]) x_min = y_min = z_min = 99999 x_max = y_max = z_max = -99999 # 指定ボーンにウェイトが振ってある頂点リスト for hv in model.vertices[model.bones[bone_name].index]: # 頂点初期位置 hv_diff = hv.position - model.bones[bone_name].position # 指定ボーンまでの行列と、頂点をかけて頂点の現在位置を取得する head_pos = (upper_matrixes[target_idx] * QVector4D(hv_diff, 1)).toVector3D() if head_pos.x() < x_min: # X位置がより前の場合、x_min更新 x_min = head_pos.x() if head_pos.x() > x_max: # X位置がより後の場合、x_max更新 x_max = head_pos.x() if head_pos.y() < y_min: # Y位置がより前の場合、y_min更新 y_min = head_pos.y() if head_pos.y() > y_max: # Y位置がより後の場合、y_max更新 y_max = head_pos.y() if head_pos.z() < z_min: # Z位置がより前の場合、z_min更新 z_min = head_pos.z() if head_pos.z() > z_max: # Z位置がより後の場合、z_max更新 z_max = head_pos.z() return QVector3D(x_min, y_min, z_min), QVector3D(x_max, y_max, z_max)