Qt Quick 3D Physics - Joints Example
Demonstrates using joints in a physics scene.

This example demonstrates using the joints available in Quick 3D Physics. Most joint types (DistanceJoint, PrismaticJoint, RevoluteJoint, and SphericalJoint) inherit from FlexibleJoint to support soft constraints via stiffness and damping. Additionally, D6Joint provides fully configurable 6-degrees-of-freedom constraints, while FixedJoint completely locks all degrees of freedom.
The scene is a typical scene with a PhysicsWorld, a View3D with a PerspectiveCamera and a DirectionalLight:
Window {
width: 640
height: 480
visible: true
title: qsTr("Qt Quick 3D Physics - Joints")
PhysicsWorld {
scene: viewport.scene
running: true
}
View3D {
id: viewport
anchors.fill: parent
environment: SceneEnvironment {
clearColor: "#d6dbdf"
backgroundMode: SceneEnvironment.Color
}
PerspectiveCamera {
position: Qt.vector3d(0, 600, 700)
eulerRotation: Qt.vector3d(-30, 0, 0)
clipFar: 5000
clipNear: 1
}
DirectionalLight {
eulerRotation.x: -45
eulerRotation.y: 45
castsShadow: true
brightness: 1
shadowFactor: 50
shadowMapQuality: Light.ShadowMapQualityHigh
}
Rope {
eulerRotation: Qt.vector3d(0, 0, -90)
position: Qt.vector3d(0, 500, 0)
}
SoftRope {
eulerRotation: Qt.vector3d(0, 0, -90)
position: Qt.vector3d(100, 500, 0)
}
Prismatic {
id: prismatic
position: Qt.vector3d(-250, 100, 0)
}
Revolute {
id: revolute
position: Qt.vector3d(200, 200, 100)
}
Spring {
eulerRotation: Qt.vector3d(0, 0, 0)
position: Qt.vector3d(0, 1, -400)
}
StaticRigidBody {
position: Qt.vector3d(0, -100, 0)
eulerRotation: Qt.vector3d(-90, 0, 0)
collisionShapes: PlaneShape {}
Model {
source: "#Rectangle"
scale: Qt.vector3d(20, 20, 1)
materials: PrincipledMaterial {
baseColor: "green"
}
castsShadows: false
receivesShadows: true
}
}
FrameAnimation {
id: animator
running: true
onTriggered: {
prismatic.jointRotation.z += 1
revolute.jointRotation.x += 0.95
}
}
}
}There is a StaticRigidBody with a PlaneShape to act as the floor. There are several custom QML objects (Rope, SoftRope, Spring, Prismatic, and Revolute) demonstrating different joint configurations.
Rope {
eulerRotation: Qt.vector3d(0, 0, -90)
position: Qt.vector3d(0, 500, 0)
}
SoftRope {
eulerRotation: Qt.vector3d(0, 0, -90)
position: Qt.vector3d(100, 500, 0)
}
Prismatic {
id: prismatic
position: Qt.vector3d(-250, 100, 0)
}
Revolute {
id: revolute
position: Qt.vector3d(200, 200, 100)
}
Spring {
eulerRotation: Qt.vector3d(0, 0, 0)
position: Qt.vector3d(0, 1, -400)
}The Rope object is a series of capsules and a sphere that are connected with spherical joints for the capsules and a fixed joint for the sphere.
Node {
id: root
SphericalJoint {
bodyB: shape0
positionA: root.position
positionB: Qt.vector3d(-25, 0, 0)
}
SphericalJoint {
bodyA: shape0
bodyB: shape1
positionA: Qt.vector3d(25, 0, 0)
positionB: Qt.vector3d(-25, 0, 0)
}
SphericalJoint {
bodyA: shape1
bodyB: shape2
positionA: Qt.vector3d(25, 0, 0)
positionB: Qt.vector3d(-25, 0, 0)
}
SphericalJoint {
bodyA: shape2
bodyB: shape3
positionA: Qt.vector3d(25, 0, 0)
positionB: Qt.vector3d(-25, 0, 0)
}
SphericalJoint {
bodyA: shape3
bodyB: shape4
positionA: Qt.vector3d(25, 0, 0)
positionB: Qt.vector3d(-25, 0, 0)
}
SphericalJoint {
bodyA: shape4
bodyB: shape5
positionA: Qt.vector3d(25, 0, 0)
positionB: Qt.vector3d(-25, 0, 0)
}
FixedJoint {
bodyA: shape5
bodyB: sphere
positionA: Qt.vector3d(25, 0, 0)
positionB: Qt.vector3d(0, 0, 0)
}
// Neighboring links touch exactly at their joints, so each body ignores collisions
// with its immediate neighbors to avoid fighting the joint with contact forces.
DynamicRigidBody {
id: shape0
position: Qt.vector3d(25, 0, 0)
filterGroup: 0
filterIgnoreGroups: 0b0000010
collisionShapes: CapsuleShape {
diameter: 10
height: 40
}
Model {
geometry: CapsuleGeometry {
diameter: 10
height: 40
}
materials: PrincipledMaterial {
baseColor: "blue"
}
}
}
DynamicRigidBody {
id: shape1
position: Qt.vector3d(75, 0, 0)
filterGroup: 1
filterIgnoreGroups: 0b0000101
collisionShapes: CapsuleShape {
diameter: 10
height: 40
}
Model {
geometry: CapsuleGeometry {
diameter: 10
height: 40
}
materials: PrincipledMaterial {
baseColor: "blue"
}
}
}
DynamicRigidBody {
id: shape2
position: Qt.vector3d(125, 0, 0)
filterGroup: 2
filterIgnoreGroups: 0b0001010
collisionShapes: CapsuleShape {
diameter: 10
height: 40
}
Model {
geometry: CapsuleGeometry {
diameter: 10
height: 40
}
materials: PrincipledMaterial {
baseColor: "blue"
}
}
}
DynamicRigidBody {
id: shape3
position: Qt.vector3d(175, 0, 0)
filterGroup: 3
filterIgnoreGroups: 0b0010100
collisionShapes: CapsuleShape {
diameter: 10
height: 40
}
Model {
geometry: CapsuleGeometry {
diameter: 10
height: 40
}
materials: PrincipledMaterial {
baseColor: "blue"
}
}
}
DynamicRigidBody {
id: shape4
position: Qt.vector3d(225, 0, 0)
filterGroup: 4
filterIgnoreGroups: 0b0101000
collisionShapes: CapsuleShape {
diameter: 10
height: 40
}
Model {
geometry: CapsuleGeometry {
diameter: 10
height: 40
}
materials: PrincipledMaterial {
baseColor: "blue"
}
}
}
DynamicRigidBody {
id: shape5
position: Qt.vector3d(275, 0, 0)
filterGroup: 5
filterIgnoreGroups: 0b1010000
collisionShapes: CapsuleShape {
diameter: 10
height: 40
}
Model {
geometry: CapsuleGeometry {
diameter: 10
height: 40
}
materials: PrincipledMaterial {
baseColor: "blue"
}
}
}
DynamicRigidBody {
id: sphere
position: Qt.vector3d(300, 0, 0)
scale: Qt.vector3d(0.5, 0.5, 0.5)
filterGroup: 6
filterIgnoreGroups: 0b0100000
collisionShapes: SphereShape {}
Model {
source: "#Sphere"
materials: PrincipledMaterial {
baseColor: "blue"
}
}
}
}The SoftRope object demonstrates how flexible joints use stiffness and damping properties to create spring-like soft connections.
Node {
id: root
property real stiffness : 15000
property real damping : 500
SphericalJoint {
bodyB: shape0
positionA: root.position
positionB: Qt.vector3d(-25, 0, 0)
}
PrismaticJoint {
bodyA: shape0
bodyB: shape1
positionA: Qt.vector3d(25, 0, 0)
positionB: Qt.vector3d(-25, 0, 0)
stiffness: root.stiffness
damping: root.damping
lowerLimit: -20
upperLimit: 0
}
SphericalJoint {
bodyA: shape1
bodyB: shape2
positionA: Qt.vector3d(25, 0, 0)
positionB: Qt.vector3d(-25, 0, 0)
}
PrismaticJoint {
bodyA: shape2
bodyB: shape3
positionA: Qt.vector3d(25, 0, 0)
positionB: Qt.vector3d(-25, 0, 0)
stiffness: root.stiffness
damping: root.damping
lowerLimit: -20
upperLimit: 0
}
FixedJoint {
bodyA: shape3
bodyB: sphere
positionA: Qt.vector3d(25, 0, 0)
positionB: Qt.vector3d(0, 0, 0)
}
// Neighboring links touch exactly at their joints, so each body ignores collisions
// with its immediate neighbors to avoid fighting the joint with contact forces.
DynamicRigidBody {
id: shape0
position: Qt.vector3d(25, 0, 0)
filterGroup: 0
filterIgnoreGroups: 0b00010
collisionShapes: CapsuleShape {
diameter: 10
height: 40
}
Model {
geometry: CapsuleGeometry {
diameter: 10
height: 40
}
materials: PrincipledMaterial {
baseColor: "blueviolet"
}
}
}
DynamicRigidBody {
id: shape1
position: Qt.vector3d(75, 0, 0)
filterGroup: 1
filterIgnoreGroups: 0b00101
collisionShapes: CapsuleShape {
diameter: 10
height: 40
}
Model {
geometry: CapsuleGeometry {
diameter: 10
height: 40
}
materials: PrincipledMaterial {
baseColor: "blueviolet"
}
}
}
DynamicRigidBody {
id: shape2
position: Qt.vector3d(125, 0, 0)
filterGroup: 2
filterIgnoreGroups: 0b01010
collisionShapes: CapsuleShape {
diameter: 10
height: 40
}
Model {
geometry: CapsuleGeometry {
diameter: 10
height: 40
}
materials: PrincipledMaterial {
baseColor: "blueviolet"
}
}
}
DynamicRigidBody {
id: shape3
position: Qt.vector3d(175, 0, 0)
filterGroup: 3
filterIgnoreGroups: 0b10100
collisionShapes: CapsuleShape {
diameter: 10
height: 40
}
Model {
geometry: CapsuleGeometry {
diameter: 10
height: 40
}
materials: PrincipledMaterial {
baseColor: "blueviolet"
}
}
}
DynamicRigidBody {
id: sphere
position: Qt.vector3d(200, 0, 0)
scale: Qt.vector3d(0.5, 0.5, 0.5)
filterGroup: 4
filterIgnoreGroups: 0b01000
collisionShapes: SphereShape {}
Model {
source: "#Sphere"
materials: PrincipledMaterial {
baseColor: "blueviolet"
}
}
}
}The Spring object shows how to use D6Joint to constrain motion across 6 degrees of freedom with custom linear and angular spring parameters.
Node {
id: root
DynamicRigidBody {
id: baseStand
position: Qt.vector3d(0, 0, 0)
collisionShapes: BoxShape {
extents: Qt.vector3d(50, 10, 50)
}
Model {
source: "#Cube"
scale: Qt.vector3d(0.50, 0.10, 0.50)
materials: PrincipledMaterial {
baseColor: "darkslategray"
}
}
}
DynamicRigidBody {
id: floatingSphere
position: Qt.vector3d(0, 102.5, 0)
collisionShapes: SphereShape {
diameter: 20
}
Model {
source: "#Sphere"
// scale: Qt.vector3d(0.2, 0.2, 0.2)
materials: PrincipledMaterial {
baseColor: "cornflowerblue"
roughness: 0.2
}
}
}
// D6 Joint acting as a soft spring wire
D6Joint {
bodyA: baseStand
bodyB: floatingSphere
positionA: Qt.vector3d(0, 2.5, 0)
positionB: Qt.vector3d(0, -100, 0)
xMotion: D6Joint.Locked
yMotion: D6Joint.Locked
zMotion: D6Joint.Locked
// Allow omnidirectional rotation
twistMotion: D6Joint.Limited
swingMotionY: D6Joint.Limited
swingMotionZ: D6Joint.Limited
twistLimitLower: -0.07 // ~-4 degrees in radians
twistLimitUpper: 0.07 // ~+4 degrees in radians
swingLimitAngleY: 0.087 // ~5 degrees in radians
swingLimitAngleZ: 0.087 // ~5 degrees in radians
angularStiffness: 2550000.0
angularDamping: 2500.0
}
}The Prismatic object consists of two bars locked in a prismatic joint along the x-axis of both of them. With this joint the smaller rod can move freely along this x-axis until it reaches its upper and lower constraint limit.
Node {
id: root
property vector3d jointRotation : Qt.vector3d(0, 0, 90)
PrismaticJoint {
bodyA: prismaticBoxA
bodyB: prismaticBoxB
lowerLimit: -200
upperLimit: 0
positionA: Qt.vector3d(100, 0, 0)
positionB: Qt.vector3d(-100, 0, 0)
}
DynamicRigidBody {
id: prismaticBoxA
position: Qt.vector3d(0, 200, 0)
eulerRotation: root.jointRotation
kinematicPosition: Qt.vector3d(0, 200, 0)
kinematicEulerRotation: root.jointRotation
isKinematic: true
scale: Qt.vector3d(2, 0.5, 0.5)
collisionShapes: BoxShape {}
Model {
source: "#Cube"
materials: PrincipledMaterial {
baseColor: "yellow"
}
}
}
DynamicRigidBody {
id: prismaticBoxB
position: Qt.vector3d(200 * Math.cos(root.jointRotation.z * Math.PI / 180),
200 + 200 * Math.sin(root.jointRotation.z * Math.PI / 180),
0)
eulerRotation: root.jointRotation
scale: Qt.vector3d(2, 0.4, 0.4)
collisionShapes: BoxShape {}
Model {
source: "#Cube"
materials: PrincipledMaterial {
baseColor: "blue"
}
}
}
}The Revolute object consists of two bars rotated by 90 degrees and locked in a revolute joint.
Node {
id: root
property vector3d jointRotation : Qt.vector3d(0, 90, 0)
RevoluteJoint {
bodyA: revoluteBoxA
bodyB: revoluteBoxB
positionA: Qt.vector3d(100, 0, 0)
positionB: Qt.vector3d(100, 0, 0)
orientationB: Quaternion.fromEulerAngles(0, 0, 90)
angularLimitLower: -Math.PI / 4
angularLimitUpper: Math.PI / 4
enableAngularLimit: true
}
DynamicRigidBody {
id: revoluteBoxA
position: Qt.vector3d(0, 0, 0)
eulerRotation: root.jointRotation
kinematicPosition: Qt.vector3d(0, 0, 0)
kinematicEulerRotation: root.jointRotation
isKinematic: true
scale: Qt.vector3d(2, 0.5, 0.5)
collisionShapes: BoxShape {}
Model {
source: "#Cube"
materials: PrincipledMaterial {
baseColor: "yellow"
}
}
}
DynamicRigidBody {
id: revoluteBoxB
position: Qt.vector3d(0, 100, -100)
eulerRotation: Qt.vector3d(0, 90, -90)
scale: Qt.vector3d(2, 0.5, 0.5)
collisionShapes: BoxShape {}
Model {
source: "#Cube"
materials: PrincipledMaterial {
baseColor: "blue"
}
}
}
}Going back to the main scene there is a FrameAnimation object that rotates the kinematic prismatic and revolute joints.
FrameAnimation {
id: animator
running: true
onTriggered: {
prismatic.jointRotation.z += 1
revolute.jointRotation.x += 0.95
}
}With all these moving parts we can see how the different joints interact in a physics scene.
Files:
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.