Qt Quick 3D - Principled Material Example | Qt Quick 3D 6.3.0

- Qt 6.3
- Qt Quick 3D
- Qt Quick 3D Examples and Tutorials
- Qt Quick 3D - Principled Material Example
- Qt Quick 3D | Commercial or GPLv3

# Qt Quick 3D - Principled Material Example

     /****************************************************************************
     **
     ** Copyright (C) 2022 The Qt Company Ltd.
     ** Contact: https://www.qt.io/licensing/
     **
     ** This file is part of the examples of the Qt Toolkit.
     **
     ** $QT_BEGIN_LICENSE:BSD$
     ** 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 https://www.qt.io/terms-conditions. For further
     ** information use the contact form at https://www.qt.io/contact-us.
     **
     ** BSD License Usage
     ** Alternatively, you may use this file under the terms of the BSD license
     ** as follows:
     **
     ** "Redistribution and use in source and binary forms, with or without
     ** modification, are permitted provided that the following conditions are
     ** met:
     **   * Redistributions of source code must retain the above copyright
     **     notice, this list of conditions and the following disclaimer.
     **   * Redistributions in binary form must reproduce the above copyright
     **     notice, this list of conditions and the following disclaimer in
     **     the documentation and/or other materials provided with the
     **     distribution.
     **   * Neither the name of The Qt Company Ltd nor the names of its
     **     contributors may be used to endorse or promote products derived
     **     from this software without specific prior written permission.
     **
     **
     ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
     **
     ** $QT_END_LICENSE$
     **
     ****************************************************************************/

     import QtQuick
     import QtQuick3D

     Item {
         id: root
         required property Node origin
         required property Camera camera

         property real speed: 1
         property real xSpeed: 0.1
         property real ySpeed: 0.1

         property bool xInvert: false
         property bool yInvert: true

         property bool mouseEnabled: true

         readonly property bool inputsNeedProcessing: status.useMouse || status.isPanning

         implicitWidth: parent.width
         implicitHeight: parent.height

         Connections {
             target: camera
             function onZChanged() {
                 // Adjust near/far values based on distance
                 let distance = camera.z
                 if (distance < 1) {
                     camera.clipNear = 0.01
                     camera.clipFar = 100
                 } else if (distance < 100) {
                     camera.clipNear = 0.1
                     camera.clipFar = 1000
                 } else {
                     camera.clipNear = 1
                     camera.clipFar = 10000
                 }
             }
         }

         DragHandler {
             id: dragHandler
             target: null
             enabled: mouseEnabled
             acceptedModifiers: Qt.NoModifier
             onCentroidChanged: {
                 mouseMoved(Qt.vector2d(centroid.position.x, centroid.position.y), false);
             }

             onActiveChanged: {
                 if (active)
                     mousePressed(Qt.vector2d(centroid.position.x, centroid.position.y));
                 else
                     mouseReleased(Qt.vector2d(centroid.position.x, centroid.position.y));
             }
         }

         DragHandler {
             id: ctrlDragHandler
             target: null
             enabled: mouseEnabled
             acceptedModifiers: Qt.ControlModifier
             onCentroidChanged: {
                 panEvent(Qt.vector2d(centroid.position.x, centroid.position.y));
             }

             onActiveChanged: {
                 if (active)
                     startPan(Qt.vector2d(centroid.position.x, centroid.position.y));
                 else
                     endPan();
             }
         }

         PinchHandler {
             id: pinchHandler
             target: null
             enabled: mouseEnabled

             property real distance: 0.0
             onCentroidChanged: {
                 panEvent(Qt.vector2d(centroid.position.x, centroid.position.y))
             }

             onActiveChanged: {
                 if (active) {
                     startPan(Qt.vector2d(centroid.position.x, centroid.position.y))
                     distance = root.camera.z
                 } else {
                     endPan()
                     distance = 0.0
                 }
             }
             onScaleChanged: {
                 camera.z = distance * (1 / scale)
             }
         }

         TapHandler {
             onTapped: root.forceActiveFocus()
         }

         WheelHandler {
             id: wheelHandler
             orientation: Qt.Vertical
             target: null
             enabled: mouseEnabled
             onWheel: event => {
                 let delta = -event.angleDelta.y * 0.01;
                 camera.z += camera.z * 0.1 * delta
             }
         }

         function mousePressed(newPos) {
             root.forceActiveFocus()
             status.currentPos = newPos
             status.lastPos = newPos
             status.useMouse = true;
         }

         function mouseReleased(newPos) {
             status.useMouse = false;
         }

         function mouseMoved(newPos: vector2d) {
             status.currentPos = newPos;
         }

         function startPan(pos: vector2d) {
             status.isPanning = true;
             status.currentPanPos = pos;
             status.lastPanPos = pos;
         }

         function endPan() {
             status.isPanning = false;
         }

         function panEvent(newPos: vector2d) {
             status.currentPanPos = newPos;
         }

         function processInputs()
         {
             if (root.inputsNeedProcessing)
                 status.processInput();
         }

         Timer {
             id: updateTimer
             interval: 16
             repeat: true
             running: root.inputsNeedProcessing
             onTriggered: {
                 processInputs();
             }
         }

         QtObject {
             id: status

             property bool useMouse: false
             property bool isPanning: false

             property vector2d lastPos: Qt.vector2d(0, 0)
             property vector2d lastPanPos: Qt.vector2d(0, 0)
             property vector2d currentPos: Qt.vector2d(0, 0)
             property vector2d currentPanPos: Qt.vector2d(0, 0)

             function negate(vector) {
                 return Qt.vector3d(-vector.x, -vector.y, -vector.z)
             }

             function processInput() {
                 if (useMouse) {
                     // Get the delta
                     var rotationVector = origin.eulerRotation;
                     var delta = Qt.vector2d(lastPos.x - currentPos.x,
                                             lastPos.y - currentPos.y);
                     // rotate x
                     var rotateX = delta.x * xSpeed
                     if (xInvert)
                         rotateX = -rotateX;
                     rotationVector.y += rotateX;

                     // rotate y
                     var rotateY = delta.y * -ySpeed
                     if (yInvert)
                         rotateY = -rotateY;
                     rotationVector.x += rotateY;
                     origin.setEulerRotation(rotationVector);
                     lastPos = currentPos;
                 }
                 if (isPanning) {
                     let delta = currentPanPos.minus(lastPanPos);
                     delta.x = -delta.x

                     delta.x = (delta.x / root.width) * camera.z
                     delta.y = (delta.y / root.height) * camera.z

                     let velocity = Qt.vector3d(0, 0, 0)
                     // X Movement
                     let xDirection = origin.right
                     velocity = velocity.plus(Qt.vector3d(xDirection.x * delta.x,
                                                          xDirection.y * delta.x,
                                                          xDirection.z * delta.x));
                     // Y Movement
                     let yDirection = origin.up
                     velocity = velocity.plus(Qt.vector3d(yDirection.x * delta.y,
                                                          yDirection.y * delta.y,
                                                          yDirection.z * delta.y));

                     origin.position = origin.position.plus(velocity)

                     lastPanPos = currentPanPos
                 }
             }
         }

     }