def __init__(self, models): super(ModelerViewport, self).__init__() self.setLayout(vlayout()) self._updateMinMouseClickDist() self._primitives = Primitives() self._models = models self._currentModel = None self._currentModelNodes = set() self._cameraTransform = cgmath.Mat44.translate(0, 0, -2) self._modelTransform = cgmath.Mat44() self._viewTransform = cgmath.Mat44() self._cameraPivot = cgmath.Vec3(0.0,0.0,0.0) self._adjustingCamera = False self._adjustCameraMode = 0 self._selecting = False self._modifierMode = ModifierMode.SELECT self._modifierAxis = ModifierAxis.NONE self.setFocusPolicy(Qt.StrongFocus) self.installEventFilter(self)
def loadState(self): # save user camera position per scene userFile = currentProjectFilePath().ensureExt('user') if not userFile.exists(): return xUser = parseXMLWithIncludes(userFile) if xUser is None: return xMod = xUser.find('Modeler') if xMod is None: return if 'CurrentModel' in xMod.attrib: currentModelIndex = int(xMod.attrib['CurrentModel']) else: currentModelIndex = -1 if currentModelIndex >= 0 and currentModelIndex < len(self._models.models): self.selectedModelNodesChanged.emit(self._models.models[currentModelIndex], None) else: self.selectedModelNodesChanged.emit(None, None) ct = list(map(float, xMod.attrib['CameraTransform'].split(','))) self._cameraTransform = cgmath.Mat44(ct[0],ct[1],ct[2],ct[3],ct[4],ct[5],ct[6],ct[7],ct[8],ct[9],ct[10],ct[11],ct[12],ct[13],ct[14],ct[15]) ct = list(map(float, xMod.attrib['CameraPivot'].split(','))) self._cameraPivot = cgmath.Vec3(ct[0], ct[1], ct[2]) self.update()
def _getModifierMVP(self): modelTransform = self._getCurrentMainModelNode().getModelTransform() modifierSize = 0.05 if self._modifierMode == ModifierMode.ROTATE else 0.10 if self._modifierMode == ModifierMode.TRANSLATE: # Translation is in world space, simply emit world space axes nonScaledModelTransform = cgmath.Mat44.translate(modelTransform[12], modelTransform[13], modelTransform[14]) else: # Orthonormalize modelTransform (remove scale) modelRight = cgmath.Vec3(modelTransform[0], modelTransform[1], modelTransform[2]) modelUp = cgmath.Vec3(modelTransform[4], modelTransform[5], modelTransform[6]) modelForward = cgmath.Vec3(modelTransform[8], modelTransform[9], modelTransform[10]) modelRight.normalize() modelUp.normalize() modelForward.normalize() nonScaledModelTransform = cgmath.Mat44(modelRight[0], modelRight[1], modelRight[2], 0, modelUp[0], modelUp[1], modelUp[2], 0, modelForward[0], modelForward[1], modelForward[2], 0, modelTransform[12], modelTransform[13], modelTransform[14], 1) mv = nonScaledModelTransform * self._viewTransform mvp = cgmath.Mat44.scale(modifierSize * mv[14], modifierSize * mv[14], modifierSize * mv[14]) * mv * self._projection return mvp
def setModelerCameraTransform(self, cameraTransform): self.__modelerCameraTransform = cameraTransform if self._cameraControlMode == CameraControlMode.MODELER: cameraTransformInv = cgmath.Mat44(cameraTransform) cameraTransformInv.inverse() angles = cameraTransformInv.eulerXYZ() self.__data = CameraTransform(cameraTransform[12], cameraTransform[13], cameraTransform[14], -angles[0], angles[1], -angles[2]) self.cameraChanged.emit()
def paintGL(self): # view = inverse of camera, which is: self._viewTransform = \ cgmath.Mat44.translate(-self._cameraTransform[12], -self._cameraTransform[13], -self._cameraTransform[14]) * \ cgmath.Mat44(self._cameraTransform[0], self._cameraTransform[4], self._cameraTransform[8], 0, self._cameraTransform[1], self._cameraTransform[5], self._cameraTransform[9], 0, self._cameraTransform[2], self._cameraTransform[6], self._cameraTransform[10], 0, 0, 0, 0, 1) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Draw grid mvp = self._viewTransform * self._projection glUniformMatrix4fv(self._uniform_mvp, 1, False, (ctypes.c_float * 16)(*mvp)) glUniform4f(self._uniform_color, 0.5, 0.5, 0.5, 1.0) glLineWidth(1) self._primitives.draw(PrimitiveType.GRID) # Draw nodes if self._currentModel is not None: # glLineWidth(2) # Put current model node at the end of the list nodes = list(self._currentModel.nodes) if len(self._currentModelNodes) > 0: for node in self._currentModelNodes: nodes.remove(node) for node in self._currentModelNodes: nodes.append(node) # Draw all nodes for node in nodes: modelTransform = node.getModelTransform() mvp = (modelTransform * self._viewTransform) * self._projection glUniformMatrix4fv( self._uniform_mvp, 1, False, (ctypes.c_float * 16)(*mvp)) if node in self._currentModelNodes: glUniform4f(self._uniform_color, 1.0, 1.0, 0.0, 1.0) else: glUniform4f(self._uniform_color, 0.0, 0.0, 0.5, 1.0) self._primitives.draw(PrimitiveType.CUBE) # Draw our modifier? if self._modifierMode != ModifierMode.SELECT and len(self._currentModelNodes) > 0: self._drawModifier() # Draw selection rect if self._selecting and (self._selectCurrentMouseScreenPos - self._selectStartMouseScreenPos).lengthSq > 0.0: self._drawSelectionRect()
def axisAngle(self, axis, angle): # https://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/ c = math.cos(angle) s = math.sin(angle) t = 1 - c m00 = c + axis[0] * axis[0] * t m11 = c + axis[1] * axis[1] * t m22 = c + axis[2] * axis[2] * t tmp1 = axis[0] * axis[1] * t tmp2 = axis[2] * s m10 = tmp1 + tmp2 m01 = tmp1 - tmp2 tmp1 = axis[0] * axis[2] * t tmp2 = axis[1] * s m20 = tmp1 - tmp2 m02 = tmp1 + tmp2 tmp1 = axis[1] * axis[2] * t tmp2 = axis[0] * s m21 = tmp1 + tmp2 m12 = tmp1 - tmp2 return cgmath.Mat44(m00, m01, m02, 0, m10, m11, m12, 0, m20, m21, m22, 0, 0, 0, 0, 1)
def __init__(self, animator, animationEditor, timer): super(Camera, self).__init__() self.setLayout(hlayout()) self._freeCameraControlButton = QPushButton( icons.get('icons8-video-camera-50'), '') self._freeCameraControlButton.clicked.connect( self._setFreeCameraControl) self._freeCameraControlButton.setCheckable(True) self._freeCameraControlButton.setIconSize(QSize(24, 24)) self._freeCameraControlButton.setToolTip("Free") self._animationCameraControlButton = QPushButton( icons.get('icons8-line-chart-50'), '') self._animationCameraControlButton.clicked.connect( self._setAnimationCameraControl) self._animationCameraControlButton.setCheckable(True) self._animationCameraControlButton.setIconSize(QSize(24, 24)) self._animationCameraControlButton.setToolTip("Animation curves") self._modelerCameraControlButton = QPushButton( icons.get('icons8-grid-50'), '') self._modelerCameraControlButton.clicked.connect( self._setModelerCameraControl) self._modelerCameraControlButton.setCheckable(True) self._modelerCameraControlButton.setIconSize(QSize(24, 24)) self._modelerCameraControlButton.setToolTip("Modeler viewport") self.layout().addWidget(self._freeCameraControlButton) self.layout().addWidget(self._animationCameraControlButton) self.layout().addWidget(self._modelerCameraControlButton) self.layout().addSpacing(24) self._cameraControlMode = CameraControlMode.FREE self.toggleBetweenFreeAndAnimation() timer.timeChanged.connect(self.__copyAnim) copyAnim = QPushButton(QIcon(icons.get('Film-Refresh-48')), '') copyAnim.setToolTip('Copy anim') copyAnim.setStatusTip('Copy anim') self.__animator = animator self.__animationEditor = animationEditor self._timer = timer copyAnim.clicked.connect(self.copyAnim) self.layout().addWidget(copyAnim) copyAnim.setIconSize(QSize(24, 24)) self.__keyStates = {Qt.Key_Shift: False, Qt.Key_Control: False} for key in Camera.MOVE_LUT: self.__keyStates[key] = False for key in Camera.TURN_LUT: self.__keyStates[key] = False self.__data = CameraTransform() self.__modelerCameraTransform = cgmath.Mat44() self.__inputs = [] for i, value in enumerate(self.__data): s = DoubleSpinBox(value) s.setMinimumWidth(50) self.__inputs.append(s) if i in (3, 4, 5): s.setSingleStep(5) self.layout().addWidget(s) s.valueChanged.connect(functools.partial(self.__setData, i)) self.__prevTime = None self.__appLoop = QTimer() self.__appLoop.timeout.connect(self.flyUpdate) self.__appLoop.start(1.0 / 15.0) self.__drag = None self.__dirty = False
def mouseMoveEvent(self, mouseEvent): super(ModelerViewport, self).mouseMoveEvent(mouseEvent) # Panning/Rotating/Zooming? if self._adjustingCamera: # Panning? if self._adjustCameraMode == 0: panSpeed = 0.025 deltaMouse = mathutil.Vec2(mouseEvent.localPos().x(), mouseEvent.localPos().y()) - self._adjustCameraStartMousePos self._cameraTransform = cgmath.Mat44.translate(deltaMouse[0] * -panSpeed, deltaMouse[1] * panSpeed, 0.0) * self._adjustCameraStartCamera self._cameraPivot = self._adjustCameraPivot + cgmath.Vec3(self._cameraTransform[12] - self._adjustCameraStartCamera[12], self._cameraTransform[13] - self._adjustCameraStartCamera[13], self._cameraTransform[14] - self._adjustCameraStartCamera[14]) # Rotating? elif self._adjustCameraMode == 1: rotateSpeed = 0.010 deltaMouse = mathutil.Vec2(mouseEvent.localPos().x(), mouseEvent.localPos().y()) - self._adjustCameraStartMousePos # Remove pivot self._cameraTransform = cgmath.Mat44(self._adjustCameraStartCamera) * cgmath.Mat44.translate(-self._adjustCameraPivot[0], -self._adjustCameraPivot[1], -self._adjustCameraPivot[2]) # Rotate self._cameraTransform = self._cameraTransform * cgmath.Mat44.rotateY(deltaMouse[0] * rotateSpeed) self._cameraTransform = self._cameraTransform * self.axisAngle(cgmath.Vec3(1.0, 0.0, 0.0) * self._cameraTransform, deltaMouse[1] * -rotateSpeed) # Add pivot back self._cameraTransform = cgmath.Mat44(self._cameraTransform) * cgmath.Mat44.translate(self._adjustCameraPivot[0], self._adjustCameraPivot[1], self._adjustCameraPivot[2]) # Zooming? elif self._adjustCameraMode == 2: zoomSpeed = 0.025 deltaMouse = mathutil.Vec2(mouseEvent.localPos().x(), mouseEvent.localPos().y()) - self._adjustCameraStartMousePos self._cameraTransform = cgmath.Mat44.translate(0.0, 0.0, deltaMouse[1] * zoomSpeed) * self._adjustCameraStartCamera self.cameraChanged.emit(self._cameraTransform) # Dragging a translation modifier axis? elif self._modifierMode == ModifierMode.TRANSLATE and self._modifierAxis != ModifierAxis.NONE: deltaMouse = self._convertMousePosToScreenPos(mouseEvent.localPos().x(), mouseEvent.localPos().y()) - self._modifyStartMouseScreenPos if self._modifierAxis == ModifierAxis.X: axisDir = cgmath.Vec3(1.0,0.0,0.0) elif self._modifierAxis == ModifierAxis.Y: axisDir = cgmath.Vec3(0.0,1.0,0.0) else: axisDir = cgmath.Vec3(0.0,0.0,1.0) screenDir = self._getModifierAxisScreenDir(axisDir) delta = screenDir[0]*deltaMouse[0] + screenDir[1]*deltaMouse[1] for node in self._currentModelNodes: node.translation = axisDir * delta + self._modifyStartModelTranslation[node] # Dragging a rotation modifier axis? elif self._modifierMode == ModifierMode.ROTATE and self._modifierAxis != ModifierAxis.NONE: deltaMouse = self._convertMousePosToScreenPos(mouseEvent.localPos().x(), mouseEvent.localPos().y()) - self._modifyStartMouseScreenPos amount = deltaMouse[0] if self._modifierAxis == ModifierAxis.X: rot = cgmath.Mat44.rotateX(amount) elif self._modifierAxis == ModifierAxis.Y: rot = cgmath.Mat44.rotateY(amount) else: rot = cgmath.Mat44.rotateZ(amount) for node in self._currentModelNodes: node.rotation = (rot * self._modifyStartModelRotationMatrix[node]).eulerXYZ() # Dragging a scale modifier axis? elif self._modifierMode == ModifierMode.SCALE_NONUNIFORM and self._modifierAxis != ModifierAxis.NONE: deltaMouse = self._convertMousePosToScreenPos(mouseEvent.localPos().x(), mouseEvent.localPos().y()) - self._modifyStartMouseScreenPos if self._modifierAxis == ModifierAxis.X: axisDir = cgmath.Vec3(1.0,0.0,0.0) elif self._modifierAxis == ModifierAxis.Y: axisDir = cgmath.Vec3(0.0,1.0,0.0) else: axisDir = cgmath.Vec3(0.0,0.0,1.0) screenDir = self._getModifierAxisScreenDir(axisDir) delta = screenDir[0]*deltaMouse[0] + screenDir[1]*deltaMouse[1] for node in self._currentModelNodes: node.size = axisDir * delta * 0.5 + self._modifyStartModelSize[node] # Selecting nodes? elif self._selecting: self._selectCurrentMouseScreenPos = self._convertMousePosToScreenPos(mouseEvent.localPos().x(), mouseEvent.localPos().y()) self.update()