가상 비서

Qt Quick 애플리케이션은 가상 비서의 3D 모델에 QML과 타임라인을 사용하여 만든 동적 애니메이션을 표시하는 애플리케이션입니다.

가상 비서 예제에서는 타임라인 애니메이션을 통해 가상 비서의 3D 모델에 생명을 불어넣어 사용자 참여와 상호 작용을 향상시키는 방법을 보여 줍니다.

3D 모델 가져오기

Qt Design Studio 에서 모델을 로드하려면 .gltf 파일을 프로젝트로 가져오기만 하면 됩니다. Qt Design Studio 그러면 개체를 나타내는 QML 파일이 자동으로 생성됩니다. 또한 필요한 에셋도 생성합니다. Qt Design Studio 이 없으면 Balsam 툴을 수동으로 실행해야 합니다. 이 예제에서는 생성된 QML 파일을 수정하여 상태, 애니메이션 및 가상 어시스턴트의 특정 부분을 선택할 수 있는 추가 보이지 않는 모델을 도입했습니다.

씬 환경 준비

이 씬에서는 HDR 이미지를 사용하여 스카이박스를 만들고 자연스러운 조명을 제공합니다.

        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
        }

카메라 옵션

카메라 속성은 설정 패널에서 변경할 수 있습니다. 슬라이더를 사용하여 시야각(FOV) 및 스카이박스 회전을 조작할 수 있습니다. 확인란을 선택하면 OrbitCameraController 카메라 위치 및 회전을 대화형으로 변경할 수도 있습니다.

애니메이션

애니메이션은 여러 개의 Timeline 타임라인과 Keyframe 키프레임을 사용하여 만들어집니다. 각 Timeline 은 가상 도우미의 다른 상태와 연결됩니다. 상태가 변경되면 연결된 애니메이션이 즉시 재생되기 시작합니다. 각 애니메이션이 끝나면 개체는 기본 상태로 돌아가서 모델의 위치 및 회전과 같은 기본값을 nodes 으로 복원합니다. 애니메이션은 스켈레톤의 노드 속성 값을 변경하고 다양한 morph targets 의 가중치를 수정하여 얼굴 요소(눈, 입)에 애니메이션을 적용합니다.

애니메이션 패널의 버튼을 사용하여 애니메이션을 실행합니다. 손, 하체, 얼굴과 같은 특정 모델 요소를 클릭하여 모델의 해당 부분과 관련된 애니메이션을 활성화할 수도 있습니다.

스켈레톤 애니메이션
  • 입장 애니메이션
  • 종료 애니메이션
  • 장면 애니메이션 탐색
  • 백플립 애니메이션
  • 하체 튕기기 애니메이션
  • 오른손 및 왼손 흔들기 애니메이션
모프 대상 애니메이션
  • 얼굴 애니메이션(행복 및 슬픔)

모델의 왼손을 흔드는 애니메이션의 샘플 구현입니다:

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
        }
    }
}

예제 프로젝트 @ 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.