在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,,&vsCode,nullptr);
glShaderSource(fsShader,,&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(, , width, height);
}
int main(void)
{
GLFWwindow* window; if (!glfwInit())
return -; window = glfwCreateWindow(, , "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -;
}
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 = , indexCount = ;
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[] = {
,,,,
,,,,
,,,,
,,,
};
//创建一个投影矩阵
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, , GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(VLocation, , GL_FALSE, identity);
glUniformMatrix4fv(PLocation, , GL_FALSE, glm::value_ptr(projection)); glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArray(posLocation);
glVertexAttribPointer(posLocation, , GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*));
glEnableVertexAttribArray(texcoordLocation);
glVertexAttribPointer(texcoordLocation, , GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)(sizeof(float) * ));
glEnableVertexAttribArray(normalLocation);
glVertexAttribPointer(normalLocation, , GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)(sizeof(float) * )); glBindBuffer(GL_ARRAY_BUFFER, );
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, );
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, );
glUseProgram();
glfwSwapBuffers(window); } glfwTerminate();
return ;
}

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(, &object);
glBindBuffer(bufferType, object);
glBufferData(bufferType, size, data, usage);
glBindBuffer(bufferType, );
return object;
} char *LoadFileContent(const char*path)
{
FILE*pFile = fopen(path, "rb");
if (pFile)
{
fseek(pFile, , SEEK_END);
int nLen = ftell(pFile);
char*buffer = nullptr;
if (nLen!=)
{
buffer=new char[nLen + ];
rewind(pFile);
fread(buffer, nLen, , 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[];
float texcoord[];
float normal[];
}; 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[];
}; 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[];
std::string temp;
while (!ssObjFile.eof())
{
memset(szOneLine, , );
ssObjFile.getline(szOneLine,);
if (strlen(szOneLine)>)
{
std::stringstream ssOneLine(szOneLine); if (szOneLine[]=='v')
{
if (szOneLine[]=='t')
{
//vertex coord
ssOneLine >> temp;
VertexInfo vi;
ssOneLine >> vi.v[];
ssOneLine >> vi.v[];
texcoords.push_back(vi);
printf("%s %f,%f\n", temp.c_str(), vi.v[], vi.v[]);
}
else if(szOneLine[]=='n')
{
//normal
ssOneLine >> temp;
VertexInfo vi;
ssOneLine >> vi.v[];
ssOneLine >> vi.v[];
ssOneLine >> vi.v[];
normals.push_back(vi);
printf("%s %f,%f,%f\n", temp.c_str(), vi.v[], vi.v[], vi.v[]);
}
else
{
//position
ssOneLine >> temp;
VertexInfo vi;
ssOneLine >> vi.v[];
ssOneLine >> vi.v[];
ssOneLine >> vi.v[];
positions.push_back(vi);
printf("%s %f,%f,%f\n",temp.c_str(), vi.v[], vi.v[], vi.v[]);
}
}
else if (szOneLine[] == 'f')
{
//face
ssOneLine >> temp;// 'f'
std::string vertexStr;
for (int i=;i<;i++)
{
ssOneLine >> vertexStr;
size_t pos = vertexStr.find_first_of('/');
std::string positionIndexStr = vertexStr.substr(, pos);
size_t pos2 = vertexStr.find_first_of('/', pos + );
std::string texcoordIndexStr = vertexStr.substr(pos + , pos2 - pos - );
std::string normalIndexStr = vertexStr.substr(pos2 + , vertexStr.length() - pos2 - );
VertexDefine vd;
vd.positionIndex = atoi(positionIndexStr.c_str())-;
vd.texcoordIndex = atoi(texcoordIndexStr.c_str()) - ;
vd.normalIndex = atoi(normalIndexStr.c_str()) - ; int nCurrentIndex = -;//indexes
//check if exist
size_t nCurrentVerticeCount = vertices.size();
for (size_t j = ; j < nCurrentVerticeCount; j++)
{
if (vertices[j].positionIndex == vd.positionIndex&&
vertices[j].texcoordIndex == vd.texcoordIndex&&
vertices[j].normalIndex == vd.normalIndex)
{
nCurrentIndex = j;
break;
}
}
if (nCurrentIndex==-)
{
//create new vertice
nCurrentIndex = vertices.size();
vertices.push_back(vd);//vertexes define
}
objIndexes.push_back(nCurrentIndex);
}
}
}
}
printf("face count %u\n",objIndexes.size()/);
//objIndexes->indexes buffer -> ibo
indexCount = (int)objIndexes.size();
*indexes = new unsigned int[indexCount];
for (int i=;i<indexCount;i++)
{
(*indexes)[i] = objIndexes[i];
}
//vertices -> vertexes -> vbo
vertexCount = (int)vertices.size();
VertexData*vertexes = new VertexData[vertexCount];
for (int i=;i<vertexCount;++i)
{
memcpy(vertexes[i].position, positions[vertices[i].positionIndex].v, sizeof(float) * );
memcpy(vertexes[i].texcoord, texcoords[vertices[i].texcoordIndex].v, sizeof(float) * );
memcpy(vertexes[i].normal, normals[vertices[i].normalIndex].v, sizeof(float) * );
}
return vertexes;
}
return nullptr;
}

model.pro

TEMPLATE = app
CONFIG += console c++
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

最后的效果:

QT_OPENGL-------- 5.model的更多相关文章

  1. Spring Boot笔记一

    Spring Boot 入门 Spring Boot 简介 > 简化Spring应用开发的一个框架:> 整个Spring技术栈的一个大整合:> J2EE开发的一站式解决方案: 微服务 ...

  2. 【疯狂造轮子-iOS】JSON转Model系列之二

    [疯狂造轮子-iOS]JSON转Model系列之二 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇<[疯狂造轮子-iOS]JSON转Model系列之一> ...

  3. 【疯狂造轮子-iOS】JSON转Model系列之一

    [疯狂造轮子-iOS]JSON转Model系列之一 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 之前一直看别人的源码,虽然对自己提升比较大,但毕竟不是自己写的,很容易遗 ...

  4. 详解树莓派Model B+控制蜂鸣器演奏乐曲

    步进电机以及无源蜂鸣器这些都需要脉冲信号才能够驱动,这里将用GPIO的PWM接口驱动无源蜂鸣器弹奏乐曲,本文基于树莓派Mode B+,其他版本树莓派实现时需参照相关资料进行修改! 1 预备知识 1.1 ...

  5. 【AutoMapper官方文档】DTO与Domin Model相互转换(上)

    写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...

  6. 拨开迷雾,找回自我:DDD 应对具体业务场景,Domain Model 到底如何设计?

    写在前面 除了博文内容之外,和 netfocus 兄的讨论,也可以让你学到很多(至少我是这样),不要错过哦. 阅读目录: 迷雾森林 找回自我 开源地址 后记 毫无疑问,领域驱动设计的核心是领域模型,领 ...

  7. 使用mybatis-generator在自动生成Model类和Mapper文件

    使用mybatis-generator插件可以很轻松的实现mybatis的逆向工程,即,能通过表结构自动生成对应的java类及mapper文件,可以大大提高工作效率,并且它提供了很多自定义的设置可以应 ...

  8. “RazorEngine.Templating.TemplateParsingException”类型的异常在 RazorEngine.NET4.0.dll 中发生,但未在用户代码中进行处理 其他信息: Expected model identifier.

    这个问题是由于在cshtml中 引用了model这个单词  它可能和Model在解析时有冲突. 解决方法:把model换成别的单词就可以了.

  9. QT内省机制、自定义Model、数据库

    本文将介绍自定义Model过程中数据库数据源的获取方法,我使用过以下三种方式获取数据库数据源: 创建 存储对应数据库所有字段的 结构体,将结构体置于容器中返回,然后根据索引值(QModelIndex) ...

  10. iOS自定义model排序

    在开发过程中,可能需要按照model的某种属性排序. 1.自定义model @interface Person : NSObject @property (nonatomic,copy) NSStri ...

随机推荐

  1. Java程序员面试题收集(4)

    Java面试题和答案JAVA相关基础知识1.面向对象的特征有哪些方面      1.抽象:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题 ...

  2. storm运行服务器一些错误解决、

    java.lang.RuntimeException: Returned channel was actually not established 重启试试 Java.lang.NoSuchMetho ...

  3. Leetcode461Hamming Distance汉明距离

    两个整数之间的汉明距离指的是这两个数字对应二进制位不同的位置的数目. 给出两个整数 x 和 y,计算它们之间的汉明距离. 注意: 0 ≤ x, y < 231. 示例: 输入: x = 1, y ...

  4. 关于node中 require 和 ES6中export 、export default的总结

    nodejs中 require 方法的加载规则 方法的加载规则 1. 优先从缓存中加载 2. 核心模块 3. 路径形式的模块 4. 第三方模块 一.优先从缓存中加载 main.js:执行加载a.js模 ...

  5. Java数据结构和算法(八)--红黑树与2-3树

    红黑树规则: 1.每个节点要么是红色,要么是黑色 2.根节点都是黑色节点 3.每个叶节点是黑色节点 3.每个红色节点的两个子节点都是黑色节点,反之,不做要求,换句话说就是不能有连续两个红色节点 4.从 ...

  6. loj6229 这是一道简单的数学题

    https://loj.ac/problem/6229 题解:https://blog.csdn.net/Vectorxj/article/details/79094659 套路推式子,杜教筛,证明复 ...

  7. poj 3468 A Simple Problem with Integers (线段树区间更新求和lazy思想)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 75541   ...

  8. NYOJ1367 物流配送

    题目描述: 物流配送是物流活动中一种非单一的业务形式,它与物品流动.资金流动紧密结合.备货是配送的准备工作或基础工作,备货工作包括筹集货源.订货或购货.集货.进货及有关的质量检查.结算.交接等.配送的 ...

  9. 群晖安装transmission

    首先 需要添加第三方的套件下载地址 http://packages.synocommunity.com/ 然后找到tr 根据需要设置文件夹路径 因为我需要跑rss,所以用到了flexget,先放这里 ...

  10. Django REST Framework之认证组件

    什么是认证 认证即需要知道是谁在访问服务器,需要有一个合法身份.认证的方式可以有很多种,例如session+cookie.token等,这里以token为例.如果请求中没有token,我们认为这是未登 ...