- Qt 6.12
- Qt Quick 3D Physics
- Qt Quick 3D Physics Examples and Tutorials
- Qt Quick 3D Physics - Joints Example
- Qt Quick 3D Physics | Commercial or GPLv3

# 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:

- joints/CMakeLists.txt
- joints/Prismatic.qml
- joints/Revolute.qml
- joints/Rope.qml
- joints/joints.pro
- joints/main.cpp
- joints/main.qml
- joints/qml.qrc