• opengl之鼠标拾取(五)


    我很懒,直接看代码吧,相信你没问题。

    头文件:

    #ifndef PICKENTITY_H
    #define PICKENTITY_H
    
    #include "base_render.h"
    #include <memory>
    namespace View3D{
    
    class PickEntity:public QObject, public BaseRender
    {
        Q_OBJECT
    public:
        PickEntity();
        ~PickEntity();
    
        void inputVertices(
                GLfloat* vertices_t,
                uint32_t num_t,
                GLuint* tri_indexs_t,
                uint32_t num_tri_t);
    
        inline void setDrawId(uint32_t id_t){
            m_draw_id = id_t;}
    
        virtual void entityInitializeGL() override;
        virtual void bindData() override;
        virtual void entityPaintGL() override;
    
    public slots:
        void rePicked(QPoint m_pos_t);
    
    
    public:
        int pickedID;
    
    private:
        uint32_t m_draw_id;
        GLfloat* vertices_ptr;
        uint32_t num_vertices;
        GLuint* indexes_ptr;
        uint32_t num_tri;
    
        QOpenGLShaderProgram pickingProgram;
        std::vector<GLuint> VBO, VAO, EBO;
        std::vector<uint32_t> num_tri_vect;
    
        QPoint mouse_pos;
        bool m_if_picked;
    
        bool redraw;
    };
    
    }
    
    #endif // PICKENTITY_H

    实现:

    #include "pick_entity.h"
    #include <sstream>
    namespace View3D{
    
    /*****************************************************/
    PickEntity::PickEntity():
        vertices_ptr(nullptr),
        num_vertices(0),
        indexes_ptr(nullptr),
        num_tri(0){
        colorset = QVector3D(1.0f, 0.2f, 1.0f);
        redraw = false;
        m_if_picked = false;
        mouse_pos.setX(0);
        mouse_pos.setY(0);
        pickedID = -1;
        m_draw_id = 0;
    }
    
    PickEntity::~PickEntity(){
        if(redraw)
        {
            for(int i = 0; i < VAO.size(); i++)
            {
                glDeleteVertexArrays(1, &(VAO[i]));
                glDeleteBuffers(1, &(VBO[i]));
                glDeleteBuffers(1, &(EBO[i]));
            }
        }
    }
    
    /*****************************************************/
    void PickEntity::inputVertices(
            GLfloat* vertices_t,
            uint32_t num_t,
            GLuint* tri_indexs_t,
            uint32_t num_tri_t){
    
        vertices_ptr = vertices_t;
        num_vertices = num_t;
        indexes_ptr = tri_indexs_t;
        num_tri = num_tri_t;
    
        num_tri_vect.push_back(num_tri);
    
        GLuint id_t(0);
        VBO.push_back(id_t);
        VAO.push_back(id_t);
        EBO.push_back(id_t);
    }
    
    /*****************************************************/
    void PickEntity::entityInitializeGL(){
        initializeOpenGLFunctions();
    
        // Create and compile our GLSL program from the shaders
        bool success = pickingProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/pick.vert");
        if (!success) {
           qDebug() << "shaderProgram addShaderFromSourceFile failed!" << pickingProgram.log();
           return;
        }
        success = pickingProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/pick.frag");
        if (!success) {
           qDebug() << "shaderProgram addShaderFromSourceFile failed!" << pickingProgram.log();
           return;
        }
        success = pickingProgram.link();
        if(!success) {
           qDebug() << "shaderProgram link failed!" << pickingProgram.log();
        }
    }
    
    /*****************************************************/
    void PickEntity::bindData()
    {
        //vao
        glGenVertexArrays(1, &VAO.back());
        glBindVertexArray(VAO.back());
    
        // Load it into a VBO
        //GLuint vertexbuffer;
        glGenBuffers(1, &VBO.back());
        glBindBuffer(GL_ARRAY_BUFFER, VBO.back());
        glBufferData(GL_ARRAY_BUFFER, num_vertices * sizeof(float), vertices_ptr, GL_STATIC_DRAW);
    
        // Generate a buffer for the indices as well
        //GLuint elementbuffer;
        glGenBuffers(1, &EBO.back());
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO.back());
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, num_tri * sizeof(unsigned int), indexes_ptr, GL_STATIC_DRAW);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*)0);
        glEnableVertexAttribArray(0);
    
        redraw = true;
    }
    
    /*****************************************************/
    void PickEntity::entityPaintGL(){
        pickingProgram.bind();
    
        // (Instead of picking each frame if the mouse button is down,
        // you should probably only check if the mouse button was just released)
        if (!m_if_picked){
    
            QMatrix4x4 MVP = projection * view * model;
            // Send our transformation to the currently bound shader,
            // in the "MVP" uniform
            pickingProgram.setUniformValue("MVP", MVP);
    
            for(int i = 0; i < VAO.size(); i++)
            {
                // Convert "i", the integer mesh ID, into an RGB color
                int r = (i & 0x000000FF) >>  0;
                int g = (i & 0x0000FF00) >>  8;
                int b = (i & 0x00FF0000) >> 16;
    
                // OpenGL expects colors to be in [0,1], so divide by 255. r/255.0f
                pickingProgram.setUniformValue("PickingColor", QVector4D(r/255.0f, g/255.0f, b/255.0f, 1.0f));
    
                glBindVertexArray(VAO[i]);
                // Draw the triangles !
                glDrawElements(GL_TRIANGLES, num_tri_vect[i], GL_UNSIGNED_INT, 0);
            }
    
            glFlush();
            glFinish();
    
            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
            unsigned char data[4];
            glReadPixels(mouse_pos.x(), Widget->height()-mouse_pos.y(), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
            //
            // Convert the color back to an integer ID
            pickedID = data[0] + data[1] * 256 + data[2] * 256 * 256;
            qDebug() << "Pixel:" << data[0]<<" "<< data[1] <<" "<<data[2];
    
            QString message("background");
            if (pickedID == 0x00ffffff){ // Full white, must be the background !
                message = "background";
            }else{
                std::stringstream ss;
                ss << "mesh " << pickedID;
                std::string rr = ss.str();
                message = QString::fromLocal8Bit(QByteArray::fromRawData(rr.c_str(), rr.size()));
            }
            qDebug() << "message:" << message << mouse_pos.x()<<" "<< mouse_pos.y();
        }
    
        pickingProgram.release();
        m_if_picked =false;
    }
    
    /*****************************************************/
    void PickEntity::rePicked(QPoint m_pos_t){
        mouse_pos.setX(m_pos_t.x());
        mouse_pos.setY(m_pos_t.y());
        m_if_picked = true;
    }
    
    
    }
  • 相关阅读:
    举荐一个源代码站—优越源代码
    [转载]如虎添翼Sybase数据库标题年夜搜罗2
    [转载]Sybase ASA中盘问元信息的几个常用SQL函数
    [转载]有关Sybase ASE数据库的滥觞
    [转载]Sybase ASA9/ASA10的运用体例
    [转载]Sybase数据库简介(初学者必看)(5)
    [转载]如虎添翼Sybase数据库效果大大包罗5
    [转载]Sybase数据库简介(初学者必看)(3)
    [转载]Sybase数据库简介(初学者必看)(2)
    [转载]Sybase数据库简介(初学者必看)(4)
  • 原文地址:https://www.cnblogs.com/lovebay/p/15608881.html
Copyright © 2020-2023  润新知