C

Qt Quick Ultralite perspective_transforms Example

/****************************************************************************** ** ** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Quick Ultralite module. ** ** $QT_BEGIN_LICENSE:COMM$ ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** $QT_END_LICENSE$ ** ******************************************************************************/
import QtQuick 2.12 import Constants 1.0 Rectangle { id: cover property string texture property int coverIndex property CoverFlowState state property matrix4x4 coverTransform: calcCoverTransform() property matrix4x4 postMatrix property matrix4x4 preMatrix property matrix4x4 reflectionTransform z: calcFinalZ() Image { id: coverImageBase source: cover.texture transform: Matrix4x4 { matrix: coverTransform } opacity: 1.0 } Image { id: mirrorImageBase visible: cover.state.showReflection source: cover.texture transform: [ Matrix4x4 { matrix: reflectionTransform }, Matrix4x4 { matrix: coverTransform } ] opacity: 0.1 } function mtxTranslate(x : real, y : real, z : real) : matrix4x4 { return Qt.matrix4x4(1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1) } function mtxScale(x : real, y : real, z : real) : matrix4x4 { return Qt.matrix4x4(x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1) } function mtxRotX(angle : real) : matrix4x4 { var radians = angle * (Math.PI / 180) var sinAngle = Math.sin(radians) var cosAngle = Math.cos(radians) return Qt.matrix4x4(1, 0, 0, 0, 0, cosAngle, -sinAngle, 0, 0, sinAngle, cosAngle, 0, 0, 0, 0, 1) } function mtxRotY(angle : real) : matrix4x4 { var radians = angle * (Math.PI / 180) var sinAngle = Math.sin(radians) var cosAngle = Math.cos(radians) return Qt.matrix4x4( cosAngle, 0, sinAngle, 0, 0, 1, 0, 0, -sinAngle, 0, cosAngle, 0, 0, 0, 0, 1) } property matrix4x4 carouselMatrixPost: { var r1 = mtxRotX(state.viewAngle) var t2 = mtxTranslate(0, state.cameraHeight, 0) return postMatrix.times(r1.times(t2)) } property matrix4x4 carouselMatrixPre: { var t4 = mtxTranslate(0, 0, state.carouselZ) var r5 = mtxRotX(-state.viewAngle/4) var s6 = mtxScale(state.coverScaling, state.coverScaling, 1) return t4.times(r5.times(s6)).times(preMatrix) } // Calculate transforms for individual transform types function calcPosMatrixCarousel() : matrix4x4 { var angle = (coverIndex - state.selectedCover) / state.numberOfCovers * 360; var r3 = mtxRotY(angle) return carouselMatrixPost.times(r3).times(carouselMatrixPre) } property matrix4x4 circlePost: { var r1 = mtxRotX(state.viewAngle) var t2 = mtxTranslate(0, state.cameraHeight, 0) return postMatrix.times(r1.times(t2)) } function calcPosMatrixCircle() : matrix4x4 { var angle = (coverIndex - state.selectedCover) / state.numberOfCovers * 360; var radians = angle * (Math.PI / 180) var sinAngle = Math.sin(radians) var cosAngle = Math.cos(radians) // var t3 = mtxTranslate(state.circleRadius * sinAngle, 0, state.circleRadius * cosAngle) // var s4 = mtxScale(state.coverScaling, state.coverScaling, 1) // the below is equivalent to t3.times(s4) var cs = state.coverScaling var dx = state.circleRadius * sinAngle var dz = state.circleRadius * cosAngle var m3 = Qt.matrix4x4(cs, 0, 0, dx, 0, cs, 0, 0, 0, 0, 1, dz, 0, 0, 0, 1) return circlePost.times(m3).times(preMatrix) } property matrix4x4 circle2DPost: { var r1 = mtxRotX(state.viewAngle) var t2 = mtxTranslate(0, state.cameraHeight, 0) return postMatrix.times(r1.times(t2)) } property matrix4x4 circle2DPre: { var r4 = mtxRotX(-state.viewAngle) var s5 = mtxScale(state.coverScaling, state.coverScaling, 1) return r4.times(s5).times(preMatrix) } function calcPosMatrixCircle2D() : matrix4x4 { var angle = (coverIndex - state.selectedCover) / state.numberOfCovers * 360; var radians = angle * (Math.PI / 180) var sinAngle = Math.sin(radians) var cosAngle = Math.cos(radians) var t3 = mtxTranslate(state.circleRadius * sinAngle, 0, state.circleRadius * cosAngle) return circle2DPost.times(t3.times(circle2DPre)) } function calcPosMatrixPerspective() : matrix4x4 { var fract = Math.min(Math.abs(coverIndex - state.selectedCover), 1) var dir = coverIndex <= state.selectedCover ? 1 : -1 var ta1 = mtxTranslate(0, 0, (1 - fract) * state.perspectiveViewCenterZ) var ta2 = mtxTranslate(fract * ((coverIndex - state.selectedCover) * state.perspectiveViewCoverDist - dir * state.perspectiveViewCenterDist), 0, 0) var ra3 = mtxRotY(dir * fract * state.perspectiveViewMaxRot) return postMatrix.times(ta1.times(ta2.times(ra3))).times(preMatrix) } // Calculates transform matrix for a given cover flow type function calcMatrixForType(type : int) : matrix4x4 { switch (type) { case CoverFlowType.Carousel: return calcPosMatrixCarousel() case CoverFlowType.Circle: return calcPosMatrixCircle() case CoverFlowType.Circle2D: return calcPosMatrixCircle2D() case CoverFlowType.Perspective: default: return calcPosMatrixPerspective() } } // Calculate final cover transformation considering morphRatio function calcCoverTransform() : matrix4x4 { var previousViewType = state.previousViewType var currentViewType = state.currentViewType if (state.morphRatio == 0) { currentViewType = previousViewType } else if (state.morphRatio == 1) { previousViewType = currentViewType } if (currentViewType == previousViewType) { return calcMatrixForType(currentViewType) } else { var currentShape = calcMatrixForType(currentViewType) var oldShape = calcMatrixForType(previousViewType) return currentShape.times(state.morphRatio).plus(oldShape.times(1 - state.morphRatio)) } } // Calculate cover depth along z-axis function calcFinalZ() : real { var coverTransform = cover.coverTransform var x = state.coverSize/2 var y = state.coverSize/2 var inv_d = 1.0 / (coverTransform.m41 * x + coverTransform.m42 * y + coverTransform.m44) var fX = (coverTransform.m11 * x + coverTransform.m12 * y + coverTransform.m14) * inv_d var fZ = (coverTransform.m31 * x + coverTransform.m32 * y + coverTransform.m34) * inv_d var littleX = Math.abs(fX - state.coverFlowX - state.coverFlowW * 0.5) return -fZ * 100000 - littleX } }