QML 3D 加载

本文介绍如何解决3dsMax2018导出OBJ文件在Qt5中出现的错误,并分享了一种机械臂联动算法实现,包括旋转矩阵和四元数的使用。通过具体的函数代码,展示了各关节的旋转和平移操作。

换成Qt5.11.2以上或者使用3ds max2014就可以了,还有一种可能是模型太大,导出的时候需要按比例缩小

机械臂联动的算法采用的是旋转矩阵和四元数.

   function clawOpenAndClose(){
        var a = clawOpenClose*Math.PI/180.0
        var m = Qt.matrix4x4(Math.cos(a),   -Math.sin(a),   0,  0,
                             Math.sin(a),   Math.cos(a),    0,  0,
                             0,             0,              1,  0,
                             0,             0,              0,  1)
        clawLeftTransform.matrix = backend.matrix4x4Multip(clawTransform.matrix,m)
 
        var n = Qt.matrix4x4(Math.cos(-a),   -Math.sin(-a),   0,  0,
                             Math.sin(-a),   Math.cos(-a),    0,  0,
                             0,              0,               1,  0,
                             0,              0,               0,  1)
        clawRightTransform.matrix = backend.matrix4x4Multip(clawTransform.matrix,n)
    }
 
    function clawTransformRotationY(){
        var a = clawLeftRight*Math.PI/180.0
 
        var m = Qt.matrix4x4(Math.cos(a),   0,  Math.sin(a),    0,
                             0,             1,  0,              -2.0173,
                             -Math.sin(a),  0,  Math.cos(a),    -0.151733,
                             0,             0,  0,              1)
        clawTransform.matrix = backend.matrix4x4Multip(wristClawTransform.matrix,m)
        clawOpenAndClose()
    }
 
    //腕部变换
    function wristClawTransformRotationX(){
        wristClawMatrix()
        clawTransformRotationY()
        clawOpenAndClose()
    }
 
    function wristClawMatrix(){
        var a = wristClawRota*Math.PI/180.0
//                              旋转x         旋转y     旋转z
        var m = Qt.matrix4x4(1,  0,           0,            -0.83,                      //平移x
                             0,  Math.cos(a), -Math.sin(a), 0.24856,                    //平移y
                             0,  Math.sin(a), Math.cos(a),  -10.0608,                   //平移z
                             0,  0,           0,            1)
        wristClawTransform.matrix = backend.matrix4x4Multip(upperArmTransform.matrix,m)
    }
 
    //上臂变换
    function upperArmTransformRotationX(){
        //上臂
        upperArmMatrix()
        wristClawMatrix()
        clawTransformRotationY()
        clawOpenAndClose()
    }
 
 
    function upperArmMatrix(){
        var a = upperArmRota*Math.PI/180.0
        var m = Qt.matrix4x4(1, 0,          0,              1.0032,
                             0,  Math.cos(a), -Math.sin(a), 1.63431,
                             0,  Math.sin(a), Math.cos(a), 7.84555,
                             0,            0,           0, 1)
        upperArmTransform.matrix = backend.matrix4x4Multip(lowerArmTransform.matrix,m)
        wristClawMatrix()
    }
 
    function lowerArmMatrix(){
        var a = lowerArmRota*Math.PI/180.0
        var m = Qt.matrix4x4(1,  0,           0,            0,
                             0,  Math.cos(a), -Math.sin(a), -0.33856,
                             0,  Math.sin(a), Math.cos(a),  0,
                             0,  0,           0,            1)
        lowerArmTransform.matrix = backend.matrix4x4Multip(turretTransform.matrix,m)
    }
 
    //下臂变换
    function lowerArmTransformRotationX(){
        //下臂
        lowerArmMatrix()
        upperArmMatrix()
        clawTransformRotationY()
        clawOpenAndClose()
    }
 
 
    function turretTransformFunction(){
        //下臂
        lowerArmMatrix()
        upperArmMatrix()
        clawTransformRotationY()
        clawOpenAndClose()
    }
 
    function turretTransformRotationY(){
        turretVect3d = backend.matrix4x4Index2(baseTransform.matrix)
        turretAngle = -turretRota - turretL
 
        turretTransform.rotation = backend.quaternionMultip(trans.rotation,turretBaseQuaternion)
        turretTransformFunction()
    }
 
    function baseTransformFunctionX(){
        var a = turretRota*Math.PI/180.0
        var m = Qt.matrix4x4(Math.cos(a),   0, Math.sin(a), 0,
                             0,             1, 0,           4.27978,
                             -Math.sin(a),  0, Math.cos(a), -4.50885,
                             0,             0, 0,           1)
        turretTransform.matrix = backend.matrix4x4Multip(baseTransform.matrix,m)
        turretL = turretRota
        turretTransformFunction()
 
    }
 
    function baseTransformFunctionY(){
        var a = turretRota*Math.PI/180.0
        var m = Qt.matrix4x4(Math.cos(a),   0, Math.sin(a), 0,
                             0,             1, 0,           4.27978,
                             -Math.sin(a),  0, Math.cos(a), -4.50885,
                             0,             0, 0,           1)
        turretTransform.matrix = backend.matrix4x4Multip(baseTransform.matrix,m)
        turretL = turretRota
        turretTransformFunction()
 
    }
 
    function baseTransformFunctionZ(){
        var a = turretRota*Math.PI/180.0
        var m = Qt.matrix4x4(Math.cos(a),   0, Math.sin(a), 0,
                             0,             1, 0,           4.27978,
                             -Math.sin(a),  0, Math.cos(a), -4.50885,
                             0,             0, 0,           1)
        turretTransform.matrix = backend.matrix4x4Multip(baseTransform.matrix,m)
        turretL = turretRota
        turretTransformFunction()
 
    }
 
 
    function baseTransformRotationZ(){
        baseTransform.rotationZ = basePitch
 
        baseTransformFunctionZ()
        turretBaseQuaternion = turretTransform.rotation
 
    }
 
 
    function baseTransformRotationY(){
        baseTransform.rotationY = baseHeading //角度
 
        baseTransformFunctionY()
        turretBaseQuaternion = turretTransform.rotation
    }
 
 
    function baseTransformRotationX(){
        baseTransform.rotationX = baseRoll
 
        baseTransformFunctionX()
        turretBaseQuaternion = turretTransform.rotation
    }
 
 
 
    function baseHeadingFunction(){
        return baseHeading
    }
    function baseRollFunction(){
        return baseRoll
    }
    function basePitchFunction(){
        return basePitch
    }
    function turretRotaFunction(){
        return turretRota
    }
    function lowerArmRotaFunction(){
        return lowerArmRota
    }
    function upperArmRotaFunction(){
        return upperArmRota
    }
    function wristClawRotaFunction(){
        return wristClawRota
    }
    function clawLeftRightFunction(){
        return clawLeftRight
    }
    function clawOpenCloseFunction(){
        return clawOpenClose
    }
 
    function setBaseHeading(delta){
        baseHeading = delta
        baseTransformRotationY()
    }
    function setBaseRoll(delta){
        baseRoll = delta
        baseTransformRotationX()
    }
    function setBasePitch(delta){
        basePitch = delta
        baseTransformRotationZ()
    }
    function setTurretRota(delta){
        turretRota = delta
        turretTransformRotationY()
    }
    function setLowerArmRota(delta){
        lowerArmRota = delta
        lowerArmTransformRotationX()
    }
    function setUpperArmRota(delta){
        upperArmRota = delta
        upperArmTransformRotationX()
    }
    function setWristClawRota(delta){
        wristClawRota = delta
        wristClawTransformRotationX()
    }
    function setClawLeftRight(delta){
        clawLeftRight = delta
        clawTransformRotationY()
    }
    function setClawOpenClose(delta){
        clawOpenClose = delta
        clawOpenAndClose()
        //console.info(delta)
    }
#include <Qt3DQuickExtras/qt3dquickwindow.h>
#include <QGuiApplication>
#include <QQuickView>
#include <QQmlEngine>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickItem>
 
int main(int argc, char* argv[])
{
    QGuiApplication app(argc, argv);
 
    QQuickView view;
 
    view.setFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
    view.setColor(QColor(Qt::transparent));
    view.setSource(QUrl("qrc:/main.qml"));
    view.show();
 
    return app.exec();
}

 用于显示3d模型

 
import QtQuick 2.2 as QQ2
import QtQuick 2.0
import QtQuick.Scene3D 2.0
import Qt3D.Core 2.0
import Qt3D.Render 2.0
import Qt3D.Input 2.0
import Qt3D.Extras 2.0
 
 
 
Entity {
    id: sceneRoot
    property alias upperArmPos: upperArmTransform
    property alias wristClawPos: wristClawTransform
 
    property real wristClawRota: 0.0    //腕部旋转度数Y
    property real upperArmRota: 0.0     //上臂旋转度数Y
    property real lowerArmRota: 0.0     //下臂旋转度数Y
    property real turretRota: 0.0       //塔台旋转度数Y
    property real baseRotaY: 0.0        //基座旋转度数Y
    property real baseRotaZ: 0.0        //基座旋转度数Z
 
    Component.onCompleted:{
        var upperArmPos = upperArmTransform.translation
        var wristClawPos = wristClawTransform.translation
        //console.log(upperArmPos,wristClawPos)
    }
 
    components: [
        RenderSettings {
            activeFrameGraph: ForwardRenderer {
                camera: camera
                clearColor: "transparent"
 
            }
        },
        // Event Source will be set by the Qt3DQuickWindow
        InputSettings {
        }
    ]
 
 
 
    Camera {
        id: camera
        projectionType: CameraLens.PerspectiveProjection
        fieldOfView: 25
        aspectRatio: 16/9
        nearPlane : 0.01
        farPlane : 1000.0
        position: Qt.vector3d( 0.0, 10.0, -40.0 )
        upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
        viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
 
    }
 
    OrbitCameraController {
        camera: camera
    }
 
    FirstPersonCameraController { camera: camera }
 
    Entity {
        id: base
 
        Transform {
            id: baseTransform
 
            translation:Qt.vector3d(-4.01445,-5.87275,0.02425)
        }
 
        PhongMaterial {
            id: materialBase
            ambient: Qt.rgba( 0.1, 0.2, 0.3, 1 )            //环境光
            diffuse: Qt.rgba( 0.1, 0.1, 0.1, 1 )            //漫反射
            specular: Qt.rgba( 0.2, 0.2, 0.1, 1 )           //高光反射
            //                shininess: 0.6
            shininess: 10.0
        }
 
        Mesh {
            id: meshBase
            source: "qrc:/obj/obj/Base.obj"
        }
 
        components: [meshBase, materialBase,baseTransform]
    }
}

 main.qml调用

 
import QtQuick 2.0
import QtQuick.Scene3D 2.0
import QtQuick.Controls 1.4
 
Rectangle {
 
    width: 600
    height: 400
    color: "transparent"
    focus: true
 
 
    Rectangle {
        id: scene
        anchors.fill: parent
        anchors.margins: 0
        color: "transparent"
        Scene3D {
            id: scene3d
            anchors.fill: parent
            anchors.margins: 0
            aspects: ["input", "logic"]
            cameraAspectRatioMode: Scene3D.AutomaticAspectRatio
 
            AnimatedEntity {
            id:unicorn
            }
 
 
        }
 
 
    }
}

QML加载3D模型有多种方法,以下是不同格式模型的加载方式: ### 加载.mesh格式模型 若想在QML中使用3D且无三维程序开发基础,可使用Qt Quick 3D加载3D模型,该功能从Qt 5.15之后被添加到Qt中,三维模型使用.mesh格式的模型文件。示例代码如下: ```qml import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick3D 1.15 Window { width: 640 height: 480 visible: true title: qsTr("Hello World") View3D { id: view3D anchors.fill: parent environment: sceneEnvironment SceneEnvironment { id: sceneEnvironment antialiasingQuality: SceneEnvironment.High antialiasingMode: SceneEnvironment.MSAA } Node { id: node DirectionalLight { id: directionalLight } PerspectiveCamera { id: camera z: 15 } Model { id: cubeModel source: "test.mesh" DefaultMaterial { id: cubeMaterial diffuseColor: "#4aee45" } materials: cubeMaterial } } } } ``` 上述代码创建了一个窗口,在其中使用`View3D`组件加载一个`.mesh`格式的3D模型,并设置了光照、相机和材质等属性 [^1][^3]。 ### 加载.gltf格式模型 使用`SceneLoader`组件加载`.gltf`格式的模型,示例代码如下: ```qml import Qt3D.Core 2.15 import Qt3D.Render 2.15 import Qt3D.Extras 2.15 Entity { components: [ SceneLoader { source: "model.gltf" onStatusChanged: { if (status === SceneLoader.Ready) console.log("模型加载完成,包含", entities.length, "个子实体") } } ] } ``` 此代码在`Entity`中使用`SceneLoader`加载`.gltf`模型,并在加载完成后输出子实体数量 [^2]。 ### 加载其他格式模型 对于`.obj`格式的模型文件,若满足一定条件,可以使用Qt 6或者Qt 5自带的`balsam.exe`解析模型数据,转化为QML文件;`.fbx`格式的模型数据,只能用Qt 6自带的`balsam.exe`解析,会解析出带贴图的代码,而用Qt 5自带的`balsam.exe`解析则只会显示基础颜色 [^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值