0

Introduction

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.

The problem

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.

What did I try

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.

What I want to know

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

The code I have (View3DArea.qml - custom type)

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
    }
}
fever
  • 18
  • 4

1 Answers1

1

[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!

Stephen Quan
  • 21,481
  • 4
  • 88
  • 75
  • Thank you for the answer, sir. I have understood my mistake on that one, but it seems that position does not affect the axes of Model (I have tested this right now). I think it is not a translation like translate property from the Transform QML type. I do not know how exactly axes of models are placed relative to Model when it is created. For example, when I use built-in model of a cube (source: "#Cube"), its axes placed in the center of model. The problem still remains. – fever Feb 06 '23 at 05:57
  • Can you share the model? gist or github? – Stephen Quan Feb 06 '23 at 07:55
  • Here is my [GitHub repository](https://github.com/AlekseyLapunov/QML-Quick3D-Custom-Models). In the [assets](https://github.com/AlekseyLapunov/QML-Quick3D-Custom-Models/tree/master/assets) directory you can find .fbx file of dice model and .mesh file that was created via Balsam tool. – fever Feb 06 '23 at 08:57
  • 1
    Thanks @fever. I had problems loading your model, but, anyhow, I updated my answer. I hope it helps. – Stephen Quan Feb 07 '23 at 11:46