Virtueller Assistent

Qt Quick Anwendung, die ein 3D-Modell eines virtuellen Assistenten mit dynamischen Animationen präsentiert, die mit QML und Zeitleisten erstellt wurden.

Das Beispiel für einen virtuellen Assistenten zeigt, wie ein 3D-Modell eines virtuellen Assistenten durch Zeitleistenanimationen zum Leben erweckt werden kann, um die Beteiligung und Interaktion der Benutzer zu erhöhen.

3D-Modell importieren

Um das Modell in Qt Design Studio zu laden, genügt es, die .gltf-Datei in das Projekt zu importieren. Qt Design Studio erstellt dann automatisch eine QML-Datei, die das Objekt darstellt. Es generiert auch die notwendigen Assets. Ohne Qt Design Studio müssen Sie das Balsam-Tool manuell ausführen. In diesem Beispiel wurde die generierte QML-Datei geändert, um die Zustände, Animationen und zusätzlichen unsichtbaren Modelle einzuführen, die die Auswahl bestimmter Teile des virtuellen Assistenten ermöglichen.

Vorbereiten der Szenenumgebung

Die Szene verwendet HDR-Bilder, um eine Skybox zu erstellen und für eine natürliche Beleuchtung zu sorgen.

        environment: ExtendedSceneEnvironment {
            backgroundMode: SceneEnvironment.SkyBox
            lightProbe: Texture { source: Constants.sceneName }
            antialiasingMode: SceneEnvironment.MSAA
            antialiasingQuality: SceneEnvironment.VeryHigh
            fxaaEnabled: true
            probeExposure: 0.6
            probeOrientation: Qt.vector3d(0, settingsPanel.skyboxRotation, 0)
            specularAAEnabled: true
            tonemapMode: SceneEnvironment.TonemapModeLinear
            vignetteEnabled: true
            vignetteRadius: 0.15
        }

Kamera-Optionen

Die Kameraeigenschaften können über das Einstellungsfenster geändert werden. Sie können das Sichtfeld (FOV) und die Drehung des Himmelskastens mit Schiebereglern beeinflussen. Das Kontrollkästchen aktiviert eine OrbitCameraController, mit der Sie auch die Kameraposition und -drehung interaktiv ändern können.

Animationen

Die Animationen werden mit mehreren Timeline Zeitleisten und Keyframe Keyframes erstellt. Jede Timeline ist mit einem anderen Zustand des Virtuellen Assistenten verbunden. Wenn sich der Zustand ändert, werden die verbundenen Animationen sofort abgespielt. Am Ende jeder Animation kehrt das Objekt in den Standardzustand zurück und stellt die Standardwerte wieder her, z. B. Position und Drehung des Modells nodes. Die Animationen ändern die Eigenschaftswerte der Knoten in unserem Skelett und modifizieren das Gewicht der verschiedenen morph targets, um die Gesichtselemente (Augen, Mund) zu animieren.

Verwenden Sie die Schaltflächen im Animationsfenster, um die Animationen auszuführen. Sie können auch auf bestimmte Modellelemente wie Hände, Unterkörper und Gesicht klicken, um die Animation für diesen Teil des Modells zu aktivieren.

Skelett-Animationen
  • Eingangsanimation
  • Ausstiegs-Animation
  • Animation zum Erkunden der Szene
  • Rückwärtssalto-Animation
  • Animation zum Hüpfen des Unterkörpers
  • Animation zum Winken mit der rechten und linken Hand
Morph-Ziel-Animationen
  • Gesichtsanimationen (glücklich und traurig)

Beispielimplementierung der Winkanimation für die linke Hand des Modells:

Timeline {
    id: leftHandWavingTimeline
    animations: [
        TimelineAnimation {
            id: leftHandWavingAnimation
            onFinished: node.restoreDefaults()
            running: false
            loops: 1
            duration: 2000
            to: 2000
            from: 0
        }
    ]
    startFrame: 0
    endFrame: 2000
    enabled: false

    KeyframeGroup {
        target: hand_l
        property: "x"
        Keyframe {
            value: 2.89
            frame: 400
        }

        Keyframe {
            value: 2.89
            frame: 1600
        }

        Keyframe {
            value: 1.89
            frame: 2000
        }
    }

    KeyframeGroup {
        target: hand_l
        property: "y"
        Keyframe {
            value: 1
            frame: 400
        }

        Keyframe {
            value: 1
            frame: 1600
        }

        Keyframe {
            value: 0.5
            frame: 2000
        }
    }

    KeyframeGroup {
        target: hand_l
        property: "z"
        Keyframe {
            value: 1
            frame: 400
        }

        Keyframe {
            value: 1
            frame: 1600
        }

        Keyframe {
            value: -0.1
            frame: 2000
        }
    }

    KeyframeGroup {
        target: hand_l
        property: "eulerRotation.x"
        Keyframe {
            value: -15
            frame: 400
        }

        Keyframe {
            value: -5
            frame: 700
        }

        Keyframe {
            value: -15
            frame: 1000
        }

        Keyframe {
            value: -5
            frame: 1300
        }

        Keyframe {
            value: -15
            frame: 1600
        }

        Keyframe {
            value: -0.18
            frame: 2000
        }
    }

    KeyframeGroup {
        target: hand_l
        property: "eulerRotation.y"
        Keyframe {
            value: -15
            frame: 400
        }

        Keyframe {
            value: -30
            frame: 1600
        }

        Keyframe {
            value: -145
            frame: 2000
        }

        Keyframe {
            value: -40
            frame: 700
        }
    }

    KeyframeGroup {
        target: hand_l
        property: "eulerRotation.z"
        Keyframe {
            value: -88
            frame: 400
        }

        Keyframe {
            value: -30
            frame: 700
        }

        Keyframe {
            value: -86.05
            frame: 1000
        }

        Keyframe {
            value: -30
            frame: 1300
        }

        Keyframe {
            value: -86.05
            frame: 1600
        }

        Keyframe {
            value: -178.92
            frame: 2000
        }
    }

    KeyframeGroup {
        target: morphTarget38
        property: "weight"
        Keyframe {
            value: 1
            frame: 0
        }

        Keyframe {
            value: 0.25
            frame: 400
        }

        Keyframe {
            value: 0.25
            frame: 1600
        }

        Keyframe {
            value: 1
            frame: 2000
        }
    }

    KeyframeGroup {
        target: morphTarget42
        property: "weight"
        Keyframe {
            value: 0
            frame: 2000
        }

        Keyframe {
            value: 0.75
            frame: 1600
        }

        Keyframe {
            value: 0.75
            frame: 400
        }

        Keyframe {
            value: 0
            frame: 0
        }
    }

    KeyframeGroup {
        target: morphTarget27
        property: "weight"
        Keyframe {
            value: 0
            frame: 0
        }

        Keyframe {
            value: 1
            frame: 400
        }

        Keyframe {
            value: 1
            frame: 1600
        }

        Keyframe {
            value: 0
            frame: 2000
        }
    }

    KeyframeGroup {
        target: morphTarget28
        property: "weight"
        Keyframe {
            value: 1
            frame: 2000
        }

        Keyframe {
            value: 0
            frame: 1600
        }

        Keyframe {
            value: 0
            frame: 400
        }

        Keyframe {
            value: 1
            frame: 0
        }
    }
}

Beispielprojekt @ code.qt.io

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