How can I shift the Rotation Axis of imported model? (QML, QtQuick3D, View3D)

288 Views Asked by At

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
    }
}
1

There are 1 best solutions below

4
Stephen Quan On BEST ANSWER

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