Qt勉強会の成果 Qt3Dを使ってみた


Qt3D StudioとQt3D

以前Qt3D Studioを使って3Dの表現を試したことはあったのですが、今日はQtCreatorでQt3Dを使ってみました。

Qt3D Studioはタイムラインを使って3Dモデルを動かすシーケンサーのような印象を持ちましたが、Qt3Dはもっとプラグラマがゴリゴリ実装する感じ。

サッと3Dを使った表現を作るにはQt3D Studioは向いてそうですが、1個のアプリとして色々やるにはQMLでQt3Dを使ったほうが良いのかなと今は思ってます。

実装したプロジェクトはこちら

できたもの

自分ではモデリングできないので、フリー素材を利用させていただきました。 雰囲気をだすために建物を置いて、道路を車が直進していくというものです。

ただ真っ直ぐ走るだけでは面白くないので、マウスクリックすると車がジャンプするアニメーションを追加してみました。

実装の中身

今回はC++は使わず全てQMLで書いてます。

車や建物の3Dモデル

やっている事はSceneLoaderのsourceにファイルを指定するだけで、あとはQtが勝手に読み込んでくれてます。便利!

車については、移動させたいのでTransformのtranslationの値を外から触れるようにプロパティにしてます。

rotationも指定してるのは、3Dモデルを普通に読みこむと横を向いちゃったので90度回転させてます。BlenderなどのモデリングツールでちゃんとQtと座標系をあわせてあげれば、これは必要ないとは思います。

余談ですが、普段Unreal Engine触っているのでX, Y, Zの座標系がいつもと違い戸惑いました。YとZがUnrealとQtでは逆でした。

 Entity {
        components: [
            SceneLoader {
                source : "/model3d/track.obj"
            },
            Transform {
                id: myCarTransform
                property real locationX: 0.0
                property real locationY: 0.0
                rotation: fromAxisAndAngle(Qt.vector3d(0, 1, 0), 90)
                translation : Qt.vector3d(locationX, locationY, 0)
            }

        ]
    }

道路

地面と道路と白線は板ポリに色付きのマテリアルを貼って表現してます。

CoboidMeshっていうのが、立方体を表現するものでxExtent, yExtent, zExtentに大きさを指定してます。

マテリアルはPhongMaterialを利用して、とりあえず色(ambient)だけ指定してます。やけにテカった表現になってますが、その他のプロパティを使うとまた違った表現も作れるのかなとは思いますが今日の時点では未確認です。

Entity {
        components: [
            CuboidMesh {
                xExtent: 2000
                yExtent: 0.1
                zExtent: 500
            },
            PhongMaterial {
                ambient:"dimgray"
            },
            Transform {
                translation: Qt.vector3d(0, -0.01, 0)
            }
        ]
    }

車の走る部分

NumberAnimation を使って、車のX座標を動かしてます。 -20mから1000mまで繰り返し設定です。 このfrom, toの値とdurationの関係で車速も狙った値にできます。

QQ2.NumberAnimation {
        id:moveAnimation
        target: myCarTransform
        property: "locationX"
        duration: 30000
        from: -20
        to: 1000

        loops: QQ2.Animation.Infinite
        running: true
    }

ジャンプ

マウスのクリックでジャンプする部分ですが、実はこのクリックしたらという部分が最初実現できず悩みました。

通常の2Dの場合はMouseAreaを使っていたのですが、Qt3DのEntity内では利用できず、今はObjectPickerを利用しています。

でもこのObjectPickerで何故マウスイベントがとれているのかが、まだちゃんと理解できてないので今後ちゃんとしらべます。

マウスイベントをとったあとは、アニメーションのスタートに繋げてます。 ジャンプの上に上がるアニメと下に下るアニメをSequentialAnimationで繋げて表現しています。

ObjectPicker{
          onPressed:{
             myCar.notifyClick()
          }
}

function notifyClick()
{
      jumpAnimation.start()
}

QQ2.SequentialAnimation {
        id:jumpAnimation
        QQ2.NumberAnimation {
            target: myCarTransform
            property: "locationY"
            duration: 500
            from: 0
            to: 3
            easing.type: Easing.InSine
        }

        QQ2.NumberAnimation {
            target: myCarTransform
            property: "locationY"
            duration: 500
            from: 3
            to: 0
            easing.type: Easing.OutSine
            onStopped: myCarTransform.locationY= 0
        }
    }

まとめ

Qt3Dを使って簡単な3Dモデルの操作を実現することができました。

今日はタイムアップでできませんでしたが、あとはこんな事もやってみたいと思ってます。


See also