Revision control

Copy as Markdown

// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qdistancejoint_p.h"
#include "physxnode/qphysxactorbody_p.h"
#include "qabstractphysicsnode_p.h"
#include "qstaticphysxobjects_p.h"
#include <extensions/PxDistanceJoint.h>
#include <foundation/PxSimpleTypes.h>
QT_BEGIN_NAMESPACE
/*!
\qmltype DistanceJoint
\inqmlmodule QtQuick3D.Physics
\since 6.12
\inherits FlexibleJoint
\brief A distance joint.
A distance joint that will keep the origins of the joint within the
distance range specified by \l{DistanceJoint::}{minDistance} and
\l{DistanceJoint::}{maxDistance}.
\sa {FixedJoint}
\sa {PrismaticJoint}
\sa {RevoluteJoint}
\sa {SphericalJoint}
\sa {D6Joint}
*/
/*!
\qmlproperty real DistanceJoint::minDistance
\since 6.12
\default 0.0
The minimum distance of the joint constraint. The constraint is only
enforced when this value is greater than \c 0.0.
Range: \c{[0, inf]}
\sa maxDistance
*/
/*!
\qmlproperty real DistanceJoint::maxDistance
\since 6.12
\default 0.0
The maximum distance of the joint constraint. The constraint is only
enforced when this value is greater than \c 0.0.
Range: \c{[0, inf]}
\sa minDistance
*/
float QDistanceJoint::minDistance() const
{
return m_minDistance;
}
void QDistanceJoint::setMinDistance(float newMinDistance)
{
newMinDistance = qBound(0.0f, newMinDistance, PX_MAX_F32);
if (qFuzzyCompare(m_minDistance, newMinDistance))
return;
m_minDistance = newMinDistance;
m_dirtyProperties = true;
emit minDistanceChanged();
}
float QDistanceJoint::maxDistance() const
{
return m_maxDistance;
}
void QDistanceJoint::setMaxDistance(float newMaxDistance)
{
newMaxDistance = qBound(0.0f, newMaxDistance, PX_MAX_F32);
if (qFuzzyCompare(m_maxDistance, newMaxDistance))
return;
m_maxDistance = newMaxDistance;
m_dirtyProperties = true;
emit maxDistanceChanged();
}
physx::PxJoint *QDistanceJoint::createPhysxJoint(physx::PxRigidActor *actorA,
physx::PxRigidActor *actorB,
const physx::PxTransform &trfA,
const physx::PxTransform &trfB)
{
return physx::PxDistanceJointCreate(*StaticPhysXObjects::getReference().physics, actorA, trfA,
actorB, trfB);
}
void QDistanceJoint::setJointProperties()
{
physx::PxDistanceJoint *joint = static_cast<physx::PxDistanceJoint *>(m_joint);
float minDistance = m_minDistance;
float maxDistance = m_maxDistance;
// PhysX doesn't enforce minDistance <= maxDistance itself, but violating
// it produces a constraint that can never be satisfied. Only reorder when
// both limits are actually active - a value left at the 0 "disabled"
// default must never be treated as "smaller than" an actively-configured
// limit on the other side.
if (m_minDistance > 0 && m_maxDistance > 0) {
minDistance = qMin(m_minDistance, m_maxDistance);
maxDistance = qMax(m_minDistance, m_maxDistance);
}
joint->setMinDistance(minDistance);
joint->setMaxDistance(maxDistance);
joint->setDistanceJointFlag(physx::PxDistanceJointFlag::eMIN_DISTANCE_ENABLED, minDistance > 0);
joint->setDistanceJointFlag(physx::PxDistanceJointFlag::eMAX_DISTANCE_ENABLED, maxDistance > 0);
joint->setStiffness(m_stiffness);
joint->setDamping(m_damping);
const bool enableSpring = (m_stiffness > 0.0f) || (m_damping > 0.0f);
joint->setDistanceJointFlag(physx::PxDistanceJointFlag::eSPRING_ENABLED, enableSpring);
}
QT_END_NAMESPACE