Added Namespace: charcoal

This commit is contained in:
elipzer 2018-09-12 17:03:46 -04:00
parent 3205680062
commit 77e8b0de5e
41 changed files with 1322 additions and 1227 deletions

View File

@ -4,77 +4,80 @@
#include "Util.h" #include "Util.h"
Application::Application(int width, int height) namespace charcoal
: m_screen_size(width, height)
{ {
if (width < 0 || height < 0) Application::Application(int width, int height)
throw EXCEPTION("Invalid screen dimensions"); : m_screen_size(width, height)
if (!glfwInit())
throw EXCEPTION("Unable to Initialize GLFW");
m_p_window = glfwCreateWindow(width, height, "OpenGLEngine", NULL, NULL);
if (!m_p_window)
{ {
glfwTerminate(); if (width < 0 || height < 0)
throw EXCEPTION("Unable to Create GLFW Window"); throw EXCEPTION("Invalid screen dimensions");
}
glfwSwapInterval(1); if (!glfwInit())
throw EXCEPTION("Unable to Initialize GLFW");
glfwMakeContextCurrent(m_p_window); m_p_window = glfwCreateWindow(width, height, "OpenGLEngine", NULL, NULL);
if (!m_p_window)
glewExperimental = GL_TRUE;
GLenum glew_err = glewInit();
if (glew_err != GLEW_OK)
{
glfwTerminate();
throw EXCEPTION("Unable to Initialize GLEW: " + std::string((char*)glewGetErrorString(glew_err)));
}
// Output Version Information
OutputDebugString("\nOpenGL Version Information:\nRenderer: ");
OutputDebugString((char*)glGetString(GL_RENDERER));
OutputDebugString("\nOpenGL Version: ");
OutputDebugString((char*)glGetString(GL_VERSION));
OutputDebugString("\n\n");
// TODO: Mouse Movement, Mouse Scroll
m_glfw_input_manager.init(m_p_window);
glfwSetKeyCallback(m_p_window, &GLFWInputManager::key_callback);
m_fps.prepare();
}
int Application::run()
{
try
{
init();
while (!glfwWindowShouldClose(m_p_window))
{ {
// Handle all messages glfwTerminate();
m_glfw_input_manager.mark(); throw EXCEPTION("Unable to Create GLFW Window");
glfwPollEvents();
float delta_time = m_fps.mark();
clock_t clock = m_fps.get_clock();
update(delta_time, clock);
prerender();
render();
CHECK_GL_ERR();
glfwSwapBuffers(m_p_window);
} }
return 0; glfwSwapInterval(1);
}
catch (Exception& e)
{
glfwTerminate();
throw e;
}
}
void Application::base_close() glfwMakeContextCurrent(m_p_window);
{
close(); glewExperimental = GL_TRUE;
} GLenum glew_err = glewInit();
if (glew_err != GLEW_OK)
{
glfwTerminate();
throw EXCEPTION("Unable to Initialize GLEW: " + std::string((char*)glewGetErrorString(glew_err)));
}
// Output Version Information
OutputDebugString("\nOpenGL Version Information:\nRenderer: ");
OutputDebugString((char*)glGetString(GL_RENDERER));
OutputDebugString("\nOpenGL Version: ");
OutputDebugString((char*)glGetString(GL_VERSION));
OutputDebugString("\n\n");
// TODO: Mouse Movement, Mouse Scroll
m_glfw_input_manager.init(m_p_window);
glfwSetKeyCallback(m_p_window, &GLFWInputManager::key_callback);
m_fps.prepare();
}
int Application::run()
{
try
{
init();
while (!glfwWindowShouldClose(m_p_window))
{
// Handle all messages
m_glfw_input_manager.mark();
glfwPollEvents();
float delta_time = m_fps.mark();
clock_t clock = m_fps.get_clock();
update(delta_time, clock);
prerender();
render();
CHECK_GL_ERR();
glfwSwapBuffers(m_p_window);
}
return 0;
}
catch (Exception& e)
{
glfwTerminate();
throw e;
}
}
void Application::base_close()
{
close();
}
}

View File

@ -9,43 +9,45 @@
// TODO: Close without rendering next frame. // TODO: Close without rendering next frame.
using namespace glm; namespace charcoal
class Application
{ {
public: using namespace glm;
Application(int width = -1, int height = -1);
virtual ~Application() {}
int run(); class Application
{
public:
Application(int width = -1, int height = -1);
virtual ~Application() {}
const ivec2& get_screen_size() const { return m_screen_size; } int run();
const GLFWInputManager& get_input_manager() const { return m_glfw_input_manager; } const ivec2& get_screen_size() const { return m_screen_size; }
const FPS& get_fps() const { return m_fps; } const GLFWInputManager& get_input_manager() const { return m_glfw_input_manager; }
protected: const FPS& get_fps() const { return m_fps; }
// Called on initialization of the application (called by base_init)
virtual void init() = 0;
virtual void update(float delta_time, clock_t clock) = 0; protected:
// Called on initialization of the application (called by base_init)
virtual void prerender() = 0; virtual void init() = 0;
virtual void render() = 0; virtual void update(float delta_time, clock_t clock) = 0;
// Called on closing of the application (called before base_close) virtual void prerender() = 0;
virtual void close() {}
GLFWwindow* m_p_window; virtual void render() = 0;
const ivec2 m_screen_size; // Called on closing of the application (called before base_close)
virtual void close() {}
GLFWInputManager m_glfw_input_manager; GLFWwindow* m_p_window;
FPS m_fps; const ivec2 m_screen_size;
private:
void base_close();
};
GLFWInputManager m_glfw_input_manager;
FPS m_fps;
private:
void base_close();
};
}

View File

@ -7,117 +7,115 @@
#include "Exception.h" #include "Exception.h"
namespace namespace charcoal
{ {
struct EmptyElement {}; template <typename VertexType, typename IndexType, int element_buffer_count = 0, typename Renderable = Renderable<VertexType, IndexType> >
} class Batch
template <typename VertexType, typename IndexType, int element_buffer_count = 0, typename Renderable = Renderable<VertexType, IndexType> >
class Batch
{
public:
typedef GLsizei SizeType;
Batch(
const Renderable* renderable,
const SizeType& element_render_count
)
: m_p_renderable(renderable), m_element_render_count(element_render_count), m_element_buffers(element_buffer_count)
{ {
if (std::is_same<unsigned int, IndexType>::value) public:
typedef GLsizei SizeType;
Batch(
const Renderable* renderable,
const SizeType& element_render_count
)
: m_p_renderable(renderable), m_element_render_count(element_render_count), m_element_buffers(element_buffer_count)
{ {
m_gl_index_type = GL_UNSIGNED_INT; if (std::is_same<unsigned int, IndexType>::value)
} {
else if (std::is_same<unsigned short, IndexType>::value) m_gl_index_type = GL_UNSIGNED_INT;
{ }
m_gl_index_type = GL_UNSIGNED_SHORT; else if (std::is_same<unsigned short, IndexType>::value)
} {
else if (std::is_same<unsigned char, IndexType>::value) m_gl_index_type = GL_UNSIGNED_SHORT;
{ }
m_gl_index_type = GL_UNSIGNED_BYTE; else if (std::is_same<unsigned char, IndexType>::value)
} {
else m_gl_index_type = GL_UNSIGNED_BYTE;
{ }
throw EXCEPTION("Invalid Batch IndexType"); else
{
throw EXCEPTION("Invalid Batch IndexType");
}
glGenVertexArrays(1, &m_vao);
glGenBuffers(1, &m_vertex_vbo);
glGenBuffers(1, &m_index_vbo);
glGenBuffers(element_buffer_count, m_element_buffers.data());
} }
glGenVertexArrays(1, &m_vao); virtual ~Batch()
glGenBuffers(1, &m_vertex_vbo); {
glGenBuffers(1, &m_index_vbo); glDeleteVertexArrays(1, &m_vao);
glDeleteBuffers(1, &m_vertex_vbo);
glDeleteBuffers(1, &m_index_vbo);
glGenBuffers(element_buffer_count, m_element_buffers.data()); glDeleteBuffers(element_buffer_count, m_element_buffers.data());
} }
virtual ~Batch() void init()
{ {
glDeleteVertexArrays(1, &m_vao); glBindBuffer(GL_ARRAY_BUFFER, m_vertex_vbo);
glDeleteBuffers(1, &m_vertex_vbo); glBufferData(GL_ARRAY_BUFFER, m_p_renderable->get_mesh()->vertex_count * sizeof(VertexType), m_p_renderable->get_mesh()->vertices, GL_STATIC_DRAW);
glDeleteBuffers(1, &m_index_vbo); glBindBuffer(GL_ARRAY_BUFFER, NULL);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_vbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_p_renderable->get_mesh()->index_count * sizeof(IndexType), m_p_renderable->get_mesh()->indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL);
glDeleteBuffers(element_buffer_count, m_element_buffers.data()); setup_element_buffers();
}
void init() glBindVertexArray(m_vao); // Possibly want to move these three lines into the init function
{ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vertex_vbo);
glBufferData(GL_ARRAY_BUFFER, m_p_renderable->get_mesh()->vertex_count * sizeof(VertexType), m_p_renderable->get_mesh()->vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, NULL);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_vbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_p_renderable->get_mesh()->index_count * sizeof(IndexType), m_p_renderable->get_mesh()->indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL);
setup_element_buffers(); setup_vao();
glBindVertexArray(m_vao); // Possibly want to move these three lines into the init function glBindVertexArray(NULL);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_vbo); }
setup_vao(); void prerender()
{
update_element_buffers();
}
glBindVertexArray(NULL); void render() const
} {
glBindVertexArray(m_vao);
glDrawElementsInstanced(
m_p_renderable->get_draw_mode(),
m_p_renderable->get_mesh()->index_count,
m_gl_index_type,
0,
m_element_render_count
);
glBindVertexArray(NULL);
}
void prerender() void set_element_render_count(const SizeType& element_render_count)
{ {
update_element_buffers(); m_element_render_count = element_render_count;
} }
void render() const const Renderable* get_renderable() const { return m_p_renderable; }
{
glBindVertexArray(m_vao);
glDrawElementsInstanced(
m_p_renderable->get_draw_mode(),
m_p_renderable->get_mesh()->index_count,
m_gl_index_type,
0,
m_element_render_count
);
glBindVertexArray(NULL);
}
void set_element_render_count(const SizeType& element_render_count) SizeType get_element_render_count() const { return m_element_render_count; }
{
m_element_render_count = element_render_count;
}
const Renderable* get_renderable() const { return m_p_renderable; } protected:
virtual void setup_element_buffers() {}
SizeType get_element_render_count() const { return m_element_render_count; } virtual void setup_vao() = 0;
protected: virtual void update_element_buffers() {}
virtual void setup_element_buffers() {}
virtual void setup_vao() = 0; const Renderable* m_p_renderable;
SizeType m_element_render_count;
virtual void update_element_buffers() {} GLuint m_vertex_vbo;
std::vector<GLuint> m_element_buffers;
const Renderable* m_p_renderable; private:
SizeType m_element_render_count; GLuint m_vao;
GLuint m_index_vbo;
GLuint m_vertex_vbo; GLenum m_gl_index_type;
std::vector<GLuint> m_element_buffers; };
}
private:
GLuint m_vao;
GLuint m_index_vbo;
GLenum m_gl_index_type;
};

View File

@ -4,20 +4,23 @@
#include "Poseable.h" #include "Poseable.h"
using namespace glm; namespace charcoal
class Camera
{ {
public: using namespace glm;
Camera() : m_view_matrix(1.0f), m_projection_matrix(1.0f) {}
mat4 get_world_to_view_matrix() const { return m_projection_matrix * m_view_matrix; } class Camera
{
public:
Camera() : m_view_matrix(1.0f), m_projection_matrix(1.0f) {}
const mat4& get_view_matrix() const { return m_view_matrix; } mat4 get_world_to_view_matrix() const { return m_projection_matrix * m_view_matrix; }
const mat4& get_projection_matrix() const { return m_projection_matrix; } const mat4& get_view_matrix() const { return m_view_matrix; }
protected: const mat4& get_projection_matrix() const { return m_projection_matrix; }
mat4 m_view_matrix;
mat4 m_projection_matrix; protected:
}; mat4 m_view_matrix;
mat4 m_projection_matrix;
};
}

View File

@ -2,46 +2,50 @@
#include "Exception.h" #include "Exception.h"
Camera2D::Camera2D(const vec2& size, const vec2& position) namespace charcoal
: Camera2D(vec3(size.x, size.y, 2.0f), vec3(position.x, position.y, 0.0f)) {}
Camera2D::Camera2D(const vec3& size, const vec3& position)
{ {
update_size(size); Camera2D::Camera2D(const vec2& size, const vec2& position)
update_position(position); : Camera2D(vec3(size.x, size.y, 2.0f), vec3(position.x, position.y, 0.0f))
} {}
void Camera2D::update_size(const vec3& size) Camera2D::Camera2D(const vec3& size, const vec3& position)
{ {
m_size = size; update_size(size);
update_scale(); update_position(position);
} }
void Camera2D::update_position(const vec3& position) void Camera2D::update_size(const vec3& size)
{ {
m_position = position; m_size = size;
} update_scale();
}
void Camera2D::translate(const vec2& translation) void Camera2D::update_position(const vec3& position)
{ {
translate(vec3(translation.x, translation.y, 0.0f)); m_position = position;
} }
void Camera2D::translate(const vec3& translation) void Camera2D::translate(const vec2& translation)
{ {
m_position += translation; translate(vec3(translation.x, translation.y, 0.0f));
} }
void Camera2D::prerender() void Camera2D::translate(const vec3& translation)
{ {
m_view_matrix[3][0] = -m_position.x; m_position += translation;
m_view_matrix[3][1] = -m_position.y; }
m_view_matrix[3][2] = -m_position.z;
}
void Camera2D::update_scale() void Camera2D::prerender()
{ {
m_projection_matrix[0][0] = 2.0f / m_size.x; m_view_matrix[3][0] = -m_position.x;
m_projection_matrix[1][1] = 2.0f / m_size.y; m_view_matrix[3][1] = -m_position.y;
m_projection_matrix[2][2] = -2.0f / m_size.z; m_view_matrix[3][2] = -m_position.z;
}
void Camera2D::update_scale()
{
m_projection_matrix[0][0] = 2.0f / m_size.x;
m_projection_matrix[1][1] = 2.0f / m_size.y;
m_projection_matrix[2][2] = -2.0f / m_size.z;
}
} }

View File

@ -4,28 +4,31 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
using namespace glm; namespace charcoal
class Camera2D : public Camera
{ {
public: using namespace glm;
Camera2D(const vec2& size, const vec2& position = vec2(0.0f, 0.0f));
Camera2D(const vec3& size = vec3(2.0f, 2.0f, 2.0f), const vec3& position = vec3(0.0f, 0.0f, 0.0f));
void update_size(const vec3& size); class Camera2D : public Camera
void update_position(const vec3& position); {
public:
Camera2D(const vec2& size, const vec2& position = vec2(0.0f, 0.0f));
Camera2D(const vec3& size = vec3(2.0f, 2.0f, 2.0f), const vec3& position = vec3(0.0f, 0.0f, 0.0f));
void translate(const vec2& translation); void update_size(const vec3& size);
void translate(const vec3& translation); void update_position(const vec3& position);
void prerender(); void translate(const vec2& translation);
void translate(const vec3& translation);
const vec3& get_size() const { return m_size; } void prerender();
const vec3& get_position() const { return m_position; }
private: const vec3& get_size() const { return m_size; }
void update_scale(); const vec3& get_position() const { return m_position; }
vec3 m_size; private:
vec3 m_position; void update_scale();
};
vec3 m_size;
vec3 m_position;
};
}

View File

@ -2,79 +2,82 @@
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
Camera3D::Camera3D( namespace charcoal
float fov_y,
float aspect_ratio,
float znear,
float zfar,
const vec3& position,
const vec3& forward,
const vec3& up,
const vec3& right
)
{ {
update_frustum(fov_y, aspect_ratio, znear, zfar); Camera3D::Camera3D(
update_position(position); float fov_y,
update_orientation(forward, up, right); float aspect_ratio,
} float znear,
float zfar,
const vec3& position,
const vec3& forward,
const vec3& up,
const vec3& right
)
{
update_frustum(fov_y, aspect_ratio, znear, zfar);
update_position(position);
update_orientation(forward, up, right);
}
void Camera3D::update_frustum(float fov_y, float aspect_ratio, float znear, float zfar) void Camera3D::update_frustum(float fov_y, float aspect_ratio, float znear, float zfar)
{ {
m_projection_matrix = glm::perspective(fov_y, aspect_ratio, znear, zfar); m_projection_matrix = glm::perspective(fov_y, aspect_ratio, znear, zfar);
} }
void Camera3D::update_position(const vec3& position) void Camera3D::update_position(const vec3& position)
{ {
m_position = position; m_position = position;
} }
void Camera3D::update_orientation(const vec3& forward, const vec3& up, const vec3& right) void Camera3D::update_orientation(const vec3& forward, const vec3& up, const vec3& right)
{ {
vec3 real_forward; vec3 real_forward;
vec3 real_up; vec3 real_up;
vec3 real_right; vec3 real_right;
if (right == vec3(0.0f)) if (right == vec3(0.0f))
real_right = glm::normalize(glm::cross(forward, up)); real_right = glm::normalize(glm::cross(forward, up));
else else
real_right = right; real_right = right;
real_forward = glm::normalize(forward); real_forward = glm::normalize(forward);
real_up = glm::cross(real_right, real_forward); real_up = glm::cross(real_right, real_forward);
m_forward = vec4(real_forward, 0.0f); m_forward = vec4(real_forward, 0.0f);
m_up = vec4(real_up, 0.0f); m_up = vec4(real_up, 0.0f);
m_right = vec4(real_right, 0.0f); m_right = vec4(real_right, 0.0f);
} }
void Camera3D::direct_update_orientation(const vec3& forward, const vec3& up, const vec3& right) void Camera3D::direct_update_orientation(const vec3& forward, const vec3& up, const vec3& right)
{ {
m_forward = vec4(forward, 0.0f); m_forward = vec4(forward, 0.0f);
m_up = vec4(up, 0.0f); m_up = vec4(up, 0.0f);
m_right = vec4(right, 0.0f); m_right = vec4(right, 0.0f);
} }
void Camera3D::translate(const vec3& translation) void Camera3D::translate(const vec3& translation)
{ {
m_position += translation; m_position += translation;
} }
void Camera3D::rotate(const vec3& axis, float angle) void Camera3D::rotate(const vec3& axis, float angle)
{ {
mat4 rotation = glm::rotate(mat4(1.0f), angle, axis); mat4 rotation = glm::rotate(mat4(1.0f), angle, axis);
m_forward = rotation * m_forward; m_forward = rotation * m_forward;
m_up = rotation * m_up; m_up = rotation * m_up;
m_right = rotation * m_right; m_right = rotation * m_right;
} }
void Camera3D::prerender() void Camera3D::prerender()
{ {
// This works but it mirrors the scene left and right? // This works but it mirrors the scene left and right?
m_view_matrix = mat4( m_view_matrix = mat4(
vec4(m_right.x, m_up.x, -m_forward.x, 0.0f), vec4(m_right.x, m_up.x, -m_forward.x, 0.0f),
vec4(m_right.y, m_up.y, -m_forward.y, 0.0f), vec4(m_right.y, m_up.y, -m_forward.y, 0.0f),
vec4(m_right.z, m_up.z, -m_forward.z, 0.0f), vec4(m_right.z, m_up.z, -m_forward.z, 0.0f),
vec4(-glm::dot(vec3(m_right), m_position), -glm::dot(vec3(m_up), m_position), glm::dot(vec3(m_forward), m_position), 1.0f) vec4(-glm::dot(vec3(m_right), m_position), -glm::dot(vec3(m_up), m_position), glm::dot(vec3(m_forward), m_position), 1.0f)
); );
}
} }

View File

@ -4,44 +4,47 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
using namespace glm; namespace charcoal
class Camera3D : public Camera
{ {
public: using namespace glm;
Camera3D(
float fov_y,
float aspect_ratio,
float znear,
float zfar,
const vec3& position,
const vec3& forward = vec3(0.0f, 0.0f, 1.0f),
const vec3& up = vec3(0.0f, 1.0f, 0.0f),
const vec3& right = vec3(0.0f) // Zero for auto-calculated
);
void update_frustum(float fov_y, float aspect_ratio, float znear, float zfar); class Camera3D : public Camera
void update_position(const vec3& position); {
// Updates the orientation based on three vectors. public:
// If right is equal to zero it is calculated with glm::cross(forward, up). Camera3D(
// Then the true up is calculated with glm::cross(right, forward) float fov_y,
void update_orientation(const vec3& forward = vec3(0.0f, 0.0f, 1.0f), const vec3& up = vec3(0.0f, 1.0f, 0.0f), const vec3& right = vec3(0.0f)); float aspect_ratio,
// Directly sets the forward, up, and right values. float znear,
void direct_update_orientation(const vec3& forward, const vec3& up, const vec3& right); float zfar,
const vec3& position,
const vec3& forward = vec3(0.0f, 0.0f, 1.0f),
const vec3& up = vec3(0.0f, 1.0f, 0.0f),
const vec3& right = vec3(0.0f) // Zero for auto-calculated
);
void translate(const vec3& translation); void update_frustum(float fov_y, float aspect_ratio, float znear, float zfar);
void rotate(const vec3& axis, float angle); void update_position(const vec3& position);
// Updates the orientation based on three vectors.
// If right is equal to zero it is calculated with glm::cross(forward, up).
// Then the true up is calculated with glm::cross(right, forward)
void update_orientation(const vec3& forward = vec3(0.0f, 0.0f, 1.0f), const vec3& up = vec3(0.0f, 1.0f, 0.0f), const vec3& right = vec3(0.0f));
// Directly sets the forward, up, and right values.
void direct_update_orientation(const vec3& forward, const vec3& up, const vec3& right);
void prerender(); void translate(const vec3& translation);
void rotate(const vec3& axis, float angle);
const vec3& get_position() const { return m_position; } void prerender();
vec3 get_forward() const { return vec3(m_forward); }
vec3 get_up() const { return vec3(m_up); }
vec3 get_right() const { return vec3(m_right); }
private: const vec3& get_position() const { return m_position; }
vec3 m_position; vec3 get_forward() const { return vec3(m_forward); }
vec4 m_forward; vec3 get_up() const { return vec3(m_up); }
vec4 m_up; vec3 get_right() const { return vec3(m_right); }
vec4 m_right;
}; private:
vec3 m_position;
vec4 m_forward;
vec4 m_up;
vec4 m_right;
};
}

View File

@ -2,18 +2,21 @@
#include "stdafx.h" #include "stdafx.h"
enum DrawMode : GLenum namespace charcoal
{ {
DRAW_POINTS = GL_POINTS, enum DrawMode : GLenum
DRAW_LINE_STRIP = GL_LINE_STRIP, {
DRAW_LINE_LOOP = GL_LINE_LOOP, DRAW_POINTS = GL_POINTS,
DRAW_LINES = GL_LINES, DRAW_LINE_STRIP = GL_LINE_STRIP,
DRAW_LINE_STRIP_ADJACENCY = GL_LINE_STRIP_ADJACENCY, DRAW_LINE_LOOP = GL_LINE_LOOP,
DRAW_LINES_ADJACENCY = GL_LINES_ADJACENCY, DRAW_LINES = GL_LINES,
DRAW_TRIANGLE_STRIP = GL_TRIANGLE_STRIP, DRAW_LINE_STRIP_ADJACENCY = GL_LINE_STRIP_ADJACENCY,
DRAW_TRIANGLE_FAN = GL_TRIANGLE_FAN, DRAW_LINES_ADJACENCY = GL_LINES_ADJACENCY,
DRAW_TRIANGLES = GL_TRIANGLES, DRAW_TRIANGLE_STRIP = GL_TRIANGLE_STRIP,
DRAW_TRIANGLE_STRIP_ADJACENCY = GL_TRIANGLE_STRIP_ADJACENCY, DRAW_TRIANGLE_FAN = GL_TRIANGLE_FAN,
DRAW_TRIANGLES_ADJACENCY = GL_TRIANGLES_ADJACENCY, DRAW_TRIANGLES = GL_TRIANGLES,
DRAW_PATCHES = GL_PATCHES, DRAW_TRIANGLE_STRIP_ADJACENCY = GL_TRIANGLE_STRIP_ADJACENCY,
}; DRAW_TRIANGLES_ADJACENCY = GL_TRIANGLES_ADJACENCY,
DRAW_PATCHES = GL_PATCHES,
};
}

View File

@ -5,19 +5,22 @@
// TODO: This MUST be changed to something less generic // TODO: This MUST be changed to something less generic
#define EXCEPTION(message) Exception(message, __FILE__, __LINE__) #define EXCEPTION(message) Exception(message, __FILE__, __LINE__)
class Exception namespace charcoal
{ {
public: class Exception
Exception(const std::string& message, const std::string& file_name, int line) {
: m_message(message), m_file_name(file_name), m_line(line) public:
{} Exception(const std::string& message, const std::string& file_name, int line)
: m_message(message), m_file_name(file_name), m_line(line)
{}
const std::string& get_message() { return m_message; } const std::string& get_message() { return m_message; }
const std::string& get_file_name() { return m_file_name; } const std::string& get_file_name() { return m_file_name; }
int get_line() { return m_line; } int get_line() { return m_line; }
private: private:
std::string m_message; std::string m_message;
std::string m_file_name; std::string m_file_name;
int m_line; int m_line;
}; };
}

View File

@ -1,48 +1,51 @@
#include "FPS.h" #include "FPS.h"
FPS::FPS(unsigned short frames /* = 2 */) : namespace charcoal
m_iter(frames), m_frames(frames)
{ {
if (frames < 2) FPS::FPS(unsigned short frames /* = 2 */) :
throw "Frames is too small"; m_iter(frames), m_frames(frames)
m_clocks = new clock_t[m_frames]; {
} if (frames < 2)
throw "Frames is too small";
m_clocks = new clock_t[m_frames];
}
FPS::~FPS() FPS::~FPS()
{ {
if (m_clocks) if (m_clocks)
delete[] m_clocks; delete[] m_clocks;
} }
const clock_t& FPS::get_clock() const const clock_t& FPS::get_clock() const
{ {
return m_clocks[m_iter]; return m_clocks[m_iter];
} }
float FPS::get_spf() const float FPS::get_spf() const
{ {
clock_t diff = (m_clocks[m_iter] - m_clocks[(m_iter + 1) % m_frames]) / (m_frames - 1); clock_t diff = (m_clocks[m_iter] - m_clocks[(m_iter + 1) % m_frames]) / (m_frames - 1);
return ((float)diff) / CLOCKS_PER_SEC; return ((float)diff) / CLOCKS_PER_SEC;
} }
float FPS::get_fps() const float FPS::get_fps() const
{ {
clock_t diff = (m_clocks[m_iter] - m_clocks[(m_iter + 1) % m_frames]) / (m_frames - 1); clock_t diff = (m_clocks[m_iter] - m_clocks[(m_iter + 1) % m_frames]) / (m_frames - 1);
return ((float)CLOCKS_PER_SEC) / diff; return ((float)CLOCKS_PER_SEC) / diff;
} }
void FPS::prepare() void FPS::prepare()
{ {
clock_t c = clock(); clock_t c = clock();
for (unsigned short i = 0; i < m_frames; ++i) for (unsigned short i = 0; i < m_frames; ++i)
m_clocks[i] = c; m_clocks[i] = c;
} }
float FPS::mark() float FPS::mark()
{ {
(++m_iter) %= m_frames; (++m_iter) %= m_frames;
m_clocks[m_iter] = clock(); m_clocks[m_iter] = clock();
clock_t diff = (m_clocks[m_iter] - m_clocks[(m_iter > 0 ? m_iter - 1 : m_frames - 1)]); clock_t diff = (m_clocks[m_iter] - m_clocks[(m_iter > 0 ? m_iter - 1 : m_frames - 1)]);
return ((float)diff) / CLOCKS_PER_SEC; return ((float)diff) / CLOCKS_PER_SEC;
}
} }

View File

@ -2,43 +2,46 @@
#include <ctime> #include <ctime>
//A class to handle the FPS of the game namespace charcoal
//Calculations are done per the number of frames specified
//Frames must be a value from 2 - 255
//Recommended numbers for frames is 2 (Instant), 5 (Slightly Smoothed), 60 (Smoothed)
//Max number for frames = 255
//Lower frames = jumpy, instant updates
//Higher frames = smoother, flowing updates
class FPS final
{ {
public: //A class to handle the FPS of the game
FPS(unsigned short frames = 2); //Calculations are done per the number of frames specified
~FPS(); //Frames must be a value from 2 - 255
//Recommended numbers for frames is 2 (Instant), 5 (Slightly Smoothed), 60 (Smoothed)
//Max number for frames = 255
//Lower frames = jumpy, instant updates
//Higher frames = smoother, flowing updates
class FPS final
{
public:
FPS(unsigned short frames = 2);
~FPS();
//Returns the clock of the last mark() call //Returns the clock of the last mark() call
const clock_t& get_clock() const; const clock_t& get_clock() const;
//Returns FPS (frames per second) of the game (based on the last marked frame) //Returns FPS (frames per second) of the game (based on the last marked frame)
//CLOCKS_PER_SECOND / (m_clock - m_prevClock) //CLOCKS_PER_SECOND / (m_clock - m_prevClock)
float get_spf() const; float get_spf() const;
//Returns FPS (frames per second) of the game (based on the last marked frame) //Returns FPS (frames per second) of the game (based on the last marked frame)
//CLOCKS_PER_SECOND / (m_clock - m_prevClock) //CLOCKS_PER_SECOND / (m_clock - m_prevClock)
float get_fps() const; float get_fps() const;
//Fills the clocks with the current clock() value (to prevent unreasonable clock counts at the first few frames) //Fills the clocks with the current clock() value (to prevent unreasonable clock counts at the first few frames)
void prepare(); void prepare();
//Marks the end of the frame (resets the clock) //Marks the end of the frame (resets the clock)
//Should be called right before the update() and render() functions //Should be called right before the update() and render() functions
//Also calculates the seconds per frame (able to be considered the dTime) //Also calculates the seconds per frame (able to be considered the dTime)
//(m_clock - m_prevClock) / CLOCKS_PER_SEC //(m_clock - m_prevClock) / CLOCKS_PER_SEC
float mark(); float mark();
private: private:
//m_iter marks the place of the next mark //m_iter marks the place of the next mark
unsigned short m_iter; unsigned short m_iter;
unsigned short m_frames; unsigned short m_frames;
clock_t* m_clocks = nullptr; clock_t* m_clocks = nullptr;
}; };
}

View File

@ -2,33 +2,36 @@
#include "Exception.h" #include "Exception.h"
std::map<GLFWwindow*, GLFWInputManager*> GLFWInputManager::s_glfw_windows; namespace charcoal
GLFWInputManager::~GLFWInputManager()
{ {
s_glfw_windows.erase(m_p_window); std::map<GLFWwindow*, GLFWInputManager*> GLFWInputManager::s_glfw_windows;
}
void GLFWInputManager::init(GLFWwindow* p_window) GLFWInputManager::~GLFWInputManager()
{ {
if (m_p_window != nullptr) s_glfw_windows.erase(m_p_window);
throw EXCEPTION("GLFWInputManager Already Initialized."); }
m_p_window = p_window;
s_glfw_windows.insert(std::map<GLFWwindow*, GLFWInputManager*>::value_type(m_p_window, this));
}
void GLFWInputManager::key_callback(GLFWwindow* p_window, int key, int scancode, int action, int mods) void GLFWInputManager::init(GLFWwindow* p_window)
{ {
std::map<GLFWwindow*, GLFWInputManager*>::iterator iter = s_glfw_windows.find(p_window); if (m_p_window != nullptr)
if (iter == s_glfw_windows.end()) throw EXCEPTION("GLFWInputManager Already Initialized.");
return; // Ignore Unknown Windows m_p_window = p_window;
GLFWInputManager& input_manager = *iter->second; s_glfw_windows.insert(std::map<GLFWwindow*, GLFWInputManager*>::value_type(m_p_window, this));
if (action == GLFW_PRESS) }
input_manager.key_down(key);
else if (action == GLFW_RELEASE) void GLFWInputManager::key_callback(GLFWwindow* p_window, int key, int scancode, int action, int mods)
input_manager.key_up(key); {
else if (action == GLFW_REPEAT) { /* Ignored */} std::map<GLFWwindow*, GLFWInputManager*>::iterator iter = s_glfw_windows.find(p_window);
else if (iter == s_glfw_windows.end())
throw EXCEPTION("Invalid GLFW Key Action: " + std::to_string(action) + " (" + std::to_string(scancode) + ")"); return; // Ignore Unknown Windows
GLFWInputManager& input_manager = *iter->second;
} if (action == GLFW_PRESS)
input_manager.key_down(key);
else if (action == GLFW_RELEASE)
input_manager.key_up(key);
else if (action == GLFW_REPEAT) { /* Ignored */ }
else
throw EXCEPTION("Invalid GLFW Key Action: " + std::to_string(action) + " (" + std::to_string(scancode) + ")");
}
}

View File

@ -6,16 +6,19 @@
#include <map> #include <map>
class GLFWInputManager : public InputManager namespace charcoal
{ {
public: class GLFWInputManager : public InputManager
~GLFWInputManager(); {
public:
~GLFWInputManager();
void init(GLFWwindow* p_window); void init(GLFWwindow* p_window);
static void key_callback(GLFWwindow* p_window, int key, int scancode, int action, int mods); static void key_callback(GLFWwindow* p_window, int key, int scancode, int action, int mods);
private: private:
GLFWwindow* m_p_window = nullptr; GLFWwindow* m_p_window = nullptr;
static std::map<GLFWwindow*, GLFWInputManager*> s_glfw_windows; static std::map<GLFWwindow*, GLFWInputManager*> s_glfw_windows;
}; };
}

View File

@ -1,81 +1,83 @@
#include "InputManager.h" #include "InputManager.h"
InputManager::InputManager() {} namespace charcoal
InputManager::~InputManager() {}
void InputManager::mark()
{ {
m_keys_pressed.clear(); InputManager::InputManager() {}
m_mouse_delta = { 0, 0 };
m_scroll_distance = 0;
}
void InputManager::key_down(KeyCode key_code) InputManager::~InputManager() {}
{
if (!m_keys_down[key_code]) void InputManager::mark()
{ {
m_keys_down[key_code] = true; m_keys_pressed.clear();
m_keys_pressed[key_code] = true; m_mouse_delta = { 0, 0 };
m_scroll_distance = 0;
} }
}
void InputManager::key_up(KeyCode key_code) void InputManager::key_down(KeyCode key_code)
{ {
m_keys_down[key_code] = false; if (!m_keys_down[key_code])
m_keys_pressed[key_code] = false; {
} m_keys_down[key_code] = true;
m_keys_pressed[key_code] = true;
}
}
void InputManager::mouse_move(const ivec2& position) void InputManager::key_up(KeyCode key_code)
{ {
m_mouse_delta += position - m_mouse_position; m_keys_down[key_code] = false;
m_mouse_position = position; m_keys_pressed[key_code] = false;
} }
void InputManager::mouse_scroll(int distance) void InputManager::mouse_move(const ivec2& position)
{ {
m_scroll_distance += distance; m_mouse_delta += position - m_mouse_position;
} m_mouse_position = position;
}
bool InputManager::is_key_down(KeyCode key_code) const void InputManager::mouse_scroll(int distance)
{ {
auto iter = m_keys_down.find(key_code); m_scroll_distance += distance;
if (iter == m_keys_down.end()) }
return false;
else
return iter->second;
}
bool InputManager::is_key_pressed(KeyCode key_code) const bool InputManager::is_key_down(KeyCode key_code) const
{ {
auto iter = m_keys_pressed.find(key_code); auto iter = m_keys_down.find(key_code);
if (iter == m_keys_pressed.end()) if (iter == m_keys_down.end())
return false; return false;
else else
return iter->second; return iter->second;
} }
bool InputManager::is_key_released(KeyCode key_code) const bool InputManager::is_key_pressed(KeyCode key_code) const
{ {
auto iter = m_keys_pressed.find(key_code); auto iter = m_keys_pressed.find(key_code);
if (iter == m_keys_pressed.end()) if (iter == m_keys_pressed.end())
return false; return false;
else else
return !iter->second; return iter->second;
} }
const ivec2& InputManager::get_mouse_position() const bool InputManager::is_key_released(KeyCode key_code) const
{ {
return m_mouse_position; auto iter = m_keys_pressed.find(key_code);
} if (iter == m_keys_pressed.end())
return false;
else
return !iter->second;
}
const ivec2& InputManager::get_mouse_delta() const const ivec2& InputManager::get_mouse_position() const
{ {
return m_mouse_delta; return m_mouse_position;
} }
const int& InputManager::get_scroll_distance() const const ivec2& InputManager::get_mouse_delta() const
{ {
return m_scroll_distance; return m_mouse_delta;
}
const int& InputManager::get_scroll_distance() const
{
return m_scroll_distance;
}
} }

View File

@ -44,50 +44,53 @@
#define K_Y 0x59 #define K_Y 0x59
#define K_Z 0x5A #define K_Z 0x5A
using namespace glm; namespace charcoal
class InputManager
{ {
public: using namespace glm;
typedef int KeyCode;
InputManager(); class InputManager
virtual ~InputManager(); {
public:
typedef int KeyCode;
//Should be called after each frame to reset the keysPressed InputManager();
void mark(); virtual ~InputManager();
bool is_key_down(KeyCode key_code) const; //Should be called after each frame to reset the keysPressed
bool is_key_pressed(KeyCode key_code) const; void mark();
bool is_key_released(KeyCode key_code) const;
const ivec2& get_mouse_position() const;
const ivec2& get_mouse_delta() const;
const int& get_scroll_distance() const;
protected: bool is_key_down(KeyCode key_code) const;
void key_down(KeyCode key_code); bool is_key_pressed(KeyCode key_code) const;
void key_up(KeyCode key_code); bool is_key_released(KeyCode key_code) const;
void mouse_move(const ivec2& position); const ivec2& get_mouse_position() const;
void mouse_scroll(int distance); const ivec2& get_mouse_delta() const;
const int& get_scroll_distance() const;
private: protected:
//Keys pressed since the last frame void key_down(KeyCode key_code);
//The existance of a value in this array means that the key has changed to that state void key_up(KeyCode key_code);
//since the last mark() call. void mouse_move(const ivec2& position);
//A value of true means the key was pressed, false means the value was released void mouse_scroll(int distance);
std::map<KeyCode, bool> m_keys_pressed;
//Keys that are down private:
std::map<KeyCode, bool> m_keys_down; //Keys pressed since the last frame
//The existance of a value in this array means that the key has changed to that state
//since the last mark() call.
//A value of true means the key was pressed, false means the value was released
std::map<KeyCode, bool> m_keys_pressed;
//Current Mouse Position //Keys that are down
ivec2 m_mouse_position; std::map<KeyCode, bool> m_keys_down;
//Change in mouse position since last mark() call //Current Mouse Position
ivec2 m_mouse_delta; ivec2 m_mouse_position;
//The change in scroll (mouse wheel) since the last mark() call //Change in mouse position since last mark() call
int m_scroll_distance; ivec2 m_mouse_delta;
//TODO: Controller Movement //The change in scroll (mouse wheel) since the last mark() call
}; int m_scroll_distance;
//TODO: Controller Movement
};
}

View File

@ -1,13 +1,16 @@
#pragma once #pragma once
template <typename VertexType, typename IndexType> namespace charcoal
struct Mesh
{ {
typedef VertexType VertexType; template <typename VertexType, typename IndexType>
typedef IndexType IndexType; struct Mesh
{
typedef VertexType VertexType;
typedef IndexType IndexType;
VertexType* vertices = nullptr; VertexType* vertices = nullptr;
unsigned int vertex_count = 0; unsigned int vertex_count = 0;
IndexType* indices = nullptr; IndexType* indices = nullptr;
unsigned int index_count = 0; unsigned int index_count = 0;
}; };
}

View File

@ -8,371 +8,374 @@
#include "Mesh.h" #include "Mesh.h"
template <typename VertexType, typename IndexType> namespace charcoal
class MeshFactory
{ {
public: template <typename VertexType, typename IndexType>
typedef Mesh<VertexType, IndexType> MeshType; class MeshFactory
private:
MeshFactory() {} // Prevent instanciation of this static class
public:
typedef unsigned int SizeType;
virtual ~MeshFactory()
{ {
for (SizeType i = 0; i < m_meshes.size(); ++i) public:
{ typedef Mesh<VertexType, IndexType> MeshType;
delete[] m_meshes[i]->vertices;
m_meshes[i]->vertices = nullptr;
delete[] m_meshes[i]->indices;
m_meshes[i]->indices = nullptr;
delete m_meshes[i];
m_meshes[i] = nullptr;
}
}
static MeshType* gen(const DrawMode& draw_mode, const VertexType& a) private:
{ MeshFactory() {} // Prevent instanciation of this static class
MeshType* mesh;
switch (draw_mode)
{
case DrawMode::DRAW_POINTS:
mesh = create_mesh(1, 1);
mesh->vertices[0] = a;
mesh->indices[0] = 0;
return mesh;
case DrawMode::DRAW_LINE_STRIP:
case DrawMode::DRAW_LINE_LOOP:
case DrawMode::DRAW_LINES:
case DrawMode::DRAW_TRIANGLE_STRIP:
case DrawMode::DRAW_TRIANGLE_FAN:
case DrawMode::DRAW_TRIANGLES:
case DrawMode::DRAW_LINE_STRIP_ADJACENCY:
case DrawMode::DRAW_LINES_ADJACENCY:
case DrawMode::DRAW_TRIANGLE_STRIP_ADJACENCY:
case DrawMode::DRAW_TRIANGLES_ADJACENCY:
case DrawMode::DRAW_PATCHES:
default:
throw EXCEPTION("Unable to gen for current draw mode: " + std::to_string(draw_mode));
}
}
static MeshType* gen(const DrawMode& draw_mode, const VertexType& a, const VertexType& b) public:
{ typedef unsigned int SizeType;
MeshType* mesh;
switch (draw_mode)
{
case DrawMode::DRAW_POINTS:
case DrawMode::DRAW_LINE_STRIP:
case DrawMode::DRAW_LINE_LOOP:
case DrawMode::DRAW_LINES:
mesh = create_mesh(2, 2);
mesh->vertices[0] = a;
mesh->vertices[1] = b;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
return mesh;
case DrawMode::DRAW_TRIANGLE_STRIP:
case DrawMode::DRAW_TRIANGLE_FAN:
case DrawMode::DRAW_TRIANGLES:
case DrawMode::DRAW_LINE_STRIP_ADJACENCY:
case DrawMode::DRAW_LINES_ADJACENCY:
case DrawMode::DRAW_TRIANGLE_STRIP_ADJACENCY:
case DrawMode::DRAW_TRIANGLES_ADJACENCY:
case DrawMode::DRAW_PATCHES:
default:
throw EXCEPTION("Unable to gen for current draw mode: " + std::to_string(draw_mode));
}
}
static MeshType* gen(const DrawMode& draw_mode, const VertexType& a, const VertexType& b, const VertexType& c) virtual ~MeshFactory()
{
MeshType* mesh;
switch (draw_mode)
{ {
case DrawMode::DRAW_POINTS: for (SizeType i = 0; i < m_meshes.size(); ++i)
case DrawMode::DRAW_LINE_STRIP:
case DrawMode::DRAW_LINE_LOOP:
case DrawMode::DRAW_TRIANGLE_STRIP:
case DrawMode::DRAW_TRIANGLE_FAN:
case DrawMode::DRAW_TRIANGLES:
mesh = create_mesh(3, 3);
mesh->vertices[0] = a;
mesh->vertices[1] = b;
mesh->vertices[2] = c;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 2;
return mesh;
case DrawMode::DRAW_LINES:
mesh = create_mesh(3, 6);
mesh->vertices[0] = a;
mesh->vertices[1] = b;
mesh->vertices[2] = c;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 1;
mesh->indices[3] = 2;
mesh->indices[4] = 2;
mesh->indices[5] = 0;
return mesh;
case DrawMode::DRAW_LINE_STRIP_ADJACENCY:
case DrawMode::DRAW_LINES_ADJACENCY:
case DrawMode::DRAW_TRIANGLE_STRIP_ADJACENCY:
case DrawMode::DRAW_TRIANGLES_ADJACENCY:
case DrawMode::DRAW_PATCHES:
default:
throw EXCEPTION("Unable to gen for current draw mode: " + std::to_string(draw_mode));
}
}
static MeshType* gen(const DrawMode& draw_mode, const VertexType& a, const VertexType& b, const VertexType& c, const VertexType& d)
{
MeshType* mesh;
switch (draw_mode)
{
case DrawMode::DRAW_POINTS:
case DrawMode::DRAW_LINE_STRIP:
case DrawMode::DRAW_LINE_LOOP:
case DrawMode::DRAW_TRIANGLE_STRIP:
case DrawMode::DRAW_TRIANGLE_FAN:
mesh = create_mesh(4, 4);
mesh->vertices[0] = a;
mesh->vertices[1] = b;
mesh->vertices[2] = c;
mesh->vertices[3] = d;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 2;
mesh->indices[3] = 3;
return mesh;
case DrawMode::DRAW_LINES: // Implementation similar to LINE_LOOP
mesh = create_mesh(4, 8);
mesh->vertices[0] = a;
mesh->vertices[1] = b;
mesh->vertices[2] = c;
mesh->vertices[3] = d;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 1;
mesh->indices[3] = 2;
mesh->indices[4] = 2;
mesh->indices[5] = 3;
mesh->indices[6] = 3;
mesh->indices[7] = 0;
return mesh;
case DrawMode::DRAW_TRIANGLES:
mesh = create_mesh(4, 6);
mesh->vertices[0] = a;
mesh->vertices[1] = b;
mesh->vertices[2] = c;
mesh->vertices[3] = d;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 2;
mesh->indices[3] = 2;
mesh->indices[4] = 1;
mesh->indices[5] = 3;
return mesh;
case DrawMode::DRAW_LINE_STRIP_ADJACENCY:
case DrawMode::DRAW_LINES_ADJACENCY:
case DrawMode::DRAW_TRIANGLE_STRIP_ADJACENCY:
case DrawMode::DRAW_TRIANGLES_ADJACENCY:
case DrawMode::DRAW_PATCHES:
default:
throw EXCEPTION("Unable to gen for current draw mode: " + std::to_string(draw_mode));
}
}
static MeshType* gen(const DrawMode& draw_mode, const std::vector<VertexType>& vertices, const std::vector<IndexType>& indices)
{
MeshType* mesh;
switch (draw_mode)
{
case DrawMode::DRAW_POINTS:
case DrawMode::DRAW_LINE_STRIP:
case DrawMode::DRAW_LINE_LOOP:
case DrawMode::DRAW_LINES:
case DrawMode::DRAW_TRIANGLE_STRIP:
case DrawMode::DRAW_TRIANGLE_FAN:
case DrawMode::DRAW_TRIANGLES:
int n = vertices.size();
mesh = create_mesh(n, n);
for (SizeType i = 0; i < vertices.size(); ++i)
{ {
mesh->vertices[i] = vertices[i]; delete[] m_meshes[i]->vertices;
mesh->indices[i] = i; m_meshes[i]->vertices = nullptr;
delete[] m_meshes[i]->indices;
m_meshes[i]->indices = nullptr;
delete m_meshes[i];
m_meshes[i] = nullptr;
} }
return mesh;
case DrawMode::DRAW_LINE_STRIP_ADJACENCY:
case DrawMode::DRAW_LINES_ADJACENCY:
case DrawMode::DRAW_TRIANGLE_STRIP_ADJACENCY:
case DrawMode::DRAW_TRIANGLES_ADJACENCY:
case DrawMode::DRAW_PATCHES:
default:
throw EXCEPTION("Unable to gen for current draw mode: " + std::to_string(draw_mode));
} }
}
// Generates a "cube" (8-vert shape) with 8 vertices. This function should probably not be used static MeshType* gen(const DrawMode& draw_mode, const VertexType& a)
// if the vertices are expected to have normals.
static MeshType* gen_cube(
const DrawMode& draw_mode,
const VertexType& top_left_front,
const VertexType& bottom_left_front,
const VertexType& top_right_front,
const VertexType& bottom_right_front,
const VertexType& top_left_back,
const VertexType& bottom_left_back,
const VertexType& top_right_back,
const VertexType& bottom_right_back
)
{
MeshType* mesh;
switch (draw_mode)
{ {
case DrawMode::DRAW_POINTS: MeshType* mesh;
mesh = create_mesh(8, 8); switch (draw_mode)
mesh->vertices[0] = top_left_front; {
mesh->vertices[1] = bottom_left_front; case DrawMode::DRAW_POINTS:
mesh->vertices[2] = top_right_front; mesh = create_mesh(1, 1);
mesh->vertices[3] = bottom_right_front; mesh->vertices[0] = a;
mesh->vertices[4] = top_left_back; mesh->indices[0] = 0;
mesh->vertices[5] = bottom_left_back; return mesh;
mesh->vertices[6] = top_right_back; case DrawMode::DRAW_LINE_STRIP:
mesh->vertices[7] = bottom_right_back; case DrawMode::DRAW_LINE_LOOP:
mesh->indices[0] = 0; case DrawMode::DRAW_LINES:
mesh->indices[1] = 1; case DrawMode::DRAW_TRIANGLE_STRIP:
mesh->indices[2] = 3; case DrawMode::DRAW_TRIANGLE_FAN:
mesh->indices[3] = 3; case DrawMode::DRAW_TRIANGLES:
mesh->indices[4] = 4; case DrawMode::DRAW_LINE_STRIP_ADJACENCY:
mesh->indices[5] = 5; case DrawMode::DRAW_LINES_ADJACENCY:
mesh->indices[6] = 6; case DrawMode::DRAW_TRIANGLE_STRIP_ADJACENCY:
mesh->indices[7] = 7; case DrawMode::DRAW_TRIANGLES_ADJACENCY:
return mesh; case DrawMode::DRAW_PATCHES:
case DrawMode::DRAW_LINES: default:
mesh = create_mesh(8, 24); throw EXCEPTION("Unable to gen for current draw mode: " + std::to_string(draw_mode));
mesh->vertices[0] = top_left_front; }
mesh->vertices[1] = bottom_left_front;
mesh->vertices[2] = top_right_front;
mesh->vertices[3] = bottom_right_front;
mesh->vertices[4] = top_left_back;
mesh->vertices[5] = bottom_left_back;
mesh->vertices[6] = top_right_back;
mesh->vertices[7] = bottom_right_back;
// Front
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 1;
mesh->indices[3] = 2;
mesh->indices[4] = 2;
mesh->indices[5] = 3;
mesh->indices[6] = 3;
mesh->indices[7] = 0;
// Back
mesh->indices[8] = 4;
mesh->indices[9] = 5;
mesh->indices[10] = 5;
mesh->indices[11] = 6;
mesh->indices[12] = 6;
mesh->indices[13] = 7;
mesh->indices[14] = 7;
mesh->indices[15] = 4;
// Connecting
mesh->indices[16] = 0;
mesh->indices[17] = 4;
mesh->indices[18] = 1;
mesh->indices[19] = 5;
mesh->indices[20] = 2;
mesh->indices[21] = 6;
mesh->indices[22] = 3;
mesh->indices[23] = 7;
return mesh;
case DrawMode::DRAW_TRIANGLES:
mesh = create_mesh(8, 36);
mesh->vertices[0] = top_left_front;
mesh->vertices[1] = bottom_left_front;
mesh->vertices[2] = top_right_front;
mesh->vertices[3] = bottom_right_front;
mesh->vertices[4] = top_left_back;
mesh->vertices[5] = bottom_left_back;
mesh->vertices[6] = top_right_back;
mesh->vertices[7] = bottom_right_back;
// Counter Clockwise
// Front
mesh->indices[0] = 1;
mesh->indices[1] = 3;
mesh->indices[2] = 0;
mesh->indices[3] = 0;
mesh->indices[4] = 3;
mesh->indices[5] = 2;
// Right
mesh->indices[6] = 3;
mesh->indices[7] = 7;
mesh->indices[8] = 2;
mesh->indices[9] = 2;
mesh->indices[10] = 7;
mesh->indices[11] = 6;
// Back
mesh->indices[12] = 7;
mesh->indices[13] = 5;
mesh->indices[14] = 6;
mesh->indices[15] = 6;
mesh->indices[16] = 5;
mesh->indices[17] = 4;
// Left
mesh->indices[18] = 5;
mesh->indices[19] = 1;
mesh->indices[20] = 4;
mesh->indices[21] = 4;
mesh->indices[22] = 1;
mesh->indices[23] = 0;
// Top
mesh->indices[24] = 0;
mesh->indices[25] = 2;
mesh->indices[26] = 4;
mesh->indices[27] = 4;
mesh->indices[28] = 2;
mesh->indices[29] = 6;
// Bottom
mesh->indices[30] = 5;
mesh->indices[31] = 7;
mesh->indices[32] = 1;
mesh->indices[33] = 1;
mesh->indices[34] = 7;
mesh->indices[35] = 3;
return mesh;
case DrawMode::DRAW_LINE_STRIP:
case DrawMode::DRAW_LINE_LOOP:
case DrawMode::DRAW_TRIANGLE_STRIP: // Could probably implement this one in some way in the future
case DrawMode::DRAW_TRIANGLE_FAN:
case DrawMode::DRAW_LINE_STRIP_ADJACENCY:
case DrawMode::DRAW_LINES_ADJACENCY:
case DrawMode::DRAW_TRIANGLE_STRIP_ADJACENCY:
case DrawMode::DRAW_TRIANGLES_ADJACENCY:
case DrawMode::DRAW_PATCHES:
default:
throw EXCEPTION("Unable to gen_cube for current draw mode: " + std::to_string(draw_mode));
} }
}
protected: static MeshType* gen(const DrawMode& draw_mode, const VertexType& a, const VertexType& b)
static MeshType* create_mesh(unsigned int vertex_count, unsigned int index_count) {
{ MeshType* mesh;
MeshType* mesh = new MeshType(); switch (draw_mode)
mesh->vertices = new VertexType[vertex_count]; {
mesh->vertex_count = vertex_count; case DrawMode::DRAW_POINTS:
mesh->indices = new IndexType[index_count]; case DrawMode::DRAW_LINE_STRIP:
mesh->index_count = index_count; case DrawMode::DRAW_LINE_LOOP:
m_meshes.push_back(mesh); case DrawMode::DRAW_LINES:
return mesh; mesh = create_mesh(2, 2);
} mesh->vertices[0] = a;
mesh->vertices[1] = b;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
return mesh;
case DrawMode::DRAW_TRIANGLE_STRIP:
case DrawMode::DRAW_TRIANGLE_FAN:
case DrawMode::DRAW_TRIANGLES:
case DrawMode::DRAW_LINE_STRIP_ADJACENCY:
case DrawMode::DRAW_LINES_ADJACENCY:
case DrawMode::DRAW_TRIANGLE_STRIP_ADJACENCY:
case DrawMode::DRAW_TRIANGLES_ADJACENCY:
case DrawMode::DRAW_PATCHES:
default:
throw EXCEPTION("Unable to gen for current draw mode: " + std::to_string(draw_mode));
}
}
private: static MeshType* gen(const DrawMode& draw_mode, const VertexType& a, const VertexType& b, const VertexType& c)
static std::vector<MeshType*> m_meshes; {
}; MeshType* mesh;
switch (draw_mode)
{
case DrawMode::DRAW_POINTS:
case DrawMode::DRAW_LINE_STRIP:
case DrawMode::DRAW_LINE_LOOP:
case DrawMode::DRAW_TRIANGLE_STRIP:
case DrawMode::DRAW_TRIANGLE_FAN:
case DrawMode::DRAW_TRIANGLES:
mesh = create_mesh(3, 3);
mesh->vertices[0] = a;
mesh->vertices[1] = b;
mesh->vertices[2] = c;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 2;
return mesh;
case DrawMode::DRAW_LINES:
mesh = create_mesh(3, 6);
mesh->vertices[0] = a;
mesh->vertices[1] = b;
mesh->vertices[2] = c;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 1;
mesh->indices[3] = 2;
mesh->indices[4] = 2;
mesh->indices[5] = 0;
return mesh;
case DrawMode::DRAW_LINE_STRIP_ADJACENCY:
case DrawMode::DRAW_LINES_ADJACENCY:
case DrawMode::DRAW_TRIANGLE_STRIP_ADJACENCY:
case DrawMode::DRAW_TRIANGLES_ADJACENCY:
case DrawMode::DRAW_PATCHES:
default:
throw EXCEPTION("Unable to gen for current draw mode: " + std::to_string(draw_mode));
}
}
template <typename VertexType, typename IndexType> static MeshType* gen(const DrawMode& draw_mode, const VertexType& a, const VertexType& b, const VertexType& c, const VertexType& d)
std::vector<Mesh<VertexType, IndexType>*> MeshFactory<VertexType, IndexType>::m_meshes = std::vector<Mesh<VertexType, IndexType>*>(); {
MeshType* mesh;
switch (draw_mode)
{
case DrawMode::DRAW_POINTS:
case DrawMode::DRAW_LINE_STRIP:
case DrawMode::DRAW_LINE_LOOP:
case DrawMode::DRAW_TRIANGLE_STRIP:
case DrawMode::DRAW_TRIANGLE_FAN:
mesh = create_mesh(4, 4);
mesh->vertices[0] = a;
mesh->vertices[1] = b;
mesh->vertices[2] = c;
mesh->vertices[3] = d;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 2;
mesh->indices[3] = 3;
return mesh;
case DrawMode::DRAW_LINES: // Implementation similar to LINE_LOOP
mesh = create_mesh(4, 8);
mesh->vertices[0] = a;
mesh->vertices[1] = b;
mesh->vertices[2] = c;
mesh->vertices[3] = d;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 1;
mesh->indices[3] = 2;
mesh->indices[4] = 2;
mesh->indices[5] = 3;
mesh->indices[6] = 3;
mesh->indices[7] = 0;
return mesh;
case DrawMode::DRAW_TRIANGLES:
mesh = create_mesh(4, 6);
mesh->vertices[0] = a;
mesh->vertices[1] = b;
mesh->vertices[2] = c;
mesh->vertices[3] = d;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 2;
mesh->indices[3] = 2;
mesh->indices[4] = 1;
mesh->indices[5] = 3;
return mesh;
case DrawMode::DRAW_LINE_STRIP_ADJACENCY:
case DrawMode::DRAW_LINES_ADJACENCY:
case DrawMode::DRAW_TRIANGLE_STRIP_ADJACENCY:
case DrawMode::DRAW_TRIANGLES_ADJACENCY:
case DrawMode::DRAW_PATCHES:
default:
throw EXCEPTION("Unable to gen for current draw mode: " + std::to_string(draw_mode));
}
}
static MeshType* gen(const DrawMode& draw_mode, const std::vector<VertexType>& vertices, const std::vector<IndexType>& indices)
{
MeshType* mesh;
switch (draw_mode)
{
case DrawMode::DRAW_POINTS:
case DrawMode::DRAW_LINE_STRIP:
case DrawMode::DRAW_LINE_LOOP:
case DrawMode::DRAW_LINES:
case DrawMode::DRAW_TRIANGLE_STRIP:
case DrawMode::DRAW_TRIANGLE_FAN:
case DrawMode::DRAW_TRIANGLES:
int n = vertices.size();
mesh = create_mesh(n, n);
for (SizeType i = 0; i < vertices.size(); ++i)
{
mesh->vertices[i] = vertices[i];
mesh->indices[i] = i;
}
return mesh;
case DrawMode::DRAW_LINE_STRIP_ADJACENCY:
case DrawMode::DRAW_LINES_ADJACENCY:
case DrawMode::DRAW_TRIANGLE_STRIP_ADJACENCY:
case DrawMode::DRAW_TRIANGLES_ADJACENCY:
case DrawMode::DRAW_PATCHES:
default:
throw EXCEPTION("Unable to gen for current draw mode: " + std::to_string(draw_mode));
}
}
// Generates a "cube" (8-vert shape) with 8 vertices. This function should probably not be used
// if the vertices are expected to have normals.
static MeshType* gen_cube(
const DrawMode& draw_mode,
const VertexType& top_left_front,
const VertexType& bottom_left_front,
const VertexType& top_right_front,
const VertexType& bottom_right_front,
const VertexType& top_left_back,
const VertexType& bottom_left_back,
const VertexType& top_right_back,
const VertexType& bottom_right_back
)
{
MeshType* mesh;
switch (draw_mode)
{
case DrawMode::DRAW_POINTS:
mesh = create_mesh(8, 8);
mesh->vertices[0] = top_left_front;
mesh->vertices[1] = bottom_left_front;
mesh->vertices[2] = top_right_front;
mesh->vertices[3] = bottom_right_front;
mesh->vertices[4] = top_left_back;
mesh->vertices[5] = bottom_left_back;
mesh->vertices[6] = top_right_back;
mesh->vertices[7] = bottom_right_back;
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 3;
mesh->indices[3] = 3;
mesh->indices[4] = 4;
mesh->indices[5] = 5;
mesh->indices[6] = 6;
mesh->indices[7] = 7;
return mesh;
case DrawMode::DRAW_LINES:
mesh = create_mesh(8, 24);
mesh->vertices[0] = top_left_front;
mesh->vertices[1] = bottom_left_front;
mesh->vertices[2] = top_right_front;
mesh->vertices[3] = bottom_right_front;
mesh->vertices[4] = top_left_back;
mesh->vertices[5] = bottom_left_back;
mesh->vertices[6] = top_right_back;
mesh->vertices[7] = bottom_right_back;
// Front
mesh->indices[0] = 0;
mesh->indices[1] = 1;
mesh->indices[2] = 1;
mesh->indices[3] = 2;
mesh->indices[4] = 2;
mesh->indices[5] = 3;
mesh->indices[6] = 3;
mesh->indices[7] = 0;
// Back
mesh->indices[8] = 4;
mesh->indices[9] = 5;
mesh->indices[10] = 5;
mesh->indices[11] = 6;
mesh->indices[12] = 6;
mesh->indices[13] = 7;
mesh->indices[14] = 7;
mesh->indices[15] = 4;
// Connecting
mesh->indices[16] = 0;
mesh->indices[17] = 4;
mesh->indices[18] = 1;
mesh->indices[19] = 5;
mesh->indices[20] = 2;
mesh->indices[21] = 6;
mesh->indices[22] = 3;
mesh->indices[23] = 7;
return mesh;
case DrawMode::DRAW_TRIANGLES:
mesh = create_mesh(8, 36);
mesh->vertices[0] = top_left_front;
mesh->vertices[1] = bottom_left_front;
mesh->vertices[2] = top_right_front;
mesh->vertices[3] = bottom_right_front;
mesh->vertices[4] = top_left_back;
mesh->vertices[5] = bottom_left_back;
mesh->vertices[6] = top_right_back;
mesh->vertices[7] = bottom_right_back;
// Counter Clockwise
// Front
mesh->indices[0] = 1;
mesh->indices[1] = 3;
mesh->indices[2] = 0;
mesh->indices[3] = 0;
mesh->indices[4] = 3;
mesh->indices[5] = 2;
// Right
mesh->indices[6] = 3;
mesh->indices[7] = 7;
mesh->indices[8] = 2;
mesh->indices[9] = 2;
mesh->indices[10] = 7;
mesh->indices[11] = 6;
// Back
mesh->indices[12] = 7;
mesh->indices[13] = 5;
mesh->indices[14] = 6;
mesh->indices[15] = 6;
mesh->indices[16] = 5;
mesh->indices[17] = 4;
// Left
mesh->indices[18] = 5;
mesh->indices[19] = 1;
mesh->indices[20] = 4;
mesh->indices[21] = 4;
mesh->indices[22] = 1;
mesh->indices[23] = 0;
// Top
mesh->indices[24] = 0;
mesh->indices[25] = 2;
mesh->indices[26] = 4;
mesh->indices[27] = 4;
mesh->indices[28] = 2;
mesh->indices[29] = 6;
// Bottom
mesh->indices[30] = 5;
mesh->indices[31] = 7;
mesh->indices[32] = 1;
mesh->indices[33] = 1;
mesh->indices[34] = 7;
mesh->indices[35] = 3;
return mesh;
case DrawMode::DRAW_LINE_STRIP:
case DrawMode::DRAW_LINE_LOOP:
case DrawMode::DRAW_TRIANGLE_STRIP: // Could probably implement this one in some way in the future
case DrawMode::DRAW_TRIANGLE_FAN:
case DrawMode::DRAW_LINE_STRIP_ADJACENCY:
case DrawMode::DRAW_LINES_ADJACENCY:
case DrawMode::DRAW_TRIANGLE_STRIP_ADJACENCY:
case DrawMode::DRAW_TRIANGLES_ADJACENCY:
case DrawMode::DRAW_PATCHES:
default:
throw EXCEPTION("Unable to gen_cube for current draw mode: " + std::to_string(draw_mode));
}
}
protected:
static MeshType* create_mesh(unsigned int vertex_count, unsigned int index_count)
{
MeshType* mesh = new MeshType();
mesh->vertices = new VertexType[vertex_count];
mesh->vertex_count = vertex_count;
mesh->indices = new IndexType[index_count];
mesh->index_count = index_count;
m_meshes.push_back(mesh);
return mesh;
}
private:
static std::vector<MeshType*> m_meshes;
};
template <typename VertexType, typename IndexType>
std::vector<Mesh<VertexType, IndexType>*> MeshFactory<VertexType, IndexType>::m_meshes = std::vector<Mesh<VertexType, IndexType>*>();
}

View File

@ -6,6 +6,8 @@
#include "MySimple3DScene.h" #include "MySimple3DScene.h"
#include "MySimpleCubeScene.h" #include "MySimpleCubeScene.h"
using namespace charcoal;
class MyApplication : class MyApplication :
public Application public Application
{ {

View File

@ -4,6 +4,8 @@
#include "MyBasicShaderProgram.h" #include "MyBasicShaderProgram.h"
using namespace charcoal;
class MyBasicScene : public Scene class MyBasicScene : public Scene
{ {
public: public:

View File

@ -5,6 +5,8 @@
#include "Mesh.h" #include "Mesh.h"
#include "Renderable.h" #include "Renderable.h"
using namespace charcoal;
class MyBasicShaderProgram : public ShaderProgram class MyBasicShaderProgram : public ShaderProgram
{ {
public: public:

View File

@ -6,6 +6,8 @@
#include "MySimpleShaderProgram.h" #include "MySimpleShaderProgram.h"
using namespace charcoal;
class MyBatch : public Batch<MySimpleShaderProgram::Vertex, MySimpleShaderProgram::Index, 2> class MyBatch : public Batch<MySimpleShaderProgram::Vertex, MySimpleShaderProgram::Index, 2>
{ {
public: public:

View File

@ -56,7 +56,7 @@ void MySimple2DScene::update(float delta_time, clock_t clock)
else else
brightness = (float)(intervals - c) / half_interval; brightness = (float)(intervals - c) / half_interval;
radians = (float)egm::TAU * c / intervals; radians = (float)TAU * c / intervals;
{ {
MySimpleShaderProgram::Color& color = m_batch.get_color(0); MySimpleShaderProgram::Color& color = m_batch.get_color(0);

View File

@ -7,6 +7,8 @@
#include "MyBatch.h" #include "MyBatch.h"
#include "MySimpleShaderProgram.h" #include "MySimpleShaderProgram.h"
using namespace charcoal;
class MySimple2DScene : public Scene class MySimple2DScene : public Scene
{ {
public: public:

View File

@ -20,7 +20,7 @@ MySimple3DScene::MySimple3DScene(Application& application)
MySimpleShaderProgram::Vertex(2.0f, -1.0f, 0.0f) MySimpleShaderProgram::Vertex(2.0f, -1.0f, 0.0f)
), DrawMode::DRAW_TRIANGLES), ), DrawMode::DRAW_TRIANGLES),
m_batch(&m_shape, 2), m_batch(&m_shape, 2),
m_camera((float)egm::TAU_1_4, (float)m_screen_size.x / m_screen_size.y, 1.0f, 10.0f, vec3(0.0f, 0.0f, -5.0f)) m_camera((float)TAU_1_4, (float)m_screen_size.x / m_screen_size.y, 1.0f, 10.0f, vec3(0.0f, 0.0f, -5.0f))
{} {}
MySimple3DScene::~MySimple3DScene() MySimple3DScene::~MySimple3DScene()
@ -56,7 +56,7 @@ void MySimple3DScene::update(float delta_time, clock_t clock)
else else
brightness = (float)(intervals - c) / half_interval; brightness = (float)(intervals - c) / half_interval;
radians = (float)egm::TAU * c / intervals; radians = (float)TAU * c / intervals;
{ {
MySimpleShaderProgram::Color& color = m_batch.get_color(0); MySimpleShaderProgram::Color& color = m_batch.get_color(0);

View File

@ -7,6 +7,8 @@
#include "MyBatch.h" #include "MyBatch.h"
#include "MySimpleShaderProgram.h" #include "MySimpleShaderProgram.h"
using namespace charcoal;
class MySimple3DScene : public Scene class MySimple3DScene : public Scene
{ {
public: public:

View File

@ -19,7 +19,7 @@ MySimpleCubeScene::MySimpleCubeScene(Application& application)
MySimpleShaderProgram::Vertex( 1.0f, -1.0f, 1.0f) MySimpleShaderProgram::Vertex( 1.0f, -1.0f, 1.0f)
), DrawMode::DRAW_TRIANGLES), ), DrawMode::DRAW_TRIANGLES),
m_batch(&m_shape, 1), m_batch(&m_shape, 1),
m_camera((float)egm::TAU_1_4, (float)m_screen_size.x / m_screen_size.y, 1.0f, 10.0f, vec3(0.0f, 0.0f, -5.0f)) m_camera((float)TAU_1_4, (float)m_screen_size.x / m_screen_size.y, 1.0f, 10.0f, vec3(0.0f, 0.0f, -5.0f))
{} {}
MySimpleCubeScene::~MySimpleCubeScene() MySimpleCubeScene::~MySimpleCubeScene()
@ -55,7 +55,7 @@ void MySimpleCubeScene::update(float delta_time, clock_t clock)
else else
brightness = (float)(intervals - c) / half_interval; brightness = (float)(intervals - c) / half_interval;
radians = (float)egm::TAU * c / intervals; radians = (float)TAU * c / intervals;
{ {
MySimpleShaderProgram::Color& color = m_batch.get_color(0); MySimpleShaderProgram::Color& color = m_batch.get_color(0);
@ -65,7 +65,7 @@ void MySimpleCubeScene::update(float delta_time, clock_t clock)
color.a = 1.0f; color.a = 1.0f;
Poseable& pose = m_batch.get_pose(0); Poseable& pose = m_batch.get_pose(0);
pose.rotate(glm::normalize(vec3(1.0f, 1.0f, 0.0f)), (float)egm::TAU_1_2 * delta_time); pose.rotate(glm::normalize(vec3(1.0f, 1.0f, 0.0f)), (float)TAU_1_2 * delta_time);
pose.update_position(vec3(3 * (float)cos(radians), 0.0f, 0.0f)); pose.update_position(vec3(3 * (float)cos(radians), 0.0f, 0.0f));
} }
@ -83,7 +83,7 @@ void MySimpleCubeScene::update(float delta_time, clock_t clock)
if (m_input_manager.is_key_down(GLFW_KEY_C)) camera_rotation -= 1; if (m_input_manager.is_key_down(GLFW_KEY_C)) camera_rotation -= 1;
m_camera.translate(camera_translation * delta_time); m_camera.translate(camera_translation * delta_time);
m_camera.rotate(vec3(0.0f, 1.0f, 0.0f), camera_rotation * (float)egm::TAU_1_8 * delta_time); m_camera.rotate(vec3(0.0f, 1.0f, 0.0f), camera_rotation * (float)TAU_1_8 * delta_time);
} }
void MySimpleCubeScene::prerender() void MySimpleCubeScene::prerender()

View File

@ -7,6 +7,8 @@
#include "MyBatch.h" #include "MyBatch.h"
#include "MySimpleShaderProgram.h" #include "MySimpleShaderProgram.h"
using namespace charcoal;
class MySimpleCubeScene : public Scene class MySimpleCubeScene : public Scene
{ {
public: public:

View File

@ -5,6 +5,8 @@
#include "Mesh.h" #include "Mesh.h"
#include "Renderable.h" #include "Renderable.h"
using namespace charcoal;
class MySimpleShaderProgram : public ShaderProgram class MySimpleShaderProgram : public ShaderProgram
{ {
public: public:

View File

@ -146,24 +146,15 @@
<ClInclude Include="ShaderProgram.h"> <ClInclude Include="ShaderProgram.h">
<Filter>Header Files\Engine\Rendering</Filter> <Filter>Header Files\Engine\Rendering</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="DrawMode.h">
<Filter>Header Files\Engine\Rendering</Filter>
</ClInclude>
<ClInclude Include="Shader.h"> <ClInclude Include="Shader.h">
<Filter>Header Files\Engine\Rendering</Filter> <Filter>Header Files\Engine\Rendering</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Mesh.h">
<Filter>Header Files\Engine\Rendering</Filter>
</ClInclude>
<ClInclude Include="Camera.h"> <ClInclude Include="Camera.h">
<Filter>Header Files\Engine\Rendering</Filter> <Filter>Header Files\Engine\Rendering</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Batch.h"> <ClInclude Include="Batch.h">
<Filter>Header Files\Engine\Rendering</Filter> <Filter>Header Files\Engine\Rendering</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Renderable.h">
<Filter>Header Files\Engine\Rendering</Filter>
</ClInclude>
<ClInclude Include="MyBatch.h"> <ClInclude Include="MyBatch.h">
<Filter>Header Files\Example\Rendering</Filter> <Filter>Header Files\Example\Rendering</Filter>
</ClInclude> </ClInclude>
@ -200,6 +191,15 @@
<ClInclude Include="MySimpleCubeScene.h"> <ClInclude Include="MySimpleCubeScene.h">
<Filter>Header Files\Example\Application</Filter> <Filter>Header Files\Example\Application</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="DrawMode.h">
<Filter>Header Files\Engine</Filter>
</ClInclude>
<ClInclude Include="Renderable.h">
<Filter>Header Files\Engine</Filter>
</ClInclude>
<ClInclude Include="Mesh.h">
<Filter>Header Files\Engine</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="MySimpleVS.glsl"> <None Include="MySimpleVS.glsl">

View File

@ -2,52 +2,56 @@
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
Poseable::Poseable( namespace charcoal
const vec3& position,
const vec3& forward,
const vec3& up,
const vec3& right
)
: m_orientation_matrix(
vec4(right, 0.0f),
vec4(up, 0.0f),
vec4(forward, 0.0f),
vec4(position, 1.0f)
) {}
void Poseable::update_position(const vec3& position)
{ {
m_orientation_matrix[3][0] = position.x; Poseable::Poseable(
m_orientation_matrix[3][1] = position.y; const vec3& position,
m_orientation_matrix[3][2] = position.z; const vec3& forward,
} const vec3& up,
const vec3& right
)
: m_orientation_matrix(
vec4(right, 0.0f),
vec4(up, 0.0f),
vec4(forward, 0.0f),
vec4(position, 1.0f)
)
{}
void Poseable::update_orientation(const vec3& forward, const vec3& up, const vec3& right) void Poseable::update_position(const vec3& position)
{ {
m_orientation_matrix[0][0] = right.x; m_orientation_matrix[3][0] = position.x;
m_orientation_matrix[0][1] = right.y; m_orientation_matrix[3][1] = position.y;
m_orientation_matrix[0][2] = right.z; m_orientation_matrix[3][2] = position.z;
}
m_orientation_matrix[1][0] = up.x; void Poseable::update_orientation(const vec3& forward, const vec3& up, const vec3& right)
m_orientation_matrix[1][1] = up.y; {
m_orientation_matrix[1][2] = up.z; m_orientation_matrix[0][0] = right.x;
m_orientation_matrix[0][1] = right.y;
m_orientation_matrix[0][2] = right.z;
m_orientation_matrix[2][0] = forward.x; m_orientation_matrix[1][0] = up.x;
m_orientation_matrix[2][1] = forward.y; m_orientation_matrix[1][1] = up.y;
m_orientation_matrix[2][2] = forward.z; m_orientation_matrix[1][2] = up.z;
}
void Poseable::translate(const vec3& translation) m_orientation_matrix[2][0] = forward.x;
{ m_orientation_matrix[2][1] = forward.y;
m_orientation_matrix[3][0] += translation.x; m_orientation_matrix[2][2] = forward.z;
m_orientation_matrix[3][1] += translation.y; }
m_orientation_matrix[3][2] += translation.z;
}
void Poseable::rotate(const vec3& axis, float angle) void Poseable::translate(const vec3& translation)
{ {
mat4 rotation_matrix = glm::rotate(glm::mat4(1.0f), angle, axis); m_orientation_matrix[3][0] += translation.x;
m_orientation_matrix[0] = rotation_matrix * m_orientation_matrix[0]; m_orientation_matrix[3][1] += translation.y;
m_orientation_matrix[1] = rotation_matrix * m_orientation_matrix[1]; m_orientation_matrix[3][2] += translation.z;
m_orientation_matrix[2] = rotation_matrix * m_orientation_matrix[2]; }
void Poseable::rotate(const vec3& axis, float angle)
{
mat4 rotation_matrix = glm::rotate(glm::mat4(1.0f), angle, axis);
m_orientation_matrix[0] = rotation_matrix * m_orientation_matrix[0];
m_orientation_matrix[1] = rotation_matrix * m_orientation_matrix[1];
m_orientation_matrix[2] = rotation_matrix * m_orientation_matrix[2];
}
} }

View File

@ -2,28 +2,31 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
using namespace glm; namespace charcoal
class Poseable
{ {
public: using namespace glm;
// Assumes that forward, up, and right are orthogonal and normalized
Poseable(
const vec3& position = vec3(0.0f, 0.0f, 0.0f),
const vec3& forward = vec3(0.0f, 0.0f, 1.0f),
const vec3& up = vec3(0.0f, 1.0f, 0.0f),
const vec3& right = vec3(1.0f, 0.0f, 0.0f)
);
void update_position(const vec3& position); class Poseable
// Assumes that forward, up, and right are orthogonal and normalized {
void update_orientation(const vec3& forward, const vec3& up, const vec3& right); public:
// Assumes that forward, up, and right are orthogonal and normalized
Poseable(
const vec3& position = vec3(0.0f, 0.0f, 0.0f),
const vec3& forward = vec3(0.0f, 0.0f, 1.0f),
const vec3& up = vec3(0.0f, 1.0f, 0.0f),
const vec3& right = vec3(1.0f, 0.0f, 0.0f)
);
void translate(const vec3& translation); void update_position(const vec3& position);
void rotate(const vec3& axis, float angle); // Assumes that forward, up, and right are orthogonal and normalized
void update_orientation(const vec3& forward, const vec3& up, const vec3& right);
const mat4& get_orientation_matrix() const { return m_orientation_matrix; }
protected: void translate(const vec3& translation);
mat4 m_orientation_matrix; void rotate(const vec3& axis, float angle);
};
const mat4& get_orientation_matrix() const { return m_orientation_matrix; }
protected:
mat4 m_orientation_matrix;
};
}

View File

@ -8,22 +8,26 @@
#include "DrawMode.h" #include "DrawMode.h"
#include "Batch.h" #include "Batch.h"
template <typename VertexType, typename IndexType> namespace charcoal
class Renderable final
{ {
public: template <typename VertexType, typename IndexType>
typedef VertexType VertexType; class Renderable final
typedef IndexType IndexType; {
typedef Mesh<VertexType, IndexType> MeshType; public:
typedef VertexType VertexType;
typedef IndexType IndexType;
typedef Mesh<VertexType, IndexType> MeshType;
Renderable(const MeshType* mesh, const DrawMode& draw_mode) Renderable(const MeshType* mesh, const DrawMode& draw_mode)
: m_p_mesh(mesh), m_draw_mode(draw_mode) {} : m_p_mesh(mesh), m_draw_mode(draw_mode)
{}
const MeshType* get_mesh() const { return m_p_mesh; } const MeshType* get_mesh() const { return m_p_mesh; }
const DrawMode& get_draw_mode() const { return m_draw_mode; } const DrawMode& get_draw_mode() const { return m_draw_mode; }
private: private:
const MeshType* m_p_mesh = nullptr; const MeshType* m_p_mesh = nullptr;
DrawMode m_draw_mode; DrawMode m_draw_mode;
}; };
}

View File

@ -6,38 +6,41 @@
#include "Application.h" #include "Application.h"
class Scene namespace charcoal
{ {
public: class Scene
Scene(Application& application) {
: m_screen_size(application.get_screen_size()), public:
m_input_manager(application.get_input_manager()), Scene(Application& application)
m_fps(application.get_fps()) {}; : m_screen_size(application.get_screen_size()),
virtual ~Scene() { }; m_input_manager(application.get_input_manager()),
m_fps(application.get_fps())
{};
virtual ~Scene() {};
// Called when the scene is ready to be initialized // Called when the scene is ready to be initialized
virtual void init() = 0; virtual void init() = 0;
// Called when the scene is going to be used // Called when the scene is going to be used
// Should allocate all graphics memory. // Should allocate all graphics memory.
virtual void use() = 0; virtual void use() = 0;
// Called when the scene is no longer going to be used // Called when the scene is no longer going to be used
// Should release all graphics memory // Should release all graphics memory
virtual void unuse() = 0; virtual void unuse() = 0;
// Called when the frame is being updated // Called when the frame is being updated
virtual void update(float delta_time, clock_t clock) = 0; virtual void update(float delta_time, clock_t clock) = 0;
// Called before the scene is rendered. // Called before the scene is rendered.
// Intended to prepare objects for rendering (generally by calling their prerender function) // Intended to prepare objects for rendering (generally by calling their prerender function)
virtual void prerender() = 0; virtual void prerender() = 0;
// Called when the frame is being rendered
virtual void render() = 0;
protected:
const ivec2& m_screen_size;
const GLFWInputManager& m_input_manager;
const FPS& m_fps;
};
// Called when the frame is being rendered
virtual void render() = 0;
protected:
const ivec2& m_screen_size;
const GLFWInputManager& m_input_manager;
const FPS& m_fps;
};
}

View File

@ -2,50 +2,53 @@
#include "Exception.h" #include "Exception.h"
Shader::Shader(const std::string& source, ShaderType type) namespace charcoal
{ {
GLenum gl_shader_type; Shader::Shader(const std::string& source, ShaderType type)
switch (type)
{ {
case VERTEX_SHADER: GLenum gl_shader_type;
gl_shader_type = GL_VERTEX_SHADER; switch (type)
break; {
case FRAGMENT_SHADER: case VERTEX_SHADER:
gl_shader_type = GL_FRAGMENT_SHADER; gl_shader_type = GL_VERTEX_SHADER;
break; break;
default: case FRAGMENT_SHADER:
throw "Invalid Shader Type Specified"; gl_shader_type = GL_FRAGMENT_SHADER;
break;
default:
throw "Invalid Shader Type Specified";
}
m_shader = glCreateShader(gl_shader_type);
const char* c_str = source.c_str();
glShaderSource(m_shader, 1, &c_str, NULL);
glCompileShader(m_shader);
// Make sure that the shader has been compiled successfully
GLint compiled;
glGetShaderiv(m_shader, GL_COMPILE_STATUS, &compiled);
if (compiled != GL_TRUE)
{
char buffer[1024];
GLsizei log_length;
glGetShaderInfoLog(m_shader, 1023, &log_length, buffer);
buffer[log_length] = '\0'; // Add null terminator
OutputDebugString("Error Compiling Shader:\n");
OutputDebugString(buffer);
OutputDebugString("\nSource:\n");
OutputDebugString(source.c_str());
OutputDebugString("\n");
m_shader = 0;
throw EXCEPTION("Error compiling shader.");
}
} }
m_shader = glCreateShader(gl_shader_type); Shader::~Shader() {}
const char* c_str = source.c_str(); GLuint Shader::get_shader() const
glShaderSource(m_shader, 1, &c_str, NULL);
glCompileShader(m_shader);
// Make sure that the shader has been compiled successfully
GLint compiled;
glGetShaderiv(m_shader, GL_COMPILE_STATUS, &compiled);
if (compiled != GL_TRUE)
{ {
char buffer[1024]; return m_shader;
GLsizei log_length;
glGetShaderInfoLog(m_shader, 1023, &log_length, buffer);
buffer[log_length] = '\0'; // Add null terminator
OutputDebugString("Error Compiling Shader:\n");
OutputDebugString(buffer);
OutputDebugString("\nSource:\n");
OutputDebugString(source.c_str());
OutputDebugString("\n");
m_shader = 0;
throw EXCEPTION("Error compiling shader.");
} }
} }
Shader::~Shader() {}
GLuint Shader::get_shader() const
{
return m_shader;
}

View File

@ -4,21 +4,23 @@
#include <string> #include <string>
enum ShaderType namespace charcoal
{ {
VERTEX_SHADER, enum ShaderType
FRAGMENT_SHADER {
}; VERTEX_SHADER,
FRAGMENT_SHADER
};
class Shader class Shader
{ {
public: public:
Shader(const std::string& source, ShaderType type); Shader(const std::string& source, ShaderType type);
~Shader(); ~Shader();
GLuint get_shader() const; GLuint get_shader() const;
private:
GLuint m_shader;
};
private:
GLuint m_shader;
};
}

View File

@ -1,31 +1,34 @@
#include "ShaderProgram.h" #include "ShaderProgram.h"
ShaderProgram::ShaderProgram() namespace charcoal
: m_program(glCreateProgram())
{}
ShaderProgram::~ShaderProgram()
{ {
glDeleteProgram(m_program); ShaderProgram::ShaderProgram()
} : m_program(glCreateProgram())
{}
void ShaderProgram::attach_shader(const Shader& shader) ShaderProgram::~ShaderProgram()
{ {
glAttachShader(m_program, shader.get_shader()); glDeleteProgram(m_program);
} }
void ShaderProgram::link() void ShaderProgram::attach_shader(const Shader& shader)
{ {
glLinkProgram(m_program); glAttachShader(m_program, shader.get_shader());
// TODO: Error handling }
}
void ShaderProgram::use() const void ShaderProgram::link()
{ {
glUseProgram(m_program); glLinkProgram(m_program);
} // TODO: Error handling
}
GLuint ShaderProgram::get_program() const void ShaderProgram::use() const
{ {
return m_program; glUseProgram(m_program);
} }
GLuint ShaderProgram::get_program() const
{
return m_program;
}
}

View File

@ -6,20 +6,23 @@
#include "Shader.h" #include "Shader.h"
class ShaderProgram namespace charcoal
{ {
public: class ShaderProgram
ShaderProgram(); {
virtual ~ShaderProgram(); public:
ShaderProgram();
virtual ~ShaderProgram();
void use() const; void use() const;
GLuint get_program() const; GLuint get_program() const;
protected: protected:
void attach_shader(const Shader& shader); void attach_shader(const Shader& shader);
void link(); void link();
private: private:
GLuint m_program = 0; GLuint m_program = 0;
}; };
}

View File

@ -9,75 +9,78 @@
#include "Exception.h" #include "Exception.h"
std::string Util::load_file(const std::string& path) namespace charcoal
{ {
std::ifstream input_stream; std::string Util::load_file(const std::string& path)
try
{ {
input_stream.open(path); std::ifstream input_stream;
try
{
input_stream.open(path);
}
catch (std::ios::failure& e)
{
throw EXCEPTION(std::string("Error Opening File: ") + e.what());
}
if (input_stream.is_open())
{
input_stream.seekg(0, std::ios::end);
std::size_t size = input_stream.tellg();
std::string buffer(size, ' ');
input_stream.seekg(std::ios::beg);
input_stream.read(&buffer[0], size);
return buffer;
}
else
{
throw EXCEPTION("Unable to access file: " + path);
}
} }
catch (std::ios::failure& e)
void Util::set_console_position(short x, short y)
{ {
throw EXCEPTION(std::string("Error Opening File: ") + e.what()); COORD pos = { x, y };
HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(output, pos);
} }
if (input_stream.is_open())
void Util::print_matrix(const mat4& matrix)
{ {
input_stream.seekg(0, std::ios::end); std::cout << std::showpos << std::scientific << std::setprecision(5)
std::size_t size = input_stream.tellg(); << "[ " << matrix[0][0] << " " << matrix[1][0] << " " << matrix[2][0] << " " << matrix[3][0] << " ]" << std::endl
std::string buffer(size, ' '); << "[ " << matrix[0][1] << " " << matrix[1][1] << " " << matrix[2][1] << " " << matrix[3][1] << " ]" << std::endl
input_stream.seekg(std::ios::beg); << "[ " << matrix[0][2] << " " << matrix[1][2] << " " << matrix[2][2] << " " << matrix[3][2] << " ]" << std::endl
input_stream.read(&buffer[0], size); << "[ " << matrix[0][3] << " " << matrix[1][3] << " " << matrix[2][3] << " " << matrix[3][3] << " ]" << std::endl;
return buffer;
} }
else
void Util::print_vec(const vec2& v)
{ {
throw EXCEPTION("Unable to access file: " + path); std::cout << std::showpos << std::fixed << std::setprecision(5)
<< "[" << v.x << "]" << std::endl
<< "[" << v.y << "]" << std::endl;
} }
}
void Util::set_console_position(short x, short y) void Util::print_vec(const vec3& v)
{ {
COORD pos = { x, y }; std::cout << std::showpos << std::fixed << std::setprecision(5)
HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE); << "[" << v.x << "]" << std::endl
SetConsoleCursorPosition(output, pos); << "[" << v.y << "]" << std::endl
} << "[" << v.z << "]" << std::endl;
}
void Util::print_matrix(const mat4& matrix) void Util::print_vec(const vec4& v)
{ {
std::cout << std::showpos << std::scientific << std::setprecision(5) std::cout << std::showpos << std::fixed << std::setprecision(5)
<< "[ " << matrix[0][0] << " " << matrix[1][0] << " " << matrix[2][0] << " " << matrix[3][0] << " ]" << std::endl << "[" << v.x << "]" << std::endl
<< "[ " << matrix[0][1] << " " << matrix[1][1] << " " << matrix[2][1] << " " << matrix[3][1] << " ]" << std::endl << "[" << v.y << "]" << std::endl
<< "[ " << matrix[0][2] << " " << matrix[1][2] << " " << matrix[2][2] << " " << matrix[3][2] << " ]" << std::endl << "[" << v.z << "]" << std::endl
<< "[ " << matrix[0][3] << " " << matrix[1][3] << " " << matrix[2][3] << " " << matrix[3][3] << " ]" << std::endl; << "[" << v.w << "]" << std::endl;
} }
void Util::print_vec(const vec2& v) void Util::_check_gl_err(const char* file_name, int line)
{ {
std::cout << std::showpos << std::fixed << std::setprecision(5) GLenum gl_err = glGetError();
<< "[" << v.x << "]" << std::endl if (gl_err != GL_NO_ERROR)
<< "[" << v.y << "]" << std::endl; throw Exception(("Caught OpenGL Error: " + std::string((const char*)gluErrorString(gl_err)) + " (" + std::to_string(gl_err) + ")").c_str(), file_name, line);
} }
void Util::print_vec(const vec3& v)
{
std::cout << std::showpos << std::fixed << std::setprecision(5)
<< "[" << v.x << "]" << std::endl
<< "[" << v.y << "]" << std::endl
<< "[" << v.z << "]" << std::endl;
}
void Util::print_vec(const vec4& v)
{
std::cout << std::showpos << std::fixed << std::setprecision(5)
<< "[" << v.x << "]" << std::endl
<< "[" << v.y << "]" << std::endl
<< "[" << v.z << "]" << std::endl
<< "[" << v.w << "]" << std::endl;
}
void Util::_check_gl_err(const char* file_name, int line)
{
GLenum gl_err = glGetError();
if (gl_err != GL_NO_ERROR)
throw Exception(("Caught OpenGL Error: " + std::string((const char*)gluErrorString(gl_err)) + " (" + std::to_string(gl_err) + ")").c_str(), file_name, line);
} }

View File

@ -5,22 +5,25 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
using namespace glm;
#define DISPLAY_DIGITS 5 #define DISPLAY_DIGITS 5
#define CHECK_GL_ERR() Util::_check_gl_err(__FILE__, __LINE__) #define CHECK_GL_ERR() Util::_check_gl_err(__FILE__, __LINE__)
class Util namespace charcoal
{ {
public: using namespace glm;
static std::string load_file(const std::string& path);
static void set_console_position(short x, short y);
static void print_matrix(const mat4& matrix);
static void print_vec(const vec2& v);
static void print_vec(const vec3& v);
static void print_vec(const vec4& v);
// Use the CHECK_GL_ERR macro unless you know what you are doing with this function class Util
static void _check_gl_err(const char* file_name, int line); {
}; public:
static std::string load_file(const std::string& path);
static void set_console_position(short x, short y);
static void print_matrix(const mat4& matrix);
static void print_vec(const vec2& v);
static void print_vec(const vec3& v);
static void print_vec(const vec4& v);
// Use the CHECK_GL_ERR macro unless you know what you are doing with this function
static void _check_gl_err(const char* file_name, int line);
};
}

View File

@ -3,7 +3,7 @@
#define DEG_TO_RAD(x) x * egm::TAU_1_360; #define DEG_TO_RAD(x) x * egm::TAU_1_360;
#define RAD_TO_DEG(x) #define RAD_TO_DEG(x)
namespace egm namespace charcoal
{ {
// 2PI = TAU: 6.2831853071795864769252867665590 // 2PI = TAU: 6.2831853071795864769252867665590