Qt Quick 3D学习:鼠标拾取物体

这篇具有很好参考价值的文章主要介绍了Qt Quick 3D学习:鼠标拾取物体。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

(注意,开源版的 Qt Quick 3D 是狗都不用的 GPL 协议)

Qt Creator 中有一个 picking 的示例,用于演示 View3D 中物体的拾取:

Qt Quick 3D学习:鼠标拾取物体

在示例基础上,我又加了一个简单的拖动效果,如图所示:

 Qt Quick 3D学习:鼠标拾取物体

在使用 OpenGL 实现拾取的时候,我们可以用射线法。Qt Quick 3D 中封装了拾取操作,通过 View3D 的 pick 函数,可以取到 View3D 视口某个点下离屏幕最近的那个物体 Model。

PickResult pick(float x, float y)

该函数返回一个 PickResult 对象,通过其 objectHit 属性可以判断是否拾取到了物体。

View3D {
    MouseArea {
        id: mouse_area
        anchors.fill: parent
        onPressed: {
            //获取点在View上的屏幕坐标
            pick_screen.text = "(" + mouse.x + ", " + mouse.y + ")"
            //pick取与该点射线路径相交的离最近的Model的信息,返回PickResult对象
            var result = control.pick(mouse.x, mouse.y)
            //判断objectHit是否有效,就可以只知道是否拾取到了物体
            if (result.objectHit) {

            } else {

            }
        }
    }
}

在 Qt5.15 中,返回的 PickResult 类型只有简单的几个属性:

//拾取原点与物体之间的距离,用视口坐标拾取则拾取原点就是观察点Camera的位置
distance : float

//拾取选中的Model对象
objectHit : Model

//pick点在场景中的位置,(可能相当于射线与物体表面的焦点坐标)
//This property holds the scene position of the hit.
scenePosition : vector3d

//pick点的UV位置
//This property holds the UV position of the hit.
uvPosition : vector2d

在 Qt6.3 中,View3D 增加了 pickAll 函数拾取该点下所有的物体,同时 PickResult 类型也增加了一些属性:

//局部空间中被选中的面的法线
//This property holds the normal of the face that was hit in local coordinate space.
normal : vector3d

//This property holds the scene position of the hit in local coordinate space.
position : vector3d

//This property holds the normal of the face that was hit in scene coordinate space.
sceneNormal : vector3d

拾取到物体之后,就可以对这个 Model 节点进行操作了。本文 Demo 中我实现了一个简单的拖动操作,主要流程是:

1.pick 选中时保存 Model 位置和 pick 位置的视口屏幕坐标差值(可以通过 View3D 的 mapFrom3DScene 函数将场景坐标转换为视口坐标,使用该函数需要先给 View3D 设置 camera )

2.在鼠标移动的过程中,通过差值还原物体 Model 的相对位置,使用 View3D 的 mapTo3DScene 函数转换得到 Model 新的场景坐标。

(但是这个逻辑没有考虑透视投影时,移动场景坐标 xy,视口坐标 xy 并不是等比变化的)

主要代码

Github(PickModel.qml): https://github.com/gongjianbo/HelloQtQuick3D

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick3D 1.15
import QtQuick3D.Helpers 1.15

View3D {
    id: control

    //背景
    environment: SceneEnvironment {
        clearColor: "darkGreen"
        backgroundMode: SceneEnvironment.Color
    }

    //观察相机
    //View3D的mapTo/mapFrom坐标转换函数需要先设置camera属性
    camera: perspective_camera
    PerspectiveCamera {
        id: perspective_camera
        z: 300
    }

    //光照
    DirectionalLight {
        eulerRotation.y: 45
    }

    //立方体
    Model {
        id: cube_node
        objectName: "Cube"
        source: "#Cube"
        //使能pick
        pickable: true
        materials: DefaultMaterial {
            diffuseColor: mouse_area.pickNode == cube_node ? "cyan" : "yellow"
        }
        //立方体转动
        SequentialAnimation on eulerRotation {
            running: true
            loops: Animation.Infinite
            PropertyAnimation {
                duration: 10000
                from: Qt.vector3d(0, 0, 0)
                to: Qt.vector3d(360, 360, 360)
            }
        }
    }

    //锥体
    Model {
        id: cone_node
        objectName: "Cone"
        source: "#Cone"
        pickable: true
        x: 100
        z: 50
        materials: DefaultMaterial {
            diffuseColor: mouse_area.pickNode == cone_node ? "cyan" : "orange"
        }
    }

    //球体
    Model {
        id: sphere_node
        objectName: "Sphere"
        source: "#Sphere"
        pickable: true
        x: -100
        z: -50
        materials: DefaultMaterial {
            diffuseColor: mouse_area.pickNode == sphere_node ? "cyan" : "purple"
        }
    }

    //展示拾取对象的信息
    Row {
        x: 20
        y: 20
        spacing: 10
        Column {
            Label {
                color: "white"
                text: "Pick Node:"
            }
            Label {
                color: "white"
                text: "Screen Position:"
            }
            Label {
                color: "white"
                text: "Distance:"
            }
            Label {
                color: "white"
                text: "World Position:"
            }
        }
        Column {
            Label {
                id: pick_name
                color: "white"
            }
            Label {
                id: pick_screen
                color: "white"
            }
            Label {
                id: pick_distance
                color: "white"
            }
            Label {
                id: pick_word
                color: "white"
            }
        }
    }

    MouseArea {
        id: mouse_area
        anchors.fill: parent
        hoverEnabled: false
        property var pickNode: null
        //鼠标和物体xy的偏移
        property real xOffset: 0
        property real yOffset: 0
        property real zOffset: 0

        onPressed: {
            //获取点在View上的屏幕坐标
            pick_screen.text = "(" + mouse.x + ", " + mouse.y + ")"
            //pick取与该点射线路径相交的离最近的Model的信息,返回PickResult对象
            //因为该模块一直在迭代,新的版本可以从PickResult对象获取更多的信息
            //Qt6中还提供了pickAll获取与该射线相交的所有Model信息
            var result = control.pick(mouse.x, mouse.y)
            //目前只在点击时更新了pick物体的信息
            if (result.objectHit) {
                pickNode = result.objectHit
                pick_name.text = pickNode.objectName
                pick_distance.text = result.distance.toFixed(2)
                pick_word.text = "("
                        + result.scenePosition.x.toFixed(2) + ", "
                        + result.scenePosition.y.toFixed(2) + ", "
                        + result.scenePosition.z.toFixed(2) + ")"
                //console.log('in',pick_screen.text)
                //console.log(result.scenePosition)
                var map_from = control.mapFrom3DScene(pickNode.scenePosition)
                //var map_to = control.mapTo3DScene(Qt.vector3d(mouse.x,mouse.y,map_from.z))
                //console.log(map_from)
                //console.log(map_to)
                xOffset = map_from.x - mouse.x
                yOffset = map_from.y - mouse.y
                zOffset = map_from.z
            } else {
                pickNode = null
                pick_name.text = "None"
                pick_distance.text = " "
                pick_word.text = " "
            }
        }
        onPositionChanged: {
            if(!mouse_area.containsMouse || !pickNode){
                return
            }
            var pos_temp = Qt.vector3d(mouse.x + xOffset, mouse.y + yOffset, zOffset);
            var map_to = control.mapTo3DScene(pos_temp)
            pickNode.x = map_to.x
            pickNode.y = map_to.y
        }
    }
}

参考

Qt文档:https://doc.qt.io/qt-5/qml-qtquick3d-view3d.html文章来源地址https://www.toymoban.com/news/detail-497275.html

到了这里,关于Qt Quick 3D学习:鼠标拾取物体的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity中鼠标控制3D物体进行拖拽

    拖拽 1 、获取3D物体在世界坐标的位置转换屏幕坐标 2、鼠标在屏幕的坐标与物体在屏幕的坐标Z轴进行拟合 3、获取3D物体与拟合出来的坐标的偏移量 4、通过向量投影得到移动坐标 5、上干货,附带手指控制,手指控制逻辑同鼠标一样 自由拖拽 自由拖拽同上不同的是 获取3D物

    2024年03月26日
    浏览(44)
  • unity3D 鼠标滚轮实现物体的大小缩放

    鼠标滚轮响应函数是Input.GetAxis(\\\"Mouse ScrollWheel\\\"),函数返回值类型是float,向前滚是返回正数,向后滚是返回负数,且鼠标滚轮滑动单次函数返回值为0.1 利用返回值修改模型transform.localscale,实现模型缩放 鼠标滚轮一直向后滚,会看见模型逐渐变小,当变到很小到消失的时候,

    2024年02月08日
    浏览(81)
  • Qt6 Qt Quick UI原型学习QML第七篇

    导入 QtQuick 2.12 导入 QtQuick.Window 2.12 导入 QtQuick.Controls 2.12 导入 QtQuick.Layouts 1.3 导入 Qt.labs.calendar 1.0 矩形 { id: root 属性 int duration: 3000 } 这段代码使用了QtQuick库来创建一个用户界面。其中的Rectangle是界面的根元素。 id: root : 为Rectangle元素指定唯一的标识符root。 property int durat

    2024年02月16日
    浏览(40)
  • Qt6 Qt Quick UI原型学习QML第三篇

    图像 Image(图片)元素 解释 这段代码是使用QtQuick 2.0库来创建一个Image(图片)元素的定义。以下是代码的解释: Image 元素是一个用于显示图像的控件。 id: root 是为Image元素指定了一个标识符,以便在代码中引用它。 signal clicked 定义了一个名为 clicked 的信号。信号用于在特

    2024年02月16日
    浏览(53)
  • Qt6 Qt Quick UI原型学习QML第二篇

    元素可以分为 视觉元素和非视觉元素 。视觉元素(如Rectangle)具有几何形状,并且通常在屏幕上呈现一个区域。非可视元素(如Timer)提供一般功能,通常用于操作可视元素。 目前,我们将关注基本的视觉元素,例如 Item, Rectangle, Text, Image和MouseArea 。但是,通过使用Qt Quick Contro

    2024年02月16日
    浏览(38)
  • Qt6 Qt Quick UI原型学习QML第六篇

    import QtQuick 2.12 :导入QtQuick模块的版本2.12,用于创建Qt快速应用程序的用户界面。 import QtQuick.Window 2.12 :导入QtQuick.Window模块的版本2.12,用于创建窗口对象。 import QtQuick.Controls 2.12 :导入QtQuick.Controls模块的版本2.12,用于创建用户界面控件。 Window {} :定义了一个窗口对象,

    2024年02月16日
    浏览(49)
  • Qt6 Qt Quick UI Prototype学习QML第一篇

    创建一个具有QML入口点的Qt Quick 2 UI项目。要使用它,您需要设置一个QML运行时环境,例如gmlscene。 仅当您正在进行原型设计时才使用此功能。您无法使用此创建完整的应用程序。请考虑使用Qt Quick application项目 Qt Quick UI原型主要用于快速创建交互式的用户界面(UI)原型。它

    2024年02月16日
    浏览(49)
  • 【Unity脚本开源】记录鼠标按下的位置和移动的距离来进行物体的旋转,并在鼠标释放后将物体恢复到初始旋转位置

    ♥️作者:白日参商 🤵‍♂️个人主页:白日参商主页 ♥️坚持分析平时学习到的项目以及学习到的软件开发知识,和大家一起努力呀!!! 🎈🎈加油! 加油! 加油! 加油 🎈欢迎评论 💬点赞👍🏻 收藏 📂加关注+! 提针对这个需求,以下是示例脚本代码: ♥️作者

    2024年02月12日
    浏览(44)
  • Unity XR Interaction Toolkit(三)拾取物体

    首先配置一个可拾取的物体,右键-XR-Grab Interactable,就会创建一个0.1尺寸的小立方体 XRGrabInteractable: Distance Calculation Mode:根据模式选择坐标点,可以选择Transform的坐标或者碰撞器的坐标 Select Mode:抓取方式,分为单手和双手,在变换脚本挂载时,会根据这个脚本激活 Movem

    2024年02月08日
    浏览(43)
  • Unity3D实现鼠标悬浮UI或物体上显示文字信息

    Unity工具 大家好,我是心疼你的一切,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 本篇文章实现一个鼠标悬浮在ui或者物体上显示文字的功能 unity鼠标悬浮ui显示文字 鼠标进入UI执行的 鼠标离开UI执行的 鼠标在ui里滑动执行的 1. 2. 搭建比较简单,各位顺便搭建吧。

    2024年02月04日
    浏览(95)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包