It Works! A triangle renders on the screen.

This commit gets creates the ObjectOriented scene and gets it
working.

The current test program swaps a triangle from small to large with
the 1 and 2 keys on the keyboard. (1 for small and 2 for large).

The small triangle is rendered by the simple scene and the large
one is rendered by the object oriented one.
This commit is contained in:
elipzer 2018-09-05 19:10:38 -04:00
parent 6db2ba4f21
commit a8c4b05d2f
20 changed files with 212 additions and 80 deletions

View File

@ -2,8 +2,7 @@
#include "Exception.h" #include "Exception.h"
Application::Application(const char* class_name, HINSTANCE h_instance) Application::Application()
: m_client_size(1280, 720)
{ {
base_init(); base_init();
} }
@ -22,6 +21,7 @@ int Application::run()
while (!glfwWindowShouldClose(m_p_window)) while (!glfwWindowShouldClose(m_p_window))
{ {
// Handle all messages // Handle all messages
m_glfw_input_manager.mark();
glfwPollEvents(); glfwPollEvents();
float delta_time = m_fps.mark(); float delta_time = m_fps.mark();
clock_t clock = m_fps.get_clock(); clock_t clock = m_fps.get_clock();
@ -55,13 +55,15 @@ void Application::base_init()
{ {
throw EXCEPTION("Unable to Initialize GLFW"); throw EXCEPTION("Unable to Initialize GLFW");
} }
m_p_window = glfwCreateWindow(m_client_size.x, m_client_size.y, "OpenGLEngine", NULL, NULL); m_p_window = glfwCreateWindow(1280, 720, "OpenGLEngine", NULL, NULL);
if (!m_p_window) if (!m_p_window)
{ {
glfwTerminate(); glfwTerminate();
throw EXCEPTION("Unable to Create GLFW Window"); throw EXCEPTION("Unable to Create GLFW Window");
} }
glfwMakeContextCurrent(m_p_window); glfwMakeContextCurrent(m_p_window);
glewExperimental = GL_TRUE; glewExperimental = GL_TRUE;
GLenum glew_err = glewInit(); GLenum glew_err = glewInit();
if (glew_err != GLEW_OK) if (glew_err != GLEW_OK)
@ -77,6 +79,9 @@ void Application::base_init()
OutputDebugString((char*)glGetString(GL_VERSION)); OutputDebugString((char*)glGetString(GL_VERSION));
OutputDebugString("\n\n"); OutputDebugString("\n\n");
m_glfw_input_manager.init(m_p_window);
glfwSetKeyCallback(m_p_window, &GLFWInputManager::key_callback);
m_fps.prepare(); m_fps.prepare();
} }

View File

@ -4,6 +4,7 @@
#include "vec2.h" #include "vec2.h"
#include "GLFWInputManager.h"
#include "FPS.h" #include "FPS.h"
using namespace egm; using namespace egm;
@ -13,7 +14,7 @@ using namespace egm;
class Application class Application
{ {
public: public:
Application(const char* class_name, HINSTANCE h_instance); Application();
virtual ~Application(); virtual ~Application();
int run(); int run();
@ -29,13 +30,10 @@ protected:
// Called on closing of the application (called before base_close) // Called on closing of the application (called before base_close)
virtual void close(); virtual void close();
// The size of the window
ivec2 m_client_size;
// The GLFWwindow that is used by this application
GLFWwindow* m_p_window; GLFWwindow* m_p_window;
// The FPS counter of this application GLFWInputManager m_glfw_input_manager;
FPS m_fps; FPS m_fps;
private: private:
void base_init(); void base_init();

View File

@ -1,6 +1,48 @@
#include "GLFWInputManager.h" #include "GLFWInputManager.h"
#include "Exception.h"
std::map<GLFWwindow*, GLFWInputManager*> GLFWInputManager::s_glfw_windows;
GLFWInputManager::~GLFWInputManager()
{
s_glfw_windows.erase(m_p_window);
}
void GLFWInputManager::init(GLFWwindow* p_window)
{
if (m_p_window != nullptr)
{
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::key_callback(GLFWwindow* p_window, int key, int scancode, int action, int mods)
{ {
std::map<GLFWwindow*, GLFWInputManager*>::iterator iter = s_glfw_windows.find(p_window);
if (iter == s_glfw_windows.end())
{
// Ignore Unknown Windows
return;
}
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) + ")", "class GLFWInputManager");
}
} }

View File

@ -4,8 +4,18 @@
#include "InputManager.h" #include "InputManager.h"
#include <map>
class GLFWInputManager : public InputManager class GLFWInputManager : public InputManager
{ {
public: public:
void key_callback(GLFWwindow* p_window, int key, int scancode, int action, int mods); ~GLFWInputManager();
void init(GLFWwindow* p_window);
static void key_callback(GLFWwindow* p_window, int key, int scancode, int action, int mods);
private:
GLFWwindow* m_p_window = nullptr;
static std::map<GLFWwindow*, GLFWInputManager*> s_glfw_windows;
}; };

View File

@ -16,19 +16,19 @@ void InputManager::mark()
m_scroll_distance = 0; m_scroll_distance = 0;
} }
void InputManager::key_down(const unsigned long& keyCode) void InputManager::key_down(KeyCode key_code)
{ {
if (!m_keys_down[keyCode]) if (!m_keys_down[key_code])
{ {
m_keys_down[keyCode] = true; m_keys_down[key_code] = true;
m_keys_pressed[keyCode] = true; m_keys_pressed[key_code] = true;
} }
} }
void InputManager::key_up(const unsigned long& keyCode) void InputManager::key_up(KeyCode key_code)
{ {
m_keys_down[keyCode] = false; m_keys_down[key_code] = false;
m_keys_pressed[keyCode] = false; m_keys_pressed[key_code] = false;
} }
void InputManager::mouse_move(const ivec2& position) void InputManager::mouse_move(const ivec2& position)
@ -37,28 +37,28 @@ void InputManager::mouse_move(const ivec2& position)
m_mouse_position = position; m_mouse_position = position;
} }
void InputManager::mouse_scroll(const unsigned int& distance) void InputManager::mouse_scroll(int distance)
{ {
m_scroll_distance += distance; m_scroll_distance += distance;
} }
bool InputManager::is_key_down(const unsigned long& keyCode) bool InputManager::is_key_down(KeyCode key_code)
{ {
return m_keys_down[keyCode]; return m_keys_down[key_code];
} }
bool InputManager::is_key_pressed(const unsigned long& keyCode) bool InputManager::is_key_pressed(KeyCode key_code)
{ {
auto iter = m_keys_pressed.find(keyCode); 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;
} }
bool InputManager::is_key_released(const unsigned long& keyCode) bool InputManager::is_key_released(KeyCode key_code)
{ {
auto iter = m_keys_pressed.find(keyCode); 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

View File

@ -4,7 +4,7 @@
#include "vec2.h" #include "vec2.h"
//Define the Virtual Keys for the numbers & letters // Define the Windows Virtual Keys for the numbers & letters
#define K_0 0x30 #define K_0 0x30
#define K_1 0x31 #define K_1 0x31
@ -49,34 +49,36 @@ using namespace egm;
class InputManager class InputManager
{ {
public: public:
typedef int KeyCode;
InputManager(); InputManager();
virtual ~InputManager(); virtual ~InputManager();
//Should be called after each frame to reset the keysPressed //Should be called after each frame to reset the keysPressed
void mark(); void mark();
bool is_key_down(const unsigned long& keyCode); bool is_key_down(KeyCode key_code);
bool is_key_pressed(const unsigned long& keyCode); bool is_key_pressed(KeyCode key_code);
bool is_key_released(const unsigned long& keyCode); bool is_key_released(KeyCode key_code);
const ivec2& get_mouse_position(); const ivec2& get_mouse_position();
const ivec2& get_mouse_delta(); const ivec2& get_mouse_delta();
const int& get_scroll_distance(); const int& get_scroll_distance();
protected: protected:
void key_down(const unsigned long& keyCode); void key_down(KeyCode key_code);
void key_up(const unsigned long& keyCode); void key_up(KeyCode key_code);
void mouse_move(const ivec2& position); void mouse_move(const ivec2& position);
void mouse_scroll(const unsigned int& distance); void mouse_scroll(int distance);
private: private:
//Keys pressed since the last frame //Keys pressed since the last frame
//The existance of a value in this array means that the key has changed to that state //The existance of a value in this array means that the key has changed to that state
//since the last mark() call. //since the last mark() call.
//A value of true means the key was pressed, false means the value was released //A value of true means the key was pressed, false means the value was released
std::map<unsigned long, bool> m_keys_pressed; std::map<KeyCode, bool> m_keys_pressed;
//Keys that are down //Keys that are down
std::map<unsigned long, bool> m_keys_down; std::map<KeyCode, bool> m_keys_down;
//Current Mouse Position //Current Mouse Position
ivec2 m_mouse_position; ivec2 m_mouse_position;

View File

@ -1,34 +1,44 @@
#include "MyApplication.h" #include "MyApplication.h"
MyApplication::MyApplication(const char* class_name, HINSTANCE h_instance)
: Application(class_name, h_instance)
{
}
MyApplication::~MyApplication()
{
}
void MyApplication::init() void MyApplication::init()
{ {
m_scene.init(); m_simple_scene.init();
m_scene.use(); m_object_oriented_scene.init();
m_p_current_scene = &m_simple_scene;
m_p_current_scene->use();
} }
void MyApplication::update(float delta_time, clock_t clock) void MyApplication::update(float delta_time, clock_t clock)
{ {
m_scene.update(delta_time, clock); if (m_glfw_input_manager.is_key_pressed(GLFW_KEY_1))
{
swap_scene(&m_simple_scene);
}
else if (m_glfw_input_manager.is_key_pressed(GLFW_KEY_2))
{
swap_scene(&m_object_oriented_scene);
}
m_p_current_scene->update(delta_time, clock);
} }
void MyApplication::render() void MyApplication::render()
{ {
m_scene.render(); m_p_current_scene->render();
} }
void MyApplication::close() void MyApplication::close()
{ {
m_scene.unuse(); m_p_current_scene->unuse();
} }
void MyApplication::swap_scene(Scene* scene)
{
if (m_p_current_scene != scene)
{
m_p_current_scene->unuse();
m_p_current_scene = scene;
m_p_current_scene->use();
}
}

View File

@ -2,14 +2,12 @@
#include "Application.h" #include "Application.h"
#include "MySimpleScene.h" #include "MySimpleScene.h"
#include "MyObjectOrientedScene.h"
class MyApplication : class MyApplication :
public Application public Application
{ {
public: public:
MyApplication(const char* class_name, HINSTANCE h_instance);
~MyApplication();
void init() override; void init() override;
void update(float delta_time, clock_t clock) override; void update(float delta_time, clock_t clock) override;
@ -19,6 +17,10 @@ public:
void close() override; void close() override;
private: private:
MySimpleScene m_scene; void swap_scene(Scene* scene);
Scene* m_p_current_scene = nullptr;
MySimpleScene m_simple_scene;
MyObjectOrientedScene m_object_oriented_scene;
}; };

View File

@ -8,7 +8,6 @@ MyBatch::MyBatch(const MyTriangle& triangle)
void MyBatch::render() const void MyBatch::render() const
{ {
// For now, just render everything!
glBindVertexArray(m_vao); glBindVertexArray(m_vao);
glDrawArrays(GL_TRIANGLES, 0, 3); glDrawArrays(GL_TRIANGLES, 0, 3);
} }

View File

@ -0,0 +1,38 @@
#include "MyObjectOrientedScene.h"
MyObjectOrientedScene::MyObjectOrientedScene()
: m_batch(m_triangle)
{
}
MyObjectOrientedScene::~MyObjectOrientedScene()
{
}
void MyObjectOrientedScene::init()
{
m_batch.init();
}
void MyObjectOrientedScene::use()
{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
}
void MyObjectOrientedScene::unuse()
{
}
void MyObjectOrientedScene::update(float delta_time, clock_t clock)
{
}
void MyObjectOrientedScene::render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
m_shader_program.use();
m_batch.render();
}

View File

@ -0,0 +1,29 @@
#pragma once
#include "Scene.h"
#include "MyBatch.h"
#include "MyShaderProgram.h"
#include "MyTriangle.h"
class MyObjectOrientedScene : public Scene
{
public:
MyObjectOrientedScene();
~MyObjectOrientedScene();
void init() override;
void use() override;
void unuse() override;
void update(float delta_time, clock_t clock) override;
void render() override;
private:
MyBatch m_batch;
MyTriangle m_triangle;
MyShaderProgram m_shader_program;
};

View File

@ -3,7 +3,7 @@
#include "Util.h" #include "Util.h"
MyShaderProgram::MyShaderProgram() MyShaderProgram::MyShaderProgram()
// TEMP Hardcode in the path // TEMP Hardcode in the path. (Should Use Relative Path to General Shader Dir)
: m_vertex_shader(Util::load_file("D:\\Development\\C++\\OpenGLEngine\\OpenGLEngine\\MyVertexShader.glsl"), VERTEX_SHADER), : m_vertex_shader(Util::load_file("D:\\Development\\C++\\OpenGLEngine\\OpenGLEngine\\MyVertexShader.glsl"), VERTEX_SHADER),
m_fragment_shader(Util::load_file("D:\\Development\\C++\\OpenGLEngine\\OpenGLEngine\\MyFragmentShader.glsl"), FRAGMENT_SHADER) m_fragment_shader(Util::load_file("D:\\Development\\C++\\OpenGLEngine\\OpenGLEngine\\MyFragmentShader.glsl"), FRAGMENT_SHADER)
{ {

View File

@ -7,14 +7,18 @@
class MyShaderProgram : public ShaderProgram class MyShaderProgram : public ShaderProgram
{ {
public: public:
struct Vertex struct VertexType
{ {
VertexType(float x, float y, float z)
: x(x), y(y), z(z)
{
}
float x; float x;
float y; float y;
float z; float z;
}; };
typedef unsigned int Index; typedef unsigned int IndexType;
typedef Renderable<Vertex, Index> RenderableType; typedef Renderable<VertexType, IndexType> RenderableType;
MyShaderProgram(); MyShaderProgram();

View File

@ -11,9 +11,6 @@ MySimpleScene::~MySimpleScene()
void MySimpleScene::init() void MySimpleScene::init()
{ {
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
float points[] = { float points[] = {
0.0f, 0.5f, 0.0f, 0.0f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f,
@ -27,12 +24,14 @@ void MySimpleScene::init()
glGenVertexArrays(1, &m_vao); glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao); glBindVertexArray(m_vao);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, m_vao); glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
} }
void MySimpleScene::use() void MySimpleScene::use()
{ {
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
} }
void MySimpleScene::unuse() void MySimpleScene::unuse()

View File

@ -1,7 +1,5 @@
#pragma once #pragma once
#include <time.h>
#include "Scene.h" #include "Scene.h"
#include "MyBatch.h" #include "MyBatch.h"

View File

@ -7,9 +7,9 @@ MyTriangle::MyTriangle()
MeshType* mesh = new MeshType(); MeshType* mesh = new MeshType();
mesh->vertices = new VertexType[3] mesh->vertices = new VertexType[3]
{ {
{ 0.0, 0.5, 1.0 }, { 0.0f, 0.75f, 0.0f },
{ 0.5, -0.5, 1.0 }, { 0.75f, -0.75f, 0.0f },
{ -0.5, -0.5, 1.0 }, { -0.75f, -0.75f, 0.0f },
}; };
mesh->vertex_count = 3; mesh->vertex_count = 3;
mesh->indices = new unsigned int[3] { 0, 1, 2, }; mesh->indices = new unsigned int[3] { 0, 1, 2, };
@ -38,15 +38,3 @@ void MyTriangle::populate_vbo() const
{ {
glBufferData(GL_ARRAY_BUFFER, m_p_mesh->vertex_count * sizeof(VertexType), m_p_mesh->vertices, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, m_p_mesh->vertex_count * sizeof(VertexType), m_p_mesh->vertices, GL_STATIC_DRAW);
} }
/*
GLuint MyTriangle::gen_vbo() const
{
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, m_p_mesh->vertex_count * sizeof(VertexType), m_p_mesh->vertices, GL_STATIC_DRAW); // TODO: Optimise Usage
return vbo;
}
*/

View File

@ -4,7 +4,7 @@
#include "MyShaderProgram.h" #include "MyShaderProgram.h"
class MyTriangle : public Renderable<MyShaderProgram::Vertex, MyShaderProgram::Index> class MyTriangle : public Renderable<MyShaderProgram::VertexType, MyShaderProgram::IndexType>
{ {
public: public:
MyTriangle(); MyTriangle();

View File

@ -157,6 +157,7 @@
<ClCompile Include="main.cpp" /> <ClCompile Include="main.cpp" />
<ClCompile Include="MyApplication.cpp" /> <ClCompile Include="MyApplication.cpp" />
<ClCompile Include="MyBatch.cpp" /> <ClCompile Include="MyBatch.cpp" />
<ClCompile Include="MyObjectOrientedScene.cpp" />
<ClCompile Include="MyShaderProgram.cpp" /> <ClCompile Include="MyShaderProgram.cpp" />
<ClCompile Include="MySimpleScene.cpp" /> <ClCompile Include="MySimpleScene.cpp" />
<ClCompile Include="MyTriangle.cpp" /> <ClCompile Include="MyTriangle.cpp" />
@ -179,6 +180,7 @@
<ClInclude Include="Mesh.h" /> <ClInclude Include="Mesh.h" />
<ClInclude Include="MyApplication.h" /> <ClInclude Include="MyApplication.h" />
<ClInclude Include="MyBatch.h" /> <ClInclude Include="MyBatch.h" />
<ClInclude Include="MyObjectOrientedScene.h" />
<ClInclude Include="MyShaderProgram.h" /> <ClInclude Include="MyShaderProgram.h" />
<ClInclude Include="MySimpleScene.h" /> <ClInclude Include="MySimpleScene.h" />
<ClInclude Include="MyTriangle.h" /> <ClInclude Include="MyTriangle.h" />

View File

@ -72,6 +72,9 @@
<ClCompile Include="GLFWInputManager.cpp"> <ClCompile Include="GLFWInputManager.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="MyObjectOrientedScene.cpp">
<Filter>Source Files\Example</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="InputManager.h"> <ClInclude Include="InputManager.h">
@ -140,6 +143,9 @@
<ClInclude Include="GLFWInputManager.h"> <ClInclude Include="GLFWInputManager.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="MyObjectOrientedScene.h">
<Filter>Header Files\Example</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="MyVertexShader.glsl"> <None Include="MyVertexShader.glsl">

View File

@ -10,7 +10,7 @@ int WINAPI WinMain(HINSTANCE h_instance, HINSTANCE h_prev_instance, LPSTR cmd_li
{ {
try try
{ {
MyApplication my_app("my_app", h_instance); MyApplication my_app;
return my_app.run(); return my_app.run();
} }
catch (Exception& e) catch (Exception& e)