OpenGL工程重构和obj文件loader编写

最近做毕设,将代码重新整理一遍,将原来的OpenGL框架抽象了一遍,重构了一下,在此总结一下。同时,仿照assimp重写了一个obj文件的loader。

obj文件loader编写

obj文件格式解析见之前的博客,pcd,obj,mtl文件格式解析obj主要包含obj文件和材质文件mtl。其中模型的结构是按照组来划分的,每个组有自己的材质,而且绝大部分模型不同组不共享顶点【猜测~】。因此将模型处理成组,每个组拥有自己的顶点【包括顶点,纹理,法线】,材质信息【漫反射,高光,贴图等】。主要包含两个类,一个是model,这是一个模型一个类,一个是mesh,为每个组一个类。
以下介绍数据结构:

// 材质,暂时没有写贴图
struct Matrial
    {
        glm::vec3 Ka;
        glm::vec3 Kd;
        glm::vec3 Ks;
        int illum;
        std::string mat_name;
    };
// 顶点
struct Vertex
    {
        glm::vec3 pos;
        glm::vec3 nor;
        glm::vec2 tex;
    };  
// mesh类
class Mesh
    {           
    public:
        std::string meshName;
        std::string matrialName;
        // 该组的顶点信息
        std::vector<glm::vec3> points;
        std::vector<glm::vec3> normal;
        std::vector<glm::vec2> textCoords;
        // 存储网格信息,将顶点重新组织,每个顶点含有位置,纹理,法线        
        std::vector<Vertex> vertices;
        Matrial mat;
        void clear();
        void setUp();// 传输数据到GPU
        void draw(Shader *);// 绘制
    private:
        GLuint VAO;
        GLuint VBO;     
    };  
// model类
class Model
    {
    public:     
        Model(){};
        ~Model(){};
        std::string path;
        std::string matrial_path;
        bool loadModel(std::string path);// 读取模型
        void setUp();
        void draw(Shader *);
    private:
    // 包含所有的组
        std::vector<Mesh> meshes;
    // 记录所有的材质
        std::map<std::string, Matrial> matrials;
    };

具体的实现参见最后的资源链接。

重构OpenGL工程

OpenGL是原生支持的,但构建完整的OpenGL工程需要有辅助的函数库,主要包括窗口的工具类glfw,获取OpenGL函数地址的库glew或者glad。原生的写OpenGL会代码比较丑陋,很难抽象出来。参考learning OpenGL上的代码整理成如下的格式。

  • callBack
    注册回调函数的基类
  • glfwinit.h
    传入基类指针,并且初始化OpenGL环境
  • camera.h
    相机类
  • shader.h
    着色器类
  • Entrance
    继承自callback基类,负责渲染的主过程控制,指针传入到glfwinit.h

部分代码如下:

// callback.h
class ICallbacks
{
public :    
    GLfloat deltaTime = 0.0f;
    virtual void RenderSceneCB() {};// 绘制场景接口
    // 回调函数接口
    virtual void MouseCB(MOUSE Button, KEY_STATE State, int x, int y){};    
    virtual void PassiveMouseCB(GLfloat x, GLfloat y) {};
    virtual void KeyboardCB(GLFWwindow* window, int Key, int KeyState){};
};

// glfwinit.h
void InitGlfw(ICallbacks * s,int width, int height, std::string title);// 初始化OpenGL环境
// 注册回调函数
void keyfunc(GLFWwindow* window, int k, int scancode, int action, int mode);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
// 绘制场景
void RunShader();

// Entrance.h
class Entrance :public ICallbacks
{
private:
    GLfloat lastX = 400, lastY = 300;
    GLfloat lastFrame = 0.0f;
    bool firstMouse = true;
public:
    Camera camera;
    std::vector<int> key;
    OBJ::Model * o_model;
    Shader * shader;
    Entrance(int width, int height, std::string title);
    void Run();// 绘制函数
    // 继承自callback基类的接口
    virtual void RenderSceneCB() override;
    virtual void KeyboardCB(GLFWwindow* window, int k, int action = GLFW_RELEASE) override;
    virtual void PassiveMouseCB(GLfloat xpos, GLfloat ypos) override;
    void Do_Movement();// 处理移动
};

这里写图片描述
效果如图:只适用了最简单的着色器,没有使用贴图。
完整代码github地址
如有错误,欢迎指正~

猜你喜欢

转载自blog.csdn.net/hu694028833/article/details/80140305