2.qml 3D-View3D类学习

本章我们来学习View3D类。

View3D是用来渲染3D场景并显示在2D平面的类,并且该类可以放在QML2D下继承于Item子类的任何场景中,比如将View3D放在Rectangle中:

cs 复制代码
Rectangle {
        width: 200 
        height: 200
        color: "red"
        View3D {    
                anchors.fill: parent   
                anchors.margins: 40
                // ... ...
        }
}

效果如下所示:

View3D是用来渲染3D场景的,所以我们可以通过environment属性来设置环境参数,比如设置3D背景色、抗锯齿、天空盒等等,比如设置:

cs 复制代码
environment: SceneEnvironment {
            clearColor: "red"            // 设置背景色为红色
            backgroundMode: SceneEnvironment.Color   // 设置背景模式为color,也可以设置为天空盒、透明等等
            antialiasingMode: SceneEnvironment.MSAA  // 抗锯齿模式
            antialiasingQuality: SceneEnvironment.High  //  抗锯齿质量
  }

如果我们要在场景中显示2D类(必须是Item子类),可以通过Node类实现、比如我们要在View3D中显示一个Text:

cs 复制代码
import QtQuick
import QtQuick.Window
import QtQuick3D
import QtQuick3D.Helpers
Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")
    View3D {
        anchors.fill: parent
        environment: SceneEnvironment {
            clearColor: "#F1F1F1"
            backgroundMode: SceneEnvironment.Color
            antialiasingMode: SceneEnvironment.MSAA
            antialiasingQuality: SceneEnvironment.High
        }

        PerspectiveCamera {
            id: camera
            position: Qt.vector3d(0, 0, 440)
        }

        Node {
            Rectangle {
                width: 400
                height: 400
                x: -width/2
                y: -height/2
                color: "#77202020"
                radius: 10
                border.width: 2
                border.color: "#77f0f0f0"
                Text {
                    anchors.centerIn: parent
                    font.pixelSize: 20
                    color: "#FFF"
                    font.family: "Microsoft Yahei"
                    style: Text.Raised
                    styleColor: "#111"
                    text: "QML3D学习 by诺谦"
                }
            }
        } 
    } 
}

效果如下所示:

这里我们使用了PerspectiveCamera 相机,要让View3D显示出来则必须需要一个继承于Camera类的相机,否则View3D无法知道我们要从哪个角度去展示3D场景。

我们设置了摄像机的positionQt.vector3d(0, 0, 440)、只设置了z为440,而欧拉角度默认是0,所以可以看出摄像机的方向默认是从Z方向照射XY方向的。

假如我们设置为:

cs 复制代码
PerspectiveCamera {
            id: camera
            position: Qt.vector3d(0, -200, 440)    // 摄像机Y方向后退200
            eulerRotation.x: 30                    // 绕x正方向旋转30°
 }

效果如下所示:

而我们设置的Rectangle的x和y为宽高的负一半,这是为了让Rectangle在原点居中显示,除此之外,Node还可以组合式显示,比如:

cs 复制代码
Node {
    Rectangle {
        width: 400
        height: 400
        x: -width/2
        y: -height/2
        color: "#77202020"
    }
    Rectangle {
        width: 400
        height: 400
        x: 0
        y: 0
        color: "#77202020"
    } 	
}

效果如下所示:


其中Node类介绍如下所示:

如上图可以看到,Node类的子类非常多,比如Model类(显示3D模型)、ParticleSystem3D粒子系统类、Light光照类 等等。

所以Node类非常重要,下章我们便来来学习Node类,再来学习其它类就会非常的方便快捷。

View3D的其它相关属性和方法介绍

  • **importScene :**设置公共的Node,比如有多个View3D,其内容都是相同的Node,只是相机位置不一致而已,具体参考示例(View3D Example),注意:该属性只能设置一次,后续更改将无效。
  • camera : QtQuick3D::Camera,指定用哪个相机来显示
  • **environment :**QtQuick3D::SceneEnvironment,设置渲染场景,比如背景色
  • importScene :QtQuick3D::Node,设置公共的Node,比如有多个View3D,其内容都是相同的Node,只是相机位置不一致而已,具体参考示例(View3D Example),注意:该属性只能设置一次,后续更改将无效。
  • **renderFormat :**enumeration, 设置渲染纹理的格式,默认为ShaderEffectSource.RGBA8
  • renderMode : enumeration,渲染模式,默认为View3D.Offscreen,只有当某些GOU硬件不支持时,才会去更改渲染模式。
  • **renderStats :**QtQuick3D::RenderStats,只读属性,统计信息,比如fps实时刷新率,frameTime,renderTime,syncTime, 和maxFrameTime等等
  • scene : QtQuick3D::Node, 只读属性, 保存View3D场景的根节点。

方法如下所示:

  • **vector3d mapFrom3DScene(vector3d scenePos) :**将scenePos场景空间位置(3D)转换到视图平面位置(2D)
  • **vector3d mapTo3DScene(vector3d viewPos) :**将viewPos视图平面位置(2D)转换到场景空间位置(3D)
  • **PickResult pick(float x, float y) :**此方法将从视图坐标xy位置"射"一条光线到3D场景中,并返回与射线最近交叉的物体信息。例如,可以使用鼠标坐标来调用它来查找鼠标光标下的对象.
  • **List<PickResult> pickAll(float x, float y) :**和pick函数类似,不过是从视图坐标xy位置"射"一条光线到3D场景中,并返回与射线所有交叉的物体信息列表并从近到远进行排序
  • PickResult rayPick(vector3d origin, vector3d direction) : 获取从场景空间位置origin,发出一个direction方向的射线,并返回与射线最近交叉的物体信息,例如,在判断射击子弹时是否有碰撞
  • **List<PickResult> rayPickAll(vector3d origin, vector3d direction):**和rayPick函数类似,不过获取的是一个所有交叉的列表

而PickResult 类常用参数如下所示:

  • distance : float, 拾取距离,也就是射出光线的原点与交叉点的距离
  • **instanceIndex :**int,当拾取命中实例模型的实例时,此属性保存实例表中的索引,如果该模型不是由多个子模块组成,那么始终返回0
  • **normal :**vector3d,保存局部坐标空间中被击中的面的法线。
  • objectHit : Model,保存被选中的模型对象,我们可以通过!=null来判断是否有选中对象
  • **position :**vector3d,保存拾取命中时,在3D空间中的场景位置

接下来我们便来实现一个点击3D物体变色的示例。

由于点击只有对3D模型才有效果(比如对光无法进行点击),所以我们需要使用Model类,Model类需要在学了Node类后再详解,所以本章只简单使用,示例如下所示:

cs 复制代码
import QtQuick
import QtQuick.Window
import QtQuick3D
Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")
    View3D {
        id: _view
        anchors.fill: parent

        environment: SceneEnvironment {
            clearColor: "#F1F1F1"
            backgroundMode: SceneEnvironment.Color
            antialiasingMode: SceneEnvironment.MSAA
            antialiasingQuality: SceneEnvironment.High
        }
        camera: camera
        PerspectiveCamera {
            id: camera
            position: Qt.vector3d(0, -900, 800)
            eulerRotation.x: 45
        }

        MouseArea {
            anchors.fill: parent
            onClicked: (mouse)=> {
                let ret = _view.pick(mouse.x, mouse.y)
                if(ret.objectHit != null)
                    ret.objectHit.materials[0].diffuseColor =
                           Qt.rgba(Math.random(),Math.random(), Math.random(), 1.0)

            }
        }

        DirectionalLight {
           eulerRotation: Qt.vector3d(0, 0, 0)
           castsShadow: true
           brightness: 3
        }

        Model {
            id: _sphere
            source: "#Sphere"
            z: 300
            pickable: true
            scale: Qt.vector3d(2, 2, 2)
            materials: DefaultMaterial {
                diffuseColor: Qt.rgba(0.6, 0.5, 0.2, 1.0)
            }
        }


        Model {
            source: "#Rectangle"
            pickable: true
            scale: Qt.vector3d(10, 10, 1)
            materials: DefaultMaterial {
                diffuseColor: Qt.rgba(0.7, 0.2, 0.2, 1.0)
            }
        }
    }

}

运行效果如下所示:

未完待续

相关推荐
学编程的小程1 小时前
从“单模冲锋”到“多模共生”——2026 国产时序数据库新物种进化图谱
数据库·时序数据库
卓怡学长1 小时前
m111基于MVC的舞蹈网站的设计与实现
java·前端·数据库·spring boot·spring·mvc
存在的五月雨1 小时前
Redis的一些使用
java·数据库·redis
小冷coding8 小时前
【MySQL】MySQL 插入一条数据的完整流程(InnoDB 引擎)
数据库·mysql
鲨莎分不晴9 小时前
Redis 基本指令与命令详解
数据库·redis·缓存
专注echarts研发20年9 小时前
工业级 Qt 业务窗体标杆实现・ResearchForm 类深度解析
数据库·qt·系统架构
周杰伦的稻香11 小时前
MySQL中常见的慢查询与优化
android·数据库·mysql
冉冰学姐11 小时前
SSM学生社团管理系统jcjyw(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·ssm 框架·学生社团管理系统·多角色管理
nvd1112 小时前
深入分析:Pytest异步测试中的数据库会话事件循环问题
数据库·pytest
appearappear12 小时前
如何安全批量更新数据库某个字段
数据库