Qt Quick 3D Physics - Beispiel Masse
Zeigt, wie Masse und Trägheit eines Körpers auf unterschiedliche Weise festgelegt werden können.
Dieses Beispiel demonstriert drei verschiedene Möglichkeiten, die Masse und Trägheit eines Körpers einzustellen. Die Szene besteht aus drei Körpern, die aus drei vertikal gestapelten Kugeln bestehen. Diese Körper haben alle die gleiche Masse, aber unterschiedliche Massenschwerpunkte und Trägheitstensoren, wodurch sie sich beim Zusammenstoß unterschiedlich verhalten.
Einrichtung
Zuerst 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 üblichen Einstellungen vor, d. h. wir haben eine Umgebung, eine Kamera und Lichter:
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 normale statische Ebene:
StaticRigidBody { position: Qt.vector3d(0, 0, 0) eulerRotation: Qt.vector3d(-90, 0, 0) collisionShapes: PlaneShape {} Model { source: "#Rectangle" materials: DefaultMaterial { diffuseColor: "green" } castsShadows: false receivesShadows: true } }
Wir definieren eine benutzerdefinierte QML-Klasse für unseren Körper, den wir RolyPoly nennen, da er sich wie ein so genanntes RolyPoly-Spielzeug verhält. Das RolyPoly ist ein DynamicRigidBody mit drei kugelförmigen Kollisionsformen:
DynamicRigidBody { 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: color } } Model { source: "#Sphere" position: sphere1.position scale: Qt.vector3d(1,1,1).times(sphere1.diameter*0.01) materials: PrincipledMaterial { baseColor: color } } Model { source: "#Sphere" position: sphere2.position scale: Qt.vector3d(1,1,1).times(sphere2.diameter*0.01) materials: PrincipledMaterial { baseColor: color } } }
Wir fügen dann drei RolyPolys zu unserer Szene 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 }
Das lila und blaue RolyPoly hat einen eigenen Massenschwerpunkt und Trägheitstensor. Da Körper standardmäßig eine einheitliche Dichte verwenden und Masse und Trägheit automatisch berechnen, setzen wir massMode auf DynamicRigidBody.MassAndInertiaTensor in unseren lila und blauen Körpern, um stattdessen unsere bereitgestellten Masse- und Trägheitstensoren zu verwenden. Der niedrigere Massenschwerpunkt sorgt dafür, dass die Körper immer aufstehen, wenn sie umgestoßen werden. Der Trägheitstensor des lila Körpers sorgt dafür, dass er leicht in eine Richtung wackelt, aber kaum in die andere. Der rote Körper hat einen automatisch berechneten Massenschwerpunkt und bleibt daher nach dem Umstoßen liegen.
Bälle schieß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() } }
Wir fügen dann ein WasdController hinzu, um die Kamera zu bewegen 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:
© 2025 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.