- Qt 6.6
- Qt Quick 3D
- Qt Quick 3D Examples and Tutorials
- Qt Quick 3D - Particles 3D Testbed Example
- Qt Quick 3D | Commercial or GPLv3

# Qt Quick 3D - Particles 3D Testbed Example

     // Copyright (C) 2023 The Qt Company Ltd.
     // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

     import QtQuick
     import QtQuick3D
     import QtQuick3D.Particles3D
     import QtQuick3D.Helpers

     Item {
         anchors.fill: parent

         View3D {
             anchors.fill: parent

             environment: SceneEnvironment {
                 clearColor: "#101010"
                 backgroundMode: SceneEnvironment.Color
                 antialiasingMode: AppSettings.antialiasingMode
                 antialiasingQuality: AppSettings.antialiasingQuality
             }
             PerspectiveCamera {
                 id: camera
                 position: Qt.vector3d(0, 100, 600)
                 clipFar: 2000
             }
             WasdController {
                 controlledObject: camera
             }
             PointLight {
                 id: pointLight
                 position.y: 100
                 brightness: 100
                 quadraticFade: 50
             }

             Model {
                 source: "#Cube"
                 position.y: -100
                 scale: Qt.vector3d(20, 1, 20)
                 materials: PrincipledMaterial {
                     baseColor: Qt.rgba(1.0, 0.8, 0.8, 1.0)
                 }
             }
             Node {
                 id: spheres
                 property real angle: 0.0
                 NumberAnimation {
                     target: spheres
                     property: "angle"
                     from: 0.0
                     to: 360.0
                     duration: 5000
                     loops: Animation.Infinite
                     running: true
                 }
                 eulerRotation.y: angle
                 Model {
                     id: sphere1
                     source: "#Sphere"
                     position.y: -50
                     position.x: -100
                     scale: Qt.vector3d(1.8, 1.8, 1.8)
                     materials: PrincipledMaterial {
                         baseColor: Qt.rgba(0.8, 1.0, 0.8, 1.0)
                     }
                 }
                 Model {
                     id: sphere2
                     source: "#Sphere"
                     position.y: 0
                     position.x: 300
                     scale: Qt.vector3d(0.9, 0.9, 0.9)
                     materials: PrincipledMaterial {
                         baseColor: Qt.rgba(0.8, 1.0, 0.8, 1.0)
                     }
                 }
             }

             ParticleSystem3D {
                 id: psystem

                 property real particleScaleFactor : 1.0 + Math.abs(Math.cos(2.0 * Math.PI * scaleTemp))
                 property real scaleTemp: 0.0
                 NumberAnimation {
                     target: psystem
                     property: "scaleTemp"
                     from: 0.0
                     to: 1.0
                     duration: 400
                     loops: Animation.Infinite
                     running: true
                 }

                 LineParticle3D {
                     id: particle
                     sprite: Texture {
                         source: "images/qt_logo.png"
                     }
                     maxAmount: 200 + emitter.emitRate * emitter.lifeSpan / 1000
                     color: Qt.rgba(1.0, 1.0, 1.0, sliderOpacity.sliderValue * 0.01)
                     colorVariation: Qt.vector4d(0.6, 0.6, 0.6, 0.0)
                     fadeInDuration: 500
                     fadeOutDuration: 500
                     segmentCount: sliderSegmentCount.sliderValue
                     alphaFade: sliderOpacityFade.sliderValue * 0.01
                     scaleMultiplier: sliderSizeFactor.sliderValue
                     texcoordMultiplier: sliderTexcoordFactor.sliderValue
                     particleScale: sliderSize.sliderValue
                     eolFadeOutDuration: 500
                     texcoordMode: LineParticle3D.Relative
                     billboard: billboardCheckBox.checked
                     length: lengthCheckBox.checked ? lengthSlider.sliderValue : -1.0
                     lengthVariation: lengthVariationSlider.sliderValue
                     lengthDeltaMin: lengthDeltaSlider.sliderValue
                     sortMode: LineParticle3D.SortDistance
                 }

                 ParticleEmitter3D {
                     id: emitter
                     particle: particle
                     position: Qt.vector3d(-550, 0, 0)
                     scale: Qt.vector3d(2.0, 0.5, 2.0)
                     shape: ParticleShape3D {
                         type: ParticleShape3D.Sphere
                     }
                     velocity: VectorDirection3D {
                         direction: Qt.vector3d(sliderVelocityY.sliderValue * 40, 0, 0)
                         directionVariation: Qt.vector3d(sliderVelocityY.sliderValue * 20, 15, 0)
                     }
                     emitRate: sliderEmitRate.sliderValue
                     lifeSpan: 500 * 1000 / (sliderVelocityY.sliderValue * 40)
                 }

                 ParticleEmitter3D {
                     id: emitter2
                     particle: particle
                     position: Qt.vector3d(-550, 0, 60)
                     scale: Qt.vector3d(2.0, 0.5, 2.0)
                     shape: ParticleShape3D {
                         type: ParticleShape3D.Sphere
                     }
                     velocity: VectorDirection3D {
                         direction: Qt.vector3d(sliderVelocityY.sliderValue * 40, 0, 0)
                         directionVariation: Qt.vector3d(sliderVelocityY.sliderValue * 20, 15, 0)
                     }
                     emitRate: sliderEmitRate.sliderValue
                     lifeSpan: 500 * 1000 / (sliderVelocityY.sliderValue * 40)
                 }
                 ParticleEmitter3D {
                     id: emitter3
                     particle: particle
                     position: Qt.vector3d(-550, 0, 120)
                     scale: Qt.vector3d(2.0, 0.5, 2.0)
                     shape: ParticleShape3D {
                         type: ParticleShape3D.Sphere
                     }
                     velocity: VectorDirection3D {
                         direction: Qt.vector3d(sliderVelocityY.sliderValue * 40, 0, 0)
                         directionVariation: Qt.vector3d(sliderVelocityY.sliderValue * 20, 15, 0)
                     }
                     emitRate: sliderEmitRate.sliderValue
                     lifeSpan: 500 * 1000 / (sliderVelocityY.sliderValue * 40)
                 }

                 Repeller3D {
                     particles: [particle]
                     position: sphere1.scenePosition
                     outerRadius: sliderRadius.sliderValue
                     strength: sliderRepelStrength.sliderValue
                 }
                 Repeller3D {
                     particles: [particle]
                     position: sphere2.scenePosition
                     outerRadius: sliderRadius.sliderValue * 0.5
                     strength: sliderRepelStrength.sliderValue
                 }
             }
         }

         SettingsView {
             CustomLabel {
                 text: "Billboard particle"
             }
             CustomCheckBox {
                 id: billboardCheckBox
                 checked: true
             }
             CustomLabel {
                 text: "Line Segment Count"
             }
             CustomSlider {
                 id: sliderSegmentCount
                 sliderValue: 10
                 fromValue: 1
                 toValue: 250
                 sliderStepSize: 1
             }
             CustomLabel {
                 text: "Line minimum length"
             }
             CustomSlider {
                 id: lengthDeltaSlider
                 sliderValue: 10.0
                 fromValue: 0.0
                 toValue: 50.0
             }
             CustomLabel {
                 text: "Line Opacity Fade"
             }
             CustomSlider {
                 id: sliderOpacityFade
                 sliderValue: 0
                 fromValue: 0
                 toValue: 100
                 sliderStepSize: 1
             }
             CustomLabel {
                 text: "Size"
             }
             CustomSlider {
                 id: sliderSize
                 sliderValue: 1
                 fromValue: 0.1
                 toValue: 20.0
             }
             CustomLabel {
                 text: "Line Size Modifier"
             }
             CustomSlider {
                 id: sliderSizeFactor
                 sliderValue: 1
                 fromValue: 0.1
                 toValue: 2.0
             }
             CustomLabel {
                 text: "Line Texcoord Modifier"
             }
             CustomSlider {
                 id: sliderTexcoordFactor
                 sliderValue: 1
                 fromValue: 0.01
                 toValue: 20.0
             }
             CustomLabel {
                 text: "Emit Rate"
             }
             CustomSlider {
                 id: sliderEmitRate
                 sliderValue: 50
                 fromValue: 1
                 toValue: 200
             }
             CustomLabel {
                 text: "Start Velocity"
             }
             CustomSlider {
                 id: sliderVelocityY
                 sliderValue: 10
                 fromValue: 0.1
                 toValue: 50
             }
             CustomLabel {
                 text: "Opacity"
             }
             CustomSlider {
                 id: sliderOpacity
                 sliderValue: 30.0
                 fromValue: 0.0
                 toValue: 100.0
             }
             CustomLabel {
                 text: "Repel Radius"
             }
             CustomSlider {
                 id: sliderRadius
                 sliderValue: 1000
                 fromValue: 1
                 toValue: 2000
             }
             CustomLabel {
                 text: "Repel Strength"
             }
             CustomSlider {
                 id: sliderRepelStrength
                 sliderValue: 50.0
                 fromValue: 0.0
                 toValue: 400.0
             }
             CustomLabel {
                 text: "Fixed Length"
             }
             CustomCheckBox {
                 id: lengthCheckBox
                 checked: false
             }
             CustomLabel {
                 text: "Line Length"
             }
             CustomSlider {
                 id: lengthSlider
                 sliderValue: 50.0
                 fromValue: 10.0
                 toValue: 200.0
             }
             CustomLabel {
                 text: "Line Length Variation"
             }
             CustomSlider {
                 id: lengthVariationSlider
                 sliderValue: 0.0
                 fromValue: 0.0
                 toValue: 100.0
             }
         }

         LoggingView {
             anchors.bottom: parent.bottom
             particleSystems: [psystem]
         }
     }