这篇文章来绘制3D模型。添加了model.h和model.cpp文件.

model.h

#pragma once
#include "ggl.h"
#include "vertexbuffer.h"
#include "shader.h"
class Model
{VertexBuffer* mVertexBuffer;Shader* mShader;glm::mat4 mModelMatrix;
public:Model();void Init(const char* modelPath);void Draw(glm::mat4& viewMatrix, glm::mat4 projectionMatrix);void SetPosition(float x, float y, float z);
};

model.cpp

#include "Utils.h"
#include "model.h"Model::Model()
{}void Model::Init(const char* modelPath)
{struct FloatData{float v[3];};struct VertexDefine {int posIndex;int texcoordIndex;int normalIndex;};int nFileSize = 0;unsigned char* fileContent = LoadFileContent(modelPath, nFileSize);if (fileContent == nullptr){return;}std::vector<FloatData>positions, texcoords, normals;std::vector<VertexDefine> vertexes;std::stringstream ssFileContent((char*)fileContent);std::string temp;char szOneLine[256];while (!ssFileContent.eof()){memset(szOneLine, 0, 256);ssFileContent.getline(szOneLine, 256);if (strlen(szOneLine)>0){std::stringstream ssOneLine(szOneLine);if (szOneLine[0]=='v'){if (szOneLine[1]=='t'){ssOneLine >> temp;FloatData floatData;ssOneLine >> floatData.v[0];ssOneLine >> floatData.v[1];texcoords.push_back(floatData);printf("texcoord: %f,%f\n",floatData.v[0],floatData.v[1]);}else if (szOneLine[1] == 'n'){ssOneLine >> temp;FloatData floatData;ssOneLine >> floatData.v[0];ssOneLine >> floatData.v[1];ssOneLine >> floatData.v[2];normals.push_back(floatData);printf("normal: %f,%f,%f\n", floatData.v[0], floatData.v[1], floatData.v[2]);}else{ssOneLine >> temp;FloatData floatData;ssOneLine >> floatData.v[0];ssOneLine >> floatData.v[1];ssOneLine >> floatData.v[2];positions.push_back(floatData);printf("normal: %f,%f,%f\n", floatData.v[0], floatData.v[1], floatData.v[2]);}}else if (szOneLine[0] == 'f'){std::stringstream ssOneLine(szOneLine);ssOneLine >> temp;std::string verterStr;for (int i=0;i<3;i++){ssOneLine >> verterStr;size_t pos = verterStr.find_first_of('/');std::string posIndexStr = verterStr.substr(0, pos);size_t pos2 = verterStr.find_first_of('/', pos + 1);std::string texcoordIndexStr = verterStr.substr(pos + 1, pos2 - 1 - pos);std::string normalIndexStr = verterStr.substr(pos2 + 1, verterStr.length() - 1 - pos2);VertexDefine vd;vd.posIndex = atoi(posIndexStr.c_str());vd.texcoordIndex = atoi(texcoordIndexStr.c_str());vd.normalIndex = atoi(normalIndexStr.c_str());vertexes.push_back(vd);}printf("draw command: %s\n", szOneLine);}}}delete fileContent;int vertexCount = (int)vertexes.size();mVertexBuffer = new VertexBuffer;mVertexBuffer->SetSize(vertexCount);for (int i=0;i<vertexCount;++i){float* temp = positions[vertexes[i].posIndex - 1].v;mVertexBuffer->SetPosition(i, temp[0], temp[1], temp[2]);temp = texcoords[vertexes[i].texcoordIndex - 1].v;mVertexBuffer->SetTexcoord(i, temp[0], temp[1]);temp = normals[vertexes[i].normalIndex - 1].v;mVertexBuffer->SetNormal(i, temp[0], temp[1], temp[2]);}mShader = new Shader;mShader->Init("Res/model.vs", "Res/model.fs");
}void Model::Draw(glm::mat4& viewMatrix, glm::mat4 projectionMatrix)
{//Model是3D物体,开启深度测试glEnable(GL_DEPTH_TEST);mVertexBuffer->Bind();mShader->Bind(glm::value_ptr(mModelMatrix), glm::value_ptr(viewMatrix), glm::value_ptr(projectionMatrix));glDrawArrays(GL_TRIANGLES, 0, mVertexBuffer->mVertexCount);mVertexBuffer->UnBind();
}void Model::SetPosition(float x, float y, float z)
{mModelMatrix = glm::translate(x, y, z);
}

3D模型的数据使用记事本打开可看到其数据结构(Sphere.obj的太长了,找了个小一点的,其结构都是一样的,数据长短的问题):

我们只需要v,vt,vn以及f开头的数据。model.cpp就是在做这件事。

shader.h和shader.cpp里添加了新的接口和结构体:

shader.h

#pragma once
#include "ggl.h"
struct UniformTexture
{GLint mLocation;GLuint mTexture;UniformTexture() {mLocation = -1;mTexture = 0;}
};
struct UniformVector4f
{GLint mLocation;float v[4];UniformVector4f() {mLocation = -1;memset(v, 0, sizeof(float) * 4);}
};
class Shader
{
public:GLuint mProgram;GLuint mPosition;GLuint mColor;GLuint mTexcoord;GLuint mNormal;std::map<std::string, UniformTexture*> mUniformTextures;std::map<std::string, UniformVector4f*> mUniformVec4s;GLint mModelMatrixLocation, mViewMatrixLocation, mProjectionMatrixLocation;GLint mPositionLocation, mColorLocation, mTexcoordLocation, mNormalLocation;void Init(const char* vs, const char* fs);void Bind(float* M, float* V, float* P);void SetTexture(const char* name, const char* imagePath);void SetVec4(const char* name, float x, float y, float z, float w);
};

shader.cpp:

#include "shader.h"
#include "utils.h"
#include "vertexbuffer.h"
void Shader::Init(const char* vs, const char* fs)
{int nFileSize = 0;const char* vsCode = (char*)LoadFileContent(vs, nFileSize);const char* fsCode = (char*)LoadFileContent(fs, nFileSize);GLuint vsShader = CompileShader(GL_VERTEX_SHADER, vsCode);if (vsShader == 0) {return;}GLuint fsShader = CompileShader(GL_FRAGMENT_SHADER, fsCode);if (fsShader == 0) {return;}mProgram = CreateProgram(vsShader, fsShader);glDeleteShader(vsShader);glDeleteShader(fsShader);if (mProgram != 0) {mModelMatrixLocation = glGetUniformLocation(mProgram, "ModelMatrix");mViewMatrixLocation = glGetUniformLocation(mProgram, "ViewMatrix");mProjectionMatrixLocation = glGetUniformLocation(mProgram, "ProjectionMatrix");mPositionLocation = glGetAttribLocation(mProgram, "position");mColorLocation = glGetAttribLocation(mProgram, "color");mTexcoordLocation = glGetAttribLocation(mProgram, "texcoord");mNormalLocation = glGetAttribLocation(mProgram, "normal");}
}
void Shader::Bind(float* M, float* V, float* P)
{glUseProgram(mProgram);glUniformMatrix4fv(mModelMatrixLocation, 1, GL_FALSE, M);glUniformMatrix4fv(mViewMatrixLocation, 1, GL_FALSE, V);glUniformMatrix4fv(mProjectionMatrixLocation, 1, GL_FALSE, P);int iIndex = 0;for (auto iter = mUniformTextures.begin(); iter != mUniformTextures.end(); ++iter) {glActiveTexture(GL_TEXTURE0 + iIndex);glBindTexture(GL_TEXTURE_2D, iter->second->mTexture);glUniform1i(iter->second->mLocation, iIndex++);}for (auto iter = mUniformVec4s.begin(); iter != mUniformVec4s.end(); ++iter) {glUniform4fv(iter->second->mLocation, 1, iter->second->v);}glEnableVertexAttribArray(mPositionLocation);glVertexAttribPointer(mPositionLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);glEnableVertexAttribArray(mColorLocation);glVertexAttribPointer(mColorLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 4));glEnableVertexAttribArray(mTexcoordLocation);glVertexAttribPointer(mTexcoordLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 8));glEnableVertexAttribArray(mNormalLocation);glVertexAttribPointer(mNormalLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(sizeof(float) * 12));
}
void Shader::SetTexture(const char* name, const char* imagePath)
{auto iter = mUniformTextures.find(name);if (iter == mUniformTextures.end()) {GLint location = glGetUniformLocation(mProgram, name);if (location != -1){UniformTexture* t = new UniformTexture;t->mLocation = location;t->mTexture = CreateTexture2DFromBMP(imagePath);mUniformTextures.insert(std::pair<std::string, UniformTexture*>(name, t));}}else {glDeleteTextures(1, &iter->second->mTexture);iter->second->mTexture = CreateTexture2DFromBMP(imagePath);}
}
void Shader::SetVec4(const char* name, float x, float y, float z, float w)
{auto iter = mUniformVec4s.find(name);if (iter == mUniformVec4s.end()) {GLint location = glGetUniformLocation(mProgram, name);if (location != -1){UniformVector4f* v = new UniformVector4f;v->v[0] = x;v->v[1] = y;v->v[2] = z;v->v[3] = w;v->mLocation = location;mUniformVec4s.insert(std::pair<std::string, UniformVector4f*>(name, v));}}else {iter->second->v[0] = x;iter->second->v[1] = y;iter->second->v[2] = z;iter->second->v[3] = w;}
}

新添加了model.vs和model.fs的shader

model.vs:

attribute vec4 position;
attribute vec4 color;
attribute vec4 texcoord;
attribute vec4 normal;
uniform mat4 ModelMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ProjectionMatrix;
varying vec4 V_Color;
void main()
{V_Color=color;gl_Position=ProjectionMatrix*ViewMatrix*ModelMatrix*position;
}

model.fs:

#ifdef GL_ES
precision mediump float;
#endif
varying vec4 V_Color;
void main()
{gl_FragColor=V_Color;
}

scene.cpp里调用model的初始化以及绘制接口:

#include "scene.h"
#include "ggl.h"
#include "utils.h"
#include "ground.h"
#include "shader.h"
#include "model.h"
glm::mat4 modelMatrix, viewMatrix, projectionMatrix;
Ground ground;
Model model;
void Init()
{ground.Init();model.Init("Res/Sphere.obj");model.SetPosition(0.0f, 0.0f, -5.0f);
}
void SetViewPortSize(float width, float height)
{projectionMatrix = glm::perspective(60.0f, width / height, 0.1f, 1000.0f);
}
void Draw()
{float frameTime = GetFrameTime();glClearColor(0.1f, 0.4f, 0.6f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);ground.Draw(viewMatrix, projectionMatrix);model.Draw(viewMatrix, projectionMatrix);
}

看下效果:

太丑了,下篇文章来让它变得好看一点~

【OpenGL进阶】05.绘制3D模型相关推荐

  1. opengl加载显示3D模型UC类型文件

    opengl加载显示3D模型UC类型文件 前置条件 注意事项 项目展示 项目完整C++源代码 前置条件 opengl三方库freeglut,显示uc格式的三维模型文件, 注意事项 源代码 model_ ...

  2. opengl加载显示3D模型3d类型文件

    opengl加载显示3d模型UC类型文件 前置条件 注意事项 项目展示 项目完整C++源代码 前置条件 opengl三方库freeglut,显示3d格式的三维模型文件, 注意事项 源代码 model_ ...

  3. opengl加载显示3D模型3MF类型文件

    opengl加载显示3D模型3MF类型文件 前置条件 注意事项 项目展示 项目完整C++源代码 前置条件 opengl三方库freeglut,显示3MF格式的三维模型文件 注意事项 源代码 model ...

  4. opengl加载显示3D模型AC类型文件

    opengl加载显示3D模型AC类型文件 前置条件 注意事项 项目展示 项目完整C++源代码 前置条件 opengl三方库freeglut,显示AC格式的三维模型文件 注意事项 源代码 model_f ...

  5. opengl加载显示3D模型AMF类型文件

    opengl加载显示3D模型AMF类型文件 前置条件 注意事项 项目展示 项目完整C++源代码 前置条件 opengl三方库freeglut,显示AMF格式的三维模型文件 注意事项 源代码 model ...

  6. opengl加载显示3D模型ase类型文件

    opengl加载显示3D模型ase类型文件 前置条件 注意事项 项目展示 项目完整C++源代码 前置条件 opengl三方库freeglut,显示ase格式的三维模型文件 注意事项 源代码 C:/Us ...

  7. opengl加载显示3D模型blend类型文件

    opengl加载显示3D模型blend类型文件 前置条件 注意事项 项目展示 项目完整C++源代码 前置条件 opengl三方库freeglut,显示blend格式的三维模型文件 注意事项 源代码 m ...

  8. opengl加载显示3D模型BVH类型文件

    opengl加载显示3D模型BVH类型文件 前置条件 注意事项 项目展示 项目完整C++源代码 前置条件 opengl三方库freeglut,显示BVH格式的三维模型文件 注意事项 源代码 model ...

  9. opengl加载显示3D模型COB类型文件

    opengl加载显示3D模型COB类型文件 前置条件 注意事项 项目展示 项目完整C++源代码 前置条件 opengl三方库freeglut,显示COB格式的三维模型文件 注意事项 源代码 model ...

最新文章

  1. java sortedset_Java类集-SortedSet接口 | 学步园
  2. Nginx的动态代理,负载均衡,动静分离的简单使用
  3. PAT_B_1009_Java(20分)
  4. 浅谈session,cookie,sessionStorage,localStorage的区别及应用场景
  5. 1-6docker数据共享与持久化
  6. 【网络安全工程师面试合集】— 网络攻防技术演化历程
  7. workbench设置单元坐标系_ANSYS经典案例在Workbench中实现分享连载(三)
  8. L1-043 阅览室 (20 分)—团体程序设计天梯赛
  9. 用unity协程写的发牌程序
  10. 推荐一款专为新手用的Python开发工具
  11. Layer表格列根据配置动态显示
  12. 考研杂谈一:计算机专业有必要考研吗?
  13. 电脑中毒,文件夹都变成exe文件怎么办?
  14. java的cursor_JAVA中类 Cursor的定义.
  15. Android Studio修改工程项目编码,修正运行程序乱码问题
  16. python画图解决Times New Roman自带粗体问题
  17. 爬虫项目(一)爬虫+jsoup轻松爬知乎
  18. 蓝桥杯 ADV-287 算法提高 Monday-Saturday质因子
  19. MySQL的用途(转)
  20. springboot高级篇(认证,授权)

热门文章

  1. 中国人工智能学会通讯——搜狗搜索:从搜索到问答 1.3 搜狗立知系统
  2. 创业必读:没钱没技术,如何开发App?
  3. ROS 和 ROS2 架构和通信
  4. 基于ISO 21448和STPA方法的自动驾驶安全性和可靠性设计
  5. 快递查询慢?试试这个方法,一键查询物流,又快又准
  6. idea 设置自动生成类和方法注释,TODO标记作者日期信息以及过滤自己所写标记
  7. Camtasia Studio 2022mac新版强大的屏幕录制软件
  8. edge浏览器新建inprivate窗口是灰色(删除账户,退出家庭组,重装edge无法解决情况下下)
  9. Allegro 机械安装孔制作
  10. 计算机网络三种数据交换方式