Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qcharactercontroller.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
5
7
121
123{
124 return m_movement;
125}
126
128{
129 if (m_movement == newMovement)
130 return;
131 m_movement = newMovement;
133}
134
136{
137 return m_gravity;
138}
139
141{
142 if (m_gravity == newGravity)
143 return;
144 m_gravity = newGravity;
146}
147
148// Calculate move based on movement/gravity
149
151{
152 // Start with basic movement, assuming no other factors
153 QVector3D displacement = sceneRotation() * m_movement * deltaTime;
154
155 // modified based on gravity
156 const auto g = m_gravity;
157 if (!g.isNull()) {
158
159 // Avoid "spider mode": we are also supposed to be in free fall if gravity
160 // is pointing away from a surface we are touching. I.e. we are NOT in free
161 // fall only if gravity has a component in the direction of one of the collisions.
162 // Also: if we have "upwards" free fall velocity, that motion needs to stop
163 // when we hit the "ceiling"; i.e we are not in free fall at the moment of impact.
164 auto isGrounded = [this](){
165 if (m_collisions == Collision::None)
166 return false;
167
168 // Standard gravity case first
169 if (m_gravity.y() < 0) {
170 if (m_collisions & Collision::Down)
171 return true; // We land on the ground
172 if ((m_collisions & Collision::Up) && m_freeFallVelocity.y() > 0)
173 return true; // We bump our head on the way up
174 }
175
176 // Inverse gravity next: exactly the opposite
177 if (m_gravity.y() > 0) {
178 if (m_collisions & Collision::Up)
179 return true;
180 if ((m_collisions & Collision::Down) && m_freeFallVelocity.y() < 0)
181 return true;
182 }
183
184 // The sideways gravity case can't be perfectly handled since we don't
185 // know the direction of sideway contacts. We could in theory inspect
186 // the mesh, but that is far too complex for an extremely marginal use case.
187
188 if ((m_gravity.x() != 0 || m_gravity.z() != 0) && m_collisions & Collision::Side)
189 return true;
190
191 return false;
192 };
193
194 bool freeFalling = !isGrounded();
195 if (freeFalling) {
196 if (!m_midAirControl)
197 displacement = {}; // Ignore the movement() controls in true free fall
198
199 displacement += m_freeFallVelocity * deltaTime;
200 m_freeFallVelocity += g * deltaTime;
201 } else {
202 m_freeFallVelocity = displacement / deltaTime + g * deltaTime;
203 if (m_midAirControl) // free fall only straight down
204 m_freeFallVelocity =
205 QVector3D::dotProduct(m_freeFallVelocity, g.normalized()) * g.normalized();
206 }
207 const QVector3D gravityAcceleration = 0.5 * deltaTime * deltaTime * g;
208 displacement += gravityAcceleration; // always add gravitational acceleration, in case we start
209 // to fall. If we don't, PhysX will move us back to the ground.
210 }
211
212 return displacement;
213}
214
216{
217 return m_midAirControl;
218}
219
220void QCharacterController::setMidAirControl(bool newMidAirControl)
221{
222 if (m_midAirControl == newMidAirControl)
223 return;
224 m_midAirControl = newMidAirControl;
226}
227
229{
230 m_teleport = true;
231 m_teleportPosition = position;
232 m_freeFallVelocity = {};
233}
234
236{
237 if (m_teleport) {
238 position = m_teleportPosition;
239 m_teleport = false;
240 return true;
241 }
242 return false;
243}
244
245const QCharacterController::Collisions &QCharacterController::collisions() const
246{
247 return m_collisions;
248}
249
250void QCharacterController::setCollisions(const Collisions &newCollisions)
251{
252 if (m_collisions == newCollisions)
253 return;
254 m_collisions = newCollisions;
256}
257
259{
260 return m_enableShapeHitCallback;
261}
262
263void QCharacterController::setEnableShapeHitCallback(bool newEnableShapeHitCallback)
264{
265 if (m_enableShapeHitCallback == newEnableShapeHitCallback)
266 return;
267 m_enableShapeHitCallback = newEnableShapeHitCallback;
269}
270
void setMidAirControl(bool newMidAirControl)
Q_INVOKABLE void teleport(const QVector3D &position)
void setCollisions(const Collisions &newCollisions)
QCharacterController()
\qmltype CharacterController \inqmlmodule QtQuick3D.Physics \inherits PhysicsBody
QVector3D getDisplacement(float deltaTime)
void enableShapeHitCallbackChanged()
void setMovement(const QVector3D &newMovement)
bool getTeleport(QVector3D &position)
void setGravity(const QVector3D &newGravity)
QQuaternion sceneRotation
QVector3D position
The QVector3D class represents a vector or vertex in 3D space.
Definition qvectornd.h:171
QVector3D normalized() const noexcept
Returns the normalized unit vector form of this vector.
Definition qvectornd.h:695
constexpr float y() const noexcept
Returns the y coordinate of this point.
Definition qvectornd.h:671
constexpr float x() const noexcept
Returns the x coordinate of this point.
Definition qvectornd.h:670
static constexpr float dotProduct(QVector3D v1, QVector3D v2) noexcept
Returns the dot product of v1 and v2.
Definition qvectornd.h:770
constexpr float z() const noexcept
Returns the z coordinate of this point.
Definition qvectornd.h:672
Combined button and popup list for selecting options.
GLboolean GLboolean g
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define emit