- Qt 6.5
- 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) 2021 The Qt Company Ltd.
     // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

     import QtQuick
     import QtQuick3D
     import QtQuick3D.Particles3D

     Item {
         id: mainWindow

         readonly property real tentacleEmitRate: 120
         readonly property real cameraDistance: sliderCameraDistance.sliderValue
         property real cameraDistanceSmoothed: cameraDistance
         property real tentacleWideness: 0

         anchors.fill: parent

         // Animate tentacle movement
         SequentialAnimation on tentacleWideness {
             loops: Animation.Infinite
             NumberAnimation {
                 to: 30
                 duration: 6000
                 easing.type: Easing.InOutQuad
             }
             NumberAnimation {
                 to: -30
                 duration: 6000
                 easing.type: Easing.InOutQuad
             }
         }

         Behavior on cameraDistanceSmoothed {
             SmoothedAnimation {
                 velocity: 100
                 duration: 1000
             }
         }

         // Background ocean gradient
         Rectangle {
             anchors.fill: parent
             gradient: Gradient {
                 GradientStop {
                     color: "#005060"
                     position: 0.0
                 }
                 GradientStop {
                     color: "#000000"
                     position: 1.0
                 }
             }
         }

         View3D {
             anchors.fill: parent

             environment: SceneEnvironment {
                 backgroundMode: SceneEnvironment.Transparent
                 antialiasingMode: settings.antialiasingMode
                 antialiasingQuality: settings.antialiasingQuality
             }

             // Camera rotating the spider
             Node {
                 PerspectiveCamera {
                     id: camera
                     position: Qt.vector3d(0, 0, cameraDistanceSmoothed)
                 }

                 NumberAnimation on eulerRotation.y {
                     loops: Animation.Infinite
                     from: 0
                     to: 360
                     duration: 20000
                 }

                 SequentialAnimation on eulerRotation.x {
                     loops: Animation.Infinite
                     NumberAnimation {
                         to: -50
                         duration: 6000
                         easing.type: Easing.InOutQuad
                     }
                     NumberAnimation {
                         to: 0
                         duration: 6000
                         easing.type: Easing.InOutQuad
                     }
                 }
             }

             PointLight {
                 position: Qt.vector3d(0, 400, 0)
                 brightness: 200
             }

             // Body of the spider
             Model {
                 id: spiderBody
                 source: "#Sphere"
                 scale: Qt.vector3d(1.0, 0.6, 1.2)

                 PrincipledMaterial {
                     id: spiderMaterial
                     baseColor: tentacleParticle.color
                     metalness: 1.0
                     roughness: 0.6
                     normalMap: Texture {
                         source: "images/leather_n.png"
                     }
                     normalStrength: 0.8
                 }
                 materials: spiderMaterial
                 Model {
                     source: "#Cone"
                     scale: Qt.vector3d(0.4, 0.5, 0.5)
                     position: Qt.vector3d(20, 10, -20)
                     eulerRotation: Qt.vector3d(-40, -80, 0)
                     materials: spiderMaterial
                 }
                 Model {
                     source: "#Cone"
                     scale: Qt.vector3d(0.4, 0.5, 0.5)
                     position: Qt.vector3d(-20, 10, -20)
                     eulerRotation: Qt.vector3d(-40, 80, 0)
                     materials: spiderMaterial
                 }
                 SequentialAnimation on y {
                     loops: Animation.Infinite
                     NumberAnimation {
                         to: 100
                         duration: 2500
                         easing.type: Easing.InOutQuad
                     }
                     NumberAnimation {
                         to: 0
                         duration: 2500
                         easing.type: Easing.InOutQuad
                     }
                 }

                 // System for tentacles particles
                 ParticleSystem3D {
                     id: psystemTentacles
                     SpriteParticle3D {
                         id: tentacleParticle
                         sprite: Texture {
                             source: "images/dot.png"
                         }
                         maxAmount: 8 * tentacleEmitRate * 1.5
                         color: "#000000"
                         colorVariation: Qt.vector4d(0.0, 0.0, 0.0, 0.2)
                         fadeInEffect: SpriteParticle3D.FadeNone
                         fadeOutDuration: 800
                         billboard: true
                         SequentialAnimation on color {
                             loops: Animation.Infinite
                             ColorAnimation {
                                 to: "#202000"
                                 duration: 2000
                             }
                             ColorAnimation {
                                 to: "#200000"
                                 duration: 2000
                             }
                             ColorAnimation {
                                 to: "#000020"
                                 duration: 2000
                             }
                             ColorAnimation {
                                 to: "#002000"
                                 duration: 2000
                             }
                         }
                         blendMode: SpriteParticle3D.Screen
                     }

                     // Emitters for all 8 tentacles
                     component TentacleEmitter: Node {
                         id: tentacleNode
                         property real movementAmount: 1.0
                         ParticleEmitter3D {
                             z: 55
                             eulerRotation.x: 80 + mainWindow.tentacleWideness * tentacleNode.movementAmount
                             system: psystemTentacles
                             particle: tentacleParticle
                             velocity: VectorDirection3D {
                                 direction: Qt.vector3d(0, 300, 0)
                             }
                             particleScale: 6.0
                             particleEndScale: 0.5
                             emitRate: tentacleEmitRate
                             lifeSpan: 1500
                         }
                     }
                     TentacleEmitter {
                         eulerRotation.y: 0.5 * 45
                         movementAmount: 1.8
                     }
                     TentacleEmitter {
                         eulerRotation.y: 1.5 * 45
                         movementAmount: 1.3
                     }
                     TentacleEmitter {
                         eulerRotation.y: 2.5 * 45
                         movementAmount: 1.5
                     }
                     TentacleEmitter {
                         eulerRotation.y: 3.5 * 45
                         movementAmount: 2.2
                     }
                     TentacleEmitter {
                         eulerRotation.y: 4.5 * 45
                         movementAmount: 1.6
                     }
                     TentacleEmitter {
                         eulerRotation.y: 5.5 * 45
                         movementAmount: 1.1
                     }
                     TentacleEmitter {
                         eulerRotation.y: 6.5 * 45
                         movementAmount: 1.5
                     }
                     TentacleEmitter {
                         eulerRotation.y: 7.5 * 45
                         movementAmount: 2.1
                     }

                     Gravity3D {
                         direction: Qt.vector3d(0, 1, 0)
                         magnitude: -300
                     }

                     Wander3D {
                         globalAmount: Qt.vector3d(15, 15, 15)
                         globalPace: Qt.vector3d(1.0, 1.0, 1.0)
                         fadeInDuration: 1000
                         Vector3dAnimation on globalPaceStart {
                             loops: Animation.Infinite
                             duration: 8000
                             from: Qt.vector3d(0, 0, 0)
                             to: Qt.vector3d(5 * Math.PI * 2, 3 * Math.PI * 2, Math.PI * 2)
                         }
                     }
                 }

                 // Emitters for dust/smoke particles
                 ParticleEmitter3D {
                     id: smokeEmitter
                     system: psystemDust
                     particle: smokeParticle
                     particleScale: 10
                     particleScaleVariation: 5
                     particleEndScale: 60
                     particleEndScaleVariation: 30
                     particleRotationVariation: Qt.vector3d(0, 0, 180)
                     particleRotationVelocityVariation: Qt.vector3d(0, 0, 40)
                     emitRate: sliderDustEmitRate.sliderValue
                     lifeSpan: 3000
                     lifeSpanVariation: 1000
                     velocity: VectorDirection3D {
                         direction: Qt.vector3d(0, 0, 200)
                         directionVariation: Qt.vector3d(50, 50, 50)
                     }
                 }
                 ParticleEmitter3D {
                     id: dustEmitter
                     system: psystemDust
                     particle: dustParticle
                     emitRate: sliderDustEmitRate.sliderValue * 0.5
                     lifeSpan: 3000
                     lifeSpanVariation: 1000
                     particleScale: 10.0
                     particleScaleVariation: 5.0
                     particleEndScale: 30.0
                     particleEndScaleVariation: 10.0
                     particleRotationVariation: Qt.vector3d(20, 20, 180)
                     particleRotationVelocityVariation: Qt.vector3d(5, 5, 50)
                     velocity: VectorDirection3D {
                         direction: Qt.vector3d(0, 0, 100)
                         directionVariation: Qt.vector3d(20, 20, 20)
                     }
                 }

             }

             // System for dust/smoke particles
             ParticleSystem3D {
                 id: psystemDust
                 SpriteParticle3D {
                     id: smokeParticle
                     sprite: Texture {
                         source: "images/smoke_sprite.png"
                     }
                     maxAmount: 200
                     spriteSequence: SpriteSequence3D {
                         frameCount: 15
                         interpolate: true
                     }
                     billboard: true
                     color: tentacleParticle.color
                     fadeInEffect: SpriteParticle3D.FadeNone
                     fadeOutEffect: Particle3D.FadeOpacity
                     fadeOutDuration: 1500
                     blendMode: SpriteParticle3D.Screen
                 }

                 SpriteParticle3D {
                     id: dustParticle
                     sprite: Texture {
                         source: "images/dust.png"
                     }
                     maxAmount: 100
                     color: "#ffffff"
                     colorVariation: Qt.vector4d(0.4, 0.4, 0.4, 0.4)
                     billboard: true
                     fadeInDuration: 200
                     fadeOutDuration: 1500
                     blendMode: SpriteParticle3D.Screen
                 }
             }

             // System for bubbles particles
             ParticleSystem3D {
                 id: psystemBubbles
                 position: Qt.vector3d(0, 100, -200)
                 SpriteParticle3D {
                     id: bubbleParticle
                     sprite: Texture {
                         source: "images/sphere.png"
                     }
                     maxAmount: 300
                     color: "#80ffffff"
                     colorVariation: Qt.vector4d(0.0, 0.0, 0.0, 0.2)
                     fadeInDuration: 1000
                     fadeOutDuration: 1000
                     blendMode: SpriteParticle3D.Screen
                     billboard: true
                 }

                 ParticleEmitter3D {
                     particle: bubbleParticle
                     scale: Qt.vector3d(12, 12, 12)
                     particleScale: 2.0
                     particleScaleVariation: 1.0
                     particleEndScale: 1.0
                     particleEndScaleVariation: 0.5
                     emitRate: 100
                     lifeSpan: 3000
                     shape: ParticleShape3D {
                         type: ParticleShape3D.Sphere
                     }
                     velocity: VectorDirection3D {
                         direction: Qt.vector3d(0, 0, 200)
                         directionVariation: Qt.vector3d(20, 20, 100)
                     }
                 }
             }
         }

         SettingsView {
             CustomLabel {
                 text: "Camera Distance"
             }
             CustomSlider {
                 id: sliderCameraDistance
                 sliderValue: 400
                 fromValue: 200
                 toValue: 800
             }
             CustomLabel {
                 text: "Mystical Dust"
             }
             CustomSlider {
                 id: sliderDustEmitRate
                 sliderValue: 20
                 fromValue: 0
                 toValue: 50
             }
         }

         LoggingView {
             anchors.bottom: parent.bottom
             particleSystems: [psystemTentacles, psystemBubbles, psystemDust]
         }
     }