68 Q_ASSERT(!controller);
70 auto *characterController =
static_cast<QCharacterController *>(frontendNode);
72 auto shapes = characterController->getCollisionShapesList();
73 if (shapes.length() != 1) {
74 qWarning() <<
"CharacterController: invalid collision shapes list.";
77 auto *capsule = qobject_cast<QCapsuleShape *>(shapes.first());
79 qWarning() <<
"CharacterController: collision shape is not a capsule.";
82 auto *mgr = world->controllerManager();
84 qWarning() <<
"QtQuick3DPhysics internal error: missing controller manager.";
90 const QVector3D scale = characterController->sceneScale();
91 const qreal heightScale = scale.y();
92 const qreal radiusScale = scale.x();
93 physx::PxCapsuleControllerDesc desc;
94 reportCallback =
new ControllerCallback(world);
95 desc.reportCallback = reportCallback;
96 desc.radius = 0.5f * radiusScale * capsule->diameter();
97 desc.height = heightScale * capsule->height();
98 desc.stepOffset = 0.25f * desc.height;
101 const QVector3D pos = characterController->scenePosition();
102 desc.position = { pos.x(), pos.y(), pos.z() };
105 controller =
static_cast<
physx::PxCapsuleController *>(mgr->createController(desc));
108 qWarning() <<
"QtQuick3DPhysics internal error: could not create controller.";
112 controller->setUserData(
static_cast<
void *>(
frontendNode));
114 auto *actor = controller->getActor();
116 actor->userData = characterController;
118 qWarning() <<
"QtQuick3DPhysics internal error: CharacterController created without actor.";
122 QHash<QQuick3DNode *, QMatrix4x4> & )
124 if (controller ==
nullptr)
127 auto *characterController =
static_cast<QCharacterController *>(frontendNode);
130 const auto &shapes = characterController->getCollisionShapesList();
131 auto capsule = shapes.length() == 1 ? qobject_cast<QCapsuleShape *>(shapes.front()) :
nullptr;
133 if (shapes.length() != 1) {
134 qWarning() <<
"CharacterController: invalid collision shapes list.";
135 }
else if (!capsule) {
136 qWarning() <<
"CharacterController: collision shape is not a capsule.";
138 const QVector3D sceneScale = characterController->sceneScale();
139 const qreal heightScale = sceneScale.y();
140 const qreal radiusScale = sceneScale.x();
143 const float heightNew = heightScale * capsule->height();
144 if (!qFuzzyCompare(controller->getHeight(), heightNew))
145 controller->resize(heightNew);
147 const float radiusNew = 0.5f * radiusScale * capsule->diameter();
148 if (!qFuzzyCompare(controller->getRadius(), radiusNew))
149 controller->setRadius(radiusNew);
151 const float stepOffsetNew = 0.25f * heightNew;
152 if (!qFuzzyCompare(controller->getStepOffset(), stepOffsetNew))
153 controller->setStepOffset(stepOffsetNew);
157 QVector3D position = QPhysicsUtils::toQtType(physx::toVec3(controller->getPosition()));
158 const QQuick3DNode *parentNode =
static_cast<QQuick3DNode *>(characterController->parentItem());
161 characterController->setPosition(position);
163 characterController->setPosition(parentNode->mapPositionFromScene(position));
166 QVector3D teleportPos;
167 bool teleport = characterController->getTeleport(teleportPos);
169 controller->setPosition({ teleportPos.x(), teleportPos.y(), teleportPos.z() });
170 }
else if (deltaTime > 0) {
171 const auto displacement =
172 QPhysicsUtils::toPhysXType(characterController->getDisplacement(deltaTime));
174 controller->move(displacement, displacement.magnitude() / 100, deltaTime, {});
175 characterController->setCollisions(QCharacterController::Collisions(uint(collisions)));