Qt Quick 3D Physics - Exemple sur la masse
Illustre différentes façons de définir la masse et l'inertie d'un corps.

Cet exemple présente trois méthodes différentes pour définir la masse et l'inertie d'un corps. La scène se compose de trois corps, constitués de trois sphères empilées verticalement. Ces corps ont tous la même masse, mais leurs centres de masse et leurs tenseurs d'inertie diffèrent, ce qui leur confère un comportement différent en cas de collision.
Configuration
Nous commençons par ajouter nos « PhysicsWorld » :
PhysicsWorld {
running: true
gravity: Qt.vector3d(0, -9.81, 0)
typicalLength: 1
typicalSpeed: 10
scene: viewport.scene
}Nous procédons à la configuration habituelle avec un environnement, une caméra et des lumières :
environment: SceneEnvironment {
clearColor: "lightblue"
backgroundMode: SceneEnvironment.Color
}
PerspectiveCamera {
id: camera
position: Qt.vector3d(0, 2, 5)
eulerRotation: Qt.vector3d(-10, 0, 0)
clipFar: 100
clipNear: 0.01
}
DirectionalLight {
eulerRotation.x: -45
eulerRotation.y: 45
castsShadow: true
brightness: 1
shadowFactor: 50
shadowBias: 0.1
pcfFactor: 0.01
}Objets physiques
Nous disposons de notre plan statique habituel :
StaticRigidBody {
position: Qt.vector3d(0, 0, 0)
eulerRotation: Qt.vector3d(-90, 0, 0)
collisionShapes: PlaneShape {}
Model {
source: "#Rectangle"
materials: PrincipledMaterial {
baseColor: "green"
}
castsShadows: false
receivesShadows: true
}
}Nous définissons une classe QML personnalisée pour notre corps, que nous appelons RolyPoly, car il se comporte comme un jouet « roly-poly ». Le RolyPoly est un « DynamicRigidBody » doté de trois formes de collision sphériques :
DynamicRigidBody {
id: body
property string color: "blue"
collisionShapes: [
SphereShape {
id: sphere0
diameter: 1
},
SphereShape {
id: sphere1
diameter: 0.8
position: Qt.vector3d(0, 0.6, 0)
},
SphereShape {
id: sphere2
diameter: 0.6
position: Qt.vector3d(0, 1.1, 0)
}
]
Model {
source: "#Sphere"
position: sphere0.position
scale: Qt.vector3d(1,1,1).times(sphere0.diameter*0.01)
materials: PrincipledMaterial {
baseColor: body.color
}
}
Model {
source: "#Sphere"
position: sphere1.position
scale: Qt.vector3d(1,1,1).times(sphere1.diameter*0.01)
materials: PrincipledMaterial {
baseColor: body.color
}
}
Model {
source: "#Sphere"
position: sphere2.position
scale: Qt.vector3d(1,1,1).times(sphere2.diameter*0.01)
materials: PrincipledMaterial {
baseColor: body.color
}
}
}Nous ajoutons ensuite trois « roly-polys » à notre scène :
RolyPoly {
position: Qt.vector3d(-2, 0.5, 0)
color: "blue"
mass: 0.9
centerOfMassPosition: Qt.vector3d(0, -0.5, 0)
inertiaTensor: Qt.vector3d(0.217011, 0.0735887, 0.217011)
massMode: DynamicRigidBody.MassAndInertiaTensor
}
RolyPoly {
position: Qt.vector3d(0, 0.5, 0)
color: "purple"
mass: 0.9
centerOfMassPosition: Qt.vector3d(0, -0.5, 0)
inertiaTensor: Qt.vector3d(0.05, 100, 100)
massMode: DynamicRigidBody.MassAndInertiaTensor
}
RolyPoly {
position: Qt.vector3d(2, 0.5, 0)
color: "red"
mass: 0.9
massMode: DynamicRigidBody.Mass
}Les RolyPoly violets et bleus possèdent un centre de masse et un tenseur d’inertie personnalisés. Étant donné que les corps utilisent par défaut une densité uniforme et calculent automatiquement la masse et l’inertie, nous définissons `massMode` sur ` DynamicRigidBody.MassAndInertiaTensor` pour nos corps violets et bleus afin d’utiliser à la place les tenseurs de masse et d’inertie que nous avons fournis. Le centre de masse plus bas fera en sorte que les corps se redressent toujours après avoir été renversés. Le tenseur d’inertie du corps violet fait en sorte qu’il vacillera facilement dans un sens mais à peine dans l’autre. Le corps rouge possède un centre de masse calculé automatiquement et restera donc couché après avoir été renversé.
Lancer de balles
Pour tester le comportement des différents corps, nous ajoutons un nœud permettant de tirer des balles :
Node {
id: shapeSpawner
property var spheres: []
property var sphereComponent: Qt.createComponent("Sphere.qml")
function createBall(position, forward) {
let diameter = 0.2
let speed = 20
let sphere = sphereComponent.createObject(shapeSpawner, {
"position": position,
"sphereDiameter": diameter
})
sphere.setLinearVelocity(forward.times(speed))
var pair = {
"sphere": sphere,
"date": Date.now()
}
spheres.push(pair)
if (sphere === null) {
console.log("Error creating object")
}
}
function clean() {
spheres = spheres.filter(sphere => {
let diff = Date.now() - sphere['date'];
if (diff > 5000) {
sphere['sphere'].destroy();
return false;
}
return true;
});
}
Timer {
interval: 200
running: true
repeat: true
onTriggered: shapeSpawner.clean()
}
}Nous ajoutons ensuite un « WasdController » pour pouvoir déplacer la caméra, viser et tirer des balles sur les corps :
WasdController {
speed: 0.01
shiftSpeed: 0.1
controlledObject: camera
Keys.onPressed: (event) => {
handleKeyPress(event);
if (event.key === Qt.Key_Space) {
shapeSpawner.createBall(camera.position, camera.forward);
}
}
Keys.onReleased: (event) => { handleKeyRelease(event) }
}Fichiers :
© 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.