Merge branch 'OctTree' of github.com:teamfisk/TacticalZ into OctTree
# Conflicts: # include/Engine/Core/OctTree.h # src/Engine/Core/OctTree.cpp
This commit is contained in:
+1
-1
Submodule assets updated: 4bd902b697...b37468222e
@@ -1,13 +1,13 @@
|
||||
# XERCES_FOUND
|
||||
# XERCES_INCLUDE_DIRS
|
||||
# XERCES_LIBRARIES
|
||||
# Xerces_FOUND
|
||||
# Xerces_INCLUDE_DIRS
|
||||
# Xerces_LIBRARIES
|
||||
|
||||
find_path(XERCES_INCLUDE_DIR xercesc/dom/dom.hpp
|
||||
find_path(Xerces_INCLUDE_DIR xercesc/dom/dom.hpp
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
)
|
||||
|
||||
find_library(XERCES_LIBRARY
|
||||
find_library(Xerces_LIBRARY
|
||||
NAMES
|
||||
xerces-c_3
|
||||
xerces-c_3D
|
||||
@@ -16,8 +16,8 @@ find_library(XERCES_LIBRARY
|
||||
/usr/lib
|
||||
)
|
||||
|
||||
set(XERCES_INCLUDE_DIRS ${XERCES_INCLUDE_DIR})
|
||||
set(XERCES_LIBRARIES ${XERCES_LIBRARY})
|
||||
set(Xerces_INCLUDE_DIRS ${Xerces_INCLUDE_DIR})
|
||||
set(Xerces_LIBRARIES ${Xerces_LIBRARY})
|
||||
|
||||
find_package_handle_standard_args(Xerces DEFAULT_MSG XERCES_LIBRARY XERCES_INCLUDE_DIR)
|
||||
mark_as_advanced(Xerces_FOUND XERCES_INCLUDE_DIR XERCES_LIBRARY)
|
||||
find_package_handle_standard_args(Xerces DEFAULT_MSG Xerces_LIBRARY Xerces_INCLUDE_DIR)
|
||||
mark_as_advanced(Xerces_FOUND Xerces_INCLUDE_DIR Xerces_LIBRARY)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define ComponentWrapper_h__
|
||||
|
||||
#include "../Common.h"
|
||||
#include "EntityWrapper.h"
|
||||
#include "Entity.h"
|
||||
#include "ComponentInfo.h"
|
||||
#include "Util/Any.h"
|
||||
|
||||
@@ -11,7 +11,7 @@ struct ComponentWrapper
|
||||
ComponentWrapper(const ComponentInfo& componentInfo, char* data)
|
||||
: Info(componentInfo)
|
||||
, EntityID(*reinterpret_cast<::EntityID*>(data))
|
||||
, Data(data + sizeof(EntityID))
|
||||
, Data(data + sizeof(::EntityID))
|
||||
{ }
|
||||
|
||||
const ComponentInfo& Info;
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef Entity_h__
|
||||
#define Entity_h__
|
||||
|
||||
typedef unsigned int EntityID;
|
||||
|
||||
#endif
|
||||
@@ -1,12 +0,0 @@
|
||||
#include "ResourceManager.h"
|
||||
|
||||
class EntityFile : public Resource
|
||||
{
|
||||
friend class ResourceManager;
|
||||
|
||||
private:
|
||||
EntityFile(std::string path);
|
||||
|
||||
public:
|
||||
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
#ifndef Entity_h__
|
||||
#define Entity_h__
|
||||
|
||||
typedef unsigned int EntityID;
|
||||
|
||||
struct EntityWrapper
|
||||
{
|
||||
EntityWrapper(EntityID entityID)
|
||||
: ID(entityID)
|
||||
{ }
|
||||
|
||||
EntityID ID;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,141 @@
|
||||
#ifndef EntityXMLFile_h__
|
||||
#define EntityXMLFile_h__
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "../Common.h"
|
||||
#include "../GLM.h"
|
||||
#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 "ResourceManager.h"
|
||||
#include "Entity.h"
|
||||
#include "ComponentInfo.h"
|
||||
class World;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
class EntityXMLFile : public Resource
|
||||
{
|
||||
friend class ResourceManager;
|
||||
|
||||
private:
|
||||
EntityXMLFile(std::string path);
|
||||
|
||||
public:
|
||||
~EntityXMLFile();
|
||||
|
||||
void PopulateWorld(World* world);
|
||||
|
||||
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;
|
||||
|
||||
// Preprocesses the entity file to insert include-by-copy child entities
|
||||
// TODO: Make this work in memory instead of saving to file
|
||||
void preprocess(std::string inPath, std::string outPath);
|
||||
|
||||
void parseComponentInfo();
|
||||
void parseDefaults();
|
||||
void predictComponentAllocation();
|
||||
void parseEntityGraph(World* world, xercesc::DOMElement* parent, EntityID parentEntity);
|
||||
std::size_t getTypeStride(std::string typeName);
|
||||
float getFloatAttribute(const xercesc::DOMElement* element, const char* attribute) const;
|
||||
void writeData(const xercesc::DOMElement* element, std::string typeName, char* outData);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -13,7 +13,8 @@ public:
|
||||
struct Output
|
||||
{
|
||||
float CollideDistance;
|
||||
};
|
||||
};
|
||||
|
||||
OctTree();
|
||||
~OctTree();
|
||||
//For the root OctTree, [octTreeBounds] should be a box containing the entire level.
|
||||
@@ -24,43 +25,84 @@ public:
|
||||
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();
|
||||
|
||||
//Collision test function. WTODO: Probably remove or relocate elsewhere, Collision system?
|
||||
void Update(float dt, World* world, Camera* cam);
|
||||
|
||||
void AddDynamicObject(const AABB& box);
|
||||
void AddStaticObject(const AABB& box);
|
||||
|
||||
void BoxesInSameRegion(const AABB& box, std::vector<AABB>& outBoxes) const;
|
||||
|
||||
void ClearObjects();
|
||||
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) const;
|
||||
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].
|
||||
bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const;
|
||||
//Note: More efficient than calling BoxesInSameRegion from outside and testing there.
|
||||
bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected);
|
||||
|
||||
private:
|
||||
OctTree* m_Children[8];
|
||||
//WTODO: Do -derived class from AABB- struct containing AABB, with a bool Tested, falsify at
|
||||
//start of Collision test, set on check, don't check if set already. Solves duplicate boxes in tree.
|
||||
//Store indices in the struct, pointing to grand ancestor list of boxes, need the same AABB not copies to save Tested.
|
||||
//WTODO: Boxes collide with themselves? Fix somehow, maybe float epsilon stuff.
|
||||
std::vector<AABB> m_StaticObjects;
|
||||
std::vector<AABB> m_DynamicObjects;
|
||||
AABB m_Box;
|
||||
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;
|
||||
|
||||
inline bool hasChildren() const;
|
||||
public:
|
||||
int childIndexContainingPoint(const glm::vec3& point) const;
|
||||
std::vector<int> childIndicesContainingBox(const AABB& box) const;
|
||||
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
|
||||
@@ -81,6 +81,8 @@ public:
|
||||
@param resourceName Fully qualified name of the resource to reload.
|
||||
*/
|
||||
static void Reload(std::string resourceName);
|
||||
|
||||
static void Release(std::string resourceType, std::string resourceName);
|
||||
|
||||
static void Update();
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef System_h__
|
||||
#define System_h__
|
||||
|
||||
#include "EventBroker.h"
|
||||
#include "World.h"
|
||||
#include "ComponentWrapper.h"
|
||||
|
||||
class System
|
||||
{
|
||||
friend class SystemPipeline;
|
||||
|
||||
public:
|
||||
System(const EventBroker* eventBroker, std::string componentType)
|
||||
: m_EventBroker(eventBroker)
|
||||
, m_ComponentType(componentType)
|
||||
{ }
|
||||
|
||||
virtual void Update(World* world, ComponentWrapper& component, double dt) = 0;
|
||||
|
||||
private:
|
||||
const EventBroker* m_EventBroker;
|
||||
std::string m_ComponentType;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,58 @@
|
||||
#ifndef SystemPipeline_h__
|
||||
#define SystemPipeline_h__
|
||||
|
||||
#include "../Common.h"
|
||||
#include "EventBroker.h"
|
||||
#include "System.h"
|
||||
#include "World.h"
|
||||
|
||||
class SystemPipeline
|
||||
{
|
||||
public:
|
||||
SystemPipeline(const EventBroker* eventBroker)
|
||||
: m_EventBroker(eventBroker)
|
||||
{ }
|
||||
~SystemPipeline()
|
||||
{
|
||||
for (auto& pair : m_Systems) {
|
||||
for (auto& system : pair.second) {
|
||||
delete system;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename... Arguments>
|
||||
void AddSystem(Arguments... args)
|
||||
{
|
||||
System* system = new T(m_EventBroker, args...);
|
||||
if (!system->m_ComponentType.empty()) {
|
||||
m_Systems[system->m_ComponentType].push_back(system);
|
||||
} else {
|
||||
LOG_ERROR("Failed to add system \"%s\": Missing component type!", typeid(T).name());
|
||||
delete system;
|
||||
}
|
||||
}
|
||||
|
||||
void Update(World* world, double dt)
|
||||
{
|
||||
for (auto& pair : m_Systems) {
|
||||
const std::string& componentName = pair.first;
|
||||
auto& systems = pair.second;
|
||||
const ComponentPool* pool = world->GetComponents(componentName);
|
||||
if (pool == nullptr) {
|
||||
continue;
|
||||
}
|
||||
for (auto& component : *pool) {
|
||||
for (auto& system : systems) {
|
||||
system->Update(world, component, dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const EventBroker* m_EventBroker;
|
||||
std::unordered_map<std::string, std::vector<System*>> m_Systems;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -2,7 +2,7 @@
|
||||
#define World_h__
|
||||
|
||||
#include "../Common.h"
|
||||
#include "EntityWrapper.h"
|
||||
#include "Entity.h"
|
||||
#include "ObjectPool.h"
|
||||
#include "ComponentPool.h"
|
||||
|
||||
@@ -12,6 +12,7 @@ public:
|
||||
World() = default;
|
||||
~World();
|
||||
|
||||
// Create empty entity
|
||||
EntityID CreateEntity(EntityID parent = 0);
|
||||
|
||||
// Register a component type and allocate space for it
|
||||
@@ -21,10 +22,12 @@ public:
|
||||
// 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);
|
||||
const ComponentPool* GetComponents(std::string componentType);
|
||||
// Get entity parent
|
||||
EntityID GetParent(EntityID entity);
|
||||
|
||||
private:
|
||||
EntityID m_CurrentEntityID = 0;
|
||||
EntityID m_CurrentEntityID = 1;
|
||||
|
||||
std::unordered_map<EntityID, EntityID> m_EntityParents;
|
||||
std::unordered_multimap<EntityID, EntityID> m_EntityChildren;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "../Common.h"
|
||||
#include "../GLM.h"
|
||||
#include "../Core/Util/Rectangle.h"
|
||||
#include "../Core/EntityWrapper.h"
|
||||
#include "../Core/Entity.h"
|
||||
|
||||
class Model;
|
||||
class Skeleton;
|
||||
|
||||
@@ -22,7 +22,10 @@ private:
|
||||
void FillLights(World* world, RenderQueue* renderQueue);
|
||||
|
||||
glm::mat4 ModelMatrix(World* world, EntityID entity);
|
||||
glm::vec3 GetAbsolutePosition(World* world, ComponentWrapper transformComponent);
|
||||
|
||||
glm::vec3 AbsolutePosition(World* world, EntityID entity);
|
||||
glm::quat AbsoluteOrientation(World* world, EntityID entity);
|
||||
glm::vec3 AbsoluteScale(World* world, EntityID entity);
|
||||
};
|
||||
|
||||
#endif
|
||||
+11
-3
@@ -9,8 +9,10 @@
|
||||
#include "GUI/Frame.h"
|
||||
#include "Core/World.h"
|
||||
#include "Rendering/RenderQueueFactory.h"
|
||||
|
||||
class OctTree;
|
||||
#include "Core/EKeyDown.h"
|
||||
#include "Core/EntityXMLFile.h"
|
||||
#include "Core/SystemPipeline.h"
|
||||
#include "RaptorCopterSystem.h"
|
||||
|
||||
class Game
|
||||
{
|
||||
@@ -29,8 +31,14 @@ private:
|
||||
InputManager* m_InputManager;
|
||||
GUI::Frame* m_FrameStack;
|
||||
World* m_World;
|
||||
SystemPipeline* m_SystemPipeline;
|
||||
RenderQueueFactory* m_RenderQueueFactory;
|
||||
OctTree* m_OctTree;
|
||||
|
||||
EventRelay<Game, Events::KeyUp> m_EKeyUp;
|
||||
bool testOnKeyUp(const Events::KeyUp& e);
|
||||
|
||||
void testIntialize();
|
||||
void testTick(double dt);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
#include <list>
|
||||
#include <tuple>
|
||||
#include <boost/any.hpp>
|
||||
#include "GLM.h"
|
||||
#include "Core/World.h"
|
||||
#include "Core/Util/Any.h"
|
||||
|
||||
class HardcodedTestWorld : public World
|
||||
{
|
||||
public:
|
||||
HardcodedTestWorld()
|
||||
: World()
|
||||
{
|
||||
registerTestComponents();
|
||||
createTestEntities();
|
||||
}
|
||||
|
||||
private:
|
||||
void registerTestComponents()
|
||||
{
|
||||
ComponentWrapperFactory f;
|
||||
|
||||
|
||||
f = ComponentWrapperFactory("Test");
|
||||
f.AddProperty("TestInteger", 1337);
|
||||
f.AddProperty("TestFloat", 13.37f);
|
||||
f.AddProperty("TestString", std::string("Carlito"));
|
||||
RegisterComponent(f);
|
||||
|
||||
f = ComponentWrapperFactory("Debug");
|
||||
f.AddProperty("Name", std::string("Unnamed"));
|
||||
RegisterComponent(f);
|
||||
|
||||
f = ComponentWrapperFactory("Transform");
|
||||
f.AddProperty("Position", glm::vec3(0.f, 0.f, 0.f));
|
||||
f.AddProperty("Orientation", glm::quat());
|
||||
f.AddProperty("Scale", glm::vec3(1.f, 1.f, 1.f));
|
||||
RegisterComponent(f);
|
||||
|
||||
f = ComponentWrapperFactory("Model");
|
||||
f.AddProperty("Resource", std::string());
|
||||
f.AddProperty("Color", glm::vec4(1.f, 1.f, 1.f, 1.f));
|
||||
f.AddProperty("Visible", true);
|
||||
RegisterComponent(f);
|
||||
|
||||
f = ComponentWrapperFactory("Collision");
|
||||
f.AddProperty("BoxCenter", glm::vec3(0.f, 0.f, 0.f));
|
||||
f.AddProperty("BoxSize", glm::vec3(1.f, 1.f, 1.f));
|
||||
RegisterComponent(f);
|
||||
}
|
||||
|
||||
void createTestEntities()
|
||||
{
|
||||
World& world = *this;
|
||||
|
||||
// Create an entity
|
||||
EntityID e = world.CreateEntity();
|
||||
|
||||
// Attach a Debug component
|
||||
ComponentWrapper debug = world.AttachComponent(e, "Debug");
|
||||
// Set the Name field of the Debug component using subscript operator
|
||||
debug["Name"] = "Carlito";
|
||||
|
||||
// Attach a Transform component
|
||||
world.AttachComponent(e, "Transform");
|
||||
// Fetch the component based on EntityID and component type
|
||||
ComponentWrapper transform = world.GetComponent(e, "Transform");
|
||||
// Set the fields of the Transform component
|
||||
transform["Position"] = glm::vec3(0.f, 0.f, 0.f);
|
||||
transform["Scale"] = glm::vec3(1.f, 1.f, 1.f);
|
||||
|
||||
// Move on the X axis by fetching field as reference
|
||||
((glm::vec3&)transform["Position"]).x += 10.f;
|
||||
// Shrink by a factor of 100
|
||||
((glm::vec3&)transform["Scale"]) /= 100.f;
|
||||
|
||||
// Loop through all Transform components and print them
|
||||
for (auto& transform : world.GetComponents("Transform")) {
|
||||
glm::vec3 pos = transform["Position"];
|
||||
std::cout << "Position: " << pos.x << " " << pos.y << " " << pos.z << std::endl;
|
||||
glm::vec3 scale = transform["Scale"];
|
||||
std::cout << "Scale: " << scale.x << " " << scale.y << " " << scale.z << std::endl;
|
||||
|
||||
// Fetch the Debug component also present in this entity
|
||||
ComponentWrapper debug = world.GetComponent(transform.EntityID, "Debug");
|
||||
std::cout << "Name: " << (std::string)debug["Name"] << std::endl;
|
||||
}
|
||||
|
||||
//Create some test widgets
|
||||
{
|
||||
EntityID entityScaleWidget = world.CreateEntity();
|
||||
ComponentWrapper transform = world.AttachComponent(entityScaleWidget, "Transform");
|
||||
transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f);
|
||||
ComponentWrapper model = world.AttachComponent(entityScaleWidget, "Model");
|
||||
model["Resource"] = "Models/ScaleWidget.obj";
|
||||
}
|
||||
{
|
||||
EntityID entityRotationWidget = world.CreateEntity();
|
||||
ComponentWrapper transform = world.AttachComponent(entityRotationWidget, "Transform");
|
||||
transform["Position"] = glm::vec3(1.5f, 0.f, 0.f);
|
||||
ComponentWrapper model = world.AttachComponent(entityRotationWidget, "Model");
|
||||
model["Resource"] = "Models/RotationWidget.obj";
|
||||
}
|
||||
{
|
||||
EntityID entityDummyScene = world.CreateEntity();
|
||||
ComponentWrapper transform = world.AttachComponent(entityDummyScene, "Transform");
|
||||
transform["Position"] = glm::vec3(0, 0.f, 0.f);
|
||||
ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model");
|
||||
model["Resource"] = "Models/DummyScene.obj";
|
||||
}
|
||||
{
|
||||
EntityID entityCollisionBox = world.CreateEntity();
|
||||
ComponentWrapper transform = world.AttachComponent(entityCollisionBox, "Transform");
|
||||
transform["Position"] = glm::vec3(0.f, 2.f, 0.f);
|
||||
ComponentWrapper model = world.AttachComponent(entityCollisionBox, "Model");
|
||||
model["Resource"] = "Models/Core/UnitBox.obj";
|
||||
|
||||
ComponentWrapper collision = world.AttachComponent(entityCollisionBox, "Collision");
|
||||
glm::vec3 pos = transform["Position"];
|
||||
glm::vec3 scale = transform["Scale"];
|
||||
glm::quat ori = transform["Orientation"];
|
||||
Model* modelRes = ResourceManager::Load<Model>(model["Resource"]);
|
||||
|
||||
//WTODO: This only works for objects that never moves/scales/rotates since modelMatrix don't change.
|
||||
//For dynamic objects, should save a collision box in modelspace and transform box with modelMatrix per collision check.
|
||||
glm::mat4 modelMatrix = modelRes->m_Matrix * glm::translate(glm::mat4(), pos) * glm::toMat4(ori) * glm::scale(scale);
|
||||
|
||||
glm::vec3 mini = glm::vec3(INFINITY, INFINITY, INFINITY);
|
||||
glm::vec3 maxi = glm::vec3(-INFINITY, -INFINITY, -INFINITY);
|
||||
for (const auto& v : modelRes->m_Vertices) {
|
||||
const auto& wPos = modelMatrix * glm::vec4(v.Position.x, v.Position.y, v.Position.z, 1);
|
||||
maxi.x = std::max(wPos.x, maxi.x);
|
||||
maxi.y = std::max(wPos.y, maxi.y);
|
||||
maxi.z = std::max(wPos.z, maxi.z);
|
||||
mini.x = std::min(wPos.x, mini.x);
|
||||
mini.y = std::min(wPos.y, mini.y);
|
||||
mini.z = std::min(wPos.z, mini.z);
|
||||
}
|
||||
collision["BoxCenter"] = 0.5f * (maxi + mini);
|
||||
collision["BoxSize"] = maxi - mini;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "Common.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
class RaptorCopterSystem : public System
|
||||
{
|
||||
public:
|
||||
RaptorCopterSystem(const EventBroker* eventBroker)
|
||||
: System(eventBroker, "RaptorCopter")
|
||||
{ }
|
||||
|
||||
virtual void Update(World* world, ComponentWrapper& raptorCopter, double dt) override
|
||||
{
|
||||
ComponentWrapper& transform = world->GetComponent(raptorCopter.EntityID, "Transform");
|
||||
(glm::vec3&)transform["Orientation"] += (float)(double)raptorCopter["Speed"] * (float)dt * (glm::vec3)raptorCopter["Axis"];
|
||||
}
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
[Debug]
|
||||
LogLevel=1
|
||||
LoadMap=
|
||||
|
||||
[Video]
|
||||
Fullscreen=false
|
||||
|
||||
@@ -2,5 +2,7 @@
|
||||
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="components" elementFormDefault="qualified">
|
||||
<xs:include schemaLocation="Components/Transform.xsd"/>
|
||||
<xs:include schemaLocation="Components/Model.xsd"/>
|
||||
<xs:include schemaLocation="Components/Test.xsd"/>
|
||||
<xs:include schemaLocation="Components/RaptorCopter.xsd"/>
|
||||
</xs:schema>
|
||||
@@ -0,0 +1,5 @@
|
||||
<c:Model>
|
||||
<Resource></Resource>
|
||||
<Color R="1" G="1" B="1" A="1"/>
|
||||
<Visible>true</Visible>
|
||||
</c:Model>
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
|
||||
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
|
||||
|
||||
<xs:element name="Model">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A visible model loaded from disk</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="Resource" type="t:string" minOccurs="0">
|
||||
<xs:annotation><xs:documentation>Model file</xs:documentation></xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="Color" type="t:Color" minOccurs="0">
|
||||
<xs:annotation><xs:documentation>Color tint</xs:documentation></xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="Visible" type="t:bool" minOccurs="0">
|
||||
<xs:annotation><xs:documentation>Wether the model is visible or not</xs:documentation></xs:annotation>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
@@ -0,0 +1,4 @@
|
||||
<c:RaptorCopter>
|
||||
<Speed>0</Speed>
|
||||
<Axis X="0" Y="0" Z="0"/>
|
||||
</c:RaptorCopter>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
|
||||
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
|
||||
|
||||
<xs:element name="RaptorCopter">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="Speed" type="t:double" minOccurs="0"/>
|
||||
<xs:element name="Axis" type="t:Vector" minOccurs="0"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
@@ -2,5 +2,5 @@
|
||||
<Integer>1</Integer>
|
||||
<Float>1.333</Float>
|
||||
<Vector X="1.33333" Y="2.33333" Z="3.33333"/>
|
||||
<Quaternion I="1.33333" J="2.33333" K="3.33333"/>
|
||||
<Quaternion X="1.33333" Y="2.33333" Z="3.33333" W="4.44444"/>
|
||||
</c:Test>
|
||||
@@ -1,5 +1,5 @@
|
||||
<TransformComponent>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="0" Z="0"/>
|
||||
<Orientation I="0" J="0" K="0"/>
|
||||
<Orientation X="0" Y="0" Z="0" W="0"/>
|
||||
<Scale X="1" Y="1" Z="1"/>
|
||||
</TransformComponent>
|
||||
</c:Transform>
|
||||
@@ -12,7 +12,7 @@
|
||||
<xs:element name="Position" type="t:Vector" minOccurs="0">
|
||||
<xs:annotation><xs:documentation>The position vector</xs:documentation></xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="Orientation" type="t:Quaternion" minOccurs="0"/>
|
||||
<xs:element name="Orientation" type="t:Vector" minOccurs="0"/>
|
||||
<xs:element name="Scale" type="t:Vector" minOccurs="0"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
|
||||
@@ -3,18 +3,114 @@
|
||||
<Entity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd" xmlns:c="components">
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="1.02" Y="3.123123" Z="41.123"/>
|
||||
<Orientation I="1.234" J="1.234" K="1.234"/>
|
||||
<Scale X="1.02" Y="3.123123" Z="41.123"/>
|
||||
<Orientation X="0" Y="0" Z="0"/>
|
||||
</c:Transform>
|
||||
<c:Test>
|
||||
<Integer>12</Integer>
|
||||
<Double>11.11</Double>
|
||||
<String>Hello World</String>
|
||||
</c:Test>
|
||||
<c:Model>
|
||||
<Resource>Models/DummyScene.obj</Resource>
|
||||
</c:Model>
|
||||
</Components>
|
||||
<Children>
|
||||
<xi:include href="OtherEntity.xml"/>
|
||||
<xi:include href="OtherEntity.xml"/>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="-1.5"/>
|
||||
<Scale X="1" Y="1" Z="1"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/ScaleWidget.obj</Resource>
|
||||
</c:Model>
|
||||
</Components>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="1.5"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/RotationWidget.obj</Resource>
|
||||
</c:Model>
|
||||
</Components>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="-0"/>
|
||||
<Scale X="1" Y="1" Z="1"/>
|
||||
</c:Transform>
|
||||
<!--<c:Move>
|
||||
<Speed>1</Speed>
|
||||
<Direction X="-1"/>
|
||||
<Rotation Y="3.14"/>
|
||||
</c:Move>-->
|
||||
</Components>
|
||||
<Children>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="0"/>
|
||||
<Orientation X="0.0" Y="0" Z="0.0"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitRaptor.obj</Resource>
|
||||
<Color R="1" G="0.4" B="0.8"/>
|
||||
</c:Model>
|
||||
</Components>
|
||||
<Children>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="0"/>
|
||||
<Orientation X="0" Y="0" Z="0"/>
|
||||
</c:Transform>
|
||||
<c:RaptorCopter>
|
||||
<Speed>20</Speed>
|
||||
<Axis Y="1"/>
|
||||
</c:RaptorCopter>
|
||||
</Components>
|
||||
<Children>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="0.4"/>
|
||||
<Scale X="0.1" Y="0.4" Z="0.1"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCylinder.obj</Resource>
|
||||
<Color R="1" G="0.4" B="0.8"/>
|
||||
</c:Model>
|
||||
</Components>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="0.6"/>
|
||||
<Scale X="1.7" Y="0.03" Z="0.1"/>
|
||||
<Orientation X="0" Y="0" Z="0"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Color R="1" G="0.4" B="0.8"/>
|
||||
</c:Model>
|
||||
</Components>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="0.6"/>
|
||||
<Scale X="1.7" Y="0.03" Z="0.1"/>
|
||||
<Orientation X="0" Y="1.57" Z="0"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Color R="1" G="0.4" B="0.8"/>
|
||||
</c:Model>
|
||||
</Components>
|
||||
</Entity>
|
||||
</Children>
|
||||
</Entity>
|
||||
</Children>
|
||||
</Entity>
|
||||
</Children>
|
||||
</Entity>
|
||||
</Children>
|
||||
</Entity>
|
||||
@@ -3,6 +3,10 @@
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="types" elementFormDefault="qualified">
|
||||
<xs:include schemaLocation="Types/Quaternion.xsd"/>
|
||||
<xs:include schemaLocation="Types/Vector.xsd"/>
|
||||
<xs:include schemaLocation="Types/Color.xsd"/>
|
||||
<xs:simpleType name="bool">
|
||||
<xs:restriction base="xs:boolean"></xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="int">
|
||||
<xs:restriction base="xs:integer"></xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="types" elementFormDefault="qualified">
|
||||
<xs:complexType name="Color">
|
||||
<xs:attribute name="R" type="xs:decimal" default="0.0"/>
|
||||
<xs:attribute name="G" type="xs:decimal" default="0.0"/>
|
||||
<xs:attribute name="B" type="xs:decimal" default="0.0"/>
|
||||
<xs:attribute name="A" type="xs:decimal" default="1.0"/>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
||||
@@ -7,11 +7,13 @@
|
||||
<xs:element name="Entity">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="Components">
|
||||
<xs:element name="Components" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element ref="c:Transform" minOccurs="0"/>
|
||||
<xs:element ref="c:Model" minOccurs="0"/>
|
||||
<xs:element ref="c:Test" minOccurs="0"/>
|
||||
<xs:element ref="c:RaptorCopter" minOccurs="0"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
@@ -0,0 +1,481 @@
|
||||
#include "Core/EntityXMLFile.h"
|
||||
#include "Core/World.h"
|
||||
|
||||
unsigned int EntityXMLFile::InstanceCount = 0;
|
||||
|
||||
EntityXMLFile::EntityXMLFile(std::string path)
|
||||
: m_EntityFile(path)
|
||||
{
|
||||
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);
|
||||
|
||||
// HACK: Use Sax2 parser instead so the entire 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
|
||||
predictComponentAllocation();
|
||||
}
|
||||
|
||||
EntityXMLFile::~EntityXMLFile()
|
||||
{
|
||||
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 EntityXMLFile::PopulateWorld(World* world)
|
||||
{
|
||||
for (auto& pair : m_ComponentInfo) {
|
||||
world->RegisterComponent(pair.second);
|
||||
}
|
||||
|
||||
// 4. Parse entity hierarchy
|
||||
auto root = m_DOMDocument->getDocumentElement();
|
||||
parseEntityGraph(world, root, 0);
|
||||
}
|
||||
|
||||
|
||||
void EntityXMLFile::preprocess(std::string inPath, std::string 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.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.c_str());
|
||||
// TODO: MemBufFormatTarget* formatTarget = new MemBufFormatTarget()
|
||||
output->setByteStream(formatTarget);
|
||||
writer->write(doc, output);
|
||||
|
||||
delete formatTarget;
|
||||
output->release();
|
||||
writer->release();
|
||||
parser->release();
|
||||
}
|
||||
|
||||
void EntityXMLFile::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 EntityXMLFile::parseDefaults()
|
||||
{
|
||||
using namespace xercesc;
|
||||
|
||||
for (auto& ci : m_ComponentInfo) {
|
||||
// Allocate memory for default values
|
||||
ci.second.Defaults = std::shared_ptr<char>(new char[ci.second.Meta.Stride]);
|
||||
memset(ci.second.Defaults.get(), 0, ci.second.Meta.Stride);
|
||||
|
||||
XercesDOMParser parser(nullptr, XMLPlatformUtils::fgMemoryManager);
|
||||
parser.setErrorHandler(m_ErrorHandler);
|
||||
|
||||
std::string componentName = ci.first;
|
||||
LOG_DEBUG("Parsing defaults for component %s", componentName.c_str());
|
||||
boost::filesystem::path defaultsFile = "Schema/Components/" + componentName + ".xml";
|
||||
|
||||
parser.parse(defaultsFile.string().c_str());
|
||||
auto doc = parser.getDocument();
|
||||
if (doc == nullptr) {
|
||||
LOG_ERROR("%s not found! Skipping.", defaultsFile.string().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find the node in the components namespace matching the component name
|
||||
std::string tagName = "c:" + componentName;
|
||||
auto rootNodes = doc->getElementsByTagName(XSTR(tagName.c_str()));
|
||||
if (rootNodes->getLength() == 0) {
|
||||
LOG_ERROR("Couldn't find defaults for component \"%s\"! Skipping.", componentName.c_str());
|
||||
continue;
|
||||
}
|
||||
auto componentElement = dynamic_cast<DOMElement*>(rootNodes->item(0));
|
||||
|
||||
// Fill the default value buffer with values
|
||||
for (auto& field : ci.second.FieldOffsets) {
|
||||
std::string fieldName = field.first;
|
||||
auto fieldNodes = componentElement->getElementsByTagName(XSTR(fieldName.c_str()));
|
||||
auto fieldNode = fieldNodes->item(0);
|
||||
if (fieldNode == nullptr) {
|
||||
LOG_ERROR("Defaults for component \"%s\" is missing field \"%s\"!", componentName.c_str(), fieldName.c_str());
|
||||
continue;
|
||||
}
|
||||
auto fieldElement = dynamic_cast<DOMElement*>(fieldNode);
|
||||
|
||||
std::string fieldType = ci.second.FieldTypes.at(fieldName);
|
||||
unsigned int fieldOffset = ci.second.FieldOffsets.at(fieldName);
|
||||
writeData(fieldElement, fieldType, ci.second.Defaults.get() + fieldOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityXMLFile::predictComponentAllocation()
|
||||
{
|
||||
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
|
||||
std::size_t stride = 0;
|
||||
// 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: " << ci.Meta.Stride << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityXMLFile::parseEntityGraph(World* world, xercesc::DOMElement* element, EntityID parentEntity)
|
||||
{
|
||||
using namespace xercesc;
|
||||
|
||||
// Create entity
|
||||
EntityID entity = world->CreateEntity(parentEntity);
|
||||
LOG_DEBUG("Created entity %i, parent %i", entity, parentEntity);
|
||||
|
||||
// Add components
|
||||
auto components = m_DOMDocument->evaluate(XSTR("Components/*"), element, nullptr, DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, nullptr);
|
||||
for (int i = 0; i < components->getSnapshotLength(); i++) {
|
||||
components->snapshotItem(i);
|
||||
auto componentElement = dynamic_cast<DOMElement*>(components->getNodeValue());
|
||||
std::string componentName = XSTR(componentElement->getLocalName());
|
||||
auto& ci = m_ComponentInfo.at(componentName);
|
||||
|
||||
// Attach the component
|
||||
auto c = world->AttachComponent(entity, componentName);
|
||||
LOG_DEBUG("Attached %s component", componentName.c_str());
|
||||
|
||||
// Write field data
|
||||
auto fields = componentElement->getChildNodes();
|
||||
for (int j = 0; j < fields->getLength(); ++j) {
|
||||
auto fieldNode = fields->item(j);
|
||||
auto nodeType = fieldNode->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 (ci.FieldTypes.find(fieldName) == ci.FieldTypes.end()) {
|
||||
std::cout << "Warning: Component \"" << componentName << "\" contains invalid field \"" << fieldName << "\". Skipping." << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string fieldType = ci.FieldTypes.at(fieldName);
|
||||
unsigned int fieldOffset = ci.FieldOffsets.at(fieldName);
|
||||
std::string fieldValue(XSTR(field->getTextContent()));
|
||||
LOG_DEBUG(" %s %s = %s", fieldType.c_str(), fieldName.c_str(), fieldValue.c_str());
|
||||
writeData(field, fieldType, c.Data + fieldOffset);
|
||||
}
|
||||
}
|
||||
|
||||
// Recurse children
|
||||
auto children = m_DOMDocument->evaluate(XSTR("Children/Entity"), element, nullptr, DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, nullptr);
|
||||
for (int i = 0; i < children->getSnapshotLength(); i++) {
|
||||
children->snapshotItem(i);
|
||||
parseEntityGraph(world, dynamic_cast<DOMElement*>(children->getNodeValue()), entity);
|
||||
}
|
||||
|
||||
//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;
|
||||
//}
|
||||
}
|
||||
|
||||
std::size_t EntityXMLFile::getTypeStride(std::string typeName)
|
||||
{
|
||||
std::map<std::string, size_t> typeStrides{
|
||||
{ "bool", sizeof(bool) },
|
||||
{ "int", sizeof(int) },
|
||||
{ "double", sizeof(double) },
|
||||
{ "string", sizeof(std::string) },
|
||||
{ "Vector", sizeof(glm::vec3) },
|
||||
{ "Quaternion", sizeof(glm::quat) },
|
||||
{ "Color", sizeof(glm::vec4) }
|
||||
};
|
||||
|
||||
auto it = typeStrides.find(typeName);
|
||||
return (it != typeStrides.end()) ? it->second : 0;
|
||||
}
|
||||
|
||||
float EntityXMLFile::getFloatAttribute(const xercesc::DOMElement* element, const char* attribute) const
|
||||
{
|
||||
using namespace xercesc;
|
||||
XSValue::Status status;
|
||||
XSValue* val = XSValue::getActualValue(element->getAttribute(XSTR(attribute)), xercesc::XSValue::DataType::dt_float, status);
|
||||
if (val == nullptr) {
|
||||
LOG_ERROR("Element \"%s\" doesn't have an \"%s\" attribute!", XSTR(element->getTagName()), attribute);
|
||||
return 0.f;
|
||||
} else {
|
||||
return val->fData.fValue.f_float;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityXMLFile::writeData(const xercesc::DOMElement* element, std::string typeName, char* outData)
|
||||
{
|
||||
using namespace xercesc;
|
||||
|
||||
XSValue::DataType dataType = XSValue::getDataType(XSTR(typeName.c_str()));
|
||||
if (dataType == XSValue::DataType::dt_MAXCOUNT) {
|
||||
if (typeName == "Vector") {
|
||||
glm::vec3 vec;
|
||||
vec.x = getFloatAttribute(element, "X");
|
||||
vec.y = getFloatAttribute(element, "Y");
|
||||
vec.z = getFloatAttribute(element, "Z");
|
||||
memcpy(outData, reinterpret_cast<char*>(&vec), getTypeStride(typeName));
|
||||
} else if (typeName == "Color") {
|
||||
glm::vec4 vec;
|
||||
vec.r = getFloatAttribute(element, "R");
|
||||
vec.g = getFloatAttribute(element, "G");
|
||||
vec.b = getFloatAttribute(element, "B");
|
||||
vec.a = getFloatAttribute(element, "A");
|
||||
memcpy(outData, reinterpret_cast<char*>(&vec), getTypeStride(typeName));
|
||||
} else if (typeName == "Quaternion") {
|
||||
glm::quat q;
|
||||
q.x = getFloatAttribute(element, "X");
|
||||
q.y = getFloatAttribute(element, "Y");
|
||||
q.z = getFloatAttribute(element, "Z");
|
||||
q.w = getFloatAttribute(element, "W");
|
||||
memcpy(outData, reinterpret_cast<char*>(&q), getTypeStride(typeName));
|
||||
}
|
||||
} else if (dataType == XSValue::DataType::dt_string) {
|
||||
char* str = XMLString::transcode(element->getTextContent());
|
||||
std::string standardString(str);
|
||||
new (outData) std::string(str);
|
||||
XMLString::release(&str);
|
||||
//memcpy(outData, reinterpret_cast<char*>(&standardString), getTypeStride(typeName));
|
||||
} else {
|
||||
XSValue::Status status;
|
||||
XSValue* val = XSValue::getActualValue(element->getTextContent(), dataType, status);
|
||||
memcpy(outData, reinterpret_cast<char*>(&val->fData.fValue), getTypeStride(typeName));
|
||||
}
|
||||
}
|
||||
|
||||
+174
-50
@@ -21,6 +21,16 @@ bool isFirstLower(const ChildInfo& first, const ChildInfo& second)
|
||||
return first.Distance < second.Distance;
|
||||
}
|
||||
|
||||
bool isSameBoxProbably(const AABB& first, const AABB& second)
|
||||
{
|
||||
const float EPS = 0.0001f;
|
||||
const auto& ma = first.MaxCorner();
|
||||
const auto& mi = first.MinCorner();
|
||||
return (std::abs(ma.x - mi.x) < EPS) &&
|
||||
(std::abs(ma.z - mi.z) < EPS) &&
|
||||
(std::abs(ma.y - mi.y) < EPS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
OctTree::OctTree()
|
||||
@@ -28,11 +38,79 @@ OctTree::OctTree()
|
||||
{}
|
||||
|
||||
OctTree::OctTree(const AABB& octTreeBounds, int subDivisions)
|
||||
: m_Box(octTreeBounds)
|
||||
: m_Root(new OctChild(octTreeBounds, subDivisions, m_StaticObjects, m_DynamicObjects))
|
||||
, m_UpdatedOnce(false)
|
||||
{}
|
||||
|
||||
OctTree::~OctTree()
|
||||
{
|
||||
delete m_Root;
|
||||
}
|
||||
|
||||
void OctTree::AddDynamicObject(const AABB& box)
|
||||
{
|
||||
m_Root->AddDynamicObject(box);
|
||||
m_DynamicObjects.push_back(box);
|
||||
}
|
||||
|
||||
void OctTree::AddStaticObject(const AABB& box)
|
||||
{
|
||||
m_Root->AddStaticObject(box);
|
||||
m_StaticObjects.push_back(box);
|
||||
}
|
||||
|
||||
void OctTree::BoxesInSameRegion(const AABB& box, std::vector<AABB>& outBoxes)
|
||||
{
|
||||
falsifyObjectChecks();
|
||||
m_Root->BoxesInSameRegion(box, outBoxes);
|
||||
}
|
||||
|
||||
void OctTree::ClearObjects()
|
||||
{
|
||||
m_StaticObjects.clear();
|
||||
m_DynamicObjects.clear();
|
||||
m_Root->ClearObjects();
|
||||
}
|
||||
|
||||
void OctTree::ClearDynamicObjects()
|
||||
{
|
||||
m_DynamicObjects.clear();
|
||||
m_Root->ClearDynamicObjects();
|
||||
}
|
||||
|
||||
bool OctTree::RayCollides(const Ray& ray, Output& data)
|
||||
{
|
||||
falsifyObjectChecks();
|
||||
data.CollideDistance = -1;
|
||||
return m_Root->RayCollides(ray, data);
|
||||
}
|
||||
|
||||
bool OctTree::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected)
|
||||
{
|
||||
falsifyObjectChecks();
|
||||
return m_Root->BoxCollides(boxToTest, outBoxIntersected);
|
||||
}
|
||||
|
||||
void OctTree::falsifyObjectChecks()
|
||||
{
|
||||
for (auto& obj : m_StaticObjects) {
|
||||
obj.Checked = false;
|
||||
}
|
||||
for (auto& obj : m_DynamicObjects) {
|
||||
obj.Checked = false;
|
||||
}
|
||||
}
|
||||
|
||||
OctTree::OctChild::OctChild(const AABB& octTreeBounds,
|
||||
int subDivisions,
|
||||
std::vector<ContainedObject>& staticObjects,
|
||||
std::vector<ContainedObject>& dynamicObjects)
|
||||
: m_Box(octTreeBounds)
|
||||
, m_StaticObjectsRef(staticObjects)
|
||||
, m_DynamicObjectsRef(dynamicObjects)
|
||||
{
|
||||
if (subDivisions == 0) {
|
||||
for (OctTree*& c : m_Children) {
|
||||
for (OctChild*& c : m_Children) {
|
||||
c = nullptr;
|
||||
}
|
||||
} else {
|
||||
@@ -68,14 +146,14 @@ OctTree::OctTree(const AABB& octTreeBounds, int subDivisions)
|
||||
minPos.z = parentMin.z;
|
||||
maxPos.z = parentCenter.z;
|
||||
}
|
||||
m_Children[i] = new OctTree(AABB(minPos, maxPos), subDivisions);
|
||||
m_Children[i] = new OctChild(AABB(minPos, maxPos), subDivisions, m_StaticObjectsRef, m_DynamicObjectsRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OctTree::~OctTree()
|
||||
OctTree::OctChild::~OctChild()
|
||||
{
|
||||
for (OctTree*& c : m_Children) {
|
||||
for (OctChild*& c : m_Children) {
|
||||
if (c != nullptr) {
|
||||
delete c;
|
||||
c = nullptr;
|
||||
@@ -85,19 +163,22 @@ OctTree::~OctTree()
|
||||
|
||||
void OctTree::Update(float dt, World* world, Camera* cam)
|
||||
{
|
||||
AABB aabb;
|
||||
for (ComponentWrapper& c : world->GetComponents("Collision")) {
|
||||
AABB aabb;
|
||||
aabb.CreateFromCenter(c["BoxCenter"], c["BoxSize"]);
|
||||
AddStaticObject(aabb);
|
||||
AddDynamicObject(aabb);
|
||||
}
|
||||
const glm::vec4 redCol = glm::vec4(1, 0.2f, 0, 1);
|
||||
const glm::vec4 greenCol = glm::vec4(0.1f, 1.0f, 0.25f, 1);
|
||||
const glm::vec3 boxSize = 0.1f*glm::vec3(1.0f, 1.0f, 1.0f);
|
||||
const glm::vec4 blueCol = glm::vec4(0.1f, 0.05f, 0.95f, 1);
|
||||
const glm::vec4 cyanCol = glm::vec4(0.1f, 0.9f, 0.85f, 1);
|
||||
const glm::vec3 boxSize = 0.05f*glm::vec3(1.0f, 1.0f, 1.0f);
|
||||
|
||||
if (!m_UpdatedOnce) {
|
||||
m_BoxID = world->CreateEntity();
|
||||
ComponentWrapper transform = world->AttachComponent(m_BoxID, "Transform");
|
||||
transform["Scale"] = boxSize;
|
||||
|
||||
ComponentWrapper model = world->AttachComponent(m_BoxID, "Model");
|
||||
model["Resource"] = "Models/Core/UnitBox.obj";
|
||||
m_UpdatedOnce = true;
|
||||
@@ -109,21 +190,24 @@ void OctTree::Update(float dt, World* world, Camera* cam)
|
||||
ComponentWrapper transform = world->GetComponent(m_BoxID, "Transform");
|
||||
transform["Position"] = boxPos;
|
||||
ComponentWrapper model = world->GetComponent(m_BoxID, "Model");
|
||||
if (BoxCollides(box, AABB())) {
|
||||
//if (Collision::AABBVsAABB(box, aabb)) {
|
||||
bool collBox = BoxCollides(box, AABB());
|
||||
if (collBox) {
|
||||
cam->SetPosition(m_PrevPos);
|
||||
cam->SetOrientation(m_PrevOri);
|
||||
model["Color"] = greenCol;
|
||||
bool collRay = RayCollides({ cam->Position(), cam->Forward() }, Output());
|
||||
model["Color"] = collRay ? cyanCol : greenCol;
|
||||
} else if (RayCollides({ cam->Position(), cam->Forward() }, Output())) {
|
||||
model["Color"] = blueCol;
|
||||
} else {
|
||||
model["Color"] = redCol;
|
||||
}
|
||||
|
||||
m_PrevPos = cam->Position();
|
||||
m_PrevOri = cam->Orientation();
|
||||
ClearObjects();
|
||||
ClearDynamicObjects();
|
||||
}
|
||||
|
||||
bool OctTree::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const
|
||||
bool OctTree::OctChild::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const
|
||||
{
|
||||
if (hasChildren()) {
|
||||
for (int i : childIndicesContainingBox(boxToTest)) {
|
||||
@@ -131,23 +215,32 @@ bool OctTree::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
std::vector<std::vector<AABB>> objVectors = {
|
||||
m_StaticObjects,
|
||||
m_DynamicObjects
|
||||
};
|
||||
for (const auto& objVector : objVectors) {
|
||||
for (const auto& obj : objVector) {
|
||||
if (Collision::AABBVsAABB(boxToTest, obj)) {
|
||||
outBoxIntersected = obj;
|
||||
for (int i : m_StaticObjIndices) {
|
||||
if (!m_StaticObjectsRef[i].Checked) {
|
||||
const AABB& objBox = m_StaticObjectsRef[i].Box;
|
||||
if (Collision::AABBVsAABB(boxToTest, objBox)) {
|
||||
outBoxIntersected = objBox;
|
||||
return true;
|
||||
}
|
||||
m_StaticObjectsRef[i].Checked = true;
|
||||
}
|
||||
}
|
||||
for (int i : m_DynamicObjIndices) {
|
||||
if (!m_DynamicObjectsRef[i].Checked) {
|
||||
const AABB& objBox = m_DynamicObjectsRef[i].Box;
|
||||
if (!isSameBoxProbably(boxToTest, objBox) &&
|
||||
Collision::AABBVsAABB(boxToTest, objBox)) {
|
||||
outBoxIntersected = objBox;
|
||||
return true;
|
||||
}
|
||||
m_DynamicObjectsRef[i].Checked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OctTree::RayCollides(const Ray& ray, Output& data) const
|
||||
bool OctTree::OctChild::RayCollides(const Ray& ray, Output& data) const
|
||||
{
|
||||
//If the node AABB is missed, everything it contains is missed.
|
||||
if (Collision::RayAABBIntr(ray, m_Box)) {
|
||||
@@ -170,18 +263,25 @@ bool OctTree::RayCollides(const Ray& ray, Output& data) const
|
||||
//Check against boxes in the node.
|
||||
float minDist = INFINITY;
|
||||
bool intersected = false;
|
||||
std::vector<std::vector<AABB>> objVectors = {
|
||||
m_StaticObjects,
|
||||
m_DynamicObjects
|
||||
};
|
||||
for (const auto& objVector : objVectors) {
|
||||
for (const auto& obj : objVector) {
|
||||
float dist;
|
||||
if (Collision::RayVsAABB(ray, obj, dist)) {
|
||||
minDist = std::min(dist, minDist);
|
||||
intersected = true;
|
||||
}
|
||||
for (int i : m_StaticObjIndices) {
|
||||
float dist;
|
||||
//If we haven't tested against this object before, and the ray hits.
|
||||
if (!m_StaticObjectsRef[i].Checked &&
|
||||
Collision::RayVsAABB(ray, m_StaticObjectsRef[i].Box, dist)) {
|
||||
minDist = std::min(dist, minDist);
|
||||
intersected = true;
|
||||
}
|
||||
m_StaticObjectsRef[i].Checked = true;
|
||||
}
|
||||
for (int i : m_DynamicObjIndices) {
|
||||
float dist;
|
||||
//If we haven't tested against this object before, and the ray hits.
|
||||
if (!m_DynamicObjectsRef[i].Checked &&
|
||||
Collision::RayVsAABB(ray, m_DynamicObjectsRef[i].Box, dist)) {
|
||||
minDist = std::min(dist, minDist);
|
||||
intersected = true;
|
||||
}
|
||||
m_DynamicObjectsRef[i].Checked = true;
|
||||
}
|
||||
|
||||
data.CollideDistance = minDist;
|
||||
@@ -192,60 +292,84 @@ bool OctTree::RayCollides(const Ray& ray, Output& data) const
|
||||
}
|
||||
|
||||
|
||||
void OctTree::AddDynamicObject(const AABB& box)
|
||||
void OctTree::OctChild::AddDynamicObject(const AABB& box)
|
||||
{
|
||||
if (hasChildren()) {
|
||||
for (auto i : childIndicesContainingBox(box)) {
|
||||
m_Children[i]->AddDynamicObject(box);
|
||||
}
|
||||
} else {
|
||||
m_DynamicObjects.push_back(box);
|
||||
//Since it hasn't been added yet to the real object list, the index is after the last =size.
|
||||
m_DynamicObjIndices.push_back(m_DynamicObjectsRef.size());
|
||||
}
|
||||
}
|
||||
|
||||
void OctTree::AddStaticObject(const AABB& box)
|
||||
void OctTree::OctChild::AddStaticObject(const AABB& box)
|
||||
{
|
||||
if (hasChildren()) {
|
||||
for (auto i : childIndicesContainingBox(box)) {
|
||||
m_Children[i]->AddStaticObject(box);
|
||||
}
|
||||
} else {
|
||||
m_StaticObjects.push_back(box);
|
||||
//Since it hasn't been added yet to the real object list, the index is after the last =size.
|
||||
m_StaticObjIndices.push_back(m_StaticObjectsRef.size());
|
||||
}
|
||||
}
|
||||
|
||||
void OctTree::BoxesInSameRegion(const AABB& box, std::vector<AABB>& outBoxes) const
|
||||
void OctTree::OctChild::BoxesInSameRegion(const AABB& box, std::vector<AABB>& outBoxes) const
|
||||
{
|
||||
if (hasChildren()) {
|
||||
for (auto i : childIndicesContainingBox(box)) {
|
||||
m_Children[i]->BoxesInSameRegion(box, outBoxes);
|
||||
}
|
||||
} else {
|
||||
outBoxes.insert(outBoxes.end(), m_StaticObjects.begin(), m_StaticObjects.end());
|
||||
outBoxes.insert(outBoxes.end(), m_DynamicObjects.begin(), m_DynamicObjects.end());
|
||||
int startIndex = outBoxes.size();
|
||||
int numDuplicates = 0;
|
||||
outBoxes.resize(outBoxes.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;
|
||||
outBoxes[startIndex + i - numDuplicates] = obj.Box;
|
||||
}
|
||||
}
|
||||
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;
|
||||
outBoxes[startIndex + i - numDuplicates] = obj.Box;
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < numDuplicates; ++i) {
|
||||
outBoxes.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OctTree::ClearObjects()
|
||||
void OctTree::OctChild::ClearObjects()
|
||||
{
|
||||
if (hasChildren()) {
|
||||
for (OctTree*& c : m_Children) {
|
||||
for (OctChild*& c : m_Children) {
|
||||
c->ClearObjects();
|
||||
}
|
||||
} else {
|
||||
m_DynamicObjects.clear();
|
||||
m_StaticObjects.clear();
|
||||
m_DynamicObjIndices.clear();
|
||||
m_StaticObjIndices.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void OctTree::ClearDynamicObjects()
|
||||
void OctTree::OctChild::ClearDynamicObjects()
|
||||
{
|
||||
if (hasChildren()) {
|
||||
for (OctTree*& c : m_Children) {
|
||||
for (OctChild*& c : m_Children) {
|
||||
c->ClearObjects();
|
||||
}
|
||||
} else {
|
||||
m_DynamicObjects.clear();
|
||||
m_DynamicObjIndices.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,13 +385,13 @@ void OctTree::ClearDynamicObjects()
|
||||
// x : - - - - + + + +
|
||||
// y : - - + + - - + +
|
||||
// z : - + - + - + - +
|
||||
int OctTree::childIndexContainingPoint(const glm::vec3& point) const
|
||||
int OctTree::OctChild::childIndexContainingPoint(const glm::vec3& point) const
|
||||
{
|
||||
const glm::vec3& c = m_Box.Center();
|
||||
return (1 << 2) * (point.x >= c.x) | (1 << 1) * (point.y >= c.y) | (point.z >= c.z);
|
||||
}
|
||||
|
||||
std::vector<int> OctTree::childIndicesContainingBox(const AABB& box) const
|
||||
std::vector<int> OctTree::OctChild::childIndicesContainingBox(const AABB& box) const
|
||||
{
|
||||
int minInd = childIndexContainingPoint(box.MinCorner());
|
||||
int maxInd = childIndexContainingPoint(box.MaxCorner());
|
||||
@@ -305,7 +429,7 @@ std::vector<int> OctTree::childIndicesContainingBox(const AABB& box) const
|
||||
}
|
||||
}
|
||||
|
||||
inline bool OctTree::hasChildren() const
|
||||
inline bool OctTree::OctChild::hasChildren() const
|
||||
{
|
||||
return m_Children[0] != nullptr;
|
||||
}
|
||||
@@ -35,6 +35,20 @@ void ResourceManager::Reload(std::string resourceName)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ResourceManager::Release(std::string resourceType, std::string resourceName)
|
||||
{
|
||||
auto key = std::make_pair(resourceType, resourceName);
|
||||
if (m_ResourceCache.find(key) == m_ResourceCache.end()) {
|
||||
return;
|
||||
}
|
||||
auto resource = m_ResourceCache.at(key);
|
||||
m_ResourceCache.erase(key);
|
||||
m_ResourceFromName.erase(resourceName);
|
||||
m_ResourceParents.erase(resource);
|
||||
delete resource;
|
||||
}
|
||||
|
||||
unsigned int ResourceManager::GetNewResourceID(unsigned int typeID)
|
||||
{
|
||||
return m_ResourceCount[typeID]++;
|
||||
|
||||
@@ -41,9 +41,16 @@ ComponentWrapper World::GetComponent(EntityID entity, std::string componentType)
|
||||
return pool->GetByEntity(entity);
|
||||
}
|
||||
|
||||
const ComponentPool& World::GetComponents(std::string componentType)
|
||||
const ComponentPool* World::GetComponents(std::string componentType)
|
||||
{
|
||||
return *m_ComponentPools.at(componentType);
|
||||
auto it = m_ComponentPools.find(componentType);
|
||||
return (it != m_ComponentPools.end()) ? it->second : nullptr;
|
||||
}
|
||||
|
||||
|
||||
EntityID World::GetParent(EntityID entity)
|
||||
{
|
||||
return m_EntityParents.at(entity);
|
||||
}
|
||||
|
||||
EntityID World::generateEntityID()
|
||||
|
||||
@@ -34,10 +34,10 @@ RawModel::RawModel(std::string fileName)
|
||||
numIndices += face.mNumIndices;
|
||||
}
|
||||
}
|
||||
LOG_DEBUG("Vertex count %i", numVertices);
|
||||
LOG_DEBUG("Index count %i", numIndices);
|
||||
//LOG_DEBUG("Vertex count %i", numVertices);
|
||||
//LOG_DEBUG("Index count %i", numIndices);
|
||||
|
||||
LOG_DEBUG("Model has %i embedded textures", scene->mNumTextures);
|
||||
//LOG_DEBUG("Model has %i embedded textures", scene->mNumTextures);
|
||||
|
||||
std::vector<std::tuple<std::string, glm::mat4>> boneInfo;
|
||||
std::map<std::string, int> boneNameMapping;
|
||||
@@ -132,35 +132,35 @@ RawModel::RawModel(std::string fileName)
|
||||
matGroup.EndIndex = m_Indices.size() - 1;
|
||||
// Material shininess
|
||||
material->Get(AI_MATKEY_SHININESS, matGroup.Shininess);
|
||||
LOG_DEBUG("Shininess: %f", matGroup.Shininess);
|
||||
//LOG_DEBUG("Shininess: %f", matGroup.Shininess);
|
||||
// Diffuse texture
|
||||
LOG_DEBUG("%i diffuse textures found", material->GetTextureCount(aiTextureType_DIFFUSE));
|
||||
//LOG_DEBUG("%i diffuse textures found", material->GetTextureCount(aiTextureType_DIFFUSE));
|
||||
if (material->GetTextureCount(aiTextureType_DIFFUSE)) {
|
||||
aiString path;
|
||||
aiTextureMapping mapping;
|
||||
material->GetTexture(aiTextureType_DIFFUSE, 0, &path, &mapping);
|
||||
std::string absolutePath = (boost::filesystem::path(fileName).branch_path() / path.C_Str()).string();
|
||||
LOG_DEBUG("Diffuse texture: %s", absolutePath.c_str());
|
||||
//LOG_DEBUG("Diffuse texture: %s", absolutePath.c_str());
|
||||
matGroup.Texture = std::shared_ptr<Texture>(ResourceManager::Load<Texture>(absolutePath));
|
||||
}
|
||||
// Normal map
|
||||
LOG_DEBUG("%i normal maps found", material->GetTextureCount(aiTextureType_HEIGHT));
|
||||
//LOG_DEBUG("%i normal maps found", material->GetTextureCount(aiTextureType_HEIGHT));
|
||||
if (material->GetTextureCount(aiTextureType_HEIGHT)) {
|
||||
aiString path;
|
||||
aiTextureMapping mapping;
|
||||
material->GetTexture(aiTextureType_HEIGHT, 0, &path, &mapping);
|
||||
std::string absolutePath = (boost::filesystem::path(fileName).branch_path() / path.C_Str()).string();
|
||||
LOG_DEBUG("Normal map: %s", absolutePath.c_str());
|
||||
//LOG_DEBUG("Normal map: %s", absolutePath.c_str());
|
||||
matGroup.NormalMap = std::shared_ptr<Texture>(ResourceManager::Load<Texture>(absolutePath));
|
||||
}
|
||||
// Specular map
|
||||
LOG_DEBUG("%i specular maps found", material->GetTextureCount(aiTextureType_SPECULAR));
|
||||
//LOG_DEBUG("%i specular maps found", material->GetTextureCount(aiTextureType_SPECULAR));
|
||||
if (material->GetTextureCount(aiTextureType_SPECULAR)) {
|
||||
aiString path;
|
||||
aiTextureMapping mapping;
|
||||
material->GetTexture(aiTextureType_SPECULAR, 0, &path, &mapping);
|
||||
std::string absolutePath = (boost::filesystem::path(fileName).branch_path() / path.C_Str()).string();
|
||||
LOG_DEBUG("Specular map: %s", absolutePath.c_str());
|
||||
//LOG_DEBUG("Specular map: %s", absolutePath.c_str());
|
||||
matGroup.SpecularMap = std::shared_ptr<Texture>(ResourceManager::Load<Texture>(absolutePath));
|
||||
}
|
||||
TextureGroups.push_back(matGroup);
|
||||
@@ -216,20 +216,20 @@ RawModel::RawModel(std::string fileName)
|
||||
m_Skeleton = new Skeleton();
|
||||
CreateSkeleton(boneInfo, boneNameMapping, scene->mRootNode, -1);
|
||||
int numBones = m_Skeleton->Bones.size();
|
||||
LOG_DEBUG("Bone count: %i", numBones);
|
||||
//LOG_DEBUG("Bone count: %i", numBones);
|
||||
if (numBones > 0) {
|
||||
m_Skeleton->PrintSkeleton();
|
||||
}
|
||||
}
|
||||
|
||||
// Animations
|
||||
LOG_DEBUG("Animation count: %i", scene->mNumAnimations);
|
||||
//LOG_DEBUG("Animation count: %i", scene->mNumAnimations);
|
||||
for (int i = 0; i < scene->mNumAnimations; ++i) {
|
||||
auto animation = scene->mAnimations[i];
|
||||
std::string animationName = animation->mName.C_Str();
|
||||
LOG_DEBUG("Animation: %s", animationName.c_str());
|
||||
LOG_DEBUG("Duration: %f", animation->mDuration);
|
||||
LOG_DEBUG("Ticks per second: %f", animation->mTicksPerSecond);
|
||||
//LOG_DEBUG("Animation: %s", animationName.c_str());
|
||||
//LOG_DEBUG("Duration: %f", animation->mDuration);
|
||||
//LOG_DEBUG("Ticks per second: %f", animation->mTicksPerSecond);
|
||||
|
||||
Skeleton::Animation skelAnim;
|
||||
skelAnim.Name = animationName;
|
||||
@@ -303,7 +303,7 @@ void RawModel::CreateSkeleton(std::vector<std::tuple<std::string, glm::mat4>> &b
|
||||
|
||||
// Find the bone by name in the bone info list
|
||||
if (boneNameMapping.find(nodeName) == boneNameMapping.end()) {
|
||||
LOG_DEBUG("Node \"%s\" was not a bone", nodeName.c_str());
|
||||
//LOG_DEBUG("Node \"%s\" was not a bone", nodeName.c_str());
|
||||
} else {
|
||||
glm::mat4 offsetMatrix;
|
||||
int ID = boneNameMapping[nodeName];
|
||||
|
||||
@@ -15,49 +15,87 @@ void RenderQueueFactory::Update(World* world)
|
||||
|
||||
glm::mat4 RenderQueueFactory::ModelMatrix(World* world, EntityID entity)
|
||||
{
|
||||
//should really return absolute model matrix based on parents position, scale and orientation
|
||||
//GetAbsolutePosition(World* world, ComponentWrapper transformComponent)
|
||||
glm::vec3 position = AbsolutePosition(world, entity);
|
||||
glm::quat orientation = AbsoluteOrientation(world, entity);
|
||||
glm::vec3 scale = AbsoluteScale(world, entity);
|
||||
|
||||
ComponentWrapper transformComponent = world->GetComponent(entity, "Transform");
|
||||
glm::vec3 position = transformComponent["Position"];
|
||||
glm::vec3 scale = transformComponent["Scale"];
|
||||
glm::quat oritentation = transformComponent["Orientation"];
|
||||
|
||||
glm::mat4 modelMatrix = glm::translate(glm::mat4(), position) * glm::toMat4(oritentation) * glm::scale(scale);
|
||||
glm::mat4 modelMatrix = glm::translate(glm::mat4(), position) * glm::toMat4(orientation) * glm::scale(scale);
|
||||
return modelMatrix;
|
||||
}
|
||||
|
||||
glm::vec3 GetAbsolutePosition(World* world, ComponentWrapper transformComponent)
|
||||
|
||||
glm::vec3 RenderQueueFactory::AbsolutePosition(World* world, EntityID entity)
|
||||
{
|
||||
// positionComponent.EntityID
|
||||
return glm::vec3();
|
||||
glm::vec3 position;
|
||||
|
||||
do {
|
||||
ComponentWrapper transform = world->GetComponent(entity, "Transform");
|
||||
position += AbsoluteOrientation(world, entity) * (glm::vec3)transform["Position"];
|
||||
entity = world->GetParent(entity);
|
||||
} while (entity != 0);
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
glm::quat RenderQueueFactory::AbsoluteOrientation(World* world, EntityID entity)
|
||||
{
|
||||
glm::quat orientation;
|
||||
|
||||
do {
|
||||
ComponentWrapper transform = world->GetComponent(entity, "Transform");
|
||||
orientation = glm::quat((glm::vec3)transform["Orientation"]) * orientation;
|
||||
entity = world->GetParent(entity);
|
||||
} while (entity != 0);
|
||||
|
||||
return orientation;
|
||||
}
|
||||
|
||||
glm::vec3 RenderQueueFactory::AbsoluteScale(World* world, EntityID entity)
|
||||
{
|
||||
ComponentWrapper transform = world->GetComponent(entity, "Transform");
|
||||
glm::vec3 scale = (glm::vec3)transform["Scale"];
|
||||
|
||||
EntityID parent = world->GetParent(entity);
|
||||
if (parent != 0) {
|
||||
return AbsoluteScale(world, parent) * scale;
|
||||
} else {
|
||||
return scale;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderQueueFactory::FillModels(World* world, RenderQueue* renderQueue)
|
||||
{
|
||||
for(auto& modelC : world->GetComponents("Model")) {
|
||||
ModelJob job;
|
||||
std::string resource = modelC["Resource"];
|
||||
glm::vec4 color = modelC["Color"];
|
||||
Model* model = ResourceManager::Load<Model>(resource);
|
||||
auto models = world->GetComponents("Model");
|
||||
if (models == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto texGroup : model->TextureGroups) {
|
||||
job.TextureID = (texGroup.Texture) ? texGroup.Texture->ResourceID : 0;
|
||||
job.DiffuseTexture = texGroup.Texture.get();
|
||||
job.NormalTexture = texGroup.NormalMap.get();
|
||||
job.SpecularTexture = texGroup.SpecularMap.get();
|
||||
job.Model = model;
|
||||
job.StartIndex = texGroup.StartIndex;
|
||||
job.EndIndex = texGroup.EndIndex;
|
||||
job.ModelMatrix = model->m_Matrix * ModelMatrix(world, modelC.EntityID);
|
||||
job.Color = color;
|
||||
for (auto& modelC : *models) {
|
||||
std::string resource = modelC["Resource"];
|
||||
if (resource.empty()) {
|
||||
continue;
|
||||
}
|
||||
glm::vec4 color = modelC["Color"];
|
||||
Model* model = ResourceManager::Load<Model>(resource);
|
||||
|
||||
//TODO: RENDERER: Not sure if the best solution for pickingColor to entity link is this
|
||||
job.Entity = modelC.EntityID;
|
||||
for (auto texGroup : model->TextureGroups) {
|
||||
ModelJob job;
|
||||
job.TextureID = (texGroup.Texture) ? texGroup.Texture->ResourceID : 0;
|
||||
job.DiffuseTexture = texGroup.Texture.get();
|
||||
job.NormalTexture = texGroup.NormalMap.get();
|
||||
job.SpecularTexture = texGroup.SpecularMap.get();
|
||||
job.Model = model;
|
||||
job.StartIndex = texGroup.StartIndex;
|
||||
job.EndIndex = texGroup.EndIndex;
|
||||
job.ModelMatrix = model->m_Matrix * ModelMatrix(world, modelC.EntityID);
|
||||
job.Color = color;
|
||||
|
||||
renderQueue->Add(job);
|
||||
}
|
||||
}
|
||||
//TODO: RENDERER: Not sure if the best solution for pickingColor to entity link is this
|
||||
job.Entity = modelC.EntityID;
|
||||
|
||||
renderQueue->Add(job);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderQueueFactory::FillLights(World* world, RenderQueue* renderQueue)
|
||||
|
||||
+43
-13
@@ -1,12 +1,11 @@
|
||||
#include "Game.h"
|
||||
#include "HardcodedTestWorld.h"
|
||||
#include "Core/OctTree.h"
|
||||
|
||||
Game::Game(int argc, char* argv[])
|
||||
{
|
||||
ResourceManager::RegisterType<ConfigFile>("ConfigFile");
|
||||
ResourceManager::RegisterType<Model>("Model");
|
||||
ResourceManager::RegisterType<Texture>("Texture");
|
||||
ResourceManager::RegisterType<EntityXMLFile>("EntityXMLFile");
|
||||
|
||||
m_Config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||
LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get<int>("Debug.LogLevel", 1));
|
||||
@@ -36,21 +35,26 @@ Game::Game(int argc, char* argv[])
|
||||
m_FrameStack->Width = m_Renderer->Resolution().Width;
|
||||
m_FrameStack->Height = m_Renderer->Resolution().Height;
|
||||
|
||||
// Create a TEST WORLD
|
||||
m_World = new HardcodedTestWorld();
|
||||
|
||||
//WTODO: Current worldsize is temp.
|
||||
glm::vec3 worldSize = glm::vec3(50, 50, 50);
|
||||
m_OctTree = new OctTree(AABB(-0.5f*worldSize, 0.5f*worldSize), 2);
|
||||
// Create a world
|
||||
m_World = new World();
|
||||
std::string mapToLoad = m_Config->Get<std::string>("Debug.LoadMap", "");
|
||||
if (!mapToLoad.empty()) {
|
||||
ResourceManager::Load<EntityXMLFile>(mapToLoad)->PopulateWorld(m_World);
|
||||
}
|
||||
|
||||
// Create system pipeline
|
||||
m_SystemPipeline = new SystemPipeline(m_EventBroker);
|
||||
m_SystemPipeline->AddSystem<RaptorCopterSystem>();
|
||||
|
||||
m_LastTime = glfwGetTime();
|
||||
|
||||
testIntialize();
|
||||
}
|
||||
|
||||
Game::~Game()
|
||||
{
|
||||
delete m_FrameStack;
|
||||
delete m_EventBroker;
|
||||
delete m_OctTree;
|
||||
}
|
||||
|
||||
void Game::Tick()
|
||||
@@ -62,13 +66,13 @@ void Game::Tick()
|
||||
m_EventBroker->Swap();
|
||||
m_InputManager->Update(dt);
|
||||
m_Renderer->Update(dt);
|
||||
|
||||
m_OctTree->Update(dt, m_World, m_Renderer->Camera());
|
||||
|
||||
m_EventBroker->Swap();
|
||||
|
||||
m_RenderQueueFactory->Update(m_World);
|
||||
// Iterate through systems and update world!
|
||||
m_SystemPipeline->Update(m_World, dt);
|
||||
testTick(dt);
|
||||
|
||||
m_RenderQueueFactory->Update(m_World);
|
||||
m_Renderer->Draw(m_RenderQueueFactory->RenderQueues());
|
||||
|
||||
m_EventBroker->Swap();
|
||||
@@ -76,3 +80,29 @@ void Game::Tick()
|
||||
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
|
||||
bool Game::testOnKeyUp(const Events::KeyUp& e)
|
||||
{
|
||||
if (e.KeyCode == GLFW_KEY_R) {
|
||||
std::string mapToLoad = m_Config->Get<std::string>("Debug.LoadMap", "");
|
||||
if (!mapToLoad.empty()) {
|
||||
delete m_World;
|
||||
m_World = new World();
|
||||
ResourceManager::Release("EntityXMLFile", mapToLoad);
|
||||
ResourceManager::Load<EntityXMLFile>(mapToLoad)->PopulateWorld(m_World);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Game::testIntialize()
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &Game::testOnKeyUp);
|
||||
}
|
||||
|
||||
void Game::testTick(double dt)
|
||||
{
|
||||
m_EventBroker->Process<Game>();
|
||||
}
|
||||
|
||||
@@ -45,4 +45,24 @@ BOOST_AUTO_TEST_CASE(octTreeTest2)
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(octSameRegionTest)
|
||||
{
|
||||
glm::vec3 mini = glm::vec3(-1, -1, -1);
|
||||
glm::vec3 maxi = glm::vec3(1, 1, 1);
|
||||
OctTree tree(AABB(mini, maxi), 2);
|
||||
AABB firstQuadrant(mini, 0.8f*mini);
|
||||
tree.AddStaticObject(firstQuadrant);
|
||||
AABB testBox(0.9f*mini, 0.8f*mini);
|
||||
std::vector<AABB> region;
|
||||
tree.BoxesInSameRegion(testBox, region);
|
||||
BOOST_REQUIRE(region.size() == 1);
|
||||
AABB& box = region[0];
|
||||
BOOST_CHECK_CLOSE_FRACTION(box.Center().x, firstQuadrant.Center().x, 0.00001f);
|
||||
BOOST_CHECK_CLOSE_FRACTION(box.Center().y, firstQuadrant.Center().y, 0.00001f);
|
||||
BOOST_CHECK_CLOSE_FRACTION(box.Center().z, firstQuadrant.Center().z, 0.00001f);
|
||||
BOOST_CHECK_CLOSE_FRACTION(box.HalfSize().x, firstQuadrant.HalfSize().x, 0.00001f);
|
||||
BOOST_CHECK_CLOSE_FRACTION(box.HalfSize().y, firstQuadrant.HalfSize().y, 0.00001f);
|
||||
BOOST_CHECK_CLOSE_FRACTION(box.HalfSize().z, firstQuadrant.HalfSize().z, 0.00001f);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
@@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE(WorldTestMultipleAllocations, * utf::tolerance(0.00001))
|
||||
|
||||
// Loop through them and check data
|
||||
int i = 0;
|
||||
for (auto& c : w.GetComponents("Test")) {
|
||||
for (auto& c : *w.GetComponents("Test")) {
|
||||
BOOST_TEST((int)c["TestInteger"] == i);
|
||||
i++;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user