Merge branch 'master' into OctTree

This commit is contained in:
William Moberg
2015-12-08 10:47:27 +01:00
62 changed files with 3435 additions and 157 deletions
+31
View File
@@ -0,0 +1,31 @@
#ifndef ComponentInfo_h__
#define ComponentInfo_h__
#include "../Common.h"
struct ComponentInfo
{
struct Meta_t
{
std::string Annotation;
unsigned int Allocation = 0;
unsigned int Stride = 0;
};
std::string Name;
std::unordered_map<std::string, std::string> FieldTypes;
std::unordered_map<std::string, unsigned int> FieldOffsets;
Meta_t Meta;
std::shared_ptr<char> Defaults = nullptr;
};
template<>
struct std::hash<ComponentInfo>
{
inline std::size_t operator()(const ComponentInfo& v) const
{
return std::hash<std::string>()(v.Name);
}
};
#endif
+80
View File
@@ -0,0 +1,80 @@
#ifndef ComponentPool_h__
#define ComponentPool_h__
#include "MemoryPool.h"
#include "ComponentInfo.h"
#include "ComponentWrapper.h"
class ComponentPoolForwardIterator
: public std::iterator<std::forward_iterator_tag, ComponentWrapper>
{
public:
ComponentPoolForwardIterator(const ComponentInfo& componentInfo, const MemoryPool<char>::iterator begin, const MemoryPool<char>::iterator end)
: m_ComponentInfo(componentInfo)
, m_MemoryPoolIterator(begin)
, m_MemoryPoolEnd(end)
{ }
ComponentPoolForwardIterator(const ComponentPoolForwardIterator& other) = default;
ComponentPoolForwardIterator(ComponentPoolForwardIterator&& other) = default;
~ComponentPoolForwardIterator() = default;
ComponentPoolForwardIterator& operator=(const ComponentPoolForwardIterator& other) = default;
ComponentPoolForwardIterator& operator++();
ComponentPoolForwardIterator& operator++(int);
bool operator!=(const ComponentPoolForwardIterator& other) const;
bool operator==(const ComponentPoolForwardIterator& other) const;
ComponentWrapper operator*() const;
private:
const ComponentInfo& m_ComponentInfo;
MemoryPool<char>::iterator m_MemoryPoolIterator;
const MemoryPool<char>::iterator m_MemoryPoolEnd;
};
class ComponentPool
{
public:
typedef ComponentPoolForwardIterator iterator;
typedef ptrdiff_t difference_type;
typedef size_t size_type;
typedef ComponentWrapper value_type;
typedef ComponentWrapper* pointer;
typedef ComponentWrapper& reference;
ComponentPool(const ::ComponentInfo& ci)
: m_ComponentInfo(ci)
, m_Pool(ci.Meta.Allocation, sizeof(EntityID) + ci.Meta.Stride)
{ }
ComponentPool(const ComponentPool& other) = delete;
ComponentPool(const ComponentPool&& other) = delete;
const ::ComponentInfo& ComponentInfo() const { return m_ComponentInfo; }
// Allocate space for a component and store which entity it belongs to in internal structure
ComponentWrapper Allocate(EntityID entity);
// Get the component belonging to a specific entity
ComponentWrapper GetByEntity(EntityID ent);
// Delete a component and free its memory
void Delete(ComponentWrapper& wrapper);
iterator begin() const;
iterator end() const;
//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<<)
//Interpret the data in the memory as InterpretType.
template <typename InterpretType = char, typename OutStream>
void Dump(OutStream& out) const;
//Dumps information about what the pool memory looks like right now
//into std::cout. Interpret the data in the memory as InterpretType.
template <typename InterpretType = char>
void Dump() const;
private:
::ComponentInfo m_ComponentInfo;
MemoryPool<char> m_Pool;
std::unordered_map<EntityID, char*> m_EntityToComponent;
};
#endif
+105
View File
@@ -0,0 +1,105 @@
#ifndef ComponentWrapper_h__
#define ComponentWrapper_h__
#include "../Common.h"
#include "EntityWrapper.h"
#include "ComponentInfo.h"
#include "Util/Any.h"
struct ComponentWrapper
{
ComponentWrapper(const ComponentInfo& componentInfo, char* data)
: Info(componentInfo)
, EntityID(*reinterpret_cast<::EntityID*>(data))
, Data(data + sizeof(EntityID))
{ }
const ComponentInfo& Info;
const ::EntityID EntityID;
char* Data;
template <typename T>
T& Property(std::string name)
{
unsigned int offset = Info.FieldOffsets.at(name);
return *reinterpret_cast<T*>(&Data[offset]);
}
template <typename T>
void SetProperty(std::string name, const T value) { Property<T>(name) = value; }
//template <typename T>
//void SetProperty(std::string name, T& value) { Property<T>(name) = value; }
// Specialization for string literals
template <std::size_t N>
void SetProperty(std::string name, const char(&value)[N]) { Property<std::string>(name) = std::string(value); }
struct SubscriptProxy
{
friend struct ComponentWrapper;
private:
SubscriptProxy(ComponentWrapper* component, std::string propertyName)
: m_Component(component)
, m_PropertyName(propertyName)
{ }
ComponentWrapper* m_Component;
std::string m_PropertyName;
public:
template <typename T>
operator T&() { return m_Component->Property<T>(m_PropertyName); }
template <typename T>
void operator=(const T val) { m_Component->SetProperty<T>(m_PropertyName, val); }
// TODO: Pass by reference and rvalue (universal reference?)
//template <typename T>
//void operator=(T& val) { m_Component->SetProperty<T>(m_PropertyName, val); }
// Specialization for string literals
template<std::size_t N>
void operator=(const char(&val)[N]) { m_Component->SetProperty<N>(m_PropertyName, val); }
};
SubscriptProxy operator[](std::string propertyName) { return SubscriptProxy(this, propertyName); }
};
// TODO: Move this to Tests once entity importing is finished
class ComponentWrapperFactory
{
public:
ComponentWrapperFactory() = default;
ComponentWrapperFactory(std::string componentTypeName, std::size_t allocation = 0)
{
m_ComponentInfo.Name = componentTypeName;
m_ComponentInfo.Meta.Allocation = allocation;
}
template <typename T>
void AddProperty(std::string fieldName, T defaultValue)
{
m_DefaultValues.push_back(defaultValue);
m_ComponentInfo.FieldTypes[fieldName] = typeid(T).name();
m_ComponentInfo.FieldOffsets[fieldName] = m_ComponentInfo.Meta.Stride;
m_ComponentInfo.Meta.Stride += sizeof(T);
}
ComponentInfo& Finalize()
{
m_ComponentInfo.Defaults = std::shared_ptr<char>(new char[m_ComponentInfo.Meta.Stride]);
std::size_t offset = 0;
for (auto& val : m_DefaultValues) {
memcpy(m_ComponentInfo.Defaults.get() + offset, val.Data.get(), val.Size);
offset += val.Size;
}
return m_ComponentInfo;
}
operator ComponentInfo&() { return Finalize(); }
private:
ComponentInfo m_ComponentInfo;
std::vector<Any> m_DefaultValues;
};
#endif
+480
View File
@@ -0,0 +1,480 @@
#include "../Common.h"
#include <sstream>
#include "../GLM.h"
#include <boost/filesystem.hpp>
#include <boost/utility/string_ref.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/dom/DOMLSInput.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/framework/Wrapper4InputSource.hpp>
#include <xercesc/framework/LocalFileInputSource.hpp>
#include <xercesc/framework/LocalFileFormatTarget.hpp>
#include <xercesc/framework/MemBufFormatTarget.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/sax/HandlerBase.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLFloat.hpp>
#include <xercesc/framework/XMLGrammarPoolImpl.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/framework/psvi/XSElementDeclaration.hpp>
#include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp>
#include <xercesc/framework/psvi/XSParticle.hpp>
#include <xercesc/framework/psvi/XSModelGroup.hpp>
#include <xercesc/framework/psvi/XSAnnotation.hpp>
#include <xercesc/framework/psvi/XSValue.hpp>
#include <xercesc/framework/XMLValidator.hpp>
#include "EntityWrapper.h"
#include "ComponentWrapper.h"
class EntityPreprocessorXMLErrorHandler : public xercesc::DOMErrorHandler
{
public:
bool handleError(const xercesc::DOMError &e) override
{
char* message = xercesc::XMLString::transcode(e.getMessage());
std::cerr << "Preprocessor DOMError: " << message << std::endl;
xercesc::XMLString::release(&message);
return false;
}
};
class EntityParserXMLErrorHandler : public xercesc::ErrorHandler
{
public:
void warning(const xercesc::SAXParseException& e) override
{
reportParseException("Warning", e);
}
void error(const xercesc::SAXParseException& e) override
{
reportParseException("Error", e);
}
void fatalError(const xercesc::SAXParseException& e) override
{
reportParseException("FATAL ERROR", e);
}
void resetErrors() override { }
private:
void reportParseException(std::string type, const xercesc::SAXParseException& e)
{
char* message = xercesc::XMLString::transcode(e.getMessage());
char* systemID = xercesc::XMLString::transcode(e.getSystemId());
std::cerr << systemID << ":" << e.getLineNumber() << ":" << e.getColumnNumber() << std::endl;
std::cerr << type << ": " << message << std::endl;
xercesc::XMLString::release(&systemID);
xercesc::XMLString::release(&message);
}
};
class XSTR
{
public:
XSTR(const XMLCh* const xmlString)
{
m_AsChar = xercesc::XMLString::transcode(xmlString);
}
XSTR(const char* normalString)
{
m_AsXMLCh = xercesc::XMLString::transcode(normalString);
}
~XSTR()
{
if (m_AsChar != nullptr) {
xercesc::XMLString::release(&m_AsChar);
}
if (m_AsXMLCh != nullptr) {
xercesc::XMLString::release(&m_AsXMLCh);
}
}
operator const char*() const { return m_AsChar; }
operator const XMLCh*() const { return m_AsXMLCh; }
private:
char* m_AsChar = nullptr;
XMLCh* m_AsXMLCh = nullptr;
};
struct ComponentPool
{
std::string ComponentName;
unsigned int Size = 0;
unsigned int Stride = 0;
ComponentInfo Info;
char* Data = nullptr;
// TODO: Iterators
ComponentWrapper at(unsigned int index)
{
// TODO: EntityID
return ComponentWrapper(0, &Info, Data + (index*Stride));
}
};
class EntityFactory
{
public:
EntityFactory(std::string entityFile)
: m_EntityFile(entityFile)
{
using namespace xercesc;
if (InstanceCount == 0) {
XMLPlatformUtils::Initialize();
}
InstanceCount++;
m_GrammarPool = new XMLGrammarPoolImpl();
m_ErrorHandler = new EntityParserXMLErrorHandler();
m_DOMParser = new XercesDOMParser(nullptr, XMLPlatformUtils::fgMemoryManager, m_GrammarPool);
m_DOMParser->setErrorHandler(m_ErrorHandler);
m_DOMParser->setDoNamespaces(true);
m_DOMParser->setDoXInclude(true);
m_DOMParser->setDoSchema(true);
m_DOMParser->setValidationSchemaFullChecking(true);
m_DOMParser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto);
m_DOMParser->setValidationSchemaFullChecking(true);
m_DOMParser->setValidationConstraintFatal(false);
m_DOMParser->setIncludeIgnorableWhitespace(false);
// Make sure schema grammar is kept after validation
m_DOMParser->cacheGrammarFromParse(true);
}
~EntityFactory()
{
using namespace xercesc;
if (m_DOMParser != nullptr) {
delete m_DOMParser;
}
if (m_ErrorHandler != nullptr) {
delete m_ErrorHandler;
}
if (m_GrammarPool != nullptr) {
delete m_GrammarPool;
}
InstanceCount++;
if (InstanceCount == 0) {
XMLPlatformUtils::Terminate();
}
}
void Preprocess(boost::filesystem::path inPath, boost::filesystem::path outPath)
{
using namespace xercesc;
static const XMLCh gLS[] = { 'L', 'S', '\0' };
DOMImplementationLS* di = static_cast<DOMImplementationLS*>(DOMImplementationRegistry::getDOMImplementation(gLS));
// Parse the file
DOMLSParser* parser = di->createLSParser(DOMImplementationLS::MODE_SYNCHRONOUS, nullptr);
DOMConfiguration* config = parser->getDomConfig();
config->setParameter(XMLUni::fgDOMNamespaces, true);
config->setParameter(XMLUni::fgXercesSchema, true);
config->setParameter(XMLUni::fgXercesHandleMultipleImports, true);
config->setParameter(XMLUni::fgXercesSchemaFullChecking, true);
config->setParameter(XMLUni::fgXercesDoXInclude, true);
auto errHandler = new EntityPreprocessorXMLErrorHandler();
config->setParameter(XMLUni::fgDOMErrorHandler, errHandler);
auto source = new LocalFileInputSource(XSTR(inPath.string().c_str()));
Wrapper4InputSource* domSourceWrapper = new Wrapper4InputSource(source);
DOMDocument* doc = parser->parse(dynamic_cast<DOMLSInput*>(domSourceWrapper));
// Serialize and output the new XML
DOMLSSerializer* writer = di->createLSSerializer();
DOMLSOutput* output = di->createLSOutput();
XMLFormatTarget* formatTarget = new LocalFileFormatTarget(outPath.string().c_str());
// TODO: MemBufFormatTarget* formatTarget = new MemBufFormatTarget()
output->setByteStream(formatTarget);
writer->write(doc, output);
delete formatTarget;
output->release();
writer->release();
parser->release();
}
void Parse()
{
// HACK: Use Sax2 parser instead so the whole DOM doesn't have to reside in memory
m_DOMParser->parse(m_EntityFile.c_str());
m_DOMDocument = m_DOMParser->getDocument();
// 1. Fill in ComponentInfo name, fields, default values and metadata from PSVI
ParseComponentInfo();
// 2. Parse default value files for those components
ParseDefaults();
// 3. Allocate component structures
AllocateComponentStore();
// 4. Parse entity hierarchy
ParseEntityGraph();
}
private:
static unsigned int InstanceCount;
std::string m_EntityFile;
xercesc::XMLGrammarPool* m_GrammarPool = nullptr;
EntityParserXMLErrorHandler* m_ErrorHandler = nullptr;
xercesc::XercesDOMParser* m_DOMParser = nullptr;
xercesc::DOMDocument* m_DOMDocument = nullptr;
std::map<std::string, ComponentInfo> m_ComponentInfo;
public:
std::map<std::string, ComponentPool> m_ComponentStore;
std::vector<EntityWrapper*> m_Entities;
private:
/*
Preprocess an XML file and output a new one
where xsi:includes are processed, since apparently
Xerces can't handle processing includes before validating schema.
*/
void ParseComponentInfo()
{
using namespace xercesc;
bool wasChanged;
XSModel* xsModel = m_GrammarPool->getXSModel(wasChanged);
// Find component xsd element declarations
std::cout << "Enumerating components..." << std::endl;
// <xs:element name="ComponentName">
auto topLevelElements = xsModel->getComponents(XSConstants::ELEMENT_DECLARATION);
for (unsigned int i = 0; i < topLevelElements->getLength(); ++i) {
auto element = static_cast<XSElementDeclaration*>(topLevelElements->item(i));
std::string nameSpace(XSTR(element->getNamespace()));
if (nameSpace != "components") {
continue;
}
ComponentInfo compInfo;
// Name
compInfo.Name = XSTR(element->getName());
// Annotation
auto componentAnnotation = element->getAnnotation();
if (componentAnnotation != nullptr) {
// Parse annotation XML
char* annotationString = XMLString::transcode(componentAnnotation->getAnnotationString());
MemBufInputSource annotationInput(reinterpret_cast<const XMLByte*>(annotationString), strlen(annotationString), "MemBuf: Annotation String");
XercesDOMParser parser(nullptr, XMLPlatformUtils::fgMemoryManager, m_GrammarPool);
parser.setErrorHandler(m_ErrorHandler);
parser.parse(annotationInput);
XMLString::release(&annotationString);
auto doc = parser.getDocument();
// Add allocation estimation(s)
auto allocationTags = doc->getElementsByTagName(XSTR("meta:allocation"));
for (int i = 0; i < allocationTags->getLength(); ++i) {
auto allocation = dynamic_cast<DOMElement*>(allocationTags->item(i));
auto child = allocation->getFirstChild();
if (child == nullptr) {
continue;
}
XSValue::Status status;
XSValue* val = XSValue::getActualValue(child->getNodeValue(), XSValue::dt_integer, status);
compInfo.Meta.Allocation += val->fData.fValue.f_int;
}
// Save documentation string
auto documentationTags = doc->getElementsByTagName(XSTR("xs:documentation"));
if (documentationTags->getLength() != 0) {
auto child = documentationTags->item(0)->getFirstChild();
if (child != nullptr) {
compInfo.Meta.Annotation = XSTR(child->getNodeValue());
}
}
// TODO: Parse annotation string XML
// compInfo.Meta.Allocation = ...
} else {
std::cout << "Warning: Component is missing an annotation!" << std::endl;
}
// <xs:complexType>
auto typeDefinition = element->getTypeDefinition();
if (typeDefinition->getTypeCategory() != XSTypeDefinition::COMPLEX_TYPE) {
std::cerr << "Error: Type definition wasn't COMPLEX_TYPE! Skipping." << std::endl;
continue;
}
auto complexTypeDefinition = dynamic_cast<XSComplexTypeDefinition*>(typeDefinition);
// <xs:all>
auto modelGroupParticle = complexTypeDefinition->getParticle();
if (modelGroupParticle->getTermType() != XSParticle::TERM_MODELGROUP) {
std::cerr << "Error: Model group particle wasn't TERM_MODELGROUP! Skipping." << std::endl;
continue;
}
auto modelGroup = modelGroupParticle->getModelGroupTerm();
// <xs:element...
// <xs:attribute...
unsigned int fieldOffset = 0;
auto particles = modelGroup->getParticles();
for (unsigned int i = 0; i < particles->size(); ++i) {
auto particle = particles->elementAt(i);
if (particle->getTermType() != XSParticle::TERM_ELEMENT) {
std::cerr << "Error: Particle wasn't TERM_ELEMENT! Skipping." << std::endl;
continue;
}
auto elementDeclaration = particle->getElementTerm();
std::string name = XSTR(elementDeclaration->getName());
std::string type = XSTR(elementDeclaration->getTypeDefinition()->getName());
size_t stride = getTypeStride(type);
if (stride == 0) {
std::cout << "Warning: Field \"" << name << "\" in component \"" << compInfo.Name << "\" uses unexpected field type \"" << type << "\". Skipping." << std::endl;
continue;
}
compInfo.FieldTypes[name] = type;
compInfo.FieldOffsets[name] = fieldOffset;
fieldOffset += getTypeStride(type);
}
compInfo.Meta.Stride = fieldOffset;
m_ComponentInfo[compInfo.Name] = compInfo;
}
}
void ParseDefaults()
{
}
void AllocateComponentStore()
{
using namespace xercesc;
auto root = m_DOMDocument->getDocumentElement();
// Count static instances of components present in entity hierarchy
auto components = m_DOMDocument->getElementsByTagNameNS(XSTR("components"), XSTR("*"));
for (int i = 0; i < components->getLength(); ++i) {
auto component = dynamic_cast<DOMElement*>(components->item(i));
std::string componentName = XSTR(component->getLocalName());
auto& compInfo = m_ComponentInfo.at(componentName);
compInfo.Meta.Allocation += 1;
}
std::cout << "COMPONENT INFO" << std::endl;
for (auto& pair : m_ComponentInfo) {
ComponentInfo& ci = pair.second;
std::cout << "Component: " << ci.Name << " (" << ci.Meta.Annotation << ")" << std::endl;
std::cout << " Allocation: " << ci.Meta.Allocation << std::endl;
std::cout << " Fields:" << std::endl;
// Calculate component size
unsigned int stride = 0;
// Reserve space for Entity pointer
stride += sizeof(EntityWrapper*);
std::cout << " Entity " << " (" << sizeof(EntityWrapper*) << " byte)" << std::endl;
// Add size of fields
for (auto& field : ci.FieldTypes) {
std::cout << " " << field.second << " " << field.first << " (" << getTypeStride(field.second) << " byte)" << std::endl;
stride += getTypeStride(field.second);
}
std::cout << " Stride: " << stride << std::endl;
ComponentPool cs;
cs.ComponentName = ci.Name;
cs.Stride = stride;
cs.Info = ci;
cs.Data = new char[stride*ci.Meta.Allocation];
m_ComponentStore[cs.ComponentName] = cs;
}
}
void ParseEntityGraph()
{
using namespace xercesc;
auto root = m_DOMDocument->getDocumentElement();
auto components = m_DOMDocument->getElementsByTagNameNS(XSTR("components"), XSTR("*"));
for (int i = 0; i < components->getLength(); ++i) {
auto component = dynamic_cast<DOMElement*>(components->item(i));
std::string componentName = XSTR(component->getLocalName());
auto& compStore = m_ComponentStore.at(componentName);
auto& compInfo = compStore.Info;
char* data = &compStore.Data[compStore.Size*compStore.Stride];
compStore.Size += 1;
auto fields = component->getChildNodes();
for (int j = 0; j < fields->getLength(); ++j) {
auto field = fields->item(j);
auto nodeType = field->getNodeType();
if (nodeType != DOMNode::ELEMENT_NODE) {
continue;
}
//auto field = dynamic_cast<DOMElement*>(fields->item(j));
//const XMLCh* value = fields->item(j)->getTextContent();
std::string fieldName = XSTR(field->getLocalName());
if (compInfo.FieldTypes.find(fieldName) == compInfo.FieldTypes.end()) {
std::cout << "Warning: Component \"" << componentName << "\" contains invalid field \"" << fieldName << "\". Skipping." << std::endl;
continue;
}
std::string fieldType = compInfo.FieldTypes.at(fieldName);
unsigned int fieldOffset = compInfo.FieldOffsets.at(fieldName);
XSValue::DataType dataType = XSValue::getDataType(XSTR(fieldType.c_str()));
if (dataType == XSValue::DataType::dt_MAXCOUNT) {
// TODO:
continue;
}
if (dataType == XSValue::DataType::dt_string) {
char* str = XMLString::transcode(field->getTextContent());
std::string standardString(str);
XMLString::release(&str);
memcpy(&data[fieldOffset], reinterpret_cast<char*>(&standardString), getTypeStride(fieldType));
} else {
XSValue::Status status;
XSValue* val = XSValue::getActualValue(field->getTextContent(), dataType, status);
memcpy(&data[fieldOffset], reinterpret_cast<char*>(&val->fData.fValue), getTypeStride(fieldType));
}
}
}
auto entities = m_DOMDocument->getElementsByTagName(XSTR("Entity"));
for (int i = 0; i < entities->getLength(); ++i) {
auto entity = dynamic_cast<DOMElement*>(entities->item(i));
//entity->setIdAttribute()
std::cout << "ENTITY " << i + 1 << std::endl;
}
}
size_t getTypeStride(std::string typeName)
{
std::map<std::string, size_t> typeStrides{
{ "int", sizeof(int) },
{ "double", sizeof(double) },
{ "string", sizeof(std::string) },
{ "Vector", sizeof(glm::vec3) },
{ "Quaternion", sizeof(glm::quat) },
};
auto it = typeStrides.find(typeName);
return (it != typeStrides.end()) ? it->second : 0;
}
};
unsigned int EntityFactory::InstanceCount = 0;
+12
View File
@@ -0,0 +1,12 @@
#include "ResourceManager.h"
class EntityFile : public Resource
{
friend class ResourceManager;
private:
EntityFile(std::string path);
public:
};
+15
View File
@@ -0,0 +1,15 @@
#ifndef Entity_h__
#define Entity_h__
typedef unsigned int EntityID;
struct EntityWrapper
{
EntityWrapper(EntityID entityID)
: ID(entityID)
{ }
EntityID ID;
};
#endif
+1
View File
@@ -32,6 +32,7 @@ public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
MemoryPool()
: m_StartAddress(nullptr)
, m_SlotIsAllocated()
+42
View File
@@ -0,0 +1,42 @@
#ifndef Util_Any_h__
#define Util_Any_h__
#include <memory>
struct Any
{
Any() { }
template <typename T>
Any(const T& value)
{
Data = std::shared_ptr<char>(new char[sizeof(T)]);
Size = sizeof(T);
memcpy(Data.get(), &value, Size);
}
template <typename T>
Any(T&& value)
{
Data = std::shared_ptr<char>(new char[sizeof(T)]);
Size = sizeof(T);
memcpy(Data.get(), &value, Size);
}
template <typename T>
Any& operator=(const T& value)
{
return Any(value);
}
template <typename T>
Any& operator=(T&& value)
{
return Any(value);
}
std::shared_ptr<char> Data = nullptr;
std::size_t Size = 0;
};
#endif
+36
View File
@@ -0,0 +1,36 @@
#ifndef World_h__
#define World_h__
#include "../Common.h"
#include "EntityWrapper.h"
#include "ObjectPool.h"
#include "ComponentPool.h"
class World
{
public:
World() = default;
~World();
EntityID CreateEntity(EntityID parent = 0);
// Register a component type and allocate space for it
void RegisterComponent(ComponentInfo& ci);
// Attach a component to an entity and fill it with default values
ComponentWrapper AttachComponent(EntityID entity, std::string componentType);
// Get a component of an entity
ComponentWrapper GetComponent(EntityID entity, std::string componentType);
// Get all components of the specified type
const ComponentPool& GetComponents(std::string componentType);
private:
EntityID m_CurrentEntityID = 0;
std::unordered_map<EntityID, EntityID> m_EntityParents;
std::unordered_multimap<EntityID, EntityID> m_EntityChildren;
std::unordered_map<std::string, ComponentPool*> m_ComponentPools;
EntityID generateEntityID();
};
#endif
+15
View File
@@ -0,0 +1,15 @@
#ifndef Client_h__
#define Client_h__
#include <boost\asio.hpp>
class Client
{
Client();
~Client();
};
#endif
+13
View File
@@ -0,0 +1,13 @@
#ifndef Server_h__
#define Server_h__
#include <boost\asio.hpp>
class Server
{
Server();
~Server();
};
#endif
+6 -4
View File
@@ -46,10 +46,7 @@ public:
float FarClip() const { return m_FarClip; }
void SetFarClip(float val);
float m_AspectRatio;
float m_FOV;
float m_NearClip;
float m_FarClip;
private:
void UpdateViewMatrix();
@@ -60,6 +57,11 @@ private:
glm::mat4 m_ProjectionMatrix;
glm::mat4 m_ViewMatrix;
float m_AspectRatio;
float m_FOV;
float m_NearClip;
float m_FarClip;
};
#endif
+64
View File
@@ -0,0 +1,64 @@
#ifndef FrameBuffer_h__
#define FrameBuffer_h__
#include "../OpenGL.h"
#include "Util/GLError.h"
class BufferResource
{
public:
BufferResource(GLuint* resourceHandle, GLenum resourceType, GLenum attachment);
GLuint* m_ResourceHandle;
GLenum m_ResourceType;
GLenum m_Attachment;
private:
};
template <GLenum RESOURCETYPE>
class ResourceType : public BufferResource
{
public:
ResourceType(GLuint* resourceHandle, GLenum attachment)
: BufferResource(resourceHandle, RESOURCETYPE, attachment) { }
};
class Texture2D : public ResourceType<GL_TEXTURE_2D>
{
public:
Texture2D(GLuint* resourceHandle, GLenum attachment)
: ResourceType(resourceHandle, attachment) { };
~Texture2D();
};
class RenderBuffer : public ResourceType<GL_RENDERBUFFER>
{
public:
RenderBuffer(GLuint* resourceHandle, GLenum attachment)
: ResourceType(resourceHandle, attachment)
{ };
~RenderBuffer();
};
class FrameBuffer
{
public:
FrameBuffer()
: m_BufferHandle(0) { }
~FrameBuffer();
void AddResource(std::shared_ptr<BufferResource> resource);
void Generate();
void Bind();
void Unbind();
GLuint GetHandle();
private:
GLuint m_BufferHandle;
std::vector<std::shared_ptr<BufferResource>> m_Resources;
};
#endif
+4
View File
@@ -3,9 +3,12 @@
#include "../Common.h"
#include "../OpenGL.h"
#include "../GLM.h"
#include "../Core/Util/Rectangle.h"
#include "Util/ScreenCoords.h"
#include "Camera.h"
#include "RenderQueue.h"
#include "Model.h"
class IRenderer
{
@@ -28,6 +31,7 @@ public:
}
virtual void Initialize() = 0;
virtual void Update(double dt) = 0;
virtual void Draw(RenderQueueCollection& rq) = 0;
protected:
+7 -30
View File
@@ -7,12 +7,15 @@
#include "../Common.h"
#include "../GLM.h"
#include "../Core/Util/Rectangle.h"
#include "../Core/EntityWrapper.h"
class Model;
class Skeleton;
class Texture;
class RenderQueue;
//TODO: Render: Remove obsolete RenderJobs and fix standard values on variables.
struct RenderJob
{
friend class RenderQueue;
@@ -35,6 +38,9 @@ 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;
@@ -80,30 +86,7 @@ struct PointLightJob : RenderJob
glm::vec3 SpecularColor = glm::vec3(1, 1, 1);
glm::vec3 DiffuseColor = glm::vec3(1, 1, 1);
float Radius = 1.f;
void CalculateHash() override
{
Hash = 0;
}
};
struct FrameJob : SpriteJob
{
Rectangle Scissor;
Rectangle Viewport;
std::string Name;
void CalculateHash() override
{
Hash = 0;
}
};
struct WaterParticleJob : RenderJob
{
glm::vec3 Position;
glm::vec4 Color;
glm::mat4 ModelMatrix;
float Intensity = 0.8f;
void CalculateHash() override
{
@@ -152,25 +135,19 @@ private:
struct RenderQueueCollection
{
RenderQueue Deferred;
RenderQueue Forward;
RenderQueue Lights;
RenderQueue GUI;
void Clear()
{
Deferred.Clear();
Forward.Clear();
Lights.Clear();
GUI.Clear();
}
void Sort()
{
Deferred.Sort();
Forward.Sort();
Lights.Sort();
GUI.Sort();
}
};
@@ -0,0 +1,28 @@
#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; }
private:
RenderQueueCollection m_RenderQueues;
void FillModels(World* world, RenderQueue* renderQueue);
void FillLights(World* world, RenderQueue* renderQueue);
glm::mat4 ModelMatrix(World* world, EntityID entity);
glm::vec3 GetAbsolutePosition(World* world, ComponentWrapper transformComponent);
};
#endif
+57
View File
@@ -0,0 +1,57 @@
#ifndef Renderer_h__
#define Renderer_h__
#include <sstream>
#include "IRenderer.h"
#include "ShaderProgram.h"
//TODO: Temp resourceManager
#include "../Core/ResourceManager.h"
#include "Util/UnorderedMapVec2.h"
#include "FrameBuffer.h"
#include "../Core/World.h"
class Renderer : public IRenderer
{
public:
virtual void Initialize() override;
virtual void Update(double dt) override;
virtual void Draw(RenderQueueCollection& rq) override;
private:
//----------------------Variables----------------------//
Texture* m_ErrorTexture;
Texture* m_WhiteTexture;
float m_CameraMoveSpeed;
FrameBuffer m_PickingBuffer;
GLuint m_PickingTexture;
GLuint m_DepthBuffer;
Model* m_ScreenQuad;
Model* m_UnitQuad;
Model* m_UnitSphere;
std::unordered_map<glm::vec2, EntityID> m_PickingColorsToEntity;
//----------------------Functions----------------------//
void InitializeWindow();
void InitializeShaders();
void InitializeTextures();
void InitializeFrameBuffers();
//TODO: Renderer: Get InputUpdate out of renderer
void InputUpdate(double dt);
void PickingPass(RenderQueueCollection& rq);
void DrawScreenQuad(GLuint textureToDraw);
void DrawScene(RenderQueueCollection& rq);
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type);
//--------------------ShaderPrograms-------------------//
ShaderProgram m_BasicForwardProgram;
ShaderProgram m_PickingProgram;
ShaderProgram m_DrawScreenQuadProgram;
};
#endif
+81
View File
@@ -0,0 +1,81 @@
#include "../Common.h"
#include "../OpenGL.h"
#include <fstream>
class Shader
{
public:
static GLuint CompileShader(GLenum shaderType, std::string fileName);
Shader(GLenum shaderType, std::string fileName);
virtual ~Shader();
GLuint Compile();
GLenum GetType() const;
std::string GetFileName() const;
GLuint GetHandle() const;
bool IsCompiled() const;
protected:
GLenum m_ShaderType;
std::string m_FileName;
GLint m_ShaderHandle;
};
template <int SHADERTYPE>
class ShaderType : public Shader
{
public:
ShaderType(std::string fileName)
: Shader(SHADERTYPE, fileName) { }
};
class VertexShader : public ShaderType<GL_VERTEX_SHADER>
{
public:
VertexShader(std::string fileName)
: ShaderType(fileName) { }
};
class FragmentShader : public ShaderType<GL_FRAGMENT_SHADER>
{
public:
FragmentShader(std::string fileName)
: ShaderType(fileName) { }
};
class GeometryShader : public ShaderType<GL_GEOMETRY_SHADER>
{
public:
GeometryShader(std::string fileName)
: ShaderType(fileName) { }
};
class ComputeShader : public ShaderType<GL_COMPUTE_SHADER>
{
public:
ComputeShader(std::string fileName)
: ShaderType(fileName) { }
};
class ShaderProgram
{
public:
ShaderProgram()
: m_ShaderProgramHandle(0) { }
~ShaderProgram();
void AddShader(std::shared_ptr<Shader> shader);
void Compile();
GLuint Link();
GLuint GetHandle();
void Bind();
void Unbind();
void BindFragDataLocation(int index, std::string name);
private:
GLuint m_ShaderProgramHandle;
std::vector<std::shared_ptr<Shader>> m_Shaders;
};
@@ -0,0 +1,30 @@
#ifndef ScreenCoords_h__
#define ScreenCoords_h__
#include "../../Common.h"
#include "../../OpenGL.h"
#include "../../GLM.h"
#include "../../Core/Util/Rectangle.h"
#include "../FrameBuffer.h"
class ScreenCoords
{
public:
ScreenCoords() = delete;
//Return world position from given screenspace coordinates and depth value in viewspace.
static glm::vec3 ToWorldPos(glm::vec2 screenCoord, float depth, Rectangle resolution, glm::mat4 cameraProjectionMat, glm::mat4 cameraViewMat);
static glm::vec3 ToWorldPos(float x, float y, float depth, Rectangle resolution, glm::mat4 cameraProjectionMat, glm::mat4 cameraViewMat);
static glm::vec3 ToWorldPos(glm::vec2 screenCoord, float depth, float screenWidth, float screenHeight, glm::mat4 cameraProjectionMat, glm::mat4 cameraViewMat);
static glm::vec3 ToWorldPos(float x, float y, float depth, float screenWidth, float screenHeight, glm::mat4 cameraProjectionMat, glm::mat4 cameraViewMat);
//Return data from the given buffers at the coordinates given in screenspace. Buffer should probably have a texture that covers the screen.
//Data is given as R = x, B = y, and
static glm::vec3 ToPixelData(glm::vec2 screenCoord, FrameBuffer* PickDataBuffer, GLuint DepthBuffer);
static glm::vec3 ToPixelData(float x, float y, FrameBuffer* PickDataBuffer, GLuint DepthBuffer);
//Return EntityID of the clicked coordinate in given screenspace coordinates.
//EntityID ScreenCoordsToEntityID(glm::vec2 screenCoord, float depth);
private:
};
#endif
@@ -0,0 +1,23 @@
#ifndef UnorderedMapVec2_h__
#define UnorderedMapVec2_h__
#include <functional>
#include <boost/functional/hash.hpp>
#include <glm/vec2.hpp>
template<>
struct std::hash<glm::vec2>
{
inline std::size_t operator()(const glm::vec2 &v) const
{
return boost::hash<float>()(v.x) ^ boost::hash<float>()(v.y);
}
inline bool operator()(const glm::vec2& a, const glm::vec2& b)const
{
return a.x == b.x && a.y == b.y;
}
};
#endif