Qt3D StudioとQt3D
以前Qt3D Studioを使って3Dの表現を試したことはあったのですが、今日はQtCreatorでQt3Dを使ってみました。
Qt3D Studioはタイムラインを使って3Dモデルを動かすシーケンサーのような印象を持ちましたが、Qt3Dはもっとプラグラマがゴリゴリ実装する感じ。
サッと3Dを使った表現を作るにはQt3D Studioは向いてそうですが、1個のアプリとして色々やるにはQMLでQt3Dを使ったほうが良いのかなと今は思ってます。
実装したプロジェクトはこちら
できたもの
自分ではモデリングできないので、フリー素材を利用させていただきました。 雰囲気をだすために建物を置いて、道路を車が直進していくというものです。
ただ真っ直ぐ走るだけでは面白くないので、マウスクリックすると車がジャンプするアニメーションを追加してみました。
今日のQt勉強会で作ったもの。
— ayuma (@ayuma_x) August 25, 2018
Qt3Dとフリー素材でサンプルを作ってみた。
少し味付けでマウスクリックでジャンプする仕組みを足してみた。#qtjp pic.twitter.com/onGR5UpqQ6
実装の中身
今回は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モデルの操作を実現することができました。
今日はタイムアップでできませんでしたが、あとはこんな事もやってみたいと思ってます。