C

Qt Quick Ultralite perspective_transforms Example

// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial

import QtQuick 2.12

Item {
    id: root
    property CoverFlowState currentState
    property matrix4x4 globalPreMatrix: calcPreMatrix(currentState.coverSize)
    property matrix4x4 globalPostMatrix: calcPostMatrix(currentState.coverFlowX,
                                                        currentState.coverFlowY,
                                                        currentState.coverFlowW,
                                                        currentState.coverFlowH,
                                                        currentState.fov,
                                                        currentState.viewDistance)

    property matrix4x4 reflectionTransform: Qt.matrix4x4(1, 0, 0, 0,
                                                         0, -1, 0, currentState.reflectionDistance,
                                                         0, 0, 1, 0,
                                                         0, 0, 0, 1)

    // Calc camera transform matrix
    function 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)
        return t1.times(s2.times(t3.times(p4.times(t5))))
    }

    function calcPreMatrix(coverSize : real) : matrix4x4 {
        var t1 = mtxTranslate(-1, -1, 0)
        var s2 = mtxScale(2 / coverSize, 2 / coverSize, 1)
        return t1.times(s2)
    }

    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 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)

        return Qt.matrix4x4(fovCotan / aspectRatio, 0, 0, 0,
                            0, fovCotan, 0, 0,
                            0, 0, (near + far) * s, (2 * near * far) * s,
                            0, 0, -1, 1)
    }

    Repeater {
        model: root.currentState.numberOfCovers
        delegate: Cover {
            required property int index

            texture: "cover" + index + ".jpg"
            coverIndex: index
            state: root.currentState
            postMatrix: root.globalPostMatrix
            preMatrix: root.globalPreMatrix
            reflectionTransform: root.reflectionTransform
        }
    }
}