Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
9
126
128{
129 return m_movement;
130}
131
133{
134 if (m_movement == newMovement)
135 return;
136 m_movement = newMovement;
138}
139
141{
142 return m_gravity;
143}
144
146{
147 if (m_gravity == newGravity)
148 return;
149 m_gravity = newGravity;
151}
152
153// Calculate move based on movement/gravity
154
156{
157 // Start with basic movement, assuming no other factors
158 QVector3D displacement = sceneRotation() * m_movement * deltaTime;
159
160 // modified based on gravity
161 const auto g = m_gravity;
162 if (!g.isNull()) {
163
164 // Avoid "spider mode": we are also supposed to be in free fall if gravity
165 // is pointing away from a surface we are touching. I.e. we are NOT in free
166 // fall only if gravity has a component in the direction of one of the collisions.
167 // Also: if we have "upwards" free fall velocity, that motion needs to stop
168 // when we hit the "ceiling"; i.e we are not in free fall at the moment of impact.
169 auto isGrounded = [this](){
170 if (m_collisions == Collision::None)
171 return false;
172
173 // Standard gravity case first
174 if (m_gravity.y() < 0) {
175 if (m_collisions & Collision::Down)
176 return true; // We land on the ground
177 if ((m_collisions & Collision::Up) && m_freeFallVelocity.y() > 0)
178 return true; // We bump our head on the way up
179 }
180
181 // Inverse gravity next: exactly the opposite
182 if (m_gravity.y() > 0) {
183 if (m_collisions & Collision::Up)
184 return true;
185 if ((m_collisions & Collision::Down) && m_freeFallVelocity.y() < 0)
186 return true;
187 }
188
189 // The sideways gravity case can't be perfectly handled since we don't
190 // know the direction of sideway contacts. We could in theory inspect
191 // the mesh, but that is far too complex for an extremely marginal use case.
192
193 if ((m_gravity.x() != 0 || m_gravity.z() != 0) && m_collisions & Collision::Side)
194 return true;
195
196 return false;
197 };
198
199 bool freeFalling = !isGrounded();
200 if (freeFalling) {
201 if (!m_midAirControl)
202 displacement = {}; // Ignore the movement() controls in true free fall
203
204 displacement += m_freeFallVelocity * deltaTime;
205 m_freeFallVelocity += g * deltaTime;
206 } else {
207 m_freeFallVelocity = displacement / deltaTime + g * deltaTime;
208 if (m_midAirControl) // free fall only straight down
209 m_freeFallVelocity =
210 QVector3D::dotProduct(m_freeFallVelocity, g.normalized()) * g.normalized();
211 }
212 const QVector3D gravityAcceleration = 0.5 * deltaTime * deltaTime * g;
213 displacement += gravityAcceleration; // always add gravitational acceleration, in case we start
214 // to fall. If we don't, PhysX will move us back to the ground.
215 }
216
217 return displacement;
218}
219
221{
222 return m_midAirControl;
223}
224
225void QCharacterController::setMidAirControl(bool newMidAirControl)
226{
227 if (m_midAirControl == newMidAirControl)
228 return;
229 m_midAirControl = newMidAirControl;
231}
232
234{
235 m_teleport = true;
236 m_teleportPosition = position;
237 m_freeFallVelocity = {};
238}
239
241{
242 if (m_teleport) {
243 position = m_teleportPosition;
244 m_teleport = false;
245 return true;
246 }
247 return false;
248}
249
250const QCharacterController::Collisions &QCharacterController::collisions() const
251{
252 return m_collisions;
253}
254
255void QCharacterController::setCollisions(const Collisions &newCollisions)
256{
257 if (m_collisions == newCollisions)
258 return;
259 m_collisions = newCollisions;
261}
262
264{
265 return m_enableShapeHitCallback;
266}
267
272
273void QCharacterController::setEnableShapeHitCallback(bool newEnableShapeHitCallback)
274{
275 if (m_enableShapeHitCallback == newEnableShapeHitCallback)
276 return;
277 m_enableShapeHitCallback = newEnableShapeHitCallback;
279}
280
void setMidAirControl(bool newMidAirControl)
Q_INVOKABLE void teleport(const QVector3D &position)
QAbstractPhysXNode * createPhysXBackend() final
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