Sur cette page

Qt Quick 3D Physics - Exemple de roue

Illustre l'utilisation des corps déclencheurs et des informations de collision.

Capture d'écran d'un rendu 3D montrant une sphère bleue posée sur une surface verte, un bloc rectangulaire rose au-dessus, et une sphère rouge flottant au-dessus

Cet exemple montre comment utiliser les corps de déclenchement et les informations de collision. La scène se compose d’un plan statique vert, d’une sphère dynamique rouge, d’un déclencheur en forme de boîte rose et d’une sphère statique bleue. Lorsque la sphère rouge chevauche le corps de déclenchement, elle devient jaune, et lorsqu’elle entre en collision avec la sphère bleue, elle est repoussée.

Configuration

Comme d’habitude, nous devons ajouter notre fichier « PhysicsWorld » :

PhysicsWorld {
    gravity: Qt.vector3d(0, -490, 0)
    scene: viewport.scene
}

Nous ajoutons également une « View3D » dans laquelle nous plaçons les objets de notre scène. Nous y définissons certains paramètres relatifs à l’environnement visuel :

environment: SceneEnvironment {
    clearColor: "#d6dbdf"
    backgroundMode: SceneEnvironment.Color
}

PerspectiveCamera {
    position: Qt.vector3d(0, 200, 1000)
    clipFar: 2000
    clipNear: 1
}

DirectionalLight {
    eulerRotation.x: -45
    eulerRotation.y: 45
    castsShadow: true
    brightness: 1
    shadowFactor: 50
}

Objets physiques

Nous avons notre plan statique habituel :

StaticRigidBody {
    position: Qt.vector3d(0, -100, 0)
    eulerRotation: Qt.vector3d(-90, 0, 0)
    collisionShapes: PlaneShape {}
    Model {
        source: "#Rectangle"
        scale: Qt.vector3d(500, 500, 1)
        materials: PrincipledMaterial {
            baseColor: "green"
        }
        castsShadows: false
        receivesShadows: true
    }
}

Voici comment notre sphère dynamique est définie :

DynamicRigidBody {
    id: sphere
    massMode: DynamicRigidBody.CustomDensity
    density: 0.00001
    position: Qt.vector3d(0, 600, 0)
    property bool inArea: false
    sendContactReports: true
    receiveTriggerReports: true

    onEnteredTriggerBody: {
        inArea = true
    }
    onExitedTriggerBody: {
        inArea = false
    }

    collisionShapes: SphereShape {}
    Model {
        source: "#Sphere"
        materials: PrincipledMaterial {
            baseColor: sphere.inArea ? "yellow" : "red"
        }
    }
}

La propriété « inArea » est une propriété personnalisée que nous utilisons pour détecter quand la sphère chevauche le corps du déclencheur (box trigger). Elle est ensuite utilisée par la propriété « baseColor » pour colorer la sphère en jaune lorsqu’elle chevauche la boîte, et en rouge dans le cas contraire. Comme nous souhaitons que la sphère participe au signalement des contacts, la propriété sendContactReports doit être définie sur true. Comme nous souhaitons également que la sphère reçoive des rappels lorsqu’elle entre dans un corps de déclenchement ( TriggerBody) ou en sort, la propriété receiveContactReports est également définie sur true. Nous implémentons les méthodes de signal enteredTriggerBody et exitedTriggerBody sur la sphère, où nous définissons la propriété inArea sur true ou false lorsqu’elle entre dans le corps de déclenchement ou en sort.

Examinons maintenant le corps du déclencheur :

TriggerBody {
    position: Qt.vector3d(0, 350, 0)
    scale: Qt.vector3d(1, 2, 1)

    collisionShapes: BoxShape {
        id: boxShape
    }
    Model {
        source: "#Cube"
        materials: PrincipledMaterial {
            baseColor: Qt.rgba(1, 0, 1, 0.2)
            alphaMode: PrincipledMaterial.Blend
        }
    }
}

Le type QML est un « TriggerBody » qui se comporte comme un corps statique, à l’exception de ses collisions qui sont inactives. À la place, il déclenchera les appels de méthodes « enteredTriggerBody » et « exitedTriggerBody » sur la sphère.

Enfin, examinons la roue :

StaticRigidBody {
    position: Qt.vector3d(0, 0, 0)
    scale: Qt.vector3d(2, 2, 2)
    receiveContactReports: true

    collisionShapes: SphereShape {}

    Model {
        source: "#Sphere"
        materials: PrincipledMaterial {
            baseColor: "blue"
        }
    }

    onBodyContact: (body, positions, impulses, normals) => {
        for (let normal of normals) {
            let velocity = normal.times(-700)
            if (body instanceof DynamicRigidBody) {
                (body as DynamicRigidBody).setLinearVelocity(velocity)
            }
        }
    }
}

Il s’agit d’un corps statique et nous définissons receiveContactReports sur true pour activer les callbacks de collision. Le callback bodyContact est appelé chaque fois qu’une collision est signalée. Dans cette méthode, nous appelons setLinearVelocity pour définir la vitesse linéaire dans la direction opposée au vecteur normal de la collision afin de simuler une roue.

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.