Qt Quick 3D Physik – Beispiel zur Masse
Veranschaulicht verschiedene Möglichkeiten, Masse und Trägheit eines Körpers festzulegen.

Dieses Beispiel veranschaulicht drei verschiedene Möglichkeiten, die Masse und Trägheit eines Körpers festzulegen. Die Szene besteht aus drei Körpern, die sich aus drei vertikal übereinander angeordneten Kugeln zusammensetzen. Diese Körper haben alle die gleiche Masse, jedoch unterschiedliche Massenschwerpunkte und Trägheitstensor, wodurch sie sich bei einer Kollision unterschiedlich verhalten.
Einrichtung
Zunächst fügen wir unsere „ PhysicsWorld “ hinzu:
PhysicsWorld {
running: true
gravity: Qt.vector3d(0, -9.81, 0)
typicalLength: 1
typicalSpeed: 10
scene: viewport.scene
}Wir nehmen die übliche Einrichtung vor, bei der wir eine Umgebung, eine Kamera und Lichtquellen haben:
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
}Physikalische Objekte
Wir haben unsere übliche statische Ebene:
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
}
}Wir definieren eine benutzerdefinierte QML-Klasse für unseren Körper, die wir „RolyPoly“ nennen, da sie sich wie sogenannte Roly-Poly-Spielzeuge verhält. Das RolyPoly ist ein „ DynamicRigidBody “ mit drei kugelförmigen Kollisionsformen:
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
}
}
}Anschließend fügen wir unserer Szene drei Roly-Polys hinzu:
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
}Die violetten und blauen Roly-Polys verfügen über einen benutzerdefinierten Massenschwerpunkt und einen Trägheitstensor. Da Körper standardmäßig eine gleichmäßige Dichte verwenden und Masse sowie Trägheit automatisch berechnen, setzen wir bei unseren violetten und blauen Körpern `massMode` auf ` DynamicRigidBody.MassAndInertiaTensor`, um stattdessen unsere bereitgestellten Masse- und Trägheitstensoren zu verwenden. Durch den tiefer liegenden Schwerpunkt stehen die Körper immer wieder auf, nachdem sie umgestoßen wurden. Der Trägheitstensor des violetten Körpers sorgt dafür, dass er leicht in eine Richtung wackelt, in die andere jedoch kaum. Der rote Körper hat einen automatisch berechneten Schwerpunkt und bleibt daher liegen, nachdem er umgestoßen wurde.
Bälle abschießen
Um das Verhalten der verschiedenen Körper zu testen, fügen wir einen Knoten zum Schießen von Bällen hinzu:
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()
}
}Anschließend fügen wir einen „ WasdController “ hinzu, um die Kamera zu bewegen, zu zielen und Bälle auf die Körper zu schießen:
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) }
}Dateien:
© 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.