Add code
This commit is contained in:
parent
777df2cbe7
commit
9fbd7938d0
|
@ -0,0 +1,65 @@
|
||||||
|
cmake_minimum_required(VERSION 3.14)
|
||||||
|
project(nexus)
|
||||||
|
|
||||||
|
|
||||||
|
find_package(X11 REQUIRED)
|
||||||
|
find_package(OpenGL REQUIRED)
|
||||||
|
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
|
||||||
|
add_executable(nexus)
|
||||||
|
|
||||||
|
target_compile_options(
|
||||||
|
nexus
|
||||||
|
PRIVATE
|
||||||
|
-fno-exceptions
|
||||||
|
-Wall)
|
||||||
|
|
||||||
|
target_sources(
|
||||||
|
nexus
|
||||||
|
PRIVATE
|
||||||
|
Source/Graphics/GlLoader.cpp
|
||||||
|
Source/Graphics/Shader.cpp
|
||||||
|
Source/Main.cpp
|
||||||
|
Source/Systems/CameraControlSystem.cpp
|
||||||
|
Source/Systems/PhysicsSystem.cpp
|
||||||
|
Source/Systems/PlayerControlSystem.cpp
|
||||||
|
Source/Systems/RenderSystem.cpp
|
||||||
|
Source/WindowManager.cpp)
|
||||||
|
|
||||||
|
target_sources(
|
||||||
|
nexus
|
||||||
|
PRIVATE
|
||||||
|
Source/Components/Camera.hpp
|
||||||
|
Source/Components/Gravity.hpp
|
||||||
|
Source/Components/Player.hpp
|
||||||
|
Source/Components/Renderable.hpp
|
||||||
|
Source/Components/RigidBody.hpp
|
||||||
|
Source/Components/Thrust.hpp
|
||||||
|
Source/Components/Transform.hpp
|
||||||
|
Source/Core/ComponentArray.hpp
|
||||||
|
Source/Core/ComponentManager.hpp
|
||||||
|
Source/Core/Coordinator.hpp
|
||||||
|
Source/Core/EntityManager.hpp
|
||||||
|
Source/Core/EventManager.hpp
|
||||||
|
Source/Core/System.hpp
|
||||||
|
Source/Core/SystemManager.hpp
|
||||||
|
Source/Core/Types.hpp
|
||||||
|
Source/Math/Vec2.hpp
|
||||||
|
Source/Math/Vec3.hpp
|
||||||
|
Source/Math/Vec4.hpp)
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
nexus
|
||||||
|
PRIVATE
|
||||||
|
Source)
|
||||||
|
|
||||||
|
target_link_libraries(
|
||||||
|
nexus
|
||||||
|
PRIVATE
|
||||||
|
OpenGL::GLX
|
||||||
|
X11::X11)
|
|
@ -0,0 +1,29 @@
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
in vec3 normal;
|
||||||
|
in vec3 fragPosWorld;
|
||||||
|
|
||||||
|
uniform vec3 uColor;
|
||||||
|
|
||||||
|
vec3 lightColor = vec3(1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
vec3 lightPos = vec3(-100.0f, 50.0f, 100.0f);
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Ambient
|
||||||
|
float ambientStrength = 0.5;
|
||||||
|
vec3 ambient = ambientStrength * lightColor;
|
||||||
|
|
||||||
|
// Diffuse
|
||||||
|
vec3 norm = normalize(normal);
|
||||||
|
vec3 lightDir = normalize(lightPos - fragPosWorld);
|
||||||
|
float diff = max(dot(norm, lightDir), 0.0);
|
||||||
|
vec3 diffuse = diff * lightColor;
|
||||||
|
|
||||||
|
|
||||||
|
vec3 result = (ambient + diffuse) * uColor;
|
||||||
|
FragColor = vec4(result, 1.0);
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout (location = 0) in vec3 inPos;
|
||||||
|
layout (location = 1) in vec3 inNormal;
|
||||||
|
|
||||||
|
uniform mat4 uModel;
|
||||||
|
uniform mat4 uView;
|
||||||
|
uniform mat4 uProjection;
|
||||||
|
|
||||||
|
out vec3 normal;
|
||||||
|
out vec3 fragPosWorld;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
fragPosWorld = vec3(uModel * vec4(inPos, 1.0));
|
||||||
|
normal = vec3(uModel * vec4(inNormal, 0.0));
|
||||||
|
|
||||||
|
gl_Position = uProjection * uView * uModel * vec4(inPos, 1.0f);
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Math/Mat44.hpp"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct Camera
|
||||||
|
{
|
||||||
|
Mat44 projectionTransform;
|
||||||
|
|
||||||
|
|
||||||
|
static Mat44 MakeProjectionTransform(float fov, float nearClip, float farClip, unsigned int viewWidth, unsigned int viewHeight)
|
||||||
|
{
|
||||||
|
float zClipBias0 =
|
||||||
|
(farClip + nearClip)
|
||||||
|
/ (farClip - nearClip);
|
||||||
|
|
||||||
|
float zClipBias1 =
|
||||||
|
(2.0f * farClip * nearClip)
|
||||||
|
/ (farClip - nearClip);
|
||||||
|
|
||||||
|
float zoomX = 1.0f / tanf((fov / 2.0f) * (M_PI / 180.0f));
|
||||||
|
float zoomY = (zoomX * static_cast<float>(viewWidth)) / static_cast<float>(viewHeight);
|
||||||
|
|
||||||
|
Mat44 transform;
|
||||||
|
transform.m[0][0] = zoomX;
|
||||||
|
transform.m[1][1] = zoomY;
|
||||||
|
transform.m[2][2] = -zClipBias0;
|
||||||
|
transform.m[3][2] = -1;
|
||||||
|
transform.m[2][3] = -zClipBias1;
|
||||||
|
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Math/Vec3.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
struct Gravity
|
||||||
|
{
|
||||||
|
Vec3 force;
|
||||||
|
};
|
|
@ -0,0 +1,6 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
struct Player
|
||||||
|
{
|
||||||
|
};
|
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Math/Vec3.hpp"
|
||||||
|
|
||||||
|
struct Renderable
|
||||||
|
{
|
||||||
|
Vec3 color;
|
||||||
|
};
|
|
@ -0,0 +1,10 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Math/Vec3.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
struct RigidBody
|
||||||
|
{
|
||||||
|
Vec3 velocity;
|
||||||
|
Vec3 acceleration;
|
||||||
|
};
|
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Math/Vec3.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
struct Thrust
|
||||||
|
{
|
||||||
|
Vec3 force;
|
||||||
|
};
|
|
@ -0,0 +1,11 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Math/Vec3.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
struct Transform
|
||||||
|
{
|
||||||
|
Vec3 position;
|
||||||
|
Vec3 rotation;
|
||||||
|
Vec3 scale;
|
||||||
|
};
|
|
@ -0,0 +1,73 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Types.hpp"
|
||||||
|
#include <array>
|
||||||
|
#include <cassert>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
||||||
|
class IComponentArray
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IComponentArray() = default;
|
||||||
|
virtual void EntityDestroyed(Entity entity) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class ComponentArray : public IComponentArray
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void InsertData(Entity entity, T component)
|
||||||
|
{
|
||||||
|
assert(mEntityToIndexMap.find(entity) == mEntityToIndexMap.end() && "Component added to same entity more than once.");
|
||||||
|
|
||||||
|
// Put new entry at end
|
||||||
|
size_t newIndex = mSize;
|
||||||
|
mEntityToIndexMap[entity] = newIndex;
|
||||||
|
mIndexToEntityMap[newIndex] = entity;
|
||||||
|
mComponentArray[newIndex] = component;
|
||||||
|
++mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveData(Entity entity)
|
||||||
|
{
|
||||||
|
assert(mEntityToIndexMap.find(entity) != mEntityToIndexMap.end() && "Removing non-existent component.");
|
||||||
|
|
||||||
|
// Copy element at end into deleted element's place to maintain density
|
||||||
|
size_t indexOfRemovedEntity = mEntityToIndexMap[entity];
|
||||||
|
size_t indexOfLastElement = mSize - 1;
|
||||||
|
mComponentArray[indexOfRemovedEntity] = mComponentArray[indexOfLastElement];
|
||||||
|
|
||||||
|
// Update map to point to moved spot
|
||||||
|
Entity entityOfLastElement = mIndexToEntityMap[indexOfLastElement];
|
||||||
|
mEntityToIndexMap[entityOfLastElement] = indexOfRemovedEntity;
|
||||||
|
mIndexToEntityMap[indexOfRemovedEntity] = entityOfLastElement;
|
||||||
|
|
||||||
|
mEntityToIndexMap.erase(entity);
|
||||||
|
mIndexToEntityMap.erase(indexOfLastElement);
|
||||||
|
|
||||||
|
--mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
T& GetData(Entity entity)
|
||||||
|
{
|
||||||
|
assert(mEntityToIndexMap.find(entity) != mEntityToIndexMap.end() && "Retrieving non-existent component.");
|
||||||
|
|
||||||
|
return mComponentArray[mEntityToIndexMap[entity]];
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntityDestroyed(Entity entity) override
|
||||||
|
{
|
||||||
|
if (mEntityToIndexMap.find(entity) != mEntityToIndexMap.end())
|
||||||
|
{
|
||||||
|
RemoveData(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<T, MAX_ENTITIES> mComponentArray{};
|
||||||
|
std::unordered_map<Entity, size_t> mEntityToIndexMap{};
|
||||||
|
std::unordered_map<size_t, Entity> mIndexToEntityMap{};
|
||||||
|
size_t mSize{};
|
||||||
|
};
|
|
@ -0,0 +1,79 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ComponentArray.hpp"
|
||||||
|
#include "Types.hpp"
|
||||||
|
#include <any>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
||||||
|
class ComponentManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template<typename T>
|
||||||
|
void RegisterComponent()
|
||||||
|
{
|
||||||
|
const char* typeName = typeid(T).name();
|
||||||
|
|
||||||
|
assert(mComponentTypes.find(typeName) == mComponentTypes.end() && "Registering component type more than once.");
|
||||||
|
|
||||||
|
mComponentTypes.insert({typeName, mNextComponentType});
|
||||||
|
mComponentArrays.insert({typeName, std::make_shared<ComponentArray<T>>()});
|
||||||
|
|
||||||
|
++mNextComponentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
ComponentType GetComponentType()
|
||||||
|
{
|
||||||
|
const char* typeName = typeid(T).name();
|
||||||
|
|
||||||
|
assert(mComponentTypes.find(typeName) != mComponentTypes.end() && "Component not registered before use.");
|
||||||
|
|
||||||
|
return mComponentTypes[typeName];
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void AddComponent(Entity entity, T component)
|
||||||
|
{
|
||||||
|
GetComponentArray<T>()->InsertData(entity, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void RemoveComponent(Entity entity)
|
||||||
|
{
|
||||||
|
GetComponentArray<T>()->RemoveData(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T& GetComponent(Entity entity)
|
||||||
|
{
|
||||||
|
return GetComponentArray<T>()->GetData(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntityDestroyed(Entity entity)
|
||||||
|
{
|
||||||
|
for (auto const& pair : mComponentArrays)
|
||||||
|
{
|
||||||
|
auto const& component = pair.second;
|
||||||
|
|
||||||
|
component->EntityDestroyed(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<const char*, ComponentType> mComponentTypes{};
|
||||||
|
std::unordered_map<const char*, std::shared_ptr<IComponentArray>> mComponentArrays{};
|
||||||
|
ComponentType mNextComponentType{};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::shared_ptr<ComponentArray<T>> GetComponentArray()
|
||||||
|
{
|
||||||
|
const char* typeName = typeid(T).name();
|
||||||
|
|
||||||
|
assert(mComponentTypes.find(typeName) != mComponentTypes.end() && "Component not registered before use.");
|
||||||
|
|
||||||
|
return std::static_pointer_cast<ComponentArray<T>>(mComponentArrays[typeName]);
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,118 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ComponentManager.hpp"
|
||||||
|
#include "EntityManager.hpp"
|
||||||
|
#include "EventManager.hpp"
|
||||||
|
#include "SystemManager.hpp"
|
||||||
|
#include "Types.hpp"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
|
class Coordinator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Init()
|
||||||
|
{
|
||||||
|
mComponentManager = std::make_unique<ComponentManager>();
|
||||||
|
mEntityManager = std::make_unique<EntityManager>();
|
||||||
|
mEventManager = std::make_unique<EventManager>();
|
||||||
|
mSystemManager = std::make_unique<SystemManager>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Entity methods
|
||||||
|
Entity CreateEntity()
|
||||||
|
{
|
||||||
|
return mEntityManager->CreateEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DestroyEntity(Entity entity)
|
||||||
|
{
|
||||||
|
mEntityManager->DestroyEntity(entity);
|
||||||
|
|
||||||
|
mComponentManager->EntityDestroyed(entity);
|
||||||
|
|
||||||
|
mSystemManager->EntityDestroyed(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Component methods
|
||||||
|
template<typename T>
|
||||||
|
void RegisterComponent()
|
||||||
|
{
|
||||||
|
mComponentManager->RegisterComponent<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void AddComponent(Entity entity, T component)
|
||||||
|
{
|
||||||
|
mComponentManager->AddComponent<T>(entity, component);
|
||||||
|
|
||||||
|
auto signature = mEntityManager->GetSignature(entity);
|
||||||
|
signature.set(mComponentManager->GetComponentType<T>(), true);
|
||||||
|
mEntityManager->SetSignature(entity, signature);
|
||||||
|
|
||||||
|
mSystemManager->EntitySignatureChanged(entity, signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void RemoveComponent(Entity entity)
|
||||||
|
{
|
||||||
|
mComponentManager->RemoveComponent<T>(entity);
|
||||||
|
|
||||||
|
auto signature = mEntityManager->GetSignature(entity);
|
||||||
|
signature.set(mComponentManager->GetComponentType<T>(), false);
|
||||||
|
mEntityManager->SetSignature(entity, signature);
|
||||||
|
|
||||||
|
mSystemManager->EntitySignatureChanged(entity, signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T& GetComponent(Entity entity)
|
||||||
|
{
|
||||||
|
return mComponentManager->GetComponent<T>(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
ComponentType GetComponentType()
|
||||||
|
{
|
||||||
|
return mComponentManager->GetComponentType<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// System methods
|
||||||
|
template<typename T>
|
||||||
|
std::shared_ptr<T> RegisterSystem()
|
||||||
|
{
|
||||||
|
return mSystemManager->RegisterSystem<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void SetSystemSignature(Signature signature)
|
||||||
|
{
|
||||||
|
mSystemManager->SetSignature<T>(signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Event methods
|
||||||
|
void AddEventListener(EventId eventId, std::function<void(Event&)> const& listener)
|
||||||
|
{
|
||||||
|
mEventManager->AddListener(eventId, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendEvent(Event& event)
|
||||||
|
{
|
||||||
|
mEventManager->SendEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendEvent(EventId eventId)
|
||||||
|
{
|
||||||
|
mEventManager->SendEvent(eventId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<ComponentManager> mComponentManager;
|
||||||
|
std::unique_ptr<EntityManager> mEntityManager;
|
||||||
|
std::unique_ptr<EventManager> mEventManager;
|
||||||
|
std::unique_ptr<SystemManager> mSystemManager;
|
||||||
|
};
|
|
@ -0,0 +1,58 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Types.hpp"
|
||||||
|
#include <array>
|
||||||
|
#include <cassert>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
|
||||||
|
class EntityManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EntityManager()
|
||||||
|
{
|
||||||
|
for (Entity entity = 0; entity < MAX_ENTITIES; ++entity)
|
||||||
|
{
|
||||||
|
mAvailableEntities.push(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity CreateEntity()
|
||||||
|
{
|
||||||
|
assert(mLivingEntityCount < MAX_ENTITIES && "Too many entities in existence.");
|
||||||
|
|
||||||
|
Entity id = mAvailableEntities.front();
|
||||||
|
mAvailableEntities.pop();
|
||||||
|
++mLivingEntityCount;
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DestroyEntity(Entity entity)
|
||||||
|
{
|
||||||
|
assert(entity < MAX_ENTITIES && "Entity out of range.");
|
||||||
|
|
||||||
|
mSignatures[entity].reset();
|
||||||
|
mAvailableEntities.push(entity);
|
||||||
|
--mLivingEntityCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSignature(Entity entity, Signature signature)
|
||||||
|
{
|
||||||
|
assert(entity < MAX_ENTITIES && "Entity out of range.");
|
||||||
|
|
||||||
|
mSignatures[entity] = signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
Signature GetSignature(Entity entity)
|
||||||
|
{
|
||||||
|
assert(entity < MAX_ENTITIES && "Entity out of range.");
|
||||||
|
|
||||||
|
return mSignatures[entity];
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::queue<Entity> mAvailableEntities{};
|
||||||
|
std::array<Signature, MAX_ENTITIES> mSignatures{};
|
||||||
|
uint32_t mLivingEntityCount{};
|
||||||
|
};
|
|
@ -0,0 +1,37 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Types.hpp"
|
||||||
|
#include <any>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
||||||
|
class Event
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Event() = delete;
|
||||||
|
|
||||||
|
explicit Event(EventId type)
|
||||||
|
: mType(type)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void SetParam(EventId id, T value)
|
||||||
|
{
|
||||||
|
mData[id] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T GetParam(EventId id)
|
||||||
|
{
|
||||||
|
return std::any_cast<T>(mData[id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
EventId GetType() const
|
||||||
|
{
|
||||||
|
return mType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
EventId mType{};
|
||||||
|
std::unordered_map<EventId, std::any> mData{};
|
||||||
|
};
|
|
@ -0,0 +1,40 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Event.hpp"
|
||||||
|
#include "Types.hpp"
|
||||||
|
#include <functional>
|
||||||
|
#include <list>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
||||||
|
class EventManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void AddListener(EventId eventId, std::function<void(Event&)> const& listener)
|
||||||
|
{
|
||||||
|
listeners[eventId].push_back(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendEvent(Event& event)
|
||||||
|
{
|
||||||
|
uint32_t type = event.GetType();
|
||||||
|
|
||||||
|
for (auto const& listener : listeners[type])
|
||||||
|
{
|
||||||
|
listener(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendEvent(EventId eventId)
|
||||||
|
{
|
||||||
|
Event event(eventId);
|
||||||
|
|
||||||
|
for (auto const& listener : listeners[eventId])
|
||||||
|
{
|
||||||
|
listener(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<EventId, std::list<std::function<void(Event&)>>> listeners;
|
||||||
|
};
|
|
@ -0,0 +1,11 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Types.hpp"
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
|
||||||
|
class System
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::set<Entity> mEntities;
|
||||||
|
};
|
|
@ -0,0 +1,68 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "System.hpp"
|
||||||
|
#include "Types.hpp"
|
||||||
|
#include <cassert>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
||||||
|
class SystemManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template<typename T>
|
||||||
|
std::shared_ptr<T> RegisterSystem()
|
||||||
|
{
|
||||||
|
const char* typeName = typeid(T).name();
|
||||||
|
|
||||||
|
assert(mSystems.find(typeName) == mSystems.end() && "Registering system more than once.");
|
||||||
|
|
||||||
|
auto system = std::make_shared<T>();
|
||||||
|
mSystems.insert({typeName, system});
|
||||||
|
return system;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void SetSignature(Signature signature)
|
||||||
|
{
|
||||||
|
const char* typeName = typeid(T).name();
|
||||||
|
|
||||||
|
assert(mSystems.find(typeName) != mSystems.end() && "System used before registered.");
|
||||||
|
|
||||||
|
mSignatures.insert({typeName, signature});
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntityDestroyed(Entity entity)
|
||||||
|
{
|
||||||
|
for (auto const& pair : mSystems)
|
||||||
|
{
|
||||||
|
auto const& system = pair.second;
|
||||||
|
|
||||||
|
|
||||||
|
system->mEntities.erase(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntitySignatureChanged(Entity entity, Signature entitySignature)
|
||||||
|
{
|
||||||
|
for (auto const& pair : mSystems)
|
||||||
|
{
|
||||||
|
auto const& type = pair.first;
|
||||||
|
auto const& system = pair.second;
|
||||||
|
auto const& systemSignature = mSignatures[type];
|
||||||
|
|
||||||
|
if ((entitySignature & systemSignature) == systemSignature)
|
||||||
|
{
|
||||||
|
system->mEntities.insert(entity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
system->mEntities.erase(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<const char*, Signature> mSignatures{};
|
||||||
|
std::unordered_map<const char*, std::shared_ptr<System>> mSystems{};
|
||||||
|
};
|
|
@ -0,0 +1,62 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <bitset>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
|
||||||
|
// Source: https://gist.github.com/Lee-R/3839813
|
||||||
|
constexpr std::uint32_t fnv1a_32(char const* s, std::size_t count)
|
||||||
|
{
|
||||||
|
return ((count ? fnv1a_32(s, count - 1) : 2166136261u) ^ s[count]) * 16777619u; // NOLINT (hicpp-signed-bitwise)
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr std::uint32_t operator "" _hash(char const* s, std::size_t count)
|
||||||
|
{
|
||||||
|
return fnv1a_32(s, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ECS
|
||||||
|
using Entity = std::uint32_t;
|
||||||
|
const Entity MAX_ENTITIES = 5000;
|
||||||
|
using ComponentType = std::uint8_t;
|
||||||
|
const ComponentType MAX_COMPONENTS = 32;
|
||||||
|
using Signature = std::bitset<MAX_COMPONENTS>;
|
||||||
|
|
||||||
|
|
||||||
|
// Input
|
||||||
|
enum class InputButtons
|
||||||
|
{
|
||||||
|
W,
|
||||||
|
A,
|
||||||
|
S,
|
||||||
|
D,
|
||||||
|
Q,
|
||||||
|
E
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Events
|
||||||
|
using EventId = std::uint32_t;
|
||||||
|
using ParamId = std::uint32_t;
|
||||||
|
|
||||||
|
#define METHOD_LISTENER(EventType, Listener) EventType, std::bind(&Listener, this, std::placeholders::_1)
|
||||||
|
#define FUNCTION_LISTENER(EventType, Listener) EventType, std::bind(&Listener, std::placeholders::_1)
|
||||||
|
|
||||||
|
// TODO: Make these easier to define and use (macro?)
|
||||||
|
// TODO: Add some kind of enforcement/automation that a SetParam type and a GetParam type match
|
||||||
|
|
||||||
|
namespace Events::Window {
|
||||||
|
const EventId QUIT = "Events::Window::QUIT"_hash;
|
||||||
|
const EventId RESIZED = "Events::Window::RESIZED"_hash;
|
||||||
|
const EventId INPUT = "Events::Window::INPUT"_hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Events::Window::Input {
|
||||||
|
const ParamId INPUT = "Events::Window::Input::INPUT"_hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Events::Window::Resized {
|
||||||
|
const ParamId WIDTH = "Events::Window::Resized::WIDTH"_hash;
|
||||||
|
const ParamId HEIGHT = "Events::Window::Resized::HEIGHT"_hash;
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
#include "GlLoader.hpp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
|
||||||
|
PFNGLCREATESHADERPROC glCreateShader = nullptr;
|
||||||
|
PFNGLSHADERSOURCEPROC glShaderSource = nullptr;
|
||||||
|
PFNGLCOMPILESHADERPROC glCompileShader = nullptr;
|
||||||
|
PFNGLGETSHADERIVPROC glGetShaderiv = nullptr;
|
||||||
|
PFNGLGETSHADERSOURCEPROC glGetShaderInfo = nullptr;
|
||||||
|
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog = nullptr;
|
||||||
|
PFNGLCREATEPROGRAMPROC glCreateProgram = nullptr;
|
||||||
|
PFNGLATTACHSHADERPROC glAttachShader = nullptr;
|
||||||
|
PFNGLLINKPROGRAMPROC glLinkProgram = nullptr;
|
||||||
|
PFNGLGETPROGRAMIVPROC glGetProgramiv = nullptr;
|
||||||
|
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = nullptr;
|
||||||
|
PFNGLDELETESHADERPROC glDeleteShader = nullptr;
|
||||||
|
PFNGLGENBUFFERSPROC glGenBuffers = nullptr;
|
||||||
|
PFNGLBINDBUFFERPROC glBindBuffer = nullptr;
|
||||||
|
PFNGLBUFFERDATAPROC glBufferData = nullptr;
|
||||||
|
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = nullptr;
|
||||||
|
PFNGLBINDVERTEXARRAYPROC glBindVertexArray = nullptr;
|
||||||
|
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = nullptr;
|
||||||
|
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = nullptr;
|
||||||
|
PFNGLUSEPROGRAMPROC glUseProgram = nullptr;
|
||||||
|
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = nullptr;
|
||||||
|
PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv = nullptr;
|
||||||
|
PFNGLUNIFORM3FVPROC glUniform3fv = nullptr;
|
||||||
|
|
||||||
|
#define LOAD_GL_FUNCTION(type, name) \
|
||||||
|
(name) = (PFN##type##PROC) glXGetProcAddress((unsigned char *) #name); \
|
||||||
|
assert(name && "GL function not found");
|
||||||
|
|
||||||
|
void LoadGlFunctions()
|
||||||
|
{
|
||||||
|
LOAD_GL_FUNCTION(GLCREATESHADER, glCreateShader)
|
||||||
|
LOAD_GL_FUNCTION(GLSHADERSOURCE, glShaderSource)
|
||||||
|
LOAD_GL_FUNCTION(GLCOMPILESHADER, glCompileShader)
|
||||||
|
LOAD_GL_FUNCTION(GLGETSHADERIV, glGetShaderiv)
|
||||||
|
LOAD_GL_FUNCTION(GLGETSHADERSOURCE, glGetShaderInfo)
|
||||||
|
LOAD_GL_FUNCTION(GLGETSHADERINFOLOG, glGetShaderInfoLog)
|
||||||
|
LOAD_GL_FUNCTION(GLCREATEPROGRAM, glCreateProgram)
|
||||||
|
LOAD_GL_FUNCTION(GLATTACHSHADER, glAttachShader)
|
||||||
|
LOAD_GL_FUNCTION(GLLINKPROGRAM, glLinkProgram)
|
||||||
|
LOAD_GL_FUNCTION(GLGETPROGRAMIV, glGetProgramiv)
|
||||||
|
LOAD_GL_FUNCTION(GLGETPROGRAMINFOLOG, glGetProgramInfoLog)
|
||||||
|
LOAD_GL_FUNCTION(GLDELETESHADER, glDeleteShader)
|
||||||
|
LOAD_GL_FUNCTION(GLGENBUFFERS, glGenBuffers)
|
||||||
|
LOAD_GL_FUNCTION(GLBINDBUFFER, glBindBuffer)
|
||||||
|
LOAD_GL_FUNCTION(GLBUFFERDATA, glBufferData)
|
||||||
|
LOAD_GL_FUNCTION(GLGENVERTEXARRAYS, glGenVertexArrays)
|
||||||
|
LOAD_GL_FUNCTION(GLBINDVERTEXARRAY, glBindVertexArray)
|
||||||
|
LOAD_GL_FUNCTION(GLVERTEXATTRIBPOINTER, glVertexAttribPointer)
|
||||||
|
LOAD_GL_FUNCTION(GLENABLEVERTEXATTRIBARRAY, glEnableVertexAttribArray)
|
||||||
|
LOAD_GL_FUNCTION(GLUSEPROGRAM, glUseProgram)
|
||||||
|
LOAD_GL_FUNCTION(GLGETUNIFORMLOCATION, glGetUniformLocation)
|
||||||
|
LOAD_GL_FUNCTION(GLUNIFORMMATRIX4FV, glUniformMatrix4fv)
|
||||||
|
LOAD_GL_FUNCTION(GLUNIFORM3FV, glUniform3fv)
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <GL/glx.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern PFNGLCREATESHADERPROC glCreateShader;
|
||||||
|
extern PFNGLSHADERSOURCEPROC glShaderSource;
|
||||||
|
extern PFNGLCOMPILESHADERPROC glCompileShader;
|
||||||
|
extern PFNGLGETSHADERIVPROC glGetShaderiv;
|
||||||
|
extern PFNGLGETSHADERSOURCEPROC glGetShaderInfo;
|
||||||
|
extern PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
|
||||||
|
extern PFNGLCREATEPROGRAMPROC glCreateProgram;
|
||||||
|
extern PFNGLATTACHSHADERPROC glAttachShader;
|
||||||
|
extern PFNGLLINKPROGRAMPROC glLinkProgram;
|
||||||
|
extern PFNGLGETPROGRAMIVPROC glGetProgramiv;
|
||||||
|
extern PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
|
||||||
|
extern PFNGLDELETESHADERPROC glDeleteShader;
|
||||||
|
extern PFNGLGENBUFFERSPROC glGenBuffers;
|
||||||
|
extern PFNGLBINDBUFFERPROC glBindBuffer;
|
||||||
|
extern PFNGLBUFFERDATAPROC glBufferData;
|
||||||
|
extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
|
||||||
|
extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
|
||||||
|
extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
|
||||||
|
extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
|
||||||
|
extern PFNGLUSEPROGRAMPROC glUseProgram;
|
||||||
|
extern PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
|
||||||
|
extern PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
|
||||||
|
extern PFNGLUNIFORM3FVPROC glUniform3fv;
|
||||||
|
|
||||||
|
void LoadGlFunctions();
|
|
@ -0,0 +1,84 @@
|
||||||
|
#include "Shader.hpp"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
|
||||||
|
Shader::Shader(std::string const& vertexPath, std::string const& fragmentPath)
|
||||||
|
{
|
||||||
|
std::string fragmentFileContents;
|
||||||
|
std::string vertexFileContents;
|
||||||
|
|
||||||
|
// Read in the vertex shader
|
||||||
|
std::ifstream vertex_file;
|
||||||
|
|
||||||
|
vertex_file.open(vertexPath);
|
||||||
|
std::stringstream vertex_file_stream;
|
||||||
|
vertex_file_stream << vertex_file.rdbuf();
|
||||||
|
vertex_file.close();
|
||||||
|
vertexFileContents = vertex_file_stream.str();
|
||||||
|
|
||||||
|
// Read in the fragment shader
|
||||||
|
std::ifstream fragment_file;
|
||||||
|
|
||||||
|
fragment_file.open(fragmentPath);
|
||||||
|
std::stringstream fragment_file_stream;
|
||||||
|
fragment_file_stream << fragment_file.rdbuf();
|
||||||
|
fragment_file.close();
|
||||||
|
fragmentFileContents = fragment_file_stream.str();
|
||||||
|
|
||||||
|
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||||
|
|
||||||
|
const GLchar* vertex_shader_source = vertexFileContents.c_str();
|
||||||
|
glShaderSource(vertex_shader, 1, &vertex_shader_source, nullptr);
|
||||||
|
glCompileShader(vertex_shader);
|
||||||
|
|
||||||
|
int success;
|
||||||
|
char infoLog[512];
|
||||||
|
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
glGetShaderInfoLog(vertex_shader, 512, nullptr, infoLog);
|
||||||
|
std::cerr << "Error compiling vertex shader: " << infoLog << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
|
||||||
|
const GLchar* fragment_shader_source = fragmentFileContents.c_str();
|
||||||
|
glShaderSource(fragment_shader, 1, &fragment_shader_source, nullptr);
|
||||||
|
glCompileShader(fragment_shader);
|
||||||
|
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
glGetShaderInfoLog(fragment_shader, 512, nullptr, infoLog);
|
||||||
|
std::cerr << "Error compiling fragment shader: " << infoLog << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mId = glCreateProgram();
|
||||||
|
|
||||||
|
glAttachShader(mId, vertex_shader);
|
||||||
|
glAttachShader(mId, fragment_shader);
|
||||||
|
glLinkProgram(mId);
|
||||||
|
glGetProgramiv(mId, GL_LINK_STATUS, &success);
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
glGetProgramInfoLog(mId, 512, nullptr, infoLog);
|
||||||
|
std::cerr << "Error linking shaders: " << infoLog << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
glDeleteShader(vertex_shader);
|
||||||
|
glDeleteShader(fragment_shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::Activate()
|
||||||
|
{
|
||||||
|
glUseProgram(mId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "GlLoader.hpp"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
class Mat44;
|
||||||
|
class Vec3;
|
||||||
|
|
||||||
|
|
||||||
|
class Shader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Shader(std::string const& vertexPath, std::string const& fragmentPath);
|
||||||
|
|
||||||
|
void Activate();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void SetUniform(const std::string& name, const T& value)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<T, Mat44>)
|
||||||
|
{
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(mId, name.c_str()), 1, GL_TRUE, (GLfloat*)value.m);
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, Vec3>)
|
||||||
|
{
|
||||||
|
glUniform3fv(glGetUniformLocation(mId, name.c_str()), 1, (GLfloat*)&value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLuint mId;
|
||||||
|
};
|
|
@ -0,0 +1,165 @@
|
||||||
|
#include "Components/Camera.hpp"
|
||||||
|
#include "Components/Gravity.hpp"
|
||||||
|
#include "Components/Player.hpp"
|
||||||
|
#include "Components/Renderable.hpp"
|
||||||
|
#include "Components/RigidBody.hpp"
|
||||||
|
#include "Components/Thrust.hpp"
|
||||||
|
#include "Components/Transform.hpp"
|
||||||
|
#include "Core/Coordinator.hpp"
|
||||||
|
#include "Systems/CameraControlSystem.hpp"
|
||||||
|
#include "Systems/PhysicsSystem.hpp"
|
||||||
|
#include "Systems/PlayerControlSystem.hpp"
|
||||||
|
#include "Systems/RenderSystem.hpp"
|
||||||
|
#include "WindowManager.hpp"
|
||||||
|
#include <chrono>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
|
||||||
|
Coordinator gCoordinator;
|
||||||
|
|
||||||
|
static bool quit = false;
|
||||||
|
|
||||||
|
|
||||||
|
void QuitHandler(Event& event)
|
||||||
|
{
|
||||||
|
quit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
gCoordinator.Init();
|
||||||
|
|
||||||
|
|
||||||
|
WindowManager windowManager;
|
||||||
|
windowManager.Init("Nexus", 1920, 1080, 0, 0);
|
||||||
|
|
||||||
|
|
||||||
|
LoadGlFunctions();
|
||||||
|
|
||||||
|
|
||||||
|
gCoordinator.AddEventListener(FUNCTION_LISTENER(Events::Window::QUIT, QuitHandler));
|
||||||
|
|
||||||
|
|
||||||
|
gCoordinator.RegisterComponent<Camera>();
|
||||||
|
gCoordinator.RegisterComponent<Gravity>();
|
||||||
|
gCoordinator.RegisterComponent<Player>();
|
||||||
|
gCoordinator.RegisterComponent<Renderable>();
|
||||||
|
gCoordinator.RegisterComponent<RigidBody>();
|
||||||
|
gCoordinator.RegisterComponent<Thrust>();
|
||||||
|
gCoordinator.RegisterComponent<Transform>();
|
||||||
|
|
||||||
|
|
||||||
|
auto physicsSystem = gCoordinator.RegisterSystem<PhysicsSystem>();
|
||||||
|
{
|
||||||
|
Signature signature;
|
||||||
|
signature.set(gCoordinator.GetComponentType<Gravity>());
|
||||||
|
signature.set(gCoordinator.GetComponentType<RigidBody>());
|
||||||
|
signature.set(gCoordinator.GetComponentType<Transform>());
|
||||||
|
gCoordinator.SetSystemSignature<PhysicsSystem>(signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
physicsSystem->Init();
|
||||||
|
|
||||||
|
|
||||||
|
auto cameraControlSystem = gCoordinator.RegisterSystem<CameraControlSystem>();
|
||||||
|
{
|
||||||
|
Signature signature;
|
||||||
|
signature.set(gCoordinator.GetComponentType<Camera>());
|
||||||
|
signature.set(gCoordinator.GetComponentType<Transform>());
|
||||||
|
gCoordinator.SetSystemSignature<CameraControlSystem>(signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
cameraControlSystem->Init();
|
||||||
|
|
||||||
|
|
||||||
|
auto playerControlSystem = gCoordinator.RegisterSystem<PlayerControlSystem>();
|
||||||
|
{
|
||||||
|
Signature signature;
|
||||||
|
signature.set(gCoordinator.GetComponentType<Player>());
|
||||||
|
signature.set(gCoordinator.GetComponentType<Transform>());
|
||||||
|
gCoordinator.SetSystemSignature<PlayerControlSystem>(signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
playerControlSystem->Init();
|
||||||
|
|
||||||
|
|
||||||
|
auto renderSystem = gCoordinator.RegisterSystem<RenderSystem>();
|
||||||
|
{
|
||||||
|
Signature signature;
|
||||||
|
signature.set(gCoordinator.GetComponentType<Renderable>());
|
||||||
|
signature.set(gCoordinator.GetComponentType<Transform>());
|
||||||
|
gCoordinator.SetSystemSignature<RenderSystem>(signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSystem->Init();
|
||||||
|
|
||||||
|
std::vector<Entity> entities(MAX_ENTITIES - 1);
|
||||||
|
|
||||||
|
std::default_random_engine generator;
|
||||||
|
std::uniform_real_distribution<float> randPosition(-100.0f, 100.0f);
|
||||||
|
std::uniform_real_distribution<float> randRotation(0.0f, 3.0f);
|
||||||
|
std::uniform_real_distribution<float> randScale(3.0f, 5.0f);
|
||||||
|
std::uniform_real_distribution<float> randColor(0.0f, 1.0f);
|
||||||
|
std::uniform_real_distribution<float> randGravity(-10.0f, -1.0f);
|
||||||
|
|
||||||
|
float scale = randScale(generator);
|
||||||
|
|
||||||
|
for (auto& entity : entities)
|
||||||
|
{
|
||||||
|
entity = gCoordinator.CreateEntity();
|
||||||
|
gCoordinator.AddComponent(entity, Player{});
|
||||||
|
|
||||||
|
gCoordinator.AddComponent<Gravity>(
|
||||||
|
entity,
|
||||||
|
{Vec3(0.0f, randGravity(generator), 0.0f)});
|
||||||
|
|
||||||
|
gCoordinator.AddComponent(
|
||||||
|
entity,
|
||||||
|
RigidBody{
|
||||||
|
.velocity = Vec3(0.0f, 0.0f, 0.0f),
|
||||||
|
.acceleration = Vec3(0.0f, 0.0f, 0.0f)
|
||||||
|
});
|
||||||
|
|
||||||
|
gCoordinator.AddComponent(
|
||||||
|
entity,
|
||||||
|
Transform{
|
||||||
|
.position = Vec3(randPosition(generator), randPosition(generator), randPosition(generator)),
|
||||||
|
.rotation = Vec3(randRotation(generator), randRotation(generator), randRotation(generator)),
|
||||||
|
.scale = Vec3(scale, scale, scale)
|
||||||
|
});
|
||||||
|
|
||||||
|
gCoordinator.AddComponent(
|
||||||
|
entity,
|
||||||
|
Renderable{
|
||||||
|
.color = Vec3(randColor(generator), randColor(generator), randColor(generator))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
float dt = 0.0f;
|
||||||
|
|
||||||
|
while (!quit)
|
||||||
|
{
|
||||||
|
auto startTime = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
windowManager.ProcessEvents();
|
||||||
|
|
||||||
|
playerControlSystem->Update(dt);
|
||||||
|
|
||||||
|
cameraControlSystem->Update(dt);
|
||||||
|
|
||||||
|
physicsSystem->Update(dt);
|
||||||
|
|
||||||
|
renderSystem->Update(dt);
|
||||||
|
|
||||||
|
windowManager.Update();
|
||||||
|
|
||||||
|
auto stopTime = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
dt = std::chrono::duration<float, std::chrono::seconds::period>(stopTime - startTime).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
windowManager.Shutdown();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Vec4.hpp"
|
||||||
|
|
||||||
|
class Mat44
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Mat44()
|
||||||
|
{
|
||||||
|
//@formatter:off
|
||||||
|
m[0][0] = 1.0f; m[0][1] = 0.0f; m[0][2] = 0.0f; m[0][3] = 0.0f;
|
||||||
|
m[1][0] = 0.0f; m[1][1] = 1.0f; m[1][2] = 0.0f; m[1][3] = 0.0f;
|
||||||
|
m[2][0] = 0.0f; m[2][1] = 0.0f; m[2][2] = 1.0f; m[2][3] = 0.0f;
|
||||||
|
m[3][0] = 0.0f; m[3][1] = 0.0f; m[3][2] = 0.0f; m[3][3] = 1.0f;
|
||||||
|
//@formatter:on
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Mat44 operator*(Mat44 const& rhs)
|
||||||
|
{
|
||||||
|
Mat44 result;
|
||||||
|
|
||||||
|
for (int row = 0; row < 4; ++row)
|
||||||
|
{
|
||||||
|
for (int col = 0; col < 4; ++col)
|
||||||
|
{
|
||||||
|
float sum = 0.0f;
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
sum += m[row][i] * rhs.m[i][col];
|
||||||
|
}
|
||||||
|
|
||||||
|
result.m[row][col] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Vec4 operator*(Vec4 const& rhs)
|
||||||
|
{
|
||||||
|
return Vec4(
|
||||||
|
(rhs.x * m[0][0]) + (rhs.y * m[0][1]) + (rhs.z * m[0][2]) + (rhs.w * m[0][3]),
|
||||||
|
(rhs.x * m[1][0]) + (rhs.y * m[1][1]) + (rhs.z * m[1][2]) + (rhs.w * m[1][3]),
|
||||||
|
(rhs.x * m[2][0]) + (rhs.y * m[2][1]) + (rhs.z * m[2][2]) + (rhs.w * m[2][3]),
|
||||||
|
(rhs.x * m[3][0]) + (rhs.y * m[3][1]) + (rhs.z * m[3][2]) + (rhs.w * m[3][3]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float m[4][4];
|
||||||
|
};
|
|
@ -0,0 +1,47 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
class Vec2
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vec2()
|
||||||
|
: x(0.0f), y(0.0f)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Vec2(float x, float y)
|
||||||
|
: x(x), y(y)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Vec2 operator+(Vec2 const& v)
|
||||||
|
{
|
||||||
|
return Vec2(
|
||||||
|
x + v.x,
|
||||||
|
y + v.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 operator+=(Vec2 const& v)
|
||||||
|
{
|
||||||
|
x += v.x;
|
||||||
|
y += v.y;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 operator-(Vec2 const& v)
|
||||||
|
{
|
||||||
|
return Vec2(
|
||||||
|
x - v.x,
|
||||||
|
y - v.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 operator-=(Vec2 const& v)
|
||||||
|
{
|
||||||
|
x -= v.x;
|
||||||
|
y -= v.y;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float x, y;
|
||||||
|
};
|
|
@ -0,0 +1,85 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
class Vec3
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vec3()
|
||||||
|
: x(0.0f), y(0.0f), z(0.0f)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Vec3(float x, float y, float z)
|
||||||
|
: x(x), y(y), z(z)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Vec3 operator+(Vec3 const& rhs) const
|
||||||
|
{
|
||||||
|
return Vec3(
|
||||||
|
x + rhs.x,
|
||||||
|
y + rhs.y,
|
||||||
|
z + rhs.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3 operator+=(Vec3 const& rhs)
|
||||||
|
{
|
||||||
|
x += rhs.x;
|
||||||
|
y += rhs.y;
|
||||||
|
z += rhs.z;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3 operator-(Vec3 const& rhs) const
|
||||||
|
{
|
||||||
|
return Vec3(
|
||||||
|
x - rhs.x,
|
||||||
|
y - rhs.y,
|
||||||
|
z - rhs.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3 operator-=(Vec3 const& rhs)
|
||||||
|
{
|
||||||
|
x -= rhs.x;
|
||||||
|
y -= rhs.y;
|
||||||
|
z -= rhs.z;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3 operator*(Vec3 const& rhs) const
|
||||||
|
{
|
||||||
|
return Vec3(
|
||||||
|
x * rhs.x,
|
||||||
|
y * rhs.y,
|
||||||
|
z * rhs.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3 operator*=(Vec3 const& rhs)
|
||||||
|
{
|
||||||
|
x *= rhs.x;
|
||||||
|
y *= rhs.y;
|
||||||
|
z *= rhs.z;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3 operator*(float rhs) const
|
||||||
|
{
|
||||||
|
return Vec3(
|
||||||
|
x * rhs,
|
||||||
|
y * rhs,
|
||||||
|
z * rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3 operator*=(float rhs)
|
||||||
|
{
|
||||||
|
x *= rhs;
|
||||||
|
y *= rhs;
|
||||||
|
z *= rhs;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float x, y, z;
|
||||||
|
};
|
|
@ -0,0 +1,59 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
class Vec4
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vec4()
|
||||||
|
: x(0.0f), y(0.0f), z(0.0f), w(0.0f)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Vec4(float x, float y, float z)
|
||||||
|
: x(x), y(y), z(z), w(0.0f)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Vec4(float x, float y, float z, float w)
|
||||||
|
: x(x), y(y), z(z), w(w)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Vec4 operator+(Vec4 const& v) const
|
||||||
|
{
|
||||||
|
return Vec4(
|
||||||
|
x + v.x,
|
||||||
|
y + v.y,
|
||||||
|
z + v.z,
|
||||||
|
w + v.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4 operator+=(Vec4 const& v)
|
||||||
|
{
|
||||||
|
x += v.x;
|
||||||
|
y += v.y;
|
||||||
|
z += v.z;
|
||||||
|
w += v.w;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4 operator-(Vec4 const& v) const
|
||||||
|
{
|
||||||
|
return Vec4(
|
||||||
|
x - v.x,
|
||||||
|
y - v.y,
|
||||||
|
z - v.z,
|
||||||
|
w - v.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4 operator-=(Vec4 const& v)
|
||||||
|
{
|
||||||
|
x -= v.x;
|
||||||
|
y -= v.y;
|
||||||
|
z -= v.z;
|
||||||
|
w -= v.w;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float x, y, z, w;
|
||||||
|
};
|
|
@ -0,0 +1,61 @@
|
||||||
|
#include "CameraControlSystem.hpp"
|
||||||
|
|
||||||
|
#include "Components/Transform.hpp"
|
||||||
|
#include "Core/Coordinator.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
extern Coordinator gCoordinator;
|
||||||
|
|
||||||
|
|
||||||
|
void CameraControlSystem::Init()
|
||||||
|
{
|
||||||
|
gCoordinator.AddEventListener(METHOD_LISTENER(Events::Window::INPUT, CameraControlSystem::InputListener));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraControlSystem::Update(float dt)
|
||||||
|
{
|
||||||
|
for (auto& entity : mEntities)
|
||||||
|
{
|
||||||
|
auto& transform = gCoordinator.GetComponent<Transform>(entity);
|
||||||
|
|
||||||
|
float speed = 20.0f;
|
||||||
|
|
||||||
|
|
||||||
|
if (mButtons.test(static_cast<std::size_t>(InputButtons::W)))
|
||||||
|
{
|
||||||
|
transform.position.z -= (dt * speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (mButtons.test(static_cast<std::size_t>(InputButtons::S)))
|
||||||
|
{
|
||||||
|
transform.position.z += (dt * speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (mButtons.test(static_cast<std::size_t>(InputButtons::Q)))
|
||||||
|
{
|
||||||
|
transform.position.y += (dt * speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (mButtons.test(static_cast<std::size_t>(InputButtons::E)))
|
||||||
|
{
|
||||||
|
transform.position.y -= (dt * speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (mButtons.test(static_cast<std::size_t>(InputButtons::A)))
|
||||||
|
{
|
||||||
|
transform.position.x -= (dt * speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (mButtons.test(static_cast<std::size_t>(InputButtons::D)))
|
||||||
|
{
|
||||||
|
transform.position.x += (dt * speed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraControlSystem::InputListener(Event& event)
|
||||||
|
{
|
||||||
|
mButtons = event.GetParam<std::bitset<8>>(Events::Window::Input::INPUT);
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Core/System.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
class Event;
|
||||||
|
|
||||||
|
|
||||||
|
class CameraControlSystem : public System
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
void Update(float dt);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::bitset<8> mButtons;
|
||||||
|
|
||||||
|
void InputListener(Event& event);
|
||||||
|
};
|
|
@ -0,0 +1,31 @@
|
||||||
|
#include "PhysicsSystem.hpp"
|
||||||
|
|
||||||
|
#include "Components/Gravity.hpp"
|
||||||
|
#include "Components/RigidBody.hpp"
|
||||||
|
#include "Components/Thrust.hpp"
|
||||||
|
#include "Components/Transform.hpp"
|
||||||
|
#include "Core/Coordinator.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
extern Coordinator gCoordinator;
|
||||||
|
|
||||||
|
|
||||||
|
void PhysicsSystem::Init()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicsSystem::Update(float dt)
|
||||||
|
{
|
||||||
|
for (auto const& entity : mEntities)
|
||||||
|
{
|
||||||
|
auto& rigidBody = gCoordinator.GetComponent<RigidBody>(entity);
|
||||||
|
auto& transform = gCoordinator.GetComponent<Transform>(entity);
|
||||||
|
|
||||||
|
// Forces
|
||||||
|
auto const& gravity = gCoordinator.GetComponent<Gravity>(entity);
|
||||||
|
|
||||||
|
transform.position += rigidBody.velocity * dt;
|
||||||
|
|
||||||
|
rigidBody.velocity += gravity.force * dt;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Core/System.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
class PhysicsSystem : public System
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
void Update(float dt);
|
||||||
|
};
|
|
@ -0,0 +1,61 @@
|
||||||
|
#include "PlayerControlSystem.hpp"
|
||||||
|
|
||||||
|
#include "Components/Player.hpp"
|
||||||
|
#include "Components/Thrust.hpp"
|
||||||
|
#include "Components/Transform.hpp"
|
||||||
|
#include "Core/Coordinator.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
extern Coordinator gCoordinator;
|
||||||
|
|
||||||
|
|
||||||
|
void PlayerControlSystem::Init()
|
||||||
|
{
|
||||||
|
gCoordinator.AddEventListener(METHOD_LISTENER(Events::Window::INPUT, PlayerControlSystem::InputListener));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerControlSystem::Update(float dt)
|
||||||
|
{
|
||||||
|
//for (auto& entity : mEntities)
|
||||||
|
//{
|
||||||
|
// auto& transform = gCoordinator.Get<Transform>(entity);
|
||||||
|
|
||||||
|
|
||||||
|
// if (mButtons.test(static_cast<std::size_t>(InputButtons::W)))
|
||||||
|
// {
|
||||||
|
// transform.position.z += (dt * 10.0f);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// else if (mButtons.test(static_cast<std::size_t>(InputButtons::S)))
|
||||||
|
// {
|
||||||
|
// transform.position.z -= (dt * 10.0f);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// if (mButtons.test(static_cast<std::size_t>(InputButtons::Q)))
|
||||||
|
// {
|
||||||
|
// transform.position.y += (dt * 10.0f);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// else if (mButtons.test(static_cast<std::size_t>(InputButtons::E)))
|
||||||
|
// {
|
||||||
|
// transform.position.y -= (dt * 10.0f);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// if (mButtons.test(static_cast<std::size_t>(InputButtons::A)))
|
||||||
|
// {
|
||||||
|
// transform.position.x += (dt * 10.0f);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// else if (mButtons.test(static_cast<std::size_t>(InputButtons::D)))
|
||||||
|
// {
|
||||||
|
// transform.position.x -= (dt * 10.0f);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerControlSystem::InputListener(Event& event)
|
||||||
|
{
|
||||||
|
mButtons = event.GetParam<std::bitset<8>>(Events::Window::Input::INPUT);
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Core/System.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
class Event;
|
||||||
|
|
||||||
|
|
||||||
|
class PlayerControlSystem : public System
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
void Update(float dt);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::bitset<8> mButtons;
|
||||||
|
|
||||||
|
void InputListener(Event& event);
|
||||||
|
};
|
|
@ -0,0 +1,224 @@
|
||||||
|
#include "RenderSystem.hpp"
|
||||||
|
|
||||||
|
#include "Components/Camera.hpp"
|
||||||
|
#include "Components/Renderable.hpp"
|
||||||
|
#include "Components/Transform.hpp"
|
||||||
|
#include "Core/Coordinator.hpp"
|
||||||
|
#include "Graphics/Shader.hpp"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
|
||||||
|
extern Coordinator gCoordinator;
|
||||||
|
|
||||||
|
|
||||||
|
void RenderSystem::Init()
|
||||||
|
{
|
||||||
|
gCoordinator.AddEventListener(METHOD_LISTENER(Events::Window::RESIZED, RenderSystem::WindowSizeListener));
|
||||||
|
|
||||||
|
shader = std::make_unique<Shader>("../Shaders/vertex.glsl", "../Shaders/fragment.glsl");
|
||||||
|
|
||||||
|
mCamera = gCoordinator.CreateEntity();
|
||||||
|
|
||||||
|
gCoordinator.AddComponent(
|
||||||
|
mCamera,
|
||||||
|
Transform{
|
||||||
|
.position = Vec3(0.0f, 0.0f, 500.0f)
|
||||||
|
});
|
||||||
|
|
||||||
|
gCoordinator.AddComponent(
|
||||||
|
mCamera,
|
||||||
|
Camera{
|
||||||
|
.projectionTransform = Camera::MakeProjectionTransform(45.0f, 0.1f, 1000.0f, 1920, 1080)
|
||||||
|
});
|
||||||
|
|
||||||
|
std::vector<Vec3> vertices =
|
||||||
|
{
|
||||||
|
Vec3(-0.5f, -0.5f, -0.5f),
|
||||||
|
Vec3(0.5f, -0.5f, -0.5f),
|
||||||
|
Vec3(0.5f, 0.5f, -0.5f),
|
||||||
|
Vec3(0.5f, 0.5f, -0.5f),
|
||||||
|
Vec3(-0.5f, 0.5f, -0.5f),
|
||||||
|
Vec3(-0.5f, -0.5f, -0.5f),
|
||||||
|
Vec3(-0.5f, -0.5f, 0.5),
|
||||||
|
Vec3(0.5f, -0.5f, 0.5),
|
||||||
|
Vec3(0.5f, 0.5f, 0.5),
|
||||||
|
Vec3(0.5f, 0.5f, 0.5),
|
||||||
|
Vec3(-0.5f, 0.5f, 0.5),
|
||||||
|
Vec3(-0.5f, -0.5f, 0.5),
|
||||||
|
Vec3(-0.5f, 0.5f, 0.5f),
|
||||||
|
Vec3(-0.5f, 0.5f, -0.5f),
|
||||||
|
Vec3(-0.5f, -0.5f, -0.5f),
|
||||||
|
Vec3(-0.5f, -0.5f, -0.5f),
|
||||||
|
Vec3(-0.5f, -0.5f, 0.5f),
|
||||||
|
Vec3(-0.5f, 0.5f, 0.5f),
|
||||||
|
Vec3(0.5f, 0.5f, 0.5),
|
||||||
|
Vec3(0.5f, 0.5f, -0.5),
|
||||||
|
Vec3(0.5f, -0.5f, -0.5),
|
||||||
|
Vec3(0.5f, -0.5f, -0.5),
|
||||||
|
Vec3(0.5f, -0.5f, 0.5),
|
||||||
|
Vec3(0.5f, 0.5f, 0.5),
|
||||||
|
Vec3(-0.5f, -0.5f, -0.5f),
|
||||||
|
Vec3(0.5f, -0.5f, -0.5f),
|
||||||
|
Vec3(0.5f, -0.5f, 0.5f),
|
||||||
|
Vec3(0.5f, -0.5f, 0.5f),
|
||||||
|
Vec3(-0.5f, -0.5f, 0.5f),
|
||||||
|
Vec3(-0.5f, -0.5f, -0.5f),
|
||||||
|
Vec3(-0.5f, 0.5f, -0.5),
|
||||||
|
Vec3(0.5f, 0.5f, -0.5),
|
||||||
|
Vec3(0.5f, 0.5f, 0.5),
|
||||||
|
Vec3(0.5f, 0.5f, 0.5),
|
||||||
|
Vec3(-0.5f, 0.5f, 0.5),
|
||||||
|
Vec3(-0.5f, 0.5f, -0.5)
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<Vec3> normals =
|
||||||
|
{
|
||||||
|
Vec3(0.0f, 0.0f, -1.0f),
|
||||||
|
Vec3(0.0f, 0.0f, -1.0f),
|
||||||
|
Vec3(0.0f, 0.0f, -1.0f),
|
||||||
|
Vec3(0.0f, 0.0f, -1.0f),
|
||||||
|
Vec3(0.0f, 0.0f, -1.0f),
|
||||||
|
Vec3(0.0f, 0.0f, -1.0f),
|
||||||
|
Vec3(0.0f, 0.0f, 1.0f),
|
||||||
|
Vec3(0.0f, 0.0f, 1.0f),
|
||||||
|
Vec3(0.0f, 0.0f, 1.0f),
|
||||||
|
Vec3(0.0f, 0.0f, 1.0f),
|
||||||
|
Vec3(0.0f, 0.0f, 1.0f),
|
||||||
|
Vec3(0.0f, 0.0f, 1.0f),
|
||||||
|
Vec3(-1.0f, 0.0f, 0.0f),
|
||||||
|
Vec3(-1.0f, 0.0f, 0.0f),
|
||||||
|
Vec3(-1.0f, 0.0f, 0.0f),
|
||||||
|
Vec3(-1.0f, 0.0f, 0.0f),
|
||||||
|
Vec3(-1.0f, 0.0f, 0.0f),
|
||||||
|
Vec3(-1.0f, 0.0f, 0.0f),
|
||||||
|
Vec3(1.0f, 0.0f, 0.0f),
|
||||||
|
Vec3(1.0f, 0.0f, 0.0f),
|
||||||
|
Vec3(1.0f, 0.0f, 0.0f),
|
||||||
|
Vec3(1.0f, 0.0f, 0.0f),
|
||||||
|
Vec3(1.0f, 0.0f, 0.0f),
|
||||||
|
Vec3(1.0f, 0.0f, 0.0f),
|
||||||
|
Vec3(0.0f, -1.0f, 0.0f),
|
||||||
|
Vec3(0.0f, -1.0f, 0.0f),
|
||||||
|
Vec3(0.0f, -1.0f, 0.0f),
|
||||||
|
Vec3(0.0f, -1.0f, 0.0f),
|
||||||
|
Vec3(0.0f, -1.0f, 0.0f),
|
||||||
|
Vec3(0.0f, -1.0f, 0.0f),
|
||||||
|
Vec3(0.0f, 1.0f, 0.0f),
|
||||||
|
Vec3(0.0f, 1.0f, 0.0f),
|
||||||
|
Vec3(0.0f, 1.0f, 0.0f),
|
||||||
|
Vec3(0.0f, 1.0f, 0.0f),
|
||||||
|
Vec3(0.0f, 1.0f, 0.0f),
|
||||||
|
Vec3(0.0f, 1.0f, 0.0)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &mVao);
|
||||||
|
glBindVertexArray(mVao);
|
||||||
|
|
||||||
|
// Vertices
|
||||||
|
glGenBuffers(1, &mVboVertices);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, mVboVertices);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(Vec3) * vertices.size(), vertices.data(), GL_STATIC_DRAW);
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), (void*)nullptr);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
// Surface normal
|
||||||
|
glGenBuffers(1, &mVboNormals);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, mVboNormals);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(Vec3) * normals.size(), normals.data(), GL_STATIC_DRAW);
|
||||||
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), (void*)nullptr);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RenderSystem::Update(float dt)
|
||||||
|
{
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // NOLINT (hicpp-signed-bitwise)
|
||||||
|
|
||||||
|
shader->Activate();
|
||||||
|
glBindVertexArray(mVao);
|
||||||
|
|
||||||
|
|
||||||
|
auto& cameraTransform = gCoordinator.GetComponent<Transform>(mCamera);
|
||||||
|
auto& camera = gCoordinator.GetComponent<Camera>(mCamera);
|
||||||
|
|
||||||
|
for (auto const& entity : mEntities)
|
||||||
|
{
|
||||||
|
auto const& transform = gCoordinator.GetComponent<Transform>(entity);
|
||||||
|
auto const& renderable = gCoordinator.GetComponent<Renderable>(entity);
|
||||||
|
|
||||||
|
Mat44 view;
|
||||||
|
view.m[0][3] = -cameraTransform.position.x;
|
||||||
|
view.m[1][3] = -cameraTransform.position.y;
|
||||||
|
view.m[2][3] = -cameraTransform.position.z;
|
||||||
|
|
||||||
|
Mat44 rotY;
|
||||||
|
|
||||||
|
float cos_theta_y = cosf(transform.rotation.y);
|
||||||
|
float sin_theta_y = sinf(transform.rotation.y);
|
||||||
|
|
||||||
|
rotY.m[0][0] = cos_theta_y;
|
||||||
|
rotY.m[2][0] = -sin_theta_y;
|
||||||
|
rotY.m[0][2] = sin_theta_y;
|
||||||
|
rotY.m[2][2] = cos_theta_y;
|
||||||
|
|
||||||
|
|
||||||
|
Mat44 rotX;
|
||||||
|
|
||||||
|
float cosThetaX = cosf(transform.rotation.x);
|
||||||
|
float sinThetaX = sinf(transform.rotation.x);
|
||||||
|
|
||||||
|
rotX.m[1][1] = cosThetaX;
|
||||||
|
rotX.m[2][1] = sinThetaX;
|
||||||
|
rotX.m[1][2] = -sinThetaX;
|
||||||
|
rotX.m[2][2] = cosThetaX;
|
||||||
|
|
||||||
|
|
||||||
|
Mat44 rotZ;
|
||||||
|
|
||||||
|
float cosThetaZ = cosf(transform.rotation.z);
|
||||||
|
float sinThetaZ = sinf(transform.rotation.z);
|
||||||
|
|
||||||
|
rotZ.m[0][0] = cosThetaZ;
|
||||||
|
rotZ.m[1][0] = sinThetaZ;
|
||||||
|
rotZ.m[0][1] = -sinThetaZ;
|
||||||
|
rotZ.m[1][1] = cosThetaZ;
|
||||||
|
|
||||||
|
|
||||||
|
Mat44 translate;
|
||||||
|
translate.m[0][3] = transform.position.x;
|
||||||
|
translate.m[1][3] = transform.position.y;
|
||||||
|
translate.m[2][3] = transform.position.z;
|
||||||
|
|
||||||
|
Mat44 scaleMat;
|
||||||
|
scaleMat.m[0][0] = transform.scale.x;
|
||||||
|
scaleMat.m[1][1] = transform.scale.y;
|
||||||
|
scaleMat.m[2][2] = transform.scale.z;
|
||||||
|
|
||||||
|
Mat44 model = translate * scaleMat * rotY;
|
||||||
|
|
||||||
|
Mat44 projection = camera.projectionTransform;
|
||||||
|
|
||||||
|
shader->SetUniform<Mat44>("uModel", model);
|
||||||
|
shader->SetUniform<Mat44>("uView", view);
|
||||||
|
shader->SetUniform<Mat44>("uProjection", projection);
|
||||||
|
shader->SetUniform<Vec3>("uColor", renderable.color);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderSystem::WindowSizeListener(Event& event)
|
||||||
|
{
|
||||||
|
auto windowWidth = event.GetParam<unsigned int>(Events::Window::Resized::WIDTH);
|
||||||
|
auto windowHeight = event.GetParam<unsigned int>(Events::Window::Resized::HEIGHT);
|
||||||
|
|
||||||
|
auto& camera = gCoordinator.GetComponent<Camera>(mCamera);
|
||||||
|
camera.projectionTransform = Camera::MakeProjectionTransform(45.0f, 0.1f, 1000.0f, windowWidth, windowHeight);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Core/System.hpp"
|
||||||
|
#include "Graphics/GlLoader.hpp"
|
||||||
|
#include "Graphics/Shader.hpp"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
|
class Event;
|
||||||
|
|
||||||
|
|
||||||
|
class RenderSystem : public System
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
void Update(float dt);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void WindowSizeListener(Event& event);
|
||||||
|
|
||||||
|
std::unique_ptr<Shader> shader;
|
||||||
|
|
||||||
|
Entity mCamera;
|
||||||
|
|
||||||
|
GLuint mVao{};
|
||||||
|
GLuint mVboVertices{};
|
||||||
|
GLuint mVboNormals{};
|
||||||
|
};
|
|
@ -0,0 +1,301 @@
|
||||||
|
#include "WindowManager.hpp"
|
||||||
|
|
||||||
|
#include "Core/Coordinator.hpp"
|
||||||
|
#include <bitset>
|
||||||
|
#include <iostream>
|
||||||
|
#include <X11/XKBlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern Coordinator gCoordinator;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Return error to caller
|
||||||
|
void WindowManager::Init(
|
||||||
|
std::string const& windowTitle, unsigned int windowWidth, unsigned int windowHeight, unsigned int windowPositionX,
|
||||||
|
unsigned int windowPositionY)
|
||||||
|
{
|
||||||
|
// Open the mDisplay
|
||||||
|
{
|
||||||
|
mDisplay = XOpenDisplay(nullptr);
|
||||||
|
|
||||||
|
if (!mDisplay)
|
||||||
|
{
|
||||||
|
std::cerr << "Error: XOpenDisplay()\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the proper frame buffer config
|
||||||
|
GLXFBConfig frameBufferConfig{};
|
||||||
|
{
|
||||||
|
// Frame buffer configs were added in GLX version 1.3.
|
||||||
|
if (int glxMajor, glxMinor;
|
||||||
|
!glXQueryVersion(mDisplay, &glxMajor, &glxMinor)
|
||||||
|
|| ((glxMajor == 1) && (glxMinor < 3)) || (glxMajor < 1))
|
||||||
|
{
|
||||||
|
std::cerr << "Invalid GLX version.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int visualAttributes[] =
|
||||||
|
{
|
||||||
|
GLX_X_RENDERABLE, True,
|
||||||
|
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
|
||||||
|
GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
||||||
|
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
|
||||||
|
GLX_RED_SIZE, 8,
|
||||||
|
GLX_GREEN_SIZE, 8,
|
||||||
|
GLX_BLUE_SIZE, 8,
|
||||||
|
GLX_ALPHA_SIZE, 8,
|
||||||
|
GLX_DEPTH_SIZE, 24,
|
||||||
|
GLX_STENCIL_SIZE, 8,
|
||||||
|
GLX_DOUBLEBUFFER, True,
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int frameBufferCount;
|
||||||
|
GLXFBConfig* frameBufferConfigList = glXChooseFBConfig(
|
||||||
|
mDisplay, DefaultScreen(mDisplay), visualAttributes, &frameBufferCount);
|
||||||
|
|
||||||
|
if (!frameBufferConfigList)
|
||||||
|
{
|
||||||
|
std::cerr << "Error: glXChooseFBConfig()\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
frameBufferConfig = frameBufferConfigList[0];
|
||||||
|
|
||||||
|
XFree(frameBufferConfigList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create the window
|
||||||
|
{
|
||||||
|
XVisualInfo* visualInfo = glXGetVisualFromFBConfig(mDisplay, frameBufferConfig);
|
||||||
|
|
||||||
|
XSetWindowAttributes swa;
|
||||||
|
swa.colormap = XCreateColormap(
|
||||||
|
mDisplay,
|
||||||
|
RootWindow(mDisplay, visualInfo->screen),
|
||||||
|
visualInfo->visual, AllocNone);
|
||||||
|
|
||||||
|
swa.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask; // NOLINT(hicpp-signed-bitwise)
|
||||||
|
|
||||||
|
mWindow = XCreateWindow(
|
||||||
|
mDisplay, RootWindow(mDisplay, visualInfo->screen),
|
||||||
|
windowPositionX, windowPositionY,
|
||||||
|
windowWidth, windowHeight,
|
||||||
|
0, visualInfo->depth, InputOutput,
|
||||||
|
visualInfo->visual,
|
||||||
|
CWColormap | CWEventMask, &swa); // NOLINT (hicpp-signed-bitwise)
|
||||||
|
|
||||||
|
if (!mWindow)
|
||||||
|
{
|
||||||
|
std::cerr << "Error: XCreateWindow()\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
XFree(visualInfo);
|
||||||
|
XStoreName(mDisplay, mWindow, windowTitle.c_str());
|
||||||
|
XMapWindow(mDisplay, mWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Create the context
|
||||||
|
{
|
||||||
|
typedef GLXContext (* glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
|
||||||
|
|
||||||
|
auto glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddress(
|
||||||
|
(const GLubyte*)"glXCreateContextAttribsARB");
|
||||||
|
|
||||||
|
if (!glXCreateContextAttribsARB)
|
||||||
|
{
|
||||||
|
std::cerr << "glXCreateContextAttribsARB() not found\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int contextAttributes[] =
|
||||||
|
{
|
||||||
|
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||||
|
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
mGlxContext = glXCreateContextAttribsARB(
|
||||||
|
mDisplay, frameBufferConfig, nullptr,
|
||||||
|
True, contextAttributes);
|
||||||
|
|
||||||
|
if (!mGlxContext)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to create an OpenGL context\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate KeyRelease event only when physical key is actually released
|
||||||
|
{
|
||||||
|
bool detectableSet = XkbSetDetectableAutoRepeat(mDisplay, true, nullptr);
|
||||||
|
|
||||||
|
if (!detectableSet)
|
||||||
|
{
|
||||||
|
std::cerr << "Detectable auto repeat not set - holding a key down will cause event spamming and delays.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glXMakeCurrent(mDisplay, mWindow, mGlxContext);
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
glXSwapBuffers(mDisplay, mWindow);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WindowManager::Update()
|
||||||
|
{
|
||||||
|
glXSwapBuffers(mDisplay, mWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WindowManager::Shutdown()
|
||||||
|
{
|
||||||
|
glXMakeCurrent(mDisplay, 0, nullptr);
|
||||||
|
glXDestroyContext(mDisplay, mGlxContext);
|
||||||
|
XDestroyWindow(mDisplay, mWindow);
|
||||||
|
XCloseDisplay(mDisplay);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowManager::ProcessEvents()
|
||||||
|
{
|
||||||
|
XEvent xEvent;
|
||||||
|
|
||||||
|
if (XCheckWindowEvent(mDisplay, mWindow, ExposureMask | KeyPressMask | KeyReleaseMask, &xEvent)) // NOLINT (hicpp-signed-bitwise)
|
||||||
|
{
|
||||||
|
if (xEvent.type == Expose)
|
||||||
|
{
|
||||||
|
XWindowAttributes gwa;
|
||||||
|
XGetWindowAttributes(mDisplay, mWindow, &gwa);
|
||||||
|
glViewport(0, 0, gwa.width, gwa.height);
|
||||||
|
|
||||||
|
Event event(Events::Window::RESIZED);
|
||||||
|
event.SetParam<unsigned int>(Events::Window::Resized::WIDTH, gwa.width);
|
||||||
|
event.SetParam<unsigned int>(Events::Window::Resized::HEIGHT, gwa.height);
|
||||||
|
|
||||||
|
gCoordinator.SendEvent(event);
|
||||||
|
}
|
||||||
|
else if (xEvent.type == KeyPress)
|
||||||
|
{
|
||||||
|
KeySym key = XkbKeycodeToKeysym(
|
||||||
|
mDisplay,
|
||||||
|
static_cast<KeyCode>(xEvent.xkey.keycode),
|
||||||
|
0, 0);
|
||||||
|
|
||||||
|
bool buttonStateChanged = true;
|
||||||
|
|
||||||
|
if (key == XK_Escape)
|
||||||
|
{
|
||||||
|
gCoordinator.SendEvent(Events::Window::QUIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (key == XK_w)
|
||||||
|
{
|
||||||
|
mButtons.set(static_cast<std::size_t>(InputButtons::W));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (key == XK_a)
|
||||||
|
{
|
||||||
|
mButtons.set(static_cast<std::size_t>(InputButtons::A));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (key == XK_s)
|
||||||
|
{
|
||||||
|
mButtons.set(static_cast<std::size_t>(InputButtons::S));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (key == XK_d)
|
||||||
|
{
|
||||||
|
mButtons.set(static_cast<std::size_t>(InputButtons::D));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (key == XK_q)
|
||||||
|
{
|
||||||
|
mButtons.set(static_cast<std::size_t>(InputButtons::Q));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (key == XK_e)
|
||||||
|
{
|
||||||
|
mButtons.set(static_cast<std::size_t>(InputButtons::E));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buttonStateChanged = false;
|
||||||
|
XFlush(mDisplay);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buttonStateChanged)
|
||||||
|
{
|
||||||
|
Event event(Events::Window::INPUT);
|
||||||
|
event.SetParam(Events::Window::Input::INPUT, mButtons);
|
||||||
|
gCoordinator.SendEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (xEvent.type == KeyRelease)
|
||||||
|
{
|
||||||
|
KeySym key = XkbKeycodeToKeysym(
|
||||||
|
mDisplay,
|
||||||
|
static_cast<KeyCode>(xEvent.xkey.keycode),
|
||||||
|
0, 0);
|
||||||
|
|
||||||
|
bool buttonStateChanged = true;
|
||||||
|
|
||||||
|
if (key == XK_Escape)
|
||||||
|
{
|
||||||
|
gCoordinator.SendEvent(Events::Window::QUIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (key == XK_w)
|
||||||
|
{
|
||||||
|
mButtons.reset(static_cast<std::size_t>(InputButtons::W));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (key == XK_a)
|
||||||
|
{
|
||||||
|
mButtons.reset(static_cast<std::size_t>(InputButtons::A));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (key == XK_s)
|
||||||
|
{
|
||||||
|
mButtons.reset(static_cast<std::size_t>(InputButtons::S));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (key == XK_d)
|
||||||
|
{
|
||||||
|
mButtons.reset(static_cast<std::size_t>(InputButtons::D));
|
||||||
|
}
|
||||||
|
else if (key == XK_q)
|
||||||
|
{
|
||||||
|
mButtons.reset(static_cast<std::size_t>(InputButtons::Q));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (key == XK_e)
|
||||||
|
{
|
||||||
|
mButtons.reset(static_cast<std::size_t>(InputButtons::E));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buttonStateChanged = false;
|
||||||
|
XFlush(mDisplay);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buttonStateChanged)
|
||||||
|
{
|
||||||
|
Event event(Events::Window::INPUT);
|
||||||
|
event.SetParam(Events::Window::Input::INPUT, mButtons);
|
||||||
|
gCoordinator.SendEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XFlush(mDisplay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <bitset>
|
||||||
|
#include <GL/glx.h>
|
||||||
|
#include <string>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
class WindowManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Init(
|
||||||
|
std::string const& windowTitle, unsigned int windowWidth, unsigned int windowHeight,
|
||||||
|
unsigned int windowPositionX, unsigned int windowPositionY);
|
||||||
|
|
||||||
|
void Update();
|
||||||
|
|
||||||
|
void ProcessEvents();
|
||||||
|
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Display* mDisplay;
|
||||||
|
Window mWindow;
|
||||||
|
GLXContext mGlxContext;
|
||||||
|
|
||||||
|
std::bitset<8> mButtons;
|
||||||
|
};
|
Loading…
Reference in New Issue