69 Q_ASSERT(!controller);
71 auto *characterController =
static_cast<QCharacterController *>(frontendNode);
73 auto shapes = characterController->getCollisionShapesList();
74 if (shapes.length() != 1) {
75 qWarning() <<
"CharacterController: invalid collision shapes list.";
78 auto *capsule = qobject_cast<QCapsuleShape *>(shapes.first());
80 qWarning() <<
"CharacterController: collision shape is not a capsule.";
83 auto *mgr = world->controllerManager();
85 qWarning() <<
"QtQuick3DPhysics internal error: missing controller manager.";
91 const QVector3D scale = characterController->sceneScale();
92 const qreal heightScale = scale.y();
93 const qreal radiusScale = scale.x();
94 physx::PxCapsuleControllerDesc desc;
95 reportCallback =
new ControllerCallback(world);
96 desc.reportCallback = reportCallback;
97 desc.radius = 0.5f * radiusScale * capsule->diameter();
98 desc.height = heightScale * capsule->height();
99 desc.stepOffset = 0.25f * desc.height;
101 desc.material = material;
102 const QVector3D pos = characterController->scenePosition();
103 desc.position = { pos.x(), pos.y(), pos.z() };
106 controller =
static_cast<
physx::PxCapsuleController *>(mgr->createController(desc));
109 qWarning() <<
"QtQuick3DPhysics internal error: could not create controller.";
113 controller->setUserData(
static_cast<
void *>(frontendNode));
115 auto *actor = controller->getActor();
117 actor->userData = characterController;
119 qWarning() <<
"QtQuick3DPhysics internal error: CharacterController created without actor.";
123 QHash<QQuick3DNode *, QMatrix4x4> & )
125 if (controller ==
nullptr)
128 auto *characterController =
static_cast<QCharacterController *>(frontendNode);
131 const auto &shapes = characterController->getCollisionShapesList();
132 auto capsule = shapes.length() == 1 ? qobject_cast<QCapsuleShape *>(shapes.front()) :
nullptr;
134 if (shapes.length() != 1) {
135 qWarning() <<
"CharacterController: invalid collision shapes list.";
136 }
else if (!capsule) {
137 qWarning() <<
"CharacterController: collision shape is not a capsule.";
139 const QVector3D sceneScale = characterController->sceneScale();
140 const qreal heightScale = sceneScale.y();
141 const qreal radiusScale = sceneScale.x();
144 const float heightNew = heightScale * capsule->height();
145 if (!qFuzzyCompare(controller->getHeight(), heightNew))
146 controller->resize(heightNew);
148 const float radiusNew = 0.5f * radiusScale * capsule->diameter();
149 if (!qFuzzyCompare(controller->getRadius(), radiusNew))
150 controller->setRadius(radiusNew);
152 const float stepOffsetNew = 0.25f * heightNew;
153 if (!qFuzzyCompare(controller->getStepOffset(), stepOffsetNew))
154 controller->setStepOffset(stepOffsetNew);
158 QVector3D position = QPhysicsUtils::toQtType(physx::toVec3(controller->getPosition()));
159 const QQuick3DNode *parentNode =
static_cast<QQuick3DNode *>(characterController->parentItem());
162 characterController->setPosition(position);
164 characterController->setPosition(parentNode->mapPositionFromScene(position));
167 QVector3D teleportPos;
168 bool teleport = characterController->getTeleport(teleportPos);
170 controller->setPosition({ teleportPos.x(), teleportPos.y(), teleportPos.z() });
171 }
else if (deltaTime > 0) {
172 const auto displacement =
173 QPhysicsUtils::toPhysXType(characterController->getDisplacement(deltaTime));
175 controller->move(displacement, displacement.magnitude() / 100, deltaTime, {});
176 characterController->setCollisions(QCharacterController::Collisions(uint(collisions)));