Initial commit

This commit is contained in:
Riyyi
2021-02-20 01:07:10 +01:00
commit 57c16ef187
46 changed files with 7496 additions and 0 deletions
+111
View File
@@ -0,0 +1,111 @@
#include <glm/gtx/transform.hpp> // glm::lookAt, glm::perspective
#include <glm/ext/matrix_clip_space.hpp> // glm::perspective
#include "camera.h"
#include "input.h"
#include "window.h"
void Camera::initialize()
{
setPosition(glm::vec3(0.0f, 0.0f, 3.0f));
setRotation(glm::vec3(0.0f, 0.0f, -1.0f));
setScale(glm::vec3(1.0f, 1.0f, 1.0f));
setFov(90.0f);
m_pitch = 0.0f;
m_yaw = 0.0f;
// Up vector in world space
m_up = glm::vec3(0.0f, 1.0f, 0.0f);
}
void Camera::update()
{
// Get mouse movement offset compared to last frame
float xoffset = g_inputManager->xOffset() * SENSITIVITY;
float yoffset = g_inputManager->yOffset() * SENSITIVITY;
m_yaw += xoffset;
m_pitch += yoffset;
// Prevent gimbal lock
if(m_pitch > 89.0f) m_pitch = 89.0f;
if(m_pitch < -89.0f) m_pitch = -89.0f;
// Update camera rotation, by calculating direction vector via yaw and pitch
setRotation(
cos(glm::radians(m_pitch)) * cos(glm::radians(m_yaw)),
sin(glm::radians(m_pitch)),
cos(glm::radians(m_pitch)) * sin(glm::radians(m_yaw)));
setRotation(glm::normalize(rotation()));
// The direction vector is based on
// Camera direction (z): normalize(position - target)
// Right axis (x): normalize(cross(up, direction))
// Up axis (y): cross(direction, right)
// Source: https://learnopengl.com/img/getting-started/camera_axes.png
// Cross = combination of two vectors in 3D space,
// where result is always perpendicular to both of the vectors
// Update camera position
float cameraSpeed = SPEED * g_window->deltaTime();
// WASD movement
if (g_inputManager->keyState(GLFW_KEY_W) == InputManager::DOWN) {
setPosition(position() + cameraSpeed * rotation());
}
if (g_inputManager->keyState(GLFW_KEY_S) == InputManager::DOWN) {
setPosition(position() - cameraSpeed * rotation());
}
if (g_inputManager->keyState(GLFW_KEY_A) == InputManager::DOWN) {
setPosition(position() -
glm::normalize(glm::cross(rotation(), m_up)) * cameraSpeed);
}
if (g_inputManager->keyState(GLFW_KEY_D) == InputManager::DOWN) {
setPosition(position() +
glm::normalize(glm::cross(rotation(), m_up)) * cameraSpeed);
}
// Up / down movement
if (g_inputManager->keyState(GLFW_KEY_SPACE) == InputManager::DOWN) {
setPosition(position().x, position().y + cameraSpeed, position().z);
}
if (g_inputManager->keyState(GLFW_KEY_LEFT_SHIFT) == InputManager::DOWN) {
setPosition(position().x, position().y - cameraSpeed, position().z);
}
// Update camera matrix
// Local space -> World space: model matrix
// Is done in Object::update()
// World space -> View space: view matrix
setModel(glm::lookAt(position(), position() + rotation(), m_up));
// View space -> Clip space: projection matrix
m_projection = glm::perspective(glm::radians(m_fov), g_window->aspect(),
NEAR_PlANE, FAR_PlANE);
// Clip space -> Screen space: viewport transform
// Is done in the fragment shader using the settings of glViewport
// Souce: https://learnopengl.com/img/getting-started/coordinate_systems.png
}
void Camera::render()
{
}
void Camera::destroy()
{
}
// -----------------------------------------
float Camera::fov() {
return m_fov;
}
void Camera::setFov(float fov)
{
m_fov = fov;
}
glm::mat4 Camera::projection() {
return m_projection;
}
+188
View File
@@ -0,0 +1,188 @@
#include <cmath> // sin, fmod
#include <cstdio> // printf
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/gtx/transform.hpp> // glm::translate, glm::rotate, glm::scale
#include "camera.h"
#include "cube.h"
#include "shader.h"
#include "texture.h"
#include "window.h"
Cube::Cube() : Object(), m_color(1.0f), m_shader(nullptr)
{
initialize();
}
Cube::Cube(float r, float g, float b) : Cube()
{
m_color = glm::vec3(r, g, b);
}
Cube::~Cube()
{
destroy();
}
// -----------------------------------------
void Cube::initialize()
{
printf("Cube::initialize\n");
setPosition(glm::vec3(0.0f, 0.0f, 0.0f));
setRotation(glm::vec3(0.0f, 0.0f, 0.0f));
setScale(glm::vec3(1.0f, 1.0f, 1.0f));
// Vertex attribute pointer size
int p1Size = 3;
int p2Size = 2;
// Vertex data
float vertexData[] = {
// x y z tx ty
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
};
m_vSize = sizeof(vertexData) / sizeof(vertexData[0]) / (p1Size + p2Size);
m_shader = g_window->shader();
// Create objects
glGenVertexArrays(1, &m_vao);
glGenBuffers(1, &m_vbo);
// Bind vertex array object
glBindVertexArray(m_vao);
// Bind vertex buffer object
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
int stride = (p1Size + p2Size) * sizeof(float);
//~ Set vertex shader attribute pointers
unsigned int p1 = glGetAttribLocation(m_shader->program(), "aPos");
glEnableVertexAttribArray(p1);
// Specify vertex data interpretation
glVertexAttribPointer(
p1, // Index
p1Size, // Size
GL_FLOAT, // Data type
GL_FALSE, // Normalize
stride, // Stride, byte offset between vertex attributes
(void*)0); // Pointer, byte offset
unsigned int p2 = glGetAttribLocation(m_shader->program(), "aTextCoord");
glEnableVertexAttribArray(p2);
// Specify vertex data interpretation
glVertexAttribPointer(
p2,
p2Size,
GL_FLOAT,
GL_FALSE,
stride,
(void*)(p1Size * sizeof(float)));
//~
// Unbind vertex array object
glBindVertexArray(0);
// Texture
m_texture = g_textureManager->loadTexture("../data/gfx/awesome-face.png");
}
void Cube::update()
{
float timeValue = glfwGetTime();
float amount = std::fmod(timeValue * 50, 360);
setRotation(amount, amount, 0.0f);
// Call parent update
Object::update();
}
void Cube::render()
{
// Render
m_shader->use();
m_shader->setFloat("color", glm::vec4(m_color, 1.0f));
m_shader->setFloat("model", model());
m_shader->setFloat("view", g_window->camera()->model());
m_shader->setFloat("projection", g_window->camera()->projection());
glBindVertexArray(m_vao);
glBindTexture(GL_TEXTURE_2D, m_texture);
glDrawArrays(GL_TRIANGLES, 0, m_vSize);
glBindTexture(GL_TEXTURE_2D, 0);
glBindVertexArray(0);
}
void Cube::destroy()
{
// Clean resources
glDeleteVertexArrays(1, &m_vao);
glDeleteBuffers(1, &m_vbo);
}
// -----------------------------------------
void Cube::setColor(float r, float g, float b)
{
m_color = glm::vec3(r, g, b);
}
// @Todo
// + Local postition flipped
// + Shader textures
// + World positions ?
// + Cleanup and understand camera::update
// + Cleanup cube more
// ! Only set shader projection on camera fov update, remove projection getter
// - Object: model matrix (add translate to origin before rotation)
// - Object: model matrix (rotations in radians here or in child (cube)?)
// |- rotation around 2 axis ?
// https://learnopengl.com/Getting-started/Coordinate-Systems
// + Object setter overload, take 3 floats as well
// - Object setter, single float position update (?)
// - Cube init: check if glGetAttribLocation != UINT_MAX
// - Text in window: FPS, Player position, player rotation
+197
View File
@@ -0,0 +1,197 @@
#include <cmath> // sin, fmod
#include <cstdio> // printf
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/gtx/transform.hpp> // glm::translate, glm::rotate, glm::scale
#include "camera.h"
#include "cubecolor.h"
#include "shader.h"
#include "window.h"
CubeColor::CubeColor() : Object(), m_lineMode(false), m_color(1.0f), m_shader(nullptr)
{
initialize();
}
CubeColor::CubeColor(float r, float g, float b, bool lineMode)
{
setColor(r, g, b);
setLineMode(lineMode);
initialize();
}
CubeColor::~CubeColor()
{
destroy();
}
// -----------------------------------------
void CubeColor::initialize()
{
printf("CubeColor::initialize\n");
setPosition(glm::vec3(0.0f, 0.0f, 0.0f));
setRotation(glm::vec3(0.0f, 0.0f, 0.0f));
setScale(glm::vec3(1.0f, 1.0f, 1.0f));
// Vertex attribute pointer size
int p1Size = 3;
int p2Size = 3;
// Vertex data
float vertexData[] = {
// x y z r g b
// Front
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
// Back
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f,
// Right
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
// Left
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
// Bottom
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
// To
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,
};
m_vSize = sizeof(vertexData) / sizeof(vertexData[0]) / (p1Size + p2Size);
m_shader = g_window->shaderColor();
// If color besides glm::vec3(1.0f) has been set, overwrite rainbow pattern
if (m_color != glm::vec3(1.0f)) {
// Loop through all 'rows'
for (unsigned int i = p1Size; i < m_vSize * (p1Size + p2Size); i += p1Size + p2Size) {
vertexData[i] = m_color.r;
vertexData[i + 1] = m_color.g;
vertexData[i + 2] = m_color.b;
}
}
// Create objects
glGenVertexArrays(1, &m_vao);
glGenBuffers(1, &m_vbo);
// Bind vertex array object
glBindVertexArray(m_vao);
// Bind vertex buffer object
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
int stride = (p1Size + p2Size) * sizeof(float);
//~ Set vertex shader attribute pointers
unsigned int p1 = glGetAttribLocation(m_shader->program(), "aPos");
glEnableVertexAttribArray(p1);
// Specify vertex data interpretation
glVertexAttribPointer(
p1, // Index
p1Size, // Size
GL_FLOAT, // Data type
GL_FALSE, // Normalize
stride, // Stride, byte offset between vertex attributes
(void*)0); // Pointer, byte offset
unsigned int p2 = glGetAttribLocation(m_shader->program(), "aColor");
glEnableVertexAttribArray(p2);
// Specify vertex data interpretation
glVertexAttribPointer(
p2,
p2Size,
GL_FLOAT,
GL_FALSE,
stride,
(void*)(p1Size * sizeof(float)));
//~
// Unbind vertex array object
glBindVertexArray(0);
}
void CubeColor::update()
{
float timeValue = glfwGetTime();
float loopValue = (std::sin(timeValue) / 2.0f) + 0.5f;
if (m_color == glm::vec3(1.0f)) {
setPosition(position().x, position().y, -loopValue * 6 + 6);
}
else if (m_lineMode) {
setScale(loopValue, loopValue, loopValue);
}
// Call parent update
Object::update();
}
void CubeColor::render()
{
// Enable wireframe mode
if (m_lineMode) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
// Render
m_shader->use();
m_shader->setFloat("model", model());
m_shader->setFloat("view", g_window->camera()->model());
m_shader->setFloat("projection", g_window->camera()->projection());
glBindVertexArray(m_vao);
glDrawArrays(GL_TRIANGLES, 0, m_vSize);
glBindVertexArray(0);
// Disable wireframe mode
if (m_lineMode) {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
}
void CubeColor::destroy()
{
// Clean resources
glDeleteVertexArrays(1, &m_vao);
glDeleteBuffers(1, &m_vbo);
}
// -----------------------------------------
void CubeColor::setLineMode(bool lineMode)
{
m_lineMode = lineMode;
}
void CubeColor::setColor(float r, float g, float b)
{
m_color = glm::vec3(r, g, b);
}
+21
View File
@@ -0,0 +1,21 @@
#include "entity.h"
Entity::Entity() : m_active(true)
{
}
Entity::~Entity()
{
}
// -----------------------------------------
bool Entity::active() const
{
return m_active;
}
void Entity::setActive(bool active)
{
m_active = active;
}
+86
View File
@@ -0,0 +1,86 @@
#include <glad/glad.h>
#include "font.h"
#include "texture.h"
FT_Face FontManager::loadFont(const std::string &path)
{
// Return previously loaded font
auto iter = m_fontList.find(path);
if (iter != m_fontList.end()) {
return m_fontList[path];
}
// Init FreeType library
FT_Library ft;
if (FT_Init_FreeType(&ft)) {
printf("FontManager::loadFont::ERROR::FREETYPE: Could not init FreeType Library\n");
}
// Load font
FT_Face face;
if (FT_New_Face(ft, path.c_str(), 0, &face)) {
printf("FontManager::loadFont::FAILED\n%s\n", path.c_str());
}
else {
// Define font size for this face
FT_Set_Pixel_Sizes(face, 0, 24); // face, width, height, where width = dynamic
// Create character list of the first 128 ascii characters
for (unsigned char c = 0; c < 128; c++) {
// Creat 8-bit bitmap image of the character
if (FT_Load_Char(face, c, FT_LOAD_RENDER)) {
printf("FontManager::loadFont::ERROR::FREETYTPE: Failed to load Glyph\n");
continue;
}
// Create texture
unsigned int texture = g_textureManager->createTexture(
GL_RED,
face->glyph->bitmap.width,
face->glyph->bitmap.rows,
face->glyph->bitmap.buffer,
GL_CLAMP_TO_EDGE,
GL_LINEAR,
GL_LINEAR
);
// Create character
Character character = {
texture,
glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
face->glyph->advance.x
};
// Construct and insert new element in the map
m_characterList.emplace(c, character);
}
// Construct and insert new element in the unordered_map
m_fontList.emplace(path, face);
}
// Clean resources
FT_Done_Face(face);
FT_Done_FreeType(ft);
return face;
}
// -----------------------------------------
Character FontManager::character(const char character) const
{
return m_characterList.at(character);
}
const std::map<const char, Character> &FontManager::characterList() const
{
return m_characterList;
}
// @Todo link fontList to characterList via:
// <freetype/freetype.h>
// typedef struct FT_FaceRec_* FT_Face;
+120
View File
@@ -0,0 +1,120 @@
#include <cstring> // memset, memcpy
#include "input.h"
#include "window.h"
InputManager::InputManager()
{
initialize();
}
InputManager::~InputManager()
{
destroy();
}
// -----------------------------------------
void InputManager::initialize()
{
// Set every key to release state
memset(&m_previousKeyStates, GLFW_RELEASE, sizeof(char) * GLFW_KEY_LAST);
memset(&m_currentKeyStates, GLFW_RELEASE, sizeof(char) * GLFW_KEY_LAST);
m_firstMouse = true;
// Set cursor in middle of the screen initially
m_xLast = g_window->width() / 2;
m_yLast = g_window->height() / 2;
}
void InputManager::update()
{
}
void InputManager::render()
{
// Copy current key states to previous
memcpy(&m_previousKeyStates, &m_currentKeyStates, sizeof(char) * GLFW_KEY_LAST);
// Stop mouse movement
m_xOffset = 0.0f;
m_yOffset = 0.0f;
}
void InputManager::destroy()
{
}
// -----------------------------------------
char InputManager::keyState(int key)
{
if (m_previousKeyStates[key] == GLFW_RELEASE &&
m_currentKeyStates[key] == GLFW_RELEASE) {
return InputManager::UP;
}
if (m_previousKeyStates[key] == GLFW_RELEASE &&
m_currentKeyStates[key] == GLFW_PRESS) {
return InputManager::PRESSED;
}
if (m_previousKeyStates[key] == GLFW_PRESS &&
m_currentKeyStates[key] == GLFW_PRESS) {
return InputManager::DOWN;
}
if (m_currentKeyStates[key] == GLFW_REPEAT) {
return InputManager::DOWN;
}
if (m_previousKeyStates[key] == GLFW_PRESS &&
m_currentKeyStates[key] == GLFW_RELEASE) {
return InputManager::RELEASED;
}
return InputManager::UP;
}
void InputManager::setKeyState(int key, int scancode, int action, int mode)
{
if (key != GLFW_KEY_UNKNOWN) {
m_currentKeyStates[key] = (char)action;
}
// Suppress unused warning
(void)scancode;
(void)mode;
}
float InputManager::xOffset()
{
return m_xOffset;
}
float InputManager::yOffset()
{
return m_yOffset;
}
void InputManager::setMouse(double xpos, double ypos)
{
// Prevent weird jump on first cursor window enter
if(m_firstMouse) {
m_xLast = xpos;
m_yLast = ypos;
m_firstMouse = false;
}
m_xOffset = xpos - m_xLast;
// Reversed since y-coordinates range from bottom to top
m_yOffset = m_yLast - ypos;
m_xLast = xpos;
m_yLast = ypos;
}
// @Todo
// - Instead of copying the entire key array into the previous array each frame.
// Have a pointer point to one of the arrays.
// To read input, say: array that pointer points to now = current,
// array that pointer does not point to now = previous.
// At the end of the frame, point the pointer to the other array.
// (?) How to get not point to array now easily? maybe two pointers that swap
// - current pointer
// - previous pointer
+70
View File
@@ -0,0 +1,70 @@
/*
* Rick van Vonderen
* 0945444
* TI2B
*
* https://www.glfw.org/docs/latest/build_guide.html#build_link_cmake_source
*
* `m_` for member variables,
* `s_` for static variables,
* `g_` for global variables.
*/
#include <cstdio> // printf
#include "font.h"
#include "gamestate.h"
#include "input.h"
#include "state/maingame.h"
#include "texture.h"
#include "window.h"
// Define globals here
GameStateManager *g_gameStateManager;
InputManager *g_inputManager;
TextureManager *g_textureManager;
FontManager *g_fontManager;
Window *g_window;
#include <glm/gtx/transform.hpp> // glm::translate, glm::rotate, glm::scale
int main(int argc, char *argv[])
{
#ifndef NDEBUG
printf("--- Debug mode ---\n");
// Supress unused warning
(void)argc;
(void)argv;
#endif
printf("--- Main ---\n");
g_window = new Window(1280, 720);
g_inputManager = new InputManager();
g_textureManager = new TextureManager();
g_fontManager = new FontManager();
g_gameStateManager = new GameStateManager();
g_gameStateManager->setState(new MainGame());
g_fontManager->loadFont("../data/font/DejaVuSansMono.ttf");
// Window loop
while (!g_window->shouldClose()) {
g_window->update();
g_inputManager->update();
g_gameStateManager->update();
g_gameStateManager->render();
g_inputManager->render();
g_window->render();
}
delete g_gameStateManager;
delete g_fontManager;
delete g_textureManager;
delete g_inputManager;
delete g_window;
return 0;
}
+95
View File
@@ -0,0 +1,95 @@
// #include <glm/gtx/string_cast.hpp>
#include <glm/gtx/transform.hpp> // glm::translate, glm::rotate, glm::scale
#include "object.h"
Object::Object() : Entity(), m_position(), m_rotation(), m_scale(), m_model()
{
// printf("obj: %s\n", glm::to_string(position()).c_str());
}
// -----------------------------------------
void Object::initialize()
{
}
void Object::update()
{
// Local space -> World space: model matrix
m_model = glm::mat4(1.0f);
// Translate
m_model = glm::translate(m_model, position());
// Rotate
m_model = glm::rotate(m_model, glm::radians(rotation().x),
glm::vec3(1.0, 0.0, 0.0));
m_model = glm::rotate(m_model, glm::radians(rotation().y),
glm::vec3(0.0, 1.0, 0.0));
m_model = glm::rotate(m_model, glm::radians(rotation().z),
glm::vec3(0.0, 0.0, 1.0));
// Scale
m_model = glm::scale(m_model, scale());
}
void Object::render()
{
}
void Object::destroy()
{
}
// -----------------------------------------
glm::vec3 Object::position() const
{
return m_position;
}
void Object::setPosition(glm::vec3 position)
{
m_position = position;
}
void Object::setPosition(float x, float y, float z)
{
m_position = glm::vec3(x, y, z);
}
glm::vec3 Object::rotation() const
{
return m_rotation;
}
void Object::setRotation(glm::vec3 rotation)
{
m_rotation = rotation;
}
void Object::setRotation(float x, float y, float z)
{
m_rotation = glm::vec3(x, y, z);
}
glm::vec3 Object::scale() const
{
return m_scale;
}
void Object::setScale(glm::vec3 scale)
{
m_scale = scale;
}
void Object::setScale(float x, float y, float z)
{
m_scale = glm::vec3(x, y, z);
}
glm::mat4 Object::model() const {
return m_model;
}
void Object::setModel(glm::mat4 model) {
m_model = model;
}
+162
View File
@@ -0,0 +1,162 @@
#include <climits> // UINT_MAX
#include <cstdio> // printf
#include <fstream> // ifstream
#include <iostream> // ios
#include <memory> // make_unique
#include <glad/glad.h>
#include <glm/gtc/type_ptr.hpp> // glm::value_ptr
#include "shader.h"
Shader::Shader(const std::string &vertexSource, const std::string &fragmentSource) :
m_program(0)
{
std::string vertex = readFile(vertexSource);
std::string fragment = readFile(fragmentSource);
unsigned int vertexShader = compileShader(GL_VERTEX_SHADER, vertex.c_str());
unsigned int fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragment.c_str());
if (vertexShader != UINT_MAX && fragmentShader != UINT_MAX) {
m_program = linkShader(vertexShader, fragmentShader);
}
}
Shader::~Shader()
{
if (m_program > 0) {
glDeleteProgram(m_program);
m_program = 0;
}
}
// -----------------------------------------
std::string Shader::readFile(const std::string &path) const
{
// Create input stream object and open file
std::ifstream file;
file.open(path.c_str(), std::ifstream::in);
// Check if file exists
if (!file.is_open()) {
printf("Shader::readFile::FAILED\n%s\n", path.c_str());
return nullptr;
}
// Get length of the file
file.seekg(0, std::ios::end);
unsigned int length = file.tellg();
file.seekg(0, std::ios::beg);
// Allocate memory filled with zeros
auto buffer = std::make_unique<char[]>(length + 1);
file.read(buffer.get(), length);
file.close();
// Create string from the buffer
std::string result = std::string(buffer.get(), length + 1);
return result;
}
unsigned int Shader::compileShader(unsigned int type, const char *source) const
{
// Create new shader
unsigned int shader;
shader = glCreateShader(type);
// Attach shader source to shader object
glShaderSource(shader, 1, &source, nullptr);
// Compile shader
glCompileShader(shader);
// Check compilation status
if (checkStatus(shader)) {
return shader;
}
// On fail
glDeleteShader(shader);
return UINT_MAX;
}
unsigned int Shader::linkShader(unsigned int vertex, unsigned int fragment) const
{
// Create new shader program
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
// Attach both shaders to the shader program
glAttachShader(shaderProgram, vertex);
glAttachShader(shaderProgram, fragment);
// Setup vertex attributes
glBindAttribLocation(shaderProgram, 0, "aPos");
// Link the shaders
glLinkProgram(shaderProgram);
// Clear resources
glDeleteShader(vertex);
glDeleteShader(fragment);
// Check linking status
if (checkStatus(shaderProgram, true)) {
return shaderProgram;
}
// On fail
glDeleteProgram(shaderProgram);
return UINT_MAX;
}
int Shader::checkStatus(unsigned int check, bool isProgram) const
{
int success;
char infoLog[INFO_LOG_SIZE];
// Check shader or program
!isProgram
? glGetShaderiv(check, GL_COMPILE_STATUS, &success)
: glGetProgramiv(check, GL_LINK_STATUS, &success);
if (!success) {
// Check shader or program
!isProgram
? glGetShaderInfoLog(check, INFO_LOG_SIZE, nullptr, infoLog)
: glGetProgramInfoLog(check, INFO_LOG_SIZE, nullptr, infoLog);
printf("Shader::checkStatus::FAILED\n%s\n", infoLog);
}
return success;
}
void Shader::use() const
{
glUseProgram(m_program);
}
void Shader::setFloat(const std::string &name, float f1, float f2, float f3, float f4) const
{
// Set uniform vec4 data
glUniform4f(glGetUniformLocation(m_program, name.c_str()), f1, f2, f3, f4);
}
void Shader::setFloat(const std::string &name, glm::vec3 v) const {
// Set uniform vec3 data
glUniform3f(glGetUniformLocation(m_program, name.c_str()), v.x, v.y, v.z);
}
void Shader::setFloat(const std::string &name, glm::vec4 v) const {
// Set uniform vec4 data
glUniform4f(glGetUniformLocation(m_program, name.c_str()), v.x, v.y, v.z, v.w);
// glUniform4fv(glGetUniformLocation(m_program, name.c_str()), 1, glm::value_ptr(v));
}
void Shader::setFloat(const std::string &name, glm::mat4 m) const {
// Set uniform mat4 data
glUniformMatrix4fv(glGetUniformLocation(m_program, name.c_str()),
1, GL_FALSE, glm::value_ptr(m));
}
// -----------------------------------------
unsigned int Shader::program() const
{
return m_program;
}
+100
View File
@@ -0,0 +1,100 @@
#include <cstdio> // printf
#include <glm/glm.hpp>
#include "cube.h"
#include "cubecolor.h"
#include "state/maingame.h"
#include "text.h"
void MainGame::initialize() {
printf("MainGame::initialize\n");
glm::vec3 cubeColors[CUBE_SIZE] = {
// Textured cube
glm::vec3( 0.6f, 0.2f, 0.2f),
glm::vec3( 0.2f, 0.6f, 0.2f),
glm::vec3( 0.2f, 0.2f, 0.6f),
glm::vec3( 1.0f, 1.0f, 1.0f),
glm::vec3( 1.0f, 1.0f, 1.0f),
glm::vec3( 1.0f, 1.0f, 1.0f),
// Colored cube
glm::vec3( 0.6f, 0.2f, 0.2f),
glm::vec3( 0.2f, 0.6f, 0.2f),
glm::vec3( 0.2f, 0.2f, 0.6f),
glm::vec3( 0.6f, 0.2f, 0.2f),
glm::vec3( 0.2f, 0.6f, 0.2f),
glm::vec3( 0.2f, 0.2f, 0.6f),
glm::vec3( 1.0f, 1.0f, 1.0f),
glm::vec3( 1.0f, 1.0f, 1.0f),
glm::vec3( 1.0f, 1.0f, 1.0f),
};
glm::vec3 cubePositions[CUBE_SIZE] = {
// Textured cube
glm::vec3( 0.0f, 0.0f, 0.0f),
glm::vec3( 2.0f, 0.0f, 0.0f),
glm::vec3( 4.0f, 0.0f, 0.0f),
glm::vec3( 0.0f, 2.0f, 0.0f),
glm::vec3( 2.0f, 2.0f, 0.0f),
glm::vec3( 4.0f, 2.0f, 0.0f),
// Colored cube
glm::vec3( 0.0f, 0.0f, 6.0f),
glm::vec3( 2.0f, 0.0f, 6.0f),
glm::vec3( 4.0f, 0.0f, 6.0f),
glm::vec3( 0.0f, 2.0f, 6.0f),
glm::vec3( 2.0f, 2.0f, 6.0f),
glm::vec3( 4.0f, 2.0f, 6.0f),
glm::vec3( 0.0f, 4.0f, 6.0f),
glm::vec3( 2.0f, 4.0f, 6.0f),
glm::vec3( 4.0f, 4.0f, 6.0f),
};
bool cubeLine[CUBE_SIZE] = {
// Colored cube
false,
false,
false,
true,
true,
true,
true,
};
for(int i = 0; i < CUBE; i++) {
m_object[i] = new Cube(cubeColors[i].x, cubeColors[i].y, cubeColors[i].z);
m_object[i]->setPosition(cubePositions[i]);
}
for(int i = CUBE; i < CUBE_SIZE; i++) {
m_object[i] = new CubeColor(cubeColors[i].x, cubeColors[i].y, cubeColors[i].z,
cubeLine[i - CUBE]);
m_object[i]->setPosition(cubePositions[i]);
}
m_text = new Text();
m_text->setText("Test");
}
void MainGame::update() {
for(int i = 0; i < CUBE_SIZE; i++) {
m_object[i]->update();
}
m_text->update();
}
void MainGame::render() {
for(int i = 0; i < CUBE_SIZE; i++) {
m_object[i]->render();
}
m_text->render();
}
void MainGame::destroy() {
for(int i = 0; i < CUBE_SIZE; i++) {
m_object[i]->destroy();
}
m_text->destroy();
}
+117
View File
@@ -0,0 +1,117 @@
#include <cstdio> // printf
// #include <iostream>
#include <glad/glad.h>
#include <glm/ext/matrix_clip_space.hpp> // glm::ortho
#include "font.h"
#include "shader.h"
#include "text.h"
#include "texture.h"
#include "window.h"
Text::Text() : Object(), m_color(1.0f), m_shader(nullptr), m_text("")
{
initialize();
}
Text::~Text()
{
destroy();
}
// -----------------------------------------
void Text::initialize()
{
setScale(1.0f, 1.0f, 1.0f);
m_shader = g_window->shaderFont();
// Generate buffer
glGenVertexArrays(1, &m_vao);
glGenBuffers(1, &m_vbo);
glBindVertexArray(m_vao);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Text::update()
{
setPosition(50.0f, 50.0f, 0.0f);
}
void Text::render()
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Render
m_shader->use();
m_shader->setFloat("color", m_color);
m_shader->setFloat("projection", glm::ortho(
0.0f, (float)g_window->width(),
0.0f, (float)g_window->height()));
// glActiveTexture(GL_TEXTURE0);
glBindVertexArray(m_vao);
// Iterate through all characters
std::string::const_iterator c;
for (c = m_text.begin(); c != m_text.end(); c++)
{
Character ch = g_fontManager->character(*c);
// printf("ch: %u, %d %d, %d %d, %u\n",
// ch.texture, ch.size.x, ch.size.y, ch.bearing.x, ch.bearing.y, ch.advance);
float xpos = position().x + ch.bearing.x * scale().x;
float ypos = position().y - (ch.size.y - ch.bearing.y) * scale().x;
// printf("xpos-ypos: %f, %f\n", xpos, ypos);
float w = ch.size.x * scale().x;
float h = ch.size.y * scale().x;
// printf("w-h: %f, %f\n", w, h);
// Update VBO for each character
float vertices[6][4] = {
{ xpos, ypos + h, 0.0, 0.0 },
{ xpos, ypos, 0.0, 1.0 },
{ xpos + w, ypos, 1.0, 1.0 },
{ xpos, ypos + h, 0.0, 0.0 },
{ xpos + w, ypos, 1.0, 1.0 },
{ xpos + w, ypos + h, 1.0, 0.0 }
};
// Render glyph texture over quad
glBindTexture(GL_TEXTURE_2D, ch.texture);
// Update content of VBO memory
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Render quad
glDrawArrays(GL_TRIANGLES, 0, 6);
// Now advance cursors for next glyph (note that advance is number of 1/64 pixels)
// Bitshift by 6 to get value in pixels (2^6 = 64)
setPosition(position().x + (ch.advance >> 6) * scale().x, position().y, position().z);
}
// printf("\n");
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
}
void Text::destroy()
{
}
// -----------------------------------------
void Text::setText(std::string text)
{
m_text = text;
}
+105
View File
@@ -0,0 +1,105 @@
#include <climits> // UINT_MAX
#include <glad/glad.h>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#include "texture.h"
unsigned int TextureManager::loadTexture(const std::string &path)
{
// Return previously loaded texture
auto iter = m_textureList.find(path);
if (iter != m_textureList.end()) {
return m_textureList[path];
}
int width;
int height;
int channels;
// Load image data
stbi_set_flip_vertically_on_load(true);
unsigned char *image = stbi_load(path.c_str(), &width, &height, &channels, STBI_default);
unsigned int texture = UINT_MAX;
if (!image) {
printf("TextureManager::loadTexure::FAILED\n%s\n", path.c_str());
}
else {
int format = 0;
if (channels == 3) {
format = GL_RGB;
}
else if (channels == 4) {
format = GL_RGBA;
}
// Generate texture
texture = createTexture(
format,
width,
height,
image,
GL_REPEAT,
GL_NEAREST,
GL_NEAREST,
true);
// Construct and insert new element in the unordered_map
m_textureList.emplace(path, texture);
}
// Clean resources
stbi_image_free(image);
return texture;
}
void TextureManager::deleteTexture(const unsigned int texture)
{
glDeleteTextures(1, &texture);
}
unsigned int TextureManager::createTexture(
int format, unsigned int width, unsigned int height, const void *image,
int wrap, int filterMin, int filterMag, bool genMipmap)
{
unsigned int texture = UINT_MAX;
// Create texture object
glGenTextures(1, &texture);
// Bind texture object
glBindTexture(GL_TEXTURE_2D, texture);
// Set unpacking of pixel data to byte-alignment,
// this prevents alignment issues when using a single byte for color
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Generate texture
glTexImage2D(
GL_TEXTURE_2D, // Texture target
0, // Midmap level, base starts at level 0
format, // Texture format
width, height, // Image width/height
0, // Always 0 (legacy)
format, // Texture source format
GL_UNSIGNED_BYTE, // Texture source datatype
image); // Image data
// Set the texture wrapping / filtering options
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap); // X
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap); // Y
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filterMin); // Minify
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterMag); // Magnify
if (genMipmap) {
// Automatically generate all mipmap levels
glGenerateMipmap(GL_TEXTURE_2D);
}
// Unbind texture object
glBindTexture(GL_TEXTURE_2D, 0);
return texture;
}
+215
View File
@@ -0,0 +1,215 @@
#include <cstdio> // printf
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <stb_image.h>
#include "camera.h"
#include "input.h"
#include "shader.h"
#include "window.h"
// Window::Window() : Entity(), m_width(0), m_height(0)
// {
// }
Window::Window(int width, int height) : Entity(), m_width(width), m_height(height)
{
this->initialize();
}
Window::~Window()
{
this->destroy();
}
bool Window::shouldClose()
{
return glfwWindowShouldClose(m_window);
}
// -----------------------------------------
void Window::initialize()
{
// Error callback function
glfwSetErrorCallback(Window::errorCallback);
// Init GLFW and set the required options
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
// Create a GLFWwindow object that can be used for GLFW's functions
m_window = glfwCreateWindow(m_width, m_height,
"Lines", NULL, NULL);
glfwMakeContextCurrent(m_window);
if (m_window == NULL) {
printf("Failed to create GLFW window\n");
glfwTerminate();
}
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
printf("Failed to initialize OpenGL context\n");
}
// Associate the wrapper to the window
glfwSetWindowUserPointer(m_window, this);
// Keyboard callback function
glfwSetKeyCallback(m_window, Window::keyCallback);
// Capture cursor and hide it
glfwSetInputMode(m_window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Mouse callback function
glfwSetCursorPosCallback(m_window, Window::mouseCallback);
// Load shaders
m_shader = new Shader("../data/glsl/simple.vert", "../data/glsl/simple.frag");
m_shaderColor = new Shader("../data/glsl/color.vert", "../data/glsl/color.frag");
m_shaderFont = new Shader("../data/glsl/font.vert", "../data/glsl/font.frag");
// Enable z-buffer / depth buffer
glEnable(GL_DEPTH_TEST);
m_lastFrameTime = 0.0f;
m_deltaTime = 0.0f;
// Initialize camera
m_camera = new Camera();
m_camera->initialize();
}
void Window::update()
{
// Clear buffers
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Check if any events have been activated (keypresses, mouse movement)
glfwPollEvents();
// Reset the viewport to the new window size
glfwGetFramebufferSize(m_window, &m_width, &m_height);
m_aspect = (float)m_width / (float)m_height;
glViewport(0, 0, m_width, m_height);
// Calculate delta time
m_currentTime = glfwGetTime();
m_deltaTime = m_currentTime - m_lastFrameTime;
m_lastFrameTime = m_currentTime;
m_camera->update();
}
void Window::render()
{
m_camera->render();
// Swap the screen buffers
glfwSwapBuffers(m_window);
}
void Window::destroy()
{
delete m_shader;
delete m_shaderColor;
delete m_shaderFont;
delete m_camera;
// Clean GLFW allocated resources
glfwDestroyWindow(m_window);
glfwTerminate();
printf("Cleaned up GLFW resources..\n");
}
// -----------------------------------------
int Window::width()
{
return m_width;
}
int Window::height()
{
return m_height;
}
float Window::aspect()
{
return m_aspect;
}
float Window::currentTime()
{
return m_currentTime;
}
float Window::deltaTime()
{
return m_deltaTime;
}
GLFWwindow *Window::window()
{
return m_window;
}
Shader *Window::shader()
{
return m_shader;
}
Shader *Window::shaderColor()
{
return m_shaderColor;
}
Shader *Window::shaderFont()
{
return m_shaderFont;
}
Camera *Window::camera()
{
return m_camera;
}
// -----------------------------------------
void Window::errorCallback(int error, const char* description)
{
fputs(description, stderr);
// Suppress unused warning
(void)error;
}
void Window::keyCallback(GLFWwindow* window, int key, int scancode,
int action, int mode)
{
// printf("%d\n", key);
// Quit game
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
// Mouse capture
if (key == GLFW_KEY_LEFT_SUPER && action == GLFW_PRESS)
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
else
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
g_inputManager->setKeyState(key, scancode, action, mode);
}
void Window::mouseCallback(GLFWwindow* window, double xpos, double ypos)
{
g_inputManager->setMouse(xpos, ypos);
// Suppress unused warning
(void)window;
}