在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. ajax原理及使用

    1.关于同步和异步 异步传输是面向字符的传输,它的单位是字符:而同步传输是面向比特的传输,它的单位是桢,它传输的时候要求接受方和发送方的时钟是保持一致的. 具体来说,异步传输是将比特分成小组来进行传送 ...

  2. 一、WebService基础概念

    一.Web Service简介 1.1.Web Service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intrane ...

  3. nfs服务安装配置

    一.准备阶段 配置解析主机 检查版本及内核 二.服务端安装 1) 配置yum把下载好的软件留着,下次备用,不用再下载 cachedir=/var/cache/yum/$basearch/$releas ...

  4. 单元测试神器Mockito

    Mockit是一种mock工具/框架.mock可以模拟各种各样的对象,从而代替真正的对象做出希望的响应 1.工程中引入Mockito #以gradle的方式为例 testCompile("o ...

  5. mongodb本地搭建过程

    1.解压安装包后安装 安装时注意:1.选择customs    2.路径选择C盘以外的盘符 安装完成后: 2.在bin的同级目录下新建data.log文件夹 3.在data文件夹下新建db文件夹,在l ...

  6. idea目录结构子目录在父目录后面跟着改成树形结构

    1.点击项目窗口的设置按钮 2.取消Compact Middle Packages选项的对勾即可

  7. Linux预习

    目录 linux系统和unix系统的简介 linux系统和unix系统的简介 unix是什么:和widows一样 特点:多用户,多任务 同一时刻,多用户同时执行多项程序,互不干扰 GNU项目 就是一个 ...

  8. Leetcode653.Two Sum IV - Input is a BST两数之和4-输入BST

    给定一个二叉搜索树和一个目标结果,如果 BST 中存在两个元素且它们的和等于给定的目标结果,则返回 true. struct TreeNode { int val; struct TreeNode * ...

  9. 卡特兰数(catalan)总结

    卡特兰数的公式 递推公式1:$f(n)=\sum \limits_{i=0}^{n-1}f(i)*f(n-i-1)$ 递推公式2:$f(n)=\frac{f(n-1)*(4*n-2)}{n+1}$ 组 ...

  10. LintCode_14 二分查找

    题目 给定一个排序的整数数组(升序)和一个要查找的整数target,用O(logn)的时间查找到target第一次出现的下标(从0开始),如果target不存在于数组中,返回-1. 样例 在数组 [1 ...