QT_OPENGL-------- 5.model

在qt中实现opengl obj模型导入:

main.cpp

#include<GL/glew.h>
#include <GLFW/glfw3.h>
#include<stdio.h>
#include<glm/glm.hpp>
#include<glm/ext.hpp>
#include"misc.h"
#include"model.h"
GLfloat deltaTime = 0.0f;
GLfloat lastFrame = 0.0f;


GLint CreateGPUProgram(const char*vsShaderPath,const char*fsShaderPath)
{
    GLuint vsShader=glCreateShader(GL_VERTEX_SHADER);
    GLuint fsShader=glCreateShader(GL_FRAGMENT_SHADER);
    const char*vsCode=LoadFileContent(vsShaderPath);
    const char*fsCode=LoadFileContent(fsShaderPath);
    glShaderSource(vsShader,1,&vsCode,nullptr);
    glShaderSource(fsShader,1,&fsCode,nullptr);
    glCompileShader(vsShader);
    glCompileShader(fsShader);
    GLuint program=glCreateProgram();
    glAttachShader(program,vsShader);
    glAttachShader(program,fsShader);
    glLinkProgram(program);
    glDetachShader(program,vsShader);
    glDetachShader(program,fsShader);
    glDeleteShader(vsShader);
    glDeleteShader(fsShader);
    return program;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    glViewport(0, 0, width, height);
}
int main(void)
{
    GLFWwindow* window;


    if (!glfwInit())
        return -1;

    window = glfwCreateWindow(480, 320, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glewExperimental = GL_TRUE;
    // 还需要注册这个函数,告诉GLFW我们希望每当窗口调整大小的时候调用这个函数。
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

    glewInit();
    GLuint program = CreateGPUProgram("/home/jun/OpenGL/model/sample.vs", "/home/jun/OpenGL/model/sample.fs");
    GLint posLocation, texcoordLocation,normalLocation, MLocation, VLocation, PLocation;
    posLocation = glGetAttribLocation(program, "pos");
    texcoordLocation = glGetAttribLocation(program, "texcoord");
    normalLocation = glGetAttribLocation(program, "normal");

    MLocation = glGetUniformLocation(program, "M");
    VLocation = glGetUniformLocation(program, "V");
    PLocation = glGetUniformLocation(program, "P");


    unsigned int *indexes = nullptr;
    int vertexCount = 0, indexCount = 0;
    VertexData*vertexes = LoadObjModel("/home/jun/OpenGL/model/MODEL/niutou.obj", &indexes, vertexCount, indexCount);
    if (vertexes==nullptr)
    {
        printf("load obj model fail
");
    }
    //obj model -> vbo & ibo
    GLuint vbo = CreateBufferObject(GL_ARRAY_BUFFER, sizeof(VertexData) * vertexCount, GL_STATIC_DRAW, vertexes);
    GLuint ibo = CreateBufferObject(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * indexCount, GL_STATIC_DRAW, indexes);
    printf("vertex count %d index count %d
",vertexCount,indexCount);

    glClearColor(41.0f / 255.0f, 71.0f / 255.0f, 121.0f / 255.0f, 1.0f);

    //ShowWindow(hwnd, SW_SHOW);
    //UpdateWindow(hwnd);

    float identity[] = {
        1,0,0,0,
        0,1,0,0,
        0,0,1,0,
        0,0,0,1
    };
   //创建一个投影矩阵
   glm::mat4 model;
   model = glm::translate(model, glm::vec3(0.0f, 0.0f, -54.0f));
    model = glm::scale(model, glm::vec3(0.2f, 0.2f, 0.2f));
   glm::mat4 projection=glm::perspective(45.0f,800.0f/600.0f,0.1f,1000.0f);


   glEnable(GL_DEPTH_TEST);
   glEnable(GL_CULL_FACE);

    while (!glfwWindowShouldClose(window))
    {
        GLfloat currentFrame = (GLfloat)glfwGetTime();
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;
        glfwPollEvents();

       // glClearColor(1.0f, 0.04f, 0.14f, 1.0f);

        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
        glUseProgram(program);
        glUniformMatrix4fv(MLocation, 1, GL_FALSE, glm::value_ptr(model));
        glUniformMatrix4fv(VLocation, 1, GL_FALSE, identity);
        glUniformMatrix4fv(PLocation, 1, GL_FALSE, glm::value_ptr(projection));

        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glEnableVertexAttribArray(posLocation);
        glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)0);
        glEnableVertexAttribArray(texcoordLocation);
        glVertexAttribPointer(texcoordLocation, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)(sizeof(float) * 3));
        glEnableVertexAttribArray(normalLocation);
        glVertexAttribPointer(normalLocation, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)(sizeof(float) * 5));

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
        glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
        glUseProgram(0);
        glfwSwapBuffers(window);


    }

    glfwTerminate();
    return 0;
}

mish.h

#include<GL/glew.h>
GLuint CreateBufferObject(GLenum bufferType, GLsizeiptr size, GLenum usage, void*data = nullptr);
char *LoadFileContent(const char*path);

mish.cpp

#include "misc.h"
#include <stdio.h>

GLuint CreateBufferObject(GLenum bufferType, GLsizeiptr size, GLenum usage, void*data /* = nullptr */)
{
    GLuint object;
    glGenBuffers(1, &object);
    glBindBuffer(bufferType, object);
    glBufferData(bufferType, size, data, usage);
    glBindBuffer(bufferType, 0);
    return object;
}


char *LoadFileContent(const char*path)
{
    FILE*pFile = fopen(path, "rb");
    if (pFile)
    {
        fseek(pFile, 0, SEEK_END);
        int nLen = ftell(pFile);
        char*buffer = nullptr;
        if (nLen!=0)
        {
            buffer=new char[nLen + 1];
            rewind(pFile);
            fread(buffer, nLen, 1, pFile);
            buffer[nLen] = '';
        }
        else
        {
            printf("load file fail %s content len is 0
", path);
        }
        fclose(pFile);
        return buffer;
    }
    else
    {
        printf("open file %s fail
",path);
    }
    fclose(pFile);
    return nullptr;
}

model.h

struct VertexData
{
    float position[3];
    float texcoord[2];
    float normal[3];
};

VertexData*LoadObjModel(const char* filePath,unsigned int **indexes,int&vertexCount,int&indexCount);

model.cpp

#include "model.h"
#include "misc.h"
#include <stdio.h>
#include <string.h>
#include <sstream>
#include <vector>

VertexData*LoadObjModel(const char* filePath, unsigned int **indexes, int&vertexCount, int&indexCount)
{
    char*fileContent = LoadFileContent(filePath);
    if (fileContent!=nullptr)
    {
        //obj model decode
        struct VertexInfo
        {
            float v[3];
        };

        struct VertexDefine
        {
            int positionIndex;
            int texcoordIndex;
            int normalIndex;
        };
        std::vector<VertexInfo> positions;
        std::vector<VertexInfo> texcoords;
        std::vector<VertexInfo> normals;

        std::vector<unsigned int> objIndexes;// -> opengl indexes
        std::vector<VertexDefine> vertices;// -> opengl vertexes

        std::stringstream ssObjFile(fileContent);
        char szOneLine[256];
        std::string temp;
        while (!ssObjFile.eof())
        {
            memset(szOneLine, 0, 256);
            ssObjFile.getline(szOneLine,256);
            if (strlen(szOneLine)>0)
            {
                std::stringstream ssOneLine(szOneLine);

                if (szOneLine[0]=='v')
                {
                    if (szOneLine[1]=='t')
                    {
                        //vertex coord
                        ssOneLine >> temp;
                        VertexInfo vi;
                        ssOneLine >> vi.v[0];
                        ssOneLine >> vi.v[1];
                        texcoords.push_back(vi);
                        printf("%s %f,%f
", temp.c_str(), vi.v[0], vi.v[1]);
                    }
                    else if(szOneLine[1]=='n')
                    {
                        //normal
                        ssOneLine >> temp;
                        VertexInfo vi;
                        ssOneLine >> vi.v[0];
                        ssOneLine >> vi.v[1];
                        ssOneLine >> vi.v[2];
                        normals.push_back(vi);
                        printf("%s %f,%f,%f
", temp.c_str(), vi.v[0], vi.v[1], vi.v[2]);
                    }
                    else
                    {
                        //position
                        ssOneLine >> temp;
                        VertexInfo vi;
                        ssOneLine >> vi.v[0];
                        ssOneLine >> vi.v[1];
                        ssOneLine >> vi.v[2];
                        positions.push_back(vi);
                        printf("%s %f,%f,%f
",temp.c_str(), vi.v[0], vi.v[1], vi.v[2]);
                    }
                }
                else if (szOneLine[0] == 'f')
                {
                    //face
                    ssOneLine >> temp;// 'f'
                    std::string vertexStr;
                    for (int i=0;i<3;i++)
                    {
                        ssOneLine >> vertexStr;
                        size_t pos = vertexStr.find_first_of('/');
                        std::string positionIndexStr = vertexStr.substr(0, pos);
                        size_t pos2 = vertexStr.find_first_of('/', pos + 1);
                        std::string texcoordIndexStr = vertexStr.substr(pos + 1, pos2 - pos - 1);
                        std::string normalIndexStr = vertexStr.substr(pos2 + 1, vertexStr.length() - pos2 - 1);
                        VertexDefine vd;
                        vd.positionIndex = atoi(positionIndexStr.c_str())-1;
                        vd.texcoordIndex = atoi(texcoordIndexStr.c_str()) - 1;
                        vd.normalIndex = atoi(normalIndexStr.c_str()) - 1;

                        int nCurrentIndex = -1;//indexes
                        //check if exist
                        size_t nCurrentVerticeCount = vertices.size();
                        for (size_t j = 0; j < nCurrentVerticeCount; j++)
                        {
                            if (vertices[j].positionIndex == vd.positionIndex&&
                                vertices[j].texcoordIndex == vd.texcoordIndex&&
                                vertices[j].normalIndex == vd.normalIndex)
                            {
                                nCurrentIndex = j;
                                break;
                            }
                        }
                        if (nCurrentIndex==-1)
                        {
                            //create new vertice
                            nCurrentIndex = vertices.size();
                            vertices.push_back(vd);//vertexes define
                        }
                        objIndexes.push_back(nCurrentIndex);
                    }
                }
            }
        }
        printf("face count %u
",objIndexes.size()/3);
        //objIndexes->indexes buffer -> ibo
        indexCount = (int)objIndexes.size();
        *indexes = new unsigned int[indexCount];
        for (int i=0;i<indexCount;i++)
        {
            (*indexes)[i] = objIndexes[i];
        }
        //vertices -> vertexes -> vbo
        vertexCount = (int)vertices.size();
        VertexData*vertexes = new VertexData[vertexCount];
        for (int i=0;i<vertexCount;++i)
        {
            memcpy(vertexes[i].position, positions[vertices[i].positionIndex].v, sizeof(float) * 3);
            memcpy(vertexes[i].texcoord, texcoords[vertices[i].texcoordIndex].v, sizeof(float) * 2);
            memcpy(vertexes[i].normal, normals[vertices[i].normalIndex].v, sizeof(float) * 3);
        }
        return vertexes;
    }
    return nullptr;
}

model.pro

TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle
CONFIG -= qt

SOURCES += main.cpp 
    misc.cpp 
    model.cpp

LIBS+= -L/usr/lib64 -lGLEW
LIBS +=-L/usr/local/lib -lglfw3 -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lGL -lpthread -ldl

HEADERS += 
    misc.h 
    model.h

最后的效果:

原文地址:https://www.cnblogs.com/fuhang/p/10037953.html