Qt Quick Física 3D - Ejemplo de masa
Demuestra diferentes formas de establecer la masa y la inercia de un cuerpo.

Este ejemplo demuestra tres formas diferentes de configurar la masa y la inercia de un cuerpo. La escena consta de tres cuerpos que consisten en tres esferas apiladas verticalmente. Todos estos cuerpos tienen la misma masa pero diferentes centros de masa y tensores de inercia, lo que les da un comportamiento diferente al colisionar.
Configuración
Primero añadimos nuestro PhysicsWorld:
PhysicsWorld { running: true gravity: Qt.vector3d(0, -9.81, 0) typicalLength: 1 typicalSpeed: 10 scene: viewport.scene }
Hacemos la configuración habitual donde tenemos un entorno, cámara y luces:
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 }
Objetos físicos
Tenemos nuestro plano estático normal:
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 } }
Definimos una clase QML personalizada para nuestro cuerpo que llamamos RolyPoly ya que se comportan como los llamados juguetes roly-poly. El RolyPoly es un DynamicRigidBody con tres formas de colisión esféricas:
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 } } }
A continuación, añadimos tres roly-polys a nuestra escena:
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 }
Los roly-poly púrpura y azul tienen un centro de masa y un tensor de inercia personalizados. Dado que los cuerpos utilizan una densidad uniforme por defecto y calcularán la masa y la inercia automáticamente, configuramos massMode en DynamicRigidBody.MassAndInertiaTensor en nuestros cuerpos morado y azul para utilizar en su lugar los tensores de masa e inercia proporcionados. El centro de masa más bajo hará que los cuerpos siempre se mantengan en pie después de ser empujados. El tensor de inercia del cuerpo morado hace que se tambalee fácilmente en una dirección pero difícilmente en la otra. El cuerpo rojo tiene un centro de masa calculado automáticamente y, por tanto, seguirá tumbado después de ser derribado.
Disparar bolas
Para probar el comportamiento de los diferentes cuerpos añadimos un Nodo para disparar bolas:
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() } }
A continuación añadimos un WasdController para poder mover la cámara y apuntar y disparar bolas a los cuerpos:
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) } }
Ficheros:
© 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.