在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\n"); } //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\n",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] = '\0'; } else { printf("load file fail %s content len is 0\n", path); } fclose(pFile); return buffer; } else { printf("open file %s fail\n",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\n", 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\n", 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\n",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\n",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
最后的效果: