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

This example demonstrates using a few of the joints available in Quick 3D Physics.
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)
}
Prismatic {
id: prismatic
position: Qt.vector3d(-250, 100, 0)
}
Revolute {
id: revolute
position: Qt.vector3d(200, 200, 100)
}
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 and three custom QML objects; Rope, Prismatic and Revolute.
Rope {
eulerRotation: Qt.vector3d(0, 0, -90)
position: Qt.vector3d(0, 500, 0)
}
Prismatic {
id: prismatic
position: Qt.vector3d(-250, 100, 0)
}
Revolute {
id: revolute
position: Qt.vector3d(200, 200, 100)
}
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(-20, 0, 0)
}
SphericalJoint {
bodyA: shape0
bodyB: shape1
positionA: Qt.vector3d(20, 0, 0)
positionB: Qt.vector3d(-20, 0, 0)
}
SphericalJoint {
bodyA: shape1
bodyB: shape2
positionA: Qt.vector3d(20, 0, 0)
positionB: Qt.vector3d(-20, 0, 0)
}
SphericalJoint {
bodyA: shape2
bodyB: shape3
positionA: Qt.vector3d(20, 0, 0)
positionB: Qt.vector3d(-20, 0, 0)
}
SphericalJoint {
bodyA: shape3
bodyB: shape4
positionA: Qt.vector3d(20, 0, 0)
positionB: Qt.vector3d(-20, 0, 0)
}
SphericalJoint {
bodyA: shape4
bodyB: shape5
positionA: Qt.vector3d(20, 0, 0)
positionB: Qt.vector3d(-20, 0, 0)
}
FixedJoint {
bodyA: shape5
bodyB: sphere
positionA: Qt.vector3d(20, 0, 0)
positionB: Qt.vector3d(0, 0, 0)
}
DynamicRigidBody {
id: shape0
position: Qt.vector3d(0, 0, 0)
collisionShapes: CapsuleShape {
diameter: 10
height: 40
}
Model {
geometry: CapsuleGeometry {
diameter: 10
height: 40
}
materials: PrincipledMaterial {
baseColor: "blue"
}
}
}
DynamicRigidBody {
id: shape1
position: Qt.vector3d(40, 0, 0)
collisionShapes: CapsuleShape {
diameter: 10
height: 40
}
Model {
geometry: CapsuleGeometry {
diameter: 10
height: 40
}
materials: PrincipledMaterial {
baseColor: "blue"
}
}
}
DynamicRigidBody {
id: shape2
position: Qt.vector3d(80, 0, 0)
collisionShapes: CapsuleShape {
diameter: 10
height: 40
}
Model {
geometry: CapsuleGeometry {
diameter: 10
height: 40
}
materials: PrincipledMaterial {
baseColor: "blue"
}
}
}
DynamicRigidBody {
id: shape3
position: Qt.vector3d(120, 0, 0)
collisionShapes: CapsuleShape {
diameter: 10
height: 40
}
Model {
geometry: CapsuleGeometry {
diameter: 10
height: 40
}
materials: PrincipledMaterial {
baseColor: "blue"
}
}
}
DynamicRigidBody {
id: shape4
position: Qt.vector3d(160, 0, 0)
collisionShapes: CapsuleShape {
diameter: 10
height: 40
}
Model {
geometry: CapsuleGeometry {
diameter: 10
height: 40
}
materials: PrincipledMaterial {
baseColor: "blue"
}
}
}
DynamicRigidBody {
id: shape5
position: Qt.vector3d(200, 0, 0)
collisionShapes: CapsuleShape {
diameter: 10
height: 40
}
Model {
geometry: CapsuleGeometry {
diameter: 10
height: 40
}
materials: PrincipledMaterial {
baseColor: "blue"
}
}
}
DynamicRigidBody {
id: sphere
position: Qt.vector3d(240, 0, 0)
scale: Qt.vector3d(0.5, 0.5, 0.5)
collisionShapes: SphereShape {}
Model {
source: "#Sphere"
materials: PrincipledMaterial {
baseColor: "blue"
}
}
}
}
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, 0)
PrismaticJoint {
bodyA: prismaticBoxA
bodyB: prismaticBoxB
lowerLimit: -200
upperLimit: 0
positionA: Qt.vector3d(100, 0, 0)
positionB: Qt.vector3d(-100, 0, 0)
}
DynamicRigidBody {
id: prismaticBoxA
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(0, 0, 0)
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
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: