Qt Quick 3D Physics - 质量示例
演示设置物体质量和惯性的不同方法。
本例演示了设置物体质量和惯性的三种不同方法。场景由三个垂直叠放的球体组成。这些物体的质量相同,但质心和惯性张量不同,因此在碰撞时会产生不同的行为。
设置
我们首先添加PhysicsWorld :
PhysicsWorld { running: true gravity: Qt.vector3d(0, -9.81, 0) typicalLength: 1 typicalSpeed: 10 scene: viewport.scene }
我们进行常规设置,包括环境、摄像机和灯光:
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 }
物理对象
我们有常规的静态平面:
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 } }
我们为我们的身体定义了一个自定义 QML 类,我们称之为 RolyPoly,因为它们的行为就像所谓的 Roly-poly 玩具。RolyPoly 是一个带有三个球形碰撞形状的DynamicRigidBody :
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 } } }
然后,我们在场景中添加三个 RolyPoly:
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 }
紫色和蓝色的 RolyPoly 具有自定义的质量中心和惯性张量。由于物体默认使用均匀密度并会自动计算质量和惯性,因此我们在紫色和蓝色物体中将 massMode 设置为DynamicRigidBody.MassAndInertiaTensor,以使用我们提供的质量和惯性张量。较低的质量中心可以使物体在被推倒后始终站立起来。紫色物体的惯性张量使其在一个方向上很容易晃动,但在另一个方向上几乎不会晃动。红色物体的质心是自动计算出来的,因此被推倒后会一直躺着。
投篮
为了测试不同物体的行为,我们添加了一个用于射球的节点:
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() } }
然后,我们添加一个WasdController ,以便能够移动摄像机,瞄准并向车身射球:
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) } }
文件:
© 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.