├── .github └── workflows │ └── blank.yml ├── MinBoundingBox.cpp ├── MinBoundingBox.h ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui ├── myqopenglwidget.cpp ├── myqopenglwidget.h ├── openglwidget.pro └── openglwidget.pro.user /.github/workflows/blank.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v1 12 | - name: Run a one-line script 13 | run: echo Hello, world! 14 | - name: Run a multi-line script 15 | run: | 16 | echo Add other actions to build, 17 | echo test, and deploy your project. 18 | -------------------------------------------------------------------------------- /MinBoundingBox.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "MinBoundingBox.h" 3 | 4 | MinBoundingBox::MinBoundingBox(void): 5 | m_finvalidDis(90000.0f) 6 | { 7 | zerolize(); 8 | } 9 | 10 | MinBoundingBox::~MinBoundingBox(void) 11 | { 12 | } 13 | 14 | bool MinBoundingBox::calculateMinBoundingBox(const std::vector& cloud) 15 | { 16 | zerolize(); 17 | int size =(int) cloud.size(); 18 | if (size == 0) 19 | { 20 | return false; 21 | } 22 | else if (size ==1) 23 | { 24 | firstPoint(cloud[0]); 25 | return false; 26 | } 27 | else 28 | { 29 | bool bfirst = false; 30 | for (int i = 0; i < size; i++) 31 | { 32 | if (!bfirst) 33 | { 34 | if (isValid(cloud[i])) 35 | { 36 | firstPoint(cloud[i]); 37 | bfirst = true; 38 | } 39 | } 40 | else 41 | { 42 | nextPoint(cloud[i]); 43 | } 44 | } 45 | m_center = QVector3D(midX(), midY(), midZ()); 46 | } 47 | return true; 48 | } 49 | 50 | void MinBoundingBox::setMinMax(QVector3D point, QVector3D &min, QVector3D &max) 51 | { 52 | min.setX(std::min(point.x(),min.x())); 53 | min.setY(std::min(point.y(),min.y())); 54 | min.setZ(std::min(point.z(),min.z())); 55 | 56 | max.setX(std::max(point.x(),max.x())); 57 | max.setY(std::max(point.y(),max.y())); 58 | max.setZ(std::max(point.z(),max.z())); 59 | } 60 | 61 | MinBoundingBox& MinBoundingBox::operator = (MinBoundingBox &box) 62 | { 63 | this->m_min = box.m_min; 64 | this->m_max = box.m_max; 65 | this->m_mean = box.m_mean; 66 | this->m_center = box.m_center; 67 | this->index = box.index; 68 | return *this; 69 | } 70 | void MinBoundingBox::nextPoint(QVector3D p) 71 | { 72 | if (!isValid(p)) 73 | { 74 | return; 75 | } 76 | setMinMax(p, m_min, m_max); 77 | index++; 78 | } 79 | 80 | bool MinBoundingBox::isContain(QVector3D point) 81 | { 82 | return ( point.x() <= m_max.x() && point.x() >= m_min.x() 83 | && point.y() <= m_max.y() && point.y() >= m_min.y() 84 | && point.z() <= m_max.z() && point.z() >= m_min.z()); 85 | } 86 | 87 | bool MinBoundingBox::isValid(QVector3D point) 88 | { 89 | if (abs(point.z())>m_finvalidDis || abs(point.y())>m_finvalidDis || abs(point.x())>m_finvalidDis) 90 | { 91 | return false; 92 | } 93 | return true; 94 | } 95 | 96 | -------------------------------------------------------------------------------- /MinBoundingBox.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | class MinBoundingBox 7 | { 8 | public: 9 | MinBoundingBox(void); 10 | ~MinBoundingBox(void); 11 | 12 | public: 13 | 14 | bool calculateMinBoundingBox(const std::vector& cloud); 15 | 16 | inline QVector3D getMinPoint() { return m_min; } 17 | inline QVector3D getMaxPoint() { return m_max; } 18 | inline QVector3D getMeanPoint() { return m_mean; } 19 | inline QVector3D getCenterPoint() { return m_center; } 20 | 21 | inline void firstPoint(QVector3D p) { m_min = m_max = m_mean= p; } 22 | inline float width(void) const { return m_max.x() - m_min.x(); } 23 | inline float height(void) const { return m_max.y() - m_min.y(); } 24 | inline float depth(void) const { return m_max.z() - m_min.z(); } 25 | float midX(void) const { return (m_min.x() + m_max.x()) / 2; } 26 | float midY(void) const { return (m_min.y() + m_max.y()) / 2; } 27 | float midZ(void) const { return (m_min.z() + m_max.z()) / 2; } 28 | inline void zerolize(void) { 29 | m_min = m_max = m_center = m_mean = QVector3D(0.0, 0.0, 0.0); 30 | index = 1; 31 | } 32 | inline void setMin(QVector3D point) { m_min = point; } 33 | inline void setMax(QVector3D point) { m_max = point; } 34 | 35 | inline bool Iszerolized() { 36 | return (abs(m_min.x()) < 0.00001 && abs(m_min.y()) < 0.00001 && abs(m_min.z()) < 0.00001 && 37 | abs(m_max.x()) < 0.00001 && abs(m_max.y()) < 0.00001 && abs(m_max.z()) < 0.00001); 38 | } 39 | 40 | inline void setMinMax(float x, float &min, float &max) 41 | { 42 | if (x > max) max = x; 43 | if (x < min) min = x; 44 | } 45 | void setMinMax(QVector3D point, QVector3D &min, QVector3D &max); 46 | void nextPoint(QVector3D p); 47 | 48 | MinBoundingBox& operator = (MinBoundingBox &box); 49 | private: 50 | int index; 51 | const float m_finvalidDis; 52 | QVector3D m_min; 53 | QVector3D m_max; 54 | QVector3D m_center; 55 | QVector3D m_mean; 56 | 57 | bool isContain(QVector3D point); 58 | bool isValid(QVector3D point); 59 | }; 60 | //end min bounding box 61 | 62 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include 3 | 4 | #include 5 | int main(int argc, char *argv[]) 6 | { 7 | QApplication a(argc, argv); 8 | //QSurfaceFormat format; 9 | // format.setDepthBufferSize(24); 10 | //QSurfaceFormat::setDefaultFormat(format); 11 | MainWindow w; 12 | w.show(); 13 | 14 | return a.exec(); 15 | } 16 | -------------------------------------------------------------------------------- /mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "ui_mainwindow.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | MainWindow::MainWindow(QWidget *parent) : 8 | QMainWindow(parent), 9 | ui(new Ui::MainWindow) 10 | { 11 | ui->setupUi(this); 12 | m_pOpenglWidget = new MyQOpenglWidget(ui->openGLWidget); 13 | m_pOpenglWidget->resize(ui->openGLWidget->width(),ui->openGLWidget->height()); 14 | } 15 | 16 | MainWindow::~MainWindow() 17 | { 18 | delete ui; 19 | } 20 | 21 | void MainWindow::on_pushButton_openfile_clicked() 22 | { 23 | // QString qfile = QFileDialog::getOpenFileName(this, 24 | // tr("Open PointCloud"), ".", 25 | // tr("ASC files(*.asc)")); 26 | 27 | std::vector cloud ; 28 | QString qfile = "E:\\test\\test.asc"; 29 | cloud= ReadVec3PointCloudASC(qfile); 30 | //unitMillimeter2UnitMeter(cloud); 31 | //saveVec3PointCloudASC("e:\\cloud.asc",cloud); 32 | //cloud = testData(180*10000); 33 | QTime startTime = QTime::currentTime(); 34 | m_pOpenglWidget->showPointCloud(cloud); 35 | qDebug() << "showPointCloud =" << startTime.msecsTo(QTime::currentTime()) << "ms"; 36 | } 37 | 38 | std::vector MainWindow::ReadVec3PointCloudASC(QString path) 39 | { 40 | std::vector cloud; 41 | QFile file(path); 42 | if (!file.open(QFile::ReadOnly | QIODevice::Text)) 43 | { 44 | qDebug() << "There is no asc file" ; 45 | return cloud; 46 | } 47 | QTextStream in(&file); 48 | QString ramData = in.readAll(); 49 | QStringList list = ramData.split("\n"); 50 | QStringList listline; 51 | cloud.resize(list.count()-1); 52 | for (int i = 0; i < list.count() - 1; i++) 53 | { 54 | listline = list.at(i).split(" "); 55 | if(listline.size()>=3) 56 | { 57 | cloud[i].setX((listline.at(0).toFloat())); 58 | cloud[i].setY((listline.at(1).toFloat())); 59 | cloud[i].setZ((listline.at(2).toFloat())); 60 | } 61 | } 62 | return cloud; 63 | } 64 | 65 | void MainWindow::saveVec3PointCloudASC(QString path, const std::vector& cloud) 66 | { 67 | QFile file(path); 68 | if (!file.open(QFile::WriteOnly | QIODevice::Text)) 69 | { 70 | qDebug() << "There is no asc file" ; 71 | return ; 72 | } 73 | QTextStream out(&file); 74 | for(int i = 0 ;i<(int)cloud.size();i++) 75 | { 76 | //unit Millimeter 2 Unit Meter 77 | out< &inOutCloud) 82 | { 83 | for(int i = 0;i<(int)inOutCloud.size();i++) 84 | { 85 | inOutCloud[i] /= 1000; 86 | } 87 | } 88 | 89 | std::vector MainWindow::testData(int pointsNum) 90 | { 91 | std::vector cloud; 92 | for (int i = 0; i < pointsNum; i++) 93 | { 94 | cloud.push_back(randomVec3f()); 95 | } 96 | return cloud; 97 | } 98 | 99 | QVector3D MainWindow::randomVec3f() 100 | { 101 | return QVector3D((float)(QRandomGenerator::global()->bounded(100)) / 2.0f - 102 | (float)(QRandomGenerator::global()->bounded(100)) / 2.0f, 103 | (float)(QRandomGenerator::global()->bounded(100)) / 2.0f - 104 | (float)(QRandomGenerator::global()->bounded(100)) / 2.0f, 105 | (float)(QRandomGenerator::global()->bounded(100)) / 10.0f - 106 | (float)(QRandomGenerator::global()->bounded(100)) / 10.0f); 107 | } 108 | -------------------------------------------------------------------------------- /mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | #include "myqopenglwidget.h" 6 | namespace Ui { 7 | class MainWindow; 8 | } 9 | 10 | class MainWindow : public QMainWindow 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit MainWindow(QWidget *parent = 0); 16 | ~MainWindow(); 17 | 18 | private slots: 19 | void on_pushButton_openfile_clicked(); 20 | 21 | private: 22 | Ui::MainWindow *ui; 23 | MyQOpenglWidget* m_pOpenglWidget; 24 | 25 | std::vector ReadVec3PointCloudASC(QString path); 26 | void saveVec3PointCloudASC(QString path,const std::vector& cloud); 27 | void unitMillimeter2UnitMeter(std::vector &inOutCloud); 28 | std::vector testData(int pointsNum); 29 | QVector3D randomVec3f(); 30 | }; 31 | 32 | #endif // MAINWINDOW_H 33 | -------------------------------------------------------------------------------- /mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 874 10 | 546 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 20 | 730 21 | 100 22 | 80 23 | 20 24 | 25 | 26 | 27 | 打开文件 28 | 29 | 30 | 31 | 32 | 33 | 720 34 | 140 35 | 113 36 | 20 37 | 38 | 39 | 40 | 41 | 42 | 43 | 720 44 | 180 45 | 113 46 | 20 47 | 48 | 49 | 50 | 51 | 52 | 53 | 20 54 | 10 55 | 691 56 | 471 57 | 58 | 59 | 60 | 0 61 | 62 | 63 | 64 | Tab 1 65 | 66 | 67 | 68 | 69 | Tab 2 70 | 71 | 72 | 73 | 74 | 30 75 | 20 76 | 631 77 | 391 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 0 88 | 0 89 | 874 90 | 22 91 | 92 | 93 | 94 | 95 | 96 | TopToolBarArea 97 | 98 | 99 | false 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /myqopenglwidget.cpp: -------------------------------------------------------------------------------- 1 | #include "myqopenglwidget.h" 2 | #include 3 | #include 4 | 5 | static const char *vertexShaderSource = 6 | "attribute highp vec3 posAttr;\n" 7 | "attribute lowp vec4 colAttr;\n" 8 | "varying lowp vec4 col;\n" 9 | "uniform highp mat4 matrix;\n" 10 | "void main() {\n" 11 | " col=colAttr;\n" 12 | " gl_Position=matrix * vec4(posAttr,1.0f);\n" 13 | "}\n"; 14 | 15 | static const char *fragmentShaderSource = 16 | "varying lowp vec4 col;\n" 17 | "void main() {\n" 18 | " gl_FragColor = col;\n" 19 | "}\n"; 20 | 21 | MyQOpenglWidget::MyQOpenglWidget(QWidget *parent) 22 | : QOpenGLWidget(parent) 23 | ,m_context(nullptr) 24 | ,m_Program(nullptr) 25 | //,m_VertexShader(nullptr) 26 | //,m_FragmentShader(nullptr) 27 | ,m_posAttr(0) 28 | ,m_colAttr(0) 29 | ,m_norAttr(0) 30 | ,m_matrixUniform(0) 31 | ,m_VBO(0) 32 | ,m_VAO(nullptr) 33 | ,m_scale(1.0f) 34 | ,m_bShowAxis(false) 35 | { 36 | m_Timer = new QTimer; 37 | m_context.reset(new QOpenGLContext()); 38 | m_Program.reset( new QOpenGLShaderProgram(this)); 39 | m_VertexShader.reset(new QOpenGLShader(QOpenGLShader::Vertex)); 40 | m_FragmentShader.reset( new QOpenGLShader(QOpenGLShader::Fragment)); 41 | m_VAO.reset(new QOpenGLVertexArrayObject()); 42 | 43 | m_PointsVertex = QVector(); 44 | ResetView(); 45 | for (GLuint i = 0; i < 6; ++i) { 46 | m_Axisindices[i] = i; 47 | } 48 | //this->grabKeyboard(); 49 | } 50 | 51 | MyQOpenglWidget::~MyQOpenglWidget() 52 | { 53 | 54 | } 55 | 56 | void MyQOpenglWidget::initializeGL() 57 | { 58 | makeCurrent(); 59 | bool binit = true; 60 | binit &= InitShader(); 61 | if (!binit) 62 | { 63 | return; 64 | } 65 | //OpenGLCore = new QOpenGLFunctions_4_3_Core(); 66 | initializeOpenGLFunctions(); 67 | glEnable(GL_DEPTH_TEST); 68 | 69 | m_VAO->create(); 70 | glGenBuffers(1, &m_VBO); 71 | glGenBuffers(1, &m_EBO); 72 | 73 | //init need import a point data 74 | initCloud(); 75 | changePointCloud(); 76 | 77 | QObject::connect(m_Timer, SIGNAL(timeout()), this, SLOT(onTimerOut())); 78 | m_Timer->start(30); 79 | } 80 | 81 | void MyQOpenglWidget::showPointCloud(const std::vector &cloud) 82 | { 83 | QTime startTime = QTime::currentTime(); 84 | initPointCloud(cloud); 85 | debugMsg("initPointCloud =",startTime); 86 | 87 | startTime = QTime::currentTime(); 88 | changePointCloud(); 89 | debugMsg("changePointCloud =",startTime); 90 | ResetView(); 91 | repaint(); 92 | } 93 | 94 | void MyQOpenglWidget::initPointCloud(const std::vector &cloud) 95 | { 96 | m_PointsVertex.clear(); 97 | m_PointsVertex.resize((int)cloud.size()+6); 98 | m_box.calculateMinBoundingBox(cloud); 99 | 100 | addAxisData(); 101 | 102 | for(int i = 0;i6){ 119 | for(int i =0 ; i<3;i++) 120 | { 121 | m_PointsVertex[2*i] = VertexInfo(); 122 | float color[4] = {0.0,0.0,0.0,1.0}; 123 | color[i] = 1.0; 124 | for (int j = 0;j<4;j++) { 125 | m_PointsVertex[2*i].color[j] = color[j]; 126 | m_PointsVertex[2*i+1].color[j] = color[j]; 127 | } 128 | float pos[3] = {0.0,0.0,0.0}; 129 | pos[i] = axisLength; 130 | for (int j = 0;j<3;j++) { 131 | m_PointsVertex[2*i+1].pos[j] = pos[j]; 132 | } 133 | } 134 | } 135 | } 136 | 137 | void MyQOpenglWidget::gray2Pseudocolor(const QVector3D pos,float color[4]) 138 | { 139 | float fmin = m_box.getMinPoint().z(); 140 | float fmax = m_box.getMaxPoint().z(); 141 | //int colortemp = (int)(((pos[2] - fmin) / (fmax - fmin)) * 255); 142 | int colortemp = (int)(((fmax- pos.z() ) / (fmax - fmin)) * 255); 143 | int r, g, b; 144 | if (colortemp >= 0 && colortemp < 64) 145 | { 146 | r = 0; 147 | g = 254 - 4 * colortemp; 148 | b = 255; 149 | }else if (colortemp >= 64 && colortemp < 128){ 150 | r = 0; 151 | g = 4 * colortemp - 254; 152 | b = 510 - 4 * colortemp; 153 | }else if (colortemp >= 128 && colortemp < 192){ 154 | r = 4 * colortemp - 510; 155 | g = 255; 156 | b = 0; 157 | } 158 | else if (colortemp >= 192 && colortemp <= 255) 159 | { 160 | r = 255; 161 | g = 1022 - 4 * colortemp; 162 | b = 0; 163 | }else{ 164 | r = 255; 165 | g = 255; 166 | b = 255; 167 | } 168 | color[0] = r*1.0f / 255; 169 | color[1] = g*1.0f / 255; 170 | color[2] = b*1.0f / 255; 171 | color[3] = 1.0f; 172 | } 173 | 174 | void MyQOpenglWidget::changePointCloud() 175 | { 176 | if(m_PointsVertex.size()<=0) 177 | { 178 | return ; 179 | } 180 | m_VAO->bind(); 181 | glBindBuffer(GL_ARRAY_BUFFER, m_VBO); 182 | glBufferData(GL_ARRAY_BUFFER, sizeof(VertexInfo)*(int)m_PointsVertex.size(), m_PointsVertex.data(), GL_DYNAMIC_DRAW); 183 | 184 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,m_EBO); 185 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(m_Axisindices), m_Axisindices, GL_DYNAMIC_DRAW); 186 | 187 | glEnableVertexAttribArray(m_posAttr); 188 | glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, sizeof(VertexInfo), (void*)(offsetof(VertexInfo, pos))); 189 | glEnableVertexAttribArray(m_colAttr); 190 | glVertexAttribPointer(m_colAttr, 4, GL_FLOAT, GL_FALSE, sizeof(VertexInfo), (void*)(offsetof(VertexInfo,color))); 191 | 192 | glBindBuffer(GL_ARRAY_BUFFER, 0); 193 | m_VAO->release(); 194 | } 195 | 196 | void MyQOpenglWidget::ResetView() 197 | { 198 | m_lineMove = QVector3D(); 199 | m_rotate = QQuaternion(); 200 | m_rotate *= QQuaternion::fromAxisAndAngle(QVector3D(0,0,1),180); 201 | m_rotationAxis = QVector3D(); 202 | m_scale = 1.0f; 203 | setBackgroundColor(QVector3D(0.2f,0.3f,0.3f)); 204 | } 205 | 206 | void MyQOpenglWidget::setBackgroundColor(QVector3D color) 207 | { 208 | m_backgroundColor= QVector4D(color,1.0f); 209 | } 210 | 211 | void MyQOpenglWidget::debugMsg(QString msg, QTime start) 212 | { 213 | qDebug() << msg << start.msecsTo(QTime::currentTime()) << "ms"; 214 | } 215 | 216 | void MyQOpenglWidget::resizeGL(int w, int h) 217 | { 218 | const qreal retinaScale = devicePixelRatio(); 219 | glViewport(0, 0, w * retinaScale, h * retinaScale); 220 | repaint(); 221 | } 222 | 223 | 224 | bool MyQOpenglWidget::InitShader() 225 | { 226 | bool success = true; 227 | success &= m_Program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource); 228 | success &= m_Program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource); 229 | success &= m_Program->link(); 230 | GetShaderUniformPara(); 231 | return success; 232 | } 233 | 234 | void MyQOpenglWidget::GetShaderUniformPara() 235 | { 236 | m_posAttr = m_Program->attributeLocation("posAttr"); 237 | m_colAttr = m_Program->attributeLocation("colAttr"); 238 | m_matrixUniform = m_Program->uniformLocation("matrix"); 239 | //m_norAttr = m_Program->attributeLocation("norAttr"); 240 | } 241 | 242 | void MyQOpenglWidget::paintGL() 243 | { 244 | makeCurrent(); 245 | m_Program->bind(); 246 | glClearColor(m_backgroundColor.x(), m_backgroundColor.y(), m_backgroundColor.z(), m_backgroundColor.w()); 247 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BITS); 248 | 249 | m_VAO->bind(); 250 | setMatrixUniform(); 251 | glDrawArrays(GL_POINTS, 6,(GLsizei ) m_PointsVertex.size()-6); 252 | if(m_bShowAxis){ 253 | glDrawElements(GL_LINES,6,GL_UNSIGNED_INT,0); 254 | } 255 | //glPointSize(2.0f); 256 | m_VAO->release(); 257 | m_Program->release(); 258 | } 259 | 260 | void MyQOpenglWidget::setMatrixUniform() 261 | { 262 | QMatrix4x4 matrix = QMatrix4x4(); 263 | QMatrix4x4 matrixPerspect= QMatrix4x4(); 264 | QMatrix4x4 matrixView= QMatrix4x4(); 265 | QMatrix4x4 matrixModel= QMatrix4x4(); 266 | 267 | QVector3D minPos = (m_box.getMinPoint()- m_box.getCenterPoint()); 268 | QVector3D maxPos = (m_box.getMaxPoint()- m_box.getCenterPoint()); 269 | float maxAxis; 270 | maxAxis =qAbs(qMax(qMax(m_box.depth(),m_box.width()),m_box.height())) ; 271 | 272 | //matrixPerspect.perspective(45.0f, m_width *1.0f/m_height, 0.1f, 2*maxAxis); 273 | matrixPerspect.ortho( 2*minPos[0],2*maxPos[0],2*minPos[1],2*maxPos[1],-2*maxAxis,2*maxAxis); 274 | 275 | matrixView.lookAt(QVector3D(0, 0, maxAxis),QVector3D(0.0,0.0,-1),QVector3D(0.0,1.0,0.0)); 276 | matrixView.translate(m_lineMove.x(),m_lineMove.y(),m_lineMove.z()); 277 | 278 | matrixModel.rotate(m_rotate); 279 | matrixModel.scale(m_scale); 280 | 281 | matrix = matrixPerspect*matrixView*matrixModel; 282 | m_Program->setUniformValue(m_matrixUniform, matrix); 283 | } 284 | 285 | void MyQOpenglWidget::initCloud() 286 | { 287 | m_PointsVertex.clear(); 288 | VertexInfo point; 289 | point.pos[0] =0.0f ; 290 | point.pos[1] =0.0f ; 291 | point.pos[2] =0.0f ; 292 | point.color[0] = m_backgroundColor.x(); 293 | point.color[1] = m_backgroundColor.y(); 294 | point.color[2] = m_backgroundColor.z(); 295 | point.color[3] = m_backgroundColor.w(); 296 | point.normal[0] = 0.0f; 297 | point.normal[1] = 1.0f; 298 | point.normal[2] = 0.0f; 299 | m_PointsVertex.push_back(point); 300 | } 301 | 302 | void MyQOpenglWidget::onTimerOut() 303 | { 304 | if(this->isVisible()) 305 | { 306 | repaint(); 307 | } 308 | } 309 | 310 | void MyQOpenglWidget::mousePressEvent(QMouseEvent *e) 311 | { 312 | if (e->buttons()&Qt::LeftButton || e->buttons()&Qt::MidButton) 313 | { 314 | setMouseTracking(true); 315 | m_lastPoint = QVector2D(e->localPos()); 316 | } 317 | } 318 | 319 | void MyQOpenglWidget::mouseMoveEvent(QMouseEvent *e) 320 | { 321 | if (e->buttons()&Qt::LeftButton) 322 | { 323 | Rotate(QVector2D(m_lastPoint), QVector2D(e->localPos())); 324 | } 325 | if (e->buttons()&Qt::MidButton) 326 | { 327 | LineMove(m_lastPoint, QVector2D(e->localPos())); 328 | } 329 | m_lastPoint = QVector2D(e->localPos()); 330 | } 331 | 332 | void MyQOpenglWidget::mouseReleaseEvent(QMouseEvent *e) 333 | { 334 | setMouseTracking(false); 335 | } 336 | 337 | void MyQOpenglWidget::wheelEvent(QWheelEvent *e) 338 | { 339 | if(e->delta() > 0){ 340 | modelZoomInOrOut(true); 341 | }else{ 342 | modelZoomInOrOut(false); 343 | } 344 | } 345 | 346 | void MyQOpenglWidget::keyPressEvent(QKeyEvent *e) 347 | { 348 | if (e->key() == Qt::Key_R) 349 | { 350 | ResetView(); 351 | //return; 352 | }else if ((e->key()== Qt::Key_C) && (e->modifiers() == Qt::ControlModifier)){ 353 | m_bShowAxis = !m_bShowAxis; 354 | } 355 | QWidget::keyPressEvent(e); 356 | } 357 | 358 | void MyQOpenglWidget::leaveEvent(QEvent *) 359 | { 360 | //不释放键盘事件抓取,会让编辑框无法输入 361 | releaseKeyboard(); 362 | } 363 | 364 | void MyQOpenglWidget::enterEvent(QEvent *) 365 | { 366 | grabKeyboard(); 367 | } 368 | 369 | GLuint MyQOpenglWidget::createGPUProgram(QString nVertexShaderFile, QString nFragmentShaderFile) 370 | { 371 | bool isOK = m_VertexShader->compileSourceFile(nVertexShaderFile); 372 | if (!isOK) 373 | { 374 | qDebug() << "compile vertex shader fail" ; 375 | return 0; 376 | } 377 | if (!m_FragmentShader->compileSourceFile(nFragmentShaderFile)) 378 | { 379 | qDebug() << "compile fragment shader fail"; 380 | return 0; 381 | } 382 | m_Program->addShader(m_VertexShader.get()); 383 | m_Program->addShader(m_FragmentShader.get()); 384 | m_Program->link(); 385 | GetShaderUniformPara(); 386 | return m_Program->programId(); 387 | } 388 | 389 | void MyQOpenglWidget::LineMove(QVector2D posOrgin, QVector2D posEnd) 390 | { 391 | float ratio =0.003f*sqrt(m_box.width()*m_box.height()) ; 392 | float xoffset = posEnd.x() - posOrgin.x(); 393 | float yoffset = posEnd.y() - posOrgin.y(); 394 | 395 | m_lineMove.setX(m_lineMove.x()+xoffset*ratio); 396 | m_lineMove.setY(m_lineMove.y()-yoffset*ratio); 397 | } 398 | 399 | void MyQOpenglWidget::Rotate(QVector2D posOrgin, QVector2D posEnd) 400 | { 401 | QVector2D diff = posEnd - posOrgin; 402 | qreal acc = diff.length() / 100.0; 403 | if (acc<0.01f) 404 | { 405 | return; 406 | } 407 | calRotation(posOrgin,posEnd); 408 | } 409 | 410 | void MyQOpenglWidget::modelZoomInOrOut(bool ZoomInOrOut) 411 | { 412 | if(ZoomInOrOut)//zoom in 413 | { 414 | m_scale*=1.1f; 415 | // if(m_scale>2.0f) 416 | // m_scale = 2.0f; 417 | }else{ //zoom out 418 | m_scale*=0.9f; 419 | if(m_scale<0.5f) 420 | m_scale = 0.5f; 421 | } 422 | } 423 | 424 | void MyQOpenglWidget::calRotation(QVector2D posOrgin, QVector2D posEnd) 425 | { 426 | QVector3D orginViewPos = pixelPosToViewPos(posOrgin); 427 | QVector3D endViewPos = pixelPosToViewPos(posEnd); 428 | float RotateAngle; 429 | RotateAngle = qRadiansToDegrees(std::acos(QVector3D::dotProduct(orginViewPos,endViewPos))); 430 | QVector3D axis; 431 | axis=QVector3D::crossProduct(orginViewPos, endViewPos); 432 | axis.normalize(); 433 | m_rotate= QQuaternion::fromAxisAndAngle(axis, RotateAngle)*m_rotate; 434 | } 435 | 436 | QVector3D MyQOpenglWidget::pixelPosToViewPos(const QVector2D &p) 437 | { 438 | QVector3D viewPos(2.0 * float(p.x()) / width() - 1.0, 439 | 1.0 - 2.0 * float(p.y()) / height(), 440 | 0); 441 | float sqrZ = 1 - QVector3D::dotProduct(viewPos, viewPos); 442 | if(sqrZ>0) 443 | { 444 | viewPos.setZ(std::sqrt(sqrZ)); 445 | }else{ 446 | viewPos.normalize(); 447 | } 448 | return viewPos; 449 | } 450 | 451 | 452 | 453 | -------------------------------------------------------------------------------- /myqopenglwidget.h: -------------------------------------------------------------------------------- 1 | #ifndef MYQOPENGLWIDGET_H 2 | #define MYQOPENGLWIDGET_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "MinBoundingBox.h" 20 | 21 | using namespace std; 22 | 23 | QT_BEGIN_NAMESPACE 24 | class QPainter; 25 | class QOpenGLContext; 26 | class QOpenGLPaintDevice; 27 | class QOpenGLShaderProgram; 28 | class QOpenGLShader; 29 | QT_END_NAMESPACE 30 | 31 | class MyQOpenglWidget: public QOpenGLWidget, protected QOpenGLFunctions 32 | { 33 | Q_OBJECT 34 | public: 35 | explicit MyQOpenglWidget(QWidget *parent = 0); 36 | ~MyQOpenglWidget(); 37 | void showPointCloud(const std::vector& cloud); 38 | virtual void resizeGL(int w, int h); 39 | void setBackgroundColor(QVector3D color); 40 | 41 | protected: 42 | virtual void initializeGL(void); 43 | virtual void paintGL(void); 44 | 45 | struct VertexInfo 46 | { 47 | float pos[3] = {0.0,0.0,0.0}; 48 | float normal[3] = {0.0,0.0,1.0}; 49 | float color[4] = {1.0,1.0,1.0,1.0}; 50 | }; 51 | private slots: 52 | void onTimerOut(void); 53 | virtual void mousePressEvent(QMouseEvent * e); 54 | virtual void mouseMoveEvent(QMouseEvent * e); 55 | virtual void mouseReleaseEvent(QMouseEvent * e); 56 | virtual void wheelEvent(QWheelEvent * e); 57 | virtual void keyPressEvent(QKeyEvent *e); 58 | virtual void leaveEvent(QEvent *); 59 | virtual void enterEvent(QEvent *); 60 | 61 | private: 62 | QTimer *m_Timer; 63 | QScopedPointer m_context; 64 | QScopedPointer m_Program; 65 | QScopedPointer m_VertexShader; 66 | QScopedPointer m_FragmentShader; 67 | 68 | // shader spara 69 | GLuint m_posAttr; 70 | GLuint m_colAttr; 71 | GLuint m_norAttr; 72 | GLuint m_matrixUniform; 73 | GLuint m_VBO; 74 | GLuint m_EBO; 75 | QScopedPointer m_VAO; 76 | QVector4D m_backgroundColor; 77 | 78 | //store points 79 | QVector m_PointsVertex; 80 | MinBoundingBox m_box; 81 | 82 | QVector3D m_lineMove; 83 | QQuaternion m_rotate; 84 | QVector3D m_rotationAxis; 85 | float m_scale; 86 | bool m_bShowAxis; 87 | GLuint m_Axisindices[6]; 88 | 89 | QVector2D m_lastPoint; 90 | 91 | GLuint createGPUProgram(QString nVertexShaderFile, QString nFragmentShaderFile); 92 | void GetShaderUniformPara(); 93 | bool InitShader(); 94 | 95 | void LineMove(QVector2D posOrgin, QVector2D posEnd); 96 | void Rotate(QVector2D posOrgin, QVector2D posEnd); 97 | void modelZoomInOrOut(bool ZoomInOrOut); 98 | QVector3D pixelPosToViewPos(const QVector2D& p); 99 | void calRotation(QVector2D posOrgin, QVector2D posEnd); 100 | void initPointCloud(const std::vector& cloud); 101 | void gray2Pseudocolor(const QVector3D pos, float color[4]); 102 | void changePointCloud(); 103 | void setMatrixUniform(); 104 | void ResetView(); 105 | void initCloud(); 106 | void addAxisData(); 107 | 108 | //debug 109 | void debugMsg(QString msg,QTime start); 110 | 111 | }; 112 | 113 | #endif // MYQOPENGLWIDGET_H 114 | -------------------------------------------------------------------------------- /openglwidget.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2020-01-07T10:45:46 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui 8 | 9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 10 | 11 | TARGET = openglwidget 12 | TEMPLATE = app 13 | 14 | # The following define makes your compiler emit warnings if you use 15 | # any feature of Qt which has been marked as deprecated (the exact warnings 16 | # depend on your compiler). Please consult the documentation of the 17 | # deprecated API in order to know how to port your code away from it. 18 | DEFINES += QT_DEPRECATED_WARNINGS 19 | 20 | # You can also make your code fail to compile if you use deprecated APIs. 21 | # In order to do so, uncomment the following line. 22 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 23 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 24 | 25 | 26 | SOURCES += \ 27 | main.cpp \ 28 | mainwindow.cpp \ 29 | MinBoundingBox.cpp \ 30 | myqopenglwidget.cpp 31 | 32 | HEADERS += \ 33 | mainwindow.h \ 34 | MinBoundingBox.h \ 35 | myqopenglwidget.h 36 | 37 | FORMS += \ 38 | mainwindow.ui 39 | -------------------------------------------------------------------------------- /openglwidget.pro.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {91123680-bbdc-40cf-8ed9-092094c1c831} 8 | 9 | 10 | ProjectExplorer.Project.ActiveTarget 11 | 0 12 | 13 | 14 | ProjectExplorer.Project.EditorSettings 15 | 16 | true 17 | false 18 | true 19 | 20 | Cpp 21 | 22 | CppGlobal 23 | 24 | 25 | 26 | QmlJS 27 | 28 | QmlJSGlobal 29 | 30 | 31 | 2 32 | UTF-8 33 | false 34 | 4 35 | false 36 | 80 37 | true 38 | true 39 | 1 40 | true 41 | false 42 | 0 43 | true 44 | true 45 | 0 46 | 8 47 | true 48 | 1 49 | true 50 | true 51 | true 52 | false 53 | 54 | 55 | 56 | ProjectExplorer.Project.PluginSettings 57 | 58 | 59 | -fno-delayed-template-parsing 60 | 61 | true 62 | 63 | 64 | 65 | ProjectExplorer.Project.Target.0 66 | 67 | Desktop Qt 5.13.2 MinGW 64-bit 68 | Desktop Qt 5.13.2 MinGW 64-bit 69 | qt.qt5.5132.win64_mingw73_kit 70 | 0 71 | 0 72 | 0 73 | 74 | G:/qtproject/build-openglwidget-Desktop_Qt_5_13_2_MinGW_64_bit-Debug 75 | 76 | 77 | true 78 | qmake 79 | 80 | QtProjectManager.QMakeBuildStep 81 | true 82 | 83 | false 84 | false 85 | false 86 | 87 | 88 | true 89 | Make 90 | 91 | Qt4ProjectManager.MakeStep 92 | 93 | false 94 | 95 | 96 | false 97 | 98 | 2 99 | Build 100 | 101 | ProjectExplorer.BuildSteps.Build 102 | 103 | 104 | 105 | true 106 | Make 107 | 108 | Qt4ProjectManager.MakeStep 109 | 110 | true 111 | clean 112 | 113 | false 114 | 115 | 1 116 | Clean 117 | 118 | ProjectExplorer.BuildSteps.Clean 119 | 120 | 2 121 | false 122 | 123 | Debug 124 | Debug 125 | Qt4ProjectManager.Qt4BuildConfiguration 126 | 2 127 | true 128 | 129 | 130 | G:/qtproject/build-openglwidget-Desktop_Qt_5_13_2_MinGW_64_bit-Release 131 | 132 | 133 | true 134 | qmake 135 | 136 | QtProjectManager.QMakeBuildStep 137 | false 138 | 139 | false 140 | false 141 | true 142 | 143 | 144 | true 145 | Make 146 | 147 | Qt4ProjectManager.MakeStep 148 | 149 | false 150 | 151 | 152 | false 153 | 154 | 2 155 | Build 156 | 157 | ProjectExplorer.BuildSteps.Build 158 | 159 | 160 | 161 | true 162 | Make 163 | 164 | Qt4ProjectManager.MakeStep 165 | 166 | true 167 | clean 168 | 169 | false 170 | 171 | 1 172 | Clean 173 | 174 | ProjectExplorer.BuildSteps.Clean 175 | 176 | 2 177 | false 178 | 179 | Release 180 | Release 181 | Qt4ProjectManager.Qt4BuildConfiguration 182 | 0 183 | true 184 | 185 | 186 | G:/qtproject/build-openglwidget-Desktop_Qt_5_13_2_MinGW_64_bit-Profile 187 | 188 | 189 | true 190 | qmake 191 | 192 | QtProjectManager.QMakeBuildStep 193 | true 194 | 195 | false 196 | true 197 | true 198 | 199 | 200 | true 201 | Make 202 | 203 | Qt4ProjectManager.MakeStep 204 | 205 | false 206 | 207 | 208 | false 209 | 210 | 2 211 | Build 212 | 213 | ProjectExplorer.BuildSteps.Build 214 | 215 | 216 | 217 | true 218 | Make 219 | 220 | Qt4ProjectManager.MakeStep 221 | 222 | true 223 | clean 224 | 225 | false 226 | 227 | 1 228 | Clean 229 | 230 | ProjectExplorer.BuildSteps.Clean 231 | 232 | 2 233 | false 234 | 235 | Profile 236 | Profile 237 | Qt4ProjectManager.Qt4BuildConfiguration 238 | 0 239 | true 240 | 241 | 3 242 | 243 | 244 | 0 245 | 部署 246 | 247 | ProjectExplorer.BuildSteps.Deploy 248 | 249 | 1 250 | Deploy Configuration 251 | 252 | ProjectExplorer.DefaultDeployConfiguration 253 | 254 | 1 255 | 256 | 257 | dwarf 258 | 259 | cpu-cycles 260 | 261 | 262 | 250 263 | -F 264 | true 265 | 4096 266 | false 267 | false 268 | 1000 269 | 270 | true 271 | 272 | false 273 | false 274 | false 275 | false 276 | true 277 | 0.01 278 | 10 279 | true 280 | kcachegrind 281 | 1 282 | 25 283 | 284 | 1 285 | true 286 | false 287 | true 288 | valgrind 289 | 290 | 0 291 | 1 292 | 2 293 | 3 294 | 4 295 | 5 296 | 6 297 | 7 298 | 8 299 | 9 300 | 10 301 | 11 302 | 12 303 | 13 304 | 14 305 | 306 | 2 307 | 308 | openglwidget 309 | 310 | Qt4ProjectManager.Qt4RunConfiguration:G:/qtproject/openglwidget/openglwidget.pro 311 | 312 | 3768 313 | false 314 | true 315 | true 316 | false 317 | false 318 | true 319 | 320 | G:/qtproject/build-openglwidget-Desktop_Qt_5_13_2_MinGW_64_bit-Debug 321 | 322 | 1 323 | 324 | 325 | 326 | ProjectExplorer.Project.TargetCount 327 | 1 328 | 329 | 330 | ProjectExplorer.Project.Updater.FileVersion 331 | 22 332 | 333 | 334 | Version 335 | 22 336 | 337 | 338 | --------------------------------------------------------------------------------