Program Listing for File Demeter.cpp¶
↰ Return to documentation for file (gui/Demeter/Demeter.cpp)
#include <iostream>
#include "imgui.h"
#include "imgui_impl_opengl3.h"
#include "imgui_impl_sdl2.h"
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "Demeter.hpp"
#include "Demeter/Renderer/asset_dir.hpp"
#include "logging/Logger.hpp"
void Dem::Demeter::Time::Update(const SDL2 &sdl2Instance)
{
current = sdl2Instance.GetTicks64();
delta = (current - last) / 1000.0F; // convert ms to seconds
last = current;
}
bool Dem::Demeter::Init(std::unique_ptr<SDL2> renderer, bool activateDebug)
{
sdl2 = std::move(renderer);
time = Time(*sdl2);
glDebug = activateDebug;
std::unique_ptr<VertexShader> vertexShader = std::
make_unique<VertexShader>();
if (!vertexShader->Init(ASSET_DIR "/vertexShader.glsl")) {
Log::failed << "Failed to initialize vertex shader.";
return false;
}
std::unique_ptr<FragmentShader> fragmentShader = std::
make_unique<FragmentShader>();
if (!fragmentShader->Init(ASSET_DIR "/fragmentShader.glsl")) {
Log::failed << "Failed to initialize fragment shader.";
return false;
}
if (!shader->Init(std::move(vertexShader), std::move(fragmentShader))) {
Log::failed << "Failed to initialize shader program.";
return false;
}
camera = Camera(glm::radians(90.0), 800.0 / 600.0);
if (glDebug) {
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallback(DebugCallback, nullptr);
}
return true;
}
// OpenGL debug callback function
void Dem::Demeter::DebugCallback(
GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar *message,
const void *userParam)
{
(void)source;
(void)type;
(void)id;
(void)severity;
(void)length;
(void)userParam;
std::cerr << "GL DEBUG: " << message << "\n";
}
void Dem::Demeter::Update()
{
time.Update(*sdl2);
for (std::shared_ptr<Dem::IEntity> &entity: entityPool)
if (!entity->Update(*this))
Log::warn << "Entity update failed";
}
void Dem::Demeter::Draw()
{
sdl2->Clear(0.1, 0.12, 0.15, 1.0);
shader->Use(); // set the shader program before setting mvp
for (std::shared_ptr<Dem::IEntity> &entity: entityPool)
if (!entity->Draw(*this))
Log::warn << "Entity draw failed";
if (isImGUIWindowCreated) {
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
}
sdl2->SwapWindow();
}
void Dem::Demeter::HandleEvent()
{
switch (sdl2->GetEvent().type) {
case SDL_QUIT:
isRunning = false;
break;
case SDL_KEYDOWN:
input.keys[sdl2->GetEvent().key.keysym.scancode] = true;
break;
case SDL_KEYUP:
input.keys[sdl2->GetEvent().key.keysym.scancode] = false;
break;
case SDL_MOUSEMOTION:
input.mouseDeltaX = sdl2->GetEvent().motion.xrel;
input.mouseDeltaY = sdl2->GetEvent().motion.yrel;
input.mouseX = sdl2->GetEvent().motion.x;
input.mouseY = sdl2->GetEvent().motion.y;
break;
case SDL_MOUSEBUTTONDOWN:
if (sdl2->GetEvent().button.button < 5)
input.mouseButtons[sdl2->GetEvent().button.button] = true;
break;
case SDL_MOUSEBUTTONUP:
if (sdl2->GetEvent().button.button < 5)
input.mouseButtons[sdl2->GetEvent().button.button] = false;
break;
case SDL_WINDOWEVENT:
{
if (sdl2->GetEvent().window.event == SDL_WINDOWEVENT_RESIZED
|| sdl2->GetEvent().window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
int new_width = sdl2->GetEvent().window.data1;
int new_height = sdl2->GetEvent().window.data2;
sdl2->SetWindowSize(new_width, new_height);
camera.SetAspectRatio((float)new_width / (float)new_height);
}
break;
}
default:
break;
}
}
void Dem::Demeter::Run()
{
isRunning = true;
while (isRunning) {
while (sdl2->PollEvent()) {
if (
sdl2->GetEvent().type != SDL_KEYDOWN
&& sdl2->GetEvent().type != SDL_KEYUP
&& sdl2->GetEvent().type != SDL_TEXTINPUT)
ImGui_ImplSDL2_ProcessEvent(&sdl2->GetEvent());
HandleEvent();
}
Update();
Draw();
if (glDebug) {
int e = GL_NO_ERROR;
while ((e = glGetError()) != GL_NO_ERROR)
std::cerr << "OpenGL Error: " << e << '\n';
}
}
}
std::shared_ptr<Texture> Dem::Demeter::AddTexture(const std::string &path)
{
if (textureMap.contains(path))
return texturePool[textureMap[path]];
std::shared_ptr<Texture> tex = std::make_shared<Texture>();
if (!tex->Init(*sdl2, path)) {
Log::failed
<< "Failed to load texture from path: " << path
<< ". Using default texture instead.";
tex = std::make_shared<Texture>();
tex->Init(*sdl2, ASSET_DIR "/no-texture.png");
}
texturePool.push_back(tex);
textureMap[path] = texturePool.size() - 1;
return tex;
}
[[nodiscard]] std::optional<std::shared_ptr<Object3D>>
Dem::Demeter::AddObject3D(const std::string &path)
{
if (objectMap.contains(path))
return objectPool[objectMap[path]];
std::shared_ptr<Object3D> object = std::make_shared<Object3D>();
if (!object->Init(path)) {
Log::failed << "Failed to initialize Object3D from path: " << path;
return std::nullopt;
}
objectPool.push_back(object);
objectMap[path] = objectPool.size() - 1;
return object;
}