Qt Quick 3D Physics - Impeller Example
Demonstrates using trigger bodies and collision info.
This example demonstrates how to use trigger bodies and collision info. The scene consists of a green static plane, a red dynamic sphere, a pink box trigger and a blue static sphere. When the red sphere overlaps the trigger body it will turn yellow and when it collides with the blue sphere it will be repelled away.
Setup
As usual we need to add our DynamicsWorld:
DynamicsWorld { gravity: Qt.vector3d(0, -490, 0) }
We also add a View3D where we put our scene objects. In this we have some settings for the visual environment:
environment: SceneEnvironment { clearColor: "#d6dbdf" backgroundMode: SceneEnvironment.Color } PerspectiveCamera { position: Qt.vector3d(0, 200, 1000) clipFar: 2000 clipNear: 1 } DirectionalLight { eulerRotation.x: -45 eulerRotation.y: 45 castsShadow: true brightness: 1 shadowFactor: 100 }
Physical objects
We have our regular static plane:
StaticRigidBody { position: Qt.vector3d(0, -100, 0) eulerRotation: Qt.vector3d(-90, 0, 0) collisionShapes: PlaneShape {} Model { source: "#Rectangle" scale: Qt.vector3d(500, 500, 0) materials: PrincipledMaterial { baseColor: "green" } castsShadows: false receivesShadows: true } }
This is how our dynamic sphere is defined:
DynamicRigidBody { id: sphere density: 0.00001 position: Qt.vector3d(0, 600, 0) property bool inArea: false sendContactReports: true enableTriggerReports: true collisionShapes: SphereShape {} Model { source: "#Sphere" materials: PrincipledMaterial { baseColor: sphere.inArea ? "yellow" : "red" } } }
The property inArea
is a custom property we use to keep track of when the sphere is overlapping the box trigger body. This is then used for the baseColor
property to make the sphere yellow when it is overlapping the box and red otherwise. Since we want the sphere to partake in contact reporting the property sendContactReports needs to be set to true
.
Now let's look at the trigger body:
TriggerBody { position: Qt.vector3d(0, 350, 0) scale: Qt.vector3d(1, 2, 1) collisionShapes: BoxShape { id: boxShape } Model { source: "#Cube" materials: PrincipledMaterial { baseColor: Qt.rgba(1, 0, 1, 0.2) alphaMode: PrincipledMaterial.Blend } } onBodyEntered: (body) => { if (body.hasOwnProperty('inArea')) body.inArea = true; } onBodyExited: (body) => { if (body.hasOwnProperty('inArea')) body.inArea = false; } }
The qml type is a TriggerBody which acts like a static body except it's collisions are inactive. Instead it will trigger bodyEntered and bodyExited method calls. In this case we check if the triggering body has a inArea
property and if so set it to true
or false
.
Finally, lets look at the impeller:
StaticRigidBody { position: Qt.vector3d(0, 0, 0) scale: Qt.vector3d(2, 2, 2) receiveContactReports: true collisionShapes: SphereShape {} Model { source: "#Sphere" materials: PrincipledMaterial { baseColor: "blue" } } onBodyContact: (body, positions, impulses, normals) => { for (var normal of normals) { let force = normal.times(-2000); body.applyCentralImpulse(force); } } }
This is a static body and we set receiveContactReports to true
to enable the collision callbacks. The callback bodyContact gets called whenever a collision is reported. In the method we add a repelling impulse in the opposite direction of the collision.
Files:
© 2023 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.