Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Can someone help me with this OpenGL code



  • I am trying to load a model and it is the first time. I want to apply 2 textures to my mesh. It is a computer monitor which is black. I edited the uv's in my .obj file so the screen is on the left and the other faces are on the right. I get these errors when I try to run it.

    cglwidget.obj:-1: error: LNK2019: unresolved external symbol __imp_glClear referenced in function "protected: virtual void __cdecl GLWidget::paintGL(void)" (?paintGL@GLWidget@@MEAAXXZ)
    glwidget.obj:-1: error: LNK2019: unresolved external symbol __imp_glClearColor referenced in function "protected: virtual void __cdecl GLWidget::paintGL(void)" (?paintGL@GLWidget@@MEAAXXZ)
    glwidget.obj:-1: error: LNK2019: unresolved external symbol __imp_glDrawElements referenced in function "protected: virtual void __cdecl GLWidget::paintGL(void)" (?paintGL@GLWidget@@MEAAXXZ)
    C:\Users\damon\Documents\QT\build-readinggl-Desktop_Qt_5_15_2_MSVC2015_64bit-Debug\debug\readinggl.exe:-1: error: LNK1120: 3 unresolved externals
    

    this is my glwidget.h file

    #ifndef GLWIDGET_H
    #define GLWIDGET_H
    
    #include <QtOpenGL/QGLWidget>
    #include <QOpenGLTexture>
    #include <QOpenGLFunctions>
    #include <QOpenGLBuffer>
    #include <QOpenGLShaderProgram>
    
    class GLWidget : public QGLWidget
    {
    public:
        explicit GLWidget(QWidget *parent = 0);
        void getfile();
        void setTexture(QImage img);
    
    protected:
        virtual void initializeGL();
        virtual void resizeGL(int w, int h);
        virtual void paintGL();
    
    
    private:
        void makeObject();
        void createShaders();
        const char *loadText(QString filaname);
        unsigned int *pasind1;
        unsigned int *pasind2;
        unsigned int passiz1;
        unsigned int passiz2;
        QOpenGLTexture *mytext = nullptr;
        QOpenGLTexture *blank = nullptr;
        QOpenGLBuffer vbo;
        QOpenGLShaderProgram *program = nullptr;
    };
    
    #endif // GLWIDGET_H
    
    

    this is my widget.cpp

    #include "glwidget.h"
    #include <QFile>
    #include "modelloader.h"
    GLWidget::GLWidget(QWidget *parent) :
        QGLWidget(parent)
    {
    
    }
    
    
    void GLWidget::initializeGL()
    {
        //glEnable(GL_DEPTH_TEST);
        //glEnable(GL_CULL_FACE);
    
    #define PROGRAM_VERTEX_ATTRIBUTE 0
    #define PROGRAM_TEXCOORD_ATTRIBUTE 1
        //initializeOpenGLFunctions();
        QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this);
        const char *vsrc = loadText("C:\\Users\\damon\\Documents\\QT\\readinggl\\simple.vert");
        vshader->compileSourceCode(vsrc);
    
        QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this);
        const char *fsrc = loadText("C:\\Users\\damon\\Documents\\QT\\readinggl\\simple.frag");
    
        fshader->compileSourceCode(fsrc);
    
        program = new QOpenGLShaderProgram;
        program->addShader(vshader);
        program->addShader(fshader);
        program->bindAttributeLocation("vertex", PROGRAM_VERTEX_ATTRIBUTE);
        program->bindAttributeLocation("texCoord", PROGRAM_TEXCOORD_ATTRIBUTE);
        program->link();
    
        program->bind();
        blank = new QOpenGLTexture(QImage(QString("C:\\Users\\damon\\Documents\\textures\\blanktex.png")));
        mytext = new QOpenGLTexture(QImage(QString("C:\\Users\\damon\\Documents\\textures\\blanktex.png")));
    
    
    }
    
    void GLWidget::resizeGL(int w, int h)
    {
    
    }
    
    void GLWidget::paintGL()
    {
        glClearColor(.5, .5, .5, 1.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        program->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE);
        program->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE);
    
        program->setAttributeBuffer(PROGRAM_VERTEX_ATTRIBUTE, GL_FLOAT, 0, 3, 5 * sizeof(GLfloat));
        program->setAttributeBuffer(PROGRAM_TEXCOORD_ATTRIBUTE, GL_FLOAT, 3 * sizeof(GLfloat), 2, 5 * sizeof(GLfloat));
        blank->bind();
        glDrawElements(GL_TRIANGLES, passiz1, GL_UNSIGNED_INT, &pasind1);
        //mytext->bind();
        //glDrawElements(GL_TRIANGLES, passiz2, GL_UNSIGNED_INT, pasind2);
    }
    
    void GLWidget::setTexture(QImage img)
    {
        mytext = new QOpenGLTexture(QImage(img));
    
    
    }
    
    void GLWidget::makeObject(){
        ModelLoader loader;
        bool loaded = loader.loadOBJ("C:\\Users\\damon\\Documents\\monitor.obj");
        int loc;
    
        if (loaded){
    
            QVector<int> indu1;
            QVector<int> indu2;
            Vertex curver;
            QVector<GLfloat> vertData;
            for (int i=0;i<loader.mVertices.size();i++){
                curver = loader.mVertices.at(i);
                vertData.push_back(curver.position.x);
                vertData.push_back(curver.position.y);
                vertData.push_back(curver.position.z);
                vertData.push_back(curver.texCoords.s);
                vertData.push_back(curver.texCoords.t);
                if (curver.isscrn){
                vertData.push_back(1);
                }else{
                vertData.push_back(0);
                }
            }
            vbo.create();
            vbo.bind();
            vbo.allocate(vertData.constData(), vertData.count() * sizeof(GLfloat));
            for (int i = 0;i < loader.indu.size();i++){
                loc = loader.indu.at(i);
    
                if (loader.mVertices.at(loc).isscrn){
                    indu2.push_back(loc);
                }else{
                    indu1.push_back(loc);
                }
            }
            passiz1 = indu1.size();
            pasind1 = new unsigned int[passiz1];
            for (int i = 0;i < indu1.size();i++) pasind1[i] = indu1.at(i);
            passiz2 = indu2.size();
            pasind2 = new unsigned int[passiz2];
            for (int i = 0;i < indu2.size();i++) pasind2[i] = indu2.at(i);
        }
    }
    
    void GLWidget::createShaders(){
    
    }
    
    const char *GLWidget::loadText(QString filename)
    {
        QString theText = "";
        QFile fil(filename);
        if (!fil.open(QFile::ReadOnly | QFile::Text)){
    
        }
        QTextStream inp(&fil);
        theText = inp.readAll();
        fil.close();
        const char *rets = theText.toStdString().c_str();
        return rets;
    }
    
    

    the modelloader.h

    #ifndef MODELLOADER_H
    #define MODELLOADER_H
    #include <assimp/Importer.hpp> // C++ importer interface
    #include <assimp/scene.h> // Output data structure
    #include <assimp/postprocess.h>
    #include <QtCore>
    #include <sstream>
    #include <fstream>
    struct vec3{
        float x, y, z;
    };
    
    struct vec2{
        float s, t;
    };
    
    struct Vertex{
        vec3 position;
        vec2 texCoords;
        bool isscrn;
    };
    
    class ModelLoader
    {
    public:
        ModelLoader();
        float *calculateNormal(float *coord1, float *coord2, float *coord3);
        bool DoTheImportThing( const std::string& pFile);
        bool loadOBJ(const std::string& filename);
        QString error;
        QVector<int> indu;
        QVector<vec3> norms;
    
        QVector<Vertex> mVertices;
    };
    
    #endif // MODELLOADER_H
    
    

    my modelloader.cpp

    #include "modelloader.h"
    #include <math.h>
    ModelLoader::ModelLoader()
    {
    
    }
    
    float *ModelLoader::calculateNormal(float *coord1, float *coord2, float *coord3)
    {
        float va[3], vb[3], vr[3], val;
        float *norm = new float[3];
        va[0] = coord1[0] - coord2[0];
        va[1] = coord1[1] - coord2[1];
        va[2] = coord1[2] - coord2[2];
    
        vb[0] = coord1[0] - coord3[0];
        vb[1] = coord1[1] - coord3[1];
        vb[2] = coord1[2] - coord3[2];
    
        /* cross product */
        vr[0] = va[1] * vb[2] - vb[1] * va[2];
        vr[1] = vb[0] * va[2] - va[0] * vb[2];
        vr[2] = va[0] * vb[1] - vb[0] * va[1];
    
        /* normalization factor */
        val = sqrt( vr[0]*vr[0] + vr[1]*vr[1] + vr[2]*vr[2] );
    
    
        norm[0] = vr[0]/val;
        norm[1] = vr[1]/val;
        norm[2] = vr[2]/val;
    
        return norm;
    }
    bool ModelLoader::loadOBJ(const std::string& filename)
    {
        std::vector<unsigned int> vertexIndices, uvIndices;
        std::vector<vec3> tempVertices;
        std::vector<vec2> tempUVs;
        float coor1[3];
        float coor2[3];
        float coor3[3];
        float *norm;
        vec3 tempn;
        indu.clear();
        norms.clear();
        mVertices.clear();
        if (filename.find(".obj") != std::string::npos)
        {
            std::ifstream fin(filename, std::ios::in);
            if (!fin)
            {
                error = "Cannot open " + QString::fromStdString(filename);
                return false;
            }
    
    
    
            std::string lineBuffer;
            while (std::getline(fin, lineBuffer))
            {
                if (lineBuffer.substr(0, 2) == "v ")
                {
                    std::istringstream v(lineBuffer.substr(2));
                    vec3 vertex;
                    v >> vertex.x; v >> vertex.y; v >> vertex.z;
                    tempVertices.push_back(vertex);
                }
                else if (lineBuffer.substr(0, 2) == "vt")
                {
                    std::istringstream vt(lineBuffer.substr(3));
                    vec2 uv;
                    vt >> uv.s; vt >> uv.t;
                    tempUVs.push_back(uv);
                }
                else if (lineBuffer.substr(0, 2) == "f ")
                {
                    int p1, p2, p3; //to store mesh index
                    int t1, t2, t3; //to store texture index
                    int n1, n2, n3;
                    const char* face = lineBuffer.c_str();
                    int match = sscanf_s(face, "f %i/%i/%i %i/%i/%i %i/%i/%i",
                        &p1, &t1, &n1,
                        &p2, &t2, &n2,
                        &p3, &t3, &n3);
                    if (match != 9){
                        error = "Failed to parse OBJ file using our very simple OBJ loader";
                        return false;
                    }
                    // We are ignoring normals (for now)
    
                    vertexIndices.push_back(p1);
                    vertexIndices.push_back(p2);
                    vertexIndices.push_back(p3);
    
                    uvIndices.push_back(t1);
                    uvIndices.push_back(t2);
                    uvIndices.push_back(t3);
                }
            }
    
            // Close the file
            fin.close();
    
    
            // For each vertex of each triangle
            for (unsigned int i = 0; i < vertexIndices.size(); i++)
            {
                // Get the attributes using the indices
                vec3 vertex = tempVertices[vertexIndices[i] - 1];
                vec2 uv = tempUVs[uvIndices[i] - 1];
    
                Vertex meshVertex;
                meshVertex.position = vertex;
                meshVertex.texCoords = uv;
                meshVertex.isscrn = false;
                mVertices.push_back(meshVertex);
                indu.push_back(vertexIndices[i]);
            }
            for (int i = 0;i < int(mVertices.size() / 3);i++){
                coor1[0] = mVertices.at(i * 3).position.x;
                coor1[1] = mVertices.at(i * 3).position.y;
                coor1[2] = mVertices.at(i * 3).position.z;
                coor2[0] = mVertices.at(i * 3 + 1).position.x;
                coor2[1] = mVertices.at(i * 3 + 1).position.y;
                coor2[2] = mVertices.at(i * 3 + 1).position.z;
                coor3[0] = mVertices.at(i * 3 + 2).position.x;
                coor3[1] = mVertices.at(i * 3 + 2).position.y;
                coor3[2] = mVertices.at(i * 3 + 2).position.z;
                norm = calculateNormal(coor1, coor2, coor3);
                tempn.x = norm[0];
                tempn.y = norm[1];
                tempn.z = norm[2];
                norms.push_back(tempn);
            }
    
    
    
    
            return true;
        }
    
        // We shouldn't get here so return failure
        return false;
    }
    /*
    bool ModelLoader::DoTheImportThing( const std::string& pFile) {
    // Create an instance of the Importer class
    Assimp::Importer importer;
    // And have it read the given file with some example postprocessing
    // Usually - if speed is not the most important aspect for you - you'll
    // probably to request more postprocessing than we do in this example.
    const aiScene* scene = importer.ReadFile( pFile,
    aiProcess_CalcTangentSpace |
    aiProcess_Triangulate |
    aiProcess_JoinIdenticalVertices |
    aiProcess_SortByPType);
    // If the import failed, report it
    if( !scene) {
        error = importer.GetErrorString();
    return false;
    }
    // Now we can access the file's contents.
    //DoTheSceneProcessing( scene);
    
    aiMesh *mymeshes;
    aiVector3D pos;
    aiVector3D normal;
    float texco;
    aiColor4D color;
    float coor1[3];
    float coor2[3];
    float coor3[3];
    float *norm;
    int refp;
    for(int i=0;i < scene->mNumMeshes;i++){
        aiMesh* mesh = scene->mMeshes[i];
        int iMeshFaces = mesh->mNumFaces;
        for (int j=0;j < iMeshFaces;j++){
            const aiFace& face = mesh->mFaces[j];
    
            for (int k=0;k<3;k++){
                indu.push_back(face.mIndices[k]);
                pos = mesh->mVertices[face.mIndices[k]];
                vert_x.push_back(pos.x);
                vert_y.push_back(pos.y);
                vert_z.push_back(pos.z);
    
                //color = scene->mMeshes[i]->mColors[i][j];
                tex_x.push_back(mesh->mTextureCoords[0][j * 3 + k].x);
                tex_y.push_back(mesh->mTextureCoords[0][j * 3 + k].y);
            }
            refp = vert_x.size() - 1;
            coor1[0] = vert_x.at(refp - 2);
            coor1[1] = vert_y.at(refp - 2);
            coor1[2] = vert_z.at(refp - 2);
            coor2[0] = vert_x.at(refp - 1);
            coor2[1] = vert_y.at(refp - 1);
            coor2[2] = vert_z.at(refp - 1);
            coor3[0] = vert_x.at(refp);
            coor3[1] = vert_y.at(refp);
            coor3[2] = vert_z.at(refp);
            norm = calculateNormal(coor1, coor2, coor3);
            norm_x.push_back(norm[0]);
            norm_y.push_back(norm[1]);
            norm_z.push_back(norm[2]);
        }
    }
    // We're done. Everything will be cleaned up by the importer destructor
    return true;
    }
    */
    

    the vertex shader

    attribute vec3 qt_Vertex;
    attribute vec2 qt_MultiTexCoord0;
    
    
    varying vec4 qt_TexCoord0;
    
    void main(void)
    {
        gl_Position = qt_Vertex;
        qt_TexCoord0 = qt_MultiTexCoord0;
    }
    
    

    and the fragment shader

    uniform sampler2D qt_Texture0;
    varying vec4 qt_TexCoord0;
    
    void main(void)
    {
        gl_FragColor = texture2D(qt_Texture0, qt_TexCoord0.st);
    }
    
    

  • Moderators

    @AI_Messiah said in Can someone help me with this OpenGL code:

    I get these errors when I try to run it.

    These are link errors, you don't even get to the point of running anything. Firstly do switch to QOpenGLWidget instead of the deprecated class you use.


Log in to reply