Compare commits

..

5 Commits

288 changed files with 4203 additions and 11524 deletions
+1 -2
View File
@@ -11,8 +11,7 @@ Libraries bundled along with binaries for Windows (MSVC14), available as a submo
| **[libpng](http://www.libpng.org/pub/png/libpng.html)** | 1.6.19 | [libpng License](http://www.libpng.org/pub/png/src/libpng-LICENSE.txt) | | **[libpng](http://www.libpng.org/pub/png/libpng.html)** | 1.6.19 | [libpng License](http://www.libpng.org/pub/png/src/libpng-LICENSE.txt) |
| **[Xerces-C++](https://xerces.apache.org/xerces-c)** | 3.1.2 | [Apache License Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | **[Xerces-C++](https://xerces.apache.org/xerces-c)** | 3.1.2 | [Apache License Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) |
| **[ImGui](https://github.com/ocornut/imgui)** | 2015-12-12 | [MIT License](https://github.com/ocornut/imgui/blob/de3a154f3801de22c8e0bd2aeabf663a70c05972/LICENSE) | | **[ImGui](https://github.com/ocornut/imgui)** | 2015-12-12 | [MIT License](https://github.com/ocornut/imgui/blob/de3a154f3801de22c8e0bd2aeabf663a70c05972/LICENSE) |
| **[nativefiledialog](https://github.com/mlabbe/nativefiledialog)** | 2016-01-08 | [nativefiledialog Licence](https://github.com/mlabbe/nativefiledialog/blob/master/LICENSE) | | **[nativefiledialog](https://github.com/mlabbe/nativefiledialog) | 2016-01-08 | https://github.com/mlabbe/nativefiledialog/blob/master/LICENSE |
| **[OpenAL](https://www.openal.org/)** | 1.1 | [OpenAL License](resources/Licenses/OpenAL.txt)
#### External libraries #### External libraries
Libraries that are too big to be bundled with the project. Libraries that are too big to be bundled with the project.
+1 -1
Submodule assets updated: e8174f630f...c8e631f449
@@ -1,24 +0,0 @@
#ifndef CollidableOctreeSystem_h__
#define CollidableOctreeSystem_h__
#include "../Core/System.h"
#include "../Core/Octree.h"
#include "Collision.h"
class CollidableOctreeSystem : public ImpureSystem, public PureSystem
{
public:
CollidableOctreeSystem(World* world, EventBroker* eventBroker, Octree<AABB>* octree)
: System(world, eventBroker)
, PureSystem("Collidable")
, m_Octree(octree)
{ }
virtual void Update(double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
private:
Octree<AABB>* m_Octree;
};
#endif
+7 -15
View File
@@ -6,14 +6,11 @@
//or you will get "fatal error C1189: #error: gl.h included before glew.h" //or you will get "fatal error C1189: #error: gl.h included before glew.h"
#include <vector> #include <vector>
#include <boost/optional.hpp>
#include "../Core/Ray.h" #include "Core/Ray.h"
#include "../Core/AABB.h" #include "Core/AABB.h"
#include "../Rendering/RawModel.h" #include "Engine/Rendering/RawModel.h"
#include "../Core/Transform.h" #include "Core/Entity.h"
#include "../Core/Entity.h"
#include "../Core/EntityWrapper.h"
class World; class World;
struct ComponentWrapper; struct ComponentWrapper;
@@ -46,12 +43,6 @@ bool RayVsModel(const Ray& ray,
float& outUCoord, float& outUCoord,
float& outVCoord); float& outVCoord);
bool AABBvsTriangles(const AABB& box,
const std::vector<RawModel::Vertex>& modelVertices,
const std::vector<unsigned int>& modelIndices,
const glm::mat4& modelMatrix,
glm::vec3& outResolutionVector);
//Return true if the boxes are intersecting. //Return true if the boxes are intersecting.
bool AABBVsAABB(const AABB& a, const AABB& b); bool AABBVsAABB(const AABB& a, const AABB& b);
//Return true if the boxes are intersecting. //Return true if the boxes are intersecting.
@@ -59,8 +50,9 @@ bool AABBVsAABB(const AABB& a, const AABB& b);
bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation); bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation);
bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon = 0.0001f); bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon = 0.0001f);
// Calculates an absolute AABB from an entity AABB component //Returns true if the entity has a boundingbox. Outputs the aabb in [outBox].
boost::optional<AABB> EntityAbsoluteAABB(EntityWrapper& entity); bool GetEntityBox(World* world, EntityID entity, AABB& outBox, bool forceBoxFromModel = false);
bool GetEntityBox(World* world, ComponentWrapper& AABBComponent, AABB& outBox);
} }
+7 -12
View File
@@ -4,31 +4,26 @@
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <glm/common.hpp> #include <glm/common.hpp>
#include "../Common.h" #include "Common.h"
#include "../Core/System.h" #include "Core/System.h"
#include "../Core/EventBroker.h" #include "Core/EventBroker.h"
#include "../Core/EKeyUp.h" #include "Core/EKeyUp.h"
#include "../Core/Octree.h"
class CollisionSystem : public PureSystem class CollisionSystem : public PureSystem
{ {
public: public:
CollisionSystem(World* world, EventBroker* eventBroker, Octree<AABB>* octree) CollisionSystem(EventBroker* eventBroker)
: System(world, eventBroker) : PureSystem(eventBroker, "AABB")
, PureSystem("Collidable")
, m_Octree(octree)
, zPress(false) , zPress(false)
{ {
//TODO: Debug stuff, remove later. //TODO: Debug stuff, remove later.
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &CollisionSystem::OnKeyUp); EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &CollisionSystem::OnKeyUp);
} }
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; virtual void UpdateComponent(World* world, ComponentWrapper& cAABB, double dt) override;
private: private:
Octree<AABB>* m_Octree;
bool zPress; bool zPress;
EventRelay<CollisionSystem, Events::KeyUp> m_EKeyUp; EventRelay<CollisionSystem, Events::KeyUp> m_EKeyUp;
bool OnKeyUp(const Events::KeyUp &event); bool OnKeyUp(const Events::KeyUp &event);
}; };
+6 -22
View File
@@ -4,9 +4,8 @@
#include <glm/common.hpp> #include <glm/common.hpp>
#include <unordered_set> #include <unordered_set>
#include "../Core/System.h" #include "Core/System.h"
#include "../Core/EventBroker.h" #include "Core/EventBroker.h"
#include "../Core/Octree.h"
#include "ETrigger.h" #include "ETrigger.h"
class AABB; class AABB;
@@ -14,31 +13,16 @@ class AABB;
class TriggerSystem : public PureSystem class TriggerSystem : public PureSystem
{ {
public: public:
TriggerSystem(World* world, EventBroker* eventBroker, Octree<AABB>* octree) TriggerSystem(EventBroker* eventBroker)
: System(world, eventBroker) : PureSystem(eventBroker, "Trigger")
, PureSystem("Trigger") {}
, m_Octree(octree)
{
EVENT_SUBSCRIBE_MEMBER(m_ETouch, &TriggerSystem::OnTouch);
EVENT_SUBSCRIBE_MEMBER(m_EEnter, &TriggerSystem::OnEnter);
EVENT_SUBSCRIBE_MEMBER(m_ELeave, &TriggerSystem::OnLeave);
}
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; virtual void UpdateComponent(World* world, ComponentWrapper& collision, double dt) override;
private: private:
Octree<AABB>* m_Octree;
std::unordered_map<EntityID, std::unordered_set<EntityID>> m_EntitiesTouchingTrigger; std::unordered_map<EntityID, std::unordered_set<EntityID>> m_EntitiesTouchingTrigger;
std::unordered_map<EntityID, std::unordered_set<EntityID>> m_EntitiesCompletelyInTrigger; std::unordered_map<EntityID, std::unordered_set<EntityID>> m_EntitiesCompletelyInTrigger;
//TODO: Only exists for debug purposes, remove later.
EventRelay<TriggerSystem, Events::TriggerEnter> m_EEnter;
bool OnEnter(const Events::TriggerEnter &event);
EventRelay<TriggerSystem, Events::TriggerTouch> m_ETouch;
bool OnTouch(const Events::TriggerTouch &event);
EventRelay<TriggerSystem, Events::TriggerLeave> m_ELeave;
bool OnLeave(const Events::TriggerLeave &event);
//True if leave event was thrown. //True if leave event was thrown.
bool throwLeaveIfWasInTrigger(std::unordered_set<EntityID>& triggerSet, EntityID pId, EntityID tId); bool throwLeaveIfWasInTrigger(std::unordered_set<EntityID>& triggerSet, EntityID pId, EntityID tId);
template<typename Event> template<typename Event>
-2
View File
@@ -1,10 +1,8 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <sstream>
#include <vector> #include <vector>
#include <map> #include <map>
#include <unordered_map> #include <unordered_map>
#include <algorithm>
#include "Core/Util/Logging.h" #include "Core/Util/Logging.h"
#include "Core/Util/IfDebug.h" #include "Core/Util/IfDebug.h"
+3 -3
View File
@@ -11,18 +11,18 @@ public:
AABB(const glm::vec3& minPos, const glm::vec3& maxPos); AABB(const glm::vec3& minPos, const glm::vec3& maxPos);
AABB(const glm::vec4& minPos, const glm::vec4& maxPos); AABB(const glm::vec4& minPos, const glm::vec4& maxPos);
//No checks are made. Size must consist of non-negative numbers. //No checks are made. Size must consist of non-negative numbers.
static AABB FromOriginSize(const glm::vec3& origin, const glm::vec3& size); virtual void CreateFromCenter(const glm::vec3& center, const glm::vec3& size);
virtual ~AABB(); virtual ~AABB();
const glm::vec3& MinCorner() const { return m_MinCorner; } const glm::vec3& MinCorner() const { return m_MinCorner; }
const glm::vec3& MaxCorner() const { return m_MaxCorner; } const glm::vec3& MaxCorner() const { return m_MaxCorner; }
const glm::vec3& Origin() const { return m_Origin; } const glm::vec3& Center() const { return m_Center; }
const glm::vec3 Size() const { return 2.0f * m_HalfSize; } const glm::vec3 Size() const { return 2.0f * m_HalfSize; }
const glm::vec3& HalfSize() const { return m_HalfSize; } const glm::vec3& HalfSize() const { return m_HalfSize; }
private: private:
glm::vec3 m_MinCorner; glm::vec3 m_MinCorner;
glm::vec3 m_MaxCorner; glm::vec3 m_MaxCorner;
glm::vec3 m_Origin; glm::vec3 m_Center;
glm::vec3 m_HalfSize; glm::vec3 m_HalfSize;
}; };
+3 -8
View File
@@ -5,19 +5,15 @@
struct ComponentInfo struct ComponentInfo
{ {
typedef int EnumType;
struct Meta_t struct Meta_t
{ {
std::string Annotation; std::string Annotation;
unsigned int Allocation = 0; unsigned int Allocation = 0;
std::map<std::string, std::string> FieldAnnotations; unsigned int Stride = 0;
std::map<std::string, std::map<std::string, EnumType>> FieldEnumDefinitions;
}; };
struct Field_t struct Field_t
{ {
std::string Name;
std::string Type; std::string Type;
unsigned int Offset; unsigned int Offset;
unsigned int Stride; unsigned int Stride;
@@ -25,10 +21,9 @@ struct ComponentInfo
std::string Name; std::string Name;
std::unordered_map<std::string, Field_t> Fields; std::unordered_map<std::string, Field_t> Fields;
std::vector<std::string> FieldsInOrder; std::vector<const Field_t*> FieldsInOrder;
unsigned int Stride = 0; Meta_t Meta;
std::shared_ptr<char> Defaults = nullptr; std::shared_ptr<char> Defaults = nullptr;
std::shared_ptr<Meta_t> Meta = nullptr;
}; };
template<> template<>
+1 -2
View File
@@ -43,7 +43,7 @@ public:
ComponentPool(const ::ComponentInfo& ci) ComponentPool(const ::ComponentInfo& ci)
: m_ComponentInfo(ci) : m_ComponentInfo(ci)
, m_Pool(ci.Meta->Allocation, sizeof(EntityID) + ci.Stride) , m_Pool(ci.Meta.Allocation, sizeof(EntityID) + ci.Meta.Stride)
{ } { }
ComponentPool(const ComponentPool& other) = delete; ComponentPool(const ComponentPool& other) = delete;
ComponentPool(const ComponentPool&& other) = delete; ComponentPool(const ComponentPool&& other) = delete;
@@ -61,7 +61,6 @@ public:
iterator begin() const; iterator begin() const;
iterator end() const; iterator end() const;
size_t size() const;
//Dumps information about what the pool memory looks like right now //Dumps information about what the pool memory looks like right now
//into an output stream (e.g. file/std::cout, anything that has an operator<<) //into an output stream (e.g. file/std::cout, anything that has an operator<<)
+19 -32
View File
@@ -18,32 +18,22 @@ struct ComponentWrapper
const ::EntityID EntityID; const ::EntityID EntityID;
char* Data; char* Data;
ComponentInfo::EnumType Enum(const char* fieldName, const char* enumKey) template <typename T>
T& Property(std::string name)
{ {
return Info.Meta->FieldEnumDefinitions.at(fieldName).at(enumKey); unsigned int offset = Info.Fields.at(name).Offset;
return *reinterpret_cast<T*>(&Data[offset]);
} }
template <typename T> template <typename T>
T& Field(std::string name) void SetProperty(std::string name, const T value) { Property<T>(name) = value; }
{
const ComponentInfo::Field_t& field = Info.Fields.at(name);
if (sizeof(T) > field.Stride) {
std::stringstream message;
message << "Type size of \"" << typeid(T).name() << "\" doesn't match size of component field \"" << Info.Name << "." << name << "\"!";
throw new std::runtime_error(message.str().c_str());
}
return *reinterpret_cast<T*>(&Data[field.Offset]);
}
template <typename T>
void SetField(std::string name, const T value) { Field<T>(name) = value; }
//template <typename T> //template <typename T>
//void SetField(std::string name, T& value) { Field<T>(name) = value; } //void SetProperty(std::string name, T& value) { Property<T>(name) = value; }
// Specialization for string literals // Specialization for string literals
template <std::size_t N> template <std::size_t N>
void SetField(std::string name, const char(&value)[N]) { Field<std::string>(name) = std::string(value); } void SetProperty(std::string name, const char(&value)[N]) { Property<std::string>(name) = std::string(value); }
struct SubscriptProxy struct SubscriptProxy
{ {
friend struct ComponentWrapper; friend struct ComponentWrapper;
@@ -57,21 +47,18 @@ struct ComponentWrapper
std::string m_PropertyName; std::string m_PropertyName;
public: public:
// Return the integer value of an enum type key for this field template <typename T>
ComponentInfo::EnumType Enum(const char* enumKey) { return m_Component->Enum(m_PropertyName.c_str(), enumKey); } operator T&() { return m_Component->Property<T>(m_PropertyName); }
template <typename T> template <typename T>
operator T&() { return m_Component->Field<T>(m_PropertyName); } void operator=(const T val) { m_Component->SetProperty<T>(m_PropertyName, val); }
template <typename T>
void operator=(const T val) { m_Component->SetField<T>(m_PropertyName, val); }
// TODO: Pass by reference and rvalue (universal reference?) // TODO: Pass by reference and rvalue (universal reference?)
//template <typename T> //template <typename T>
//void operator=(T& val) { m_Component->SetField<T>(m_PropertyName, val); } //void operator=(T& val) { m_Component->SetProperty<T>(m_PropertyName, val); }
// Specialization for string literals // Specialization for string literals
template <std::size_t N> template<std::size_t N>
void operator=(const char(&val)[N]) { m_Component->SetField<N>(m_PropertyName, val); } void operator=(const char(&val)[N]) { m_Component->SetProperty<N>(m_PropertyName, val); }
}; };
SubscriptProxy operator[](std::string propertyName) { return SubscriptProxy(this, propertyName); } SubscriptProxy operator[](std::string propertyName) { return SubscriptProxy(this, propertyName); }
}; };
@@ -84,22 +71,22 @@ public:
ComponentWrapperFactory(std::string componentTypeName, std::size_t allocation = 0) ComponentWrapperFactory(std::string componentTypeName, std::size_t allocation = 0)
{ {
m_ComponentInfo.Name = componentTypeName; m_ComponentInfo.Name = componentTypeName;
m_ComponentInfo.Meta->Allocation = allocation; m_ComponentInfo.Meta.Allocation = allocation;
} }
template <typename T> template <typename T>
void AddProperty(std::string fieldName, T defaultValue) void AddProperty(std::string fieldName, T defaultValue)
{ {
m_DefaultValues.push_back(defaultValue); m_DefaultValues.push_back(defaultValue);
m_ComponentInfo.Fields[fieldName].Type = typeid(T).name(); m_ComponentInfo.Fields[fieldName].Name = typeid(T).name();
m_ComponentInfo.Fields[fieldName].Offset = m_ComponentInfo.Stride; m_ComponentInfo.Fields[fieldName].Offset = m_ComponentInfo.Meta.Stride;
m_ComponentInfo.Fields[fieldName].Stride = sizeof(T); m_ComponentInfo.Fields[fieldName].Stride = sizeof(T);
m_ComponentInfo.Stride += sizeof(T); m_ComponentInfo.Meta.Stride += sizeof(T);
} }
ComponentInfo& Finalize() ComponentInfo& Finalize()
{ {
m_ComponentInfo.Defaults = std::shared_ptr<char>(new char[m_ComponentInfo.Stride]); m_ComponentInfo.Defaults = std::shared_ptr<char>(new char[m_ComponentInfo.Meta.Stride]);
std::size_t offset = 0; std::size_t offset = 0;
for (auto& val : m_DefaultValues) { for (auto& val : m_DefaultValues) {
memcpy(m_ComponentInfo.Defaults.get() + offset, val.Data.get(), val.Size); memcpy(m_ComponentInfo.Defaults.get() + offset, val.Data.get(), val.Size);
+31 -25
View File
@@ -3,10 +3,10 @@
#include <string> #include <string>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/range/adaptors.hpp>
#include <ini_file/ini_file.hpp>
#include "../Common.h" #include "../Common.h"
#include "ResourceManager.h" #include "ResourceManager.h"
@@ -20,46 +20,52 @@ private:
public: public:
template <typename T> template <typename T>
T Get(std::string key, T defaultValue); T Get(std::string key, T defaultValue);
template <typename T>
std::vector<std::pair<std::string, T>> GetAll(std::string key);
template <typename T> template <typename T>
void Set(std::string key, T value); void Set(std::string key, T value);
const ini_file::section* GetSection(std::string section);
const ini_file::section_map& GetSections() { return m_Merged; }
const ini_file::param* GetParam(std::string key);
void SaveToDisk(); void SaveToDisk();
private: private:
boost::filesystem::path m_Path; boost::filesystem::path m_Path;
boost::property_tree::ptree m_PTreeDefaults; ini_file::section_map m_Defaults;
boost::property_tree::ptree m_PTreeOverrides; ini_file::section_map m_Overrides;
boost::property_tree::ptree m_PTreeMerged; ini_file::section_map m_Merged;
// Merge ini file section map b into a
void mergeINI(ini_file::section_map& a, const ini_file::section_map& b);
// Convert an ini key delimited by periods to a section and a param
boost::optional<std::pair<std::string, std::string>> tokenizeKey(std::string key);
}; };
template <typename T> template <typename T>
T ConfigFile::Get(std::string key, T defaultValue) T ConfigFile::Get(std::string key, T defaultValue)
{ {
return m_PTreeMerged.get<T>(key, defaultValue); auto param = GetParam(key);
} if (param == nullptr) {
return defaultValue;
}
template <typename T> return boost::lexical_cast<T>(param->get_value());
std::vector<std::pair<std::string, T>> ConfigFile::GetAll(std::string key)
{
std::vector<std::pair<std::string, T>> out;
auto parent = m_PTreeMerged.find(key);
if (parent == m_PTreeMerged.not_found()) {
return out;
}
for (auto& child : parent->second) {
T value = boost::lexical_cast<T>(child.second.data());
out.push_back(std::make_pair(child.first, value));
}
return out;
} }
template <typename T> template <typename T>
void ConfigFile::Set(std::string key, T value) void ConfigFile::Set(std::string key, T value)
{ {
m_PTreeOverrides.put<T>(key, value); std::string section;
m_PTreeMerged.put<T>(key, value); std::string param;
if (auto tokens = tokenizeKey(key)) {
std::tie(section, param) = *tokens;
} else {
LOG_WARNING("%s: Malformed config key \"%s\"", m_Path.string().c_str(), key.c_str());
return;
}
m_Overrides[section][param] = boost::lexical_cast<std::string>(value);
m_Merged[section][param] = boost::lexical_cast<std::string>(value);
} }
#endif #endif
+157
View File
@@ -0,0 +1,157 @@
#ifndef DeveloperConsole_h__
#define DeveloperConsole_h__
#include <iostream>
#include <boost/lexical_cast.hpp>
#include <boost/tokenizer.hpp>
#include "../Common.h"
#include "ConfigFile.h"
class DeveloperConsole
{
public:
DeveloperConsole() = delete;
static void MergeConfig(std::string configFile)
{
auto config = ResourceManager::Load<ConfigFile>("Config.ini");
LOG_DEBUG("Debug.LogLevel %i", config->Get<int>("Debug.LogLevel", -1));
config->Set("Debug.LogLevel", 8);
LOG_DEBUG("Debug.LogLevel %i", config->Get<int>("Debug.LogLevel", -1));
config->Set("Test.TesTest.Testies", "Hello");
config->SaveToDisk();
for (auto& section : config->GetSections()) {
for (auto& param : *section.second) {
std::cout << "// " << param.second->get_comment() << std::endl;
std::cout << section.first << "." << param.first << " " << param.second->get_value() << std::endl;
}
}
for (auto& section : config->GetSections()) {
for (auto& param : *section.second) {
std::string key = section.first + "." + param.first;
m_VariableBindingSetters[key] = [config, key](std::string value) {
config->Set<std::string>(key, value);
};
m_VariableBindingGetters[key] = [config, key]() {
return config->Get<std::string>(key, "");
};
}
}
}
template <typename T>
static typename std::enable_if<std::is_enum<T>::value, void>::type
BindVariable(std::string path, T& variable)
{
BindVariable<T, std::underlying_type<T>::type>(path, variable);
}
template <typename T, typename R = T>
static typename std::enable_if<!std::is_enum<R>::value, void>::type
BindVariable(std::string path, T& variable)
{
m_VariableBindingSetters[path] = [&variable](std::string value) {
variable = static_cast<T>(boost::lexical_cast<R>(value));
};
m_VariableBindingGetters[path] = [&variable]() {
return boost::lexical_cast<std::string>(static_cast<R>(variable));
};
}
static void Consume(const std::string& command)
{
if (command.empty()) {
return;
}
boost::char_separator<char> argumentSeparator(" ");
tokenizer tokens(command, argumentSeparator);
for (tokenizer::const_iterator it = tokens.begin(); it != tokens.end(); it++) {
consumeToken(it, tokens.end());
}
}
static void Consume(std::istream& stream)
{
std::string input;
std::getline(stream, input);
Consume(input);
/*if (stream.peek() == '\n') {
printValue(key);
} else {
std::string newValue;
stream >> newValue;
if (m_VariableBindingSetters.find(key) != m_VariableBindingSetters.end()) {
m_VariableBindingSetters.at(key)(newValue);
} else {
std::cout << "Unknown path: " << key << std::endl;
}
return;
for (auto& config : m_ConfigFiles) {
config->Set(key, newValue);
config->SaveToDisk();
LOG_DEBUG("Key %s set to new value %s and saved to disk.", key.c_str(), newValue.c_str());
}
} */
}
private:
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
static std::map<std::string, std::function<std::string()>> m_VariableBindingGetters;
static std::map<std::string, std::function<void(std::string)>> m_VariableBindingSetters;
static std::map<std::string, std::function<std::string(std::string)>> m_VariableBindingMappers;
static std::map<std::string, std::string> m_VariableDocumentation;
static void consumeToken(tokenizer::iterator& token, const tokenizer::iterator end)
{
tokenizer::iterator next = token;
next++;
if (next == end) {
printValue(token);
} else {
setValue(token, end);
}
}
static void printValue(tokenizer::iterator token)
{
std::string key = *token;
std::string value;
if (m_VariableBindingGetters.find(key) != m_VariableBindingGetters.end()) {
std::cout << key << " = " << m_VariableBindingGetters.at(key)() << std::endl;
} else {
std::cout << "Unknown path: " << key << std::endl;
}
return;
if (!value.empty()) {
std::cout << key << " = " << value << std::endl;
} else {
std::cerr << "Unknown path: " << key << std::endl;
}
}
static void setValue(tokenizer::iterator& token, const tokenizer::iterator end)
{
std::string key = *token;
std::string value = *(++token);
if (m_VariableBindingSetters.find(key) != m_VariableBindingSetters.end()) {
m_VariableBindingSetters.at(key)(value);
} else {
std::cout << "Unknown path: " << key << std::endl;
}
}
};
#endif
-20
View File
@@ -1,20 +0,0 @@
#ifndef ECaptured_h__
#define ECaptured_h__
#include "EventBroker.h"
#include "../Core/Entity.h"
#include "Engine/GLM.h"
namespace Events
{
//triggers when a capturePoint has been taken over
struct Captured : Event
{
int TeamNumberThatCapturedCapturePoint;
EntityID CapturePointID;
};
}
#endif
-20
View File
@@ -1,20 +0,0 @@
#ifndef EComponentAttached_h__
#define EComponentAttached_h__
#include "EventBroker.h"
#include "World.h"
#include "Entity.h"
#include "ComponentWrapper.h"
namespace Events
{
struct ComponentAttached : Event
{
EntityWrapper Entity;
ComponentWrapper Component;
};
}
#endif
-3
View File
@@ -11,9 +11,6 @@ struct KeyDown : Event
{ {
/** GLFW key code */ /** GLFW key code */
int KeyCode; int KeyCode;
bool ModCtrl;
bool ModAlt;
bool ModShift;
}; };
} }
-3
View File
@@ -11,9 +11,6 @@ struct KeyUp : Event
{ {
/** GLFW key code */ /** GLFW key code */
int KeyCode; int KeyCode;
bool ModCtrl;
bool ModAlt;
bool ModShift;
}; };
} }
-22
View File
@@ -1,22 +0,0 @@
#ifndef EPause_h__
#define EPause_h__
#include "EventBroker.h"
#include "World.h"
namespace Events
{
struct Pause : Event
{
::World* World;
};
struct Resume : Event
{
::World* World;
};
}
#endif
+2
View File
@@ -11,6 +11,8 @@ struct PlayerDamage : Event
{ {
double DamageAmount; double DamageAmount;
EntityID PlayerDamagedID; EntityID PlayerDamagedID;
//optional TypeOfDamage
std::string TypeOfDamage;
}; };
} }
-19
View File
@@ -1,19 +0,0 @@
#ifndef EShoot_h__
#define EShoot_h__
#include "EventBroker.h"
#include "../Core/Entity.h"
#include "Engine/GLM.h"
namespace Events
{
struct Shoot : Event
{
//ID for who made the shot
EntityID shooter;
};
}
#endif
-20
View File
@@ -1,20 +0,0 @@
#ifndef EWin_h__
#define EWin_h__
#include "EventBroker.h"
#include "../Core/Entity.h"
#include "Engine/GLM.h"
namespace Events
{
//triggers when a team has captured all capturePoints
struct Win : Event
{
//can be 0 = none, 1,2
int TeamThatWon;
};
}
#endif
-1
View File
@@ -4,5 +4,4 @@
typedef unsigned int EntityID; typedef unsigned int EntityID;
const static unsigned int EntityID_Invalid = -1; const static unsigned int EntityID_Invalid = -1;
#endif #endif
+8 -8
View File
@@ -285,7 +285,7 @@ private:
XSValue::Status status; XSValue::Status status;
XSValue* val = XSValue::getActualValue(child->getNodeValue(), XSValue::dt_integer, status); XSValue* val = XSValue::getActualValue(child->getNodeValue(), XSValue::dt_integer, status);
compInfo.Meta->Allocation += val->fData.fValue.f_int; compInfo.Meta.Allocation += val->fData.fValue.f_int;
} }
// Save documentation string // Save documentation string
@@ -293,11 +293,11 @@ private:
if (documentationTags->getLength() != 0) { if (documentationTags->getLength() != 0) {
auto child = documentationTags->item(0)->getFirstChild(); auto child = documentationTags->item(0)->getFirstChild();
if (child != nullptr) { if (child != nullptr) {
compInfo.Meta->Annotation = XSTR(child->getNodeValue()); compInfo.Meta.Annotation = XSTR(child->getNodeValue());
} }
} }
// TODO: Parse annotation string XML // TODO: Parse annotation string XML
// compInfo.Meta->Allocation = ... // compInfo.Meta.Allocation = ...
} else { } else {
std::cout << "Warning: Component is missing an annotation!" << std::endl; std::cout << "Warning: Component is missing an annotation!" << std::endl;
} }
@@ -344,7 +344,7 @@ private:
fieldOffset += getTypeStride(type); fieldOffset += getTypeStride(type);
} }
compInfo.Stride = fieldOffset; compInfo.Meta.Stride = fieldOffset;
m_ComponentInfo[compInfo.Name] = compInfo; m_ComponentInfo[compInfo.Name] = compInfo;
} }
} }
@@ -367,14 +367,14 @@ private:
std::string componentName = XSTR(component->getLocalName()); std::string componentName = XSTR(component->getLocalName());
auto& compInfo = m_ComponentInfo.at(componentName); auto& compInfo = m_ComponentInfo.at(componentName);
compInfo.Meta->Allocation += 1; compInfo.Meta.Allocation += 1;
} }
std::cout << "COMPONENT INFO" << std::endl; std::cout << "COMPONENT INFO" << std::endl;
for (auto& pair : m_ComponentInfo) { for (auto& pair : m_ComponentInfo) {
ComponentInfo& ci = pair.second; ComponentInfo& ci = pair.second;
std::cout << "Component: " << ci.Name << " (" << ci.Meta->Annotation << ")" << std::endl; std::cout << "Component: " << ci.Name << " (" << ci.Meta.Annotation << ")" << std::endl;
std::cout << " Allocation: " << ci.Meta->Allocation << std::endl; std::cout << " Allocation: " << ci.Meta.Allocation << std::endl;
std::cout << " Fields:" << std::endl; std::cout << " Fields:" << std::endl;
// Calculate component size // Calculate component size
@@ -393,7 +393,7 @@ private:
cs.ComponentName = ci.Name; cs.ComponentName = ci.Name;
cs.Stride = stride; cs.Stride = stride;
cs.Info = ci; cs.Info = ci;
cs.Data = new char[stride*ci.Meta->Allocation]; cs.Data = new char[stride*ci.Meta.Allocation];
m_ComponentStore[cs.ComponentName] = cs; m_ComponentStore[cs.ComponentName] = cs;
} }
} }
+147 -18
View File
@@ -73,15 +73,88 @@ public:
ComponentField ComponentField
}; };
EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader); EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader)
: m_Handler(handler)
, m_Reader(reader)
{
// 0 is imaginary world entity
m_EntityStack.push(0);
m_StateStack.push(State::Unknown);
}
void startElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname, const xercesc::Attributes& attrs) override; void startElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname, const xercesc::Attributes& attrs) override
void characters(const XMLCh* const chars, const XMLSize_t length) override; {
void endElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname) override; std::string name = XS::ToString(_localName);
void warning(const xercesc::SAXParseException& e); if (m_StateStack.top() == State::Unknown || m_StateStack.top() == State::Entity) {
void error(const xercesc::SAXParseException& e); if (name == "Entity") {
void fatalError(const xercesc::SAXParseException& e); m_StateStack.push(State::Entity);
onStartEntity(attrs);
return;
}
if (name == "EntityRef") {
onStartEntityRef(attrs);
return;
}
}
std::string uri = XS::ToString(_uri);
if (m_StateStack.top() == State::Entity) {
if (uri == "components") {
m_StateStack.push(State::Component);
onStartComponent(name);
return;
}
}
if (m_StateStack.top() == State::Component) {
m_StateStack.push(State::ComponentField);
onStartComponentField(name, attrs);
return;
}
}
void characters(const XMLCh* const chars, const XMLSize_t length) override
{
if (m_StateStack.top() == State::ComponentField) {
char* transcoded = xercesc::XMLString::transcode(chars);
onFieldData(transcoded);
}
}
void endElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname) override
{
std::string name = XS::ToString(_localName);
if (m_StateStack.top() == State::Entity) {
if (name == "Entity") {
m_StateStack.pop();
onEndEntity();
return;
}
}
std::string uri = XS::ToString(_uri);
if (m_StateStack.top() == State::Component) {
//if (uri == "components") {
m_StateStack.pop();
onEndComponent(name);
return;
//}
}
if (m_StateStack.top() == State::ComponentField) {
m_StateStack.pop();
onEndComponentField(name);
return;
}
}
void fatalError(const xercesc::SAXParseException& e)
{
XS::ToString s(e.getMessage());
LOG_ERROR("SAXParseException: %s", ((std::string)s).c_str());
//throw e;
}
private: private:
const EntityFileHandler* m_Handler; const EntityFileHandler* m_Handler;
@@ -95,14 +168,73 @@ private:
std::string m_CurrentField; std::string m_CurrentField;
std::map<std::string, std::string> m_CurrentAttributes; std::map<std::string, std::string> m_CurrentAttributes;
void onStartEntity(const xercesc::Attributes& attrs); void onStartEntity(const xercesc::Attributes& attrs)
void onEndEntity(); {
void onStartEntityRef(const xercesc::Attributes& attrs); EntityID parent = m_EntityStack.top();
void onStartComponent(const std::string& name);
void onEndComponent(const std::string& name); if (m_Handler->m_OnStartEntityCallback) {
void onStartComponentField(const std::string& field, const xercesc::Attributes& attrs); std::string name;
void onEndComponentField(const std::string& field); auto xName = attrs.getValue(XS::ToXMLCh("name"));
void onFieldData(char* data); if (xName != nullptr) {
name = XS::ToString(xName);
}
m_Handler->m_OnStartEntityCallback(m_NextEntityID, parent, name);
}
m_EntityStack.push(m_NextEntityID);
m_NextEntityID++;
}
void onEndEntity()
{
m_EntityStack.pop();
}
void onStartEntityRef(const xercesc::Attributes& attrs)
{
std::string path = XS::ToString(attrs.getValue(XS::ToXMLCh("file")));
xercesc::SAX2XMLReader* parser = xercesc::XMLReaderFactory::createXMLReader();
parser->setContentHandler(this);
parser->setErrorHandler(this);
parser->parse(path.c_str());
delete parser;
}
void onStartComponent(const std::string& name)
{
//LOG_DEBUG(" Component: %s", name.c_str());
m_CurrentComponent = name;
if (m_Handler->m_OnStartComponentCallback) {
m_Handler->m_OnStartComponentCallback(m_EntityStack.top(), name);
}
}
void onEndComponent(const std::string& name) { }
void onStartComponentField(const std::string& field, const xercesc::Attributes& attrs)
{
//LOG_DEBUG(" Field: %s", field.c_str());
m_CurrentField = field;
m_CurrentAttributes.clear();
for (int i = 0; i < attrs.getLength(); i++) {
auto name = attrs.getQName(i);
auto value = attrs.getValue(name);
//LOG_DEBUG(" %s = %s", (char*)XS::ToString(name), (char*)XS::ToString(value));
m_CurrentAttributes[XS::ToString(name).operator std::string()] = XS::ToString(value).operator std::string();
}
if (m_Handler->m_OnStartFieldCallback) {
m_Handler->m_OnStartFieldCallback(m_EntityStack.top(), m_CurrentComponent, field, m_CurrentAttributes);
}
}
void onEndComponentField(const std::string& field) { }
void onFieldData(char* data)
{
//LOG_DEBUG(" Data: %s", data);
if (m_Handler->m_OnStartFieldDataCallback) {
m_Handler->m_OnStartFieldDataCallback(m_EntityStack.top(), m_CurrentComponent, m_CurrentField, data);
}
xercesc::XMLString::release(&data);
}
}; };
class EntityFileXMLErrorHandler : public xercesc::ErrorHandler class EntityFileXMLErrorHandler : public xercesc::ErrorHandler
@@ -137,7 +269,6 @@ private:
class EntityFile : public Resource class EntityFile : public Resource
{ {
friend class ResourceManager; friend class ResourceManager;
friend class EntityFileSAXHandler;
private: private:
EntityFile(boost::filesystem::path path); EntityFile(boost::filesystem::path path);
~EntityFile(); ~EntityFile();
@@ -157,8 +288,6 @@ private:
xercesc::SAX2XMLReader* m_SAX2XMLReader; xercesc::SAX2XMLReader* m_SAX2XMLReader;
//std::map<std::string, ::ComponentInfo> m_ComponentInfo; //std::map<std::string, ::ComponentInfo> m_ComponentInfo;
//std::vector<std::string> m_EntityReferences; //std::vector<std::string> m_EntityReferences;
static void setReaderFeatures(xercesc::SAX2XMLReader* reader);
}; };
#endif #endif
+1 -2
View File
@@ -9,13 +9,12 @@ class EntityFileParser
public: public:
EntityFileParser(const EntityFile* entityFile); EntityFileParser(const EntityFile* entityFile);
EntityID MergeEntities(World* world, EntityID baseParent = EntityID_Invalid); void MergeEntities(World* world);
private: private:
const EntityFile* m_EntityFile; const EntityFile* m_EntityFile;
EntityFileHandler m_Handler; EntityFileHandler m_Handler;
World* m_World = nullptr; World* m_World = nullptr;
EntityID m_FirstEntity = EntityID_Invalid;
// Maps EntityIDs local to the file to real IDs in the world after they've been // Maps EntityIDs local to the file to real IDs in the world after they've been
// created in order to resolve parent-child relationships. // created in order to resolve parent-child relationships.
std::map<EntityID, EntityID> m_EntityIDMapper; std::map<EntityID, EntityID> m_EntityIDMapper;
@@ -5,7 +5,6 @@
#include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp> #include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp>
#include <xercesc/framework/psvi/XSParticle.hpp> #include <xercesc/framework/psvi/XSParticle.hpp>
#include <xercesc/framework/psvi/XSModelGroup.hpp> #include <xercesc/framework/psvi/XSModelGroup.hpp>
#include <xercesc/framework/psvi/XSModelGroupDefinition.hpp>
#include <xercesc/framework/psvi/XSAnnotation.hpp> #include <xercesc/framework/psvi/XSAnnotation.hpp>
#include <xercesc/framework/psvi/XSValue.hpp> #include <xercesc/framework/psvi/XSValue.hpp>
#include <xercesc/framework/MemBufFormatTarget.hpp> #include <xercesc/framework/MemBufFormatTarget.hpp>
@@ -32,7 +31,6 @@ private:
void onStartComponent(EntityID entity, std::string type); void onStartComponent(EntityID entity, std::string type);
void parseComponentInfo(); void parseComponentInfo();
void parseDefaults(); void parseDefaults();
std::string parseAnnotationXML(const XMLCh* xml);
}; };
#endif #endif
-51
View File
@@ -1,51 +0,0 @@
#ifndef EntityWrapper_h__
#define EntityWrapper_h__
#include <boost/optional.hpp>
#include <boost/functional/hash.hpp>
#include "ComponentWrapper.h"
class World;
struct EntityWrapper
{
EntityWrapper()
: World(nullptr)
, ID(EntityID_Invalid)
{ }
EntityWrapper(::World* world, EntityID id)
: World(world)
, ID(id)
{ }
::World* World;
EntityID ID;
static const EntityWrapper Invalid;
bool HasComponent(const std::string& componentName);
EntityWrapper Parent();
bool Valid();
ComponentWrapper operator[](const char* componentName);
bool operator==(const EntityWrapper& e) const;
bool operator!=(const EntityWrapper& e) const;
explicit operator EntityID() const;
operator bool();
};
namespace std
{
template<> struct hash<EntityWrapper>
{
std::size_t operator()(const EntityWrapper& e) const
{
std::size_t seed = 0;
boost::hash_combine(seed, e.World);
boost::hash_combine(seed, e.ID);
return seed;
}
};
}
#endif
+2 -2
View File
@@ -43,7 +43,7 @@ template <typename ContextType, typename EventType>
class EventRelay : public BaseEventRelay class EventRelay : public BaseEventRelay
{ {
public: public:
typedef std::function<bool(EventType&)> CallbackType; typedef std::function<bool(const EventType&)> CallbackType;
EventRelay() EventRelay()
: m_Callback(nullptr) : m_Callback(nullptr)
@@ -65,7 +65,7 @@ template <typename ContextType, typename EventType>
bool EventRelay<ContextType, EventType>::Receive(const std::shared_ptr<Event> event) bool EventRelay<ContextType, EventType>::Receive(const std::shared_ptr<Event> event)
{ {
if (m_Callback != nullptr) { if (m_Callback != nullptr) {
return m_Callback(*static_cast<EventType*>(event.get())); return m_Callback(*static_cast<const EventType*>(event.get()));
} else { } else {
return false; return false;
} }
+4 -14
View File
@@ -5,14 +5,6 @@
template <typename T> template <typename T>
class MemoryPoolForwardIterator; class MemoryPoolForwardIterator;
namespace DisableMemoryPool
{
//if true -> Pool allocation is not used when calling Allocate/Free, just use regular dynamic allocation.
//if false -> Use pool allocation.
//Should default to false, unless the DisableMemoryPool is true in the Config.ini files.
extern bool Value;
}
//This is the class to use if you want to allocate blocks (slots) of raw memory, with a fixed maximum size (stride). //This is the class to use if you want to allocate blocks (slots) of raw memory, with a fixed maximum size (stride).
//Additionally, if you know that every memory-block will contain one object of a specific type, (i.e. the stride for the slot //Additionally, if you know that every memory-block will contain one object of a specific type, (i.e. the stride for the slot
//will the size of the object type) you should use ObjectPool<T> instead, your life will become easier. //will the size of the object type) you should use ObjectPool<T> instead, your life will become easier.
@@ -88,8 +80,8 @@ public:
//If element cannot be allocated in the pool, because the memory ran out, memory is allocated dynamically with malloc() "outside the pool". //If element cannot be allocated in the pool, because the memory ran out, memory is allocated dynamically with malloc() "outside the pool".
char* Allocate() char* Allocate()
{ {
for (; m_CurrentAllocSlot < m_NumSlots && m_SlotIsAllocated[m_CurrentAllocSlot] && !DisableMemoryPool::Value; ++m_CurrentAllocSlot); for (; m_CurrentAllocSlot < m_NumSlots && m_SlotIsAllocated[m_CurrentAllocSlot]; ++m_CurrentAllocSlot);
if (m_CurrentAllocSlot < m_NumSlots && !DisableMemoryPool::Value) { if (m_CurrentAllocSlot < m_NumSlots) {
if (m_LowestAllocatedSlot > m_CurrentAllocSlot) if (m_LowestAllocatedSlot > m_CurrentAllocSlot)
m_LowestAllocatedSlot = m_CurrentAllocSlot; m_LowestAllocatedSlot = m_CurrentAllocSlot;
//Mark the slot as allocated. //Mark the slot as allocated.
@@ -101,9 +93,7 @@ public:
else { else {
m_ExtraMemory.push_back((char*)malloc(m_Stride)); m_ExtraMemory.push_back((char*)malloc(m_Stride));
//We should preferably not enter here to avoid performance issues. Set more numMaxElements in constructor instead. //We should preferably not enter here to avoid performance issues. Set more numMaxElements in constructor instead.
if (!DisableMemoryPool::Value) { LOG_WARNING("Allocated slots exceed Pool size, extra memory allocated dynamically. Pool size: %u, dynamic size: %u.", m_NumSlots, m_ExtraMemory.size());
LOG_WARNING("Allocated slots exceed Pool size, extra memory allocated dynamically. Pool size: %u, dynamic size: %u.", m_NumSlots, m_ExtraMemory.size());
}
return m_ExtraMemory.back(); return m_ExtraMemory.back();
} }
} }
@@ -118,7 +108,7 @@ public:
//(i.e. IsAllocatedInPool may give false positives) //(i.e. IsAllocatedInPool may give false positives)
//if it was malloc():ed //if it was malloc():ed
//so, we may enter here even if we shouldn't. //so, we may enter here even if we shouldn't.
if (!DisableMemoryPool::Value && IsAllocatedInPool(obj)) { if (IsAllocatedInPool(obj)) {
--m_NumAllocatedSlots; --m_NumAllocatedSlots;
const size_t freeSlot = (obj - m_StartAddress) / m_Stride; const size_t freeSlot = (obj - m_StartAddress) / m_Stride;
m_SlotIsAllocated[freeSlot] = false; m_SlotIsAllocated[freeSlot] = false;
+104
View File
@@ -0,0 +1,104 @@
#ifndef OctTree_h__
#define OctTree_h__
#include "Core/AABB.h"
class Ray;
class OctTree
{
public:
struct Output
{
float CollideDistance;
};
OctTree();
~OctTree();
//For the root OctTree, [octTreeBounds] should be a box containing the entire level.
OctTree(const AABB& octTreeBounds, int subDivisions);
//We cannot copy the OctTree as of now, because of the recursive dynamic allocation.
//Define these if the OctTree suddenly needs to be copied, think of the children OctChild* ptrs.
OctTree(const OctTree& other) = delete;
OctTree(const OctTree&& other) = delete;
OctTree& operator= (const OctTree& other) = delete;
//Add a dynamic object (one that moves around) into the tree.
void AddDynamicObject(const AABB& box);
//Add a static object (that does not move) into the tree.
void AddStaticObject(const AABB& box);
//Get the boxes that are in the same area as the input [box], the boxes are put in [outBoxes].
void BoxesInSameRegion(const AABB& box, std::vector<AABB>& outBoxes);
//Empty the tree of all objects, static and dynamic.
void ClearObjects();
//Empty the tree of all dynamic objects. Static objects remain in the tree.
void ClearDynamicObjects();
//Returns true if the ray collides with something in the tree. Result is written to [data].
bool RayCollides(const Ray& ray, Output& data);
//Returns true if the box collides with something in the tree.
//On collision with a box, that box is written to [outBoxIntersected].
//Note: More efficient than calling BoxesInSameRegion from outside and testing there.
bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected);
private:
struct OctChild; //Fwd declaration;
struct ContainedObject
{
ContainedObject()
: Box(AABB())
, Checked(false)
{}
ContainedObject(AABB box)
: Box(box)
, Checked(false)
{}
AABB Box;
bool Checked;
};
OctChild* m_Root;
std::vector<ContainedObject> m_StaticObjects;
std::vector<ContainedObject> m_DynamicObjects;
bool m_UpdatedOnce;
unsigned int m_BoxID;
glm::vec3 m_PrevPos;
glm::quat m_PrevOri;
void falsifyObjectChecks();
struct OctChild
{
~OctChild();
OctChild(const AABB& octTreeBounds,
int subDivisions,
std::vector<OctTree::ContainedObject>& staticObjects,
std::vector<OctTree::ContainedObject>& dynamicObjects);
OctChild(const OctChild& other) = delete;
OctChild(const OctChild&& other) = delete;
OctChild& operator= (const OctChild& other) = delete;
void AddDynamicObject(const AABB& box);
void AddStaticObject(const AABB& box);
void BoxesInSameRegion(const AABB& box, std::vector<AABB>& outBoxes) const;
void ClearObjects();
void ClearDynamicObjects();
bool RayCollides(const Ray& ray, Output& data) const;
bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const;
OctChild* m_Children[8];
//Indices into the lists in OctTree.
std::vector<int> m_StaticObjIndices;
std::vector<int> m_DynamicObjIndices;
AABB m_Box;
//Reference to the lists in OctTree.
std::vector<OctTree::ContainedObject>& m_StaticObjectsRef;
std::vector<OctTree::ContainedObject>& m_DynamicObjectsRef;
inline bool hasChildren() const;
int childIndexContainingPoint(const glm::vec3& point) const;
std::vector<int> childIndicesContainingBox(const AABB& box) const;
};
};
#endif
-233
View File
@@ -1,233 +0,0 @@
#ifndef Octree_h__
#define Octree_h__
#include <type_traits>
#include "../Common.h"
#include "AABB.h"
//Fwd declarations.
class Ray;
namespace OctSpace
{
struct Output;
struct ContainedObject;
struct Child;
}
//T needs to be AABB, or inherit from AABB.
//T also needs to have a default constructor.
template<typename T>
class Octree
{
public:
Octree() = delete;
~Octree();
//For the root Octree, [octreeBounds] should be a box containing the entire level.
Octree(const AABB& octreeBounds, int subDivisions);
//We cannot copy the Octree as of now, because of the recursive dynamic allocation.
//Define these if the Octree suddenly needs to be copied, think of the children Child* ptrs.
Octree(const Octree& other) = delete;
Octree(const Octree&& other) = delete;
Octree& operator= (const Octree& other) = delete;
//Add a dynamic object (one that moves around) into the tree.
void AddDynamicObject(const T& object);
//Add a static object (that does not move) into the tree.
void AddStaticObject(const T& object);
//Get the objects that are in the same area as the input [box], the objects are put in [outObjects].
//The type Box must be AABB, or inherit from AABB.
template<typename Box>
void ObjectsInSameRegion(const Box& box, std::vector<T>& outObjects);
//Empty the tree of all objects, static and dynamic.
void ClearObjects();
//Empty the tree of all dynamic objects. Static objects remain in the tree.
void ClearDynamicObjects();
//Returns true if the ray collides with something in the tree. Result is written to [data].
bool RayCollides(const Ray& ray, OctSpace::Output& data);
//Returns true if the box collides with something in the tree.
//On collision with a box, that box is written to [outBoxIntersected].
//Note: More efficient than calling ObjectsInSameRegion from outside and testing there.
bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected);
private:
OctSpace::Child* m_Root;
std::vector<OctSpace::ContainedObject> m_StaticObjects;
std::vector<OctSpace::ContainedObject> m_DynamicObjects;
void falsifyObjectChecks();
};
namespace OctSpace
{
struct Output
{
float CollideDistance;
};
struct ContainedObject
{
ContainedObject()
: Box(nullptr)
, Checked(false)
{}
template<typename BoxlikeObject>
ContainedObject(const BoxlikeObject& box)
: Box(new BoxlikeObject(box))
, Checked(false)
{}
std::unique_ptr<AABB> Box;
bool Checked;
};
struct Child
{
~Child();
Child(const AABB& octTreeBounds,
int subDivisions,
std::vector<ContainedObject>& staticObjects,
std::vector<ContainedObject>& dynamicObjects);
Child(const Child& other) = delete;
Child(const Child&& other) = delete;
Child& operator= (const Child& other) = delete;
void AddDynamicObject(const AABB& box);
void AddStaticObject(const AABB& box);
template<typename T, typename Box>
void ObjectsInSameRegion(const Box& box, std::vector<T>& outObjects) const;
void ClearObjects();
void ClearDynamicObjects();
bool RayCollides(const Ray& ray, Output& data) const;
bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const;
Child* m_Children[8];
//Indices into the lists in Octree.
std::vector<int> m_StaticObjIndices;
std::vector<int> m_DynamicObjIndices;
AABB m_Box;
//Reference to the lists in Octree.
std::vector<ContainedObject>& m_StaticObjectsRef;
std::vector<ContainedObject>& m_DynamicObjectsRef;
inline bool hasChildren() const;
int childIndexContainingPoint(const glm::vec3& point) const;
std::vector<int> childIndicesContainingBox(const AABB& box) const;
};
}
template<typename T>
Octree<T>::Octree(const AABB& octTreeBounds, int subDivisions)
: m_Root(new OctSpace::Child(octTreeBounds, subDivisions, m_StaticObjects, m_DynamicObjects))
{
static_assert(std::is_base_of<AABB, T>::value, "template argument type T in Octree must be a subclass of AABB.");
}
template<typename T>
Octree<T>::~Octree()
{
delete m_Root;
}
template<typename T>
void Octree<T>::AddDynamicObject(const T& object)
{
m_Root->AddDynamicObject(object);
m_DynamicObjects.emplace_back(object);
}
template<typename T>
void Octree<T>::AddStaticObject(const T& object)
{
m_Root->AddStaticObject(object);
m_StaticObjects.emplace_back(object);
}
template<typename T>
template<typename Box>
void Octree<T>::ObjectsInSameRegion(const Box& box, std::vector<T>& outObjects)
{
static_assert(std::is_base_of<AABB, Box>::value, "template argument type Box in Octree<T>::ObjectsInSameRegion must be a subclass of AABB.");
falsifyObjectChecks();
m_Root->ObjectsInSameRegion(box, outObjects);
}
template<typename T>
void Octree<T>::ClearObjects()
{
m_StaticObjects.clear();
m_DynamicObjects.clear();
m_Root->ClearObjects();
}
template<typename T>
void Octree<T>::ClearDynamicObjects()
{
m_DynamicObjects.clear();
m_Root->ClearDynamicObjects();
}
template<typename T>
bool Octree<T>::RayCollides(const Ray& ray, OctSpace::Output& data)
{
falsifyObjectChecks();
data.CollideDistance = -1;
return m_Root->RayCollides(ray, data);
}
template<typename T>
bool Octree<T>::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected)
{
falsifyObjectChecks();
return m_Root->BoxCollides(boxToTest, outBoxIntersected);
}
template<typename T>
void Octree<T>::falsifyObjectChecks()
{
for (auto& obj : m_StaticObjects) {
obj.Checked = false;
}
for (auto& obj : m_DynamicObjects) {
obj.Checked = false;
}
}
template<typename T, typename Box>
void OctSpace::Child::ObjectsInSameRegion(const Box& box, std::vector<T>& outObjects) const
{
if (hasChildren()) {
for (auto i : childIndicesContainingBox(box)) {
m_Children[i]->ObjectsInSameRegion(box, outObjects);
}
} else {
size_t startIndex = outObjects.size();
int numDuplicates = 0;
outObjects.resize(outObjects.size() + m_StaticObjIndices.size() + m_DynamicObjIndices.size());
for (size_t i = 0; i < m_StaticObjIndices.size(); ++i) {
ContainedObject& obj = m_StaticObjectsRef[m_StaticObjIndices[i]];
if (obj.Checked) {
++numDuplicates;
} else {
obj.Checked = true;
outObjects[startIndex + i - numDuplicates] = *static_cast<T*>(obj.Box.get());
}
}
for (size_t i = 0; i < m_DynamicObjIndices.size(); ++i) {
ContainedObject& obj = m_DynamicObjectsRef[m_DynamicObjIndices[i]];
if (obj.Checked) {
++numDuplicates;
} else {
obj.Checked = true;
outObjects[startIndex + i - numDuplicates] = *static_cast<T*>(obj.Box.get());
}
}
for (size_t i = 0; i < numDuplicates; ++i) {
outObjects.pop_back();
}
}
}
#endif
+1 -1
View File
@@ -2,7 +2,7 @@
#define Ray_h__ #define Ray_h__
#include "../GLM.h" #include "../GLM.h"
#include "../Common.h" #include "Common.h"
class Ray class Ray
{ {
+39 -132
View File
@@ -12,6 +12,7 @@
/** Base Resource class. /** Base Resource class.
Implement this class for every resource to be handled by the resource manager. Implement this class for every resource to be handled by the resource manager.
Implement Create() to return a new object of that type.
*/ */
class Resource class Resource
{ {
@@ -21,23 +22,6 @@ protected:
Resource() { } Resource() { }
public: public:
//Should be thrown in a Resource's constructor if it cannot complete because another resource is still loading.
//Not actually an error, just a message to the ResourceManager.
struct StillLoadingException : public std::exception
{
virtual const char* what() const throw()
{
return "Resource is still loading.";
}
};
struct FailedLoadingException : public std::exception
{
virtual const char* what() const throw()
{
return "Resource is failed to load.";
}
};
// Pretend that this is a pure virtual function that you have to implement // Pretend that this is a pure virtual function that you have to implement
// FIXME: Why did we do this again instead of just using the constructor? // FIXME: Why did we do this again instead of just using the constructor?
// static Resource* Create(std::string resourceName); // static Resource* Create(std::string resourceName);
@@ -49,15 +33,6 @@ public:
unsigned int ResourceID; unsigned int ResourceID;
}; };
//Any class inheriting from this class will always be loaded on the master thread, not on a parallel worker thread.
//This is important in case some instructions must be executed on the main thread, e.g. OpenGL commands, like glBindBuffer.
//This resource can still be loaded asyncronously, but it will not be loaded in a thread, instead it's constructor will
//be called once on every ResourceManager::Load, just throw StillLoadingException in the constructor if it is not done yet.
class ThreadUnsafeResource : public Resource
{
friend class ResourceManager;
};
/** Singleton resource manager to keep track of and cache any external engine assets */ /** Singleton resource manager to keep track of and cache any external engine assets */
class ResourceManager class ResourceManager
{ {
@@ -65,7 +40,6 @@ private:
ResourceManager(); ResourceManager();
public: public:
static bool UseThreading;
/*static ResourceManager& Instance() /*static ResourceManager& Instance()
{ {
static ResourceManager s; static ResourceManager s;
@@ -75,6 +49,15 @@ public:
template <typename T> template <typename T>
static void RegisterType(std::string typeName); static void RegisterType(std::string typeName);
/** Preloads a resource and caches it for future use
@tparam T Resource type.
@param resourceName Fully qualified name of the resource to preload.
*/
template <typename T>
static void Preload(std::string resourceName);
static void Preload(std::string resourceType, std::string resourceName);
/** Checks if a resource is in cache /** Checks if a resource is in cache
@param resourceType Resource type as string. @param resourceType Resource type as string.
@@ -82,20 +65,15 @@ public:
*/ */
// TODO: Templateify // TODO: Templateify
static bool IsResourceLoaded(std::string resourceType, std::string resourceName); static bool IsResourceLoaded(std::string resourceType, std::string resourceName);
/** Return value should always be a valid pointer, will throw an exception on error.
If the resource has been loaded already, returns a pointer to it.
If Async is false: Hot-loads a resource, caches it for future use, and returns a pointer to it. /** Hot-loads a resource and caches it for future use
If Async is true: If the resource is not loaded yet, starts loading the resource
in the background and throws Resource::StillLoadingException immediately.
@tparam T Resource type. @tparam T Resource type.
@tparam async Set this to true if the resource should be loaded asyncronously.
@param resourceName Fully qualified name of the resource to load. @param resourceName Fully qualified name of the resource to load.
*/ */
template <typename T, bool async = false> template <typename T>
static T* Load(const std::string& resourceName, Resource* parent = nullptr); static T* Load(std::string resourceName, Resource* parent = nullptr);
static Resource* Load(std::string resourceType, std::string resourceName, Resource* parent = nullptr);
/** Reloads an already loaded resource, keeping its resource ID intact. /** Reloads an already loaded resource, keeping its resource ID intact.
@@ -109,31 +87,19 @@ public:
static void Update(); static void Update();
private: private:
//This is a haxy way to make sure that IsMainThread is run when the program starts, so the master thread id is set.
struct MasterThreadChecker
{
MasterThreadChecker()
{
ResourceManager::IsMainThread();
}
};
const static MasterThreadChecker m_Checker;
static std::unordered_map<std::string, std::string> m_CompilerTypenameToResourceType; static std::unordered_map<std::string, std::string> m_CompilerTypenameToResourceType;
static std::unordered_map<std::string, std::function<Resource*(std::string)>> m_FactoryFunctions; // type -> factory function static std::unordered_map<std::string, std::function<Resource*(std::string)>> m_FactoryFunctions; // type -> factory function
static std::unordered_map<std::pair<std::string, std::string>, Resource*> m_ResourceCache; // (type, name) -> resource static std::unordered_map<std::pair<std::string, std::string>, Resource*> m_ResourceCache; // (type, name) -> resource
static std::unordered_map<std::string, Resource*> m_ResourceFromName; // name -> resource static std::unordered_map<std::string, Resource*> m_ResourceFromName; // name -> resource
static std::unordered_map<Resource*, Resource*> m_ResourceParents; // resource -> parent resource static std::unordered_map<Resource*, Resource*> m_ResourceParents; // resource -> parent resource
static std::unordered_map<std::pair<std::string, std::string>, boost::thread> m_LoadingThreads; // (type, name) -> loading thread
static std::unordered_map<std::pair<std::string, std::string>, std::exception_ptr> m_LoadingThreadExceptions; // (type, name) -> exceptions
static boost::recursive_mutex m_Mutex;
// TODO: Getters for IDs // TODO: Getters for IDs
static unsigned int m_CurrentResourceTypeID; static unsigned int m_CurrentResourceTypeID;
static std::unordered_map<std::string, unsigned int> m_ResourceTypeIDs; static std::unordered_map<std::string, unsigned int> m_ResourceTypeIDs;
// Number of resources of a type. Doubles as local ID. // Number of resources of a type. Doubles as local ID.
static std::unordered_map<unsigned int, unsigned int> m_ResourceCount; static std::unordered_map<unsigned int, unsigned int> m_ResourceCount;
// Flag to suppress hot-load warnings when a preloading resource chain loads another resource
static bool m_Preloading;
static FileWatcher m_FileWatcher; static FileWatcher m_FileWatcher;
static void fileWatcherCallback(std::string path, FileWatcher::FileEventFlags flags); static void fileWatcherCallback(std::string path, FileWatcher::FileEventFlags flags);
@@ -142,13 +108,22 @@ private:
static unsigned int GetNewResourceID(unsigned int typeID); static unsigned int GetNewResourceID(unsigned int typeID);
// Internal: Create a resource and cache it // Internal: Create a resource and cache it
static Resource* createResourceThrowing(const std::string& resourceType, const std::string& resourceName, Resource* parent); static Resource* CreateResource(std::string resourceType, std::string resourceName, Resource* parent);
static Resource* createResource(const std::string& resourceType, const std::string& resourceName, Resource* parent, std::exception_ptr& exception);
static Resource* cacheResource(Resource* resource, const std::string& resourceType, const std::string& resourceName, Resource* parent);
static bool IsMainThread();
}; };
template <typename T>
T* ResourceManager::Load(std::string resourceName, Resource* parent /* = nullptr */)
{
auto resourceTypename = typeid(T).name();
auto it = m_CompilerTypenameToResourceType.find(resourceTypename);
if (it == m_CompilerTypenameToResourceType.end()) {
LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": type not registered", resourceName.c_str(), resourceTypename);
return nullptr;
}
return static_cast<T*>(Load(it->second, resourceName, parent));
}
template <typename T> template <typename T>
void ResourceManager::RegisterType(std::string typeName) void ResourceManager::RegisterType(std::string typeName)
{ {
@@ -156,85 +131,17 @@ void ResourceManager::RegisterType(std::string typeName)
m_FactoryFunctions[typeName] = [](std::string resourceName) { return new T(resourceName); }; m_FactoryFunctions[typeName] = [](std::string resourceName) { return new T(resourceName); };
} }
template <typename T, bool async> template <typename T>
static T* ResourceManager::Load(const std::string& resourceName, Resource* parent /* = nullptr */) void ResourceManager::Preload(std::string resourceName)
{ {
auto resourceTypename = typeid(T).name(); auto resourceTypename = typeid(T).name();
auto iter = m_CompilerTypenameToResourceType.find(resourceTypename); auto it = m_CompilerTypenameToResourceType.find(resourceTypename);
if (iter == m_CompilerTypenameToResourceType.end()) { if (it == m_CompilerTypenameToResourceType.end()) {
LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": type not registered", resourceName.c_str(), resourceTypename); LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": type not registered", resourceName.c_str(), resourceTypename);
throw Resource::FailedLoadingException(); return;
} }
std::string resourceType = iter->second; Preload(it->second, resourceName);
constexpr bool mustNotLoadInThread = std::is_base_of<ThreadUnsafeResource, T>::value;
if (mustNotLoadInThread && !IsMainThread()) {
LOG_ERROR("Failed to Load \"%s\": ThreadUnsafeResource type \"%s\" load in the constructor of another resource that is loaded asyncronously.", resourceName.c_str(), iter->second.c_str());
throw Resource::FailedLoadingException();
}
auto cacheKey = std::make_pair(resourceType, resourceName);
decltype(m_ResourceCache)::iterator it;
//If a thread has already been launched to load this resource.
auto tIt = m_LoadingThreads.find(cacheKey);
if (UseThreading && tIt != m_LoadingThreads.end()) {
if (async) {
//Throw StillLoadingException if the thread is still working.
if (!tIt->second.try_join_for(boost::chrono::nanoseconds(1))) {
throw Resource::StillLoadingException();
}
//Else we know the thread has completed.
} else {
//Wait for the thread to finish loading.
tIt->second.join();
}
//When the thread is done, delete the thread.
m_LoadingThreads.erase(tIt);
//Rethrow the thread exception if it threw any.
auto excIt = m_LoadingThreadExceptions.find(cacheKey);
std::exception_ptr exception = excIt->second;
m_LoadingThreadExceptions.erase(excIt);
if (exception) {
std::rethrow_exception(exception);
}
}
//If resource has already been cached and completely loaded.
it = m_ResourceCache.find(cacheKey);
if (it != m_ResourceCache.end()) {
if (it->second != nullptr) {
return static_cast<T*>(it->second);
} else {
//Don't return null on failure, exception instead.
throw Resource::FailedLoadingException();
}
}
//If resource is not cached..
if (UseThreading && async) {
if (mustNotLoadInThread) {
try {
return static_cast<T*>(createResourceThrowing(resourceType, resourceName, parent));
} catch (const Resource::StillLoadingException&) {
throw;
}
} else {
//Create a thread that loads the resource into cache.
m_LoadingThreads[cacheKey] = boost::thread(createResource, resourceType, resourceName, parent, m_LoadingThreadExceptions[cacheKey]);
throw Resource::StillLoadingException();
}
} else {
//load and return the resource.
while (true) {
try {
return static_cast<T*>(createResourceThrowing(resourceType, resourceName, parent));
} catch (const Resource::StillLoadingException&) {
continue;
} catch (const std::exception&) {
throw;
}
}
}
} }
#endif #endif
+12 -13
View File
@@ -3,7 +3,6 @@
#include "EventBroker.h" #include "EventBroker.h"
#include "World.h" #include "World.h"
#include "EntityWrapper.h"
#include "ComponentWrapper.h" #include "ComponentWrapper.h"
class System class System
@@ -11,41 +10,41 @@ class System
friend class SystemPipeline; friend class SystemPipeline;
protected: protected:
System(World* world, EventBroker) { } System(EventBroker* eventBroker)
System(World* world, EventBroker* eventBroker) : m_EventBroker(eventBroker)
: m_World(world)
, m_EventBroker(eventBroker)
{ } { }
virtual ~System() = default; virtual ~System() = default;
World* m_World;
EventBroker* m_EventBroker; EventBroker* m_EventBroker;
}; };
class PureSystem : public virtual System class PureSystem : public System
{ {
friend class SystemPipeline; friend class SystemPipeline;
protected: protected:
PureSystem(std::string componentType) PureSystem(EventBroker* eventBroker, std::string componentType)
: m_ComponentType(componentType) : System(eventBroker)
, m_ComponentType(componentType)
{ } { }
virtual ~PureSystem() = default; virtual ~PureSystem() = default;
const std::string m_ComponentType; const std::string m_ComponentType;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cComponent, double dt) = 0; virtual void UpdateComponent(World* world, ComponentWrapper& component, double dt) = 0;
}; };
class ImpureSystem : public virtual System class ImpureSystem : public System
{ {
friend class SystemPipeline; friend class SystemPipeline;
protected: protected:
ImpureSystem() = default; ImpureSystem(EventBroker* eventBroker)
: System(eventBroker)
{ }
virtual ~ImpureSystem() = default; virtual ~ImpureSystem() = default;
virtual void Update(double dt) = 0; virtual void Update(World* world, double dt) = 0;
}; };
#endif #endif
+14 -42
View File
@@ -5,19 +5,13 @@
#include "EventBroker.h" #include "EventBroker.h"
#include "System.h" #include "System.h"
#include "World.h" #include "World.h"
#include "EPause.h"
class SystemPipeline class SystemPipeline
{ {
public: public:
SystemPipeline(World* world, EventBroker* eventBroker) SystemPipeline(EventBroker* eventBroker)
: m_World(world) : m_EventBroker(eventBroker)
, m_EventBroker(eventBroker) { }
{
EVENT_SUBSCRIBE_MEMBER(m_EPause, &SystemPipeline::OnPause);
EVENT_SUBSCRIBE_MEMBER(m_EResume, &SystemPipeline::OnResume);
}
~SystemPipeline() ~SystemPipeline()
{ {
for (UnorderedSystems& group : m_OrderedSystemGroups) { for (UnorderedSystems& group : m_OrderedSystemGroups) {
@@ -35,11 +29,11 @@ public:
m_OrderedSystemGroups.resize(updateOrderLevel + 1); m_OrderedSystemGroups.resize(updateOrderLevel + 1);
} }
UnorderedSystems& group = m_OrderedSystemGroups[updateOrderLevel]; UnorderedSystems& group = m_OrderedSystemGroups[updateOrderLevel];
System* system = new T(m_World, m_EventBroker, args...); System* system = new T(m_EventBroker, args...);
group.Systems[typeid(T).name()] = system; group.Systems[typeid(T).name()] = system;
PureSystem* pureSystem = dynamic_cast<PureSystem*>(system); if (std::is_base_of<PureSystem, T>::value) {
if (pureSystem != nullptr) { PureSystem* pureSystem = static_cast<PureSystem*>(system);
if (!pureSystem->m_ComponentType.empty()) { if (!pureSystem->m_ComponentType.empty()) {
group.PureSystems[pureSystem->m_ComponentType].push_back(pureSystem); group.PureSystems[pureSystem->m_ComponentType].push_back(pureSystem);
} else { } else {
@@ -47,18 +41,14 @@ public:
} }
} }
ImpureSystem* impureSystem = dynamic_cast<ImpureSystem*>(system); if (std::is_base_of<ImpureSystem, T>::value) {
if (impureSystem != nullptr) { ImpureSystem* impureSystem = static_cast<ImpureSystem*>(system);
group.ImpureSystems.push_back(impureSystem); group.ImpureSystems.push_back(impureSystem);
} }
} }
void Update(double dt) void Update(World* world, double dt)
{ {
if (m_Paused) {
dt = 0.0;
}
for (UnorderedSystems& group : m_OrderedSystemGroups) { for (UnorderedSystems& group : m_OrderedSystemGroups) {
// Process events // Process events
for (auto& pair : group.Systems) { for (auto& pair : group.Systems) {
@@ -66,30 +56,27 @@ public:
} }
// Update // Update
for (auto& system : group.ImpureSystems) {
system->Update(dt);
}
for (auto& pair : group.PureSystems) { for (auto& pair : group.PureSystems) {
const std::string& componentName = pair.first; const std::string& componentName = pair.first;
auto& systems = pair.second; auto& systems = pair.second;
const ComponentPool* pool = m_World->GetComponents(componentName); const ComponentPool* pool = world->GetComponents(componentName);
if (pool == nullptr) { if (pool == nullptr) {
continue; continue;
} }
for (auto& component : *pool) { for (auto& component : *pool) {
for (auto& system : systems) { for (auto& system : systems) {
system->UpdateComponent(EntityWrapper(m_World, component.EntityID), component, dt); system->UpdateComponent(world, component, dt);
} }
} }
} }
for (auto& system : group.ImpureSystems) {
system->Update(world, dt);
}
} }
} }
private: private:
World* m_World;
EventBroker* m_EventBroker; EventBroker* m_EventBroker;
bool m_Paused = false;
struct UnorderedSystems struct UnorderedSystems
{ {
std::map<std::string, System*> Systems; std::map<std::string, System*> Systems;
@@ -97,21 +84,6 @@ private:
std::vector<ImpureSystem*> ImpureSystems; std::vector<ImpureSystem*> ImpureSystems;
}; };
std::vector<UnorderedSystems> m_OrderedSystemGroups; std::vector<UnorderedSystems> m_OrderedSystemGroups;
EventRelay<SystemPipeline, Events::Pause> m_EPause;
bool OnPause(const Events::Pause& e) {
if (e.World == m_World) {
m_Paused = true;
}
return true;
}
EventRelay<SystemPipeline, Events::Resume> m_EResume;
bool OnResume(const Events::Resume& e) {
if (e.World == m_World) {
m_Paused = false;
}
return true;
}
}; };
#endif #endif
-17
View File
@@ -1,17 +0,0 @@
#ifndef Transform_h__
#define Transform_h__
#include "../GLM.h"
#include "World.h"
namespace Transform
{
glm::vec3 AbsolutePosition(World* world, EntityID entity);
glm::quat AbsoluteOrientation(World* world, EntityID entity);
glm::vec3 AbsoluteScale(World* world, EntityID entity);
glm::mat4 ModelMatrix(EntityID entity, World* world);
}
#endif
-22
View File
@@ -1,22 +0,0 @@
#ifndef UniformScaleSystem_h__
#define UniformScaleSystem_h__
#include "../GLM.h"
#include "System.h"
#include "../Rendering/ESetCamera.h"
class UniformScaleSystem : public PureSystem
{
public:
UniformScaleSystem(World* world, EventBroker* eventBroker);
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cUniformScale, double dt) override;
private:
EntityWrapper m_Camera = EntityWrapper::Invalid;
EventRelay<UniformScaleSystem, Events::SetCamera> m_ESetCamera;
bool OnSetCamera(const Events::SetCamera& e);
};
#endif
+23
View File
@@ -80,4 +80,27 @@ static void _LOG(_LOG_LEVEL logLevel, const char* file, const char* func, unsign
#define LOG_DEBUG(format, ...) \ #define LOG_DEBUG(format, ...) \
LOG(LOG_LEVEL_DEBUG, format, ##__VA_ARGS__) LOG(LOG_LEVEL_DEBUG, format, ##__VA_ARGS__)
// Set the log level temporarily for the current scope
#define LOG_LEVEL_SCOPE(logLevel) \
_LOG_LEVEL_SCOPED_HELPER<logLevel> _logLevelScopedHelper;
template <_LOG_LEVEL LEVEL>
class _LOG_LEVEL_SCOPED_HELPER
{
public:
_LOG_LEVEL_SCOPED_HELPER()
{
m_OriginalLogLevel = LOG_LEVEL;
LOG_LEVEL = LEVEL;
}
~_LOG_LEVEL_SCOPED_HELPER()
{
LOG_LEVEL = m_OriginalLogLevel;
}
private:
_LOG_LEVEL m_OriginalLogLevel;
};
#endif // Logging_h__ #endif // Logging_h__
+5 -7
View File
@@ -21,21 +21,19 @@ public:
// Register a component type and allocate space for it // Register a component type and allocate space for it
void RegisterComponent(ComponentInfo& ci); void RegisterComponent(ComponentInfo& ci);
// Attach a component to an entity and fill it with default values // Attach a component to an entity and fill it with default values
ComponentWrapper AttachComponent(EntityID entity, const std::string& componentType); ComponentWrapper AttachComponent(EntityID entity, std::string componentType);
// Check if an entity has a component // Check if an entity has a component
bool HasComponent(EntityID entity, const std::string& componentType) const; bool HasComponent(EntityID entity, std::string componentType) const;
// Get a component of an entity // Get a component of an entity
ComponentWrapper GetComponent(EntityID entity, const std::string& componentType); ComponentWrapper GetComponent(EntityID entity, std::string componentType);
// Delete a component off an entity // Delete a component off an entity
void DeleteComponent(EntityID entity, const std::string& componentType); void DeleteComponent(EntityID entity, std::string componentType);
// Get all components of the specified type // Get all components of the specified type
const ComponentPool* GetComponents(const std::string& componentType); const ComponentPool* GetComponents(std::string componentType);
// Get entity parent // Get entity parent
EntityID GetParent(EntityID entity); EntityID GetParent(EntityID entity);
// Change the parent of an entity // Change the parent of an entity
void SetParent(EntityID entity, EntityID parent); void SetParent(EntityID entity, EntityID parent);
// Get children of an entity
const std::pair<std::unordered_multimap<EntityID, EntityID>::const_iterator, std::unordered_multimap<EntityID, EntityID>::const_iterator> GetChildren(EntityID entity);
// Get all component pools // Get all component pools
const std::unordered_map<std::string, ComponentPool*>& GetComponentPools() const { return m_ComponentPools; } const std::unordered_map<std::string, ComponentPool*>& GetComponentPools() const { return m_ComponentPools; }
// Get the entity children map // Get the entity children map
-153
View File
@@ -1,153 +0,0 @@
#ifndef EditorGUI_h__
#define EditorGUI_h__
#include <imgui/imgui.h>
#define IMGUI_DEFINE_MATH_OPERATORS
#include <imgui/imgui_internal.h>
#include <nativefiledialog/nfd.h>
#include <boost/filesystem.hpp>
#include <boost/any.hpp>
#include "../Common.h"
#include "../GLM.h"
#include <glm/gtx/common.hpp>
#include "EditorWidgetSystem.h"
#include "../Core/EventBroker.h"
#include "../Core/World.h"
#include "../Core/EntityWrapper.h"
#include "../Core/ResourceManager.h"
#include "../Core/EPause.h"
#include "../Core/EKeyDown.h"
#include "../Rendering/Texture.h"
class EditorGUI
{
public:
EditorGUI(World* world, EventBroker* eventBroker);
enum class WidgetMode
{
Translate,
Rotate,
Scale
};
void Draw();
void SelectEntity(EntityWrapper entity);
void SetDirty(EntityWrapper entity);
// Called when an entity is selected in the entity tree
typedef std::function<void(EntityWrapper)> OnEntitySelectedCallback_t;
void SetEntitySelectedCallback(OnEntitySelectedCallback_t f) { m_OnEntitySelected = f; }
// Called when the user means to import an entity file.
// @param EntityWrapper The entity to parent the imported entity to. The entity will be imported into the world of this entity.
// @param boost::filesystem::path The path to the entity to import
// @return EntityWrapper The newly created entity
typedef std::function<EntityWrapper(EntityWrapper, boost::filesystem::path)> OnEntityImport_t;
void SetEntityImportCallback(OnEntityImport_t f) { m_OnEntityImport = f; }
// Called when the user means to save an entity to file.
// Permitted to throw exceptions on save failure.
typedef std::function<void(EntityWrapper, boost::filesystem::path)> OnEntitySave_t;
void SetEntitySaveCallback(OnEntitySave_t f) { m_OnEntitySave = f; }
// Called when the user means to create a new entity.
// @param EntityWrapper The parent of the entity to be created
// @return EntityWrapper The newly created entity
typedef std::function<EntityWrapper(EntityWrapper)> OnEntityCreate_t;
void SetEntityCreateCallback(OnEntityCreate_t f) { m_OnEntityCreate = f; }
// Called when the user means to delete an entity.
typedef std::function<void(EntityWrapper)> OnEntityDelete_t;
void SetEntityDeleteCallback(OnEntityDelete_t f) { m_OnEntityDelete = f; }
// Called when the user means to change the parent of an entity.
typedef std::function<void(EntityWrapper, EntityWrapper)> OnEntityChangeParent_t;
void SetEntityChangeParentCallback(OnEntityChangeParent_t f) { m_OnEntityChangeParent = f; }
// Called when the user means to rename an entity.
typedef std::function<void(EntityWrapper, const std::string&)> OnEntityChangeName_t;
void SetEntityChangeNameCallback(OnEntityChangeName_t f) { m_OnEntityChangeName = f; }
// Called when the user means to attach a new component to an entity.
typedef std::function<void(EntityWrapper, const std::string&)> OnComponentAttach_t;
void SetComponentAttachCallback(OnComponentAttach_t f) { m_OnComponentAttach = f; }
// Called when the user means to delete a component off an entity.
typedef std::function<void(EntityWrapper, const std::string&)> OnComponentDelete_t;
void SetComponentDeleteCallback(OnComponentDelete_t f) { m_OnComponentDelete = f; }
// Called when the user selects a widget mode.
typedef std::function<void(WidgetMode)> OnWidgetMode_t;
void SetWidgetModeCallback(OnWidgetMode_t f) { m_OnWidgetMode = f; }
private:
World* m_World;
EventBroker* m_EventBroker;
struct EntityFileInfo
{
boost::filesystem::path Path;
bool Dirty = false;
};
// Config variables
const boost::filesystem::path m_DefaultEntityPath = boost::filesystem::path("Schema") / boost::filesystem::path("Entities");
// State
EntityWrapper m_CurrentSelection = EntityWrapper::Invalid;
std::unordered_map<EntityWrapper, EntityFileInfo> m_EntityFiles;
EntityWrapper m_CurrentlyDragging = EntityWrapper::Invalid;
std::string m_LastErrorMessage;
WidgetMode m_CurrentWidgetMode = WidgetMode::Translate;
std::set<std::string> m_ModalsToOpen;
std::map<std::string, boost::any> m_ModalData;
// Callbacks
OnEntitySelectedCallback_t m_OnEntitySelected = nullptr;
OnEntityImport_t m_OnEntityImport = nullptr;
OnEntitySave_t m_OnEntitySave = nullptr;
OnEntityCreate_t m_OnEntityCreate = nullptr;
OnEntityDelete_t m_OnEntityDelete = nullptr;
OnEntityChangeParent_t m_OnEntityChangeParent = nullptr;
OnEntityChangeName_t m_OnEntityChangeName = nullptr;
OnComponentAttach_t m_OnComponentAttach = nullptr;
OnComponentDelete_t m_OnComponentDelete = nullptr;
OnWidgetMode_t m_OnWidgetMode = nullptr;
// Events
EventRelay<EditorGUI, Events::KeyDown> m_EKeyDown;
bool OnKeyDown(const Events::KeyDown& e);
// Utility functions
boost::filesystem::path fileOpenDialog();
boost::filesystem::path fileSaveDialog();
const std::string formatEntityName(EntityWrapper entity);
GLuint tryLoadTexture(std::string filePath);
void openModal(const std::string& modal);
// Entity file handling methods
void entityImport(World* world);
void entitySave(EntityWrapper entity, bool saveAs = false);
void entityCreate(World* world, EntityWrapper parent);
void entityDelete(EntityWrapper entity);
void entityChangeParent(EntityWrapper entity, EntityWrapper parent);
// UI drawing methods
void drawMenu();
void drawTools();
void drawEntities(World* world);
void drawEntitiesRecursive(World* world, EntityID parent);
bool drawEntityNode(EntityWrapper entity);
void drawComponents(EntityWrapper entity);
bool drawComponentNode(EntityWrapper entity, const ComponentInfo& componentType);
bool drawComponentField(ComponentWrapper& c, const ComponentInfo::Field_t& field);
bool drawComponentField_Vector(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_Color(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_int(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_enum(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_float(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_double(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_bool(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_string(ComponentWrapper &c, const ComponentInfo::Field_t &field);
void drawModals();
// Custom UI elements
bool createDeleteButton(const std::string& componentType);
void createWidgetToolButton(WidgetMode mode);
};
#endif
@@ -1,27 +0,0 @@
#ifndef EditorRenderSystem_h__
#define EditorRenderSystem_h__
#include "../Core/System.h"
#include "../Rendering/IRenderer.h"
#include "../Rendering/ModelJob.h"
#include "../Rendering/Camera.h"
#include "../Rendering/ESetCamera.h"
class EditorRenderSystem : public ImpureSystem
{
public:
EditorRenderSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame);
virtual void Update(double dt) override;
private:
IRenderer* m_Renderer;
RenderFrame* m_RenderFrame;
Camera* m_EditorCamera;
EntityWrapper m_CurrentCamera = EntityWrapper::Invalid;
EventRelay<EditorRenderSystem, Events::SetCamera> m_ESetCamera;
bool OnSetCamera(Events::SetCamera& e);
};
#endif
-29
View File
@@ -1,29 +0,0 @@
#include <numeric>
#include <iomanip>
#include <imgui/imgui.h>
#include "../Common.h"
#include "../GLM.h"
#include "../OpenGL.h"
class EditorStats
{
public:
EditorStats();
void Draw(double dt);
private:
// FPS graph
const unsigned int m_SampleSize = 100;
unsigned int m_FrameCount = 0;
std::vector<double> m_FrameTimes;
double m_TimeAccumulator = 0.0;
double m_AveragedSamplesPerSecond = 10.0;
const unsigned int m_AveragedSampleSize = 100;
unsigned int m_CurrentAveragedSampleIndex = 0;
std::vector<double> m_AveragedSamples;
void drawFPSGraph(double dt);
void drawRAMUsage(double dt);
void drawVRAMStats(double dt);
};
+74 -39
View File
@@ -1,59 +1,94 @@
#include <imgui/imgui.h>
#include <glm/gtx/common.hpp>
#include <boost/filesystem/path.hpp>
#include <nativefiledialog/nfd.h>
#include "../Core/System.h" #include "../Core/System.h"
#include "../Core/EMousePress.h"
#include "../Core/EMouseRelease.h"
#include "../Core/EMouseMove.h"
#include "../Core/ConfigFile.h"
#include "../Input/EInputCommand.h"
#include "../Rendering/IRenderer.h" #include "../Rendering/IRenderer.h"
#include "../Rendering/Camera.h" #include "../Rendering/EPicking.h"
#include "../Rendering/DebugCameraInputController.h" #include "../Core/EFileDropped.h"
#include "../Rendering/ESetCamera.h" #include "../Rendering/RenderQueueFactory.h"
#include "../Core/World.h"
#include "../Core/SystemPipeline.h"
#include "../Core/ResourceManager.h"
#include "../Core/EntityFilePreprocessor.h" #include "../Core/EntityFilePreprocessor.h"
#include "../Core/EntityFileParser.h" #include "../Core/EntityFileParser.h"
#include "../Core/EntityFileWriter.h" #include "../Core/EntityFileWriter.h"
#include "../Core/EMousePress.h"
#include "EditorGUI.h"
#include "EditorStats.h"
class EditorSystem : public ImpureSystem class EditorSystem : public ImpureSystem
{ {
public: public:
EditorSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame); EditorSystem(EventBroker* eventBroker, IRenderer* renderer);
~EditorSystem();
void Update(double dt); virtual void Update(World* world, double dt) override;
private: private:
IRenderer* m_Renderer; IRenderer* m_Renderer;
RenderFrame* m_RenderFrame; World* m_World = nullptr;
World* m_EditorWorld;
SystemPipeline* m_EditorWorldSystemPipeline;
Camera* m_EditorCamera;
EntityWrapper m_Camera = EntityWrapper::Invalid;
DebugCameraInputController<EditorSystem>* m_DebugCameraInputController;
EditorGUI* m_EditorGUI;
EditorStats* m_EditorStats;
// State bool m_Enabled;
EditorGUI::WidgetMode m_WidgetMode = EditorGUI::WidgetMode::Translate; bool m_Visible;
EntityWrapper m_Widget = EntityWrapper::Invalid; boost::filesystem::path m_DefaultEntityDir;
EntityWrapper m_CurrentSelection = EntityWrapper::Invalid; boost::filesystem::path m_CurrentFile;
std::vector<glm::vec2> m_PickingQueue;
// Utility functions enum class WidgetMode
EntityWrapper importEntity(EntityWrapper parent, boost::filesystem::path filePath); {
void setWidgetMode(EditorGUI::WidgetMode mode); None,
Translate,
Rotate,
Scale
} m_WidgetMode = WidgetMode::None;
// GUI callbacks enum class WidgetSpace
void OnEntitySelected(EntityWrapper entity); {
void OnEntitySave(EntityWrapper entity, boost::filesystem::path filePath); Local,
EntityWrapper OnEntityCreate(EntityWrapper parent); Global
void OnEntityDelete(EntityWrapper entity); } m_WidgetSpace = WidgetSpace::Global;
void OnEntityChangeParent(EntityWrapper entity, EntityWrapper parent);
void OnEntityChangeName(EntityWrapper entity, const std::string& name);
void OnComponentAttach(EntityWrapper entity, const std::string& componentType);
void OnComponentDelete(EntityWrapper entity, const std::string& componentType);
// Events EntityID m_Widget = EntityID_Invalid;
EntityID m_WidgetX = EntityID_Invalid;
EntityID m_WidgetPlaneX = EntityID_Invalid;
EntityID m_WidgetY = EntityID_Invalid;
EntityID m_WidgetPlaneY = EntityID_Invalid;
EntityID m_WidgetZ = EntityID_Invalid;
EntityID m_WidgetPlaneZ = EntityID_Invalid;
EntityID m_WidgetOrigin = EntityID_Invalid;
glm::vec3 m_WidgetCurrentAxis;
float m_WidgetPickingDepth = 0.f;
EntityID m_Selection = EntityID_Invalid;
EntityID m_LastSelection = EntityID_Invalid;
EntityID m_UIDraggingEntity = EntityID_Invalid;
glm::vec3 m_Position;
std::string m_LastDroppedFile;
static boost::filesystem::path openDialog(boost::filesystem::path defaultPath);
static boost::filesystem::path saveDialog(boost::filesystem::path defaultPath);
EventRelay<EditorSystem, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand& e);
EventRelay<EditorSystem, Events::MouseRelease> m_EMouseRelease;
bool OnMouseRelease(const Events::MouseRelease& e);
EventRelay<EditorSystem, Events::MousePress> m_EMousePress; EventRelay<EditorSystem, Events::MousePress> m_EMousePress;
bool OnMousePress(const Events::MousePress& e); bool OnMousePress(const Events::MousePress& e);
EventRelay<EditorSystem, Events::WidgetDelta> m_EWidgetDelta; EventRelay<EditorSystem, Events::MouseMove> m_EMouseMove;
bool OnWidgetDelta(const Events::WidgetDelta& e); bool OnMouseMove(const Events::MouseMove& e);
EventRelay<EditorSystem, Events::Picking> m_EPicking;
bool OnPicking(const Events::Picking& e);
EventRelay<EditorSystem, Events::FileDropped> m_EFileDropped;
bool OnFileDropped(const Events::FileDropped& e);
void createWidget();
void updateWidget();
void setWidgetMode(WidgetMode newMode);
void setWidgetSpace(WidgetSpace space);
void drawUI(World* world, double dt);
bool createDeleteButton(std::string componentType);
bool createEntityNode(World* world, EntityID entity);
void changeParent(EntityID entity, EntityID newParent);
void fileImport(World* world);
void fileSave(World* world);
void fileSaveAs(World* world);
}; };
@@ -1,49 +0,0 @@
#ifndef EditorWidgetSystem_h__
#define EditorWidgetSystem_h__
#include <imgui/imgui.h>
#include "../GLM.h"
#include "../Core/System.h"
#include "../Rendering/IRenderer.h"
#include "../Rendering/Util/ScreenCoords.h"
#include "../Core/EMouseMove.h"
#include "../Core/EMousePress.h"
#include "../Core/EMouseRelease.h"
namespace Events
{
struct WidgetDelta : Event
{
glm::vec3 Translation;
glm::vec3 Rotation;
glm::vec3 Scale;
};
}
class EditorWidgetSystem : public ImpureSystem, PureSystem
{
public:
EditorWidgetSystem(World* world, EventBroker* eventBroker, IRenderer* renderer);
virtual void Update(double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cEditorWidget, double dt) override;
private:
IRenderer* m_Renderer;
// State
EntityWrapper m_PickEntity = EntityWrapper::Invalid;
PickData m_PickData;
glm::vec2 m_MouseDelta;
EventRelay<EditorWidgetSystem, Events::MouseMove> m_EMouseMove;
bool OnMouseMove(const Events::MouseMove& e);
EventRelay<EditorWidgetSystem, Events::MousePress> m_EMousePress;
bool OnMousePress(const Events::MousePress& e);
EventRelay<EditorWidgetSystem, Events::MouseRelease> m_EMouseRelease;
bool OnMouseRelease(const Events::MouseRelease& e);
};
#endif
+1 -2
View File
@@ -7,5 +7,4 @@
#include <glm/gtx/rotate_vector.hpp> #include <glm/gtx/rotate_vector.hpp>
#include <glm/gtc/quaternion.hpp> #include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp> #include <glm/gtx/quaternion.hpp>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/projection.hpp>
+1 -1
View File
@@ -40,7 +40,7 @@ public:
m_TexturePressed = resourceName; m_TexturePressed = resourceName;
} }
void Draw(RenderScene& rq) override void Draw(RenderQueueCollection& rq) override
{ {
if (m_Texture == nullptr && !m_TextureReleased.empty()) { if (m_Texture == nullptr && !m_TextureReleased.empty()) {
SetTexture(m_TextureReleased); SetTexture(m_TextureReleased);
+2 -2
View File
@@ -212,7 +212,7 @@ public:
virtual void Update(double dt) { } virtual void Update(double dt) { }
void DrawLayered(RenderScene& rq) void DrawLayered(RenderQueueCollection& rq)
{ {
if (this->Hidden()) if (this->Hidden())
return; return;
@@ -232,7 +232,7 @@ public:
} }
} }
virtual void Draw(RenderScene& rq) { } virtual void Draw(RenderQueueCollection& rq) { }
protected: protected:
::EventBroker* m_EventBroker; ::EventBroker* m_EventBroker;
+1 -1
View File
@@ -16,7 +16,7 @@ public:
void EnableScissor() { m_ScissorEnabled = true; } void EnableScissor() { m_ScissorEnabled = true; }
void DisableScissor() { m_ScissorEnabled = false; } void DisableScissor() { m_ScissorEnabled = false; }
void Draw(RenderScene& rq) override void Draw(RenderQueueCollection& rq) override
{ {
if (m_Texture == nullptr) if (m_Texture == nullptr)
return; return;
-1
View File
@@ -1,7 +1,6 @@
#ifndef InputProxy_h__ #ifndef InputProxy_h__
#define InputProxy_h__ #define InputProxy_h__
#include <boost/tokenizer.hpp>
#include "../Common.h" #include "../Common.h"
#include "../Core/ResourceManager.h" #include "../Core/ResourceManager.h"
#include "../Core/ConfigFile.h" #include "../Core/ConfigFile.h"
+14 -31
View File
@@ -3,12 +3,9 @@
#include <string> #include <string>
#include <ctime> #include <ctime>
#include <limits>
#include <queue>
#include <glm/common.hpp> #include <glm/common.hpp>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <boost/shared_array.hpp>
#include "Network/Network.h" #include "Network/Network.h"
#include "Network/MessageType.h" #include "Network/MessageType.h"
@@ -18,8 +15,6 @@
#include "Core/EventBroker.h" #include "Core/EventBroker.h"
#include "Core/ConfigFile.h" #include "Core/ConfigFile.h"
#include "Input/EInputCommand.h" #include "Input/EInputCommand.h"
#include "Core/EPlayerDamage.h"
#include "Network/EInterpolate.h"
class Client : public Network class Client : public Network
{ {
@@ -28,6 +23,7 @@ public:
~Client(); ~Client();
void Start(World* world, EventBroker* eventBroker) override; void Start(World* world, EventBroker* eventBroker) override;
void Update() override; void Update() override;
void Close();
private: private:
// Assio UDP logic // Assio UDP logic
boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::asio::ip::udp::endpoint m_ReceiverEndpoint;
@@ -36,7 +32,9 @@ private:
// Sending message to server logic // Sending message to server logic
int bytesRead = -1; int bytesRead = -1;
char readBuf[INPUTSIZE] = { 0 }; char readBuf[1024] = { 0 };
int snapshotInterval = 33;
std::clock_t previousSnapshotMessage = std::clock();
// Packet loss logic // Packet loss logic
unsigned int m_PacketID = 0; unsigned int m_PacketID = 0;
@@ -47,55 +45,40 @@ private:
World* m_World; World* m_World;
std::string m_PlayerName; std::string m_PlayerName;
int m_PlayerID = -1; int m_PlayerID = -1;
EntityID m_ServerEntityID = std::numeric_limits<EntityID>::max();
bool m_IsConnected = false;
// Server Client Lookup map
// Assumes that root node for client and server is EntityID 0.
// Don't Add items to these two maps with insert, use insertIntoServerClientMaps(EntityID, EntityID)!!!!
std::unordered_map<EntityID, EntityID> m_ServerIDToClientID;
std::unordered_map<EntityID, EntityID> m_ClientIDToServerID;
// Network logic // Network logic
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
SnapshotDefinitions m_NextSnapshot; SnapshotDefinitions m_NextSnapshot;
bool m_ThreadIsRunning = true;
double m_DurationOfPingTime; double m_DurationOfPingTime;
std::clock_t m_StartPingTime; std::clock_t m_StartPingTime;
std::vector<Events::InputCommand> m_InputCommandBuffer; // Use to check if we should send disconnect message
// if game is turned of by closing window.
bool m_WasStarted = false;
// Private member functions // Private member functions
void readFromServer(); void readFromServer();
int receive(char* data, size_t length); void sendSnapshotToServer();
int receive(char* data, size_t length);
void send(Packet& packet); void send(Packet& packet);
void connect(); void connect();
void disconnect(); void disconnect();
void ping(); void ping();
void moveMessageHead(char*& data, size_t& length, size_t stepSize);
void parseMessageType(Packet& packet); void parseMessageType(Packet& packet);
void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType); void parseEventMessage(Packet& packet);
void parseConnect(Packet& packet); void parseConnect(Packet& packet);
void parsePlayerConnected(Packet& packet);
void parsePing(); void parsePing();
void parseServerPing(); void parseServerPing();
void InterpolateFields(Packet & packet, const ComponentInfo & componentInfo, const EntityID & entityID, const std::string & componentType);
void parseSnapshot(Packet& packet); void parseSnapshot(Packet& packet);
void identifyPacketLoss(); void identifyPacketLoss();
bool hasServerTimedOut(); bool isConnected();
EntityID createPlayer(); EntityID createPlayer();
void sendInputCommands();
void becomePlayer();
// Mapping Logic
// Returns if local EntityID exist in map
bool clientServerMapsHasEntity(EntityID clientEntityID);
// Returns if server EntityID exist in map
bool serverClientMapsHasEntity(EntityID serverEntityID);
void insertIntoServerClientMaps(EntityID serverEntityID, EntityID clientEntityID);
// Events // Events
EventBroker* m_EventBroker; EventBroker* m_EventBroker;
EventRelay<Client, Events::InputCommand> m_EInputCommand; EventRelay<Client, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand& e); bool OnInputCommand(const Events::InputCommand &e);
EventRelay<Client, Events::PlayerDamage> m_EPlayeDamage;
bool OnPlayerDamage(const Events::PlayerDamage& e);
}; };
#endif #endif
-20
View File
@@ -1,20 +0,0 @@
#ifndef Events_Interpolate_h__
#define Events_Interpolate_h__
#include <boost/shared_array.hpp>
#include "Core/EventBroker.h"
#include "Core/Entity.h"
namespace Events
{
struct Interpolate : Event
{
EntityID Entity;
boost::shared_array<char> DataArray;
};
}
#endif
+1 -4
View File
@@ -11,10 +11,7 @@ enum class MessageType
ServerPing, ServerPing,
Message, Message,
Snapshot, Snapshot,
OnInputCommand, Event,
OnPlayerDamage,
PlayerConnected,
BecomePlayer
}; };
#endif #endif
+1 -2
View File
@@ -6,8 +6,7 @@
#include "Network/Packet.h" #include "Network/Packet.h"
#define MAXCONNECTIONS 8 #define MAXCONNECTIONS 8
#define INPUTSIZE 4097 #define INPUTSIZE 128
#define TIMEOUTMS 15000
class Network class Network
{ {
+5 -11
View File
@@ -14,18 +14,15 @@ public:
Packet(MessageType type, unsigned int& packetID); Packet(MessageType type, unsigned int& packetID);
// Used to create packet from already existing data buffer. // Used to create packet from already existing data buffer.
Packet(char* data, const int sizeOfPacket); Packet(char* data, const int sizeOfPacket);
Packet(MessageType type);
~Packet(); ~Packet();
void Init(MessageType type, unsigned int& packetID);
// Add primitive types like int, float, char... // Add primitive types like int, float, char...
template<typename T> template<typename T>
void WritePrimitive(T val) void WritePrimitive(T val)
{ {
// Check if we are trying to add more than the package can fit. // Check if we are trying to add more than the package can fit.
if (m_MaxPacketSize < m_Offset + sizeof(T)) { if (m_MaxPacketSize < m_Offset + sizeof(T)) {
LOG_WARNING("Packet AddPrimitive(): You are trying to add more than we have allocated for! New size is %i bytes\n", m_MaxPacketSize*2); LOG_WARNING("Packet AddPrimitive(): You are trying to add more than we have allocated for!");
resizeData();
} }
memcpy(m_Data + m_Offset, &val, sizeof(T)); memcpy(m_Data + m_Offset, &val, sizeof(T));
m_Offset += sizeof(T); m_Offset += sizeof(T);
@@ -44,24 +41,21 @@ public:
return returnValue; return returnValue;
} }
// Add a string to the message // Add a string to the message
void WriteString(const std::string& str); void WriteString(std::string str);
// Add data to the message // Add data to the message
void WriteData(char* data, int sizeOfData); void WriteData(char* data, int sizeOfData);
// Pops the first element as if it was a string. // Pops the first element as if it was a string.
std::string ReadString(); std::string ReadString();
char* ReadData(int SizeOfData); char* ReadData(int SizeOfData);
void ChangePacketID(unsigned int& packetID);
int Size() { return m_Offset; }; int Size() { return m_Offset; };
char* Data() { return m_Data; }; char* Data() { return m_Data; };
unsigned int DataReadSize() { return m_ReturnDataOffset; }
unsigned int MaxSize() { return m_MaxPacketSize; }
private: private:
char* m_Data; char* m_Data;
unsigned int m_ReturnDataOffset = 0; unsigned int m_ReturnDataOffset = 0;
int m_Offset = 0; int m_Offset = 0;
unsigned int m_MaxPacketSize = 512; unsigned int m_MaxPacketSize = 128;
void resizeData();
}; };
#endif #endif
@@ -6,8 +6,6 @@ struct PlayerDefinition {
int EntityID = -1; int EntityID = -1;
std::string Name = ""; std::string Name = "";
boost::asio::ip::udp::endpoint Endpoint; boost::asio::ip::udp::endpoint Endpoint;
unsigned int PacketID;
std::clock_t StopTime;
}; };
#endif #endif
+19 -15
View File
@@ -11,9 +11,7 @@
#include "Network/PlayerDefinition.h" #include "Network/PlayerDefinition.h"
#include "Core/World.h" #include "Core/World.h"
#include "Core/EventBroker.h" #include "Core/EventBroker.h"
#include "../Network/Network.h" #include "Network/Network.h"
#include "Input/EInputCommand.h"
#include "Core/EPlayerDamage.h"
class Server : public Network class Server : public Network
{ {
@@ -22,16 +20,17 @@ public:
~Server(); ~Server();
void Start(World* m_world, EventBroker *eventBroker) override; void Start(World* m_world, EventBroker *eventBroker) override;
void Update() override; void Update() override;
void Close();
private: private:
// UDP logic // UDP logic
boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::asio::ip::udp::endpoint m_ReceiverEndpoint;
boost::asio::io_service m_IOService; boost::asio::io_service m_IOService;
boost::asio::ip::udp::socket m_Socket; boost::asio::ip::udp::socket m_Socket;
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
// Sending messages to client logic // Sending messages to client logic
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS]; char readBuffer[1024] = { 0 };
std::vector<PlayerDefinition> m_ConnectedUsers;
char readBuffer[INPUTSIZE] = { 0 };
int bytesRead = 0; int bytesRead = 0;
// time for previouse message // time for previouse message
std::clock_t previousePingMessage = std::clock(); std::clock_t previousePingMessage = std::clock();
@@ -44,38 +43,43 @@ private:
//Timers //Timers
std::clock_t m_StartPingTime; std::clock_t m_StartPingTime;
std::clock_t m_StopTimes[8];
// Game logic // Game logic
World* m_World; World* m_World;
EventBroker* m_EventBroker; EventBroker* m_EventBroker;
// vec.size() = ammount of players to create, stores playerID's
std::vector<unsigned int> m_PlayersToCreate;
// Packet loss logic // Packet loss logic
unsigned int m_PacketID = 0; unsigned int m_PacketID;
unsigned int m_PreviousPacketID = 0; unsigned int m_PreviousPacketID;
unsigned int m_SendPacketID;
// Close logic
bool m_ThreadIsRunning = true;
// Private member functions // Private member functions
int receive(char* data, size_t length); int receive(char* data, size_t length);
void readFromClients(); void readFromClients();
void send(Packet& packet, int playerID); void send(Packet& packet, int playerID);
void send(Packet& packet); void send(Packet& packet);
void moveMessageHead(char*& data, size_t& length, size_t stepSize);
void broadcast(std::string message);
void broadcast(Packet& packet); void broadcast(Packet& packet);
void sendSnapshot(); void sendSnapshot();
void sendPing(); void sendPing();
void checkForTimeOuts(); void checkForTimeOuts();
void disconnect(int i); void disconnect(int i);
void parseMessageType(Packet& packet); void parseMessageType(Packet& packet);
void parseOnInputCommand(Packet& packet); void parseEvent(Packet& packet);
void parseOnPlayerDamage(Packet& packet);
void parseConnect(Packet& packet); void parseConnect(Packet& packet);
void parseDisconnect(); void parseDisconnect();
void parseClientPing(); void parseClientPing();
void parseServerPing(); void parseServerPing();
void parseSnapshot(Packet& packet);
void identifyPacketLoss(); void identifyPacketLoss();
void createPlayer(); EntityID createPlayer();
int GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint);
// Debug event
EventRelay<Server, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand& e);
}; };
#endif #endif
+1 -1
View File
@@ -3,7 +3,7 @@
#include "../Core/ResourceManager.h" #include "../Core/ResourceManager.h"
class BaseTexture : public ThreadUnsafeResource class BaseTexture : public Resource
{ {
friend class ResourceManager; friend class ResourceManager;
+8 -8
View File
@@ -2,7 +2,6 @@
#define Camera_h__ #define Camera_h__
#include "../GLM.h" #include "../GLM.h"
#include "../Core/Util/Rectangle.h"
class Camera class Camera
{ {
@@ -27,11 +26,13 @@ public:
glm::quat Orientation() const { return m_Orientation; } glm::quat Orientation() const { return m_Orientation; }
void SetOrientation(glm::quat val); void SetOrientation(glm::quat val);
glm::mat4 ProjectionMatrix() const { return m_ProjectionMatrix; } /*float Pitch() const { return m_Pitch; }
void SetProjectionMatrix(glm::mat4 val); void Pitch(float val);
float Yaw() const { return m_Yaw; }
void Yaw(float val);*/
glm::mat4 ProjectionMatrix() const { return m_ProjectionMatrix; }
glm::mat4 ViewMatrix() const { return m_ViewMatrix; } glm::mat4 ViewMatrix() const { return m_ViewMatrix; }
void SetViewMatrix(glm::mat4 val);
float AspectRatio() const { return m_AspectRatio; } float AspectRatio() const { return m_AspectRatio; }
void SetAspectRatio(float val); void SetAspectRatio(float val);
@@ -45,12 +46,11 @@ public:
float FarClip() const { return m_FarClip; } float FarClip() const { return m_FarClip; }
void SetFarClip(float val); void SetFarClip(float val);
void UpdateViewMatrix();
void UpdateProjectionMatrix();
glm::vec2 WorldToScreen(glm::vec3 worldCoord, Rectangle resolution);
private: private:
void UpdateViewMatrix();
void UpdateProjectionMatrix();
glm::vec3 m_Position; glm::vec3 m_Position;
glm::quat m_Orientation; glm::quat m_Orientation;
@@ -1,10 +1,5 @@
#ifndef DebugCameraInputController_h__
#define DebugCameraInputController_h__
#include <imgui/imgui.h> #include <imgui/imgui.h>
#include "../Input/FirstPersonInputController.h" #include "../Input/FirstPersonInputController.h"
#include "../Core/EMousePress.h"
#include "../Core/EMouseRelease.h"
template <typename EventContext> template <typename EventContext>
class DebugCameraInputController : public FirstPersonInputController<EventContext> class DebugCameraInputController : public FirstPersonInputController<EventContext>
@@ -12,13 +7,7 @@ class DebugCameraInputController : public FirstPersonInputController<EventContex
public: public:
DebugCameraInputController(EventBroker* eventBroker, unsigned int playerID) DebugCameraInputController(EventBroker* eventBroker, unsigned int playerID)
: FirstPersonInputController(eventBroker, playerID) : FirstPersonInputController(eventBroker, playerID)
{ { }
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &DebugCameraInputController::OnMousePress);
EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &DebugCameraInputController::OnMouseRelease);
}
void SetPosition(const glm::vec3 position) { m_Position = position; }
void SetOrientation(const glm::quat orientation) { m_Orientation = orientation; }
const glm::vec3 Position() const { return m_Position; } const glm::vec3 Position() const { return m_Position; }
void SetBaseSpeed(float speed) { m_BaseSpeed = speed; } void SetBaseSpeed(float speed) { m_BaseSpeed = speed; }
@@ -27,6 +16,17 @@ public:
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
if (e.Command == "PrimaryFire") {
if (e.Value > 0) {
if (!io.WantCaptureMouse) {
LockMouse();
}
} else {
UnlockMouse();
}
return false;
}
if (!io.WantCaptureKeyboard) { if (!io.WantCaptureKeyboard) {
if (e.Command == "Right") { if (e.Command == "Right") {
float value = std::max(-1.f, std::min(e.Value, 1.f)); float value = std::max(-1.f, std::min(e.Value, 1.f));
@@ -60,25 +60,4 @@ protected:
glm::vec3 m_Velocity = glm::vec3(0, 0, 0); glm::vec3 m_Velocity = glm::vec3(0, 0, 0);
float m_BaseSpeed = 2.0f; float m_BaseSpeed = 2.0f;
float m_Speed = m_BaseSpeed; float m_Speed = m_BaseSpeed;
EventRelay<EventContext, Events::MousePress> m_EMousePress; };
bool OnMousePress(const Events::MousePress& e)
{
if (e.Button == GLFW_MOUSE_BUTTON_2) {
ImGuiIO& io = ImGui::GetIO();
if (!io.WantCaptureMouse) {
LockMouse();
}
}
return true;
}
EventRelay<EventContext, Events::MouseRelease> m_EMouseRelease;
bool OnMouseRelease(const Events::MouseRelease& e)
{
if (e.Button == GLFW_MOUSE_BUTTON_2) {
UnlockMouse();
}
return true;
}
};
#endif
@@ -1,35 +0,0 @@
#ifndef DirectionalLightJob_h__
#define DirectionalLightJob_h__
#include <cstdint>
#include "../Common.h"
#include "../GLM.h"
#include "../Core/ComponentWrapper.h"
#include "RenderJob.h"
#include "../Core/Transform.h"
#include "../Core/World.h"
struct DirectionalLightJob : RenderJob
{
DirectionalLightJob(ComponentWrapper transformComponent, ComponentWrapper directionalLightComponent, World* m_World)
: RenderJob()
{
Direction = glm::vec4(0,0,-1,0) * glm::inverse(Transform::AbsoluteOrientation(m_World, transformComponent.EntityID));
//Direction = glm::vec4((glm::vec3)directionalLightComponent["Direction"], 0.f);
Color = (glm::vec4)directionalLightComponent["Color"];
Intensity = (double)directionalLightComponent["Intensity"];
};
glm::vec4 Direction;
glm::vec4 Color;
float Intensity;
void CalculateHash() override
{
Hash = 0;
}
};
#endif
-53
View File
@@ -1,53 +0,0 @@
#ifndef DrawBloomPass_h__
#define DrawBloomPass_h__
#include "IRenderer.h"
#include "DrawBloomPassState.h"
//#include "LightCullingPass.h" Finalpass om den skall skickas in
#include "FrameBuffer.h"
#include "ShaderProgram.h"
//#include "Util/UnorderedMapVec2.h"
#include "Texture.h"
class DrawBloomPass
{
public:
DrawBloomPass(IRenderer* renderer /* ,Texture or finalpass*/ );
~DrawBloomPass() { }
void InitializeTextures();
void InitializeFrameBuffers();
void InitializeShaderPrograms();
void InitializeBuffers();
void ClearBuffer();
void FillGaussianBuffer(FrameBuffer* fb);
void Draw(GLuint texture);
//Getters
//Return the blurred result of the texture that was sent into draw
GLuint GaussianTexture() const { return m_GaussianTexture_vert; }
private:
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
Texture* m_WhiteTexture;
Model* m_ScreenQuad;
const IRenderer* m_Renderer;
//const LightCullingPass* m_LightCullingPass
GLuint m_iterations = 9;
GLuint m_GaussianTexture_horiz;
GLuint m_GaussianTexture_vert;
FrameBuffer m_GaussianFrameBuffer_horiz;
FrameBuffer m_GaussianFrameBuffer_vert;
ShaderProgram* m_GaussianProgram_horiz;
ShaderProgram* m_GaussianProgram_vert;
};
#endif
@@ -1,15 +0,0 @@
#ifndef DrawBloomPassState_h__
#define DrawBloomPassState_h__
#include "Rendering/RenderState.h"
class DrawBloomPassState : public RenderState
{
public:
DrawBloomPassState();
~DrawBloomPassState();
private:
};
#endif
@@ -1,29 +0,0 @@
#ifndef DrawColorCorrectionPass_h__
#define DrawColorCorrectionPass_h__
#include "IRenderer.h"
#include "DrawScreenQuadPassState.h"
#include "FrameBuffer.h"
#include "ShaderProgram.h"
//#include "Util/UnorderedMapVec2.h"
#include "Texture.h"
class DrawColorCorrectionPass
{
public:
DrawColorCorrectionPass(IRenderer* renderer);
~DrawColorCorrectionPass() { }
void InitializeFrameBuffers();
void InitializeShaderPrograms();
void Draw(GLuint sceneTexture, GLuint bloomTexture);
private:
const IRenderer* m_Renderer;
ShaderProgram* m_ColorCorrectionProgram;
Model* m_ScreenQuad;
GLfloat m_Exposure;
};
#endif
-48
View File
@@ -1,48 +0,0 @@
#ifndef DrawFinalPass_h__
#define DrawFinalPass_h__
#include "IRenderer.h"
#include "DrawFinalPassState.h"
#include "LightCullingPass.h"
#include "FrameBuffer.h"
#include "ShaderProgram.h"
#include "Util/UnorderedMapVec2.h"
#include "Texture.h"
class DrawFinalPass
{
public:
DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCullingPass);
~DrawFinalPass() { }
void InitializeTextures();
void InitializeFrameBuffers();
void InitializeShaderPrograms();
void Draw(RenderScene& scene);
void ClearBuffer();
//Return the texture that is used in later stages to apply the bloom effect
GLuint BloomTexture() const { return m_BloomTexture; }
//Return the texture with diffuse and lighting of the scene.
GLuint SceneTexture() const { return m_SceneTexture; }
FrameBuffer* FinalPassFrameBuffer() { return &m_FinalPassFrameBuffer; }
private:
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
void GenerateMipMapTexture(GLuint* texture, GLenum wrapping, glm::vec2 dimensions, GLint format, GLenum type, GLint numMipMaps) const;
Texture* m_WhiteTexture;
Texture* m_BlackTexture;
FrameBuffer m_FinalPassFrameBuffer;
GLuint m_BloomTexture;
GLuint m_SceneTexture;
GLuint m_DepthBuffer;
const IRenderer* m_Renderer;
const LightCullingPass* m_LightCullingPass;
ShaderProgram* m_ForwardPlusProgram;
};
#endif
@@ -1,15 +0,0 @@
#ifndef DrawFinalPassState_h__
#define DrawFinalPassState_h__
#include "Rendering/RenderState.h"
class DrawFinalPassState : public RenderState
{
public:
DrawFinalPassState(GLuint frameBuffer);
~DrawFinalPassState();
private:
};
#endif
+36
View File
@@ -0,0 +1,36 @@
#ifndef DrawScenePass_h__
#define DrawScenePass_h__
#include "IRenderer.h"
#include "DrawScenePassState.h"
#include "FrameBuffer.h"
#include "ShaderProgram.h"
#include "Util/UnorderedMapVec2.h"
#include "Texture.h"
class DrawScenePass
{
public:
DrawScenePass(IRenderer* renderer);
~DrawScenePass() { }
void InitializeTextures();
void InitializeFrameBuffers();
void InitializeShaderPrograms();
void Draw(RenderQueueCollection& rq);
//Getters
private:
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
Texture* m_WhiteTexture;
const IRenderer* m_Renderer;
ShaderProgram* m_BasicForwardProgram;
};
#endif
@@ -0,0 +1,15 @@
#ifndef DrawScenePassState_h__
#define DrawScenePassState_h__
#include "Rendering/RenderState.h"
class DrawScenePassState : public RenderState
{
public:
DrawScenePassState();
~DrawScenePassState();
private:
};
#endif
@@ -1,28 +0,0 @@
#ifndef DrawScreenQuadPass_h__
#define DrawScreenQuadPass_h__
#include "IRenderer.h"
#include "DrawScreenQuadPassState.h"
#include "FrameBuffer.h"
#include "ShaderProgram.h"
//#include "Util/UnorderedMapVec2.h"
#include "Texture.h"
class DrawScreenQuadPass
{
public:
DrawScreenQuadPass(IRenderer* renderer);
~DrawScreenQuadPass() { }
void InitializeFrameBuffers();
void InitializeShaderPrograms();
void Draw(GLuint texture);
private:
const IRenderer* m_Renderer;
ShaderProgram* m_DrawQuadProgram;
Model* m_ScreenQuad;
};
#endif
@@ -1,15 +0,0 @@
#ifndef DrawScreenQuadPassState_h__
#define DrawScreenQuadPassState_h__
#include "Rendering/RenderState.h"
class DrawScreenQuadPassState : public RenderState
{
public:
DrawScreenQuadPassState();
~DrawScreenQuadPassState();
private:
};
#endif
+1 -1
View File
@@ -9,7 +9,7 @@ class DummyRenderer : public IRenderer
{ {
public: public:
virtual void Initialize() override; virtual void Initialize() override;
virtual void Draw(RenderFrame& rq) override; virtual void Draw(RenderQueueCollection& rq) override;
}; };
#endif #endif
+74
View File
@@ -0,0 +1,74 @@
#ifndef Events_Picking_h__
#define Events_Picking_h__
#include "../OpenGL.h"
#include "../GLM.h"
#include "../Core/EventBroker.h"
#include "Util/ScreenCoords.h"
#include "FrameBuffer.h"
#include "../Core/Entity.h"
#include "Util/UnorderedMapVec2.h"
namespace Events
{
/** Thrown Every frame, use functions to pick*/
struct Picking : Event
{
public:
Picking(FrameBuffer* pickingBuffer, GLuint* depthBuffer, glm::mat4 projectionMatrix, glm::mat4 viewMatrix, Rectangle resolution, const std::unordered_map<glm::vec2, EntityID>* pickingColorsToEntity)
: PickingBuffer(pickingBuffer)
, DepthBuffer(depthBuffer)
, ProjectionMatrix(projectionMatrix)
, ViewMatrix(viewMatrix)
, Resolution(resolution)
, PickingColorsToEntity(pickingColorsToEntity)
{ }
struct PickData
{
//Picked Entity
EntityID Entity;
//World position of the "pick"
glm::vec3 Position;
// Depth
float Depth;
};
PickData Pick(glm::vec2 screenCoord) const
{
PickData pickData;
// Invert screen y coordinate
screenCoord.y = Resolution.Height - screenCoord.y;
ScreenCoords::PixelData data = ScreenCoords::ToPixelData(screenCoord, PickingBuffer, *DepthBuffer);
pickData.Depth = data.Depth;
auto it = PickingColorsToEntity->find(glm::vec2(data.Color[0], data.Color[1]));
if (it != PickingColorsToEntity->end()) {
pickData.Entity = it->second;
} else {
pickData.Entity = EntityID_Invalid;
}
pickData.Position = ScreenCoords::ToWorldPos(screenCoord.x, screenCoord.y, data.Depth, Resolution, ProjectionMatrix, ViewMatrix);
return pickData;
}
private:
FrameBuffer* PickingBuffer;
GLuint* DepthBuffer;
const glm::mat4 ProjectionMatrix;
const glm::mat4 ViewMatrix;
const Rectangle Resolution;
const std::unordered_map<glm::vec2, EntityID>* PickingColorsToEntity;
};
}
#endif
-17
View File
@@ -1,17 +0,0 @@
#ifndef Events_SetCamera_h__
#define Events_SetCamera_h__
#include "../Core/EventBroker.h"
#include "../Core/EntityWrapper.h"
namespace Events
{
struct SetCamera : Event
{
EntityWrapper CameraEntity;
};
}
#endif
-36
View File
@@ -1,36 +0,0 @@
#ifndef Font_h__
#define Font_h__
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include <boost/tokenizer.hpp>
#include <boost/lexical_cast.hpp>
#include "../OpenGL.h"
#include "../GLM.h"
#include "../Core/ResourceManager.h"
class Font : public Resource
{
friend class ResourceManager;
private:
Font(std::string path);
public:
struct Character {
GLuint TextureID; // ID handle of the glyph texture
glm::ivec2 Size; // Size of glyph
glm::ivec2 Bearing; // Offset from baseline to left/top of glyph
GLuint Advance; // Offset to advance to next glyph
};
int FontSize = 16;
~Font();
std::map<GLchar, Character> m_Characters;
};
#endif
+13 -15
View File
@@ -9,17 +9,6 @@
#include "Camera.h" #include "Camera.h"
#include "RenderQueue.h" #include "RenderQueue.h"
#include "Model.h" #include "Model.h"
#include "../Core/World.h" //So temp
struct PickData
{
EntityID Entity;
glm::vec3 Position; //World position
float Depth;
::Camera* Camera;
const ::World* World;
};
class IRenderer class IRenderer
{ {
@@ -31,12 +20,19 @@ public:
void SetFullscreen(bool fullscreen) { m_Fullscreen = fullscreen; } void SetFullscreen(bool fullscreen) { m_Fullscreen = fullscreen; }
bool VSYNC() const { return m_VSYNC; } bool VSYNC() const { return m_VSYNC; }
void SetVSYNC(bool vsync) { m_VSYNC = vsync; } void SetVSYNC(bool vsync) { m_VSYNC = vsync; }
::Camera* Camera() const { return m_Camera; }
void SetCamera(::Camera* camera)
{
if (camera == nullptr) {
m_Camera = m_DefaultCamera;
} else {
m_Camera = camera;
}
}
virtual void Initialize() = 0; virtual void Initialize() = 0;
virtual void Update(double dt) = 0; virtual void Update(double dt) = 0;
virtual void Draw(RenderFrame& rq) = 0; virtual void Draw(RenderQueueCollection& rq) = 0;
virtual PickData Pick(glm::vec2 screenCord) = 0;
World* m_World; //Temp world, untill viktor merge.
protected: protected:
Rectangle m_Resolution = Rectangle::Rectangle(1280, 720); Rectangle m_Resolution = Rectangle::Rectangle(1280, 720);
@@ -44,6 +40,8 @@ protected:
bool m_VSYNC = false; bool m_VSYNC = false;
int m_GLVersion[2]; int m_GLVersion[2];
std::string m_GLVendor; std::string m_GLVendor;
::Camera* m_DefaultCamera;
::Camera* m_Camera = nullptr;
GLFWwindow* m_Window = nullptr; GLFWwindow* m_Window = nullptr;
}; };
@@ -1,84 +0,0 @@
#ifndef LightCullingPass_h__
#define LightCullingPass_h__
#define TILE_SIZE 16
#define MAX_LIGHTS_PER_TILE 200
#include "IRenderer.h"
#include "LightCullingPassState.h"
#include "ShaderProgram.h"
#include "RenderQueue.h"
class LightCullingPass
{
public:
LightCullingPass(IRenderer* renderer);
~LightCullingPass();
void GenerateNewFrustum(RenderScene& scene);
void OnResolutionChange();
void SetSSBOSizes();
void CullLights(RenderScene& scene);
void FillLightList(RenderScene& scene);
GLuint FrustumSSBO() const { return m_FrustumSSBO; }
GLuint LightSSBO() const { return m_LightSSBO; }
GLuint LightGridSSBO() const { return m_LightGridSSBO; }
GLuint LightOffsetSSBO() const { return m_LightOffsetSSBO; }
GLuint LightIndexSSBO() const { return m_LightIndexSSBO; }
private:
void InitializeSSBOs();
void InitializeShaderPrograms();
const IRenderer* m_Renderer;
GLuint m_FrustumSSBO = 0;
GLuint m_LightSSBO = 0;
GLuint m_LightGridSSBO = 0;
GLuint m_LightOffsetSSBO = 0;
GLuint m_LightIndexSSBO = 0;
ShaderProgram* m_CalculateFrustumProgram;
ShaderProgram* m_LightCullProgram;
int m_NumberOfTiles = 0;
struct Plane {
glm::vec3 Normal = glm::vec3(0.f);
float d = 0;
};
struct Frustum {
Plane Planes[4];
};
Frustum* m_Frustums;
//This should be a component
struct LightSource {
glm::vec4 Position = glm::vec4(0.f);
glm::vec4 Direction = glm::vec4(10.f);
glm::vec4 Color = glm::vec4(1.f);
float Radius = 5.f;
float Intensity = 0.8f;
float Falloff = 0.3f;
enum Type_t { Zero, Point, Directional, Spot } Type;
};
std::vector<LightSource> m_LightSources;
struct LightGrid {
float Start = 0;
float Amount = 0;
glm::vec2 Padding = glm::vec2(1.f, 2.f);
};
LightGrid* m_LightGrid;
int m_LightOffset = 0;
float* m_LightIndex;
};
#endif
+1 -5
View File
@@ -4,7 +4,7 @@
#include "RawModel.h" #include "RawModel.h"
#include "../OpenGL.h" #include "../OpenGL.h"
class Model : public ThreadUnsafeResource class Model : public RawModel
{ {
friend class ResourceManager; friend class ResourceManager;
@@ -13,15 +13,11 @@ private:
public: public:
~Model(); ~Model();
const std::vector<RawModel::MaterialGroup>& MaterialGroups() const { return m_RawModel->MaterialGroups; }
const glm::mat4& Matrix() const { return m_RawModel->m_Matrix; }
const std::vector<RawModel::Vertex>& Vertices() const { return m_RawModel->m_Vertices; }
GLuint VAO; GLuint VAO;
GLuint ElementBuffer; GLuint ElementBuffer;
private: private:
RawModel* m_RawModel;
GLuint VertexBuffer; GLuint VertexBuffer;
GLuint DiffuseVertexColorBuffer; GLuint DiffuseVertexColorBuffer;
GLuint SpecularVertexColorBuffer; GLuint SpecularVertexColorBuffer;
-59
View File
@@ -1,59 +0,0 @@
#ifndef ModelJob_h__
#define ModelJob_h__
#include <cstdint>
#include "../Common.h"
#include "../GLM.h"
#include "../Core/ComponentWrapper.h"
#include "Texture.h"
#include "Model.h"
#include "RenderJob.h"
#include "../Core/ResourceManager.h"
#include "Camera.h"
#include "../Core/World.h"
#include "../Core/Transform.h"
struct ModelJob : RenderJob
{
ModelJob(Model* model, Camera* camera, glm::mat4 matrix, ::RawModel::MaterialGroup matGroup, ComponentWrapper modelComponent, World* world)
: RenderJob()
{
Model = model;
TextureID = (matGroup.Texture) ? matGroup.Texture->ResourceID : 0;
DiffuseTexture = matGroup.Texture.get();
NormalTexture = matGroup.NormalMap.get();
SpecularTexture = matGroup.SpecularMap.get();
StartIndex = matGroup.StartIndex;
EndIndex = matGroup.EndIndex;
Matrix = matrix;
Color = modelComponent["Color"];
Entity = modelComponent.EntityID;
glm::vec3 abspos = Transform::AbsolutePosition(world, modelComponent.EntityID);
glm::vec3 worldpos = glm::vec3(camera->ViewMatrix() * glm::vec4(abspos, 1));
Depth = worldpos.z;
World = world;
};
unsigned int TextureID;
unsigned int ShaderID;
EntityID Entity;
glm::mat4 Matrix;
const Texture* DiffuseTexture;
const Texture* NormalTexture;
const Texture* SpecularTexture;
float Shininess = 0.f;
glm::vec4 Color;
const ::Model* Model = nullptr;
unsigned int StartIndex = 0;
unsigned int EndIndex = 0;
World* World;
void CalculateHash() override
{
Hash = TextureID;
}
};
#endif
+6 -23
View File
@@ -1,17 +1,13 @@
#ifndef PickingPass_h__ #ifndef PickingPass_h__
#define PickingPass_h__ #define PickingPass_h__
#include "IRenderer.h" #include "IRenderer.h"
#include "PickingPassState.h" #include "PickingPassState.h"
#include "FrameBuffer.h" #include "FrameBuffer.h"
#include "ShaderProgram.h" #include "ShaderProgram.h"
#include "Util/UnorderedMapiVec2.h" #include "Util/UnorderedMapVec2.h"
#include "../Core/EventBroker.h" #include "../Core/EventBroker.h"
#include "../Core/World.h" #include "EPicking.h"
class PickingPass class PickingPass
{ {
@@ -22,18 +18,16 @@ public:
void InitializeFrameBuffers(); void InitializeFrameBuffers();
void InitializeShaderPrograms(); void InitializeShaderPrograms();
void Draw(RenderScene& scene); void Draw(RenderQueueCollection& rq);
void ClearPicking();
//Getters //Getters
const ShaderProgram& PickingProgram() const { return *m_PickingProgram; } const ShaderProgram& PickingProgram() const { return *m_PickingProgram; }
//const std::unordered_map<glm::ivec2, EntityID>& PickingColorsToEntity() const { return m_PickingColorsToEntity; } const std::unordered_map<glm::vec2, EntityID>& PickingColorsToEntity() const { return m_PickingColorsToEntity; }
GLuint PickingTexture() const { return m_PickingTexture; } GLuint PickingTexture() const { return m_PickingTexture; }
GLuint DepthBuffer() const { return m_DepthBuffer; } GLuint DepthBuffer() const { return m_DepthBuffer; }
const FrameBuffer& PickingBuffer() const { return m_PickingBuffer; } const FrameBuffer& PickingBuffer() const { return m_PickingBuffer; }
PickData Pick(glm::vec2 screenCoord);
private: private:
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const; void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
@@ -43,24 +37,13 @@ private:
const IRenderer* m_Renderer; const IRenderer* m_Renderer;
ShaderProgram* m_PickingProgram; ShaderProgram* m_PickingProgram;
Camera* m_Camera;
struct PickingInfo std::unordered_map<glm::vec2, EntityID> m_PickingColorsToEntity;
{
EntityID Entity;
const ::World* World;
::Camera* Camera;
};
std::unordered_map<glm::ivec2, PickingInfo> m_PickingColorsToEntity;
GLuint m_PickingTexture; GLuint m_PickingTexture;
GLuint m_DepthBuffer; GLuint m_DepthBuffer;
FrameBuffer m_PickingBuffer; FrameBuffer m_PickingBuffer;
int m_ColorCounter[2];
std::map<std::tuple<EntityID, const World*, Camera*>, glm::ivec2> m_EntityColors;
}; };
#endif #endif
-39
View File
@@ -1,39 +0,0 @@
#ifndef PointLightJob_h__
#define PointLightJob_h__
#include <cstdint>
#include "../Common.h"
#include "../GLM.h"
#include "../Core/ComponentWrapper.h"
#include "RenderJob.h"
#include "../Core/Transform.h"
#include "../Core/World.h"
struct PointLightJob : RenderJob
{
PointLightJob(ComponentWrapper transformComponent, ComponentWrapper pointLightComponent, World* m_World)
: RenderJob()
{
Position = glm::vec4((glm::vec3)transformComponent["Position"], 1.0f);
Position = glm::vec4(Transform::AbsolutePosition(m_World, transformComponent.EntityID), 1.f);
Color = (glm::vec4)pointLightComponent["Color"];
Radius = (double)pointLightComponent["Radius"];
Intensity = (double)pointLightComponent["Intensity"];
Falloff = (double)pointLightComponent["Falloff"];
};
glm::vec4 Position;
glm::vec4 Color;
float Radius;
float Intensity;
float Falloff;
float padding = 123;
void CalculateHash() override
{
Hash = 0;
}
};
#endif
+1 -5
View File
@@ -46,18 +46,14 @@ public:
struct MaterialGroup struct MaterialGroup
{ {
float Shininess; float Shininess;
float Transparency;
std::string TexturePath;
std::shared_ptr<::Texture> Texture; std::shared_ptr<::Texture> Texture;
std::string NormalMapPath;
std::shared_ptr<::Texture> NormalMap; std::shared_ptr<::Texture> NormalMap;
std::string SpecularMapPath;
std::shared_ptr<::Texture> SpecularMap; std::shared_ptr<::Texture> SpecularMap;
unsigned int StartIndex; unsigned int StartIndex;
unsigned int EndIndex; unsigned int EndIndex;
}; };
std::vector<MaterialGroup> MaterialGroups; std::vector<MaterialGroup> TextureGroups;
std::vector<Vertex> m_Vertices; std::vector<Vertex> m_Vertices;
std::vector<unsigned int> m_Indices; std::vector<unsigned int> m_Indices;
-31
View File
@@ -1,31 +0,0 @@
#ifndef RenderJob_h__
#define RenderJob_h__
#include <cstdint>
#include "../Common.h"
#include "../GLM.h"
#include "../Core/ComponentWrapper.h"
#include "RenderQueue.h"
struct RenderJob
{
friend class RenderQueue;
public:
float Depth;
protected:
uint64_t Hash;
virtual void CalculateHash() = 0;
bool operator<(const RenderJob& rhs)
{
return this->Hash < rhs.Hash;
}
};
#endif
+127 -42
View File
@@ -8,62 +8,147 @@
#include "../GLM.h" #include "../GLM.h"
#include "../Core/Util/Rectangle.h" #include "../Core/Util/Rectangle.h"
#include "../Core/Entity.h" #include "../Core/Entity.h"
#include "Camera.h"
#include "RenderJob.h"
#include "ModelJob.h"
#include "TextJob.h"
#include "PointLightJob.h"
#include "DirectionalLightJob.h"
struct RenderScene class Model;
class Skeleton;
class Texture;
class RenderQueue;
//TODO: Render: Remove obsolete RenderJobs and fix standard values on variables.
struct RenderJob
{ {
::Camera* Camera = nullptr; friend class RenderQueue;
std::list<std::shared_ptr<RenderJob>> ForwardJobs;
std::list<std::shared_ptr<RenderJob>> PointLightJobs;
std::list<std::shared_ptr<RenderJob>> TextJobs;
std::list<std::shared_ptr<RenderJob>> DirectionalLightJobs;
Rectangle Viewport;
bool ClearDepth = false;
void Clear() float Depth;
protected:
uint64_t Hash;
virtual void CalculateHash() = 0;
bool operator<(const RenderJob& rhs)
{ {
ForwardJobs.clear(); return this->Hash < rhs.Hash;
PointLightJobs.clear();
TextJobs.clear();
DirectionalLightJobs.clear();
} }
}; };
struct RenderFrame struct ModelJob : RenderJob
{
unsigned int ShaderID = 0;
unsigned int TextureID = 0;
//TODO: RENDERER: Not sure if the best solution for pickingColor to entity link is this
EntityID Entity;
glm::mat4 ModelMatrix;
const Texture* DiffuseTexture;
const Texture* NormalTexture;
const Texture* SpecularTexture;
float Shininess = 0.f;
glm::vec4 Color;
const Model* Model = nullptr;
unsigned int StartIndex = 0;
unsigned int EndIndex = 0;
// Animation
Skeleton* Skeleton = nullptr;
bool NoRootMotion = true;
std::string AnimationName;
double AnimationTime = 0;
void CalculateHash() override
{
Hash = TextureID;
}
};
struct SpriteJob : RenderJob
{
unsigned int ShaderID = 0;
unsigned int TextureID = 0;
glm::mat4 ModelMatrix;
const Texture* DiffuseTexture = nullptr;
const Texture* NormalTexture = nullptr;
const Texture* SpecularTexture = nullptr;
glm::vec4 Color;
void CalculateHash() override
{
Hash = TextureID;
}
};
struct PointLightJob : RenderJob
{
glm::vec3 Position;
glm::vec3 SpecularColor = glm::vec3(1, 1, 1);
glm::vec3 DiffuseColor = glm::vec3(1, 1, 1);
float Radius = 1.f;
float Intensity = 0.8f;
void CalculateHash() override
{
Hash = 0;
}
};
class RenderQueue
{ {
public: public:
template <typename T>
void Add(T &job)
{
job.CalculateHash();
Jobs.push_back(std::shared_ptr<T>(new T(job)));
m_Size++;
}
void Add(RenderScene &scene) void Sort()
{ {
RenderScenes.push_back(std::shared_ptr<RenderScene>(new RenderScene(scene))); Jobs.sort();
m_Size++; }
}
void Clear() void Clear()
{ {
RenderScenes.clear(); Jobs.clear();
m_Size = 0; m_Size = 0;
} }
int Size() const { return m_Size; } int Size() const { return m_Size; }
std::list<std::shared_ptr<RenderScene>>::const_iterator begin() std::list<std::shared_ptr<RenderJob>>::const_iterator begin()
{ {
return RenderScenes.begin(); return Jobs.begin();
} }
std::list<std::shared_ptr<RenderScene>>::const_iterator end() std::list<std::shared_ptr<RenderJob>>::const_iterator end()
{ {
return RenderScenes.end(); return Jobs.end();
} }
std::list<std::shared_ptr<RenderJob>> Jobs;
std::list<std::shared_ptr<RenderScene>> RenderScenes;
private: private:
int m_Size = 0; int m_Size = 0;
}; };
struct RenderQueueCollection
{
RenderQueue Forward;
RenderQueue Lights;
void Clear()
{
Forward.Clear();
Lights.Clear();
}
void Sort()
{
Forward.Sort();
Lights.Sort();
}
};
#endif #endif
@@ -0,0 +1,31 @@
#ifndef RenderQueueFactory_h__
#define RenderQueueFactory_h__
#include "../Core/World.h"
#include "RenderQueue.h"
#include "../Core/ResourceManager.h"
#include "Model.h"
#include "../GLM.h"
class RenderQueueFactory
{
public:
RenderQueueFactory();
void Update(World* world);
RenderQueueCollection RenderQueues() const { return m_RenderQueues; }
static glm::vec3 AbsolutePosition(World* world, EntityID entity);
static glm::quat AbsoluteOrientation(World* world, EntityID entity);
static glm::vec3 AbsoluteScale(World* world, EntityID entity);
private:
RenderQueueCollection m_RenderQueues;
void FillModels(World* world, RenderQueue* renderQueue);
void FillLights(World* world, RenderQueue* renderQueue);
glm::mat4 ModelMatrix(World* world, EntityID entity);
};
#endif
+1 -1
View File
@@ -16,10 +16,10 @@ public:
bool Disable(GLenum cap); bool Disable(GLenum cap);
bool CullFace(GLenum mode); bool CullFace(GLenum mode);
bool ClearColor(glm::vec4 color); bool ClearColor(glm::vec4 color);
bool Clear(GLbitfield mask);
bool BindFramebuffer(GLint framebuffer); bool BindFramebuffer(GLint framebuffer);
bool BlendEquation(GLenum mode); bool BlendEquation(GLenum mode);
bool BlendFunc(GLenum sfactor, GLenum dfactor); bool BlendFunc(GLenum sfactor, GLenum dfactor);
bool DepthMask(GLboolean flag);
private: private:
std::vector<std::function<void(void)>> m_ResetFunctions; std::vector<std::function<void(void)>> m_ResetFunctions;
-46
View File
@@ -1,46 +0,0 @@
#ifndef RenderSystem_h__
#define RenderSystem_h__
#include "../Core/System.h"
#include "RenderQueue.h"
#include "../GLM.h"
#include "../OpenGL.h"
#include "../Core/ResourceManager.h"
#include "ESetCamera.h"
#include "Model.h"
#include "../Core/EKeyDown.h"
#include "../Input/EInputCommand.h"
#include "Camera.h"
#include "ModelJob.h"
#include "Renderer.h"
#include "PointLightJob.h"
#include "../Core/Transform.h"
#include "DebugCameraInputController.h"
class RenderSystem : public ImpureSystem
{
public:
RenderSystem(World* world, EventBroker* eventBrokerer, const IRenderer* renderer, RenderFrame* renderFrame);
~RenderSystem();
virtual void Update(double dt) override;
private:
const IRenderer* m_Renderer;
RenderFrame* m_RenderFrame;
Camera* m_Camera;
EntityWrapper m_CurrentCamera = EntityWrapper::Invalid;
EventRelay<RenderSystem, Events::SetCamera> m_ESetCamera;
bool OnSetCamera(Events::SetCamera &event);
void fillText(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
void fillPointLights(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
void fillDirectionalLights(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
EventRelay<RenderSystem, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand& e);
void fillModels(std::list<std::shared_ptr<RenderJob>>& jobs);
void fillLight(std::list<std::shared_ptr<RenderJob>>& jobs);
};
#endif
+73 -24
View File
@@ -11,17 +11,25 @@
#include "FrameBuffer.h" #include "FrameBuffer.h"
#include "../Core/World.h" #include "../Core/World.h"
#include "PickingPass.h" #include "PickingPass.h"
#include "LightCullingPass.h" #include "DrawScenePass.h"
#include "DrawFinalPass.h" #include "DebugCameraInputController.h"
#include "DrawScreenQuadPass.h"
#include "DrawBloomPass.h"
#include "DrawColorCorrectionPass.h" #define TILE_SIZE 16
#define NUM_LIGHTS 3
enum lightType
{
Point,
Spot,
Directional,
Area
};
#include "../Core/EventBroker.h" #include "../Core/EventBroker.h"
#include "EPicking.h"
#include "ImGuiRenderPass.h" #include "ImGuiRenderPass.h"
#include "Camera.h"
#include "../Core/Transform.h"
#include "imgui/imgui.h"
#include "TextPass.h"
class Renderer : public IRenderer class Renderer : public IRenderer
{ {
@@ -32,47 +40,88 @@ public:
virtual void Initialize() override; virtual void Initialize() override;
virtual void Update(double dt) override; virtual void Update(double dt) override;
virtual void Draw(RenderFrame& frame) override; virtual void Draw(RenderQueueCollection& rq) override;
virtual PickData Pick(glm::vec2 screenCoord) override;
private: private:
//----------------------Variables----------------------// //----------------------Variables----------------------//
EventBroker* m_EventBroker; EventBroker* m_EventBroker;
TextPass* m_TextPass;
std::shared_ptr<DebugCameraInputController<Renderer>> m_DebugCameraInputController;
Texture* m_ErrorTexture; Texture* m_ErrorTexture;
Texture* m_WhiteTexture; Texture* m_WhiteTexture;
float m_CameraMoveSpeed;
Model* m_ScreenQuad; Model* m_ScreenQuad;
Model* m_UnitQuad; Model* m_UnitQuad;
Model* m_UnitSphere; Model* m_UnitSphere;
int m_DebugTextureToDraw = 0; DrawScenePass* m_DrawScenePass;
PickingPass* m_PickingPass; PickingPass* m_PickingPass;
LightCullingPass* m_LightCullingPass;
ImGuiRenderPass* m_ImGuiRenderPass; ImGuiRenderPass* m_ImGuiRenderPass;
DrawFinalPass* m_DrawFinalPass;
DrawScreenQuadPass* m_DrawScreenQuadPass;
DrawBloomPass* m_DrawBloomPass;
DrawColorCorrectionPass* m_DrawColorCorrectionPass;
//----------------------Functions----------------------// //----------------------Functions----------------------//
void InitializeWindow(); void InitializeWindow();
void InitializeShaders(); void InitializeShaders();
void InitializeTextures(); void InitializeTextures();
void InitializeSSBOs();
void InitializeRenderPasses(); void InitializeRenderPasses();
//TODO: Renderer: Get InputUpdate out of renderer //TODO: Renderer: Get InputUpdate out of renderer
void InputUpdate(double dt); void InputUpdate(double dt);
//void PickingPass(RenderQueueCollection& rq); //void PickingPass(RenderQueueCollection& rq);
//void DrawScreenQuad(GLuint textureToDraw); void DrawScreenQuad(GLuint textureToDraw);
//----------------------Forward+-----------------------//
void CalculateFrustum();
void CullLights();
//Frustum
struct Plane {
glm::vec3 Normal;
float d;
};
struct Frustum {
Plane Planes[4];
};
Frustum m_Frustums[80*45]; //TODO: Renderer: Make this change with resolution
//Lights
void TEMPCreateLights();
//TODO: Renderer: Add Directionllights, spotlights and area lights to this as type.
struct PointLight {
glm::vec4 Position = glm::vec4(0.f);
glm::vec4 Color = glm::vec4(1.f);
float Radius = 5.f;
float Intensity = 0.8f;
float Falloff = 0.3f;
float Padding = 1337;
};
PointLight m_PointLights[NUM_LIGHTS];
struct LightGrid {
int Amount;
int Start;
glm::vec2 Padding;
};
LightGrid m_LightGrid[80*45];
int m_LightOffset = 0;
int m_LightIndex[80*45*200];
//-------------------------SSBO------------------------//
GLuint m_FrustumSSBO = 0;
GLuint m_LightSSBO = 1;
GLuint m_LightGridSSBO = 2;
GLuint m_LightOffsetSSBO = 3;
GLuint m_LightIndexSSBO = 4;
static bool DepthSort(const std::shared_ptr<RenderJob> &i, const std::shared_ptr<RenderJob> &j) { return (i->Depth < j->Depth); }
void SortRenderJobsByDepth(RenderScene &scene);
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type); void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type);
//--------------------ShaderPrograms-------------------// //--------------------ShaderPrograms-------------------//
ShaderProgram* m_BasicForwardProgram; ShaderProgram* m_BasicForwardProgram;
ShaderProgram* m_DrawScreenQuadProgram;
ShaderProgram* m_CalculateFrustumProgram;
ShaderProgram* m_LightCullProgram;
}; };
#endif #endif
-58
View File
@@ -1,58 +0,0 @@
#ifndef TextJob_h__
#define TextJob_h__
#include <cstdint>
#include "../Common.h"
#include "../GLM.h"
#include "../Core/ComponentWrapper.h"
#include "Texture.h"
#include "RenderJob.h"
#include "../Core/ResourceManager.h"
#include "Font.h"
struct TextJob : RenderJob
{
TextJob(glm::mat4 matrix, Font* font, ComponentWrapper textComponent)
: RenderJob()
{
Matrix = matrix;
Color = (glm::vec4)textComponent["Color"];
Content = (std::string)textComponent["Content"];
Resource = font;
if ((int)textComponent["Alignment"] == textComponent["Alignment"].Enum("Left")) {
Alignment = AlignmentEnum::Left;
} else if ((int)textComponent["Alignment"] == textComponent["Alignment"].Enum("Right")) {
Alignment = AlignmentEnum::Right;
} else if ((int)textComponent["Alignment"] == textComponent["Alignment"].Enum("Center")) {
Alignment = AlignmentEnum::Center;
} else {
LOG_ERROR("Text alignment invalid");
Alignment = AlignmentEnum::Left;
}
};
enum class AlignmentEnum
{
Left,
Right,
Center
};
glm::mat4 Matrix;
glm::vec4 Color;
std::string Content;
Font* Resource;
AlignmentEnum Alignment;
void CalculateHash() override
{
Hash = 0;
}
};
#endif
-33
View File
@@ -1,33 +0,0 @@
#ifndef TextRenderer_h__
#define TextRenderer_h__
#include <ft2build.h>
#include FT_FREETYPE_H
#include "../OpenGL.h"
#include "../GLM.h"
#include "ShaderProgram.h"
#include "Font.h"
#include "../Core/ResourceManager.h"
#include "RenderQueue.h"
#include "TextPassState.h"
#include "FrameBuffer.h"
class TextPass
{
public:
TextPass();
void Initialize();
void Update();
void Draw(RenderScene& scene, FrameBuffer& frameBuffer);
private:
void renderText(std::string text, Font* font, TextJob::AlignmentEnum alignment, glm::vec4 color, glm::mat4 modelMatrix, glm::mat4 projectionMatrix, glm::mat4 viewMatrix);
Font* font;
GLuint VAO, VBO;
ShaderProgram* m_TextProgram;
};
#endif
-15
View File
@@ -1,15 +0,0 @@
#ifndef TextPassState_h__
#define TextPassState_h__
#include "Rendering/RenderState.h"
class TextPassState : public RenderState
{
public:
TextPassState(GLuint frameBuffer);
~TextPassState();
private:
};
#endif
-1
View File
@@ -18,7 +18,6 @@ public:
void Bind(GLenum textureUnit = GL_TEXTURE0); void Bind(GLenum textureUnit = GL_TEXTURE0);
GLuint m_Texture = 0; GLuint m_Texture = 0;
}; };
#endif #endif
@@ -1,17 +0,0 @@
#ifndef CommonFuntions_h__
#define CommonFuntions_h__
#include "../../Common.h"
#include "../../OpenGL.h"
#include "../../GLM.h"
class CommonFuntions
{
public:
CommonFuntions() = delete;
private:
};
#endif
@@ -1,24 +0,0 @@
#pragma once
#ifndef UnorderedMapiVec2_h__
#define UnorderedMapiVec2_h__
#include <functional>
#include <boost/functional/hash.hpp>
#include <glm/vec2.hpp>
template<>
struct std::hash<glm::ivec2>
{
inline std::size_t operator()(const glm::ivec2 &v) const
{
return boost::hash<float>()(v.x) ^ boost::hash<float>()(v.y);
}
inline bool operator()(const glm::ivec2& a, const glm::ivec2& b)const
{
return a.x == b.x && a.y == b.y;
}
};
#endif
-17
View File
@@ -1,17 +0,0 @@
#ifndef Events_ContinueSound_h__
#define Events_ContinueSound_h__
#include "Core/EventBroker.h"
#include "Core/Entity.h"
namespace Events
{
// Continues to play a sound from where it was paused.
struct ContinueSound : Event
{
EntityID EmitterID;
};
}
#endif
-17
View File
@@ -1,17 +0,0 @@
#ifndef Events_PauseSound_h__
#define Events_PauseSound_h__
#include "Core/EventBroker.h"
#include "Core/Entity.h"
namespace Events
{
// Pauses a playing sound
struct PauseSound : Event
{
EntityID EmitterID;
};
}
#endif
@@ -1,18 +0,0 @@
#ifndef Events_PlayBackgroundMusic_h__
#define Events_PlayBackgroundMusic_h__
#include <string>
#include "Core/Entity.h"
#include "Core/Event.h"
namespace Events
{
// Play a sound that will be heared the same anywhere
struct PlayBackgroundMusic : public Event
{
std::string FilePath = "";
};
}
#endif
-21
View File
@@ -1,21 +0,0 @@
#ifndef Events_PlaySoundOnEntity_h__
#define Events_PlaySoundOnEntity_h__
#include <string>
#include "Core/Entity.h"
#include "Core/Event.h"
namespace Events
{
// Plays a sound on an entity with a SoundEmitter component attached.
// Sound behavior is thereby specified in the SoundEmitter component.
struct PlaySoundOnEntity : public Event
{
EntityID EmitterID = 0;
std::string FilePath = "";
};
}
#endif
@@ -1,26 +0,0 @@
#ifndef Events_PlaySoundOnPosition_h__
#define Events_PlaySoundOnPosition_h__
#include <string>
#include <glm/common.hpp>
#include "Core/Event.h"
namespace Events
{
// Plays a sound on a given position. Idk if this would be useful.
struct PlaySoundOnPosition : public Event
{
glm::vec3 Position = glm::vec3(0);
std::string FilePath = "";
float Gain = 1;
float Pitch = 1;
bool Loop = false;
float MaxDistance = 20;
float RollOffFactor = 1;
float ReferenceDistance = 1;
};
}
#endif
-16
View File
@@ -1,16 +0,0 @@
#ifndef Events_SetBGMGain_h__
#define Events_SetBGMGain_h__
#include "Core/Event.h"
namespace Events
{
// Set the "volume" for all background sounds
struct SetBGMGain : public Event
{
float Gain;
};
}
#endif
-16
View File
@@ -1,16 +0,0 @@
#ifndef Events_SetSFXGain_h__
#define Events_SetSFXGain_h__
#include "Core/Event.h"
namespace Events
{
// Set the "volume" for all effect sounds
struct SetSFXGain : public Event
{
float Gain;
};
}
#endif

Some files were not shown because too many files have changed in this diff Show More