In my QtQuick (QML) project I need to use 3D model of dice (a cubic one) that should be rotated during animation process. I use View3D, because rotating dice will be inside of 3D-insertion which is inside my 2D project. I have downloaded a free-to-use dice model (.fbx) and successfully imported it in my project in form of ".mesh" file via Balsam Asset Import Tool. By choosing created mesh for a source of model and also applying the texture of dice via PrincipledMaterial, I perfectly see my dice model inside View3D.
When I tried to animate the rotation process of model, I noticed, that dice rotates incorrectly. I decided to look its axis via QtQuick3D.Helpers' AxisHelper and saw that starting points of axes X and Y located just fine but the Z axis' starting point is shifted from the center of the model by about 10 units.
I tried to look up for useful properties of Model
QML type (and Node
because Model
inherits Node
type) that may allowed me to modify or specify the rotation axis of the object but I did not find anything. On the Stack Overflow there is one similar question but it does not helped me, because I should use View3D, not the whole Qt3D with Entity
. Moreover, I tried to put translate
property but it has only x and y fields and I did not seen any changes by modifying these.
I would like to know if there is a way to place rotation axis of 3D model inside the center of it. May be some Balsam Asset Import Tool's options can help me with that (I tried some options like dropNormals, removeComponentNormals, fbxPreservePivots but did not seen any changes)? Also I am not good at 3D Modelling, so could you please tell me if .mesh or .fbx files of 3D models store the information of axis rotation or something like that.
One group of axes is a 3D scene axes, and other group is dice model axes
import QtQuick
import QtQuick3D
import QtQuick3D.Helpers
Rectangle
{
id: root
width: parent.width/1.5
height: width
anchors.centerIn: parent
color: "lightgrey"
View3D
{
anchors.fill: parent
Node
{
PerspectiveCamera
{
id: _camera
z: 100
}
DirectionalLight
{
}
// Applying the texture
PrincipledMaterial
{
id: _priDiceMaterial
baseColorMap: Texture
{
source: "assets/assets/Dice_Diffuse.jpg.png"
}
}
// Model information
Model
{
id: _diceModel
source: "/assets/assets/dice_001.mesh"
materials: [_priDiceMaterial]
eulerRotation: Qt.vector3d(0, 0, 0)
position: Qt.vector3d(20, 20, 20)
AxisHelper {} // Visual axes of dice model
}
AxisHelper { id: _sceneAxis } // Visual axes of 3D scene
}
}
WasdController
{
controlledObject: _camera
}
}
[EDIT]
I reworked the answer by putting the Model
inside the Node
. You can change the axis of your Model
by setting x
, y
or z
properties. Then you apply rotation on the Node
:
Node
{
id: node
Model
{
id: _diceModel
source: "/assets/assets/dice_001.mesh"
materials: [_priDiceMaterial]
x: 100
y: 100
z: 100
}
eulerRotation: Qt.vector3d(0, 45, 0)
}
Because dice
is involved. I experimented with mixing #Cube
and #Cylinder
to create a dice effect. The approach uses the above strategy by offsetting the #Cylinder
in different places. A pain point with this approach is, on certain faces, the #Cylinder
needs to be rotated.
import QtQuick
import QtQuick.Controls
import QtQuick3D
Page {
background: Rectangle { color: "#848895" }
property color blk: Qt.rgba(0.2, 0.2, 0.2, 0.75)
property color wht: Qt.rgba(0.7, 0.7, 0.7, 0.75)
property color red: Qt.rgba(0.7, 0.2, 0.2, 0.75)
Node {
id: standAloneScene
DirectionalLight { ambientColor: Qt.rgba(1.0, 1.0, 1.0, 1.0) }
Node {
id: node
Model {
source: "#Cube"
materials: [
DefaultMaterial { diffuseColor: blk }
]
}
// 6
Dot { x: -25; y: 50; z: -25 }
Dot { x: 25; y: 50; z: -25 }
Dot { x: -25; y: 50 }
Dot { x: 25; y: 50 }
Dot { x: -25; y: 50; z: 25 }
Dot { x: 25; y: 50; z: 25 }
// 1
Dot { y: -50; c: red }
// 4
Dot { x: 50; y: -20; z: -25; r: "z"; c: red }
Dot { x: 50; y: 20; z: -25; r: "z"; c: red }
Dot { x: 50; y: -20; z: 25; r: "z"; c: red }
Dot { x: 50; y: 20; z: 25; r: "z"; c: red }
// 3
Dot { x: -50; y: -20; z: -25; r: "z" }
Dot { x: -50; r: "z" }
Dot { x: -50; y: 20; z: 25; r: "z" }
// 2
Dot { z: 50; x: 20; r: "x" }
Dot { z: 50; x: -20; r: "x" }
// 5
Dot { z: -50; x: -25; y: -25; r: "x" }
Dot { z: -50; x: 25; y: -25; r: "x" }
Dot { z: -50; r: "x" }
Dot { z: -50; x: -25; y: 25; r: "x" }
Dot { z: -50; x: 25; y: 25; r: "x" }
}
OrthographicCamera {
id: cameraOrthographicFront
lookAtNode: node
y: 800; z: 1000
}
}
View3D {
anchors.fill: parent
importScene: standAloneScene
camera: cameraOrthographicFront
}
NumberAnimation {
target: node
property: "eulerRotation.y"
loops: Animation.Infinite
running: true
from: 720; to: 0
duration: 10000
}
NumberAnimation {
target: node
property: "eulerRotation.x"
loops: Animation.Infinite
running: true
from: 360; to: 0
duration: 10000
}
}
// Dot.qml
import QtQuick
import QtQuick3D
Model {
property string r: ""
property color c: wht
source: "#Cylinder"
materials: [
DefaultMaterial { diffuseColor: c }
]
scale: Qt.vector3d(0.2, 0.05, 0.2)
eulerRotation.x: r === 'x' ? 90 : 0
eulerRotation.y: r === 'y' ? 90 : 0
eulerRotation.z: r === 'z' ? 90 : 0
}
You can Try it Online!