Qt3D Studio and Qt3D
I had previously tried expressing 3D using Qt3D Studio, but today I tried using Qt3D with Qt Creator.
Qt3D Studio gave me the impression of a sequencer that moves 3D models using a timeline, whereas Qt3D feels more like something programmers implement hardcore.
Qt3D Studio seems suitable for quickly creating 3D expressions, but for doing various things within a single application, I currently think using Qt3D with QML might be better.
The implemented project is here:
What I Made
Since I can’t do modeling myself, I used free assets. To create an atmosphere, I placed buildings, and it features a car driving straight down a road.
Just driving straight isn’t interesting, so I added an animation where the car jumps when the mouse is clicked.
今日のQt勉強会で作ったもの。
— ayuma (@ayuma_x) August 25, 2018
Qt3Dとフリー素材でサンプルを作ってみた。
少し味付けでマウスクリックでジャンプする仕組みを足してみた。#qtjp pic.twitter.com/onGR5UpqQ6
Implementation Details
This time, I didn’t use C++ and wrote everything in QML.
3D Models of Cars and Buildings
All I did was specify the file in the SceneLoader’s source, and Qt automatically loaded it. Convenient!
For the car, since I want to move it, I made the Transform’s translation value a property so it can be accessed from outside.
I also specified rotation because the 3D model faced sideways when loaded normally, so I rotated it 90 degrees. If the coordinate system is properly aligned with Qt in a modeling tool like Blender, this shouldn’t be necessary.
As an aside, since I usually use Unreal Engine, I was confused by the different X, Y, Z coordinate system. Y and Z are reversed between Unreal and Qt.
- Part that loads the car's 3D model
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)
}
]
}
Road
The ground, road, and white lines are represented by applying colored materials to flat polygons.
CuboidMesh represents a cuboid, and its size is specified using xExtent, yExtent, and zExtent.
For the material, I used PhongMaterial and just specified the color (ambient) for now. It looks quite shiny, but I think using other properties might allow for different expressions, though I haven’t confirmed this today.
- Ground
Entity {
components: [
CuboidMesh {
xExtent: 2000
yExtent: 0.1
zExtent: 500
},
PhongMaterial {
ambient:"dimgray"
},
Transform {
translation: Qt.vector3d(0, -0.01, 0)
}
]
}
Car Driving Part
I’m using NumberAnimation to move the car’s X coordinate. It’s set to repeat from -20m to 1000m. The relationship between these from, to values and the duration allows setting the desired car speed.
QQ2.NumberAnimation {
id:moveAnimation
target: myCarTransform
property: "locationX"
duration: 30000
from: -20
to: 1000
loops: QQ2.Animation.Infinite
running: true
}
Jump
Regarding the part where the car jumps on mouse click, I actually struggled to implement the “on click” part initially.
In normal 2D cases, I used MouseArea, but it couldn’t be used within a Qt3D Entity, so I’m using ObjectPicker now.
However, I still don’t fully understand why mouse events can be captured with this ObjectPicker, so I’ll investigate it properly in the future.
After capturing the mouse event, I connect it to start the animation. The animation of jumping up and coming down is expressed by connecting them using 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
}
}
Summary
I was able to achieve simple 3D model manipulation using Qt3D.
I ran out of time today, but I’d also like to try these things:
- Change material parameters to vary the texture
- Since CuboidMesh can only create straight roads, investigate how to create curved road meshes (Maybe touch OpenGL?)
- Adjust lighting to change shadows, etc.