On this page

Qt Quick 3D Physics - Raycaster Example

Demonstrates continuous ray intersection queries using Raycaster.

Raycaster intersecting physics bodies

The example sweeps a Raycaster across a static box, a dynamic sphere, and the floor. The ray changes color when it reports an intersection, and a yellow marker shows the scene-space hit position.

Configuring the Ray

The Raycaster is a child of a semi-transparent dynamic body. Its excludeParentBody property determines whether that body can be reported as the closest hit:

Raycaster {
    id: ray
    enabled: enabledCheckBox.checked
    direction: Qt.vector3d(0, -1, 0)
    maxDistance: distanceSlider.value
    includeStatic: staticCheckBox.checked
    includeDynamic: dynamicCheckBox.checked
    excludeParentBody: excludeParentCheckBox.checked
    excludedBodies: excludeSphereCheckBox.checked ? [sphereBody] : []

    Model {
        readonly property real rayLength: ray.isColliding ? ray.hit.distance : ray.maxDistance

        visible: ray.enabled
        source: "#Cube"
        y: -rayLength / 2
        scale: Qt.vector3d(0.025, rayLength / 100, 0.025)
        materials: PrincipledMaterial {
            baseColor: ray.isColliding ? "#24a148" : "#da1e28"
            lighting: PrincipledMaterial.NoLighting
        }
    }
}

The control panel enables or disables the ray, selects static and dynamic bodies, and changes the maximum query distance. Two controls leave bodies out of the result: one toggles parent exclusion, and one names the blue sphere in excludedBodies, so the ray passes through it and reports the floor instead. The sweep can also be paused to set the ray angle manually:

Frame {
    anchors.left: parent.left
    anchors.top: parent.top
    anchors.margins: 10

    background: Rectangle {
        color: "#c0c0c0"
        border.color: "#202020"
    }

    ColumnLayout {
        Label {
            text: qsTr("Raycaster")
            font.bold: true
        }
        Label {
            color: !ray.enabled ? "#525252" : ray.isColliding ? "#106b2d" : "#a2191f"
            text: !ray.enabled ? qsTr("Disabled") : ray.isColliding ? qsTr("Hit detected") : qsTr("No hit")
        }
        CheckBox {
            id: enabledCheckBox
            text: qsTr("Enabled")
            checked: true
        }
        CheckBox {
            id: staticCheckBox
            text: qsTr("Include static bodies")
            checked: true
        }
        CheckBox {
            id: dynamicCheckBox
            text: qsTr("Include dynamic bodies")
            checked: true
        }
        CheckBox {
            id: excludeParentCheckBox
            text: qsTr("Exclude parent body")
            checked: true
        }
        CheckBox {
            id: excludeSphereCheckBox
            text: qsTr("Exclude the blue sphere")
        }
        CheckBox {
            id: sweepCheckBox
            text: qsTr("Sweep ray")
            checked: true
        }
        Label {
            text: qsTr("Ray angle: %1°").arg(rayOrigin.eulerRotation.z.toFixed(0))
        }
        Slider {
            id: angleSlider
            Layout.preferredWidth: 220
            enabled: !sweepCheckBox.checked
            from: -25
            to: 25
            stepSize: 1
        }
        Label {
            text: qsTr("Maximum distance: %1").arg(distanceSlider.value.toFixed(0))
        }
        Slider {
            id: distanceSlider
            Layout.preferredWidth: 220
            from: 0
            to: 600
            value: 350
            stepSize: 10
        }
        Label {
            visible: ray.isColliding
            text: qsTr("Hit distance: %1").arg(ray.hit.distance.toFixed(1))
        }
    }
}

Files:

© 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.