在之前的文章中讲到了OpenGL鼠标拾取操作的例子,工作中需要在Qt中实现,下面的程序演示了QT中opengl的拾取例子。

本例子在Qt5.12和Qt Creator4.8.0上测试,使用的是QOpenGLWidget类,在窗口的正中央有红绿两个三角形组成一个正方形,分别点击不同的三角形部分进行对象拾取。

相关代码如下:

opengl_widget.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 
#ifdef _MSC_VER
#pragma once
#endif

#ifndef _OPENGL_WIDGET_H_
#define _OPENGL_WIDGET_H_

#include <vector>

#include <QtWidgets/qopenglwidget.h>

class OpenGLWidget : public QOpenGLWidget
{
    Q_OBJECT

public:
    explicit OpenGLWidget(QWidget *parent = nullptr);
    virtual ~OpenGLWidget();

protected:
    virtual void initializeGL() override;
    virtual void paintGL() override;
    virtual void resizeGL(int w, int h) override;
    virtual void mousePressEvent(QMouseEvent *ev) override;
    virtual void mouseMoveEvent(QMouseEvent *ev) override;
    virtual void mouseReleaseEvent(QMouseEvent *ev) override;

private:
    void drawObjects() const;

using uint = unsigned int;
    ;
    std::vector<uint> selectBuffer = std::vector<uint>(selectBufferSize);

};  // class OpenGLWidget

#endif  // _OPENGL_WIDGET_H_

opengl_widget.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
 
#include "opengl_widget.h"

#include <gl/GLU.h>

#include <QtGui/qevent.h>

OpenGLWidget::OpenGLWidget(QWidget *parent)
    : QOpenGLWidget(parent)
{
}

OpenGLWidget::~OpenGLWidget()
{
}

void OpenGLWidget::initializeGL()
{
    glEnable(GL_DEPTH_TEST);
    glClearColor(.0f);
}

void OpenGLWidget::resizeGL(int w, int h)
{
    glViewport(, w, h);
}

void OpenGLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

int renderMode;
    glGetIntegerv(GL_RENDER_MODE, &renderMode);

if (renderMode != GL_SELECT)
    {
        // Matrix setting
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        const float aspect = static_cast<float>(width()) / height();
        gluPerspective();
    }

glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt();

drawObjects();
}

void OpenGLWidget::mousePressEvent(QMouseEvent *ev)
{
    // Selection buffer
);
    glSelectBuffer(selectBufferSize, &selectBuffer[]);

// Draw for selection buffer
    glRenderMode(GL_SELECT);

// Matrix setting
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();

];
    glGetIntegerv(GL_VIEWPORT, viewport);
    gluPickMatrix(ev->x(), height() - ev->y(), , viewport);
    ];
    gluPerspective();

// Draw
    paintGL();

// Reset matrix setting
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

// Revert render mode
    int hits = glRenderMode(GL_RENDER);

// Show selection
    printf("%d hits\n", hits);
    )
    {
        ;
        ; i < hits; i++)
        {
            printf(]);
            printf(] / UINT_MAX);
            printf(] / UINT_MAX);
            printf(]);
            id += ;
        }
    }
}

void OpenGLWidget::mouseMoveEvent(QMouseEvent *ev)
{
}

void OpenGLWidget::mouseReleaseEvent(QMouseEvent *ev)
{
}

void OpenGLWidget::drawObjects() const
{
    // Prepare for selection
    glInitNames();
    glPushName();

// First
.0f);
    glLoadName();
    glBegin(GL_TRIANGLES);
    glVertex3f(-.0f);
    glVertex3f(-.0f);
    glVertex3f( .0f);
    glEnd();

// Second
.0f);
    glLoadName();
    glBegin(GL_TRIANGLES);
    glVertex3f(-.0f);
    glVertex3f( .0f);
    glVertex3f( .0f);
    glEnd();
}

运行测试:

程序中使用了printf作为输出,但是其不能直接打印在Qt的应用程序输出窗口,需要进程结束后才会打印,可以使用qDebug来替代printf。

在测试过程中,我遇到了无论点击屏幕哪里,都会将所有的对象选中的情况,查找一些资料对比试验后,提醒要注意gluLookAt、gluPerspective的调用位置。

仅供参考,出自github:https://github.com/tatsy/QtOpenGLMousePick

Qt OpenGL 鼠标拾取实现的更多相关文章

  1. CSharpGL(21)用鼠标拾取、拖拽VBO图元内的点、线或本身

    CSharpGL(21)用鼠标拾取.拖拽VBO图元内的点.线或本身 效果图 以最常见的三角形网格(用GL_TRIANGLES方式进行渲染)为例. 在拾取模式为GeometryType.Point时,你 ...

  2. OpenGL 3D拾取文章(转)

    参考文章 深入探索3D拾取技术 OpenGL 3D拾取 射线和三角形的相交检测(ray triangle intersection test) 3D拾取的方法有两种 1.基于几何计算的射线-三角形相交 ...

  3. Qt OpenGL三维绘图

     简介 OpenGL是为三维绘图提供的标准应用编程接口. OpenGL处理的仅仅是三维绘图方面,而很少或是根本不提供图形用户界面编程方面的支持.OpenGL*应用程序的用户界面必须由其它工具包创建,比 ...

  4. ubuntu下配置qt+opengl+opencv

    原地址:http://www.cnblogs.com/aleny-liu/archive/2011/12/16/aleny-Qtnote1.html http://blog.csdn.net/jdh9 ...

  5. qt 窗口鼠标穿透

    Qt 不规则窗体 – 鼠标点击穿透 qt实现鼠标穿透,如果要被穿透窗口只有一层,也即没有嵌套窗口,直接只用对子窗口使用setAttribute (Qt::WA_TransparentForMouseE ...

  6. DirectX11 With Windows SDK--21 鼠标拾取

    前言 拾取是一项非常重要的技术,不论是电脑上用鼠标操作,还是手机的触屏操作,只要涉及到UI控件的选取则必然要用到该项技术.除此之外,一些类似魔兽争霸3.星际争霸2这样的3D即时战略游戏也需要通过拾取技 ...

  7. QT 11 鼠标键盘事件添加

    鼠标事件 void mousePressEvent(QMouseEvent *event); //单击 void mouseReleaseEvent(QMouseEvent *event); //释放 ...

  8. Qt532.【转】Qt创建鼠标右键菜单

    ZC:可以通过 设置  (QWebView*)->setContextMenuPolicy(NoContextMenu); 来关闭 QWebView的默认右键菜单 Qt创建鼠标右键菜单_疯华正茂 ...

  9. Qt判断鼠标在控件上

    QT判断鼠标是否在某子窗口控件上方 需要注意的是,子窗口获取geometry,是相对于父窗口的相对位置,QCursor::pos()获取的是鼠标绝对位置,要不将父窗口的相对位置进行换算,要不将鼠标的绝 ...

随机推荐

  1. c++ 引用犯的一个错

    void cal(int * &a) { ................ } int main() { int x=1; int *p=x; cal( &x );//出错 cal( ...

  2. ISDN简记

    简介 ISDN:(Integrated Services Digital Network,综合业务数字网) 是以综合数字电话网(IDN)为基础发展演变而形成的通信网,能够提供端到端的数字连接,用来支持 ...

  3. D. Cutting Out 二分

    题意是给你n个数字的序列,让你从中找含k个数字的序列,要求这k个数字要尽可能多次的从n个数字的序列中减去. 解法就是从1到n,二分查找可以删除的最大次数. http://codeforces.com/ ...

  4. delphi TTBXToolBar 增加外部控件

    这样可以引用外部控件,还是比较方便

  5. JS数字指定长度不足前补零的实现

    问题描述:         要求输出的数字长度是固定的,如长度为2,数字为1,则输出01,即不够位数就在之前补足0. 解决方法: 方法1 function fn1(num, length) { ret ...

  6. 网卡最大传输单位MTU和巨型帧(Jumbo frame)设置

    1. 背景:在1998年,Alteon Networks 公司提出把Data Link Layer最大能传输的数据从1500 bytes 增加到9000 bytes,这个提议虽然没有得到IEEE 80 ...

  7. [Vuex] Perform Async Updates using Vuex Actions with TypeScript

    Mutations perform synchronous modifications to the state, but when it comes to make an asynchronous ...

  8. instruments symbol name 不显示函数名!

    那是因为instruments找不到编译好的dSYM  其它的什么修改配置都没什么用 最好的办法就是直接删除资源文件APP名. 资源库 -> Developer -> Xcode -> ...

  9. UVA524 素数环 Prime Ring Problem

    题目OJ地址: https://www.luogu.org/problemnew/show/UVA524 hdu oj 1016:  https://vjudge.net/problem/HDU-10 ...

  10. 使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转)

    使用 TRESTClient 与 TRESTRequest 作为 HTTP Client 转自:http://www.cnblogs.com/dennieschang/p/6966403.html   ...