/******************************************************************************
**
** 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 stringtexture
property intcoverIndex
property CoverFlowStatestate
property matrix4x4coverTransform: calcCoverTransform()
z: calcFinalZ()
Image {
id: coverImageBasesource: cover.texturetransform: Matrix4x4 { matrix: coverTransform }
opacity: 1.0
}
Image {
id: mirrorImageBasevisible: cover.state.showReflectionsource: cover.texturetransform: Matrix4x4 { matrix: calcReflectionTransform() }
opacity: 0.1
}
// Elementary matrix generations functionsfunction mtxIdentity() : matrix4x4 {
returnQt.matrix4x4(1, 0, 0, 0,
0, 1 ,0, 0,
0, 0 ,1, 0,
0, 0, 0, 1)
}
function mtxTranslate(x : real, y : real, z : real) : matrix4x4 {
returnQt.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 {
returnQt.matrix4x4(x, 0, 0, 0,
0, y ,0, 0,
0, 0 ,z, 0,
0, 0, 0, 1)
}
function mtxRotX(angle : real) : matrix4x4 {
var radians = Math.PI*angle/180
var sinAngle = Math.sin(radians)
var cosAngle = Math.cos(radians)
returnQt.matrix4x4(1, 0, 0, 0,
0, cosAngle, -sinAngle, 0,
0, sinAngle, cosAngle, 0,
0, 0, 0, 1)
}
function mtxRotY(angle : real) : matrix4x4 {
var radians = Math.PI*angle/180
var sinAngle = Math.sin(radians)
var cosAngle = Math.cos(radians)
returnQt.matrix4x4( cosAngle, 0, sinAngle, 0,
0, 1, 0, 0,
-sinAngle, 0, cosAngle, 0,
0, 0, 0, 1)
}
function mtxPerspective(fov : real, aspectRatio : real, near : real, far : real) : matrix4x4 {
var fovRadians = (fov*Math.PI/180) /2
var fovCotan = Math.cos(fovRadians) /Math.sin(fovRadians)
var s = 1.0/ (near-far)
returnQt.matrix4x4(fovCotan/aspectRatio, 0, 0, 0,
0, fovCotan, 0, 0,
0, 0, (near+far) *s, (2*near*far) *s,
0, 0, -1, 1)
}
// Calc camera transform matrixfunction calcPostMatrix(x : real, y : real, w : real, h : real, fov : real, viewDist : real) : matrix4x4 {
var t1 = mtxTranslate(x, y, 0)
var s2 = mtxScale(w/2, h/2, 1)
var t3 = mtxTranslate(1, 1, 0)
var p4 = mtxPerspective(fov, w/h, 0.1, 100)
var t5 = mtxTranslate(0, 0, -viewDist)
returnt1.times(s2.times(t3.times(p4.times(t5))))
}
// Calc initial cover transformfunction calcPreMatrix(coverSize : real) : matrix4x4 {
var t1 = mtxTranslate(-1, -1, 0)
var s2 = mtxScale(2/coverSize, 2/coverSize, 1)
returnt1.times(s2)
}
// Calculate transforms for individual transform typesfunction calcPosMatrixCarousel() : matrix4x4 {
var angle = (coverIndex-state.selectedCover) /state.numberOfCovers*360;
var r1 = mtxRotX(state.viewAngle)
var t2 = mtxTranslate(0, state.cameraHeight, 0)
var r3 = mtxRotY(angle)
var t4 = mtxTranslate(0, 0, state.carouselZ)
var r5 = mtxRotX(-state.viewAngle/4)
var s6 = mtxScale(state.coverScaling, state.coverScaling, 1)
returnr1.times(t2.times(r3.times(t4.times(r5.times(s6)))))
}
function calcPosMatrixCircle() : matrix4x4 {
var angle = (coverIndex-state.selectedCover) /state.numberOfCovers*360;
var radians = Math.PI*angle/180
var sinAngle = Math.sin(radians)
var cosAngle = Math.cos(radians)
var r1 = mtxRotX(state.viewAngle)
var t2 = mtxTranslate(0, state.cameraHeight, 0)
var t3 = mtxTranslate(state.circleRadius*sinAngle, 0, state.circleRadius*cosAngle)
var s4 = mtxScale(state.coverScaling, state.coverScaling, 1)
returnr1.times(t2.times(t3.times(s4)))
}
function calcPosMatrixCircle2D() : matrix4x4 {
var angle = (coverIndex-state.selectedCover) /state.numberOfCovers*360;
var radians = Math.PI*angle/180
var sinAngle = Math.sin(radians)
var cosAngle = Math.cos(radians)
var r1 = mtxRotX(state.viewAngle)
var t2 = mtxTranslate(0, state.cameraHeight, 0)
var t3 = mtxTranslate(state.circleRadius*sinAngle, 0, state.circleRadius*cosAngle)
var r4 = mtxRotX(-state.viewAngle)
var s5 = mtxScale(state.coverScaling, state.coverScaling, 1)
returnr1.times(t2.times(t3.times(r4.times(s5))))
}
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)
returnta1.times(ta2.times(ra3))
}
// Calculates transform matrix for a given cover flow typefunction calcMatrixForType(type : int) : matrix4x4 {
switch (type)
{
caseCoverFlowType.Carousel:
returncalcPosMatrixCarousel()
caseCoverFlowType.Circle:
returncalcPosMatrixCircle()
caseCoverFlowType.Circle2D:
returncalcPosMatrixCircle2D()
caseCoverFlowType.Perspective:
returncalcPosMatrixPerspective()
}
returnmtxIdentity()
}
// Calculate final cover transformation considering morphRatiofunction calcCoverTransform() : matrix4x4 {
var postMatrix = calcPostMatrix(state.coverFlowX, state.coverFlowY, state.coverFlowW, state.coverFlowH, state.fov, state.viewDistance)
var preMatrix = calcPreMatrix(state.coverSize)
var currentShape = postMatrix.times(calcMatrixForType(state.currentViewType).times(preMatrix))
var oldShape = postMatrix.times(calcMatrixForType(state.previousViewType).times(preMatrix))
returncurrentShape.times(state.morphRatio).plus(oldShape.times(1-state.morphRatio))
}
// Calculate reflection transform, using cover transform as a basefunction calcReflectionTransform() : matrix4x4 {
var scaleMirror = Qt.matrix4x4(1, 0, 0, 0,
0, -1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1)
var translateMirror = Qt.matrix4x4(1, 0, 0, 0,
0, 1, 0, state.reflectionDistance,
0, 0, 1, 0,
0, 0, 0, 1)
returncover.coverTransform.times(translateMirror.times(scaleMirror))
}
// Calculate cover depth along z-axisfunction calcFinalZ() : real {
var coverTransform = cover.coverTransform
var x = state.coverSize/2
var y = state.coverSize/2
var d = coverTransform.m41*x+coverTransform.m42*y+coverTransform.m44
var fX = (coverTransform.m11*x+coverTransform.m12*y+coverTransform.m14) /d
var fZ = (coverTransform.m31*x+coverTransform.m32*y+coverTransform.m34) /d
var littleX = Math.abs(fX-state.coverFlowX-state.coverFlowW/2)
return -fZ*100000-littleX
}
}