72 Q_ASSERT(!controller);
74 auto *characterController =
static_cast<QCharacterController *>(frontendNode);
76 auto shapes = characterController->getCollisionShapesList();
77 if (shapes.length() != 1) {
78 qWarning() <<
"CharacterController: invalid collision shapes list.";
81 auto *capsule = qobject_cast<QCapsuleShape *>(shapes.first());
83 qWarning() <<
"CharacterController: collision shape is not a capsule.";
86 auto *mgr = world->controllerManager();
88 qWarning() <<
"QtQuick3DPhysics internal error: missing controller manager.";
94 const QVector3D scale = characterController->sceneScale();
95 const qreal heightScale = scale.y();
96 const qreal radiusScale = scale.x();
97 physx::PxCapsuleControllerDesc desc;
98 reportCallback =
new ControllerCallback(world);
99 desc.reportCallback = reportCallback;
100 desc.radius = 0.5f * radiusScale * capsule->diameter();
101 desc.height = heightScale * capsule->height();
102 desc.stepOffset = 0.25f * desc.height;
104 desc.material = material;
105 const QVector3D pos = characterController->scenePosition();
106 desc.position = { pos.x(), pos.y(), pos.z() };
109 controller =
static_cast<
physx::PxCapsuleController *>(mgr->createController(desc));
112 qWarning() <<
"QtQuick3DPhysics internal error: could not create controller.";
116 controller->setUserData(
static_cast<
void *>(frontendNode));
118 auto *actor = controller->getActor();
120 actor->userData = characterController;
122 qWarning() <<
"QtQuick3DPhysics internal error: CharacterController created without actor.";
126 QHash<QQuick3DNode *, QMatrix4x4> & )
128 if (controller ==
nullptr)
131 auto *characterController =
static_cast<QCharacterController *>(frontendNode);
134 const auto &shapes = characterController->getCollisionShapesList();
135 auto capsule = shapes.length() == 1 ? qobject_cast<QCapsuleShape *>(shapes.front()) :
nullptr;
137 if (shapes.length() != 1) {
138 qWarning() <<
"CharacterController: invalid collision shapes list.";
139 }
else if (!capsule) {
140 qWarning() <<
"CharacterController: collision shape is not a capsule.";
142 const QVector3D sceneScale = characterController->sceneScale();
143 const qreal heightScale = sceneScale.y();
144 const qreal radiusScale = sceneScale.x();
147 const float heightNew = heightScale * capsule->height();
148 if (!qFuzzyCompare(controller->getHeight(), heightNew))
149 controller->resize(heightNew);
151 const float radiusNew = 0.5f * radiusScale * capsule->diameter();
152 if (!qFuzzyCompare(controller->getRadius(), radiusNew))
153 controller->setRadius(radiusNew);
155 const float stepOffsetNew = 0.25f * heightNew;
156 if (!qFuzzyCompare(controller->getStepOffset(), stepOffsetNew))
157 controller->setStepOffset(stepOffsetNew);
161 QVector3D position = QPhysicsUtils::toQtType(physx::toVec3(controller->getPosition()));
162 const QQuick3DNode *parentNode =
static_cast<QQuick3DNode *>(characterController->parentItem());
165 characterController->setPosition(position);
167 characterController->setPosition(parentNode->mapPositionFromScene(position));
170 QVector3D teleportPos;
171 bool teleport = characterController->getTeleport(teleportPos);
173 controller->setPosition({ teleportPos.x(), teleportPos.y(), teleportPos.z() });
174 }
else if (deltaTime > 0) {
175 const auto displacement =
176 QPhysicsUtils::toPhysXType(characterController->getDisplacement(deltaTime));
178 controller->move(displacement, displacement.magnitude() / 100, deltaTime, {});
179 characterController->setCollisions(QCharacterController::Collisions(uint(collisions)));