Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
lookatnode.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5
6#include "lookatnode_p.h"
7
8#include <QtMath>
9
10/*!
11 \qmltype LookAtNode
12 \inqmlmodule QtQuick3D.Helpers
13 \inherits Node
14 \brief A helper node that is automatically kept pointing at another node.
15 \since 6.4
16
17 This helper implements a node that automatically rotates so that it is always
18 pointed towards a specified node. The rotation only happens over X and Y axes.
19
20 For example, the following snippet keeps the cylinder pointed at the cube.
21
22 \badcode
23 View3D {
24 anchors.fill: parent
25 camera: camera
26
27 PerspectiveCamera {
28 id: camera
29 }
30
31 DirectionalLight {}
32
33 LookAtNode {
34 target: cube
35
36 Model {
37 id: cylinder
38 source: "#Cone"
39 eulerRotation.x: -90
40 materials: [
41 PrincipledMaterial {}
42 ]
43 }
44 }
45
46 Model {
47 id: cube
48 position: Qt.vector3d(300, 300, 0);
49 source: "#Cube"
50 materials: [ PrincipledMaterial {} ]
51 }
52 }
53 \endcode
54*/
55
56/*! \qmlproperty Node LookAtNode::target
57 Specifies the target node to look at. The default value is \c{null}.
58*/
59
60LookAtNode::LookAtNode()
61 : QQuick3DNode()
62{
63}
64
65LookAtNode::~LookAtNode()
66{
67}
68
69QQuick3DNode *LookAtNode::target() const
70{
71 return m_target;
72}
73
74void LookAtNode::setTarget(QQuick3DNode *node)
75{
76 if (node == m_target)
77 return;
78
79 if (m_target) {
80 disconnect(m_target, &QQuick3DNode::scenePositionChanged, this, &LookAtNode::updateLookAt);
81 disconnect(this, &QQuick3DNode::scenePositionChanged, this, &LookAtNode::updateLookAt);
82 }
83
84 m_target = node;
85
86 if (m_target) {
87 connect(m_target, &QQuick3DNode::scenePositionChanged, this, &LookAtNode::updateLookAt);
88 connect(this, &QQuick3DNode::scenePositionChanged, this, &LookAtNode::updateLookAt);
89 }
90
91 emit targetChanged();
92 updateLookAt();
93}
94
95void LookAtNode::updateLookAt()
96{
97 if (m_target) {
98 // Note: This code was originally copied from QQuick3DCamera::lookAt method.
99
100 // Assumption: we never want the node to roll.
101 // We use Euler angles here to avoid roll to sneak in through numerical instability.
102
103 const QVector3D targetPosition = m_target->scenePosition();
104 auto sourcePosition = scenePosition();
105
106 QVector3D targetVector = sourcePosition - targetPosition;
107
108 float yaw = qRadiansToDegrees(atan2(targetVector.x(), targetVector.z()));
109
110 QVector2D p(targetVector.x(), targetVector.z()); // yaw vector projected to horizontal plane
111 float pitch = qRadiansToDegrees(atan2(p.length(), targetVector.y())) - 90;
112
113 const float previousRoll = eulerRotation().z();
114 setEulerRotation(QVector3D(pitch, yaw, previousRoll));
115 }
116}