2.qml 3D-View3D类学习

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

Rectangle {
        width: 200 
        height: 200
        color: "red"
        View3D {    
                anchors.fill: parent   
                anchors.margins: 40
                // ... ...
        }
}

效果如下所示:

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

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

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

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方向的。
假如我们设置为:

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

效果如下所示:


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

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类后再详解,所以本章只简单使用,示例如下所示:

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

}

运行效果如下所示:

未完待续

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诺谦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值