在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. TZOJ 4292 Count the Trees(树hash)

    描述 A binary tree is a tree data structure in which each node has at most two child nodes, usually di ...

  2. phpSpider 单页测试_模拟登陆

    <?php require './vendor/autoload.php'; use phpspider\core\phpspider; use phpspider\core\requests; ...

  3. sulin LuceneNet 搜索二

    1.添加引用dll using Lucene.Net.Search;using Lucene.Net.Analysis.PanGu;using PanGu;using PanGu.HighLight; ...

  4. 【html、CSS、javascript-12】jquery-效果

    一.jQuery 效果- 隐藏和显示 通过 jQuery,您可以使用 hide() 和 show() 方法来隐藏和显示 HTML 元素: $("#hide").click(func ...

  5. jquery ajax跨越

    JSONP是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问 1.jsonp之$.ajax js $.ajax({ ...

  6. spring cloud深入学习(四)-----eureka源码解析、ribbon解析、声明式调用feign

    基本概念 1.Registe 一一服务注册当eureka Client向Eureka Server注册时,Eureka Client提供自身的元数据,比如IP地址.端口.运行状况指标的Uri.主页地址 ...

  7. jsp必填项加红色星号

    <th><font color=red>*</font>文字:</th>

  8. WordPress资料收集,以后整理

    WordPress主题开发:实现分页功能 http://www.cnblogs.com/tinyphp/p/6361901.html WordPress如何调取显示指定文章 https://www.d ...

  9. 对于MD5加密处理方式

    来源:http://blog.51cto.com/xqtesting/1924977 但有时候我们请求的参数可能需要加密,比如登录接口中的密码可能需要经过md5加密这时候怎么处理呢? 这种方法比较简单 ...

  10. 一些windows server的操作

    windows server2008R2的一些操作和arcgis9.3 服务和arcgis9.3安装 1.在虚拟机中安装: https://jingyan.baidu.com/article/0eb4 ...