Я пытаюсь написать базовую c оболочку над библиотекой GLFW и GLAD, чтобы я мог написать что-то вроде
graphics::Window window(*args*);
graphics::Shader shader(*args*);
graphics::Box box(*args*);
while(!window.shouldClose())
{
box.draw(shader) // Draws in current context that is set behind the scenes in Window's constructor
window.swapBuffer();
graphics::pollEvents();
}
Таким образом, это в основном прямые вызовы функций GLFW и GL (в целом), но без необходимости раздувать клиентский код такими вещами, как glfwInit
, gladLoadGLLoader
, компиляция шейдеров, инициализация VBO и т. д. c. На пути реализации всего этого я столкнулся с некоторыми трудностями. Да, на самом деле это не один вопрос (который я упомянул в заголовке), но я не хотел разбивать их на разные вопросы, потому что все они как бы связаны.
Может случиться ситуация, и мне нужно позвонить GLFW работает в разных cpp файлах, поэтому я включаю glfw3.h несколько раз, и, насколько мне известно, один и тот же код компилируется несколько раз в разных единицах перевода. Вопрос: это правильно и нормально?
Как вы могли заметить, я немного одержим идеей «Оптимизация», «Разделение зон ответственности», «Обертка кода» и т. Д. c. Из-за этого я решил организовать свой код таким образом:
- Class
GLFWCore
берет на себя управление инициализацией GLFW (имеет glfwInit();
в своем частном конструкторе, glfwTerminate();
в его деструкторе и single publi c stati c method init
, в теле которого есть только static GLFWCore core;
) - Class
GLCore
берет на себя управление инициализацией GLAD и ничего не знает о GLFW, он также имеет метод init
, который должен правильно загружать функции OpenGL. Для этого он принимает указатель на функцию в качестве параметра: void*(*func)(const char* procName)
и вызывает gladLoadGLLoader
в своем теле - Кто-то должен взять под контроль весь этот беспорядок, пусть это будет класс
Window
. Этот класс создает окно, поэтому он должен иметь GLFWWindow
как закрытый член. Я думал о включении glfw3.h
, но если кто-то включает мой класс Window
, он включает и glfw3.h
, и я не думаю, что это хорошо. А вот идиома pimpl! (Вопрос: хорошее ли это решение или я должен подумать о другом способе организации кода?). В результате я включаю glfw3.h
в cpp файл, но это не идеально для меня, мысль «Боже мой, он компилируется несколько раз в разных cpp файлах» просто взрывает мой мозг (Как мне поступить с это?) Window
конструктор вызывает метод инициализации GLFWCore
(он обеспечивает инициализацию GLFW), затем он должен вызывать несколько функций GLFW, таких как glfwWindowHint
или glfwCreateWindow
. Должен ли я включать glfw3.h
в этот cpp и вызывать эти функции напрямую или переносить их в класс, например GLFWCore
(чтобы сохранить все вызовы glfw в одном cpp) и вызывать их через GLFWCore
publi c stati c методы? В случае второго варианта, как быть с тем, что glfwCreateWindow
возвращает указатель GLFWWindow
, и я не хочу включать glfw3.h
в свои заголовки? После создания окна и инициализации контекста функции OpenGL должны быть загружены, но я не хочу вызывать метод инициализации GLCore
внутри конструктора Window
(предположим, что GLCore
вызвало исключение, в этот момент GLFWWindow
было фактически создано, но не будет уничтожено, потому что деструктор Window
не будет вызван)
Вопрос в том, не слишком ли я одержим идеей разделения зон ответственности и оптимизации CPP? Если нет, как я могу реализовать все вышеперечисленное "красивым" способом? Просто направь меня по правильному пути и расскажи мне ключевые моменты